feat: enhance DoctorFormPage with searchable specialties and improved UI components
- Refactored DoctorFormPage to use Controller from react-hook-form for better form handling. - Added a new Field component for consistent input styling and error handling. - Implemented a SpecialtyPicker component with improved selection logic for specialties. - Updated the layout and styling of the form sections for better user experience. - Integrated SearchableSelect for selecting specialties and roles in DoctorsPage and UsersPage. - Added createClinic API endpoint to handle clinic creation with validation for mobile and name fields.
This commit is contained in:
@@ -17,6 +17,7 @@ interface Props {
|
||||
isClearable?: boolean;
|
||||
noOptionsMessage?: string;
|
||||
inputId?: string;
|
||||
height?: number;
|
||||
}
|
||||
|
||||
export default function SearchableSelect({
|
||||
@@ -29,6 +30,7 @@ export default function SearchableSelect({
|
||||
isClearable,
|
||||
noOptionsMessage = 'موردی یافت نشد',
|
||||
inputId,
|
||||
height = 42,
|
||||
}: Props) {
|
||||
const darkMode = useUiStore((s) => s.darkMode);
|
||||
|
||||
@@ -40,64 +42,60 @@ export default function SearchableSelect({
|
||||
const styles: StylesConfig<SelectOption, false, GroupBase<SelectOption>> = {
|
||||
control: (base, state) => ({
|
||||
...base,
|
||||
background: darkMode ? '#111827' : '#ffffff',
|
||||
borderColor: state.isFocused ? '#7c3aed' : darkMode ? '#4b5563' : '#cbd5e1',
|
||||
boxShadow: state.isFocused ? '0 0 0 2px rgba(124,58,237,0.25)' : 'none',
|
||||
borderRadius: '0.75rem',
|
||||
minHeight: '2.75rem',
|
||||
fontSize: '0.875rem',
|
||||
background: darkMode ? 'var(--surface)' : 'var(--surface)',
|
||||
borderColor: state.isFocused ? 'var(--primary)' : 'var(--border)',
|
||||
boxShadow: state.isFocused ? '0 0 0 4px var(--ring)' : 'none',
|
||||
borderRadius: 'var(--r-sm)',
|
||||
minHeight: height,
|
||||
fontSize: 14,
|
||||
cursor: 'pointer',
|
||||
'&:hover': {
|
||||
borderColor: state.isFocused ? '#7c3aed' : darkMode ? '#6b7280' : '#94a3b8',
|
||||
borderColor: state.isFocused ? 'var(--primary)' : 'var(--border-2)',
|
||||
},
|
||||
}),
|
||||
valueContainer: (base) => ({ ...base, padding: '0 14px' }),
|
||||
menu: (base) => ({
|
||||
...base,
|
||||
background: darkMode ? '#1f2937' : '#ffffff',
|
||||
border: `1px solid ${darkMode ? '#374151' : '#e2e8f0'}`,
|
||||
boxShadow: '0 8px 24px rgba(0,0,0,0.15)',
|
||||
borderRadius: '0.75rem',
|
||||
overflow: 'hidden',
|
||||
background: 'var(--surface)',
|
||||
border: '1px solid var(--border)',
|
||||
boxShadow: 'var(--shadow-lg)',
|
||||
borderRadius: 'var(--r)',
|
||||
overflow: 'hidden',
|
||||
marginTop: 4,
|
||||
}),
|
||||
menuPortal: (base) => ({ ...base, zIndex: 9999 }),
|
||||
option: (base, state) => ({
|
||||
...base,
|
||||
background: state.isSelected
|
||||
? '#7c3aed'
|
||||
? 'var(--primary-soft2)'
|
||||
: state.isFocused
|
||||
? darkMode ? '#374151' : '#f1f5f9'
|
||||
? 'var(--surface-2)'
|
||||
: 'transparent',
|
||||
color: state.isSelected ? '#ffffff' : darkMode ? '#e5e7eb' : '#1e293b',
|
||||
fontSize: '0.875rem',
|
||||
cursor: 'pointer',
|
||||
color: state.isSelected ? 'var(--primary-700)' : 'var(--text)',
|
||||
fontWeight: state.isSelected ? 700 : 400,
|
||||
fontSize: 14,
|
||||
cursor: 'pointer',
|
||||
padding: '9px 14px',
|
||||
}),
|
||||
singleValue: (base) => ({ ...base, color: darkMode ? '#f3f4f6' : '#1e293b' }),
|
||||
input: (base) => ({ ...base, color: darkMode ? '#f3f4f6' : '#1e293b' }),
|
||||
placeholder: (base) => ({ ...base, color: darkMode ? '#6b7280' : '#94a3b8' }),
|
||||
indicatorSeparator: (base) => ({
|
||||
singleValue: (base) => ({ ...base, color: 'var(--text)' }),
|
||||
input: (base) => ({ ...base, color: 'var(--text)', margin: 0, padding: 0 }),
|
||||
placeholder: (base) => ({ ...base, color: 'var(--text-3)' }),
|
||||
indicatorSeparator: (base) => ({ ...base, background: 'var(--border)' }),
|
||||
dropdownIndicator: (base) => ({
|
||||
...base,
|
||||
background: darkMode ? '#374151' : '#e2e8f0',
|
||||
}),
|
||||
dropdownIndicator: (base) => ({
|
||||
...base,
|
||||
color: darkMode ? '#6b7280' : '#94a3b8',
|
||||
'&:hover': { color: darkMode ? '#9ca3af' : '#64748b' },
|
||||
color: 'var(--text-3)',
|
||||
padding: '0 10px',
|
||||
'&:hover': { color: 'var(--text-2)' },
|
||||
}),
|
||||
clearIndicator: (base) => ({
|
||||
...base,
|
||||
color: darkMode ? '#6b7280' : '#94a3b8',
|
||||
'&:hover': { color: '#ef4444' },
|
||||
}),
|
||||
loadingIndicator: (base) => ({ ...base, color: '#7c3aed' }),
|
||||
noOptionsMessage: (base) => ({
|
||||
...base,
|
||||
color: darkMode ? '#6b7280' : '#94a3b8',
|
||||
fontSize: '0.875rem',
|
||||
}),
|
||||
loadingMessage: (base) => ({
|
||||
...base,
|
||||
color: darkMode ? '#6b7280' : '#94a3b8',
|
||||
fontSize: '0.875rem',
|
||||
color: 'var(--text-3)',
|
||||
padding: '0 6px',
|
||||
'&:hover': { color: 'var(--danger)' },
|
||||
}),
|
||||
loadingIndicator: (base) => ({ ...base, color: 'var(--primary)' }),
|
||||
noOptionsMessage: (base) => ({ ...base, color: 'var(--text-3)', fontSize: 13 }),
|
||||
loadingMessage: (base) => ({ ...base, color: 'var(--text-3)', fontSize: 13 }),
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user