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 }) => {