Skip to content
This repository has been archived by the owner on Jan 17, 2024. It is now read-only.

exercises cards and patient routines working #22

Merged
merged 1 commit into from
Jan 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion frontend/src/views/landing/Landing.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const Landing = () => {

<div className="w-px mt-40 mb-40 bg-gray-200"></div>

<div className="w-2/5 p-12 rounded-xl">
<div className="w-2/5 p-12 rounded-xl mt-40">
<header className="mb-12">
<div className="flex justify-center items-center">
<img src={logo} alt="MobilityMate Logo" className="h-20 mr-3" />
Expand Down
7 changes: 4 additions & 3 deletions frontend/src/views/practitioner/PractitionerDashboard.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ const PractitionerDashboard = () => {
<div className="min-h-screen">
<Navbar />
<main className="p-6 flex">
<div className="flex flex-col w-36 h-auto gap-4">
<div className="flex flex-col w-36 h-auto gap-4 mt-10">
<button
className={`btn ${
isPatientsActive ? "bg-dark-teal text-white" : ""
isPatientsActive ? "bg-dark-teal text-white hover:bg-gray-600" : "hover:bg-gray-200"
}`}
onClick={() => setActiveView("patients")}
>
Expand All @@ -44,14 +44,15 @@ const PractitionerDashboard = () => {
</button>
<button
className={`btn ${
isExercisesActive ? "bg-dark-teal text-white" : ""
isExercisesActive ? "bg-dark-teal text-white hover:bg-gray-600" : "hover:bg-gray-200"
}`}
onClick={() => setActiveView("exercises")}
>
<Dumbbell />
Exercises
</button>
</div>
<div className="w-px ml-5 mt-9 bg-gray-200"></div>
{renderView()}
</main>
</div>
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/views/practitioner/PractitionerLogin.jsx
Original file line number Diff line number Diff line change
@@ -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 = () => {
Expand Down Expand Up @@ -71,7 +71,7 @@ const PractitionerLogin = () => {
<div className="flex mb-10">
<button
type="submit"
className="w-full h-[55px] bg-black hover:bg-gray-800 text-white py-2 px-4 rounded"
className="w-full h-[55px] bg-black hover:bg-gray-700 text-white py-2 px-4 rounded"
>
Login
</button>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/views/practitioner/PractitionerSignUp.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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" />
</div>

<button type="submit" className="w-full h-[55px] bg-black hover:bg-gray-800 text-white py-2 px-4 rounded transition duration-300 ease-in-out">
<button type="submit" className="w-full h-[55px] bg-black hover:bg-gray-700 text-white py-2 px-4 rounded transition duration-300 ease-in-out">
Sign Up
</button>

Expand Down
62 changes: 62 additions & 0 deletions frontend/src/views/practitioner/components/ExerciseListModal.jsx
Original file line number Diff line number Diff line change
@@ -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 (
<dialog id="exercise_list_modal" className="modal">
<div className="modal-box">
<form method="dialog">
<button
type="button"
className="btn btn-sm btn-circle btn-ghost absolute right-2 top-2"
onClick={handleClose}
>
</button>
</form>
<h3 className="font-bold text-lg">Select Exercises</h3>
<div className="py-4">
{exercises.map((exercise) => (
<div key={exercise.id} className="flex items-center">
<input
type="checkbox"
checked={selectedExercises.includes(exercise.id)}
onChange={() => 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"
/>
<span className="ml-2">{exercise.title}</span>
</div>
))}
</div>
<div className="modal-action">
<button onClick={handleSubmit} className="btn bg-gray-800 text-white hover:bg-gray-600">
Add to Routine
</button>
</div>
</div>
</dialog>
);
};

export default ExerciseListModal;
45 changes: 26 additions & 19 deletions frontend/src/views/practitioner/components/ExerciseModal.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -102,13 +109,6 @@ Step 2. Sit down in the chair.
onChange={handleChange}
/>
</div>
{imageString && (
<img
src={imageString}
alt="Selected"
className="max-w-full mb-4 rounded"
/>
)}
<div className="mb-6">
<label htmlFor="image" className="text-gray-800">
Image Demonstration
Expand All @@ -122,6 +122,13 @@ Step 2. Sit down in the chair.
onChange={handleImageChange}
/>
</div>
{imageString && (
<img
src={imageString}
alt="Selected"
className="max-w-full mb-4 rounded"
/>
)}
<div className="flex gap-4">
<button className="btn bg-dark-teal text-white" type="submit">
Submit
Expand Down
18 changes: 12 additions & 6 deletions frontend/src/views/practitioner/components/Exercises.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,11 @@ const Exercises = () => {

fetchData();
}, []);

return (
<div className="w-full p-8">
<div className="flex justify-between">
<h1 className="text-2xl font-semibold mb-4">Exercises</h1>
<h1 className="text-2xl font-semibold">Exercises</h1>
<button
className="btn bg-dark-teal text-white"
onClick={() =>
Expand All @@ -48,11 +49,16 @@ const Exercises = () => {
New Exercise
</button>
</div>
{/* TODO: map each exercise into a EXERCISE CARD HERE */}
<div className="grid">
{exercises.map((exercise, idx) => (
<p key={idx}>{exercise.title}</p>
))}
<div className="w-full bg-gray-50 rounded-lg">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-5 mt-4 p-5">
{exercises.map((exercise) => (
<div key={exercise.id} className="bg-white rounded-lg shadow-md p-4 flex flex-col">
<img src={exercise.image} alt={exercise.title} className="w-80 h-32 sm:h-48 object-fit rounded-t-lg" />
<h2 className="mt-2 font-bold text-lg">{exercise.title}</h2>
<p className="text-gray-600 text-sm mt-1">{exercise.description}</p>
</div>
))}
</div>
</div>
<ExerciseModal />
</div>
Expand Down
89 changes: 79 additions & 10 deletions frontend/src/views/practitioner/components/PatientDetails.jsx
Original file line number Diff line number Diff line change
@@ -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 (
<div className="w-full py-4 px-8">
<div className="w-full py-4 px-8 mt-4">
{patient ? (
<div>
<h1 className="text-4xl font-bold mb-4">{patient.name}</h1>
<div className="flex justify-between w-full text-gray-600 text-xl">
<div className="flex justify-between w-full text-gray-600 text-xl bg-gray-50 rounded-lg pl-2 pr-2">
<p>{patientID}</p>
<p>{patient.age} years old</p>
<p>{patient.email}</p>
<p>Last Login: {patient.lastLogin || "Never"}</p>
</div>
<div className="flex justify-between w-full text-xl font-bold mt-16">
<div className="flex justify-between w-full text-xl font-bold mt-10">
<p>Exercise Routine</p>
<button
className={"btn bg-dark-teal text-white"}
onClick={() => {}}
onClick={toggleModal}
>
<Edit />
Exercises
Add Exercises
</button>
</div>
{/* Display exercises in the patient's routine as cards */}
<div className="bg-gray-50 rounded-lg mt-4">
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-5 p-5">
{patientExercises.length === 0 ? (
<p className="text-gray-600">No exercises in the routine.</p>
) : (
patientExercises.map(exerciseId => {
const exercise = exercises.find(e => e.id === exerciseId);
return exercise && (
<div key={exercise.id} className="bg-white rounded-lg shadow-md p-4 flex flex-col">
<img src={exercise.image} alt={exercise.title} className="w-80 h-32 sm:h-48 object-fit rounded-t-lg" />
<h3 className="mt-2 font-bold text-lg">{exercise.title}</h3>
<p className="text-gray-600 text-sm mt-1">{exercise.description}</p>
</div>
);
})
)}
</div>
</div>
</div>
) : (
<p>Loading patient details...</p>
)}

<ExerciseListModal
exercises={exercises}
onAddExercises={handleAddExercises}
onClose={() => setShowModal(false)}
/>
</div>
);
};
Expand Down
Loading