From 64d241dd670fc783147fcdd984ae00babc10fd4a Mon Sep 17 00:00:00 2001 From: Bhagya Date: Sun, 7 Jan 2024 03:17:30 -0700 Subject: [PATCH] exercises cards and patient routines working --- frontend/src/views/landing/Landing.jsx | 2 +- .../practitioner/PractitionerDashboard.jsx | 7 +- .../views/practitioner/PractitionerLogin.jsx | 4 +- .../views/practitioner/PractitionerSignUp.jsx | 2 +- .../components/ExerciseListModal.jsx | 62 +++++++++++++ .../practitioner/components/ExerciseModal.jsx | 45 ++++++---- .../practitioner/components/Exercises.jsx | 18 ++-- .../components/PatientDetails.jsx | 89 ++++++++++++++++--- .../practitioner/components/PatientTable.jsx | 79 ++++++++-------- 9 files changed, 231 insertions(+), 77 deletions(-) create mode 100644 frontend/src/views/practitioner/components/ExerciseListModal.jsx diff --git a/frontend/src/views/landing/Landing.jsx b/frontend/src/views/landing/Landing.jsx index a37d3c5..c675293 100644 --- a/frontend/src/views/landing/Landing.jsx +++ b/frontend/src/views/landing/Landing.jsx @@ -12,7 +12,7 @@ const Landing = () => {
-
+
MobilityMate Logo diff --git a/frontend/src/views/practitioner/PractitionerDashboard.jsx b/frontend/src/views/practitioner/PractitionerDashboard.jsx index c2ca0ad..78a0ec3 100644 --- a/frontend/src/views/practitioner/PractitionerDashboard.jsx +++ b/frontend/src/views/practitioner/PractitionerDashboard.jsx @@ -32,10 +32,10 @@ const PractitionerDashboard = () => {
-
+
+
{renderView()}
diff --git a/frontend/src/views/practitioner/PractitionerLogin.jsx b/frontend/src/views/practitioner/PractitionerLogin.jsx index e437080..34affa0 100644 --- a/frontend/src/views/practitioner/PractitionerLogin.jsx +++ b/frontend/src/views/practitioner/PractitionerLogin.jsx @@ -1,5 +1,5 @@ import logo from "../../assets/mobilityMate-NoBg-lg.png"; -import support from "../../assets/signupPractitioner.jpeg"; +import support from "../../assets/loginPractitioner.jpeg"; import { auth } from '../../../firebaseConfig'; const PractitionerLogin = () => { @@ -71,7 +71,7 @@ const PractitionerLogin = () => {
diff --git a/frontend/src/views/practitioner/PractitionerSignUp.jsx b/frontend/src/views/practitioner/PractitionerSignUp.jsx index 51ea3b9..9ef488a 100644 --- a/frontend/src/views/practitioner/PractitionerSignUp.jsx +++ b/frontend/src/views/practitioner/PractitionerSignUp.jsx @@ -84,7 +84,7 @@ const PractitionerSignUp = () => { className="mt-1 block p-4 w-full text-black bg-[#f1f1f1] rounded-lg border sm:text-md focus:outline-none focus:border-gray-500" />
- diff --git a/frontend/src/views/practitioner/components/ExerciseListModal.jsx b/frontend/src/views/practitioner/components/ExerciseListModal.jsx new file mode 100644 index 0000000..4bc8001 --- /dev/null +++ b/frontend/src/views/practitioner/components/ExerciseListModal.jsx @@ -0,0 +1,62 @@ +import { useState } from "react"; + +const ExerciseListModal = ({ exercises, onAddExercises, onClose }) => { + const [selectedExercises, setSelectedExercises] = useState([]); + + const handleSelectExercise = (exerciseId) => { + setSelectedExercises((prev) => { + if (prev.includes(exerciseId)) { + return prev.filter((id) => id !== exerciseId); + } else { + return [...prev, exerciseId]; + } + }); + }; + + const handleClose = () => { + document.getElementById("exercise_list_modal").close(); + onClose(); + }; + + const handleSubmit = () => { + onAddExercises(selectedExercises); + onClose(); + }; + + return ( + +
+
+ +
+

Select Exercises

+
+ {exercises.map((exercise) => ( +
+ handleSelectExercise(exercise.id)} + className="checkbox checkbox-primary mt-1 border-gray-500 active:bg-gray-500 active:text-gray-500 focus:ring-gray-500 dark:focus:ring-gray-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600 text-gray-600" + /> + {exercise.title} +
+ ))} +
+
+ +
+
+
+ ); +}; + +export default ExerciseListModal; diff --git a/frontend/src/views/practitioner/components/ExerciseModal.jsx b/frontend/src/views/practitioner/components/ExerciseModal.jsx index d5907dd..f894abc 100644 --- a/frontend/src/views/practitioner/components/ExerciseModal.jsx +++ b/frontend/src/views/practitioner/components/ExerciseModal.jsx @@ -31,19 +31,26 @@ const ExerciseModal = () => { }; const handleSubmit = async (e) => { - e.preventDefault(); + e.preventDefault(); - try { - // Add the new exercise to Firestore - const currentUser = await getCurrentUser(); - await db - .collection(`practitioners/${currentUser.uid}/exercises`) - .add({ ...formData, image: imageString }); - handleClose(); - } catch (error) { - console.error("Error adding new patient:", error); - } - }; + // Check if any form fields are empty + if (!formData.title || !formData.description || !formData.steps || !imageString) { + alert("Please fill in all fields and upload an image."); + return; + } + + try { + // Add the new exercise to Firestore + const currentUser = await getCurrentUser(); + await db + .collection(`practitioners/${currentUser.uid}/exercises`) + .add({ ...formData, image: imageString }); + handleClose(); + } catch (error) { + console.error("Error adding new exercise:", error); + alert("Failed to add new exercise. Please try again."); + } +}; const handleClose = () => { setFormData(emptyForm); @@ -102,13 +109,6 @@ Step 2. Sit down in the chair. onChange={handleChange} />
- {imageString && ( - Selected - )}
+ {imageString && ( + Selected + )}
- {/* TODO: map each exercise into a EXERCISE CARD HERE */} -
- {exercises.map((exercise, idx) => ( -

{exercise.title}

- ))} +
+
+ {exercises.map((exercise) => ( +
+ {exercise.title} +

{exercise.title}

+

{exercise.description}

+
+ ))} +
diff --git a/frontend/src/views/practitioner/components/PatientDetails.jsx b/frontend/src/views/practitioner/components/PatientDetails.jsx index cf8cd30..df59789 100644 --- a/frontend/src/views/practitioner/components/PatientDetails.jsx +++ b/frontend/src/views/practitioner/components/PatientDetails.jsx @@ -1,63 +1,132 @@ import { useEffect, useState } from "react"; import { db, getCurrentUser } from "../../../../firebaseConfig"; import { Edit } from "lucide-react"; +import ExerciseListModal from "./ExerciseListModal"; const PatientDetails = ({ patientID }) => { const [patient, setPatient] = useState(null); - console.log(patientID); + const [exercises, setExercises] = useState([]); + const [patientExercises, setPatientExercises] = useState([]); + const [showModal, setShowModal] = useState(false); useEffect(() => { const fetchPatientDetails = async () => { const currentUser = await getCurrentUser(); + // Fetch patient details const patientRef = db .collection("practitioners") .doc(currentUser.uid) .collection("patients") .doc(patientID); - // Set up a snapshot listener to get real-time updates - const unsubscribe = patientRef.onSnapshot((doc) => { + const unsubscribePatient = patientRef.onSnapshot((doc) => { if (doc.exists) { - setPatient(doc.data()); + const patientData = doc.data(); + setPatient(patientData); + if (patientData.exerciseRoutine) { + setPatientExercises(patientData.exerciseRoutine); + } } else { console.error("Patient not found"); } }); + // Fetch exercises + const exercisesRef = db + .collection("practitioners") + .doc(currentUser.uid) + .collection("exercises"); + + const unsubscribeExercises = exercisesRef.onSnapshot((snapshot) => { + setExercises( + snapshot.docs.map((doc) => ({ + id: doc.id, + ...doc.data(), + })) + ); + }); + return () => { - unsubscribe(); + unsubscribePatient(); + unsubscribeExercises(); }; }; fetchPatientDetails(); }, [patientID]); + const handleAddExercises = async (selectedExercises) => { + const currentUser = await getCurrentUser(); + const patientRef = db.collection("practitioners").doc(currentUser.uid).collection("patients").doc(patientID); + await patientRef.update({ + exerciseRoutine: selectedExercises + }); + + setPatientExercises(selectedExercises); + setShowModal(false); + }; + + const toggleModal = () => { + const modal = document.getElementById('exercise_list_modal'); + if (modal) { + showModal ? modal.close() : modal.showModal(); + setShowModal(!showModal); + } else { + console.error("Modal element not found"); + } + }; + return ( -
+
{patient ? (

{patient.name}

-
+

{patientID}

{patient.age} years old

{patient.email}

Last Login: {patient.lastLogin || "Never"}

-
+

Exercise Routine

+ {/* Display exercises in the patient's routine as cards */} +
+
+ {patientExercises.length === 0 ? ( +

No exercises in the routine.

+ ) : ( + patientExercises.map(exerciseId => { + const exercise = exercises.find(e => e.id === exerciseId); + return exercise && ( +
+ {exercise.title} +

{exercise.title}

+

{exercise.description}

+
+ ); + }) + )} +
+
) : (

Loading patient details...

)} + + setShowModal(false)} + />
); }; diff --git a/frontend/src/views/practitioner/components/PatientTable.jsx b/frontend/src/views/practitioner/components/PatientTable.jsx index 6aa3c52..833af04 100644 --- a/frontend/src/views/practitioner/components/PatientTable.jsx +++ b/frontend/src/views/practitioner/components/PatientTable.jsx @@ -1,10 +1,11 @@ -import { Plus } from "lucide-react"; -import { db, getCurrentUser } from "../../../../firebaseConfig"; import { useEffect, useState } from "react"; +import { db, getCurrentUser } from "../../../../firebaseConfig"; +import { Plus } from "lucide-react"; import NewPatientModal from "./NewPatientModal"; const PatientTable = ({ onPatientClick }) => { const [patients, setPatients] = useState([]); + const [isLoading, setIsLoading] = useState(true); // State to track loading useEffect(() => { const fetchData = async () => { @@ -15,7 +16,6 @@ const PatientTable = ({ onPatientClick }) => { .doc(currentUser.uid) .collection("patients"); - // Use snapshot listener for real-time updates const unsubscribe = patientsRef.onSnapshot((snapshot) => { setPatients( snapshot.docs.map((doc) => ({ @@ -23,12 +23,13 @@ const PatientTable = ({ onPatientClick }) => { ...doc.data(), })) ); + setIsLoading(false); // Data fetched, loading complete }); return () => unsubscribe(); } catch (error) { - // Handle errors here console.error("Error fetching data:", error); + setIsLoading(false); // In case of error, also stop loading } }; @@ -44,42 +45,50 @@ const PatientTable = ({ onPatientClick }) => {

Patients

- - - - - - - - - - - - {patients.map((patient, idx) => ( - handleRowClick(patient.id)} - > - - - - - - - ))} - -
IDNameAgeEmailLast Login
{patient.id}{patient.name}{patient.age}{patient.email}{patient.lastLogin || "Never"}
+ + {isLoading ? ( +
+ Loading... {/* Replace with your spinner or loading component */} +
+ ) : ( +
+ + + + + + + + + + + + {patients.map((patient) => ( + handleRowClick(patient.id)} + > + + + + + + + ))} + +
IDNameAgeEmailLast Login
{patient.id}{patient.name}{patient.age}{patient.email}{patient.lastLogin || "Never"}
+
+ )} +
);