diff --git a/website/package-lock.json b/website/package-lock.json index 193bbf6..58392bb 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -1432,6 +1432,11 @@ "prop-types": "^15.7.2" } }, + "@icons/material": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/@icons/material/-/material-0.2.4.tgz", + "integrity": "sha512-QPcGmICAPbGLGb6F/yNf/KzKqvFx8z5qx3D1yFqVAjoFmXK35EgyW+cJ57Te3CNsmzblwtzakLGFqHPqrfb4Tw==" + }, "@next/polyfill-nomodule": { "version": "9.3.2", "resolved": "https://registry.npmjs.org/@next/polyfill-nomodule/-/polyfill-nomodule-9.3.2.tgz", @@ -5007,6 +5012,11 @@ "object-visit": "^1.0.0" } }, + "material-colors": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/material-colors/-/material-colors-1.2.6.tgz", + "integrity": "sha512-6qE4B9deFBIa9YSpOc9O0Sgc43zTeVYbgDT5veRKSlB2+ZuHNoVVxA1L/ckMUayV9Ay9y7Z/SZCLcGteW9i7bg==" + }, "md5.js": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz", @@ -8456,6 +8466,19 @@ "prop-types": "^15.6.2" } }, + "react-color": { + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/react-color/-/react-color-2.18.0.tgz", + "integrity": "sha512-FyVeU1kQiSokWc8NPz22azl1ezLpJdUyTbWL0LPUpcuuYDrZ/Y1veOk9rRK5B3pMlyDGvTk4f4KJhlkIQNRjEA==", + "requires": { + "@icons/material": "^0.2.4", + "lodash": "^4.17.11", + "material-colors": "^1.2.1", + "prop-types": "^15.5.10", + "reactcss": "^1.2.0", + "tinycolor2": "^1.4.1" + } + }, "react-dom": { "version": "16.13.0", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.13.0.tgz", @@ -8571,6 +8594,14 @@ } } }, + "reactcss": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/reactcss/-/reactcss-1.2.3.tgz", + "integrity": "sha512-KiwVUcFu1RErkI97ywr8nvx8dNOpT03rbnma0SSalTYjkrPYaEajR4a/MRt6DZ46K6arDRbWMNHF+xH7G7n/8A==", + "requires": { + "lodash": "^4.0.1" + } + }, "read-pkg": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", @@ -9675,6 +9706,11 @@ "setimmediate": "^1.0.4" } }, + "tinycolor2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.1.tgz", + "integrity": "sha1-9PrTM0R7wLB9TcjpIJ2POaisd+g=" + }, "to-arraybuffer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz", diff --git a/website/package.json b/website/package.json index ea68c48..d7a9876 100644 --- a/website/package.json +++ b/website/package.json @@ -20,6 +20,7 @@ "next-fonts": "^1.0.3", "nprogress": "^0.2.0", "react": "16.13.0", + "react-color": "^2.18.0", "react-dom": "16.13.0", "react-swipeable-views": "^0.13.9", "react-swipeable-views-utils": "^0.13.9", diff --git a/website/pages/admin/index.js b/website/pages/admin/index.js index f31588a..1ecc462 100644 --- a/website/pages/admin/index.js +++ b/website/pages/admin/index.js @@ -90,12 +90,12 @@ const Admin = (props) => {
- +
- +
diff --git a/website/pages/admin/manageCategories.js b/website/pages/admin/manageCategories.js index bea05c8..20cfc24 100644 --- a/website/pages/admin/manageCategories.js +++ b/website/pages/admin/manageCategories.js @@ -1,17 +1,117 @@ -import { Fragment } from 'react'; +import { Fragment, useState } from 'react'; import Cookies from "universal-cookie"; import date from 'date-and-time'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { faPen, faTrash } from '@fortawesome/free-solid-svg-icons'; +import { faPen, faTrash, faTimes } from '@fortawesome/free-solid-svg-icons'; +import { PhotoshopPicker } from 'react-color'; import HeadTag from '../../components/HeadTag'; +import Modal from '../../components/Modal'; import redirect from '../../utils/redirect'; +import htmlParser from 'html-react-parser'; +import Loader from '../../components/Loader'; import useAPI from '../../hooks/useAPI'; +import api from '../../utils/api'; import '../../public/css/pages/admin.css'; +const defaultCategoryState = { name: "", color: "#ffffff" }; + +const AddEditCategory = (props) => { + + const [inputState, setInputState] = useState(props.defaultInputState); + const [message, setMessage] = useState(""); + const [isLoading, setIsLoading] = useState(false); + + const handleChange = (event, isTypeCheck = false) => { + const inputStateNew = { ...inputState }; + inputStateNew[event.target.name] = (event.target.files != undefined) ? event.target.files[0] : (isTypeCheck) ? event.target.checked : event.target.value; + setInputState(inputStateNew); + } + + const apiCallCategory = () => { + if (props.isEditing) return api.put(`/admin/categories/${inputState.id}`, { name: inputState.name, color: inputState.color }, { headers: { 'Authorization': props.user.token } }); + return api.post('/admin/categories', inputState, { headers: { 'Authorization': props.user.token } }); + } + + const handleSubmit = (event) => { + event.preventDefault(); + setIsLoading(true); + apiCallCategory() + .then(() => { + setIsLoading(false); + window.location.reload(true); + }) + .catch((error) => { + setMessage(`

Erreur: ${error.response.data.message}

`); + setIsLoading(false); + }); + } + + return ( +
+
+
+
+
+ + + +

{(props.isEditing) ? "Modifier la catégorie" : "Crée une nouvelle catégorie"}

+
+
+
+ +
+ +
+ + +
+ +
+ + handleChange({ target: { name: "color", value: color.hex } })} /> +
+ +
+ +
+ +
+ { + (isLoading) ? + + : + htmlParser(message) + } +
+
+
+
+ ); +} + const manageCategories = (props) => { - const [, categories] = useAPI('/categories'); + const [, categories] = useAPI('/categories'); + const [isOpen, setIsOpen] = useState(false); + const [isEditing, setIsEditing] = useState(false); + const [defaultInputState, setDefaultInputState] = useState(defaultCategoryState); + const toggleModal = () => setIsOpen(!isOpen); + + const handleRemoveCategory = async (categoryId) => { + try { + await api.delete(`/admin/categories/${categoryId}`, { headers: { 'Authorization': props.user.token } }); + window.location.reload(true); + } catch {} + } + + const handleEditCategory = (categoryInfo) => { + setDefaultInputState(categoryInfo); + setIsEditing(true); + toggleModal(); + } + if (!props.user.isAdmin && typeof window != 'undefined') { return redirect({}, '/404'); } @@ -20,52 +120,59 @@ const manageCategories = (props) => { -
-
-
-

Gérer les catégories

- -
-
-
-
-
- - - - - - - - - - - - - - {categories.map((category) => { - return ( - - - - - - - - + { + (isOpen) ? + + + + : +
+
+
+

Gérer les catégories

+ +
+
+
+
+
+
idnamecolorcreatedAtupdatedAtModifierSupprimer
{category.id}{category.name}{category.color}{date.format(new Date(category.createdAt), 'DD/MM/YYYY à HH:mm', true)}{date.format(new Date(category.updatedAt), 'DD/MM/YYYY à HH:mm', true)} - - - -
+ + + + + + + + + - ); - })} - -
idnamecolorcreatedAtupdatedAtModifierSupprimer
+ + + {categories.map((category) => { + return ( + + {category.id} + {category.name} + {category.color} + {date.format(new Date(category.createdAt), 'DD/MM/YYYY à HH:mm', true)} + {date.format(new Date(category.updatedAt), 'DD/MM/YYYY à HH:mm', true)} + handleEditCategory({ name: category.name, color: category.color, id: category.id })}> + + + handleRemoveCategory(category.id)}> + + + + ); + })} + + +
+
-
- + } ); }