Skip to content
Snippets Groups Projects
Newsletter.tsx 9.58 KiB
Newer Older
Guilhem CARRON's avatar
Guilhem CARRON committed
import React, {
  useCallback,
  useContext,
  useEffect,
  useMemo,
  useState,
} from 'react'
Bastien DUMONT's avatar
Bastien DUMONT committed
import { getAxiosXSRFHeader } from '../../axios.config'
import { UserContext, UserContextProps } from '../../hooks/userContext'
Bastien DUMONT's avatar
Bastien DUMONT committed
import { IMailSubject } from '../../models/mailSubject.model'
import { IMonthlyInfo } from '../../models/monthlyInfo.model'
Bastien DUMONT's avatar
Bastien DUMONT committed
import { IMonthlyNews } from '../../models/monthlyNews.model'
import { IPoll } from '../../models/poll.model'
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 Modal from './Modal/Modal'
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 = () => {
  /**
   * 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>('')
  const { user }: Partial<UserContextProps> = useContext(UserContext)
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)
      )
      setIsTouched(false)
    }
  }
  const handleCancel = useCallback(() => {
    setRefreshData(true)
  }, [])

  const handleDeleteMailSubject = async (): Promise<void> => {
    if (user) {
Bastien DUMONT's avatar
Bastien DUMONT committed
      await newsletterService.deleteMailSubject(
        date,
        getAxiosXSRFHeader(user.xsrftoken)
      )
      setRefreshData(true)
    }
  }
  const handleDeleteMonthlyInfo = async (): Promise<void> => {
    if (user) {
Bastien DUMONT's avatar
Bastien DUMONT committed
      await newsletterService.deleteMonthlyInfo(
        date,
        getAxiosXSRFHeader(user.xsrftoken)
      )
      setRefreshData(true)
    }
  }
  const handleDeleteMonthlyNews = async (): Promise<void> => {
    if (user) {
Bastien DUMONT's avatar
Bastien DUMONT committed
      await newsletterService.deleteMonthlyNews(
        date,
        getAxiosXSRFHeader(user.xsrftoken)
      )
      setRefreshData(true)
    }
  }
  const handleDeletePoll = async (): Promise<void> => {
    if (user) {
Bastien DUMONT's avatar
Bastien DUMONT committed
      await newsletterService.deletePoll(
        date,
        getAxiosXSRFHeader(user.xsrftoken)
      )
      setRefreshData(true)
    }
  }
  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: IMailSubject | null =
Bastien DUMONT's avatar
Bastien DUMONT committed
          await newsletterService.getSingleMailSubject(
            date,
            getAxiosXSRFHeader(user.xsrftoken)
          )
Bastien DUMONT's avatar
Bastien DUMONT committed
        const monthlyInfo: IMonthlyInfo | null =
Bastien DUMONT's avatar
Bastien DUMONT committed
          await newsletterService.getSingleMonthlyInfo(
            date,
            getAxiosXSRFHeader(user.xsrftoken)
          )
Bastien DUMONT's avatar
Bastien DUMONT committed
        const monthlyNews: IMonthlyNews | null =
Bastien DUMONT's avatar
Bastien DUMONT committed
          await newsletterService.getSingleMonthlyNews(
            date,
            getAxiosXSRFHeader(user.xsrftoken)
          )
        const poll: IPoll | null = await newsletterService.getSinglePoll(
          date,
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">
Bastien DUMONT's avatar
Bastien DUMONT committed
        <p className="title pageTitle">Édition de la newsletter</p>
        <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}
          ></MailSubject>
          <hr />
          <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>
      )}
      {warningModal && (
        <Modal>
          <>
            <div className="modal-text">
Bastien DUMONT's avatar
Bastien DUMONT committed
              Êtes-vous sûr de vouloir supprimer{' '}
              {getContentItemString(toDelete)}&nbsp;?
            </div>
            <div className="buttons">
              <button
                className="btnCancel"
Bastien DUMONT's avatar
Bastien DUMONT committed
                onClick={() => setWarningModal(false)}
              >
                Annuler
              </button>
              <button className="btnValid" onClick={handleConfirmAlert}>
                Continuer
              </button>
            </div>
          </>
        </Modal>
      )}
    </>
  )
}

Bastien DUMONT's avatar
Bastien DUMONT committed
export default Newsletter