Files
clinicpro/assets/admin/pages/SelectContextPage.tsx
T
hamed 55ab2f5dfc 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.
2026-07-27 16:41:52 +03:30

93 lines
3.5 KiB
TypeScript

import { useNavigate } from 'react-router-dom';
import { useState } from 'react';
import { useAuthStore, ContextItem } from '../stores/authStore';
const ROLE_LABELS: Record<string, string> = {
admin: 'مدیر کل',
clinic: 'مالک کلینیک',
doctor: 'پزشک',
secretary: 'منشی',
user: 'کاربر',
};
const TYPE_ICONS: Record<string, string> = {
doctor: '🏥',
clinic: '🏢',
};
export default function SelectContextPage() {
const { availableContexts, switchContext } = useAuthStore();
const navigate = useNavigate();
const [loading, setLoading] = useState<string | null>(null);
const handleSelect = async (ctx: ContextItem) => {
setLoading(ctx.db_uuid);
await switchContext(ctx.db_uuid);
navigate('/admin/dashboard', { replace: true });
};
return (
<div style={{
minHeight: '100vh',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
background: 'var(--surface-alt, #f4f6f9)',
padding: '2rem',
}}>
<div style={{ width: '100%', maxWidth: 480 }}>
<div className="card card-pad" style={{ textAlign: 'center' }}>
<h2 style={{ marginBottom: '.25rem', fontSize: '1.25rem', fontWeight: 600 }}>
انتخاب محیط کاری
</h2>
<p className="muted" style={{ marginBottom: '1.5rem', fontSize: '.875rem' }}>
لطفاً محیط کاری مورد نظر خود را انتخاب کنید
</p>
<div style={{ display: 'flex', flexDirection: 'column', gap: '.75rem' }}>
{availableContexts.map((ctx) => (
<button
key={ctx.db_uuid}
onClick={() => handleSelect(ctx)}
disabled={loading !== null}
style={{
display: 'flex',
alignItems: 'center',
gap: '1rem',
padding: '.875rem 1rem',
border: '1.5px solid var(--border, #e2e8f0)',
borderRadius: '0.625rem',
background: loading === ctx.db_uuid ? 'var(--surface-alt, #f4f6f9)' : 'var(--surface)',
cursor: loading !== null ? 'wait' : 'pointer',
textAlign: 'right',
transition: 'border-color .15s, box-shadow .15s',
opacity: loading !== null && loading !== ctx.db_uuid ? 0.5 : 1,
}}
onMouseEnter={e => (e.currentTarget.style.borderColor = 'var(--primary, #6366f1)')}
onMouseLeave={e => (e.currentTarget.style.borderColor = 'var(--border, #e2e8f0)')}
>
<span style={{ fontSize: '1.5rem', lineHeight: 1 }}>
{TYPE_ICONS[ctx.type] ?? '👤'}
</span>
<div style={{ flex: 1 }}>
<div style={{ fontWeight: 600, fontSize: '.9375rem', marginBottom: '.125rem' }}>
{ctx.name}
</div>
<div style={{ fontSize: '.8125rem' }}>
<span className="badge blue" style={{ fontSize: '.75rem' }}>
{ROLE_LABELS[ctx.role] ?? ctx.role}
</span>
</div>
</div>
{loading === ctx.db_uuid && (
<span className="skeleton" style={{ width: 20, height: 20, borderRadius: '50%' }} />
)}
</button>
))}
</div>
</div>
</div>
</div>
);
}