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
+5 -5
View File
@@ -66,7 +66,7 @@ const PAY_LABEL: Record<string, string> = {
pending: 'در انتظار', received: 'موفق', canceled: 'لغو شده', refund: 'استرداد',
};
const PAY_COLOR: Record<string, string> = {
pending: '#f59e0b', received: '#22c55e', canceled: '#ef4444', refund: '#3b82f6',
pending: 'var(--warning)', received: 'var(--success)', canceled: 'var(--danger)', refund: 'var(--info)',
};
const PAY_CLS: Record<string, string> = {
pending: 'amber', received: 'green', canceled: 'red', refund: 'blue',
@@ -373,7 +373,7 @@ function AdminDashboard() {
const revSeries = useMemo(() => charts?.revenue_by_day?.map(d => d.amount_rials) ?? [], [charts]);
const donutData = useMemo(() =>
(charts?.appointment_status ?? []).slice(0, 7).map(s => ({
label: APPT_LABEL[s.status] ?? s.status, value: s.count, color: APPT_COLOR[s.status] ?? '#94a3b8',
label: APPT_LABEL[s.status] ?? s.status, value: s.count, color: APPT_COLOR[s.status] ?? 'var(--text-3)',
})), [charts]);
const hbarsData = useMemo(() => (charts?.top_specialties ?? []).map(s => ({ label: s.name, value: s.count })), [charts]);
@@ -400,13 +400,13 @@ function AdminDashboard() {
if (!recent) return [];
const evs: { title: string; sub: string; time: string; color: string }[] = [];
(recent.appointments ?? []).slice(0, 4).forEach(a => {
evs.push({ title: `نوبت ${APPT_LABEL[a.status] ?? a.status}`, sub: `${a.user_name || a.user_mobile} · ${a.doctor_name}`, time: a.created_at, color: APPT_COLOR[a.status] ?? '#94a3b8' });
evs.push({ title: `نوبت ${APPT_LABEL[a.status] ?? a.status}`, sub: `${a.user_name || a.user_mobile} · ${a.doctor_name}`, time: a.created_at, color: APPT_COLOR[a.status] ?? 'var(--text-3)' });
});
(recent.payments ?? []).slice(0, 3).forEach(p => {
evs.push({ title: `پرداخت ${PAY_LABEL[p.status] ?? p.status}`, sub: `${p.user_name || p.user_mobile} · ${formatRial(p.amount)}`, time: p.created_at, color: PAY_COLOR[p.status] ?? '#94a3b8' });
evs.push({ title: `پرداخت ${PAY_LABEL[p.status] ?? p.status}`, sub: `${p.user_name || p.user_mobile} · ${formatRial(p.amount)}`, time: p.created_at, color: PAY_COLOR[p.status] ?? 'var(--text-3)' });
});
(recent.users ?? []).slice(0, 3).forEach(u => {
evs.push({ title: 'ثبت‌نام کاربر جدید', sub: u.name || u.mobile, time: u.created_at, color: '#8b5cf6' });
evs.push({ title: 'ثبت‌نام کاربر جدید', sub: u.name || u.mobile, time: u.created_at, color: 'var(--violet)' });
});
return evs.sort((a, b) => new Date(b.time).getTime() - new Date(a.time).getTime()).slice(0, 8);
}, [recent]);