Add admin dashboard filtering and sorting
Provide stable server-side list queries and focused chart controls so operators can inspect large datasets without misleading partial-page ordering.
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
import type { SortOrder } from "../api/types";
|
||||
|
||||
export interface SortOption<T extends string> {
|
||||
value: T;
|
||||
label: string;
|
||||
}
|
||||
|
||||
export function SortControl<T extends string>({
|
||||
value,
|
||||
order,
|
||||
options,
|
||||
onChange,
|
||||
label = "排序",
|
||||
}: {
|
||||
value: T;
|
||||
order: SortOrder;
|
||||
options: readonly SortOption<T>[];
|
||||
onChange: (value: T, order: SortOrder) => void;
|
||||
label?: string;
|
||||
}) {
|
||||
return (
|
||||
<fieldset className="flex min-w-0 flex-wrap items-end gap-2">
|
||||
<legend className="sr-only">{label}</legend>
|
||||
<label className="grid gap-1 text-xs font-semibold text-muted">
|
||||
<span>{label}</span>
|
||||
<select
|
||||
className="h-9 rounded-lg border border-border bg-input px-3 text-sm text-foreground outline-none focus:border-primary focus:ring-4 focus:ring-primary/10"
|
||||
value={value}
|
||||
onChange={(event) => onChange(event.target.value as T, order)}
|
||||
>
|
||||
{options.map((option) => (
|
||||
<option key={option.value} value={option.value}>
|
||||
{option.label}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
</label>
|
||||
<div className="inline-flex rounded-xl border border-border bg-surface-muted p-1">
|
||||
{(["desc", "asc"] as const).map((direction) => (
|
||||
<button
|
||||
key={direction}
|
||||
className={`min-h-7 rounded-lg px-3 text-xs font-semibold transition ${
|
||||
order === direction
|
||||
? "bg-surface text-foreground shadow-sm"
|
||||
: "text-muted hover:text-foreground"
|
||||
}`}
|
||||
type="button"
|
||||
aria-pressed={order === direction}
|
||||
onClick={() => onChange(value, direction)}
|
||||
>
|
||||
{direction === "desc" ? "降序" : "升序"}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</fieldset>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user