diff --git a/src/app/etage/AddEtageComponent.jsx b/src/app/etage/AddEtageComponent.jsx
index d84ae41ffbd070751b3decbd867a59fd8fd87ee1..17e46b843081b8f393bfe43dafda977e01f81b3f 100644
--- a/src/app/etage/AddEtageComponent.jsx
+++ b/src/app/etage/AddEtageComponent.jsx
@@ -2,18 +2,20 @@
import Loader from '@/components/Loader/Loader'
import React, { useState, useRef } from 'react'
import fetchRequest from '../lib/fetchRequest'
+import { useNotification } from '@/context/NotificationContext'
+
const AddEtageComponent = ({ etagesState })=> {
const [ numeroEtage, setNumeroEtage ] = useState("")
const [isLoading, setIsLoading] = useState(false)
- const [errorMessage, setErrorMessage] = useState(null)
const inputRef = useRef(null)
+ const { toggleNotification } = useNotification()
+
const handleNewEtage = (e) => {
- setErrorMessage(null)
setNumeroEtage(e.target.value)
}
@@ -28,12 +30,25 @@ const AddEtageComponent = ({ etagesState })=> {
inputRef.current.value = ""
console.log(data)
etagesState((prevEtagesState) => [...prevEtagesState, data]);
+ toggleNotification({
+ type: "success",
+ message: "L'étage a été créer avec succès.",
+ visible: true,
+ })
} else {
setIsLoading(false)
if(errors.type == "ValidationError")
- {setErrorMessage(errors.detail.numero)}
+ toggleNotification({
+ type: "warning",
+ message: "Le numéro détage déja existe.",
+ visible: true,
+ })
else{
- setErrorMessage(errorMessage.type)
+ toggleNotification({
+ type: "error",
+ message: "Une erreur s'est produite lors de la création de la zone.",
+ visible: true,
+ })
}
console.log(errors)
}
@@ -49,7 +64,6 @@ const AddEtageComponent = ({ etagesState })=> {
- {errorMessage && {errorMessage}}
)
diff --git a/src/app/etage/page.jsx b/src/app/etage/page.jsx
index 5177625933b1d8af927834ac9068aa67da4c722f..94f79ae67d15916803b07c83badbdb8132e82404 100644
--- a/src/app/etage/page.jsx
+++ b/src/app/etage/page.jsx
@@ -4,12 +4,20 @@ import AddEtageComponent from './AddEtageComponent'
import fetchRequest from '../lib/fetchRequest'
import { useState, useEffect } from 'react';
import Loader from '@/components/Loader/Loader'
+import { useNotification } from '@/context/NotificationContext'
+import ConfirmationModal from "@/app/ui/ConfirmationModal";
+
const Etage = ()=> {
const [etages, setEtages] = useState([])
const [ isLoadingData, setIsLoadingData ] = useState(true)
+ const { toggleNotification } = useNotification()
+ const [isModalOpen, setModalOpen] = useState(false);
+ const [etageToDelete, setEtageToDelete] = useState(null);
+
+
// Fetch data from external API
useEffect(() => {
const getAllEtages = async () => {
@@ -39,11 +47,38 @@ const Etage = ()=> {
console.log(etages)
console.log("etage: ", etage)
setEtages((prevEtages) => prevEtages.filter((e) => e.id !== etage.id));
+ toggleNotification({
+ type: "success",
+ message: "L'étage a été supprimer avec succès.",
+ visible: true,
+ })
+ }else{
+ toggleNotification({
+ type: "error",
+ message: "Une erreur s'est produite lors de la suppression de l'étage.",
+ visible: true,
+ })
}
}catch(error){
- console.log(error)
+ toggleNotification({
+ type: "error",
+ message: "Internal Server Error",
+ visible: true,
+ })
}
}
+
+ const handleDeleteClick = (etage) => {
+ setEtageToDelete(etage);
+ setModalOpen(true);
+ }
+
+ const handleConfirmDelete = () => {
+ handleDeleteEtage(etageToDelete);
+ setModalOpen(false);
+ setProjectToDelete(null);
+ };
+
return(
@@ -56,7 +91,7 @@ const Etage = ()=> {
(
Etage numéro: {etage.numero}
- {handleDeleteEtage(etage)}}>
+
setModalOpen(false)}
+ onConfirm={handleConfirmDelete}
+ message={`Êtes-vous sûr de vouloir supprimer l'étage numéro "${etageToDelete?.numero}"?`}
+ />
)
diff --git a/src/app/zone/CreateNewZone.jsx b/src/app/zone/CreateNewZone.jsx
index cdfb8cb47bc60185bfd6a5f51a28aac26f481075..d02c3f50d56ceba253747f29fd72886305f1829e 100644
--- a/src/app/zone/CreateNewZone.jsx
+++ b/src/app/zone/CreateNewZone.jsx
@@ -3,54 +3,56 @@ import React, { useState, useEffect, useRef } from 'react'
import fetchRequest from '../lib/fetchRequest'
import Loader from '@/components/Loader/Loader'
import { Island_Moments } from 'next/font/google'
+import { useNotification } from '@/context/NotificationContext'
-const CreateNewZone = () => {
- const [etages, setEtages] = useState([])
+
+const CreateNewZone = ({ zoneState, etages }) => {
const [error, setError] = useState(null)
- const [isLoadingEtages, setIsLoadingEtages] = useState(true)
const [isLoadingAction, setIsLoadingAction] = useState(false)
- const [nomZone, setNomZone] = useState("")
+ const [nomZone, setNomZone] = useState(null)
const [selectedEtage, setSelectedEtage] = useState(null)
const inputRef = useRef(null)
const selectRef = useRef(null)
- useEffect(() => {
- const getAllEtages = async () => {
- try{
- const {isSuccess, errors, data} = await fetchRequest('/zoaning/etages/', {method: 'GET'})
- setIsLoadingEtages(false)
- if(isSuccess){
- setEtages(data)
- }else{
- setEtages([])
- }
- }catch(error){
- setIsLoadingEtages(false)
- console.log(error)
- }
- }
- getAllEtages()
- }, [])
+ const { toggleNotification } = useNotification()
+
const handleSubmit = async (event) => {
event.preventDefault()
- isLoadingAction(true)
- const { data, errors, isSuccess } = await fetchRequest("/zoning/zones/", {
+ setIsLoadingAction(true)
+ const { data, errors, isSuccess } = await fetchRequest("/zoaning/zones/", {
method: "POST",
- body: JSON.stringify({ name: nomZone })
+ body: JSON.stringify({ nom: nomZone, id_etage: selectedEtage })
})
if (isSuccess) {
- isLoadingAction(false)
- appendPrivilege(data)
+ setIsLoadingAction(false)
+ zoneState((prevZoneValue) => [...prevZoneValue, {...data, id_etage: etages.find(etage => etage.id === data.id_etage)}]);
inputRef.current.value = ""
- setPrivilegeName("")
+ selectRef.current.value = ""
+ setNomZone(null)
+ setSelectedEtage(null)
+ toggleNotification({
+ visible: true,
+ message: "La zone a été créer avec succès.",
+ type: "success"
+ })
} else {
- isLoadingAction(false)
+ setIsLoadingAction(false)
if (errors.type === "ValidationError") {
- if (errors.detail.name) {
- setError("Le privilège existe déjà")
+ if (errors.detail.non_field_errors) {
+ toggleNotification({
+ type: "warning",
+ message: "Le nom de la zone saisie existe déjà dans l'étage sélectionné.",
+ visible: true,
+ })
}
+ }else{
+ toggleNotification({
+ type: "error",
+ message: "Une erreur s'est produite lors de la création de la zone.",
+ visible: true,
+ })
}
console.log(errors)
}
@@ -67,6 +69,9 @@ const CreateNewZone = () => {
setSelectedEtage(event.target.value)
}
+ console.log(selectedEtage)
+ console.log(nomZone)
+
return(
@@ -79,7 +84,7 @@ const CreateNewZone = () => {
-
-
diff --git a/src/app/zone/RowZone.jsx b/src/app/zone/RowZone.jsx
index 1d71ca2b41bd1fb68e5dda4303226ade197b38c9..5ef81721048e4eb4c8157e7519f79fed7e2cef88 100644
--- a/src/app/zone/RowZone.jsx
+++ b/src/app/zone/RowZone.jsx
@@ -1,47 +1,213 @@
"use client"
-import React from 'react'
+import React, { useState, useEffect, useRef } from 'react';
import fetchRequest from '../lib/fetchRequest'
-import { useState, useEffect } from 'react';
import Loader from '@/components/Loader/Loader'
-import CreateNewZone from './CreateNewZone'
import DeleteIcon from "@/static/image/svg/delete.svg"
import EditIcon from "@/static/image/svg/edit.svg"
import CancelIcon from "@/static/image/svg/cancel.svg"
import CheckIcon from "@/static/image/svg/check.svg"
+import { useNotification } from '@/context/NotificationContext'
+import ConfirmationModal from "@/app/ui/ConfirmationModal";
-const RowZone = ({ id, nom, etage }) => {
+
+
+const RowZone = ({ id, nom, etage, zonesState, etages }) => {
+ //states
+ const [isUpdating, setIsUpdating] = useState(false)
+ const [zoneName, setZoneName] = useState(nom)
+ const [selectedEtage, setSelectedEtage] = useState(etage)
+ const [loadingStatus, setLoadingStatus] = useState(false)
+ const [isModalOpen, setModalOpen] = useState(false);
+ const { toggleNotification } = useNotification()
+ //refs
+ const inputRef = useRef(null)
+ const selectRef = useRef(null)
+ const rowRef = useRef(null)
+
+ //Logic
+ useEffect(() => {
+ setZoneName(nom)
+ setSelectedEtage(etage?.id)
+ selectRef.current.value = etage?.id
+ inputRef.current.value = nom
+ }, [nom, etage])
+
+ const handleUpdateZone = async () => {
+ setLoadingStatus(true)
+ const { isSuccess, errors, data, status } = await fetchRequest(`/zoaning/zones/${id}/`, {
+ method: "PATCH",
+ body: JSON.stringify({ nom: zoneName, id_etage: selectedEtage })
+ })
+ setLoadingStatus(false)
+ if (isSuccess) {
+ console.log(data.data)
+ zonesState((prevZonesValue) => prevZonesValue.map( (element) => element.id === id ? {...data.data, id_etage: etages.find(etage => etage.id === data.data.id_etage)} : element ))
+ setIsUpdating(false)
+ toggleNotification({
+ visible: true,
+ message: "La zone a été modifiée avec succès.",
+ type: "success"
+ })
+ } else {
+ if (errors.type === "ValidationError") {
+ if (errors.detail.name) {
+ toggleNotification({
+ type: "warning",
+ message: "Le nom de la zone existe déjà",
+ visible: true,
+ })
+ }else if (errors.detail.non_field_errors) {
+ toggleNotification({
+ type: "warning",
+ message: "Le nom de la zone saisie existe déjà dans l'étage sélectionné.",
+ visible: true,
+ })
+ }
+ else {
+ toggleNotification({
+ visible: true,
+ message: "Erreur de validation de la zone",
+ type: "warning"
+ })
+ }
+ } else if (status === 404) {
+ toggleNotification({
+ visible: true,
+ message: "La zone n'a pas été trouvé",
+ type: "warning"
+ })
+ } else {
+ toggleNotification({
+ visible: true,
+ message: "Internal Server Error",
+ type: "error"
+ })
+ }
+ console.log(errors)
+ }
+
+ }
+
+ const handleDelete = async () => {
+ const { isSuccess, errors, status } = await fetchRequest(`/zoaning/zones/${id}/`, { method: "DELETE" })
+ if (isSuccess) {
+ zonesState((prevZonesState) => prevZonesState.filter((element) => element.id !== id))
+ toggleNotification({
+ visible: true,
+ message: "La zone a été supprimée avec succès",
+ type: "success"
+ })
+ } else if (status == 404) {
+ toggleNotification({
+ visible: true,
+ message: "La zone n'a pas été trouvé",
+ type: "warning"
+ })
+ } else {
+ console.log(errors)
+ toggleNotification({
+ visible: true,
+ message: "Internal Server Error",
+ type: "error"
+ })
+ }
+ }
+
+ const cancelUpdate = () => {
+ setIsUpdating(false)
+ setZoneName(nom)
+ setSelectedEtage(etage.id)
+ selectRef.current.value = etage.id
+ inputRef.current.value = nom
+ }
+
+ const handleUpdateBlur = (event) => {
+ const eventTarget = event.target
+ let isInsideRowRef = false;
+ let element = eventTarget;
+ while (element !== null) {
+ if (element === rowRef.current) {
+ isInsideRowRef = true;
+ break;
+ }
+ if (element.parentElement === null) {
+ isInsideRowRef = false;
+ break;
+ }
+ element = element.parentElement;
+ }
+ if (!isInsideRowRef && element?.classList.contains("zoneRowSVG")) return;
+ if (!isInsideRowRef) {
+ cancelUpdate();
+ document.removeEventListener("click", handleUpdateBlur);
+ }
+ }
+
+ useEffect(() => {
+ if (isUpdating && inputRef?.current && selectRef?.current) {
+ inputRef.current.focus()
+ selectRef.current.focus()
+ document.addEventListener("click", handleUpdateBlur)
+ }
+ return () => {
+ document.removeEventListener("click", handleUpdateBlur)
+ }
+ }, [isUpdating])
+
+ const handleDeleteClick = () => {
+ setModalOpen(true);
+ }
+
+ const handleConfirmDelete = () => {
+ handleDelete();
+ setModalOpen(false);
+ };
+
return(
-
+
|
-
+ setZoneName(event.target.value)} defaultValue={nom} type='text' className='disabled:bg-white border-0 rounded-md px-2 enabled:drop-shadow border-none enabled:bg-gray-100 duration-100 h-10 outline-none' />
|
-
-
-
-
-
+ setSelectedEtage(event.target.value)} name="listEtage" id="listEtage" className="disabled:bg-white border-0 rounded-md px-2 enabled:drop-shadow border-none enabled:bg-gray-100 duration-100 h-10 outline-none">
+ {(etages && etages?.length) &&
+ etages.map((element,index) => (
+
+ ))
+ }
|
-
-
-
+ {!isUpdating
+ ?
+ { setIsUpdating(true) }} className="ml-2 h-9 w-10 flex items-center disabled:cursor-not-allowed justify-center bg-blue-500 rounded-md hover:bg-white border-2 border-blue-500 duration-300 group">
+
-
-
+
+
-
-
-
+ :
+
+ {!loadingStatus
+ ?
+ : }
-
-
+
+
-
+
+ }
|
+ setModalOpen(false)}
+ onConfirm={handleConfirmDelete}
+ message={`Êtes-vous sûr de vouloir supprimer la zone "${nom}"?`}
+ />
)
}
diff --git a/src/app/zone/page.jsx b/src/app/zone/page.jsx
index a1c067effa3ea3e661e1e37ec94322ca0c992fd8..5fc1e535eacee408e3fa04256cdaea7b1ce58138 100644
--- a/src/app/zone/page.jsx
+++ b/src/app/zone/page.jsx
@@ -8,54 +8,77 @@ import DeleteIcon from "@/static/image/svg/delete.svg"
import EditIcon from "@/static/image/svg/edit.svg"
import CancelIcon from "@/static/image/svg/cancel.svg"
import CheckIcon from "@/static/image/svg/check.svg"
+import { isArray } from '../lib/TypesHelper'
import RowZone from './RowZone'
const Zone = ()=> {
- const [zones, setZones] = useState([])
+ const [ zones, setZones ] = useState([])
const [ isLoadingData, setIsLoadingData ] = useState(true)
+ const [etages, setEtages] = useState([])
+
+
// Fetch data from external API
useEffect(() => {
const getAllZones = async () => {
try{
const {isSuccess, errors, data} = await fetchRequest('/zoaning/zones/', {method: 'GET'})
- setIsLoadingData(false)
if(isSuccess){
setZones(data)
}else{
setZones([])
}
}catch(error){
- setIsLoadingData(false)
+ console.log(error)
+ }
+ }
+ const getAllEtages = async () => {
+ try{
+ const {isSuccess, errors, data} = await fetchRequest('/zoaning/etages/', {method: 'GET'})
+ if(isSuccess){
+ setEtages(data)
+ }else{
+ setEtages([])
+ }
+ }catch(error){
console.log(error)
}
}
getAllZones()
+ getAllEtages()
+ setIsLoadingData(false)
}, [])
+
+ console.log(zones)
return(
-
-
List des Zones
- {zones ?
-
-
Pas encore des habilitations
-
- :
-
-
-
- | Zone |
- Etage |
- Action |
-
- {zones.map((element) => {
- return
- })}
-
-
- }
+ {!isLoadingData ?
+ <>
+
+
List des Zones
+ {isArray(zones) && zones?.length !== 0 && isArray(etages) && etages?.length !== 0 ?
+
+
+
+ | Zone |
+ Etage |
+ Action |
+
+ {zones?.map((element) => {
+ return
+ })}
+
+
+ :
+
+
Pas encore des habilitations
+
}
+ >
+ :
+
+ }