Skip to content

Commit 0a847c7

Browse files
committed
Tweak filters for new design
1 parent a91bd48 commit 0a847c7

File tree

10 files changed

+136
-471
lines changed

10 files changed

+136
-471
lines changed

src/app/conf/2023/sessions/[id]/_event_title.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ScheduleSession } from "../../../_components/schedule/session-list"
1+
import { ScheduleSession } from "@/app/conf/_api/sched-types"
22

33
export function getEventTitle(
44
event: ScheduleSession,

src/app/conf/2025/schedule/_components/filter-categories.ts

Lines changed: 0 additions & 75 deletions
This file was deleted.

src/app/conf/2025/schedule/_components/filters.tsx

Lines changed: 56 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,55 @@
11
import clsx from "clsx"
22
import { useState } from "react"
3-
import { Combobox } from "@headlessui/react"
3+
import {
4+
Combobox,
5+
ComboboxInput,
6+
ComboboxOption,
7+
ComboboxOptions,
8+
ComboboxButton,
9+
Label,
10+
} from "@headlessui/react"
411

512
import { Tag } from "@/app/conf/_design-system/tag"
613
import { Button } from "@/app/conf/_design-system/button"
714

815
import CloseIcon from "@/app/conf/_design-system/pixelarticons/close.svg?svgr"
916
import CaretDownIcon from "@/app/conf/_design-system/pixelarticons/caret-down.svg?svgr"
1017
import { eventsColors } from "../../utils"
18+
import { ScheduleSession } from "@/app/conf/_api/sched-types"
19+
20+
export interface FilterCategoryConfig {
21+
property: keyof ScheduleSession
22+
label: string
23+
options: string[]
24+
}
25+
26+
export const FilterCategoryConfig = {
27+
fromFields: (
28+
fields: Partial<Record<keyof ScheduleSession, string /* label */>>,
29+
scheduleData: ScheduleSession[],
30+
) => {
31+
return Object.entries(fields).map(
32+
([field, label]): FilterCategoryConfig => ({
33+
property: field as keyof ScheduleSession,
34+
label,
35+
options: Array.from(
36+
new Set(scheduleData.map(session => session[field])),
37+
).filter((x): x is string => !!x && typeof x === "string"),
38+
}),
39+
)
40+
},
41+
}
42+
43+
export type CategoryName = keyof ScheduleSession
44+
45+
export interface FilterStates extends Partial<Record<CategoryName, string[]>> {}
46+
export const FilterStates = {
47+
initial: (fields: Array<keyof ScheduleSession>) =>
48+
Object.fromEntries(fields.map(field => [field, []])),
49+
}
50+
1151
type FiltersProps = {
12-
categories: { name: string; options: string[] }[]
52+
categories: FilterCategoryConfig[]
1353
filterState: Record<string, string[]>
1454
onFilterChange: (category: string, newSelectedOptions: string[]) => void
1555
}
@@ -23,14 +63,14 @@ export function Filters({
2363
<div className="flex flex-wrap justify-stretch gap-x-2 gap-y-4 pb-10">
2464
{categories.map(category => (
2565
<FiltersCombobox
26-
key={category.name}
27-
label={category.name}
66+
key={category.property}
67+
label={category.label}
2868
options={category.options}
29-
value={filterState[category.name] || []}
69+
value={filterState[category.property] || []}
3070
onChange={newSelectedOptions => {
31-
onFilterChange(category.name, newSelectedOptions)
71+
onFilterChange(category.property, newSelectedOptions)
3272
}}
33-
placeholder={`Any ${category.name.toLowerCase()}`}
73+
placeholder={`Any ${category.label.toLowerCase()}`}
3474
className="flex-1"
3575
/>
3676
))}
@@ -95,12 +135,12 @@ function FiltersCombobox({
95135
<Combobox immediate multiple value={value} onChange={onChange}>
96136
<div className={clsx("flex flex-col", className)}>
97137
{label && (
98-
<Combobox.Label className="typography-menu mb-1 block font-mono font-medium uppercase text-neu-900">
138+
<Label className="typography-menu mb-1 block font-mono font-medium uppercase text-neu-900">
99139
{label}
100-
</Combobox.Label>
140+
</Label>
101141
)}
102142
<label className="relative w-full border border-neu-500 bg-neu-0 p-2 focus-within:outline-none focus-within:ring focus-within:ring-neu-300 dark:border-neu-200 dark:focus-within:ring-neu-200">
103-
<Combobox.Input
143+
<ComboboxInput
104144
value={query}
105145
onChange={e => setQuery(e.target.value)}
106146
className={clsx(
@@ -109,7 +149,7 @@ function FiltersCombobox({
109149
placeholder={placeholder}
110150
autoComplete="true"
111151
/>
112-
<Combobox.Button
152+
<ComboboxButton
113153
className={clsx(
114154
"absolute inset-y-0 right-0 flex items-center px-2 focus:outline-none",
115155
)}
@@ -118,7 +158,7 @@ function FiltersCombobox({
118158
className="ui-open:rotate-180 size-5 text-neu-400 transition-transform duration-150 group-hover:text-neu-500"
119159
aria-hidden="true"
120160
/>
121-
</Combobox.Button>
161+
</ComboboxButton>
122162
{value.length > 0 && (
123163
<div className="inset-y-0 left-0 z-[1] mt-1 flex items-center overflow-x-auto pr-8">
124164
<div className="flex flex-wrap items-center gap-1">
@@ -136,23 +176,23 @@ function FiltersCombobox({
136176
</label>
137177

138178
<div className="relative">
139-
<Combobox.Options
179+
<ComboboxOptions
140180
className={clsx(
141181
"absolute z-10 -mt-px max-h-60 w-full overflow-auto border border-neu-500 bg-neu-0 p-1 text-base",
142182
)}
143183
>
144184
{filteredOptions.map(option => (
145-
<Combobox.Option key={option} value={option}>
185+
<ComboboxOption key={option} value={option}>
146186
{({ active, selected }) => (
147187
<FilterComboboxOption
148188
active={active}
149189
selected={selected}
150190
option={option}
151191
/>
152192
)}
153-
</Combobox.Option>
193+
</ComboboxOption>
154194
))}
155-
</Combobox.Options>
195+
</ComboboxOptions>
156196
</div>
157197
</div>
158198
</Combobox>

0 commit comments

Comments
 (0)