Adding appointments on patient interface

This commit is contained in:
2024-04-16 23:25:19 +02:00
parent a776466591
commit 9a39e4cfdc
17 changed files with 323 additions and 41 deletions

View File

@@ -1,7 +1,7 @@
INSERT INTO services (name,description,price) VALUES
('Chirurgie','Service de visio',100),
('Médecine', 'Service de laboratoire',50),
('Cancérologie', 'Service de cancérologie',75),
('Maternité', 'Service de maternité',150),
('Imagerie médical', "Service d'imagerie",75),
('Urgences', "Service d'urgences", 25);
INSERT INTO services (name,description,price,open_time,close_time,duration) VALUES
('Chirurgie','Service de visio',100,'08:00:00','20:00:00','02:00:00'),
('Médecine', 'Service de laboratoire',50,'08:00:00','18:30:00','00:30:00'),
('Cancérologie', 'Service de cancérologie',75,'08:00:00','18:30:00','01:00:00'),
('Maternité', 'Service de maternité',150,'08:00:00','18:30:00','02:00:00'),
('Imagerie médical', "Service d'imagerie",75,'08:00:00','18:30:00','01:00:00'),
('Urgences', "Service d'urgences", 25,'08:00:00','18:30:00','00:30:00');

View File

@@ -7,7 +7,6 @@ export function ItemList({ item, setDeleteMenu, setModifyMenu, user, setDetailMe
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");

View File

@@ -16,7 +16,7 @@ function Services({user,item}) {
.then((data) => {
setLoading(false);
if(data.status === 404) {
setError("Aucun hôpital trouvé");
setError("Aucun service trouvé");
return;
}

View File

@@ -15,7 +15,7 @@ function ServicesDoctor({user,item}) {
.then((data) => {
setLoading(false);
if(data.status === 404) {
setError("Aucun hôpital trouvé");
setError("Aucun service trouvé");
return;
}

View File

@@ -51,6 +51,18 @@ function CreateMenu({setCreateMenu,user}) {
<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-4 justify-between">
<label htmlFor="open_time">Heure d'ouverture</label>
<input type="time" {...register("open_time", {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="close_time">Heure de fermeture</label>
<input type="time" {...register("close_time", {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="duration">Durée de consultation</label>
<input type="time" {...register("duration", {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">
<SubmitButton text={"Créer le service"} loading={loading}/>
<BackButton setMenu={setCreateMenu}/>

View File

@@ -6,6 +6,7 @@ function ItemList({item, setDeleteMenu, setModifyMenu}) {
<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>De {item.open_time.substring(0, item.open_time.length-3)} à {item.close_time.substring(0, item.close_time.length-3)}, {item.duration.substring(0, item.duration.length-3)} par consultation</p>
<p>{item.description}</p>
</div>
<div className="flex flex-col items-center justify-beetween gap-4">

View File

@@ -51,6 +51,18 @@ function ModifyMenu({setModifyMenu,user,item}) {
<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-4 justify-between">
<label htmlFor="open_time">Heure d'ouverture</label>
<input type="time" {...register("open_time", {required: true, value: item.open_time})} 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="close_time">Heure de fermeture</label>
<input type="time" {...register("close_time", {required: true, value: item.close_time})} 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="duration">Durée de consultation</label>
<input type="time" {...register("duration", {required: true, value: item.duration})} 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}/>

View File

@@ -18,10 +18,7 @@ function Dashboard() {
if(!type && loading === 0){
get('users/@me/roles', user.token).then((data) => {
console.log(data);
setLoading(loading + 1);
setLoading(1);
if(data.status === 403) {
window.location.href = '/login';
@@ -31,7 +28,7 @@ function Dashboard() {
if(data.status === 404 || data.JSON[0].name === "Doctor") {
setType(false);
get('doctors/@me', user.token).then((dataDoc) => {
setLoading(loading + 1);
setLoading(2);
if(dataDoc.status >= 400) {
return;

View File

@@ -1,7 +1,5 @@
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 className={className}>
<ul>

View File

@@ -0,0 +1,52 @@
import { useState, useEffect } from "react";
import { post } from "../../../../../modules/fetchManager";
function DoctorSelector({hospital,service,user,setDoctor}) {
const [doctors, setDoctors] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
if(service && hospital) {
post('doctors/search',{service_id: service.id, hospital_id: hospital},user.token)
.then((data) => {
setError(null);
setLoading(false);
if(data.status === 404) {
setError("Aucun médecin trouvé");
return;
}
if(data.status >= 400) {
setError("Erreur serveur, veuillez réessayer plus tard");
return;
}
setDoctors(data.JSON);
return;
})
}
},[service,hospital]);
const onChange = (e) => {
setDoctor(e.target.value);
}
if(loading) return <p>Chargement...</p>;
if(error) return <p>{error}</p>;
return(
<div className="text-xl flex row justify-between items-center">
<label htmlFor="doctor_id">Choisir un médecin :</label>
<select name="doctor_id" id="doctor_id" className="w-48" onChange={onChange}>
<option value="">Choisir un médecin</option>
{doctors.map((doctor) => {
return <option value={doctor.id} key={doctor.id}>{doctor.first_name} {doctor.last_name}</option>
})}
</select>
</div>
);
}
export default DoctorSelector;

View File

@@ -0,0 +1,48 @@
import { useState, useEffect } from "react";
import { get } from "../../../../../modules/fetchManager";
function HospitalSelector({setHospital,user}) {
const [hospitals, setHospitals] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const onChange = (e) => {
e.preventDefault();
setHospital(e.target.value);
}
useEffect(() => {
get('hospitals',user.token).then((data) => {
if(data.status === 404) {
setLoading(false);
setError("Aucun hôpital trouvé");
return;
}
if(data.status === 500) {
setLoading(false);
setError("Erreur serveur, veuillez réessayer plus tard");
return;
}
setHospitals(data.JSON);
setLoading(false);
});
},[]);
if(loading) return <p>Chargement...</p>;
if(error) return <p>{error}</p>;
return(
<div className="text-xl flex row justify-between items-center">
<label htmlFor="hospital_id">Choisir un hôpital :</label>
<select name="hospital_id" id="hospital_id" onChange={onChange} className="w-48">
<option value="">Choisir un hôpital</option>
{hospitals.map((hospital) => {
return <option value={hospital.id} key={hospital.id}>{hospital.name}</option>
})}
</select>
</div>
);
}
export default HospitalSelector;

View File

@@ -1,16 +1,63 @@
import ModalContainer from "../../../modal-container";
import SubmitButton from "../../../submit-button";
import BackButton from "../../../back-button";
import HospitalSelector from "./hospital";
import ServiceSelector from "./service";
import DoctorSelector from "./doctors";
import Time from "./time";
import {useState} from "react";
import {post} from "../../../../../modules/fetchManager";
function Create({setCreateMenu, user}) {
const [service, setService] = useState(null);
const [hospital, setHospital] = useState(null);
const [doctor, setDoctor] = useState(null);
const [date, setDate] = useState(null);
const [time, setTime] = useState(null);
const onSubmit = (e) => {
e.preventDefault();
e.stopPropagation();
const data = {
service_id: service.id,
hospital_id: hospital,
doctor_id: doctor,
date: date,
time: time
}
console.log(data);
post('patients/@me/appointments', data, user.token)
.then((data) => {
if(data.status === 200) {
alert("Rendez-vous pris avec succès");
return;
}
alert("Erreur lors de la prise de rendez-vous");
});
};
const onChange = (e) => {
setDate(e.target.value);
}
return (
<ModalContainer setMenu={setCreateMenu}>
<div>
<h2 className="text-2xl">Prendre Rendez-Vous</h2>
</div>
<form action="" className="flex flex-col items-center gap-4">
<div>
<form action="" className="flex flex-col items-center gap-4" onSubmit={onSubmit}>
<div className="flex flex-col gap-4">
<HospitalSelector setHospital={setHospital} user={user}/>
<ServiceSelector setService={setService} user={user}/>
<DoctorSelector hospital={hospital} service={service} user={user} setDoctor={setDoctor}/>
<div className="text-xl flex flex-row justify-between items-center">
<label htmlFor="date">Choisissez une date :</label>
<input type="date" name="date" id="date" onChange={onChange}/>
</div>
<Time service={service} setTime={setTime}/>
</div>
<div className="flex flex-row gap-5">
<SubmitButton />

View File

@@ -0,0 +1,48 @@
import { useState, useEffect } from "react";
import { get } from "../../../../../modules/fetchManager";
function ServiceSelector({setService,user}) {
const [services, setServices] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
const onChange = (e) => {
e.preventDefault();
setService(services[e.target.value]);
};
useEffect(() => {
get('services',user.token).then((data) => {
if(data.status === 404) {
setLoading(false);
setError("Aucun hôpital trouvé");
return;
}
if(data.status === 500) {
setLoading(false);
setError("Erreur serveur, veuillez réessayer plus tard");
return;
}
setServices(data.JSON);
setLoading(false);
});
},[]);
if(loading) return <p>Chargement...</p>;
if(error) return <p>{error}</p>;
return(
<div className="text-xl flex row justify-between items-center">
<label htmlFor="hospital_id">Choisir un Service :</label>
<select onChange={onChange} className="w-48">
<option value="">Choisir un service</option>
{services.map((service,key) => {
return <option value={key} key={key}>{service.name}</option>
})}
</select>
</div>
);
}
export default ServiceSelector;

View File

@@ -0,0 +1,38 @@
import { timeStringToFloat, floatToTimeString } from "../../../../../modules/timeManager";
function Time({service,setTime}) {
if(!service) return null;
const openTime = timeStringToFloat(service.open_time);
const closeTime = timeStringToFloat(service.close_time);
const duration = timeStringToFloat(service.duration);
const workTime = closeTime - openTime;
const timeSlots = Math.floor(workTime / duration);
let time = [];
for(let i = 0; i < timeSlots; i++) {
time[i] = openTime + duration * i;
}
const onChange = (e) => {
setTime(e.target.value);
};
return(
<div className="text-xl flex flex-row justify-between items-center">
<label htmlFor="time">Choisissez un horaire :</label>
<select name="time" id="time" className="w-44" onChange={onChange}>
<option value="">Choisir un horaire</option>
{time.map((time,key) => {
const timeStr = floatToTimeString(time);
return <option value={timeStr} key={key}>{timeStr}</option>
})}
</select>
</div>
);
}
export default Time;

View File

@@ -1,9 +1,9 @@
import HeadTitle from "../../head-title";
import { get } from "../../../../modules/fetchManager";
import { useState } from "react";
import { useState, useEffect } from "react";
import Create from "./create";
import CreateButton from "../../createButton";
import ItemList from "../../admin/hospital/item-list";
import ItemList from "./item-list";
import MenuDisplay from "../../menu-display";
function Appointment({user}) {
@@ -12,23 +12,29 @@ function Appointment({user}) {
const [appointments, setAppointments] = useState([]);
const [createMenu, setCreateMenu] = useState(false);
if(loading && !error && appointments.length === 0){
get('patients/@me/appointments', user.token)
.then((data) => {
setLoading(false);
if(data.status === 404) {
setError("Aucun rendez-vous trouvé");
return;
}
// if(loading && !error && appointments.length === 0){
if(data.status === 500) {
setError("Erreur serveur, veuillez réessayer plus tard");
return;
}
// }
setAppointments(data.JSON);
});
}
useEffect(() => {
if(loading && !error && appointments.length === 0){
get('patients/@me/appointments', user.token)
.then((data) => {
setLoading(false);
if(data.status === 404) {
setError("Aucun rendez-vous trouvé");
return;
}
if(data.status === 500) {
setError("Erreur serveur, veuillez réessayer plus tard");
return;
}
setAppointments(data.JSON);
});
}
},[user]);
return (
<div>

View File

@@ -1,9 +1,21 @@
function ItemList({item}) {
const date = new Date(item.date);
return (
<div>
<h2>{item.date}</h2>
<p>{item.doctor}</p>
<p>{item.reason}</p>
<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} - {date.getDay() > 9 ? date.getDay() : "0"+date.getDay()}/{date.getMonth() > 9 ? date.getMonth() : "0"+date.getMonth()}/{date.getFullYear()},{item.time.substring(0,item.time.length-3)}</h3>
<p>Dr.{item.first_name} {item.last_name}, {item.email} - {item.phone}</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>
);
}

View File

@@ -0,0 +1,12 @@
export function timeStringToFloat(time) {
const hoursMinutes = time.split(/[.:]/);
const hours = parseInt(hoursMinutes[0], 10);
const minutes = hoursMinutes[1] ? parseInt(hoursMinutes[1], 10) : 0;
return hours + minutes / 60;
}
export function floatToTimeString(float) {
const hours = Math.floor(float) > 9 ? Math.floor(float) : '0' + Math.floor(float);
const minutes = Math.round((float - hours) * 60) > 9 ? Math.round((float - hours) * 60) : '0' + Math.round((float - hours) * 60);
return hours + ':' + minutes;
}