Replace all native <select> elements in the admin panel with SearchableSelect for a consistent UI experience. This change enhances accessibility, supports RTL and dark mode, and improves the overall design by utilizing a common component. The updates include adjustments to state management and event handling to ensure seamless integration with existing functionality across various pages and components.
This commit is contained in:
@@ -26,6 +26,7 @@ import AppointmentStatusDropdown from "./ui/AppointmentStatusDropdown";
|
||||
import Modal from "./ui/Modal";
|
||||
import PersianDateInput from "./ui/PersianDateInput";
|
||||
import PriceInput from "./ui/PriceInput";
|
||||
import SearchableSelect from "./ui/SearchableSelect";
|
||||
|
||||
/** Row actions for the appointments table (Figma عملیات menu). */
|
||||
type ModalKind = null | "info" | "move" | "transfer" | "replace";
|
||||
@@ -732,16 +733,6 @@ export function ReplaceAppointmentModal({
|
||||
});
|
||||
|
||||
const label = { fontSize: 12.5, color: "var(--text-3)" } as const;
|
||||
const sel = {
|
||||
width: "100%",
|
||||
height: 38,
|
||||
borderRadius: "var(--r-sm)",
|
||||
border: "1px solid var(--border)",
|
||||
background: "var(--surface)",
|
||||
fontSize: 13,
|
||||
fontFamily: "inherit",
|
||||
padding: "0 10px",
|
||||
} as const;
|
||||
const lockedField = { margin: "6px 0 12px", opacity: 0.6 } as const;
|
||||
const patients = patientsQ.data?.data ?? [];
|
||||
|
||||
@@ -847,39 +838,32 @@ export function ReplaceAppointmentModal({
|
||||
>
|
||||
<div>
|
||||
<label style={label}>بخش</label>
|
||||
<select
|
||||
aria-label="بخش"
|
||||
style={{ ...sel, marginTop: 6 }}
|
||||
value={sectionUuid}
|
||||
onChange={(e) => {
|
||||
setSectionUuid(e.target.value);
|
||||
setItemUuid("");
|
||||
}}
|
||||
>
|
||||
<option value="">انتخاب بخش</option>
|
||||
{(sectionsQ.data?.data ?? []).map((o) => (
|
||||
<option key={o.uuid} value={o.uuid}>
|
||||
{o.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<div style={{ marginTop: 6 }}>
|
||||
<SearchableSelect
|
||||
options={(sectionsQ.data?.data ?? []).map((o) => ({ value: o.uuid, label: o.name ?? "" }))}
|
||||
value={sectionUuid || null}
|
||||
onChange={(v) => { setSectionUuid(v ? String(v) : ""); setItemUuid(""); }}
|
||||
placeholder="انتخاب بخش"
|
||||
isLoading={sectionsQ.isLoading}
|
||||
isClearable
|
||||
height={38}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<label style={label}>سرویس</label>
|
||||
<select
|
||||
aria-label="سرویس"
|
||||
style={{ ...sel, marginTop: 6 }}
|
||||
value={itemUuid}
|
||||
onChange={(e) => setItemUuid(e.target.value)}
|
||||
disabled={!sectionUuid}
|
||||
>
|
||||
<option value="">انتخاب زیر بخش</option>
|
||||
{(itemsQ.data?.data ?? []).map((o) => (
|
||||
<option key={o.uuid} value={o.uuid}>
|
||||
{o.name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<div style={{ marginTop: 6 }}>
|
||||
<SearchableSelect
|
||||
options={(itemsQ.data?.data ?? []).map((o) => ({ value: o.uuid, label: o.name ?? "" }))}
|
||||
value={itemUuid || null}
|
||||
onChange={(v) => setItemUuid(v ? String(v) : "")}
|
||||
placeholder="انتخاب زیر بخش"
|
||||
isDisabled={!sectionUuid}
|
||||
isLoading={itemsQ.isLoading}
|
||||
isClearable
|
||||
height={38}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -958,35 +942,28 @@ export function ReplaceAppointmentModal({
|
||||
</div>
|
||||
|
||||
<label style={label}>انتخاب پرسنل</label>
|
||||
<select
|
||||
aria-label="پرسنل"
|
||||
style={{ ...sel, margin: "6px 0 12px" }}
|
||||
value={staffUuid}
|
||||
onChange={(e) => setStaffUuid(e.target.value)}
|
||||
>
|
||||
<option value="">انتخاب...</option>
|
||||
{(staffQ.data?.data ?? []).map((o) => (
|
||||
<option key={o.uuid} value={o.uuid}>
|
||||
{o.full_name}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<div style={{ margin: "6px 0 12px" }}>
|
||||
<SearchableSelect
|
||||
options={(staffQ.data?.data ?? []).map((o) => ({ value: o.uuid, label: o.full_name ?? "" }))}
|
||||
value={staffUuid || null}
|
||||
onChange={(v) => setStaffUuid(v ? String(v) : "")}
|
||||
placeholder="انتخاب..."
|
||||
isLoading={staffQ.isLoading}
|
||||
isClearable
|
||||
height={38}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<label style={label}>انتخاب وضعیت</label>
|
||||
<select
|
||||
aria-label="وضعیت"
|
||||
style={{ ...sel, margin: "6px 0 12px" }}
|
||||
value={status}
|
||||
onChange={(e) =>
|
||||
setStatus(e.target.value as Appointment["status"])
|
||||
}
|
||||
>
|
||||
{statusOptions.map(([v, l]) => (
|
||||
<option key={v} value={v}>
|
||||
{l}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
<div style={{ margin: "6px 0 12px" }}>
|
||||
<SearchableSelect
|
||||
options={statusOptions.map(([v, l]) => ({ value: v, label: l }))}
|
||||
value={status || null}
|
||||
onChange={(v) => setStatus((v ? String(v) : "") as Appointment["status"])}
|
||||
placeholder="انتخاب وضعیت"
|
||||
height={38}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<label style={label}>توضیحات</label>
|
||||
<div
|
||||
|
||||
Reference in New Issue
Block a user