Skip to content
Snippets Groups Projects
Newsletter.tsx 8.92 KiB
Newer Older
import { Button, Dialog } from '@mui/material'
import React, { useCallback, useEffect, useMemo, useState } from 'react'
Bastien DUMONT's avatar
Bastien DUMONT committed
import { getAxiosXSRFHeader } from '../../axios.config'
import { useWhoAmI } from '../../hooks/useWhoAmI'
Bastien DUMONT's avatar
Bastien DUMONT committed
import { NewsletterService } from '../../services/newsletter.service'
import Loader from '../Loader/Loader'
import { EditorType } from './CustomEditor'
Bastien DUMONT's avatar
Bastien DUMONT committed
import DateSelector from './DateSelector/DateSelector'
Bastien DUMONT's avatar
Bastien DUMONT committed
import MailSubject from './MailSubject/mailSubject'
Bastien DUMONT's avatar
Bastien DUMONT committed
import MonthlyInfo from './MonthlyInfo/MonthlyInfo'
import MonthlyNews from './MonthlyNews/MonthlyNews'
import Poll from './Poll/Poll'
import './newsletter.scss'
export type ContentItems =
  | 'monthlyInfo'
  | 'monthlyNews'
  | 'poll'
  | 'subject'
  | ''
Bastien DUMONT's avatar
Bastien DUMONT committed
const Newsletter: React.FC = () => {
  const { data: user } = useWhoAmI()

  /** Display previous month until the newsletter is sent on the 3rd day of the month */
  const getCurrentNewsletterDate = (): Date => {
    const today = new Date()
    const currentDay = today.getDate()
    const currentMonth = today.getMonth()
    const currentYear = today.getFullYear()

    return currentDay < 3
      ? new Date(currentYear, currentMonth, 1)
      : new Date(currentYear, currentMonth + 1, 1)
  }

  const [date, setDate] = useState<Date>(getCurrentNewsletterDate())
  const [info, setInfo] = useState<string>('')
  const [title, setTitle] = useState<string>('')
  const [subject, setSubject] = useState<string>('')
  const [imageURL, setImageURL] = useState<string>('')
  const [content, setContent] = useState<string>('')
  const [question, setQuestion] = useState<string>('')
  const [link, setLink] = useState<string>('')
  const [isTouched, setIsTouched] = useState<boolean>(false)
  const [refreshData, setRefreshData] = useState(false)
Bastien DUMONT's avatar
Bastien DUMONT committed
  const [isLoading, setIsLoading] = useState<boolean>(false)
  const [warningModal, setWarningModal] = useState<boolean>(false)
  const [toDelete, setToDelete] = useState<ContentItems>('')
Guilhem CARRON's avatar
Guilhem CARRON committed
  const newsletterService = useMemo(() => {
    return new NewsletterService()
  }, [])
  const handleSaveSubject = async (): Promise<void> => {
    if (user) {
Bastien DUMONT's avatar
Bastien DUMONT committed
      await newsletterService.saveMailSubject(
        date,
        subject,
        getAxiosXSRFHeader(user.xsrftoken)
      )
      setIsTouched(false)
    }
  }

  const handleSaveMonthlyInfo = async (): Promise<void> => {
    if (user) {
      await newsletterService.saveMonthlyInfo(
        date,
        info,
        imageURL,
Bastien DUMONT's avatar
Bastien DUMONT committed
        getAxiosXSRFHeader(user.xsrftoken)
      )
      setIsTouched(false)
    }
  }

  const handleSaveMonthlyNews = async (): Promise<void> => {
    if (user) {
      await newsletterService.saveMonthlyNews(
        date,
        title,
        content,
Bastien DUMONT's avatar
Bastien DUMONT committed
        getAxiosXSRFHeader(user.xsrftoken)
      )
      setIsTouched(false)
    }
  }
  const handleSavePoll = async (): Promise<void> => {
    if (user) {
Bastien DUMONT's avatar
Bastien DUMONT committed
      await newsletterService.savePoll(
        date,
        question,
        link,
        getAxiosXSRFHeader(user.xsrftoken)
      )
  const handleCancel = () => {
    setRefreshData(true)
  const handleDeleteMailSubject = async (): Promise<void> => {
    if (user) {
Bastien DUMONT's avatar
Bastien DUMONT committed
      await newsletterService.deleteMailSubject(
        date,
        getAxiosXSRFHeader(user.xsrftoken)
      )
      handleCancel()
  const handleDeleteMonthlyInfo = async (): Promise<void> => {
    if (user) {
Bastien DUMONT's avatar
Bastien DUMONT committed
      await newsletterService.deleteMonthlyInfo(
        date,
        getAxiosXSRFHeader(user.xsrftoken)
      )
      handleCancel()
    }
  }
  const handleDeleteMonthlyNews = async (): Promise<void> => {
    if (user) {
Bastien DUMONT's avatar
Bastien DUMONT committed
      await newsletterService.deleteMonthlyNews(
        date,
        getAxiosXSRFHeader(user.xsrftoken)
      )
      handleCancel()
    }
  }
  const handleDeletePoll = async (): Promise<void> => {
    if (user) {
Bastien DUMONT's avatar
Bastien DUMONT committed
      await newsletterService.deletePoll(
        date,
        getAxiosXSRFHeader(user.xsrftoken)
      )
      handleCancel()
    }
  }
  const handleOpenDeleteModal = (target: ContentItems) => {
Bastien DUMONT's avatar
Bastien DUMONT committed
    setToDelete(target)
    setWarningModal(true)
  }
  const handleConfirmAlert = () => {
    if (toDelete === 'subject') {
      handleDeleteMailSubject()
    }
    if (toDelete === 'monthlyInfo') {
      handleDeleteMonthlyInfo()
    }
    if (toDelete === 'monthlyNews') {
      handleDeleteMonthlyNews()
    }
    if (toDelete === 'poll') {
      handleDeletePoll()
    }
Bastien DUMONT's avatar
Bastien DUMONT committed
    setWarningModal(false)
  }

  const isEmpty = (): boolean => {
    if (
      (info !== '' ||
        title !== '' ||
        content !== '' ||
        question !== '' ||
        imageURL !== '' ||
        link !== '' ||
        subject !== '') &&
      isTouched
    ) {
      return false
    } else return true
  }

  const handleEditorChange = (value: string, type: EditorType): void => {
    setIsTouched(true)
    switch (type) {
      case 'info':
        setInfo(value)
        break
      case 'title':
        setTitle(value)
        break
      case 'content':
        setContent(value)
        break
      case 'question':
        setQuestion(value)
        break
      case 'link':
        setLink(value)
        break
      case 'subject':
        setSubject(value)
        break
      case 'image':
        setImageURL(value)
        break
      default:
        break
  const resetFields = useCallback(() => {
    setSubject('')
    setImageURL('')
    setInfo('')
    setTitle('')
    setContent('')
    setLink('')
    setQuestion('')
  }, [])

Guilhem CARRON's avatar
Guilhem CARRON committed
  const getContentItemString = (contentItem: ContentItems) => {
    if (contentItem === 'monthlyInfo') return 'cette info mensuelle'
    if (contentItem === 'monthlyNews') return 'cette news mensuelle'
    if (contentItem === 'subject') return 'cet objet'
    return 'ce sondage'
  }

  useEffect(() => {
    let subscribed = true
    resetFields()
Bastien DUMONT's avatar
Bastien DUMONT committed
    setIsLoading(true)
    async function getCurrentMonthlyNews() {
      if (user) {
        const mailSubject = await newsletterService.getSingleMailSubject(
          date,
          getAxiosXSRFHeader(user.xsrftoken)
        )
        const monthlyInfo = await newsletterService.getSingleMonthlyInfo(
          date,
          getAxiosXSRFHeader(user.xsrftoken)
        )
        const monthlyNews = await newsletterService.getSingleMonthlyNews(
          date,
          getAxiosXSRFHeader(user.xsrftoken)
        )
        const poll = await newsletterService.getSinglePoll(
Bastien DUMONT's avatar
Bastien DUMONT committed
          getAxiosXSRFHeader(user.xsrftoken)
        if (mailSubject) {
          setSubject(mailSubject.subject)
          setIsTouched(false)
        }
Bastien DUMONT's avatar
Bastien DUMONT committed
        if (monthlyInfo) {
          setInfo(monthlyInfo.info)
          setImageURL(monthlyInfo.image)
Bastien DUMONT's avatar
Bastien DUMONT committed
        if (monthlyNews) {
          setTitle(monthlyNews.title)
          setContent(monthlyNews.content)
          setIsTouched(false)
        }
        if (poll) {
          setLink(poll.link)
          setQuestion(poll.question)
          setIsTouched(false)
        }
      }
Bastien DUMONT's avatar
Bastien DUMONT committed
      setIsLoading(false)
    }
    if (subscribed) {
      getCurrentMonthlyNews()
    }
    return () => {
      subscribed = false
      setRefreshData(false)
    }
Guilhem CARRON's avatar
Guilhem CARRON committed
  }, [date, user, refreshData, resetFields, newsletterService])

  return (
    <>
      <div className="header">
        <h1 className="title pageTitle">Édition de la newsletter</h1>
        <DateSelector date={date} setDate={setDate} isEmpty={isEmpty} />
      </div>
      {isLoading && <Loader />}
      {!isLoading && (
        <div className="content">
          <MailSubject
            onSave={handleSaveSubject}
            onCancel={handleCancel}
            subject={subject}
            handleChange={handleEditorChange}
            onDelete={handleOpenDeleteModal}
Bastien DUMONT's avatar
Bastien DUMONT committed
          />
          <MonthlyInfo
            info={info}
            onSave={handleSaveMonthlyInfo}
            onCancel={handleCancel}
            handleChange={handleEditorChange}
            onDelete={handleOpenDeleteModal}
            imageURL={imageURL}
          />
          <hr />
          <MonthlyNews
            title={title}
            content={content}
            onSave={handleSaveMonthlyNews}
            onCancel={handleCancel}
            handleChange={handleEditorChange}
            onDelete={handleOpenDeleteModal}
          />
          <hr />
          <Poll
            question={question}
            link={link}
            onSave={handleSavePoll}
            onCancel={handleCancel}
            handleChange={handleEditorChange}
            onDelete={handleOpenDeleteModal}
          />
        </div>
      )}

      <Dialog open={warningModal}>
        <div className="modal-text">
          Êtes-vous sûr de vouloir supprimer {getContentItemString(toDelete)}
          &nbsp;?
        </div>
        <div className="buttons">
          <Button variant="outlined" onClick={() => setWarningModal(false)}>
            Annuler
          </Button>
          <Button onClick={handleConfirmAlert}>Continuer</Button>
        </div>
      </Dialog>
Bastien DUMONT's avatar
Bastien DUMONT committed
export default Newsletter