import { DateTime } from 'luxon' import React, { useCallback, useContext, useEffect, useState } from 'react' import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css' import { getAxiosXSRFHeader } from '../../axios.config' import { CheckboxType } from '../../enum/checkboxType.enum' import { UserContext, UserContextProps } from '../../hooks/userContext' import { ICustomPopup, PopupDuration } from '../../models/customPopup.model' import { Option, durationEnum, durationType, } from '../../models/durationOptions.model' import { IPartnersInfo } from '../../models/partnersInfo.model' import { CustomPopupService } from '../../services/customPopup.service' import { PartnersInfoService } from '../../services/partnersInfo.service' import { convertStringToEditorState } from '../../utils/editorStateManagement' import Loader from '../Loader/Loader' import CustomEditor from '../Newsletter/CustomEditor' import './popups.scss' const OPTIONS: Array<Option> = [ { value: durationEnum.hours, label: 'Heures', }, { value: durationEnum.days, label: 'Jours', }, { value: durationEnum.infinite, label: 'Indéterminée', }, ] const Popups: React.FC = () => { const [refreshData, setRefreshData] = useState(false) const [isLoading, setIsLoading] = useState(false) const [partnersInfo, setPartnersInfo] = useState<IPartnersInfo>({ grdf_failure: false, enedis_failure: false, egl_failure: false, notification_activated: false, }) const [previousEndDate, setPreviousEndDate] = useState<string>() const [customPopup, setCustomPopup] = useState<ICustomPopup>({ popupEnabled: false, title: '', description: '', endDate: DateTime.local().toISO(), }) const [popupDuration, setPopupDuration] = useState<PopupDuration>({ type: 'days', duration: 0, }) const { user }: Partial<UserContextProps> = useContext(UserContext) const isPartnerNotificationOn = () => partnersInfo.enedis_failure || partnersInfo.egl_failure || partnersInfo.grdf_failure /** * Only one type of popup can be enabled */ const isPageValid = () => !(isPartnerNotificationOn() && customPopup.popupEnabled) const handleCheckboxChange = (value: boolean, type: CheckboxType): void => { switch (type) { case CheckboxType.GRDF: setPartnersInfo((prevPartnersInfo) => ({ ...prevPartnersInfo, grdf_failure: value, })) break case CheckboxType.ENEDIS: setPartnersInfo((prevPartnersInfo) => ({ ...prevPartnersInfo, enedis_failure: value, })) break case CheckboxType.EGL: setPartnersInfo((prevPartnersInfo) => ({ ...prevPartnersInfo, egl_failure: value, })) break case CheckboxType.CUSTOM: setCustomPopup((prev) => ({ ...prev, popupEnabled: value, })) break default: throw new Error('Unknown checkbox type') } } const handlePopupChange = (field: 'title' | 'description', value: string) => { setCustomPopup((prev) => ({ ...prev, [field]: value, })) } const handleCancel = useCallback(() => { setRefreshData(true) }, [setRefreshData]) const resetFields = useCallback(() => { setPartnersInfo({ grdf_failure: false, enedis_failure: false, egl_failure: false, notification_activated: false, }) }, [setPartnersInfo]) useEffect(() => { let subscribed = true resetFields() setIsLoading(true) async function loadSettings() { if (user) { const partnersInfoService = new PartnersInfoService() const customPopupService = new CustomPopupService() const partnersInfoData = await partnersInfoService.getPartnersInfo() const customPopupData = await customPopupService.getCustomPopupInfo() if (partnersInfoData) { setPartnersInfo({ ...partnersInfoData, }) } if (customPopupData) { setCustomPopup({ ...customPopupData, }) setPreviousEndDate(customPopupData.endDate || undefined) } } setIsLoading(false) } if (subscribed) { loadSettings() } return () => { subscribed = false setRefreshData(false) } }, [user, refreshData, setPartnersInfo, setCustomPopup, resetFields]) const handleSave = async (): Promise<void> => { if (user) { const partnersInfoService = new PartnersInfoService() const customPopupService = new CustomPopupService() const updatedPartnersInfo = { egl_failure: partnersInfo.egl_failure, enedis_failure: partnersInfo.enedis_failure, grdf_failure: partnersInfo.grdf_failure, notification_activated: isPartnerNotificationOn(), } await partnersInfoService.savePartnersInfo( updatedPartnersInfo, getAxiosXSRFHeader(user.xsrftoken) ) await customPopupService.saveCustomPopup( customPopup, getAxiosXSRFHeader(user.xsrftoken) ) setPreviousEndDate(customPopup.endDate) } } const handleSelectChange = (event: React.ChangeEvent<HTMLSelectElement>) => { setPopupDuration((prev) => ({ ...prev, type: event.target.value as durationType, })) } /** * Handles duration change */ useEffect(() => { const now = DateTime.local() let newDate: DateTime if (popupDuration.type !== durationEnum.infinite) { newDate = now.plus({ [popupDuration.type]: popupDuration.duration, }) } else if (popupDuration.type === 'infinite') { newDate = now.plus({ years: 1, }) } setCustomPopup((prev) => ({ ...prev, endDate: newDate.toISO(), })) }, [popupDuration]) const isPopupOutdated = (date: string) => DateTime.local() >= DateTime.fromISO(date) /** * Returns "Popup expirée" OR "Temps restant : ..." */ const getRemainingDuration = (date: string) => { if (isPopupOutdated(date)) { return <p className="endDate">Popup expirée</p> } return ( <p className="endDate"> Temps d'activation restant :<br /> {DateTime.fromISO(date) .diffNow(['days', 'hours', 'minutes', 'seconds']) .set({ second: 0 }) .toHuman()} </p> ) } return ( <> <div className="header"> <p className="title pageTitle">Paramètres de l'appli</p> </div> <div className="content popups"> {isLoading && <Loader />} {!isLoading && ( <> <h1>Création de Pop-up</h1> <div className="partnersInfo"> <h2 className="title">Affichage des pop-up de panne</h2> <div className={customPopup.popupEnabled ? 'disabled' : ''}> <p>Services concernés</p> <div className="switch_div"> <span>Panne Enedis</span> <input type="checkbox" id="switch_enedis" disabled={customPopup.popupEnabled} checked={partnersInfo.enedis_failure} onChange={(event) => { handleCheckboxChange( event.currentTarget.checked, CheckboxType.ENEDIS ) }} /> <label htmlFor="switch_enedis"></label> </div> <div className="switch_div"> <span>Panne EGL</span> <input type="checkbox" id="switch_egl" disabled={customPopup.popupEnabled} checked={partnersInfo.egl_failure} onChange={(event) => { handleCheckboxChange( event.currentTarget.checked, CheckboxType.EGL ) }} /> <label htmlFor="switch_egl"></label> </div> <div className="switch_div"> <span>Panne GRDF</span> <input type="checkbox" id="switch_grdf" disabled={customPopup.popupEnabled} checked={partnersInfo.grdf_failure} onChange={(event) => { handleCheckboxChange( event.currentTarget.checked, CheckboxType.GRDF ) }} /> <label htmlFor="switch_grdf"></label> </div> </div> </div> <div className="customPopup"> <h2 className="title">Affichage de pop-up personnalisée</h2> <div className={isPartnerNotificationOn() ? 'disabled' : ''}> <div className="currentPopup"> <div className="switch_div"> <span>Pop-up active</span> <input type="checkbox" id="switch_popup" disabled={isPartnerNotificationOn()} checked={customPopup.popupEnabled} onChange={(event) => { handleCheckboxChange( event.currentTarget.checked, CheckboxType.CUSTOM ) }} /> <label htmlFor="switch_popup"></label> </div> {customPopup.popupEnabled && previousEndDate && getRemainingDuration(previousEndDate)} </div> <div className="popupTitle"> <label htmlFor="title">Titre</label> <input type="text" name="title" id="title" min={1} placeholder="Titre" value={customPopup.title} onChange={(event) => handlePopupChange('title', event.target.value) } /> </div> <div className="popupDescription"> <CustomEditor baseState={convertStringToEditorState( customPopup.description )} handleChange={(value) => handlePopupChange('description', value) } type="custom_popup" /> </div> <div className="popupEndDate"> <label htmlFor="title">Nouvelle Durée</label> <div className="durationInput"> <select value={popupDuration.type} onChange={(event) => handleSelectChange(event)} > {OPTIONS.map((option) => ( <option key={option.value} value={option.value} selected={popupDuration.type === option.value} > {option.label} </option> ))} </select> {popupDuration.type !== 'infinite' && ( <input type="number" min="0" value={popupDuration.duration} onChange={(e) => setPopupDuration((prev) => ({ ...prev, duration: Number(e.target.value), })) } /> )} </div> </div> </div> </div> <div className="buttons"> <button className="btnCancel" onClick={handleCancel}> Annuler </button> <button className="btnValid" onClick={handleSave} disabled={!isPageValid()} title="Un seul type de popup peut être activé" > Sauvegarder </button> </div> </> )} </div> </> ) } export default Popups