import { Button, FormControl, FormControlLabel, FormGroup, NativeSelect, Switch, TextField, } from '@mui/material' import { DateTime } from 'luxon' import React, { useEffect, useState } from 'react' import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css' import { Link } from 'react-router-dom' import { getAxiosXSRFHeader } from '../../axios.config' import { useCustomPopup } from '../../hooks/useCustomPopup' import { usePartnersIssue } from '../../hooks/usePartnersIssue' import { useWhoAmI } from '../../hooks/useWhoAmI' import { ICustomPopup, PopupDuration } from '../../models/customPopup.model' import { Option, durationEnum, durationType, mapDuration, } from '../../models/durationOptions.model' import { convertStringToEditorState } from '../../utils/editorStateManagement' import { getFilenameFromPath } from '../../utils/imagesUrlsGetter' import ImagePicker from '../ImagePicker/ImagePicker' import Loader from '../Loader/Loader' import CustomEditor from '../Newsletter/CustomEditor' import { links } from '../Routes/Router' import './popups.scss' import { PopupWrapper } from './Wrapper' const OPTIONS: Option[] = [ { value: durationEnum.hours, label: 'Heures', }, { value: durationEnum.days, label: 'Jours', }, { value: durationEnum.infinite, label: 'Indéterminée', }, ] export const CustomPopup: React.FC = () => { const { partnersIssue } = usePartnersIssue() const { customPopup } = useCustomPopup() const isPartnerNotificationOn = Boolean( partnersIssue.data && (partnersIssue.data.enedis_failure || partnersIssue.data.egl_failure || partnersIssue.data.grdf_failure) ) if (isPartnerNotificationOn) { return ( <PopupWrapper> <p className="singlePopupWarning"> La pop-up personnalisée ne peut pas être activée en même temps que la{' '} <Link to={links.partnersIssue.path}> pop-up maintenance des partenaires </Link> </p> </PopupWrapper> ) } if (customPopup.isLoading) { return <Loader /> } if (customPopup.error) { return <p>Une erreur est survenue</p> } if (customPopup.data) { return ( <PopupWrapper> <CustomPopupForm initialData={customPopup.data} /> </PopupWrapper> ) } } export const CustomPopupForm = ({ initialData, }: { initialData: ICustomPopup }) => { const { data: user } = useWhoAmI() const { saveCustomPopup } = useCustomPopup() const isPopupOutdated = (date: string) => DateTime.local() >= DateTime.fromISO(date) const isOutdated = isPopupOutdated(initialData.endDate) const isEnabled = isOutdated ? false : initialData.popupEnabled const [popupDuration, setPopupDuration] = useState<PopupDuration>({ type: durationEnum.infinite, duration: 5, }) const [customPopup, setCustomPopup] = useState<ICustomPopup>({ popupEnabled: isEnabled, title: initialData.title, image: initialData.image || 'bullhorn', description: initialData.description, endDate: isOutdated ? DateTime.local().plus({ days: 365 }).toISO() : initialData.endDate, }) const toggleCustomPopup = (value: boolean): void => { setCustomPopup(prev => ({ ...prev, popupEnabled: value, })) } const handlePopupChange = ( value: string, field: 'title' | 'image' | 'description' ) => { setCustomPopup(prev => ({ ...prev, [field]: value, })) } const handleSave = async (): Promise<void> => { if (user) { saveCustomPopup( { ...customPopup, image: getFilenameFromPath(customPopup.image), }, getAxiosXSRFHeader(user.xsrftoken) ) } } const handleSelectChange = (event: React.ChangeEvent<HTMLSelectElement>) => { setPopupDuration(prev => ({ ...prev, type: event.target.value as durationType, })) } /** Handles duration change */ useEffect(() => { const now = DateTime.local() const newDate = popupDuration.type !== durationEnum.infinite ? now.plus({ [popupDuration.type]: popupDuration.duration }) : now.plus({ years: 1 }) setCustomPopup(prev => ({ ...prev, endDate: newDate.toISO() ?? '', })) }, [popupDuration]) /** * Returns "Popup expirée" OR "Temps restant : ..." */ const getRemainingDuration = (date: string) => { if (isOutdated) { 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="customPopup"> <h3>Affichage de pop-up personnalisée</h3> <FormGroup style={{ flexDirection: 'row' }}> <FormControlLabel label="Pop-up active" labelPlacement="top" control={ <Switch checked={customPopup.popupEnabled} onChange={event => toggleCustomPopup(event.target.checked)} /> } /> {customPopup.popupEnabled && initialData.endDate && getRemainingDuration(initialData.endDate)} </FormGroup> <div className="popupEndDate"> <h4>Durée</h4> <div> <FormControl style={{ flexDirection: 'row', gap: '1rem' }}> <NativeSelect inputProps={{ name: 'age', id: 'uncontrolled-native', }} onChange={event => handleSelectChange(event)} value={popupDuration.type} > {OPTIONS.map(option => ( <option key={option.value} value={option.value}> {option.label} </option> ))} </NativeSelect> {popupDuration.type !== 'infinite' && ( <TextField style={{ width: '6rem' }} inputProps={{ inputMode: 'numeric', pattern: '[0-9]*', }} id="outlined-number" type="number" label={mapDuration[popupDuration.type]} InputLabelProps={{ shrink: true, }} value={popupDuration.duration} onChange={e => setPopupDuration(prev => ({ ...prev, duration: Number(e.target.value), })) } /> )} </FormControl> </div> </div> <h4>Image</h4> <div> <ImagePicker imageURL={`/assets/ecogesture/${customPopup.image}.png`} handleChange={handlePopupChange} /> </div> <h4>Contenu</h4> <div className="popupTitle"> <TextField type="text" placeholder="Titre de la popup" fullWidth label="Titre" value={customPopup.title} onChange={event => handlePopupChange(event.target.value, 'title')} /> </div> <div className="popupDescription"> <CustomEditor baseState={convertStringToEditorState(customPopup.description)} handleChange={value => handlePopupChange(value, 'description')} type="custom_popup" /> </div> </div> <div className="buttons"> <Button variant="outlined" onClick={() => setCustomPopup(initialData)}> Annuler </Button> <Button onClick={handleSave} disabled={!user}> Sauvegarder </Button> </div> </> ) }