fix(admin): render medical history with each section's real shape

The medical sections in other are structured objects, not flat strings:
allergies {substance,reaction,severity}, medications {name,dose,frequency},
surgeries {type,year,hospital}, family_history {relation,disease}, disease
{id,name,status}. The admin view printed raw JSON for all but disease.
Give each section a formatter, and for disease show only entries marked
active (status true) instead of the full 30-item checklist.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
hamed
2026-06-15 22:27:42 +03:30
co-authored by Claude Opus 4.8
parent d9c0729fbb
commit a348dcae5f
+20 -10
View File
@@ -53,12 +53,19 @@ interface UserProfileData {
const GENDER_LABELS: Record<string, string> = { male: 'مرد', female: 'زن' };
const MARITAL_LABELS: Record<string, string> = { married: 'متاهل', single: 'مجرد' };
const MEDICAL_SECTIONS: { key: string; label: string }[] = [
{ key: 'allergies', label: 'آلرژی‌ها' },
{ key: 'medications', label: 'داروهای مصرفی' },
{ key: 'surgeries', label: 'جراحی‌ها' },
{ key: 'family_history', label: 'سابقه خانوادگی بیماری' },
{ key: 'disease', label: 'بیماری‌ها' },
// Each medical section stores objects with its own shape; format an item to a label.
const MEDICAL_SECTIONS: {
key: string;
label: string;
format: (item: any) => string;
filter?: (item: any) => boolean;
}[] = [
{ key: 'allergies', label: 'آلرژی‌ها', format: (i) => [i.substance, i.reaction, i.severity].filter(Boolean).join(' — ') },
{ key: 'medications', label: 'داروهای مصرفی', format: (i) => [i.name, i.dose, i.frequency].filter(Boolean).join(' — ') },
{ key: 'surgeries', label: 'جراحی‌ها', format: (i) => [i.type, i.year && `سال ${i.year}`, i.hospital].filter(Boolean).join(' — ') },
{ key: 'family_history', label: 'سابقه خانوادگی بیماری', format: (i) => [i.relation, i.disease].filter(Boolean).join(': ') },
// disease is a fixed checklist; only show the ones marked active
{ key: 'disease', label: 'بیماری‌ها', format: (i) => i.name, filter: (i) => i.status === 'true' || i.status === true },
];
// ── Helpers ───────────────────────────────────────────────────────────────
@@ -548,8 +555,11 @@ export default function UserDetailPage() {
<div className="pt-2 border-t border-slate-100 dark:border-gray-700 space-y-3">
<h3 className="text-sm font-semibold text-slate-700 dark:text-slate-300">سوابق پزشکی</h3>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
{MEDICAL_SECTIONS.map(({ key, label }) => {
const items = Array.isArray(profile.other?.[key]) ? (profile.other![key] as unknown[]) : [];
{MEDICAL_SECTIONS.map(({ key, label, format, filter }) => {
const raw = Array.isArray(profile.other?.[key]) ? (profile.other![key] as any[]) : [];
const items = (filter ? raw.filter(filter) : raw)
.map(format)
.filter((s) => s && s.trim());
return (
<div key={key} className="p-4 rounded-xl bg-slate-50 dark:bg-gray-800/60">
<p className="text-[11px] font-medium text-slate-400 dark:text-slate-500 uppercase tracking-wide mb-1.5">{label}</p>
@@ -557,9 +567,9 @@ export default function UserDetailPage() {
<p className="text-sm text-slate-400 dark:text-slate-500">موردی ثبت نشده</p>
) : (
<ul className="flex flex-wrap gap-1.5">
{items.map((it, i) => (
{items.map((text, i) => (
<li key={i} className="text-xs px-2 py-0.5 rounded-lg bg-white dark:bg-gray-700 text-slate-600 dark:text-slate-300 border border-slate-200 dark:border-gray-600">
{typeof it === 'string' ? it : (it as any)?.name ?? (it as any)?.title ?? JSON.stringify(it)}
{text}
</li>
))}
</ul>