Skip to content
Snippets Groups Projects
Popups.tsx 12.4 KiB
Newer Older
  • Learn to ignore specific revisions
  • import { DateTime } from 'luxon'
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    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'
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    import { ICustomPopup, PopupDuration } from '../../models/customPopup.model'
    
    import {
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
      Option,
    
      durationEnum,
      durationType,
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    } from '../../models/durationOptions.model'
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    import { IPartnersInfo } from '../../models/partnersInfo.model'
    import { CustomPopupService } from '../../services/customPopup.service'
    import { PartnersInfoService } from '../../services/partnersInfo.service'
    
    import { convertStringToEditorState } from '../../utils/editorStateManagement'
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    import Loader from '../Loader/Loader'
    
    import CustomEditor from '../Newsletter/CustomEditor'
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    import './popups.scss'
    
    const OPTIONS: Array<Option> = [
      {
        value: durationEnum.hours,
        label: 'Heures',
      },
      {
        value: durationEnum.days,
        label: 'Jours',
      },
      {
        value: durationEnum.infinite,
        label: 'Indéterminée',
      },
    ]
    
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    const Popups: React.FC = () => {
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
      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>()
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
      const [customPopup, setCustomPopup] = useState<ICustomPopup>({
        popupEnabled: false,
        title: '',
        description: '',
    
        endDate: DateTime.local().toISO(),
      })
      const [popupDuration, setPopupDuration] = useState<PopupDuration>({
        type: 'days',
        duration: 0,
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
      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)
    
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
      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) => {
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
        setCustomPopup((prev) => ({
          ...prev,
    
          [field]: value,
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
        }))
      }
    
      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() {
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
          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)
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
            }
          }
          setIsLoading(false)
        }
        if (subscribed) {
    
          loadSettings()
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
        }
        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&apos;activation restant :<br />
            {DateTime.fromISO(date)
              .diffNow(['days', 'hours', 'minutes', 'seconds'])
              .set({ second: 0 })
              .toHuman()}
          </p>
        )
      }
    
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
      return (
        <>
          <div className="header">
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
            <p className="title pageTitle">Paramètres de l&apos;appli</p>
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
          <div className="content popups">
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
            {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>
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
                  </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>
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
                        <input
    
                          type="checkbox"
                          id="switch_popup"
                          disabled={isPartnerNotificationOn()}
                          checked={customPopup.popupEnabled}
                          onChange={(event) => {
                            handleCheckboxChange(
                              event.currentTarget.checked,
                              CheckboxType.CUSTOM
                            )
                          }}
    
                        <label htmlFor="switch_popup"></label>
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
                      </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>
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
                </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é"
                  >
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
                    Sauvegarder
                  </button>
                </div>
              </>
            )}
          </div>
        </>
      )
    }
    
    
    Bastien DUMONT's avatar
    Bastien DUMONT committed
    export default Popups