From 2697b9410392a506853077a7e1e59ebdc1448491 Mon Sep 17 00:00:00 2001
From: "guilhem.carron" <gcarron@grandlyon.com>
Date: Wed, 4 Aug 2021 10:29:20 +0200
Subject: [PATCH] Add loader + change post to put + style toast

---
 src/components/Editing/Editing.tsx         | 90 +++++++++++++---------
 src/components/Editing/editing.scss        |  3 +
 src/components/Loader/Loader.tsx           | 10 +++
 src/components/Loader/loader.scss          | 75 ++++++++++++++++++
 src/components/MonthlyNews/MonthlyNews.tsx | 21 +++--
 src/components/Poll/Poll.tsx               | 21 +++--
 src/services/monthlyNews.service.ts        |  9 +--
 src/styles/_toast.scss                     | 25 ++++--
 src/styles/config/_typography.scss         | 13 ++++
 9 files changed, 208 insertions(+), 59 deletions(-)
 create mode 100644 src/components/Loader/Loader.tsx
 create mode 100644 src/components/Loader/loader.scss

diff --git a/src/components/Editing/Editing.tsx b/src/components/Editing/Editing.tsx
index 3c38ae10..9fef0a70 100644
--- a/src/components/Editing/Editing.tsx
+++ b/src/components/Editing/Editing.tsx
@@ -7,6 +7,7 @@ import { IMonthlyNews } from '../../models/monthlyNews.model'
 import Poll from '../Poll/Poll'
 import MonthlyNews from '../MonthlyNews/MonthlyNews'
 import { IPoll } from '../../models/poll.model'
+import Loader from '../Loader/Loader'
 
 const Editing: React.FC = () => {
   const [date, setDate] = useState<Date>(new Date())
@@ -15,10 +16,10 @@ const Editing: React.FC = () => {
   const [question, setQuestion] = useState<string>('')
   const [link, setLink] = useState<string>('')
   const [isTouched, setIsTouched] = useState<boolean>(false)
-  const [isMontlyNewsUpdating, setisMontlyNewsUpdating] =
-    useState<boolean>(false)
-  const [isPollUpdating, setisPollUpdating] = useState<boolean>(false)
+  const [refreshData, setRefreshData] = useState(false)
+  const [isLoading, setisLoading] = useState<boolean>(false)
   const { user }: Partial<UserContextProps> = useContext(UserContext)
+  const monthlyNewsService = new MonthlyNewsService()
 
   const handleSaveMonthlyNews = async (): Promise<void> => {
     if (user) {
@@ -29,27 +30,39 @@ const Editing: React.FC = () => {
         quote,
         user.xsrftoken
       )
-      console.log('saved')
       setIsTouched(false)
     }
   }
   const handleSavePoll = async (): Promise<void> => {
     if (user) {
-      const monthlyNewsService = new MonthlyNewsService()
       await monthlyNewsService.createPoll(date, question, link, user.xsrftoken)
-      console.log('saved')
       setIsTouched(false)
     }
   }
-  const handleCancelMonthlyNews = useCallback(() => {
-    setQuote('')
-    setHeader('')
+  const handleCancel = useCallback(() => {
+    setRefreshData(true)
   }, [])
 
-  const handleCancelPoll = useCallback(() => {
-    setLink('')
-    setQuestion('')
-  }, [])
+  const handleDeleteMonthlyNews = async (): Promise<void> => {
+    if (user) {
+      await monthlyNewsService.deleteMonthlyNews(
+        date.getFullYear(),
+        date.getMonth(),
+        user.xsrftoken
+      )
+      setRefreshData(true)
+    }
+  }
+  const handleDeletePoll = async (): Promise<void> => {
+    if (user) {
+      await monthlyNewsService.deletePoll(
+        date.getFullYear(),
+        date.getMonth(),
+        user.xsrftoken
+      )
+      setRefreshData(true)
+    }
+  }
 
   const isEmpty = (): boolean => {
     if ((quote !== '' || header !== '') && isTouched) {
@@ -85,6 +98,7 @@ const Editing: React.FC = () => {
   useEffect(() => {
     let subscribed = true
     resetFields()
+    setisLoading(true)
     async function getCurrentMonthlyNews() {
       if (user) {
         const monthlyNewsService = new MonthlyNewsService()
@@ -103,24 +117,24 @@ const Editing: React.FC = () => {
           setHeader(montlhyNews.header)
           setQuote(montlhyNews.quote)
           setIsTouched(false)
-          setisMontlyNewsUpdating(true)
         }
         if (poll) {
           setLink(poll.link)
           setQuestion(poll.question)
           setIsTouched(false)
-          setisPollUpdating(true)
         }
       }
+
+      setisLoading(false)
     }
     if (subscribed) {
       getCurrentMonthlyNews()
-      console.log('updating?', isMontlyNewsUpdating)
     }
     return () => {
       subscribed = false
+      setRefreshData(false)
     }
-  }, [date, user])
+  }, [date, user, refreshData])
 
   return (
     <>
@@ -129,24 +143,30 @@ const Editing: React.FC = () => {
           Édition des informations et de la citation du mois
         </p>
       </div>
-      <div className="content">
-        <DateSelector date={date} setDate={setDate} isEmpty={isEmpty} />
-        <MonthlyNews
-          header={header}
-          quote={quote}
-          onSave={handleSaveMonthlyNews}
-          onCancel={handleCancelMonthlyNews}
-          handleChange={handleEditorChange}
-        />
-        <hr />
-        <Poll
-          question={question}
-          link={link}
-          handleChange={handleEditorChange}
-          onSave={handleSavePoll}
-          onCancel={handleCancelPoll}
-        />
-      </div>
+      {isLoading ? (
+        <Loader />
+      ) : (
+        <div className="content">
+          <DateSelector date={date} setDate={setDate} isEmpty={isEmpty} />
+          <MonthlyNews
+            header={header}
+            quote={quote}
+            onSave={handleSaveMonthlyNews}
+            onCancel={handleCancel}
+            handleChange={handleEditorChange}
+            onDelete={handleDeleteMonthlyNews}
+          />
+          <hr />
+          <Poll
+            question={question}
+            link={link}
+            handleChange={handleEditorChange}
+            onSave={handleSavePoll}
+            onCancel={handleCancel}
+            onDelete={handleDeletePoll}
+          />
+        </div>
+      )}
     </>
   )
 }
diff --git a/src/components/Editing/editing.scss b/src/components/Editing/editing.scss
index 9d1a17d1..ecbd9869 100644
--- a/src/components/Editing/editing.scss
+++ b/src/components/Editing/editing.scss
@@ -19,3 +19,6 @@
 hr {
   margin: 2rem 1rem;
 }
+.buttons {
+  display: flex;
+}
diff --git a/src/components/Loader/Loader.tsx b/src/components/Loader/Loader.tsx
new file mode 100644
index 00000000..c282c3ce
--- /dev/null
+++ b/src/components/Loader/Loader.tsx
@@ -0,0 +1,10 @@
+import './loader.scss'
+const Loader: React.FC = () => {
+  return (
+    <div className="loader-container">
+      <div className="loader">Loading...</div>
+    </div>
+  )
+}
+
+export default Loader
diff --git a/src/components/Loader/loader.scss b/src/components/Loader/loader.scss
new file mode 100644
index 00000000..872512dc
--- /dev/null
+++ b/src/components/Loader/loader.scss
@@ -0,0 +1,75 @@
+@import '../../styles/config/colors.scss';
+
+.loader-container {
+  width: 100%;
+  height: 80vh;
+  display: flex;
+  overflow: hidden;
+}
+.loader {
+  font-size: 10px;
+  margin: auto;
+  text-indent: -9999em;
+  width: 11em;
+  height: 11em;
+  border-radius: 50%;
+  background: $gold;
+  background: -moz-linear-gradient(left, $gold 10%, rgba(255, 255, 255, 0) 42%);
+  background: -webkit-linear-gradient(
+    left,
+    $gold 10%,
+    rgba(255, 255, 255, 0) 42%
+  );
+  background: -o-linear-gradient(left, $gold 10%, rgba(255, 255, 255, 0) 42%);
+  background: -ms-linear-gradient(left, $gold 10%, rgba(255, 255, 255, 0) 42%);
+  background: linear-gradient(to right, $gold 10%, rgba(255, 255, 255, 0) 42%);
+  position: relative;
+  -webkit-animation: load3 1.4s infinite linear;
+  animation: load3 1.4s infinite linear;
+  -webkit-transform: translateZ(0);
+  -ms-transform: translateZ(0);
+  transform: translateZ(0);
+}
+.loader:before {
+  width: 50%;
+  height: 50%;
+  background: $gold;
+  border-radius: 100% 0 0 0;
+  position: absolute;
+  top: 0;
+  left: 0;
+  content: '';
+}
+.loader:after {
+  background: $dark-light;
+  width: 75%;
+  height: 75%;
+  border-radius: 50%;
+  content: '';
+  margin: auto;
+  position: absolute;
+  top: 0;
+  left: 0;
+  bottom: 0;
+  right: 0;
+}
+@-webkit-keyframes load3 {
+  0% {
+    -webkit-transform: rotate(0deg);
+    transform: rotate(0deg);
+  }
+  100% {
+    -webkit-transform: rotate(360deg);
+    transform: rotate(360deg);
+  }
+}
+@keyframes load3 {
+  0% {
+    -webkit-transform: rotate(0deg);
+    transform: rotate(0deg);
+  }
+  100% {
+    -webkit-transform: rotate(360deg);
+    transform: rotate(360deg);
+  }
+}
diff --git a/src/components/MonthlyNews/MonthlyNews.tsx b/src/components/MonthlyNews/MonthlyNews.tsx
index 26d5a301..9920226b 100644
--- a/src/components/MonthlyNews/MonthlyNews.tsx
+++ b/src/components/MonthlyNews/MonthlyNews.tsx
@@ -2,7 +2,7 @@ import { Editor } from '@tinymce/tinymce-react'
 import React from 'react'
 
 interface MonthlyNewsProps {
-  onSave: () => void
+  onSave: () => Promise<void>
   onCancel: () => void
   header: string
   quote: string
@@ -10,6 +10,7 @@ interface MonthlyNewsProps {
     value: string,
     type: 'header' | 'quote' | 'question' | 'link'
   ) => void
+  onDelete: () => Promise<void>
 }
 const MonthlyNews: React.FC<MonthlyNewsProps> = ({
   onSave,
@@ -17,6 +18,7 @@ const MonthlyNews: React.FC<MonthlyNewsProps> = ({
   header,
   quote,
   handleChange,
+  onDelete,
 }: MonthlyNewsProps) => {
   return (
     <>
@@ -101,12 +103,17 @@ const MonthlyNews: React.FC<MonthlyNewsProps> = ({
           value={quote}
           onEditorChange={(newQuote) => handleChange(newQuote, 'quote')}
         />
-        <button className="btnCancel" onClick={onCancel}>
-          Annuler
-        </button>
-        <button className="btnValid" onClick={onSave}>
-          Sauvegarder
-        </button>
+        <div className="buttons">
+          <button className="btnCancel" onClick={onCancel}>
+            Annuler
+          </button>
+          <button className="btnValid" onClick={onSave}>
+            Sauvegarder
+          </button>
+          <button className="btnDelete" onClick={onDelete}>
+            Supprimer
+          </button>
+        </div>
       </div>
     </>
   )
diff --git a/src/components/Poll/Poll.tsx b/src/components/Poll/Poll.tsx
index 075f1121..0cc8fb34 100644
--- a/src/components/Poll/Poll.tsx
+++ b/src/components/Poll/Poll.tsx
@@ -9,8 +9,9 @@ interface PollProps {
     value: string,
     type: 'header' | 'quote' | 'question' | 'link'
   ) => void
-  onSave: () => void
+  onSave: () => Promise<void>
   onCancel: () => void
+  onDelete: () => Promise<void>
 }
 const Poll: React.FC<PollProps> = ({
   question,
@@ -18,6 +19,7 @@ const Poll: React.FC<PollProps> = ({
   handleChange,
   onSave,
   onCancel,
+  onDelete,
 }: PollProps) => {
   const handleChangeLink = (e: ChangeEvent<HTMLInputElement>) => {
     handleChange(e.target.value, 'link')
@@ -48,12 +50,17 @@ const Poll: React.FC<PollProps> = ({
             handleChange(newQuestion, 'question')
           }
         />
-        <button className="btnCancel" onClick={onCancel}>
-          Annuler
-        </button>
-        <button className="btnValid" onClick={onSave}>
-          Sauvegarder
-        </button>
+        <div className="buttons">
+          <button className="btnCancel" onClick={onCancel}>
+            Annuler
+          </button>
+          <button className="btnValid" onClick={onSave}>
+            Sauvegarder
+          </button>
+          <button className="btnDelete" onClick={onDelete}>
+            Supprimer
+          </button>
+        </div>
       </div>
     </div>
   )
diff --git a/src/services/monthlyNews.service.ts b/src/services/monthlyNews.service.ts
index 905a4e81..eca0a334 100644
--- a/src/services/monthlyNews.service.ts
+++ b/src/services/monthlyNews.service.ts
@@ -20,7 +20,7 @@ export class MonthlyNewsService {
     token: string
   ): Promise<void> => {
     try {
-      await axios.post(
+      await axios.put(
         `${this._apiUrl}api/admin/monthlyNews`,
         {
           month: date.getMonth(),
@@ -34,7 +34,7 @@ export class MonthlyNewsService {
           },
         }
       )
-      toast.success('Monthly news succesfully created !')
+      toast.success('Monthly news succesfully saved !')
     } catch (e) {
       toast.error('Failed to create monthly news')
       console.log(e)
@@ -58,7 +58,6 @@ export class MonthlyNewsService {
           },
         }
       )
-      console.log('monthlyFetched', data)
       if (data == {}) {
         return null
       }
@@ -110,7 +109,7 @@ export class MonthlyNewsService {
     token: string
   ): Promise<void> => {
     try {
-      await axios.post(
+      await axios.put(
         `${this._apiUrl}api/admin/poll`,
         {
           month: date.getMonth(),
@@ -124,7 +123,7 @@ export class MonthlyNewsService {
           },
         }
       )
-      toast.success('Poll succesfully created !')
+      toast.success('Poll successfully saved !')
     } catch (e) {
       toast.error('Failed to create poll')
       console.log(e)
diff --git a/src/styles/_toast.scss b/src/styles/_toast.scss
index d9073c19..9654eb81 100644
--- a/src/styles/_toast.scss
+++ b/src/styles/_toast.scss
@@ -1,10 +1,25 @@
 @import 'config/colors';
 
+.Toastify__toast {
+  background: #fafafa !important;
+}
+.Toastify__toast--success {
+  .toastBody {
+    color: #73a839;
+  }
+  .toastProgress {
+    background: #73a839 !important;
+  }
+}
+
+.Toastify__toast--error {
+  .toastBody {
+    color: #c71c22;
+  }
+  .toastProgress {
+    background: #c71c22 !important;
+  }
+}
 .toastBody {
-  color: $dark-light;
   font-size: 1rem !important;
-  font-weight: bold;
-}
-.toastProgress {
-  background: white !important;
 }
diff --git a/src/styles/config/_typography.scss b/src/styles/config/_typography.scss
index 147bb9b5..380fea21 100644
--- a/src/styles/config/_typography.scss
+++ b/src/styles/config/_typography.scss
@@ -59,6 +59,19 @@ $main-spacing: 4px;
     background: darken($text-grey, 20%);
   }
 }
+.btnDelete {
+  @include baseButton();
+  display: inline-block;
+  margin-left: auto;
+  background: $dark-light;
+  color: $gold;
+  border: 1px solid $gold;
+  &:hover {
+    background: $dark-light;
+    color: $text-grey;
+    border: 1px solid $text-grey;
+  }
+}
 .input-dark {
   display: inline-block;
   margin-left: 0.5rem;
-- 
GitLab