diff --git a/src/components/Prices/PriceRow.tsx b/src/components/Prices/PriceRow.tsx new file mode 100644 index 0000000000000000000000000000000000000000..9c78f73f1a87630a7ad759b3cd4f1b5c4b337ee9 --- /dev/null +++ b/src/components/Prices/PriceRow.tsx @@ -0,0 +1,56 @@ +import React from 'react' +import { IPrice } from '../../models/price.model' +import editing from '../../assets/icons/editing.png' + +interface PriceSectionProps { + getDate: (date: string) => string + setPriceToSave: React.Dispatch<React.SetStateAction<IPrice>> + priceToSave: IPrice + price: IPrice + prices: IPrice[] + index: number + isNextPrice?: boolean +} + +const PriceRow: React.FC<PriceSectionProps> = ({ + getDate, + setPriceToSave, + priceToSave, + price, + prices, + index, + isNextPrice, +}: PriceSectionProps) => { + const editableLimit: number = 3 + + console.log('eeerer') + return ( + <> + <li + className={ + priceToSave.startDate === price.startDate + ? 'flex-bloc price-selected' + : 'flex-bloc' + } + > + <div className="prix"> + {price.price === '' ? '----' : price.price} € + </div> + <p> + à partir de :{' '} + <span className="capital">{getDate(price.startDate)}</span> + </p> + {index < editableLimit - 1 && ( + <img + src={editing} + onClick={() => setPriceToSave(isNextPrice ? price : prices[index])} + alt="edit-icon" + /> + )} + </li> + <hr></hr> + </> + ) +} + +export default PriceRow diff --git a/src/components/Prices/PriceSection.tsx b/src/components/Prices/PriceSection.tsx index 9ead1b7915248e2c98555998e5906532e2ef4ea5..20e70cb972cef633d27f0e3fa8b580ea719a8cbc 100644 --- a/src/components/Prices/PriceSection.tsx +++ b/src/components/Prices/PriceSection.tsx @@ -6,13 +6,13 @@ 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' 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) @@ -26,28 +26,30 @@ const PriceSection: React.FC<PriceSectionProps> = ({ frequency, }: PriceSectionProps) => { const [prices, setPrices] = useState<IPrice[]>([]) - const [nextPrice, setnextPrice] = 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>({ + 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 editableLimit: number = 3 const maxPerList: number = 8 - const handlePriceSelection = (val: string) => { + + const handlePriceSelection = useCallback((val: string) => { if (val === '') val = '0' val = val.replace(/,/g, '.') val = val.replace(/([^0-9.]+)/, '') - setpriceToSave({ ...priceToSave, price: val }) - } + setPriceToSave((prev) => { + return { ...prev, price: val } + }) + }, []) - const savePrice = async () => { + const savePrice = useCallback(async () => { if ( priceToSave && user && @@ -62,20 +64,21 @@ const PriceSection: React.FC<PriceSectionProps> = ({ await priceService.savePrice(formattedPrice, user.xsrftoken) setRefreshData(true) } - } + }, [priceToSave, user]) const toggleHistory = useCallback(() => { - setshowHistory((prev) => !prev) + setShowHistory((prev) => !prev) }, []) - const getDate = (isoString: string): string => { + 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) + setShowFullList((prev) => !prev) }, []) useEffect(() => { @@ -83,17 +86,16 @@ const PriceSection: React.FC<PriceSectionProps> = ({ setIsLoading(true) async function getPrices() { const priceService = new PricesService() - const prices = await priceService.getPricesByFluid(fluid) - if (prices.length) { + const pricesByFluid = await priceService.getPricesByFluid(fluid) + if (pricesByFluid.length) { const nextPriceToCreate: IPrice = { fluidType: fluid, price: '', startDate: '', endDate: null, } - console.log('prices', prices) // Set the correct for the next price to create - const date: string = dayjs(prices[0].startDate) + const date: string = dayjs(pricesByFluid[0].startDate) .utc(true) .tz('Europe/Paris') .add(frequency, 'month') @@ -102,9 +104,9 @@ const PriceSection: React.FC<PriceSectionProps> = ({ nextPriceToCreate.startDate = date if (subscribed) { - setPrices(prices) - setpriceToSave(nextPriceToCreate) - setnextPrice(nextPriceToCreate) + setPrices(pricesByFluid) + setPriceToSave(nextPriceToCreate) + setNextPrice(nextPriceToCreate) } setIsLoading(false) } @@ -118,137 +120,94 @@ const PriceSection: React.FC<PriceSectionProps> = ({ }, [refreshData, frequency, fluid]) if (isLoading) return <Loader></Loader> + if (!prices.length) return <section> Aucun prix trouvé</section> 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 - 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> + <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" + <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} /> - </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)} - alt="edit-icon" - /> - </li> - <hr></hr> - </> - )} - {prices.map((price, i) => { - return ( - <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> - {i < editableLimit - 1 && ( - <img - src={editing} - onClick={() => setpriceToSave(prices[i])} - alt="edit-icon" - /> - )} - </li> - <hr></hr> - {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> - </> - ) : ( - 'Aucun prix trouvé' - )} + {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> ) }