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:
@@ -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>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user