Adding doctor handling

This commit is contained in:
2024-04-14 21:52:22 +02:00
parent 22ce9b2704
commit a776466591
56 changed files with 1174 additions and 75 deletions

9
package-lock.json generated
View File

@@ -14,6 +14,7 @@
"node-fetch": "^3.3.2",
"pino": "^8.19.0",
"react": "^18.2.0",
"react-async": "^10.0.1",
"react-dom": "^18.2.0",
"react-hook-form": "^7.51.0",
"react-router": "^6.22.2",
@@ -15113,6 +15114,14 @@
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
"integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
},
"node_modules/react-async": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/react-async/-/react-async-10.0.1.tgz",
"integrity": "sha512-ORUz5ca0B57QgBIzEZM5SuhJ6xFjkvEEs0gylLNlWf06vuVcLZsjIw3wx58jJkZG38p+0nUAxRgFW2b7mnVZzA==",
"peerDependencies": {
"react": ">=16.3.1"
}
},
"node_modules/react-dev-utils": {
"version": "12.0.1",
"resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz",

View File

@@ -9,6 +9,7 @@
"node-fetch": "^3.3.2",
"pino": "^8.19.0",
"react": "^18.2.0",
"react-async": "^10.0.1",
"react-dom": "^18.2.0",
"react-hook-form": "^7.51.0",
"react-router": "^6.22.2",

View File

@@ -0,0 +1,45 @@
import ModalContainer from '../../../modal-container';
import { get } from '../../../../../modules/fetchManager';
import { useState } from 'react';
import BackButton from '../../../back-button';
function DetailMenu({user,detail,setDetail}) {
const [data, setData] = useState([]);
if(data.length === 0) {
get('users/'+detail.user_id, user.token)
.then((data) => {
setData(data.JSON);
});
}
return(
<ModalContainer>
{
data.length === 0 ? <p>Chargement...</p> :
<div>
<h2 className="text-2xl">Détails</h2>
<div className="flex flex-col gap-4">
<div className="flex flex-col gap-4">
<p><span className="font-bold">Nom:</span> {data.first_name}</p>
<p><span className="font-bold">Prénom:</span> {data.last_name}</p>
<p><span className="font-bold">Email Perso:</span> {data.email}</p>
<p><span className="font-bold">Téléphone Perso:</span> {data.phone}</p>
<p><span className="font-bold">Email Perso:</span> {detail.email}</p>
<p><span className="font-bold">Téléphone Perso:</span> {detail.phone}</p>
<p><span className="font-bold">Spécialité:</span> {detail.speciality}</p>
<p><span className="font-bold">Statut:</span> {detail.status}</p>
<p><span className="font-bold">Vérifié:</span> {detail.is_verified ? "Oui" : "Non"}</p>
</div>
<BackButton setMenu={setDetail}/>
</div>
</div>
}
</ModalContainer>
)
}
export default DetailMenu;

View File

@@ -0,0 +1,50 @@
import HeadTitle from "../../head-title";
import Container from "../../container";
import { useState } from "react";
import ItemList from "./item-list";
import MenuDisplay from "../../menu-display";
import ModifyMenu from "./modify";
import DeleteMenu from "../../delete-menu";
import { get } from "../../../../modules/fetchManager";
import DetailMenu from "./detail";
function Docteur({user}) {
const [docteurs, setDocteurs] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [modifyMenu, setModifyMenu] = useState(false);
const [deleteMenu, setDeleteMenu] = useState(false);
const [detailMenu, setDetailMenu] = useState(false);
if(loading && !error && docteurs.length === 0){
get('doctors', user.token)
.then((data) => {
setLoading(false);
if(data.status === 404) {
setError("Aucun docteur trouvé");
return;
}
if(data.status === 500) {
setError("Erreur serveur, veuillez réessayer plus tard");
return;
}
setDocteurs(data.JSON);
});
}
return(
<div>
<HeadTitle title={"Docteurs"}/>
<Container>
<MenuDisplay loading={loading} error={error} data={docteurs} ItemList={ItemList} setDeleteMenu={setDeleteMenu} setModifyMenu={setModifyMenu} user={user} setDetailMenu={setDetailMenu}/>
{ modifyMenu ? <ModifyMenu item={modifyMenu} setModifyMenu={setModifyMenu} user={user} /> : null }
{ deleteMenu ? <DeleteMenu deleteMenu={deleteMenu} setDeleteMenu={setDeleteMenu} user={user} link={"docteurs"} element={"ce docteur"}/> : null }
{ detailMenu ? <DetailMenu detail={detailMenu} setDetail={setDetailMenu} user={user} /> : null }
</Container>
</div>
)
}
export default Docteur;

View File

@@ -0,0 +1,38 @@
import { post } from "../../../../../modules/fetchManager";
import ModifyButton from "../../../modify-button";
import DeleteButton from "../../../delete-button";
export function ItemList({ item, setDeleteMenu, setModifyMenu, user, setDetailMenu }) {
const onClick = () => {
post('doctors/'+item.id+'/validate', {doctor_id: item.id}, user.token)
.then((data) => {
console.log(data);
if(data.status === 500) alert("Erreur serveur, veuillez réessayer plus tard");
if(data.status === 400) alert("Docteur non trouvé ou erreur dans la requête");
if(data.status === 200) alert("Docteur vérifié");
});
}
return (
<div className="text-xl bg-cyan-300 p-4 w-full flex flex-row">
<div className="w-3/4">
<h3 className="text-3xl py-2">{item.email}</h3>
<p>{item.phone}, {item.speciality}, {item.status}, {item.is_verified ? "Vérifié" : "Non vérifié"}</p>
</div>
<div className="flex flex-row items-center justify-beetween gap-4">
<div className="flex flex-col items-center justify-beetween gap-4">
{!item.is_verified ? <button className="bg-green-500 text-white px-4 py-2 rounded-lg" onClick={onClick}>Vérifier</button> : null}
<button className="bg-blue-500 text-white px-4 py-2 rounded-lg" onClick={() => setDetailMenu(item)}>Détails</button>
</div>
<div className="flex flex-col items-center justify-beetween gap-4">
<ModifyButton setModifyMenu={setModifyMenu} item={item} />
<DeleteButton setDeleteMenu={setDeleteMenu} id={item.id} />
</div>
</div>
</div>
);
}
export default ItemList;

View File

@@ -0,0 +1,63 @@
import { useState, useEffect } from "react";
import { useForm } from "react-hook-form";
import { get,post } from "../../../../../modules/fetchManager";
import SubmitButton from "../../../submit-button";
function Hospitals({user,item}) {
const {register, handleSubmit} = useForm();
const [data, setData] = useState(null);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
get('hospitals', user.token)
.then((data) => {
setLoading(false);
if(data.status === 404) {
setError("Aucun hôpital trouvé");
return;
}
if(data.status === 500) {
setError("Erreur serveur, veuillez réessayer plus tard");
return;
}
setData(data.JSON);
});
},[]);
const onSubmit = (dataForm) => {
post('hospitals/'+dataForm.hospital_id+'/doctors',{doctor_id: item.id},user.token)
.then((data) => {
if(data.status === 200) {
alert("Hôpital ajouté");
return;
}
alert(data.message);
})
}
if(error) return <p>{error}</p>;
return(
<form action="" className="" onSubmit={handleSubmit(onSubmit)}>
{
loading ? <p>Chargement...</p> :
<div className="flex flex-row items-center justify-between gap-10">
<div className="flex flex-col gap-4 text-xl">
<label htmlFor="hospital_id">Ajouter un hôpital :</label>
<select {...register("hospital_id")}>
{data.map((hospital) => {
return <option value={hospital.id} key={hospital.id}>{hospital.name}</option>
})}
</select>
</div>
<SubmitButton name="Ajouter"/>
</div>
}
</form>
);
}
export default Hospitals;

View File

@@ -0,0 +1,62 @@
import { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { get, del } from "../../../../../modules/fetchManager";
function HospitalsDoctor({user,item}) {
const {register, handleSubmit} = useForm();
const [data, setData] = useState(null);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
get('doctors/'+item.id+'/hospitals', user.token)
.then((data) => {
setLoading(false);
if(data.status === 404) {
setError("Aucun hôpital trouvé");
return;
}
if(data.status === 500) {
setError("Erreur serveur, veuillez réessayer plus tard");
return;
}
setData(data.JSON);
});
},[]);
const onSubmit = (dataForm) => {
del('hospitals/'+dataForm.hospital_id+'/doctors/'+item.id, user.token)
.then((data) => {
if(data.status === 200) {
alert("Hôpital retiré");
return;
}
alert(data.message);
})
};
if(error) return <p>{error}</p>;
return(
<form method="" onSubmit={handleSubmit(onSubmit)}>
{
loading ? <p>Chargement...</p> :
<div className="flex flex-row items-center justify-between gap-10">
<div className="flex flex-col gap-4 text-xl">
<label htmlFor="hospital_id">Retirer un hôpital :</label>
<select {...register("hospital_id")}>
{data.map((hospital) => {
return <option value={hospital.id} key={hospital.id}>{hospital.name}</option>
})}
</select>
</div>
<button type="submit" className="border-2 border-red-500 hover:bg-red-500 hover:text-white rounded-xl w-36 p-6 transition-all ease-in-out duration-300">Retirer</button>
</div>
}
</form>
);
}
export default HospitalsDoctor;

View File

@@ -0,0 +1,21 @@
import ModalContainer from '../../../modal-container';
import Hospitals from './hospitals';
import Services from './services';
import HospitalsDoctor from './hospitalsDoctor';
import ServicesDoctor from './servicesDoctor';
import BackButton from '../../../back-button';
function ModifyMenu({item, setModifyMenu,user}) {
return (
<ModalContainer>
<HospitalsDoctor user={user} item={item}></HospitalsDoctor>
<ServicesDoctor user={user} item={item}></ServicesDoctor>
<Hospitals user={user} item={item}></Hospitals>
<Services user={user} item={item}></Services>
<BackButton setMenu={setModifyMenu}></BackButton>
</ModalContainer>
);
}
export default ModifyMenu;

View File

@@ -0,0 +1,63 @@
import { useState, useEffect } from "react";
import { useForm } from "react-hook-form";
import { get,post } from "../../../../../modules/fetchManager";
import SubmitButton from "../../../submit-button";
function Services({user,item}) {
const {register, handleSubmit} = useForm();
const [data, setData] = useState(null);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
get('services', user.token)
.then((data) => {
setLoading(false);
if(data.status === 404) {
setError("Aucun hôpital trouvé");
return;
}
if(data.status === 500) {
setError("Erreur serveur, veuillez réessayer plus tard");
return;
}
setData(data.JSON);
});
},[]);
const onSubmit = (dataForm) => {
post('doctors/'+item.id+'/services',dataForm,user.token)
.then((data) => {
if(data.status === 200) {
alert("Service ajouté");
return;
}
alert(data.message);
})
}
if(error) return <p>{error}</p>;
return(
<form action="" className="" onSubmit={handleSubmit(onSubmit)}>
{
loading ? <p>Chargement...</p> :
<div className="flex flex-row items-center justify-between gap-10">
<div className="flex flex-col gap-4 text-xl">
<label htmlFor="service_id">Ajouter un service :</label>
<select {...register("service_id")}>
{data.map((service) => {
return <option value={service.id} key={service.id}>{service.name}</option>
})}
</select>
</div>
<SubmitButton name="Ajouter"/>
</div>
}
</form>
);
}
export default Services;

View File

@@ -0,0 +1,62 @@
import { useEffect, useState } from "react";
import { useForm } from "react-hook-form";
import { get, del } from "../../../../../modules/fetchManager";
function ServicesDoctor({user,item}) {
const {register, handleSubmit} = useForm();
const [data, setData] = useState(null);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
get('doctors/'+item.id+'/services', user.token)
.then((data) => {
setLoading(false);
if(data.status === 404) {
setError("Aucun hôpital trouvé");
return;
}
if(data.status === 500) {
setError("Erreur serveur, veuillez réessayer plus tard");
return;
}
setData(data.JSON);
});
},[]);
const onSubmit = (dataForm) => {
del('doctors/'+item.id+'/services/'+dataForm.service_id, user.token)
.then((data) => {
if(data.status === 200) {
alert("Service retiré");
return;
}
alert(data.message);
})
};
if(error) return <p>{error}</p>;
return(
<form method="" onSubmit={handleSubmit(onSubmit)}>
{
loading ? <p>Chargement...</p> :
<div className="flex flex-row items-center justify-between gap-10 w-full">
<div className="flex flex-col gap-4 text-xl">
<label htmlFor="service_id">Retirer un service :</label>
<select {...register("service_id")}>
{data.map((service) => {
return <option value={service.id} key={service.id}>{service.name}</option>
})}
</select>
</div>
<button type="submit" className="border-2 border-red-500 hover:bg-red-500 hover:text-white rounded-xl w-36 p-6 transition-all ease-in-out duration-300">Retirer</button>
</div>
}
</form>
);
}
export default ServicesDoctor;

View File

@@ -1,26 +1,45 @@
import ModalContainer from '../../../modal-container';
import { useForm } from 'react-hook-form';
import { useState } from 'react';
import { post } from '../../../../../modules/fetchManager';
import BackButton from '../../../back-button';
import SubmitButton from '../../../submit-button';
function CreateHospital({setCreateMenu,user}) {
const { register, handleSubmit } = useForm();
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const onSubmit = (data) => {
setLoading(true);
data.company_id = 1;
data.country = "France";
post('hospitals', data, user.token)
.then(data => {
console.log(data);
setLoading(false);
if(data.status === 400) {
setError("Des champs n'ont pas été remplis correctement");
return;
}
if(data.status !== 200) {
setError("Erreur lors de la création de l'hôpital");
return;
}
setError("N");
})
}
return(
<ModalContainer title="Créer un hôpital" setModal={setCreateMenu}>
<ModalContainer title="Créer un hôpital" setMenu={setCreateMenu}>
<form onSubmit={handleSubmit(onSubmit)} className="flex flex-col gap-10">
<div className="text-center text-2xl">
<h2>Création d'un Hôpital</h2>
</div>
{loading ? <div className="text-center">Chargement...</div> : null}
{error && error !== "N" ? <div className="text-red-500 text-center">{error}</div> : null}
{error === "N" && !loading ? <div className="text-green-500 text-center">Hôpital créé avec succès</div> : null}
<div className="flex flex-row gap-4 justify-between">
<label htmlFor="name">Nom</label>
<input type="name" {...register("name", {required: true})} className="border-b-2 border-cyan-800 w-1/2 focus:outline-none"/>
@@ -38,11 +57,11 @@ function CreateHospital({setCreateMenu,user}) {
<input type="city" {...register("city", {required: true})} className="border-b-2 border-cyan-800 w-1/2 focus:outline-none"/>
</div>
<div className="flex flex-row gap-4 justify-between">
<label htmlFor="address">Addresse</label>
<label htmlFor="address">Adresse</label>
<input type="address" {...register("address", {required: true})} className="border-b-2 border-cyan-800 w-1/2 focus:outline-none"/>
</div>
<div className="flex flex-row gap-8 justify-center">
<BackButton setMenu={setMenu}/>
<BackButton setMenu={setCreateMenu}/>
<SubmitButton/>
</div>
</form>

View File

@@ -1,9 +1,49 @@
import HeadTitle from "../../head-title";
import { get } from "../../../../modules/fetchManager";
import { useState } from "react";
import ItemList from "./item-list";
import Create from "./create";
import CreateButton from "../../createButton";
import MenuDisplay from "../../menu-display";
import ModifyMenu from "./modify";
import DeleteMenu from "../../delete-menu";
function Hospital({user}) {
const [hospitals, setHospitals] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [createMenu, setCreateMenu] = useState(false);
const [modifyMenu, setModifyMenu] = useState(false);
const [deleteMenu, setDeleteMenu] = useState(false);
if(loading && !error && hospitals.length === 0){
get('hospitals', user.token)
.then((data) => {
setLoading(false);
if(data.status === 404) {
setError("Aucun hôpital trouvé");
return;
}
if(data.status === 500) {
setError("Erreur serveur, veuillez réessayer plus tard");
return;
}
setHospitals(data.JSON);
});
}
return(
<div>
<HeadTitle title={"Hôpitaux"}/>
<div className="flex justify-center items-center mt-10">
<CreateButton setCreateMenu={setCreateMenu} nameMenu="Créez un hôpital"/>
</div>
<MenuDisplay loading={loading} error={error} data={hospitals} ItemList={ItemList} setDeleteMenu={setDeleteMenu} setModifyMenu={setModifyMenu}/>
{ createMenu ? <Create setCreateMenu={setCreateMenu} user={user}/> : null }
{ modifyMenu ? <ModifyMenu item={modifyMenu} setModifyMenu={setModifyMenu} user={user} /> : null }
{ deleteMenu ? <DeleteMenu deleteMenu={deleteMenu} setDeleteMenu={setDeleteMenu} user={user} link={"hospitals"} element={"cet hôpital"}/> : null }
</div>
)
}

View File

@@ -0,0 +1,19 @@
import ModifyButton from "../../../modify-button";
import DeleteButton from "../../../delete-button";
function ItemList({item, setDeleteMenu, setModifyMenu}) {
return(
<div className="text-xl bg-cyan-300 p-4 w-full flex flex-row">
<div className="w-3/4">
<h3 className="text-3xl py-2">{item.name} - {item.code}</h3>
<p>{item.address}, {item.city}, {item.region}, {item.country}</p>
</div>
<div className="flex flex-col items-center justify-beetween gap-4">
<ModifyButton setModifyMenu={setModifyMenu} item={item}/>
<DeleteButton setDeleteMenu={setDeleteMenu} id={item.id}/>
</div>
</div>
);
}
export default ItemList;

View File

@@ -0,0 +1,72 @@
import ModalContainer from "../../../modal-container";
import { useForm } from 'react-hook-form';
import { useState } from 'react';
import { put } from '../../../../../modules/fetchManager';
import BackButton from "../../../back-button";
import SubmitButton from "../../../submit-button";
function ModifyMenu({setModifyMenu,user,item}) {
const { register, handleSubmit } = useForm();
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const onSubmit = (data) => {
setLoading(true);
data.country = "France";
data.company_id = 1;
put('hospitals/'+item.id, data, user.token)
.then(data => {
setLoading(false);
if(data.status === 400) {
setError("Des champs n'ont pas été remplis correctement");
return;
}
if(data.status !== 200) {
setError("Erreur lors de la modification de l'hôpital");
return;
}
setError("N");
});
}
return(
<ModalContainer setModal={setModifyMenu}>
<form onSubmit={handleSubmit(onSubmit)} className="flex flex-col gap-10">
<div className="text-center text-2xl">
<h2>Modification d'un Hôpital</h2>
</div>
{loading ? <div className="text-center">Chargement...</div> : null}
{error && error !== "N" ? <div className="text-red-500 text-center">{error}</div> : null}
{error === "N" && !loading ? <div className="text-green-500 text-center">Hôpital modifié avec succès</div> : null}
<div className="flex flex-row gap-4 justify-between">
<label htmlFor="name">Nom</label>
<input type="name" {...register("name", {required: true,value: item.name})} className="border-b-2 border-cyan-800 w-1/2 focus:outline-none"/>
</div>
<div className="flex flex-row gap-4 justify-between">
<label htmlFor="code">Code</label>
<input type="code" {...register("code", {required: true,value: item.code})} className="border-b-2 border-cyan-800 w-1/2 focus:outline-none"/>
</div>
<div className="flex flex-row gap-4 justify-between">
<label htmlFor="region">Région</label>
<input type="region" {...register("region", {required: true,value: item.region})} className="border-b-2 border-cyan-800 w-1/2 focus:outline-none"/>
</div>
<div className="flex flex-row gap-4 justify-between">
<label htmlFor="city">Ville</label>
<input type="city" {...register("city", {required: true,value: item.city})} className="border-b-2 border-cyan-800 w-1/2 focus:outline-none"/>
</div>
<div className="flex flex-row gap-4 justify-between">
<label htmlFor="address">Adresse</label>
<input type="address" {...register("address", {required: true,value: item.address})} className="border-b-2 border-cyan-800 w-1/2 focus:outline-none"/>
</div>
<div className="flex flex-row gap-8 justify-center">
<BackButton setMenu={setModifyMenu}/>
<SubmitButton/>
</div>
</form>
</ModalContainer>
)
}
export default ModifyMenu;

View File

@@ -12,9 +12,12 @@ function Admin({user,setUser}) {
config.prescriptionOn ? {page:"prescription",name:"Préscriptions"} : null,
{page:"medical-file",name:"Dossier Médical"},
{page:"user",name:"Utilisateurs"},
{page:"doctor",name:"Docteurs"},
{page:"patient",name:"Patients"},
{page:"hospital",name:"Hôpitaux"},
{page:"service",name:"Services"},
{page:"profil",name:"Profil"}
]
];
return(
<PageContainer links={links} setUser={setUser} user={user} setPage={setPage}>

View File

@@ -5,6 +5,9 @@ import User from "../user";
import Hospital from "../hospital";
import Profil from "../profil";
import Home from "../../home";
import Doctor from "../doctor";
import Patient from "../patient";
import Service from "../services";
function MenuHandler({page,user}) {
switch (page) {
@@ -16,6 +19,12 @@ function MenuHandler({page,user}) {
return <Appointment user={user} />;
case "user":
return <User user={user} />;
case "doctor":
return <Doctor user={user} />;
case "patient":
return <Patient user={user} />;
case "service":
return <Service user={user} />;
case "hospital":
return <Hospital user={user} />;
case "profil":

View File

@@ -0,0 +1,11 @@
import HeadTitle from "../../head-title";
function Patient({user}) {
return(
<div>
<HeadTitle title={"Patients"}/>
</div>
)
}
export default Patient;

View File

@@ -0,0 +1,63 @@
import ModalContainer from "../../../modal-container";
import { useForm } from 'react-hook-form';
import { useState } from 'react';
import { post } from '../../../../../modules/fetchManager';
import SubmitButton from "../../../submit-button";
import BackButton from "../../../back-button";
function CreateMenu({setCreateMenu,user}) {
const { register, handleSubmit } = useForm();
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const onSubmit = (data) => {
setLoading(true);
post('services', data, user.token)
.then(data => {
setLoading(false);
if(data.status === 400) {
setError("Des champs n'ont pas été remplis correctement");
return;
}
if(data.status !== 200) {
setError("Erreur lors de la création du service");
return;
}
setError("N");
})
};
return(
<ModalContainer>
<form action="" onSubmit={handleSubmit(onSubmit)} className="flex flex-col gap-10">
<div className="text-center text-2xl">
<h2>Création d'un Service</h2>
</div>
{loading ? <div className="text-center">Chargement...</div> : null}
{error && error !== "N" ? <div className="text-red-500 text-center">{error}</div> : null}
{error === "N" && !loading ? <div className="text-green-500 text-center">Service créé avec succès</div> : null}
<div className="flex flex-row gap-4 justify-between">
<label htmlFor="name">Nom</label>
<input type="name" {...register("name", {required: true})} className="border-b-2 border-cyan-800 w-1/2 focus:outline-none"/>
</div>
<div className="flex flex-row gap-4 justify-between">
<label htmlFor="description">Description</label>
<textarea {...register("description", {required: true})} className="border-b-2 border-cyan-800 w-1/2 focus:outline-none"/>
</div>
<div className="flex flex-row gap-4 justify-between">
<label htmlFor="price">Prix</label>
<input type="number" {...register("price", {required: true, step: 0.01})} className="border-b-2 border-cyan-800 w-1/2 focus:outline-none"/>
</div>
<div className="flex flex-row gap-8 justify-center">
<SubmitButton text={"Créer le service"} loading={loading}/>
<BackButton setMenu={setCreateMenu}/>
</div>
</form>
</ModalContainer>
)
}
export default CreateMenu;

View File

@@ -0,0 +1,54 @@
import HeadTitle from "../../head-title";
import Container from "../../container";
import { useState } from "react";
import ItemList from "./item-list";
import Create from "./create";
import CreateButton from "../../createButton";
import MenuDisplay from "../../menu-display";
import ModifyMenu from "./modify";
import DeleteMenu from "../../delete-menu";
import { get } from "../../../../modules/fetchManager";
function Service({user}) {
const [services, setServices] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const [createMenu, setCreateMenu] = useState(false);
const [modifyMenu, setModifyMenu] = useState(false);
const [deleteMenu, setDeleteMenu] = useState(false);
if(loading && !error && services.length === 0){
get('services', user.token)
.then((data) => {
setLoading(false);
if(data.status === 404) {
setError("Aucun service trouvé");
return;
}
if(data.status === 500) {
setError("Erreur serveur, veuillez réessayer plus tard");
return;
}
setServices(data.JSON);
});
}
return(
<div>
<HeadTitle title={"Services"}/>
<div className="flex justify-center items-center mt-10">
<CreateButton setCreateMenu={setCreateMenu} nameMenu={"Créer un service"} />
</div>
<Container>
<MenuDisplay loading={loading} error={error} data={services} ItemList={ItemList} setDeleteMenu={setDeleteMenu} setModifyMenu={setModifyMenu}/>
{ createMenu ? <Create setCreateMenu={setCreateMenu} user={user}/> : null }
{ modifyMenu ? <ModifyMenu item={modifyMenu} setModifyMenu={setModifyMenu} user={user} /> : null }
{ deleteMenu ? <DeleteMenu deleteMenu={deleteMenu} setDeleteMenu={setDeleteMenu} user={user} link={"services"} element={"ce service"}/> : null }
</Container>
</div>
)
}
export default Service;

View File

@@ -0,0 +1,19 @@
import ModifyButton from "../../../modify-button";
import DeleteButton from "../../../delete-button";
function ItemList({item, setDeleteMenu, setModifyMenu}) {
return(
<div className="text-xl bg-cyan-300 p-4 w-full flex flex-row">
<div className="w-3/4">
<h3 className="text-3xl py-2">{item.name} - {item.price}</h3>
<p>{item.description}</p>
</div>
<div className="flex flex-col items-center justify-beetween gap-4">
<ModifyButton setModifyMenu={setModifyMenu} item={item}/>
<DeleteButton setDeleteMenu={setDeleteMenu} id={item.id}/>
</div>
</div>
);
}
export default ItemList;

View File

@@ -0,0 +1,63 @@
import ModalContainer from "../../../modal-container";
import { useForm } from 'react-hook-form';
import { useState } from 'react';
import { put } from '../../../../../modules/fetchManager';
import SubmitButton from "../../../submit-button";
import BackButton from "../../../back-button";
function ModifyMenu({setModifyMenu,user,item}) {
const { register, handleSubmit } = useForm();
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const onSubmit = (data) => {
setLoading(true);
put('services/'+item.id, data, user.token)
.then(data => {
setLoading(false);
if(data.status === 400) {
setError("Des champs n'ont pas été remplis correctement");
return;
}
if(data.status !== 200) {
setError("Erreur lors de la création du service");
return;
}
setError("N");
})
};
return(
<ModalContainer>
<form action="" onSubmit={handleSubmit(onSubmit)} className="flex flex-col gap-10">
<div className="text-center text-2xl">
<h2>Création d'un Service</h2>
</div>
{loading ? <div className="text-center">Chargement...</div> : null}
{error && error !== "N" ? <div className="text-red-500 text-center">{error}</div> : null}
{error === "N" && !loading ? <div className="text-green-500 text-center">Service modifié avec succès</div> : null}
<div className="flex flex-row gap-4 justify-between">
<label htmlFor="name">Nom</label>
<input type="name" {...register("name", {required: true, value: item.name})} className="border-b-2 border-cyan-800 w-1/2 focus:outline-none"/>
</div>
<div className="flex flex-row gap-4 justify-between">
<label htmlFor="description">Description</label>
<textarea {...register("description", {required: true, value: item.description})} className="border-b-2 border-cyan-800 w-1/2 focus:outline-none"/>
</div>
<div className="flex flex-row gap-4 justify-between">
<label htmlFor="price">Prix</label>
<input type="number" {...register("price", {required: true, value: item.price, step: 0.01})} className="border-b-2 border-cyan-800 w-1/2 focus:outline-none"/>
</div>
<div className="flex flex-row gap-8 justify-center">
<SubmitButton text={"Créer le service"} loading={loading}/>
<BackButton setMenu={setModifyMenu}/>
</div>
</form>
</ModalContainer>
)
}
export default ModifyMenu;

View File

@@ -1,4 +1,5 @@
import HeadTitle from "../../head-title";
import ItemList from "./item-list";
function User({user}) {
return(

View File

@@ -0,0 +1,7 @@
function ItemList({item, setDeleteMenu}) {
<div>
</div>
}
export default ItemList;

View File

@@ -1,6 +1,6 @@
function Container({children}) {
return(
<div className="flex justify-center items-center h-screen">
<div className="flex justify-center items-center h-fit w-full">
{children}
</div>
)

View File

@@ -0,0 +1,7 @@
function DeleteButton({setDeleteMenu,id}) {
return(
<button className="bg-red-500 text-white px-4 py-2 rounded-lg" onClick={() => {setDeleteMenu(id)}}>Supprimer</button>
)
}
export default DeleteButton;

View File

@@ -0,0 +1,48 @@
import ModalContainer from "../modal-container";
import { del } from "../../../modules/fetchManager";
import { useState } from "react";
function DeleteMenu({deleteMenu, setDeleteMenu, link, user, element}) {
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const onClick = () => {
if(deleteMenu <= 0) {
setError("L'élément sélectionné est invalide !");
return;
}
setLoading(true);
del(link+'/'+deleteMenu, user.token)
.then(data => {
setLoading(false);
if(data.status === 500) {
setError("Erreur serveur, veuillez réessayer plus tard");
return;
}
if(data.status >= 400) {
setError("Erreur lors de la suppression, veuillez réessayer plus tard");
return;
}
setDeleteMenu(false);
})
}
return(
<ModalContainer setMenu={setDeleteMenu}>
<div className="flex flex-col items-center gap-4">
<h2 className="text-2xl">Voulez-vous vraiment supprimer {element} ?</h2>
{loading ? <div>Chargement...</div> : null}
{error ? <div className="text-red-500">{error}</div> : null}
<div className="flex flex-row gap-5">
<button onClick={() => onClick()} className="bg-red-500 text-white rounded-lg p-2">Supprimer</button>
<button onClick={() => setDeleteMenu(false)} className="bg-blue-500 text-white rounded-lg p-2">Annuler</button>
</div>
</div>
</ModalContainer>
)
}
export default DeleteMenu;

View File

@@ -0,0 +1,42 @@
import { get } from "../../../../../modules/fetchManager";
import { useState, useEffect } from "react";
import ListDisplay from "../../../list-display";
import ItemList from "./item-list";
function Hospitals({user}) {
const [data, setData] = useState(null);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
get('doctors/'+user.doctor.id+'/hospitals', user.token)
.then((data) => {
setLoading(false);
if(data.status === 404) {
setError("Aucun hôpital trouvé");
return;
}
if(data.status === 500) {
setError("Erreur serveur, veuillez réessayer plus tard");
return;
}
setData(data.JSON);
});
},[user]);
if(loading) return <p>Chargement...</p>;
if(error) return <p>{error}</p>;
return (
<div className="flex flex-col gap-4 items-center w-1/2">
<div className="text-2xl">
<h3>Hôpitaux</h3>
</div>
<ListDisplay data={data} ItemComponent={ItemList} height={false}/>
</div>
);
}
export default Hospitals;

View File

@@ -0,0 +1,11 @@
function ItemList({item}) {
return(
<div className="w-full bg-cyan-300 text-black p-3">
<h4 className="text-xl">{item.name} - {item.code}</h4>
<p className="text-sm">{item.address}</p>
<p className="text-sm">{item.city}, {item.region}, {item.country}</p>
</div>
);
}
export default ItemList;

View File

@@ -0,0 +1,27 @@
import HeadTitle from "../../head-title";
import Services from "./services";
import Hospitals from "./hospitals";
function Home({user}) {
return(
<div className="flex flex-col gap-6">
<HeadTitle title="Accueil"/>
<div className="flex flex-row justify-between">
<div className="flex flex-col gap-6 w-1/2 items-center">
<div className="text-2xl">
<h2>Affectation</h2>
</div>
<div className="flex flex-row gap-4 w-full">
<Services user={user}/>
<Hospitals user={user}/>
</div>
</div>
<div className="flex flex-col gap-6 w-1/2 items-center">
</div>
</div>
</div>
);
}
export default Home;

View File

@@ -0,0 +1,42 @@
import { get } from "../../../../../modules/fetchManager";
import { useState, useEffect } from "react";
import ListDisplay from "../../../list-display";
import ItemList from "./item-list";
function Services({user}) {
const [data, setData] = useState(null);
const [error, setError] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
get('doctors/'+user.doctor.id+'/services', user.token)
.then((data) => {
setLoading(false);
if(data.status === 404) {
setError("Aucun service trouvé");
return;
}
if(data.status === 500) {
setError("Erreur serveur, veuillez réessayer plus tard");
return;
}
setData(data.JSON);
});
},[user]);
if(loading) return <p>Chargement...</p>;
if(error) return <p>{error}</p>;
return (
<div className="flex flex-col gap-4 items-center w-1/2">
<div className="text-2xl">
<h3>Services</h3>
</div>
<ListDisplay data={data} ItemComponent={ItemList} height={false}/>
</div>
);
}
export default Services;

View File

@@ -0,0 +1,11 @@
function ItemList({item}) {
return(
<div className="w-full bg-cyan-300 text-black p-3">
<h4 className="text-xl">{item.name}</h4>
<p className="text-sm">{item.price}</p>
<p className="text-sm">{item.description}</p>
</div>
)
}
export default ItemList;

View File

@@ -1,10 +1,25 @@
function MenuHandler({page, setPage, user}) {
return (
<div>
<h1>MenuHandler</h1>
<p>Current page: {page}</p>
</div>
)
import Prescription from "../prescription";
import MedicalFile from "../medical-file";
import Appointment from "../appointment";
import Profil from "../profil";
import Home from "../home";
import Patient from "../patient";
function MenuHandler({page,user}) {
switch (page) {
case "prescription":
return <Prescription user={user} />;
case "medical-file":
return <MedicalFile user={user} />;
case "appointment":
return <Appointment user={user} />;
case "patient":
return <Patient user={user} />;
case "profil":
return <Profil user={user} />;
default:
return <Home user={user} />;
}
}
export default MenuHandler;

View File

@@ -1,6 +1,6 @@
function HeadTitle({title}) {
return(
<div className="text-4xl text-center">
<div className="text-4xl text-center uppercase">
<h1 className="min-h-16">{title}</h1>
</div>
)

View File

@@ -1,5 +1,5 @@
import PageHandler from "./page-handler";
import { useState, useEffect } from "react";
import { useState } from "react";
import { getUserSession, setUserSession } from "../../modules/userManager";
import { get } from "../../modules/fetchManager";
import TypeUser from "./type-user";
@@ -12,10 +12,6 @@ function Dashboard() {
const [type, setType] = useState((user.roles) ? true : false);
const [loading, setLoading] = useState(0);
// useEffect(() => {
// setUserSession(user);
// }, [user]);
if(!user.token || !user.data){
window.location.href = '/login';
}
@@ -23,6 +19,8 @@ function Dashboard() {
if(!type && loading === 0){
get('users/@me/roles', user.token).then((data) => {
console.log(data);
setLoading(loading + 1);
if(data.status === 403) {
@@ -30,22 +28,24 @@ function Dashboard() {
return;
}
if(data.status === 404) {
if(data.status === 404 || data.JSON[0].name === "Doctor") {
setType(false);
get('doctors/@me', user.token).then((data) => {
get('doctors/@me', user.token).then((dataDoc) => {
setLoading(loading + 1);
if(data.status >= 400) {
if(dataDoc.status >= 400) {
return;
}
const newUser = {
token: user.token,
data: user.data,
roles: user.roles,
doctor: data.JSON,
roles: data.JSON,
doctor: dataDoc.JSON,
};
// console.log(newUser);
setUser(newUser);
setUserSession(newUser);
setType(true);
@@ -67,6 +67,9 @@ function Dashboard() {
// console.log(type);
}
// console.log(type);
// console.log(user);
return(
<div>
{
@@ -82,15 +85,15 @@ function Dashboard() {
null
}
{
!type && loading < 2 ?
!type && loading === 2 ?
<div>
<TypeUser />
<TypeUser setUser={setUser}/>
</div>
:
null
}
{
!type && loading === 2 ?
!type && loading < 2 ?
<SecondMenuBg>
<Loader />
</SecondMenuBg>

View File

@@ -1,6 +1,6 @@
function Layout({children}) {
return(
<main className="fixed top-0 right-0 min-h-full w-5/6 p-4">
<main className="relative left-1/6 min-h-full h-fit w-5/6 p-4">
{children}
</main>
)

View File

@@ -1,14 +1,16 @@
function ListDisplay({data,itemComponent,setCreateMenu,nameMenu}) {
function ListDisplay({data, ItemComponent, height = true, setDeleteMenu = null, setModifyMenu = null, user = null, setDetailMenu = null}) {
const className = height ? "min-h-full h-fit py-5 w-full" : "h-fit py-5 w-full";
// const className = 'h-fit py-5 w-full';
console.log(className)
return(
<div>
<button onClick={() => setCreateMenu(true)}>{nameMenu}</button>
<div className={className}>
<ul>
{
data.map((item) => {
data.map((item,index) =>
<li>
{itemComponent(item)}
{<ItemComponent key={index} item={item} setDeleteMenu={setDeleteMenu} setModifyMenu={setModifyMenu} user={user} setDetailMenu={setDetailMenu}/>}
</li>
})
)
}
</ul>
</div>

View File

@@ -0,0 +1,17 @@
import { removeUserSession } from "../../../modules/userManager";
function LogoutButton({setUser}) {
const handleClick = (e) => {
e.preventDefault();
setUser(null);
removeUserSession();
window.location.href = '/';
}
return(
<button className="bg-red-500 text-white p-5 rounded-lg text-3xl" onClick={handleClick}>Déconnexion</button>
);
}
export default LogoutButton;

View File

@@ -0,0 +1,15 @@
import Container from "../container"
import Loader from "../loader"
import ListDisplay from "../list-display"
function MenuDisplay({loading, error, data, ItemList, setDeleteMenu, setModifyMenu,user = null,setDetailMenu = null}) {
return(
<Container>
{ loading ? <Loader color={true}/> : null }
{ error ? <p className="text-2xl">{error}</p> : null }
{ !error && !loading ? <ListDisplay data={data} ItemComponent={ItemList} setDeleteMenu={setDeleteMenu} setModifyMenu={setModifyMenu} user={user} setDetailMenu={setDetailMenu}/> : null }
</Container>
)
}
export default MenuDisplay;

View File

@@ -1,7 +1,10 @@
function ModalContainer({ children }) {
return (
<div className="fixed top-0 left-0 h-screen w-screen flex justify-center items-center bg-black/25 backdrop-blur-sm">
<div className="bg-white p-5 rounded-xl flex flex-col justify-start items-center">
<div className="bg-white p-5 rounded-xl flex flex-col justify-start items-center relative gap-4">
{/* <div className="absolute top-2 left-2" onClick={() => setMenu(false)}>
X
</div> */}
{children}
</div>
</div>

View File

@@ -0,0 +1,7 @@
function ModifyButton({setModifyMenu,item}) {
return(
<button className="bg-blue-500 text-white px-4 py-2 rounded-lg" onClick={() => {setModifyMenu(item)}}>Modifier</button>
);
}
export default ModifyButton;

View File

@@ -1,9 +1,9 @@
function Hero({user}) {
return(
<div className="py-10 text-center text-3xl flex flex-col items-center gap-5 text-white">
<div className="pt-10 text-center text-3xl flex flex-col items-center gap-5 text-white w-full">
<div className="h-36 w-36 bg-gray-400 rounded-full"></div>
<div>
<h3 className="min-h-10">{user.data.first_name + " " + user.data.last_name}</h3>
<div className="w-full">
<h3 className="min-h-10 w-full">{user.data.first_name + " " + user.data.last_name}</h3>
</div>
</div>
)

View File

@@ -1,22 +1,15 @@
import Hero from "./hero";
import LinkMenu from "./link-menu";
import { removeUserSession } from "../../../modules/userManager";
import LogoutButton from "../logout-button";
function Navbarre({setPage, user, setUser, links}) {
const handleClick = (e) => {
e.preventDefault();
setUser(null);
removeUserSession();
window.location.href = '/';
}
return (
<aside className="fixed left-0 top-0 h-screen w-1/6 bg-cyan-800 flex flex-col justify-between items-center">
<Hero user={user}/>
<LinkMenu setPage={setPage} links={links}/>
<div className="py-12">
<button className="bg-red-500 text-white p-5 rounded-lg text-3xl" onClick={handleClick}>Déconnexion</button>
<div className="pb-12">
<LogoutButton setUser={setUser}/>
</div>
</aside>
)

View File

@@ -3,8 +3,10 @@ import Layout from "../layout"
function PageContainer({children,links,setPage,setUser, user}) {
return(
<div>
<div className="flex flex-row">
<div className="h-auto min-h-screen w-1/6">
<Navbarre links={links} setPage={setPage} setUser={setUser} user={user} />
</div>
<Layout>
{children}
</Layout>

View File

@@ -1,13 +1,14 @@
import { removeUserSession } from "../../../modules/userManager";
import Patient from "../patient";
import Admin from "../admin";
import Doctor from "../doctor";
function PageHandler({user,setUser}) {
switch (user.roles[0].name) {
case "Patient" :
return <Patient user={user} setUser={setUser} />;
case "Doctor" :
return null;
return <Doctor user={user} setUser={setUser} />;
case "Admin" :
return <Admin user={user} setUser={setUser} />;
default:

View File

@@ -4,7 +4,7 @@ import BackButton from "../../../back-button";
function Create({setCreateMenu, user}) {
return (
<ModalContainer>
<ModalContainer setMenu={setCreateMenu}>
<div>
<h2 className="text-2xl">Prendre Rendez-Vous</h2>
</div>

View File

@@ -1,12 +1,10 @@
import HeadTitle from "../../head-title";
import { get } from "../../../../modules/fetchManager";
import { useState } from "react";
import Loader from "../../loader";
import Container from "../../container";
import ListDisplay from "../../list-display";
import ItemList from "./item-list";
import Create from "./create";
import CreateButton from "../../createButton";
import ItemList from "../../admin/hospital/item-list";
import MenuDisplay from "../../menu-display";
function Appointment({user}) {
const [loading, setLoading] = useState(true);
@@ -38,12 +36,8 @@ function Appointment({user}) {
<div className="flex justify-center items-center mt-10">
<CreateButton setCreateMenu={setCreateMenu} nameMenu="Prendre Rendez-Vous"/>
</div>
<Container>
{ loading ? <Loader color={true}/> : null }
{ error ? <p className="text-2xl">{error}</p> : null }
{ !error && !loading ? <ListDisplay data={appointments} itemComponent={ItemList}/> : null }
<MenuDisplay loading={loading} error={error} data={appointments} ItemList={ItemList}/>
{ createMenu ? <Create setCreateMenu={setCreateMenu} user={user}/> : null }
</Container>
</div>
);
}

View File

@@ -1,7 +1,7 @@
function SubmitButton() {
function SubmitButton({name = "Envoyer"}) {
return (
<button type="submit" className="w-36 p-6 border-2 border-green-600 rounded-2xl hover:bg-green-600 hover:text-white transition-all ease-in-out duration-300">
Envoyer
{name}
</button>
);
}

View File

@@ -4,7 +4,7 @@ import DoctorTypeUser from "./doctor-type-user";
import PatientTypeUser from "./patient-type-user";
import SecondMenuBg from "../second-menu-bg";
function TypeUser() {
function TypeUser({setUser}) {
const [menu, setMenu] = useState(null);
return (
@@ -12,7 +12,7 @@ function TypeUser() {
<div className="h-auto w-auto border-2 border-cyan-600 rounded-2xl p-5 bg-white text-xl" >
{menu === "patient" ? <PatientTypeUser setMenu={setMenu} /> : null}
{menu === "doctor" ? <DoctorTypeUser setMenu={setMenu} /> : null}
{(menu !== "patient" && menu !== "doctor") ? <SelectTypeUser setMenu={setMenu} /> : null}
{(menu !== "patient" && menu !== "doctor") ? <SelectTypeUser setMenu={setMenu} setUser={setUser}/> : null}
</div>
</SecondMenuBg>
);

View File

@@ -1,6 +1,7 @@
import Container from "../container";
import LogoutButton from "../../logout-button";
function SelectTypeUser({setMenu}) {
function SelectTypeUser({setMenu,setUser}) {
const handleClick = (e) => {
e.preventDefault();
@@ -25,6 +26,7 @@ function SelectTypeUser({setMenu}) {
<button id="doctor" className="w-52 p-6 border-2 border-cyan-600 rounded-2xl hover:bg-cyan-600 hover:text-white transition-all ease-in-out duration-300" onClick={handleClick}>
Docteur
</button>
<LogoutButton setUser={setUser}/>
</div>
</Container>
);

View File

@@ -5,11 +5,12 @@ function selectUrl(url) {
return url.includes('http') ? url : `${config.api}/${url}`;
}
async function get(url, token = 'none') {
async function get(url, token = 'none',signal = null) {
const options = {
method: 'GET',
mode: 'cors',
headers: { 'Content-Type': 'application/json', authorization: `${token}` },
signal: signal,
};
return await fetch(selectUrl(url), options)
@@ -20,12 +21,13 @@ async function get(url, token = 'none') {
.catch(err => error(err));
}
async function post(url, body, token = 'none') {
async function post(url, body, token = 'none',signal = null) {
const options = {
method: 'POST',
mode: 'cors',
headers: { 'Content-Type': 'application/json', authorization: `${token}` },
body: JSON.stringify(body),
signal: signal,
};
return await fetch(selectUrl(url), options)
@@ -36,12 +38,13 @@ async function post(url, body, token = 'none') {
.catch(err => error(err));
}
async function patch(url, body, token = 'none') {
async function patch(url, body, token = 'none',signal = null) {
const options = {
method: 'PATCH',
mode: 'cors',
headers: { 'Content-Type': 'application/json', authorization: `${token}` },
body: JSON.stringify(body),
signal: signal,
};
return await fetch(selectUrl(url), options)
@@ -52,12 +55,29 @@ async function patch(url, body, token = 'none') {
.catch(err => error(err));
}
async function put(url, body, token = 'none') {
async function put(url, body, token = 'none',signal = null) {
const options = {
method: 'PUT',
mode: 'cors',
headers: { 'Content-Type': 'application/json', authorization: `${token}` },
body: JSON.stringify(body),
signal: signal,
};
return await fetch(selectUrl(url), options)
.then(res => res.json())
.then(json => {
return json;
})
.catch(err => error(err));
}
async function del(url, token = 'none',signal = null) {
const options = {
method: 'DELETE',
mode: 'cors',
headers: { 'Content-Type': 'application/json', authorization: `${token}` },
signal: signal,
};
return await fetch(selectUrl(url), options)
@@ -73,4 +93,5 @@ export {
post,
patch,
put,
del
};

42
src/modules/useAsync.js Normal file
View File

@@ -0,0 +1,42 @@
import { useState, useCallback } from "react";
const cache = new Map();
const defaultOptions = {
cacheKey: "",
refetch: false,
};
export const useAsync = (defaultData) => {
const [data, setData] = useState({
data: defaultData ?? null,
error: null,
loading: false,
});
const run = useCallback(async (asyncFn, options = {}) => {
try {
// Merge the default options with the options passed in
const { cacheKey, refetch } = { ...defaultOptions, ...options };
const result = { data: null, error: null, loading: false };
// If we have a cache key and not requesting a new data, then return the cached data
if (!refetch && cacheKey && cache.has(cacheKey)) {
const res = cache.get(cacheKey);
result.data = res;
} else {
setData({ ...result, loading: true });
const res = await asyncFn();
result.data = res;
cacheKey && cache.set(cacheKey, res);
}
setData(result);
return result;
} catch (error) {
const result = { data: null, error: error, loading: false };
setData(result);
return result;
}
}, []);
return {
data : data.data,
error: data.error,
loading: data.loading,
run,
};
};