Skip to content
Snippets Groups Projects
PriceSection.tsx 6.54 KiB
Newer Older
  • Learn to ignore specific revisions
  • 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 Loader from '../Loader/Loader'
    import './prices.scss'
    import dayjs from 'dayjs'
    import utc from 'dayjs/plugin/utc'
    import timezone from 'dayjs/plugin/timezone'
    import PriceRow from './PriceRow'
    dayjs.extend(utc)
    dayjs.extend(timezone)
    
    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<boolean>(false)
      const [showHistory, setShowHistory] = useState<boolean>(false)
      const [showFullList, setShowFullList] = useState<boolean>(false)
      const [priceToSave, setPriceToSave] = useState<IPrice>({
        fluidType: fluid,
        price: '',
        startDate: '',
        endDate: null,
      })
      const { user }: Partial<UserContextProps> = useContext(UserContext)
      const maxPerList: number = 8
    
      const handlePriceSelection = useCallback((val: string) => {
        if (val === '') val = '0'
        val = val.replace(/,/g, '.')
        val = val.replace(/([^0-9.]+)/, '')
        setPriceToSave((prev) => {
          return { ...prev, price: val }
        })
      }, [])
    
      const savePrice = useCallback(async () => {
        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)
        }
      }, [priceToSave, user])
    
      const toggleHistory = useCallback(() => {
        setShowHistory((prev) => !prev)
      }, [])
    
      const getDate = useCallback((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}`
      }, [])
    
      const toggleFullList = useCallback(() => {
        setShowFullList((prev) => !prev)
      }, [])
    
      useEffect(() => {
        let subscribed = true
        setIsLoading(true)
        async function getPrices() {
          const priceService = new PricesService()
          const pricesByFluid = await priceService.getPricesByFluid(fluid)
          if (pricesByFluid.length) {
            const nextPriceToCreate: IPrice = {
              fluidType: fluid,
              price: '',
              startDate: '',
              endDate: null,
            }
            // Set the correct for the next price to create
            const date: string = dayjs(pricesByFluid[0].startDate)
              .utc(true)
              .tz('Europe/Paris')
              .add(frequency, 'month')
              .startOf('day')
              .format('YYYY-MM-DDTHH:mm:ss[Z]')
    
            nextPriceToCreate.startDate = date
            if (subscribed) {
              setPrices(pricesByFluid)
              setPriceToSave(nextPriceToCreate)
              setNextPrice(nextPriceToCreate)
            }
            setIsLoading(false)
          }
        }
        getPrices()
    
        return () => {
          subscribed = false
          setRefreshData(false)
        }
      }, [refreshData, frequency, fluid])
    
      if (isLoading) return <Loader></Loader>
      if (!prices.length) return <section> Aucun prix trouvé</section>
      return (
        <section>
          <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
              className="input-dark price-select"
              type="text"
              value={priceToSave.price.toString()}
              onChange={(e) => handlePriceSelection(e.target.value)}
              placeholder={priceToSave.price === '' ? 'Saisir le nouveau prix' : ''}
            />
            <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>
          <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' : ''}
                alt="arrow-icon"
              />
            </button>
            {showHistory && (
              <ul className={showHistory ? 'active' : ''}>
                {nextPrice && (
                  <PriceRow
                    getDate={getDate}
                    priceToSave={priceToSave}
                    price={nextPrice}
                    prices={prices}
                    setPriceToSave={setPriceToSave}
                    index={0}
                    isNextPrice={true}
                  />
                )}
                {prices.map((price, i) => {
                  return (
                    <div
                      key={i}
                      className={
                        i > maxPerList && !showFullList ? 'price-hidden' : ''
                      }
                    >
                      <PriceRow
                        getDate={getDate}
                        priceToSave={priceToSave}
                        price={price}
                        prices={prices}
                        setPriceToSave={setPriceToSave}
                        index={i}
                      />
                      {i === maxPerList && !showFullList && (
                        <button onClick={toggleFullList} className="showButton">
                          En voir plus
                        </button>
                      )}
                    </div>
                  )
                })}
                {showFullList && (
                  <button onClick={toggleFullList} className="showButton">
                    En voir moins
                  </button>
                )}
              </ul>
            )}
          </div>
        </section>
      )
    }
    
    export default PriceSection