feat: TitlesFilterPanel component
This commit is contained in:
parent
ab29c33f5b
commit
4dd60f3b19
3 changed files with 142 additions and 6 deletions
|
|
@ -0,0 +1,122 @@
|
|||
import { useState } from "react";
|
||||
import type { TitleStatus, ReleaseSeason } from "../../api";
|
||||
import { ChevronDownIcon, ChevronUpIcon } from "@heroicons/react/24/solid";
|
||||
|
||||
export type TitlesFilter = {
|
||||
extSearch: boolean;
|
||||
status: TitleStatus | "";
|
||||
rating: number | "";
|
||||
releaseYear: number | "";
|
||||
releaseSeason: ReleaseSeason | "";
|
||||
};
|
||||
|
||||
type TitlesFilterPanelProps = {
|
||||
filters: TitlesFilter;
|
||||
setFilters: (filters: TitlesFilter) => void;
|
||||
};
|
||||
|
||||
const STATUS_OPTIONS: (TitleStatus | "")[] = ["", "planned", "finished", "ongoing"];
|
||||
const SEASON_OPTIONS: (ReleaseSeason | "")[] = ["", "winter", "spring", "summer", "fall"];
|
||||
const RATING_OPTIONS = ["", 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||
|
||||
export function TitlesFilterPanel({ filters, setFilters }: TitlesFilterPanelProps) {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const handleChange = (field: keyof TitlesFilter, value: any) => {
|
||||
setFilters({ ...filters, [field]: value });
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="w-full flex justify-center my-4">
|
||||
<div className="bg-white shadow rounded-lg w-full max-w-3xl p-4">
|
||||
{/* Заголовок панели */}
|
||||
<div
|
||||
className="flex justify-between items-center cursor-pointer"
|
||||
onClick={() => setOpen((prev) => !prev)}
|
||||
>
|
||||
<h3 className="text-lg font-medium">Filters</h3>
|
||||
{open ? <ChevronUpIcon className="w-5 h-5" /> : <ChevronDownIcon className="w-5 h-5" />}
|
||||
</div>
|
||||
|
||||
{/* Контент панели */}
|
||||
{open && (
|
||||
<div className="mt-4 grid grid-cols-2 sm:grid-cols-3 gap-4">
|
||||
{/* Extended Search */}
|
||||
<div className="flex items-center gap-2">
|
||||
<input
|
||||
type="checkbox"
|
||||
id="extSearch"
|
||||
checked={filters.extSearch}
|
||||
onChange={(e) => handleChange("extSearch", e.target.checked)}
|
||||
className="w-4 h-4"
|
||||
/>
|
||||
<label htmlFor="extSearch" className="text-sm">
|
||||
Extended Search
|
||||
</label>
|
||||
</div>
|
||||
|
||||
{/* Status */}
|
||||
<div className="flex flex-col">
|
||||
<label htmlFor="status" className="text-sm mb-1">Status</label>
|
||||
<select
|
||||
id="status"
|
||||
value={filters.status}
|
||||
onChange={(e) => handleChange("status", e.target.value || "")}
|
||||
className="border rounded px-2 py-1"
|
||||
>
|
||||
{STATUS_OPTIONS.map((s) => (
|
||||
<option key={s || "all"} value={s}>{s || "All"}</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{/* Rating */}
|
||||
<div className="flex flex-col">
|
||||
<label htmlFor="rating" className="text-sm mb-1">Rating</label>
|
||||
<select
|
||||
id="rating"
|
||||
value={filters.rating}
|
||||
onChange={(e) => handleChange("rating", e.target.value ? Number(e.target.value) : "")}
|
||||
className="border rounded px-2 py-1"
|
||||
>
|
||||
{RATING_OPTIONS.map((r) => (
|
||||
<option key={r} value={r}>{r || "All"}</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
{/* Release Year */}
|
||||
<div className="flex flex-col">
|
||||
<label htmlFor="releaseYear" className="text-sm mb-1">Release Year</label>
|
||||
<input
|
||||
type="number"
|
||||
id="releaseYear"
|
||||
value={filters.releaseYear || ""}
|
||||
onChange={(e) =>
|
||||
handleChange("releaseYear", e.target.value ? Number(e.target.value) : "")
|
||||
}
|
||||
className="border rounded px-2 py-1"
|
||||
placeholder="Any"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Release Season */}
|
||||
<div className="flex flex-col">
|
||||
<label htmlFor="releaseSeason" className="text-sm mb-1">Release Season</label>
|
||||
<select
|
||||
id="releaseSeason"
|
||||
value={filters.releaseSeason}
|
||||
onChange={(e) => handleChange("releaseSeason", e.target.value || "")}
|
||||
className="border rounded px-2 py-1"
|
||||
>
|
||||
{SEASON_OPTIONS.map((s) => (
|
||||
<option key={s || "all"} value={s}>{s || "All"}</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue