ui: restructure filters — search wider on row 1, SMS + hide-completed toggle switch on row 2
This commit is contained in:
parent
0cdd9f52a4
commit
46fac18e28
|
|
@ -0,0 +1,38 @@
|
|||
import React from "react";
|
||||
|
||||
/**
|
||||
* Accessible iOS-style toggle switch.
|
||||
* @param {object} props
|
||||
* @param {boolean} props.checked
|
||||
* @param {function} props.onChange Called with the next boolean value.
|
||||
* @param {string} [props.label] Visible text next to the switch.
|
||||
* @param {string} [props.title] Hover tooltip.
|
||||
* @param {string} [props.className]
|
||||
*/
|
||||
export const Switch = ({ checked = false, onChange, label, title, className = "" }) => {
|
||||
const id = React.useId();
|
||||
return (
|
||||
<label htmlFor={id} className={`inline-flex cursor-pointer select-none items-center gap-2.5 text-sm text-[var(--color-text)] ${className}`} title={title}>
|
||||
<button
|
||||
type="button"
|
||||
id={id}
|
||||
role="switch"
|
||||
aria-checked={checked}
|
||||
onClick={() => onChange && onChange(!checked)}
|
||||
className={`relative inline-flex h-6 w-11 shrink-0 items-center rounded-full border transition-colors ${
|
||||
checked
|
||||
? "border-[var(--color-accent)] bg-[var(--color-accent)]"
|
||||
: "border-[var(--color-border)] bg-[var(--color-surface-strong)]"
|
||||
}`}
|
||||
>
|
||||
<span
|
||||
aria-hidden="true"
|
||||
className={`inline-block h-5 w-5 transform rounded-full bg-white shadow transition-transform ${
|
||||
checked ? "translate-x-[22px]" : "translate-x-0.5"
|
||||
}`}
|
||||
/>
|
||||
</button>
|
||||
{label ? <span>{label}</span> : null}
|
||||
</label>
|
||||
);
|
||||
};
|
||||
|
|
@ -3,6 +3,7 @@ import { Button } from "../UI/Button";
|
|||
import { Input } from "../UI/Input";
|
||||
import { Panel } from "../UI/Panel";
|
||||
import { DatePicker } from "../UI/DatePicker";
|
||||
import { Switch } from "../UI/Switch";
|
||||
|
||||
const DropdownSelect = ({ value, options, onChange, placeholder }) => {
|
||||
const [isOpen, setIsOpen] = React.useState(false);
|
||||
|
|
@ -129,8 +130,8 @@ export const OrderFilters = ({ filters, setFilters, statusOptions = [], cities =
|
|||
return (
|
||||
<Panel className="p-4">
|
||||
<div className="flex flex-col gap-3">
|
||||
{/* Row 1: Status + City + DeliveryType + Search */}
|
||||
<div className="grid gap-3 md:grid-cols-[minmax(12rem,0.7fr)_minmax(0,0.5fr)_minmax(0,0.5fr)_minmax(0,1.4fr)] md:items-end">
|
||||
{/* Row 1: Status + City + DeliveryType + Search (search spans wider) */}
|
||||
<div className="grid gap-3 md:grid-cols-[minmax(12rem,0.7fr)_minmax(0,0.5fr)_minmax(0,0.5fr)_minmax(0,1.6fr)] md:items-end">
|
||||
<div ref={statusMenuRef} className="relative flex min-w-0 flex-col gap-2">
|
||||
<button
|
||||
type="button"
|
||||
|
|
@ -196,29 +197,6 @@ export const OrderFilters = ({ filters, setFilters, statusOptions = [], cities =
|
|||
placeholder="Тип получения"
|
||||
/>
|
||||
|
||||
<div className="flex items-end gap-3">
|
||||
<DropdownSelect
|
||||
value={filters.smsStatus || "all"}
|
||||
options={smsProblemOptions}
|
||||
onChange={(v) => updateFilter("smsStatus", v)}
|
||||
placeholder="Проблемы SMS"
|
||||
/>
|
||||
{typeof onToggleHideCompleted === "function" && (
|
||||
<label
|
||||
className="mb-0.5 flex shrink-0 cursor-pointer select-none items-center gap-2 text-sm text-[var(--color-text)]"
|
||||
title="Доставленные и отгруженные заказы скрыты"
|
||||
>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={hideCompleted}
|
||||
onChange={() => onToggleHideCompleted((prev) => !prev)}
|
||||
className="h-4 w-4 cursor-pointer accent-[var(--color-accent)]"
|
||||
/>
|
||||
<span>Скрыть завершённые</span>
|
||||
</label>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<Input
|
||||
className="h-[46px] py-0"
|
||||
placeholder="Поиск по группе, клиенту или телефону"
|
||||
|
|
@ -227,8 +205,8 @@ export const OrderFilters = ({ filters, setFilters, statusOptions = [], cities =
|
|||
/>
|
||||
</div>
|
||||
|
||||
{/* Row 2: Date range */}
|
||||
<div className="flex items-end gap-3 flex-wrap">
|
||||
{/* Row 2: Date range + SMS problems (width matches its text) + hide-completed toggle */}
|
||||
<div className="flex flex-wrap items-end gap-3">
|
||||
<DatePicker
|
||||
value={filters.dateFrom || ""}
|
||||
onChange={(v) => updateFilter("dateFrom", v)}
|
||||
|
|
@ -252,6 +230,23 @@ export const OrderFilters = ({ filters, setFilters, statusOptions = [], cities =
|
|||
✕ Сбросить
|
||||
</button>
|
||||
)}
|
||||
|
||||
<DropdownSelect
|
||||
value={filters.smsStatus || "all"}
|
||||
options={smsProblemOptions}
|
||||
onChange={(v) => updateFilter("smsStatus", v)}
|
||||
placeholder="Проблемы SMS"
|
||||
/>
|
||||
|
||||
{typeof onToggleHideCompleted === "function" && (
|
||||
<Switch
|
||||
checked={hideCompleted}
|
||||
onChange={onToggleHideCompleted}
|
||||
label="Скрыть завершённые"
|
||||
title="Доставленные и отгруженные заказы скрыты"
|
||||
className="mb-0.5"
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</Panel>
|
||||
|
|
|
|||
Loading…
Reference in New Issue