fix(ui): unify list filters across all pages (bare controls, standard sizes)
Every list-page FilterBar now follows one spec: bare controls (no Field label rows — which broke flex-end alignment), standardized widths (search 1 1 320px grows; small selects 0 0 160px; entity selects 0 0 220px; MonthField 0 0 180px; dates 0 0 150px), consistent 'Všechny/Všichni/Všechna <entity>' defaults, and a placeholder on every search. TripsAdmin's separate month-Select + year-Select collapse into one MonthField (yyyy-MM, split at the query boundary) — matching Attendance/TripsHistory. The 4 labeled attendance/trips pages move off the Field wrapper; Projects & ReceivedInvoices move their inline search into a FilterBar. Chrome-verified all ~18 filter pages in light + the existing theme. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -27,6 +27,7 @@ import {
|
||||
TextField,
|
||||
Select,
|
||||
DateField,
|
||||
MonthField,
|
||||
StatusChip,
|
||||
FilterBar,
|
||||
LoadingState,
|
||||
@@ -181,12 +182,10 @@ const BusinessIcon = (
|
||||
export default function TripsAdmin() {
|
||||
const alert = useAlert();
|
||||
const { hasPermission } = useAuth();
|
||||
const [filterMonth, setFilterMonth] = useState(() =>
|
||||
String(new Date().getMonth() + 1),
|
||||
);
|
||||
const [filterYear, setFilterYear] = useState(() =>
|
||||
String(new Date().getFullYear()),
|
||||
);
|
||||
const [filterPeriod, setFilterPeriod] = useState(() => {
|
||||
const now = new Date();
|
||||
return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, "0")}`;
|
||||
});
|
||||
const [filterVehicleId, setFilterVehicleId] = useState("");
|
||||
const [filterUserId, setFilterUserId] = useState("");
|
||||
const printRef = useRef<HTMLDivElement>(null);
|
||||
@@ -220,8 +219,8 @@ export default function TripsAdmin() {
|
||||
|
||||
const { data: tripsData, isPending } = useQuery(
|
||||
tripListOptions({
|
||||
month: Number(filterMonth) || undefined,
|
||||
year: Number(filterYear) || undefined,
|
||||
month: Number(filterPeriod.slice(5, 7)) || undefined,
|
||||
year: Number(filterPeriod.slice(0, 4)) || undefined,
|
||||
vehicleId: filterVehicleId ? Number(filterVehicleId) : undefined,
|
||||
userId: filterUserId ? Number(filterUserId) : undefined,
|
||||
perPage: 100,
|
||||
@@ -319,10 +318,10 @@ export default function TripsAdmin() {
|
||||
};
|
||||
|
||||
const getPeriodName = () =>
|
||||
new Date(Number(filterYear), Number(filterMonth) - 1).toLocaleString(
|
||||
"cs-CZ",
|
||||
{ month: "long", year: "numeric" },
|
||||
);
|
||||
new Date(
|
||||
Number(filterPeriod.slice(0, 4)),
|
||||
Number(filterPeriod.slice(5, 7)) - 1,
|
||||
).toLocaleString("cs-CZ", { month: "long", year: "numeric" });
|
||||
const getSelectedVehicleName = () => {
|
||||
if (!filterVehicleId) return null;
|
||||
const v = vehicles.find((v) => String(v.id) === filterVehicleId);
|
||||
@@ -566,61 +565,34 @@ export default function TripsAdmin() {
|
||||
|
||||
{/* Filters */}
|
||||
<FilterBar>
|
||||
<Box sx={{ flex: "0 0 160px" }}>
|
||||
<Field label="Měsíc">
|
||||
<Select
|
||||
value={filterMonth}
|
||||
onChange={setFilterMonth}
|
||||
options={Array.from({ length: 12 }, (_, i) => ({
|
||||
value: String(i + 1),
|
||||
label: new Date(2000, i).toLocaleString("cs-CZ", {
|
||||
month: "long",
|
||||
}),
|
||||
}))}
|
||||
/>
|
||||
</Field>
|
||||
<Box sx={{ flex: "0 0 180px" }}>
|
||||
<MonthField value={filterPeriod} onChange={setFilterPeriod} />
|
||||
</Box>
|
||||
<Box sx={{ flex: "0 0 120px" }}>
|
||||
<Field label="Rok">
|
||||
<Select
|
||||
value={filterYear}
|
||||
onChange={setFilterYear}
|
||||
options={Array.from({ length: 5 }, (_, i) => {
|
||||
const y = new Date().getFullYear() - 2 + i;
|
||||
return { value: String(y), label: String(y) };
|
||||
})}
|
||||
/>
|
||||
</Field>
|
||||
<Box sx={{ flex: "0 0 220px" }}>
|
||||
<Select
|
||||
value={filterVehicleId}
|
||||
onChange={setFilterVehicleId}
|
||||
options={[
|
||||
{ value: "", label: "Všechna vozidla" },
|
||||
...vehicles.map((v) => ({
|
||||
value: String(v.id),
|
||||
label: `${v.spz} - ${v.name}`,
|
||||
})),
|
||||
]}
|
||||
/>
|
||||
</Box>
|
||||
<Box sx={{ flex: "1 1 200px" }}>
|
||||
<Field label="Vozidlo">
|
||||
<Select
|
||||
value={filterVehicleId}
|
||||
onChange={setFilterVehicleId}
|
||||
options={[
|
||||
{ value: "", label: "Všechna vozidla" },
|
||||
...vehicles.map((v) => ({
|
||||
value: String(v.id),
|
||||
label: `${v.spz} - ${v.name}`,
|
||||
})),
|
||||
]}
|
||||
/>
|
||||
</Field>
|
||||
</Box>
|
||||
<Box sx={{ flex: "1 1 200px" }}>
|
||||
<Field label="Řidič">
|
||||
<Select
|
||||
value={filterUserId}
|
||||
onChange={setFilterUserId}
|
||||
options={[
|
||||
{ value: "", label: "Všichni řidiči" },
|
||||
...tripUsers.map((u) => ({
|
||||
value: String(u.id),
|
||||
label: u.name,
|
||||
})),
|
||||
]}
|
||||
/>
|
||||
</Field>
|
||||
<Box sx={{ flex: "0 0 220px" }}>
|
||||
<Select
|
||||
value={filterUserId}
|
||||
onChange={setFilterUserId}
|
||||
options={[
|
||||
{ value: "", label: "Všichni řidiči" },
|
||||
...tripUsers.map((u) => ({
|
||||
value: String(u.id),
|
||||
label: u.name,
|
||||
})),
|
||||
]}
|
||||
/>
|
||||
</Box>
|
||||
</FilterBar>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user