Implement comprehensive dark/light mode overhaul for admin panel

- Refactor color palette in `ui-design-spec.md` to utilize CSS variables exclusively, eliminating fixed hex values and Tailwind utility classes.
- Complete dark mode implementation in `uiStore.ts`, ensuring proper theme application via `applyTheme()` and `applyBrand()`.
- Create `admin-theme-dark-light-audit.md` to document the transition process, outlining issues with inline styles and fixed colors.
- Introduce `theme-tokens.test.ts` to enforce rules against fixed hex colors and ensure compliance with the design system.
- Update various components and styles to replace inline styles and fixed colors with CSS variables, ensuring consistent theming across light and dark modes.
- Ensure all changes maintain visual integrity in both light and dark modes, with a focus on accessibility and contrast standards.
This commit is contained in:
hamed
2026-07-27 16:41:52 +03:30
parent c29035c21e
commit 55ab2f5dfc
73 changed files with 1485 additions and 1110 deletions
+17 -17
View File
@@ -123,7 +123,7 @@ export default function AppointmentDetailPage() {
]}
action={
<button onClick={() => navigate(backTo)}
className="flex items-center gap-2 text-sm text-slate-500 dark:text-slate-400 hover:text-slate-800 dark:hover:text-slate-100 transition-colors">
className="flex items-center gap-2 text-sm text-[var(--text-2)] hover:text-[var(--text)] transition-colors">
<ArrowRightIcon className="w-4 h-4" />
بازگشت
</button>
@@ -138,8 +138,8 @@ export default function AppointmentDetailPage() {
</div>
) : appt ? (
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
<div className="bg-white rounded-2xl border border-gray-100 shadow-sm p-6">
<h3 className="font-semibold text-gray-800 mb-4">اطلاعات بیمار</h3>
<div className="bg-[var(--surface)] rounded-2xl border border-[var(--border)] shadow-sm p-6">
<h3 className="font-semibold text-[var(--text)] mb-4">اطلاعات بیمار</h3>
<InfoRow label="نام بیمار" value={appt.patient_name} />
<InfoRow label="موبایل" value={<span dir="ltr">{appt.patient_mobile}</span>} />
<InfoRow label="پزشک" value={appt.doctor?.name ?? null} />
@@ -151,10 +151,10 @@ export default function AppointmentDetailPage() {
<InfoRow label="تاریخ ثبت" value={formatDateTime(appt.created_at)} />
</div>
<div className="bg-white rounded-2xl border border-gray-100 shadow-sm p-6">
<h3 className="font-semibold text-gray-800 mb-4">وضعیت و اقدامات</h3>
<div className="bg-[var(--surface)] rounded-2xl border border-[var(--border)] shadow-sm p-6">
<h3 className="font-semibold text-[var(--text)] mb-4">وضعیت و اقدامات</h3>
<div className="mb-4">
<p className="text-sm text-gray-500 mb-2">وضعیت فعلی:</p>
<p className="text-sm text-[var(--text-2)] mb-2">وضعیت فعلی:</p>
<StatusBadge type="appointment" value={appt.status} />
</div>
@@ -189,37 +189,37 @@ export default function AppointmentDetailPage() {
</div>
</div>
<div className="mt-4 pt-4 border-t border-gray-100">
<div className="mt-4 pt-4 border-t border-[var(--border)]">
<button
onClick={() => setCancelOpen(true)}
className="w-full py-2 border border-red-300 text-red-600 text-sm rounded-[10px] hover:bg-red-50 transition-colors"
className="w-full py-2 border border-[var(--danger)] text-[var(--danger)] text-sm rounded-[10px] hover:bg-[var(--danger-bg)] transition-colors"
>
لغو نوبت
</button>
</div>
</div>
<div className="bg-white rounded-2xl border border-gray-100 shadow-sm p-6 lg:col-span-2">
<h3 className="font-semibold text-gray-800 mb-4">تاریخچه رویدادها</h3>
<div className="bg-[var(--surface)] rounded-2xl border border-[var(--border)] shadow-sm p-6 lg:col-span-2">
<h3 className="font-semibold text-[var(--text)] mb-4">تاریخچه رویدادها</h3>
{eventsQuery.isLoading ? (
<div className="h-6 w-40 rounded skeleton" />
) : events.length === 0 ? (
<p className="text-sm text-gray-400">رویدادی برای این نوبت ثبت نشده است.</p>
<p className="text-sm text-[var(--text-3)]">رویدادی برای این نوبت ثبت نشده است.</p>
) : (
<ol className="space-y-4">
{events.map((ev, i) => (
<li key={i} className="flex gap-3">
<span className="mt-1.5 w-2.5 h-2.5 rounded-full bg-red-500 shrink-0" />
<span className="mt-1.5 w-2.5 h-2.5 rounded-full bg-[var(--danger)] shrink-0" />
<div className="flex-1">
<div className="flex items-center justify-between gap-2">
<span className="text-sm font-medium text-gray-800">{ev.title}</span>
<span className="text-xs text-gray-400">{formatDateTime(ev.created_at)}</span>
<span className="text-sm font-medium text-[var(--text)]">{ev.title}</span>
<span className="text-xs text-[var(--text-3)]">{formatDateTime(ev.created_at)}</span>
</div>
{ev.actor_name && (
<div className="text-xs text-gray-500 mt-0.5">توسط: {ev.actor_name}</div>
<div className="text-xs text-[var(--text-2)] mt-0.5">توسط: {ev.actor_name}</div>
)}
{ev.reason && (
<div className="text-xs text-gray-600 mt-0.5">دلیل: {ev.reason}</div>
<div className="text-xs text-[var(--text-2)] mt-0.5">دلیل: {ev.reason}</div>
)}
</div>
</li>
@@ -229,7 +229,7 @@ export default function AppointmentDetailPage() {
</div>
</div>
) : (
<div className="bg-white rounded-2xl border border-gray-100 p-16 text-center text-gray-400">
<div className="bg-[var(--surface)] rounded-2xl border border-[var(--border)] p-16 text-center text-[var(--text-3)]">
نوبتی یافت نشد
</div>
)}