Skip to content
Snippets Groups Projects
PriceSection.tsx 7.96 KiB
Newer Older
  • Learn to ignore specific revisions
  • Guilhem CARRON's avatar
    Guilhem CARRON committed
    import React, { useCallback, useContext, useEffect, useState } from 'react'
    
    import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css'
    import { FluidType } from '../../enum/fluidTypes'
    import { FrequencyInMonth } from '../../enum/frequency.enum'
    import { UserContext, UserContextProps } from '../../hooks/userContext'
    import { IPrice } from '../../models/price.model'
    import { PricesService } from '../../services/prices.service'
    import arrowDown from '../../assets/icons/down-arrow.png'
    import editing from '../../assets/icons/editing.png'
    
    import Loader from '../Loader/Loader'
    import './prices.scss'
    interface PriceSectionProps {
      fluid: FluidType
      frequency: FrequencyInMonth
    }
    
    const PriceSection: React.FC<PriceSectionProps> = ({
      fluid,
      frequency,
    }: PriceSectionProps) => {
      const [prices, setPrices] = useState<IPrice[]>([])
      const [nextPrice, setnextPrice] = useState<IPrice>()
      const [isLoading, setIsLoading] = useState<boolean>(false)
      const [refreshData, setRefreshData] = useState(false)
      const [showHistory, setshowHistory] = useState<boolean>(false)
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
      const [showFullList, setshowFullList] = useState<boolean>(false)
    
      const [priceToSave, setpriceToSave] = useState<IPrice>({
        fluidType: fluid,
        price: '',
        startDate: '',
        endDate: null,
      })
      const { user }: Partial<UserContextProps> = useContext(UserContext)
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
      const editableLimit: number = 3
      const maxPerList: number = 8
    
      const handlePriceSelection = (val: string) => {
        if (val === '') val = '0'
        val = val.replace(/,/g, '.')
        val = val.replace(/([^0-9.]+)/, '')
        setpriceToSave({ ...priceToSave, price: val })
      }
    
      const savePrice = async () => {
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
        if (
          priceToSave &&
          user &&
          priceToSave.price !== '0' &&
          priceToSave.price !== ''
        ) {
    
          const priceService = new PricesService()
          const formattedPrice = {
            ...priceToSave,
            price: parseFloat(priceToSave.price as string),
          }
          await priceService.savePrice(formattedPrice, user.xsrftoken)
          setRefreshData(true)
        }
      }
    
      const toggleHistory = useCallback(() => {
        setshowHistory((prev) => !prev)
      }, [])
    
      const getDate = (isoString: string): string => {
        const date = new Date(isoString)
        const month = date.toLocaleString('fr', { month: 'long' })
        const year = date.toLocaleString('fr', { year: 'numeric' })
        return `${month} ${year}`
      }
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
      const toggleFullList = useCallback(() => {
        setshowFullList((prev) => !prev)
      }, [])
    
    
      useEffect(() => {
        let subscribed = true
        setIsLoading(true)
        async function getPrices() {
          const priceService = new PricesService()
          const prices = await priceService.getPricesByFluid(fluid)
          if (prices.length) {
            const nextPriceToCreate: IPrice = {
              fluidType: fluid,
              price: '',
              startDate: '',
              endDate: null,
            }
            // Set the correct for the next price to create
            const date = new Date(prices[0].startDate)
            const newDate = new Date(
              date.setMonth(date.getMonth() + frequency)
            ).toISOString()
            nextPriceToCreate.startDate = newDate
            if (subscribed) {
              setPrices(prices)
              setpriceToSave(nextPriceToCreate)
              setnextPrice(nextPriceToCreate)
              setIsLoading(false)
            }
          }
        }
        getPrices()
    
        return () => {
          subscribed = false
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
          setIsLoading(false)
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
      }, [refreshData, frequency, fluid])
    
    
      if (isLoading) return <Loader></Loader>
      return (
        <section>
          {prices.length ? (
            <>
              <h2>
                {fluid === FluidType.ELECTRICITY && 'Electricité'}
                {fluid === FluidType.WATER && 'Eau'}
                {fluid === FluidType.GAS && 'Gaz'}
              </h2>
              <hr className="price-separator" />
              <div className="flex-bloc">
                <p>Nouveau prix : </p>
                <input
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
                  className="input-dark price-select"
    
                  type="text"
                  value={priceToSave.price.toString()}
                  onChange={(e) => handlePriceSelection(e.target.value)}
                  placeholder={
                    priceToSave.price === '' ? 'Saisir le nouveau prix' : ''
                  }
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
                />
                <span className="euro"></span>
    
    
                <div className="flex-bloc startDate">
                  <p>A partir de : </p>
                  <p className="date">
                    <span className="capital">
                      {getDate(priceToSave.startDate)}
                    </span>
                  </p>
                </div>
              </div>
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
              <button
                className="btnValid"
                onClick={savePrice}
                disabled={priceToSave.price === '0' || priceToSave.price === ''}
              >
                Sauvegarder
              </button>
    
              <div className="history">
                <button
                  onClick={toggleHistory}
                  className={showHistory ? 'active' : ''}
                >
                  <span>Voir l'historique</span>
                  <img
                    src={arrowDown}
                    className={showHistory ? 'icon-active' : ''}
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
                    alt="arrow-icon"
    
                  />
                </button>
                {showHistory && (
                  <ul className={showHistory ? 'active' : ''}>
                    {nextPrice && (
                      <>
                        <li
                          className={
                            priceToSave.startDate === nextPrice.startDate
                              ? 'flex-bloc price-selected'
                              : 'flex-bloc'
                          }
                        >
                          <div className="prix">
                            {nextPrice.price === '' ? '----' : nextPrice.price}
                          </div>
                          <p>
                            à partir de :
                            <span className="capital">
                              {getDate(nextPrice.startDate)}
                            </span>
                          </p>
                          <img
                            src={editing}
                            onClick={() => setpriceToSave(nextPrice)}
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
                            alt="edit-icon"
    
                          />
                        </li>
                        <hr></hr>
                      </>
                    )}
                    {prices.map((price, i) => {
                      return (
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
                        <div
                          key={i}
                          className={
                            i > maxPerList && !showFullList ? 'price-hidden' : ''
                          }
                        >
    
                          <li
                            className={
                              priceToSave.startDate === price.startDate
                                ? 'flex-bloc price-selected'
                                : 'flex-bloc'
                            }
                          >
                            <div className="prix">{price.price}</div>
                            <p>
                              à partir de :{' '}
                              <span className="capital">
                                {getDate(price.startDate)}
                              </span>
                            </p>
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
                            {i < editableLimit - 1 && (
    
                              <img
                                src={editing}
                                onClick={() => setpriceToSave(prices[i])}
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
                                alt="edit-icon"
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
                          {i === maxPerList && !showFullList && (
                            <button onClick={toggleFullList} className="showButton">
                              En voir plus
                            </button>
                          )}
    
    Guilhem CARRON's avatar
    Guilhem CARRON committed
                    {showFullList && (
                      <button onClick={toggleFullList} className="showButton">
                        En voir moins
                      </button>
                    )}
    
                  </ul>
                )}
              </div>
            </>
          ) : (
            'Aucun prix trouvé'
          )}
        </section>
      )
    }
    
    export default PriceSection