-
}
@@ -266,7 +274,7 @@ const Reservation = () => {
}
{floors.filter((element) => concernedFloors.includes(element.id)).length === 0
&&
-
Un exemple d'un message à l'utilisateur
+
Vous êtes en télétravail aujourd'hui.
}
diff --git a/src/app/(dashboard)/place/CreateNewPlace.jsx b/src/app/(dashboard)/place/CreateNewPlace.jsx
deleted file mode 100644
index 0d9a017202afd44ad8b0a253e31d899393c6fe22..0000000000000000000000000000000000000000
--- a/src/app/(dashboard)/place/CreateNewPlace.jsx
+++ /dev/null
@@ -1,108 +0,0 @@
-"use client"
-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 CreateNewPlace = ({ placesState, tables }) => {
- const [error, setError] = useState(null)
- const [isLoadingAction, setIsLoadingAction] = useState(false)
- const [numPlace, setNumPlace] = useState(null)
- const [selectedTable, setSelectedTable] = useState(null)
-
- const inputRef = useRef(null)
- const selectRef = useRef(null)
-
- const { toggleNotification } = useNotification()
-
-
- const handleSubmit = async (event) => {
- event.preventDefault()
- setIsLoadingAction(true)
- const { data, errors, isSuccess } = await fetchRequest("/zoaning/places/", {
- method: "POST",
- body: JSON.stringify({ numero: numPlace, id_table: selectedTable })
- })
- if (isSuccess) {
- setIsLoadingAction(false)
- placesState((prevPlaceState) => [...prevPlaceState, { ...data, id_table: tables.find(table => table.id === data.id_table) }]);
- inputRef.current.value = ""
- selectRef.current.value = ""
- setNumPlace(null)
- setSelectedTable(null)
- toggleNotification({
- visible: true,
- message: "La table a été créer avec succès.",
- type: "success"
- })
- } else {
- setIsLoadingAction(false)
- if (errors.type === "ValidationError") {
- if (errors.detail.non_field_errors) {
- toggleNotification({
- type: "warning",
- message: "Le numéro de la table saisie déjà existe.",
- visible: true,
- })
- }
- } else {
- toggleNotification({
- type: "error",
- message: "Une erreur s'est produite lors de la création de la table.",
- visible: true,
- })
- }
- console.log(errors)
- }
- }
-
- // Handle the name of zone change
- const handleChangeZone = (event) => {
- setError("")
- setNumPlace(event.target.value)
- }
-
- const handleChangeEtage = (event) => {
- setError("")
- setSelectedTable(event.target.value)
- }
-
- console.log(selectedTable)
- console.log(numPlace)
-
-
-
- return (
-
- )
-}
-
-
-export default CreateNewPlace
\ No newline at end of file
diff --git a/src/app/(dashboard)/place/RowPlace.jsx b/src/app/(dashboard)/place/RowPlace.jsx
index 3d22e4814ab1768ec4a874643ae45b3ce45d4ff8..32ffc3f7d85b462114f5dbfa8554c60a6f2b4479 100644
--- a/src/app/(dashboard)/place/RowPlace.jsx
+++ b/src/app/(dashboard)/place/RowPlace.jsx
@@ -12,7 +12,8 @@ import ConfirmationModal from "@/app/ui/ConfirmationModal";
-const RowPlace = ({ id, numero, table, placesState, tables }) => {
+const RowPlace = ({ id, numero, table, placesState, tables, filteredPlacesState }) => {
+ console.log(table)
//states
const [isUpdating, setIsUpdating] = useState(false)
const [numPlace, setNumPlace] = useState(numero)
@@ -41,7 +42,6 @@ const RowPlace = ({ id, numero, table, placesState, tables }) => {
})
setLoadingStatus(false)
if (isSuccess) {
- console.log(data)
if (data.message === "NO_CHANGES") {
toggleNotification({
visible: true,
@@ -51,8 +51,8 @@ const RowPlace = ({ id, numero, table, placesState, tables }) => {
setIsUpdating(false)
return
}
- console.log(data.data)
placesState((prevPlacesState) => prevPlacesState.map((element) => element.id === id ? { ...data.data, id_table: tables.find(table => table.id === data.data.id_table) } : element))
+ filteredPlacesState((prevPlacesState) => prevPlacesState.map((element) => element.id === id ? { ...data.data, id_table: tables.find(table => table.id === data.data.id_table) } : element))
setIsUpdating(false)
toggleNotification({
visible: true,
@@ -96,13 +96,14 @@ const RowPlace = ({ id, numero, table, placesState, tables }) => {
}
console.log(errors)
}
-
+
}
const handleDelete = async () => {
const { isSuccess, errors, status } = await fetchRequest(`/zoaning/places/${id}/`, { method: "DELETE" })
if (isSuccess) {
placesState((prevPlacesState) => prevPlacesState.filter((element) => element.id !== id))
+ filteredPlacesState((prevPlacesState) => prevPlacesState.filter((element) => element.id !== id))
toggleNotification({
visible: true,
message: "La place a été supprimée avec succès",
@@ -179,12 +180,12 @@ const RowPlace = ({ id, numero, table, placesState, tables }) => {
setNumPlace(event.target.value)} defaultValue={numero} 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' />
|
-
+ |
setSelectedTable(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">
{(tables && tables?.length) &&
tables.map((element, index) => (
))
}
diff --git a/src/app/(dashboard)/place/page.jsx b/src/app/(dashboard)/place/page.jsx
index 074d6e89fd48c804b18b38b769d1c55630e3e187..68f65d6352d6bc002d969f4f964e7c24536c3636 100644
--- a/src/app/(dashboard)/place/page.jsx
+++ b/src/app/(dashboard)/place/page.jsx
@@ -1,42 +1,93 @@
"use client"
import React from 'react'
import fetchRequest from '../../lib/fetchRequest'
-import { useState, useEffect } from 'react';
+import { useState, useEffect, useRef } from 'react';
import Loader from '@/components/Loader/Loader'
-import CreateNewPlace from './CreateNewPlace'
import { isArray } from '../../lib/TypesHelper'
import RowPlace from './RowPlace'
import PlaceIcon from "@/static/image/svg/place.svg"
+import { useNotification } from '@/context/NotificationContext'
+
const Place = () => {
const [places, setPlaces] = useState([])
const [isLoadingData, setIsLoadingData] = useState(true)
const [tables, setTables] = useState([])
+ const [etages, setEtages] = useState([])
+ const [zones, setZones] = useState([])
+
+ const [error, setError] = useState(null)
+ const [isLoadingAction, setIsLoadingAction] = useState(false)
+ const [nbrPlacesToCreate, setNbrPlacesToCreate] = useState(null)
+ const [ selectedTable, setSelectedTable ] = useState(null)
+ const [ selectedEtage, setSelectedEtage ] = useState(null)
+ const [ selectedZone, setSelectedZone ] = useState(null)
+ const [ filteredPlaces, setFilteredPlaces ] = useState([])
+
+ const { toggleNotification } = useNotification()
+
+
-
- useEffect(() => {
- const fetchIP = async () => {
- try {
- const response = await fetch("https://api.ipify.org?format=json")
- const data = await response.json()
- console.log(data)
- } catch (error) {
- console.log(error)
- }
- }
- fetchIP()
- }, [])
// Fetch data from external API
useEffect(() => {
+ function extractFilters(data) {
+ let etagesMap = {};
+ let zonesMap = {};
+ let tables = [];
+
+ data.forEach(item => {
+ let etageId = item.id_zone.id_etage.id;
+ let etageNum = item.id_zone.id_etage.numero;
+ let zoneId = item.id_zone.id;
+ let zoneNom = item.id_zone.nom;
+ let tableId = item.id;
+ let tableNum = item.numero;
+
+ // Add etage to etagesMap with full details
+ if (!etagesMap[etageId]) {
+ etagesMap[etageId] = { id: etageId, numero: etageNum, zones: [] };
+ }
+
+ // Add zone to zonesMap with full details
+ if (!zonesMap[zoneId]) {
+ zonesMap[zoneId] = { id: zoneId, nom: zoneNom, etage: { id: etageId, numero: etageNum }, tables: [] };
+ }
+
+ // Add table to tables array with full details
+ tables.push({ id: tableId, numero: tableNum, zone: { id: zoneId, nom: zoneNom }, etage: { id: etageId, numero: etageNum } });
+
+ // Link zones to etages
+ if (!etagesMap[etageId].zones.some(zone => zone.id === zoneId)) {
+ etagesMap[etageId].zones.push(zonesMap[zoneId]);
+ }
+
+ // Link tables to zones
+ if (!zonesMap[zoneId].tables.some(table => table.id === tableId)) {
+ zonesMap[zoneId].tables.push({ id: tableId, numero: tableNum });
+ }
+ });
+
+ // Convert etagesMap and zonesMap to arrays
+ let etages = Object.values(etagesMap);
+ let zones = Object.values(zonesMap);
+
+ return { etages, zones, tables };
+ }
+
const getAllTables = async () => {
try {
const { isSuccess, errors, data } = await fetchRequest('/zoaning/tables/', { method: 'GET' })
if (isSuccess) {
- setTables(data)
+ const { etages, zones, tables } = extractFilters(data);
+ setTables(tables)
+ setEtages(etages)
+ setZones(zones)
} else {
setTables([])
+ setEtages([])
+ setZones([])
}
} catch (error) {
console.log(error)
@@ -47,8 +98,10 @@ const Place = () => {
const { isSuccess, errors, data } = await fetchRequest('/zoaning/places/', { method: 'GET' })
if (isSuccess) {
setPlaces(data)
+ setFilteredPlaces(data)
} else {
setPlaces([])
+ setFilteredPlaces([])
}
} catch (error) {
console.log(error)
@@ -64,26 +117,213 @@ const Place = () => {
const numero = e.target.value
try {
const { isSuccess, errors, data } = await fetchRequest(`/zoaning/search/place/${numero}`, { method: 'GET' })
- console.log(data)
if (isSuccess) {
setPlaces(data)
+ setFilteredPlaces(data)
} else {
setPlaces([])
+ setFilteredPlaces([])
}
} catch (error) {
console.log(error)
}
}
+
+ // create component files
+ const handleSubmit = async (event) => {
+ event.preventDefault()
+ setIsLoadingAction(true)
+ const { data, errors, isSuccess } = await fetchRequest("/zoaning/places/", {
+ method: "POST",
+ body: JSON.stringify({ nbrPlaces: nbrPlacesToCreate, id_table: selectedTable.id })
+ })
+ if (isSuccess) {
+ setIsLoadingAction(false)
+ setPlaces(prevPlaceState => [
+ ...prevPlaceState,
+ ...data.map(place => {
+ const foundTable = tables.find(table => table.id == place.id_table);
+ return {
+ ...place,
+ id_table: {
+ ...place.id_table,
+ id_zone: { id: foundTable.zone.id, nom: foundTable.zone.nom, id_etage: { id: foundTable.etage.id, numero: foundTable.etage.numero } },
+ id: foundTable.id,
+ numero: foundTable.numero
+ }
+ };
+ })
+ ]);
+ setFilteredPlaces(prevPlaceState => [
+ ...prevPlaceState,
+ ...data.map(place => {
+ const foundTable = tables.find(table => table.id == place.id_table);
+ return {
+ ...place,
+ id_table: {
+ ...place.id_table,
+ id_zone: { id: foundTable.zone.id, nom: foundTable.zone.nom, id_etage: { id: foundTable.etage.id, numero: foundTable.etage.numero } },
+ id: foundTable.id,
+ numero: foundTable.numero
+ }
+ };
+ })
+ ]);
+ setNbrPlacesToCreate(null)
+ setSelectedTable(null)
+ setSelectedEtage(null)
+ setSelectedZone(null)
+ toggleNotification({
+ visible: true,
+ message: "La table a été créer avec succès.",
+ type: "success"
+ })
+ } else {
+ setIsLoadingAction(false)
+ if (errors.type === "ValidationError") {
+ if (errors.detail.non_field_errors) {
+ toggleNotification({
+ type: "warning",
+ message: "Le numéro de la table saisie déjà existe.",
+ visible: true,
+ })
+ }
+ } else {
+ toggleNotification({
+ type: "error",
+ message: "Une erreur s'est produite lors de la création de la table.",
+ visible: true,
+ })
+ }
+ console.log(errors)
+ }
+ }
+
+ // Handle the name of zone change
+ const handleEtageSelection = (event) => {
+ const etageId = event.target.value
+ setFilteredPlaces(places.filter(place => place.id_table.id_zone.id_etage.id == etageId))
+ if(selectedEtage != etageId){
+ const selectedEtage = etages.find(etage => etage.id == etageId)
+ setSelectedEtage(selectedEtage)
+ setZones(selectedEtage.zones)
+ // Extract and format tables from the selected étage's zones
+ const updatedTables = selectedEtage.zones.flatMap(zone =>
+ zone.tables.map(table => ({
+ ...table,
+ zone: {
+ id: zone.id,
+ nom: zone.nom
+ },
+ etage: {
+ id: selectedEtage.id,
+ numero: selectedEtage.numero
+ }
+ }))
+ );
+ setTables(updatedTables)
+ setSelectedZone(null)
+ setSelectedTable(null)
+ }
+ }
+
+ const handleZoneSelection = (event) => {
+ const zoneId = event.target.value
+ setFilteredPlaces(places.filter(place => place.id_table.id_zone.id == zoneId))
+ if(selectedZone != zoneId){
+ const refreshTables = selectedEtage.zones.flatMap(zone =>
+ zone.tables.map(table => ({
+ ...table,
+ zone: {
+ id: zone.id,
+ nom: zone.nom
+ },
+ etage: {
+ id: selectedEtage.id,
+ numero: selectedEtage.numero
+ }
+ }))
+ );
+ const concernedZone = zones.find(zone => zone.id == zoneId)
+ setSelectedZone(concernedZone)
+ const updatedTables = concernedZone.tables.map(table => {
+ return refreshTables.find(originalTable => originalTable.id === table.id);
+ });
+ setTables(updatedTables)
+ setSelectedTable(null)
+ }
+ }
+ const handleTableSelection = (event) => {
+ const tableId = event.target.value
+ setFilteredPlaces(places.filter(place => place.id_table.id == tableId))
+ if(selectedZone != tableId){
+ const selectedTable = tables.find(table => table.id == tableId)
+ setSelectedTable(selectedTable)
+ }
+ }
+
+ const handleNbrPlaceChange = (event) => {
+ const nbrPlace = event.target.value
+ setNbrPlacesToCreate(nbrPlace)
+ }
+
+
return (
-
+
{!isLoadingData ?
<>
-
-
- List des Places
+
+
+ Liste des Places
- {isArray(places) && places?.length !== 0 && isArray(tables) && tables?.length !== 0 ?
-
-
+ {isArray(filteredPlaces) && filteredPlaces?.length != 0 && isArray(tables) && tables?.length != 0 ?
+
+
| Place |
- Place-Zone-Etage |
+ Table-Zone-Etage |
Action |
- {places?.map((element) => {
- return
+ {filteredPlaces?.map((element) => {
+ return
})}
diff --git a/src/app/(dashboard)/planning/PlanningTable.jsx b/src/app/(dashboard)/planning/PlanningTable.jsx
index 2bf1d00afb49bded2d0cca9f20b9649fe0837e50..34228d79a8940601c5a65af20d0004f6c113bf71 100644
--- a/src/app/(dashboard)/planning/PlanningTable.jsx
+++ b/src/app/(dashboard)/planning/PlanningTable.jsx
@@ -2,14 +2,41 @@ import React, {useEffect, useState} from 'react';
import fetchRequest from "@/app/lib/fetchRequest";
import {useNotification} from "@/context/NotificationContext";
-const PlanningTable = ({ data, typePresences, onTypePresenceChange }) => {
+const PlanningTable = ({ data, typePresences, onTypePresenceChange, selectedProject }) => {
// fetch type presence
const [errors, setErrors] = useState();
const [loading, setLoading] = useState(false);
const {toggleNotification} = useNotification()
+ const [selectedPresence, setSelectedPresence] = useState('');
+
+ const handleRadioChange = (e) => {
+ const newPresence = e.target.value;
+ setSelectedPresence(newPresence);
+ data.forEach((row, rowIndex) => {
+ row.days.forEach((day, dayIndex) => {
+ onTypePresenceChange(rowIndex, dayIndex, newPresence);
+ });
+ });
+ };
return (
-
+
+
+ Réglez Tout sur :
+ {typePresences.map((typePresence) => (
+
+ ))}
+
diff --git a/src/app/(dashboard)/planning/page.jsx b/src/app/(dashboard)/planning/page.jsx
index b9bdd26c9aa3b09f68f10a4dbd2d9eb1391b6af0..f6dc6d33ac762cd5301da62de4c97a9ae1ac4785 100644
--- a/src/app/(dashboard)/planning/page.jsx
+++ b/src/app/(dashboard)/planning/page.jsx
@@ -9,11 +9,11 @@ import ConfirmationModal from "@/app/ui/ConfirmationModal";
const PlanningPage = () => {
const blankData = {
planning_data: [
- { week: 1, days: [{}, {}, {}, {}, {}] },
- { week: 2, days: [{}, {}, {}, {}, {}] },
- { week: 3, days: [{}, {}, {}, {}, {}] },
- { week: 4, days: [{}, {}, {}, {}, {}] },
- { week: 5, days: [{}, {}, {}, {}, {}] },
+ { week: 1, days: [{"id": 2, "nom": "Teletravail"}, {"id": 2, "nom": "Teletravail"}, {"id": 2, "nom": "Teletravail"}, {"id": 2, "nom": "Teletravail"}, {"id": 2, "nom": "Teletravail"}] },
+ { week: 2, days: [{"id": 2, "nom": "Teletravail"}, {"id": 2, "nom": "Teletravail"}, {"id": 2, "nom": "Teletravail"}, {"id": 2, "nom": "Teletravail"}, {"id": 2, "nom": "Teletravail"}] },
+ { week: 3, days: [{"id": 2, "nom": "Teletravail"}, {"id": 2, "nom": "Teletravail"}, {"id": 2, "nom": "Teletravail"}, {"id": 2, "nom": "Teletravail"}, {"id": 2, "nom": "Teletravail"}] },
+ { week: 4, days: [{"id": 2, "nom": "Teletravail"}, {"id": 2, "nom": "Teletravail"}, {"id": 2, "nom": "Teletravail"}, {"id": 2, "nom": "Teletravail"}, {"id": 2, "nom": "Teletravail"}] },
+ { week: 5, days: [{"id": 2, "nom": "Teletravail"}, {"id": 2, "nom": "Teletravail"}, {"id": 2, "nom": "Teletravail"}, {"id": 2, "nom": "Teletravail"}, {"id": 2, "nom": "Teletravail"}] },
]
}
const [projects, setProjects] = useState([]);
@@ -99,7 +99,17 @@ const PlanningPage = () => {
if (!selectedProject) {
toggleNotification({
visible: true,
- message: 'Please select a project',
+ message: 'Veuillez sélectionner un projet',
+ type: 'error'
+ });
+ return;
+ }
+ // verify if planing data has an empty value
+ const emptyValue = planningData.planning_data.some(week => week.days.some(day => day.nom === ''));
+ if (emptyValue) {
+ toggleNotification({
+ visible: true,
+ message: 'Veuillez remplir toutes les valeurs de planification',
type: 'error'
});
return;
@@ -115,7 +125,7 @@ const PlanningPage = () => {
if (isSuccess) {
toggleNotification({
visible: true,
- message: 'Planning data saved successfully',
+ message: 'Données de planification enregistrées avec succès',
type: 'success'
});
fetchPlanningData()
@@ -123,14 +133,12 @@ const PlanningPage = () => {
setErrors(errors);
toggleNotification({
visible: true,
- message: 'Failed to save planning data',
+ message: 'Échec de lenregistrement des données de planification',
type: 'error'
});
}
};
-
-
const handleUpdate = async () => {
setLoading(true);
const requestBody = {id_project: selectedProject, planning_data: planningData.planning_data};
@@ -142,14 +150,14 @@ const PlanningPage = () => {
if (isSuccess) {
toggleNotification({
visible: true,
- message: 'Planning data updated successfully',
+ message: 'Données de planification mises à jour avec succès',
type: 'success'
});
} else {
setErrors(errors);
toggleNotification({
visible: true,
- message: 'Failed to update planning data',
+ message: 'Échec de la mise à jour des données de planification',
type: 'error'
});
}
@@ -166,14 +174,14 @@ const PlanningPage = () => {
setPlanningData(blankData);
toggleNotification({
visible: true,
- message: 'Planning data deleted successfully',
+ message: 'Données de planification supprimées avec succès',
type: 'success'
});
} else {
setErrors(errors);
toggleNotification({
visible: true,
- message: 'Failed to delete planning data',
+ message: 'Échec de la suppression des données de planification',
type: 'error'
});
}
@@ -195,14 +203,14 @@ const PlanningPage = () => {
onChange={handleProjectChange}
className="mt-4 block w-full px-3 py-2 bg-white border border-gray-300 rounded-md"
>
-
+
{projects.map((project) => (
))}
-
+
+ onTypePresenceChange={handleTypePresenceChange} selectedProject={selectedProject} />
{/* crud buttons*/}
@@ -211,22 +219,22 @@ const PlanningPage = () => {
setSelectedProject('');
setPlanningData(blankData);
}}
- >Cancel
+ >Annuler
{planningData.id ?
<>
> :
+ >Enregistrer
}
@@ -234,7 +242,7 @@ const PlanningPage = () => {
isOpen={isModalOpen}
onClose={() => setModalOpen(false)}
onConfirm={handleConfirmDelete}
- message={`Are you sure you want to delete this planning data?`}
+ message={`Etes-vous sûr de vouloir supprimer ces données de planification ?`}
/>
);
diff --git a/src/app/(dashboard)/planning/type-presence/EntityForm.jsx b/src/app/(dashboard)/planning/type-presence/EntityForm.jsx
index 83f4dfcc51e1e13352713e98f6c86c8bddfa5b51..408e3a41c2afc4009945d83e6f1d7db4930c3f42 100644
--- a/src/app/(dashboard)/planning/type-presence/EntityForm.jsx
+++ b/src/app/(dashboard)/planning/type-presence/EntityForm.jsx
@@ -68,7 +68,7 @@ const EntityForm = ({ entity, id, onSaved, onCancel }) => {
className="px-3 py-2 bg-sushi-500 text-white rounded-md"
disabled={isLoading}
>
- {isLoading ? 'Saving...' : id ? 'Update' : 'Create'}
+ {isLoading ? 'Enregistrement...' : id ? 'Mettre à jour' : 'Créer'}
diff --git a/src/app/(dashboard)/planning/type-presence/EntityList.jsx b/src/app/(dashboard)/planning/type-presence/EntityList.jsx
index b632780ce6d3b0304c2130c3d68dd62e326d2044..d2f5d9e4b0f588a3eb15f1e4ce221f9ccf4b3d99 100644
--- a/src/app/(dashboard)/planning/type-presence/EntityList.jsx
+++ b/src/app/(dashboard)/planning/type-presence/EntityList.jsx
@@ -1,5 +1,7 @@
import React, { useState } from 'react';
import ConfirmationModal from '@/app/ui/ConfirmationModal';
+import EditIcon from "@/static/image/svg/edit.svg";
+import DeleteIcon from "@/static/image/svg/delete.svg";
const EntityList = ({ title, items, setState, handleDelete, handleEdit }) => {
const [isModalOpen, setModalOpen] = useState(false);
@@ -33,16 +35,16 @@ const EntityList = ({ title, items, setState, handleDelete, handleEdit }) => {
diff --git a/src/app/(dashboard)/planning/type-presence/page.jsx b/src/app/(dashboard)/planning/type-presence/page.jsx
index 697ba16b789a4a93049d0aafee35cbcd1d1cbb07..e3902baf61ab4678b7d1d1f0f060012078cd590d 100644
--- a/src/app/(dashboard)/planning/type-presence/page.jsx
+++ b/src/app/(dashboard)/planning/type-presence/page.jsx
@@ -39,7 +39,7 @@ const ManagePage = () => {
Gérer Les Entités
- Type Presence
+ Type de Presence
{
{privileges.map((element) => {
return
})}
- {privileges.map((element) => {
- return
- })}
- {privileges.map((element) => {
- return
- })}
- {privileges.map((element) => {
- return
- })}
- {privileges.map((element) => {
- return
- })}
- {privileges.map((element) => {
- return
- })}
- {privileges.map((element) => {
- return
- })}
-
- {privileges.map((element) => {
- return
- })}
- {privileges.map((element) => {
- return
- })}
- {privileges.map((element) => {
- return
- })}
- {privileges.map((element) => {
- return
- })}
-
}>}
diff --git a/src/app/(dashboard)/projects/ProjectForm.jsx b/src/app/(dashboard)/projects/ProjectForm.jsx
index 65c06c0ce5b3c5aeb31f07cbcbd7781393cba287..bb531d52e9639b8047f24d18afc63b4444fb5b18 100644
--- a/src/app/(dashboard)/projects/ProjectForm.jsx
+++ b/src/app/(dashboard)/projects/ProjectForm.jsx
@@ -87,7 +87,7 @@ const ProjectForm = ({ onAddProject, onEditProject, editingProject, setEditingPr
};
return (
-
@@ -175,7 +176,7 @@ const Projects = () => {
@@ -217,6 +218,8 @@ const Projects = () => {
onHandlePageUrl={handlePageChange}
/>
+
+
diff --git a/src/app/(dashboard)/reservation/PlaceUI.jsx b/src/app/(dashboard)/reservation/PlaceUI.jsx
index 976bc4b0d3b49a1853d56210c0c1ae126b4a174c..43d2f8f76985f016934e10178a36cc79c3f35f89 100644
--- a/src/app/(dashboard)/reservation/PlaceUI.jsx
+++ b/src/app/(dashboard)/reservation/PlaceUI.jsx
@@ -12,7 +12,6 @@ const PlaceUI = ({ id }) => {
const place = allPlaces?.find((place) => place.id === id)
const bookedPlace = bookedPlaces?.find((bookedPlace) => bookedPlace.id_place === id)
- console.log(hasPlace);
const handleBooking = (event) => {
event.stopPropagation()
if (hasPlace && hasPlace.presence) return;
diff --git a/src/app/(dashboard)/reservation/TableUI.jsx b/src/app/(dashboard)/reservation/TableUI.jsx
index 8c77ad5b0e81c6cc7e2c99b2e1b91b3ebeb66fe9..bf4e5e6a0d402f0cecc996a8b87ba7e30b0ac8d8 100644
--- a/src/app/(dashboard)/reservation/TableUI.jsx
+++ b/src/app/(dashboard)/reservation/TableUI.jsx
@@ -1,7 +1,7 @@
import React from 'react'
import PlaceUI from './PlaceUI';
-const TableUI = ({ id, numero, places }) => {
+const TableUI = ({ places }) => {
function groupConsecutive(arr) {
arr = arr.sort((a, b) => a.id - b.id)
diff --git a/src/app/(dashboard)/reservation/ZoneUI.jsx b/src/app/(dashboard)/reservation/ZoneUI.jsx
index 48ae7d19663b3c0b7c308a4271a2252e047b92c5..42538fde425c979c9be988919bbf6c3774c10398 100644
--- a/src/app/(dashboard)/reservation/ZoneUI.jsx
+++ b/src/app/(dashboard)/reservation/ZoneUI.jsx
@@ -3,9 +3,9 @@ import TableUI from './TableUI'
const ZoneUI = ({ id, tables, nom }) => {
return (
-
- {nom}
-
+
+ Zone {nom}
+
{tables.map((table) => {
return
})}
diff --git a/src/app/(dashboard)/reservation/page.jsx b/src/app/(dashboard)/reservation/page.jsx
index e899e4013740ae504b09becab751d6e3c1cc1b2e..e77c657132fece448ba7ce94ecd204fde17fb2ce 100644
--- a/src/app/(dashboard)/reservation/page.jsx
+++ b/src/app/(dashboard)/reservation/page.jsx
@@ -1,6 +1,6 @@
'use client'
-import React, { useEffect, useState, useMemo } from 'react'
+import React, { useEffect, useState, useMemo, useRef } from 'react'
import ZoneUI from './ZoneUI'
import fetchRequest from '@/app/lib/fetchRequest'
import Loader from '@/components/Loader/Loader'
@@ -12,7 +12,7 @@ import { decrypt } from '@/app/lib/session';
export const ReservationContext = React.createContext()
const Reservation = () => {
- const [isLoadingData, setIsLoadingData] = useState(false)
+ const [isLoadingData, setIsLoadingData] = useState(true)
const { toggleNotification } = useNotification()
const [date, setDate] = useState({ day: null, week: null })
const [isLoadingSelectsData, setIsLoadingSelectsData] = useState(true)
@@ -42,7 +42,7 @@ const Reservation = () => {
const processUserLocation = () => {
const companyLatitude = 36.8402141; // Example: Company's latitude
const companyLongitude = 10.2432573; // Example: Company's longitude
- const allowedRadius = 400; // Example: Radius in meters
+ const allowedRadius = 300; // Example: Radius in meters
function getDistanceFromLatLonInMeters(lat1, lon1, lat2, lon2) {
@@ -232,8 +232,7 @@ const Reservation = () => {
const handleChangeDate = (event) => {
if (event.target.value) {
const dateSelected = JSON.parse(event.target.value);
- console.log("weekMonthly", dateSelected.weekMonthly);
- console.log("day", dateSelected.day);
+
setDate({ day: dateSelected.day, week: dateSelected.weekMonthly, date: dateSelected.date })
}
else {
@@ -247,6 +246,13 @@ const Reservation = () => {
const allPlaces = projectsData?.map((project) => project.zones.map((zone) => zone.places.map((place) => ({ ...place, project_name: project.project_name, project_id: project.project_id })))).flat(2) || []
const hasPlace = bookedPlaces?.find((p) => p.id_user === authenticatedUserData?.sessionData?.user_id)
+ const dateRef = useRef(null)
+ useEffect(() => {
+ if (dateRef.current && currentDateData?.date) {
+ dateRef.current.value = JSON.stringify(currentDateData)
+ setDate({ day: currentDateData.day, week: currentDateData.weekMonthly, date: currentDateData.date })
+ }
+ }, [dateRef.current, currentDateData?.date])
if (isLoadingSelectsData)
return
@@ -262,14 +268,13 @@ const Reservation = () => {
return (
-
-
+ {(filteredDatesData && filteredDatesData.length) &&
{filteredDatesData.map((date, index) => (
))}
-
+ }
@@ -297,7 +302,7 @@ const Reservation = () => {
?
<>
- {(floors.filter((element) => concernedFloors.includes(element.id))?.length > 0 && hasPlace && currentDate && currentDate === date?.date) &&
+ {(floors.filter((element) => concernedFloors.includes(element.id))?.length > 0 && hasPlace && !hasPlace.presence && currentDate && currentDate === date?.date) && }
@@ -309,13 +314,13 @@ const Reservation = () => {
})}
})}
- {floors.filter((element) => concernedFloors.includes(element.id)).length === 0
+ {!isLoadingData && floors.filter((element) => concernedFloors.includes(element.id)).length === 0
&&
- Un exemple d'un message à l'utilisateur
+ Vous êtes en télétravail aujourd'hui.
}
-
- >
+ >
+
:
diff --git a/src/app/(dashboard)/role/CreateRoleForm.jsx b/src/app/(dashboard)/role/CreateRoleForm.jsx
index 223840e892de01ba2b72044e0f6fb5f0fd108897..3ba4a859863b9c1f5d662cd800fb10c3c48d5b10 100644
--- a/src/app/(dashboard)/role/CreateRoleForm.jsx
+++ b/src/app/(dashboard)/role/CreateRoleForm.jsx
@@ -135,7 +135,7 @@ const CreateRoleForm = ({ appendRole, setIsOpen }) => {
{!isLoading && "Créer" || }
- :
}
+ :
}
)
diff --git a/src/app/(dashboard)/role/UpdateRoleForm.jsx b/src/app/(dashboard)/role/UpdateRoleForm.jsx
index 685b2ede7813493c55a0491e79b97b190bd48887..4b35eadf0d90ee4e0aa60d40c983f0542eebfde3 100644
--- a/src/app/(dashboard)/role/UpdateRoleForm.jsx
+++ b/src/app/(dashboard)/role/UpdateRoleForm.jsx
@@ -134,7 +134,7 @@ const UpdateRoleForm = ({ setRoleToUpdate, setRoles, roles, privileges: rolePriv
{!loadingStatus && "Modifier" || }
- :
}
+ :
}
)
diff --git a/src/app/(dashboard)/table/CreateNewTable.jsx b/src/app/(dashboard)/table/CreateNewTable.jsx
deleted file mode 100644
index 50c0f90b4c82a71065008b09c2a6389c9ffb4cf3..0000000000000000000000000000000000000000
--- a/src/app/(dashboard)/table/CreateNewTable.jsx
+++ /dev/null
@@ -1,106 +0,0 @@
-"use client"
-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 CreateNewTable = ({ tablesState, zones }) => {
- const [error, setError] = useState(null)
- const [isLoadingAction, setIsLoadingAction] = useState(false)
- const [numeroTable, setNumeroTable] = useState(null)
- const [selectedZone, setSelectedZone] = useState(null)
-
- const inputRef = useRef(null)
- const selectRef = useRef(null)
-
- const { toggleNotification } = useNotification()
-
-
- const handleSubmit = async (event) => {
- event.preventDefault()
- setIsLoadingAction(true)
- const { data, errors, isSuccess } = await fetchRequest("/zoaning/tables/", {
- method: "POST",
- body: JSON.stringify({ numero: numeroTable, id_zone: selectedZone })
- })
- if (isSuccess) {
- setIsLoadingAction(false)
- tablesState((prevTableState) => [...prevTableState, { ...data, id_zone: zones.find(zone => zone.id === data.id_zone) }]);
- inputRef.current.value = ""
- selectRef.current.value = ""
- setNumeroTable(null)
- setSelectedZone(null)
- toggleNotification({
- visible: true,
- message: "La table a été créer avec succès.",
- type: "success"
- })
- } else {
- setIsLoadingAction(false)
- if (errors.type === "ValidationError") {
- if (errors.detail.non_field_errors) {
- toggleNotification({
- type: "warning",
- message: "Le numéro de la table saisie déjà existe.",
- visible: true,
- })
- }
- } else {
- toggleNotification({
- type: "error",
- message: "Une erreur s'est produite lors de la création de la table.",
- visible: true,
- })
- }
- console.log(errors)
- }
- }
-
- // Handle the name of zone change
- const handleChangeTable = (event) => {
- setError("")
- setNumeroTable(event.target.value)
- }
-
- const handleChangeZone = (event) => {
- setError("")
- setSelectedZone(event.target.value)
- }
-
-
-
-
- return (
-
- )
-}
-
-
-export default CreateNewTable
\ No newline at end of file
diff --git a/src/app/(dashboard)/table/RowTable.jsx b/src/app/(dashboard)/table/RowTable.jsx
index 7e16dd22846c0ee0572a6af8ee6f90572fbb3639..30acd78b8d16f9932f72a4027989d64e755541c3 100644
--- a/src/app/(dashboard)/table/RowTable.jsx
+++ b/src/app/(dashboard)/table/RowTable.jsx
@@ -12,7 +12,7 @@ import ConfirmationModal from "@/app/ui/ConfirmationModal";
-const RowZone = ({ id, numero, zone, tablesState, zones }) => {
+const RowZone = ({ id, numero, zone, tablesState, zones, filteredPlacesState }) => {
//states
const [isUpdating, setIsUpdating] = useState(false)
@@ -52,6 +52,7 @@ const RowZone = ({ id, numero, zone, tablesState, zones }) => {
return
}
tablesState((prevTableState) => prevTableState.map((element) => element.id === id ? { ...data.data, id_zone: zones.find(zone => zone.id === data.data.id_zone) } : element))
+ filteredPlacesState((prevTableState) => prevTableState.map((element) => element.id === id ? { ...data.data, id_zone: zones.find(zone => zone.id === data.data.id_zone) } : element))
setIsUpdating(false)
toggleNotification({
visible: true,
@@ -102,6 +103,7 @@ const RowZone = ({ id, numero, zone, tablesState, zones }) => {
const { isSuccess, errors, status } = await fetchRequest(`/zoaning/tables/${id}/`, { method: "DELETE" })
if (isSuccess) {
tablesState((prevTableState) => prevTableState.filter((element) => element.id !== id))
+ filteredPlacesState((prevTableState) => prevTableState.filter((element) => element.id !== id))
toggleNotification({
visible: true,
message: "La table a été supprimée avec succès",
@@ -178,7 +180,7 @@ const RowZone = ({ id, numero, zone, tablesState, zones }) => {
setTableNum(event.target.value)} defaultValue={numero} 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' />
|
-
+ |
setSelectedZone(event.target.value)} name="listZones" id="listZones" 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">
{(zones && zones?.length) &&
zones.map((element, index) => (
diff --git a/src/app/(dashboard)/table/page.jsx b/src/app/(dashboard)/table/page.jsx
index 7645a113b02c50544d0ece1a139f935b1fa26d60..fa644547ea4fb2f6e5c87d52ddcd228e33c1a010 100644
--- a/src/app/(dashboard)/table/page.jsx
+++ b/src/app/(dashboard)/table/page.jsx
@@ -1,29 +1,58 @@
"use client"
import React from 'react'
import fetchRequest from '../../lib/fetchRequest'
-import { useState, useEffect } from 'react';
+import { useState, useEffect, useRef } from 'react';
import Loader from '@/components/Loader/Loader'
-import CreateNewTable from './CreateNewTable'
import TableIcon from "@/static/image/svg/table.svg"
import { isArray } from '../../lib/TypesHelper'
import RowTable from './RowTable'
+import { useNotification } from '@/context/NotificationContext'
const Table = () => {
const [tables, setTables] = useState([])
const [isLoadingData, setIsLoadingData] = useState(true)
const [zones, setZones] = useState([])
+ const [etages, setEtages] = useState([])
+ const [error, setError] = useState(null)
+ const [isLoadingAction, setIsLoadingAction] = useState(false)
+ const [numeroTable, setNumeroTable] = useState(null)
+ const [selectedZone, setSelectedZone] = useState(null)
+ const [ selectedEtage, setSelectedEtage ] = useState(null)
+ const [ filteredTables, setFilteredTables ] = useState([])
+ const { toggleNotification } = useNotification()
// Fetch data from external API
useEffect(() => {
+
+ function extractAvailableEtagesWithZones(zones) {
+ const etagesMap = new Map();
+
+ zones.forEach(zone => {
+ const etage = zone.id_etage;
+ const etageKey = `${etage.id}-${etage.numero}`;
+
+ if (!etagesMap.has(etageKey)) {
+ etagesMap.set(etageKey, { ...etage, zones: [] });
+ }
+
+ etagesMap.get(etageKey).zones.push(zone);
+ });
+
+ return Array.from(etagesMap.values());
+ }
+
+
const getAllTables = async () => {
try {
const { isSuccess, errors, data } = await fetchRequest('/zoaning/tables/', { method: 'GET' })
if (isSuccess) {
setTables(data)
+ setFilteredTables(data)
} else {
setTables([])
+ setFilteredTables([])
}
} catch (error) {
console.log(error)
@@ -34,8 +63,10 @@ const Table = () => {
const { isSuccess, errors, data } = await fetchRequest('/zoaning/zones/', { method: 'GET' })
if (isSuccess) {
setZones(data)
+ setEtages(extractAvailableEtagesWithZones(data));
} else {
setZones([])
+ setEtages([])
}
} catch (error) {
console.log(error)
@@ -45,30 +76,144 @@ const Table = () => {
getAllZones()
setIsLoadingData(false)
}, [])
-
-
+ console.log("etages", etages)
+ console.log("zones", zones)
+ console.log("tables", tables)
const handleSearchingTable = async (e) => {
const numero = e.target.value
try {
const { isSuccess, errors, data } = await fetchRequest(`/zoaning/search/table/${numero}`, { method: 'GET' })
- console.log(data)
if (isSuccess) {
setTables(data)
+ setFilteredTables(data)
} else {
setTables([])
+ setFilteredTables([])
}
} catch (error) {
console.log(error)
}
}
+
+
+ // create new table section
+
+ const handleSubmit = async (event) => {
+ event.preventDefault()
+ setIsLoadingAction(true)
+ try{
+ const { data, errors, isSuccess } = await fetchRequest("/zoaning/tables/", {
+ method: "POST",
+ body: JSON.stringify({ numero: numeroTable, id_zone: selectedZone.id })
+ })
+ if (isSuccess) {
+ setIsLoadingAction(false)
+ setTables((prevTableState) => [...prevTableState, { ...data, id_zone: zones.find(zone => zone.id === data.id_zone) }]);
+ setFilteredTables((prevTableState) => [...prevTableState, { ...data, id_zone: zones.find(zone => zone.id === data.id_zone) }]);
+ setNumeroTable(null)
+ setSelectedZone(null)
+ setSelectedEtage(null)
+ toggleNotification({
+ visible: true,
+ message: "La table a été créer avec succès.",
+ type: "success"
+ })
+ } else {
+ setIsLoadingAction(false)
+ if (errors.type === "ValidationError") {
+ if (errors.detail.non_field_errors) {
+ toggleNotification({
+ type: "warning",
+ message: "Le numéro de la table saisie déjà existe.",
+ visible: true,
+ })
+ }
+ } else {
+ toggleNotification({
+ type: "error",
+ message: "Une erreur s'est produite lors de la création de la table.",
+ visible: true,
+ })
+ }
+ console.log(errors)
+ }
+ }catch(error){
+ console.log(error)
+ }
+ }
+
+
+ // Handle the name of table change
+ const handleEtageSelection = (event) => {
+ const etageId = event.target.value
+ setFilteredTables(tables.filter(table => table.id_zone.id_etage.id == etageId))
+ if(selectedEtage != etageId){
+ const selectedEtage = etages.find(etage => etage.id == etageId)
+ setSelectedEtage(selectedEtage)
+ setZones(selectedEtage.zones)
+ setSelectedZone(null)
+ }
+ }
+
+ // Handle the name of zone change
+ const handleZoneSelection = (event) => {
+ const zoneId = event.target.value
+ setFilteredTables(tables.filter(table => table.id_zone.id == zoneId))
+ if(selectedZone != zoneId){
+ const selectedZone = zones.find(zone => zone.id == zoneId)
+ setSelectedZone(selectedZone)
+ }
+ }
+
+
+ const handleTableNumero = (event) => {
+ const numeroTable = event.target.value
+ setNumeroTable(numeroTable)
+ }
+
return (
-
+
{!isLoadingData ?
<>
-
-
+
+
List des Tables
-
- {isArray(tables) && tables?.length !== 0 && isArray(zones) && zones?.length !== 0 ?
-
-
+ {isArray(filteredTables) && filteredTables?.length !== 0 && isArray(zones) && zones?.length !== 0 ?
+
+
| Table |
- Zone-Etage |
+ Zone-Etage |
Action |
- {tables?.map((element) => {
- return
+ {filteredTables?.map((element) => {
+ return
})}
diff --git a/src/app/(dashboard)/user/CreateUserForm.jsx b/src/app/(dashboard)/user/CreateUserForm.jsx
index 90b1799188babe16e5bd34edb82d23fff6f07fbd..bb631dd0b533b48e51dda133dccf833ff32dd125 100644
--- a/src/app/(dashboard)/user/CreateUserForm.jsx
+++ b/src/app/(dashboard)/user/CreateUserForm.jsx
@@ -4,8 +4,8 @@ import fetchRequest from '../../lib/fetchRequest'
import { useNotification } from '@/context/NotificationContext'
import CancelIcon from "@/static/image/svg/cancel.svg"
import { EMAIL_REGEX } from '../../lib/constants'
-
-
+import { removeWhiteSpace } from '@/app/lib/StringHelper'
+import Select from "react-select";
function generateRandomPassword() {
@@ -71,13 +71,19 @@ const CreateUserForm = ({ setIsOpen, appendUser }) => {
getRoles()
getProjects()
}, [])
+
+ const [errors, setErrors] = useState({ first_name: "", last_name: "", email: "", role: "" })
+ const [userData, setUserData] = useState({ email: "", password: generateRandomPassword(), first_name: "", last_name: "" })
const handleFieldChange = (event) => {
setUserData({ ...userData, [event.target.name]: event.target.value })
setErrors({ ...errors, [event.target.name]: "" })
}
- const [errors, setErrors] = useState({ first_name: "", last_name: "", email: "", role: "" })
- const [userData, setUserData] = useState({ email: "", password: generateRandomPassword(), first_name: "", last_name: "" })
-
+ useEffect(() => {
+ setUserData({
+ ...userData, email: (userData.last_name || userData.first_name) ? removeWhiteSpace(userData.first_name + "." + userData.last_name + "@teamwillgroup.com") : ""
+ })
+ setErrors({ ...errors, email: "" })
+ }, [userData.first_name, userData.last_name])
const isValidFields = () => {
const localErrors = { first_name: "", last_name: "", email: "", role: "" }
if (userData.first_name === "") localErrors.first_name = "Le prénom doit être spécifier."
@@ -147,10 +153,8 @@ const CreateUserForm = ({ setIsOpen, appendUser }) => {
setSelectedRole(event.target.value)
else setSelectedRole(null)
}
- const handleProjectChange = (event) => {
- if (event.target.value)
- setSelectedProject([event.target.value])
- else setSelectedProject([])
+ const handleProjectChange = (selectedOptions) => {
+ setSelectedProject(selectedOptions.map((element) => element.value))
}
return (
@@ -171,19 +175,72 @@ const CreateUserForm = ({ setIsOpen, appendUser }) => {
-
+
+
+
+
+
+
+
+ {projects.length !== 0 ?
+
+ ({ label: project.nom, value: project.id }))}
+ styles={
+ {
+ menu: (provided) => ({
+ ...provided,
+ maxHeight: '170px',
+ overflowY: 'auto'
+ }),
+ menuList: (provided) => ({
+ ...provided,
+ maxHeight: '170px',
+ overflowY: 'auto'
+ }),
+ control: (provided, state) => ({
+ ...provided,
+ borderColor: state.isFocused ? '#93a84c' : 'rgb(212 212 212)',
+ borderWidth: "1px",
+ boxShadow: 'none',
+ borderRadius: "0.375rem",
+ height: "2.5rem",
+ '&:hover': {
+ borderColor: '#93a84c', // Tailwind's blue-600
+ },
+ }),
+ option: (provided, state) => ({
+ ...provided,
+ backgroundColor: state.isFocused ? '#d9e1b5' : 'white',
+ '&:hover': {
+ backgroundColor: '#d9e1b5', // Tailwind's blue-200
+ },
+ }),
+ }
+ }
+ />
+
+ :
+ Pas encore des projets
+ }
+
-
+
{roles.length !== 0 ?
@@ -201,27 +258,6 @@ const CreateUserForm = ({ setIsOpen, appendUser }) => {
}
-
-
-
-
-
- {projects.length !== 0 ?
-
-
-
- {projects?.map((project) => {
- return
- })}
-
-
- :
- Pas encore des projets
- }
-
-
| |