diff --git a/src/App.jsx b/src/App.jsx index f0b44c0..c0f4957 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -119,7 +119,7 @@ function App() { {/* doctor layout */} }> } /> - } /> + {/* } /> */} } /> } /> } /> diff --git a/src/assets/logo-doctor.png b/src/assets/logo-doctor.png new file mode 100644 index 0000000..dec903a Binary files /dev/null and b/src/assets/logo-doctor.png differ diff --git a/src/assets/logo-sidebar-white.png b/src/assets/logo-sidebar-white.png new file mode 100644 index 0000000..50614f4 Binary files /dev/null and b/src/assets/logo-sidebar-white.png differ diff --git a/src/components/doctor/Dashboard/ChartAreaAgeGender.jsx b/src/components/doctor/Dashboard/ChartAreaAgeGender.jsx index 2b898bf..56d38fe 100644 --- a/src/components/doctor/Dashboard/ChartAreaAgeGender.jsx +++ b/src/components/doctor/Dashboard/ChartAreaAgeGender.jsx @@ -10,8 +10,7 @@ import { YAxis, ResponsiveContainer, } from "recharts" -import { fetchAllPatients, fetchShowPatientById } from "@/store/slices/patientSlice" - +import { fetchShowPatientById } from "@/store/slices/patientSlice" import { Card, CardHeader, @@ -24,7 +23,11 @@ import { ChartTooltip, ChartTooltipContent, } from "@/components/ui/chart" -import { selectAllAppointments, selectAllPatients, selectPatientsLoading, selectShowPatientById } from "@/store/selectors" +import { + selectAllAppointments, + selectShowPatientById, + selectPatientsLoading, +} from "@/store/selectors" import { fetchAppointments } from "@/store/slices/appointmentSlice" const calculateAge = (dob) => { @@ -39,99 +42,98 @@ const calculateAge = (dob) => { } const getAgeGroup = (age) => { - if (age < 18) return "0-17" - if (age < 30) return "18-29" - if (age < 45) return "30-44" - if (age < 60) return "45-59" - return "60+" + if (age < 10) return "0-9" + if (age < 20) return "10-19" + if (age < 30) return "20-29" + if (age < 40) return "30-39" + if (age < 50) return "40-49" + if (age < 60) return "50-59" + if (age < 70) return "60-69" + return "70+" } export default function ChartAreaAgeGender() { -const [fetchedPatients, setFetchedPatients] = useState({}); -const dispatch = useDispatch(); -const Appointments = useSelector(selectAllAppointments); -const currentPatient = useSelector(selectShowPatientById); // This is a single patient object -const loading = useSelector(selectPatientsLoading); - -// Memoize unique patient IDs from appointments (adjusted for API structure) -const uniquePatientIds = useMemo(() => { - return [...new Set( - Appointments - .map(a => a.patientId?._id || a.patientId) // Handle both object and string formats - .filter(Boolean) // Remove null/undefined values - )]; -}, [Appointments]); - -// Store the current patient when it's fetched -useEffect(() => { - if (currentPatient && currentPatient._id) { - setFetchedPatients(prev => ({ - ...prev, - [currentPatient._id]: currentPatient - })); - } -}, [currentPatient]); - -// Fetch patients individually based on appointment data -useEffect(() => { - if (uniquePatientIds.length > 0) { - uniquePatientIds.forEach(id => { - if (!fetchedPatients[id]) { - dispatch(fetchShowPatientById(id)); - } - }); - } -}, [dispatch, uniquePatientIds, fetchedPatients]); - -// Fetch appointments once -useEffect(() => { - dispatch(fetchAppointments()); -}, [dispatch]); - -// Get patient list from the fetchedPatients -const patients = useMemo(() => { - console.log('Chart - fetchedPatients content:', fetchedPatients); - console.log('Chart - uniquePatientIds:', uniquePatientIds); - - const result = uniquePatientIds.map(id => fetchedPatients[id]).filter(Boolean); - console.log('Chart - Patients result:', result); - return result; -}, [fetchedPatients, uniquePatientIds]); - -// Check if we're still loading any patients -const isLoading = loading || (uniquePatientIds.length > 0 && uniquePatientIds.some(id => !fetchedPatients[id])); - -// Chart Data -const chartData = useMemo(() => { - const dataMap = {}; - - patients.forEach((patient) => { - const age = calculateAge(patient.dateOfBirth); - const ageGroup = getAgeGroup(age); - const gender = patient.gender?.toLowerCase(); - - if (!dataMap[ageGroup]) { - dataMap[ageGroup] = { male: 0, female: 0 }; + const [fetchedPatients, setFetchedPatients] = useState({}) + const dispatch = useDispatch() + const Appointments = useSelector(selectAllAppointments) + const currentPatient = useSelector(selectShowPatientById) + const loading = useSelector(selectPatientsLoading) + + const uniquePatientIds = useMemo(() => { + return [ + ...new Set( + Appointments.map((a) => a.patientId?._id || a.patientId).filter(Boolean) + ), + ] + }, [Appointments]) + + useEffect(() => { + if (currentPatient && currentPatient._id) { + setFetchedPatients((prev) => ({ + ...prev, + [currentPatient._id]: currentPatient, + })) + } + }, [currentPatient]) + + useEffect(() => { + if (uniquePatientIds.length > 0) { + uniquePatientIds.forEach((id) => { + if (!fetchedPatients[id]) { + dispatch(fetchShowPatientById(id)) + } + }) } + }, [dispatch, uniquePatientIds, fetchedPatients]) + + useEffect(() => { + dispatch(fetchAppointments()) + }, [dispatch]) - if (gender === "male") dataMap[ageGroup].male++; - else if (gender === "female") dataMap[ageGroup].female++; - }); + const patients = useMemo(() => { + return uniquePatientIds.map((id) => fetchedPatients[id]).filter(Boolean) + }, [fetchedPatients, uniquePatientIds]) - return Object.entries(dataMap).map(([ageGroup, counts]) => ({ - ageGroup, - ...counts, - })); -}, [patients]); + const isLoading = + loading || + (uniquePatientIds.length > 0 && + uniquePatientIds.some((id) => !fetchedPatients[id])) + + const chartData = useMemo(() => { + const dataMap = {} + + patients.forEach((patient) => { + const age = calculateAge(patient.dateOfBirth) + const ageGroup = getAgeGroup(age) + const gender = patient.gender?.toLowerCase() + + if (!dataMap[ageGroup]) { + dataMap[ageGroup] = { male: 0, female: 0 } + } + + if (gender === "male") dataMap[ageGroup].male++ + else if (gender === "female") dataMap[ageGroup].female++ + }) + + return Object.entries(dataMap) + .sort((a, b) => { + const parseMin = (label) => parseInt(label.split("-")[0]) || 70 + return parseMin(a[0]) - parseMin(b[0]) + }) + .map(([ageGroup, counts]) => ({ + ageGroup, + ...counts, + })) + }, [patients]) const chartConfig = { male: { label: "Male", - color: "#3b82f6", // blue + color: "#3b82f6", }, female: { label: "Female", - color: "#ec4899", // pink + color: "#ec4899", }, } @@ -141,7 +143,9 @@ const chartData = useMemo(() => { Patient Age & Gender Distribution - Loading patients... ({uniquePatientIds.length} patients to fetch) + + Loading patients... ({uniquePatientIds.length} patients to fetch) + ) } @@ -204,4 +208,4 @@ const chartData = useMemo(() => { ) -} \ No newline at end of file +} diff --git a/src/components/doctor/Dashboard/DiagnosisChart.jsx b/src/components/doctor/Dashboard/DiagnosisChart.jsx index 43b227c..37da889 100644 --- a/src/components/doctor/Dashboard/DiagnosisChart.jsx +++ b/src/components/doctor/Dashboard/DiagnosisChart.jsx @@ -1,6 +1,5 @@ import { selectAllAppointments, - selectPatientsLoading, selectShowPatientById, } from "@/store/selectors"; import { fetchAppointments } from "@/store/slices/appointmentSlice"; @@ -62,20 +61,20 @@ const DiagnosisChart = () => { const dispatch = useDispatch(); const [fetchedPatients, setFetchedPatients] = useState({}); const [diagnosisMap, setDiagnosisMap] = useState({}); - const [isDiagnosisLoading, setIsDiagnosisLoading] = useState(true); const [diagnosisError, setDiagnosisError] = useState(null); const diagnosisFetchedRef = useRef(new Set()); const appointments = useSelector(selectAllAppointments); const currentPatient = useSelector(selectShowPatientById); - const patientsLoading = useSelector(selectPatientsLoading); const uniquePatientIds = useMemo(() => { - return [...new Set( - appointments - .map((a) => a.patientId?._id || a.patientId) - .filter(Boolean) - )]; + return [ + ...new Set( + appointments + .map((a) => a.patientId?._id || a.patientId) + .filter(Boolean) + ), + ]; }, [appointments]); useEffect(() => { @@ -105,17 +104,10 @@ const DiagnosisChart = () => { return uniquePatientIds.map((id) => fetchedPatients[id]).filter(Boolean); }, [fetchedPatients, uniquePatientIds]); - const isLoadingPatients = - patientsLoading || - (uniquePatientIds.length > 0 && - uniquePatientIds.some((id) => !fetchedPatients[id])); - useEffect(() => { const fetchDiagnoses = async () => { try { - setIsDiagnosisLoading(true); const newDiagnosisMap = {}; - for (const patient of patients) { if (!diagnosisFetchedRef.current.has(patient._id)) { const result = await getAllDiagnosis(patient._id); @@ -123,19 +115,16 @@ const DiagnosisChart = () => { diagnosisFetchedRef.current.add(patient._id); } } - setDiagnosisMap((prev) => ({ ...prev, ...newDiagnosisMap })); } catch (err) { setDiagnosisError(err.message || "Failed to fetch diagnosis"); - } finally { - setIsDiagnosisLoading(false); } }; - if (patients.length > 0 && !isLoadingPatients) { + if (patients.length > 0) { fetchDiagnoses(); } - }, [patients, isLoadingPatients]); + }, [patients]); const chartData = useMemo(() => { const counts = {}; @@ -149,6 +138,14 @@ const DiagnosisChart = () => { return Object.entries(counts).map(([name, value]) => ({ name, value })); }, [diagnosisMap]); + const allDiagnosesEmpty = useMemo(() => { + return Object.values(diagnosisMap).every((d) => d.length === 0); + }, [diagnosisMap]); + + const noDiagnosisPatients = useMemo(() => { + return patients.filter((p) => (diagnosisMap[p._id]?.length || 0) === 0); + }, [patients, diagnosisMap]); + const renderCardContent = (content) => (

Average Diagnoses

@@ -156,20 +153,6 @@ const DiagnosisChart = () => {
); - if (isLoadingPatients || (isDiagnosisLoading && chartData.length === 0)) { - return ( -
- {renderCardContent( -

- {isLoadingPatients - ? `Loading patients... (${uniquePatientIds.length} patients to fetch)` - : "Loading diagnoses..."} -

- )} -
- ); - } - if (diagnosisError) { return (
@@ -188,10 +171,21 @@ const DiagnosisChart = () => { ); } - if (chartData.length === 0) { + if (chartData.length === 0 || allDiagnosesEmpty) { return (
- {renderCardContent(

No diagnosis data available

)} + {renderCardContent( + <> +

No diagnosis data available for any patients.

+ {noDiagnosisPatients.length > 0 && ( +
    + {noDiagnosisPatients.map((p) => ( +
  • โ€ข {p.name}
  • + ))} +
+ )} + + )}
); } diff --git a/src/components/doctor/Dashboard/StatCards.jsx b/src/components/doctor/Dashboard/StatCards.jsx index b0a0a95..73a9b10 100644 --- a/src/components/doctor/Dashboard/StatCards.jsx +++ b/src/components/doctor/Dashboard/StatCards.jsx @@ -6,23 +6,39 @@ import { fetchShowPatientById } from "@/store/slices/patientSlice"; import { fetchAppointments } from "@/store/slices/appointmentSlice"; import { selectAllAppointments, selectShowPatientById, selectPatientsLoading } from "@/store/selectors"; +// Helper function to calculate percentage change +const calculateTrend = (current, previous) => { + if (previous === 0) { + return current > 0 ? "+100%" : "0%"; + } + + const percentChange = ((current - previous) / previous) * 100; + const sign = percentChange >= 0 ? "+" : ""; + return `${sign}${Math.round(percentChange)}%`; +}; + +// Helper function to determine trend direction +const getTrendDirection = (trendString) => { + return trendString.startsWith("+") || trendString === "0%" ? "up" : "down"; +}; + export const StatCards = () => { const [fetchedPatients, setFetchedPatients] = useState({}); const dispatch = useDispatch(); // Use the same selectors as other components - const Appointments = useSelector(selectAllAppointments); + const appointments = useSelector(selectAllAppointments); const currentPatient = useSelector(selectShowPatientById); const loading = useSelector(selectPatientsLoading); // Memoize unique patient IDs from appointments const uniquePatientIds = useMemo(() => { return [...new Set( - Appointments + appointments .map(a => a.patientId?._id || a.patientId) .filter(Boolean) )]; - }, [Appointments]); + }, [appointments]); // Store the current patient when it's fetched useEffect(() => { @@ -56,62 +72,124 @@ export const StatCards = () => { }, [fetchedPatients, uniquePatientIds]); // Calculate date ranges - const today = new Date(); - const todaydate = `to ${today.toLocaleDateString()}`; - const weekAgo = new Date(); - weekAgo.setDate(today.getDate() - 7); - const weekAgoDate = weekAgo.toLocaleDateString(); - const weekperiod = `${weekAgoDate} ${todaydate}`; - - // Calculate patients registered this week - const patientsThisWeek = useMemo(() => { - return patients.filter(patient => { + const { today, weekAgo, previousWeekStart, todayDate, weekPeriod } = useMemo(() => { + const today = new Date(); + const weekAgo = new Date(); + weekAgo.setDate(today.getDate() - 7); + + const previousWeekStart = new Date(); + previousWeekStart.setDate(today.getDate() - 14); + + return { + today, + weekAgo, + previousWeekStart, + todayDate: `to ${today.toLocaleDateString()}`, + weekPeriod: `${weekAgo.toLocaleDateString()} to ${today.toLocaleDateString()}` + }; + }, []); + + // Calculate metrics with proper trend analysis + const metrics = useMemo(() => { + // Debug logging + console.log('Debug - patients:', patients); + console.log('Debug - appointments:', appointments); + console.log('Debug - patients length:', patients?.length); + console.log('Debug - appointments length:', appointments?.length); + + if (!patients || !appointments || patients.length === 0 || appointments.length === 0) { + console.log('Debug - Missing data, returning zeros'); + return { + totalPatients: uniquePatientIds?.length || 0, + patientsThisWeek: 0, + patientsTrend: "0%", + totalAppointments: appointments?.length || 0, + appointmentsThisWeek: 0, + appointmentsTrend: "0%" + }; + } + + // Calculate patients registered this week + const patientsThisWeek = patients.filter(patient => { const createdDate = new Date(patient.createdAt); return createdDate >= weekAgo && createdDate <= today; }).length; - }, [patients, weekAgo, today]); - // Calculate appointments this week - const appointmentsThisWeek = useMemo(() => { - return Appointments.filter(appointment => { + // Calculate patients registered previous week for trend + const patientsPreviousWeek = patients.filter(patient => { + const createdDate = new Date(patient.createdAt); + return createdDate >= previousWeekStart && createdDate < weekAgo; + }).length; + + // Calculate appointments this week + const appointmentsThisWeek = appointments.filter(appointment => { const appointmentDate = new Date(appointment.createdAt || appointment.date); return appointmentDate >= weekAgo && appointmentDate <= today; }).length; - }, [Appointments, weekAgo, today]); - // Calculate trends (you can implement more sophisticated logic here) - const patientsTrend = patientsThisWeek > 0 ? "+100%" : "0%"; - const appointmentsTrend = appointmentsThisWeek > 0 ? "+100%" : "0%"; + // Calculate appointments previous week for trend + const appointmentsPreviousWeek = appointments.filter(appointment => { + const appointmentDate = new Date(appointment.createdAt || appointment.date); + return appointmentDate >= previousWeekStart && appointmentDate < weekAgo; + }).length; + + // Calculate trends + const patientsTrend = calculateTrend(patientsThisWeek, patientsPreviousWeek); + const appointmentsTrend = calculateTrend(appointmentsThisWeek, appointmentsPreviousWeek); + + return { + totalPatients: uniquePatientIds.length, + patientsThisWeek, + patientsTrend, + totalAppointments: appointments.length, + appointmentsThisWeek, + appointmentsTrend + }; + }, [patients, appointments, weekAgo, today, previousWeekStart]); + + if (loading) { + return ( + <> + {[...Array(4)].map((_, i) => ( +
+
+
+
+
+ ))} + + ); + } return ( <> 0 ? "+100%" : "0%"} - trend={patientsThisWeek > 0 ? "up" : "down"} - period={weekperiod} + value={metrics.patientsThisWeek} + pilltext={metrics.patientsTrend} + trend={getTrendDirection(metrics.patientsTrend)} + period={weekPeriod} /> 0 ? "+100%" : "0%"} - trend={appointmentsThisWeek > 0 ? "up" : "down"} - period={weekperiod} + value={metrics.appointmentsThisWeek} + pilltext={metrics.appointmentsTrend} + trend={getTrendDirection(metrics.appointmentsTrend)} + period={weekPeriod} /> ); diff --git a/src/components/doctor/Dashboard/Topbar.jsx b/src/components/doctor/Dashboard/Topbar.jsx index 6ef58c5..27ea992 100644 --- a/src/components/doctor/Dashboard/Topbar.jsx +++ b/src/components/doctor/Dashboard/Topbar.jsx @@ -73,7 +73,7 @@ export const Topbar = ({ isCollapsed, setIsCollapsed }) => { onClick={() => setIsCollapsed(!isCollapsed)} > diff --git a/src/components/doctor/Diagnosis/AddDignosisForm.jsx b/src/components/doctor/Diagnosis/AddDignosisForm.jsx index eaa53fc..fff54bc 100644 --- a/src/components/doctor/Diagnosis/AddDignosisForm.jsx +++ b/src/components/doctor/Diagnosis/AddDignosisForm.jsx @@ -146,12 +146,12 @@ export const AddDiagnosisForm = ({ value={symptomInput} onChange={(e) => setSymptomInput(e.target.value)} placeholder="e.g., Headache" - className="flex-1 px-4 py-2 border border-mebeige rounded-lg focus:outline-none focus:ring-2 focus:ring-megreen" + className="flex-1 px-4 py-2 border border-mebeige rounded-lg focus:outline-none focus:ring-2 focus:ring-[#007eb1]" /> @@ -198,7 +198,7 @@ export const AddDiagnosisForm = ({ value={recommendations} onChange={(e) => setRecommendations(e.target.value)} placeholder="e.g., avoid junk food" - className="w-full px-4 py-2 border border-mebeige rounded-lg focus:outline-none focus:ring-2 focus:ring-meyellow" + className="w-full px-4 py-2 border border-mebeige rounded-lg focus:outline-none focus:ring-2 focus:ring-menavy" />
@@ -210,7 +210,7 @@ export const AddDiagnosisForm = ({ value={followUp} onChange={(e) => setFollowUp(e.target.value)} placeholder="e.g., Next Sunday" - className="w-full px-4 py-2 border border-mebeige rounded-lg focus:outline-none focus:ring-2 focus:ring-meyellow" + className="w-full px-4 py-2 border border-mebeige rounded-lg focus:outline-none focus:ring-2 focus:ring-menavy" /> @@ -222,7 +222,7 @@ export const AddDiagnosisForm = ({ onChange={(e) => setNotes(e.target.value)} placeholder="Additional notes or observations" rows={3} - className="w-full px-4 py-2 border border-mebeige rounded-lg resize-none focus:outline-none focus:ring-2 focus:ring-mepale" + className="w-full px-4 py-2 border border-mebeige rounded-lg resize-none focus:outline-none focus:ring-2 focus:ring-menavy" /> diff --git a/src/components/doctor/Patients/Patients_List.jsx b/src/components/doctor/Patients/Patients_List.jsx index 6c2fdae..f9c5948 100644 --- a/src/components/doctor/Patients/Patients_List.jsx +++ b/src/components/doctor/Patients/Patients_List.jsx @@ -4,7 +4,11 @@ import { Card, CardContent } from "@/components/ui/card"; import { Avatar, AvatarImage, AvatarFallback } from "@/components/ui/avatar"; import { fetchShowPatientById } from "@/store/slices/patientSlice"; import { fetchAppointments } from "@/store/slices/appointmentSlice"; -import { selectAllAppointments, selectShowPatientById, selectPatientsLoading } from "@/store/selectors"; +import { + selectAllAppointments, + selectShowPatientById, + selectPatientsLoading, +} from "@/store/selectors"; const fallbackPatients = [ { @@ -39,88 +43,102 @@ const fallbackPatients = [ phone: "+201098765432", }, }, - { - _id: "fallback-3", - name: "Nour Khaled", - gender: "Female", - dateOfBirth: "2001-12-05", - email: "nour.khaled@example.com", - phone: "+201112223344", - city: "Giza", - country: "Egypt", - createdAt: "2024-01-20T09:45:00Z", - emergencyContact: { - name: "Khaled Youssef", - relationship: "Father", - phone: "+201234001122", - }, - }, ]; export const Patients_List = ({ onPatientSelect, sortBy }) => { const [selectedPatientId, setSelectedPatientId] = useState(null); const [fetchedPatients, setFetchedPatients] = useState({}); + const [fetchedPatientIds, setFetchedPatientIds] = useState(new Set()); + const dispatch = useDispatch(); - - // Use the same selectors as the chart - const Appointments = useSelector(selectAllAppointments); - const currentPatient = useSelector(selectShowPatientById); // This is a single patient object + const appointments = useSelector(selectAllAppointments); const loading = useSelector(selectPatientsLoading); - // Memoize unique patient IDs from appointments (adjusted for API structure) + // Extract unique patient IDs const uniquePatientIds = useMemo(() => { - return [...new Set( - Appointments - .map(a => a.patientId?._id || a.patientId) // Handle both object and string formats - .filter(Boolean) // Remove null/undefined values - )]; - }, [Appointments]); - - // Fetch appointments once (same as chart) + const ids = [ + ...new Set( + appointments + .map((a) => (a.patientId?._id || a.patientId)) + .filter(Boolean) + ), + ]; + console.log("โœ… Unique patient IDs from appointments:", ids); + return ids; + }, [appointments]); + + // Fetch appointments on mount useEffect(() => { dispatch(fetchAppointments()); }, [dispatch]); - // Store the current patient when it's fetched - useEffect(() => { - if (currentPatient && currentPatient._id) { - setFetchedPatients(prev => ({ - ...prev, - [currentPatient._id]: currentPatient - })); + // Fetch missing patients + const fetchMissingPatients = async () => { + console.log("๐Ÿ” Starting patient fetch loop"); + + for (const id of uniquePatientIds) { + if (!fetchedPatientIds.has(id) && !fetchedPatients[id]) { + console.log(`โžก๏ธ Fetching patient with ID: ${id}`); + + try { + const resultAction = await dispatch(fetchShowPatientById(id)); + console.log("๐Ÿงพ Result Action:", resultAction); + + if (fetchShowPatientById.fulfilled.match(resultAction)) { + const payload = resultAction.payload; + + if (!payload) { + console.error("โŒ No payload returned for patient ID:", id); + continue; + } + + const patient = payload?.data || payload; + + if (patient && patient._id) { + console.log("โœ… Patient fetched:", patient); + setFetchedPatients((prev) => ({ + ...prev, + [patient._id]: patient, + })); + setFetchedPatientIds((prev) => new Set([...prev, id])); + } else { + console.warn("โš ๏ธ Invalid patient structure:", payload); + } + } else { + console.error("โŒ fetchShowPatientById thunk was rejected:", resultAction); + } + } catch (err) { + console.error("โŒ Exception during patient fetch:", err); + } + } else { + console.log(`โฉ Already fetched ID: ${id}`); + } } - }, [currentPatient]); + }; - // Fetch patients individually based on appointment data + // Trigger fetch useEffect(() => { if (uniquePatientIds.length > 0) { - uniquePatientIds.forEach(id => { - if (!fetchedPatients[id]) { - dispatch(fetchShowPatientById(id)); - } - }); + fetchMissingPatients(); } - }, [dispatch, uniquePatientIds, fetchedPatients]); + }, [uniquePatientIds]); - // Get patient list from the fetchedPatients + // Construct the patient list from fetched data const patients = useMemo(() => { - console.log('fetchedPatients content:', fetchedPatients); - console.log('uniquePatientIds:', uniquePatientIds); - - const result = uniquePatientIds.map(id => fetchedPatients[id]).filter(Boolean); - console.log('Patients result:', result); + const result = uniquePatientIds.map((id) => fetchedPatients[id]).filter(Boolean); + console.log("๐Ÿ“‹ Current patients to render:", result); return result; }, [fetchedPatients, uniquePatientIds]); - // Check if we're still loading any patients - const isLoading = loading || (uniquePatientIds.length > 0 && uniquePatientIds.some(id => !fetchedPatients[id])); + const isLoading = + loading || + (uniquePatientIds.length > 0 && patients.length < uniquePatientIds.length); const handlePatientClick = (patient) => { setSelectedPatientId(patient._id); onPatientSelect(patient); }; - // Use patients from store if available, otherwise fallback const patientsToDisplay = patients.length > 0 ? patients : fallbackPatients; const sortedPatients = [...patientsToDisplay].sort((a, b) => { @@ -136,20 +154,20 @@ export const Patients_List = ({ onPatientSelect, sortBy }) => { } }); - // Show loading state if we're fetching patients if (isLoading && patients.length === 0 && uniquePatientIds.length > 0) { return (
-

Loading patients... ({uniquePatientIds.length} patients to fetch)

+

+ Fetched: {patients.length} / {uniquePatientIds.length} +

); } - // Show message if no appointments found if (uniquePatientIds.length === 0) { return (
@@ -191,4 +209,4 @@ export const Patients_List = ({ onPatientSelect, sortBy }) => { ))}
); -}; \ No newline at end of file +}; diff --git a/src/components/doctor/Patients/Patients_Main.jsx b/src/components/doctor/Patients/Patients_Main.jsx index e44fc3b..4f646a8 100644 --- a/src/components/doctor/Patients/Patients_Main.jsx +++ b/src/components/doctor/Patients/Patients_Main.jsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from "react"; +import React, { useEffect, useMemo, useState } from "react"; import { useDispatch, useSelector } from "react-redux"; import { useNavigate } from "react-router-dom"; import { @@ -14,6 +14,9 @@ import { Card, CardContent } from "@/components/ui/card"; import { fetchAllPatients } from "@/store/slices/patientSlice"; import { fetchAppointments } from "@/store/slices/appointmentSlice"; import { getAllDiagnosis } from "@/services/diagnosisApi"; +import { handleNameRoute } from "@/utils/urlHelpers"; +import { selectMyDetails } from "@/store/selectors"; +import { fetchMYData } from "@/store/slices/userSlice"; export const Patients_Main = ({ selectedPatient, patientsList }) => { const dispatch = useDispatch(); @@ -34,6 +37,17 @@ export const Patients_Main = ({ selectedPatient, patientsList }) => { const patient = selectedPatient; const patientId = patient?._id; + const myDetails = useSelector(selectMyDetails); + + + + useEffect(() => { + dispatch(fetchMYData()); + }, [dispatch]); + + const doctorSlug = useMemo(() => { + return myDetails?.name ? handleNameRoute(myDetails.name) : ""; + }, [myDetails]); // Fetch all patients and appointments on mount useEffect(() => { @@ -118,7 +132,9 @@ export const Patients_Main = ({ selectedPatient, patientsList }) => { value={gender} /> } + icon={ + + } label="City" value={city} /> @@ -164,7 +180,9 @@ export const Patients_Main = ({ selectedPatient, patientsList }) => {