diff --git a/apps/admin-dashboard/src/components/source-config-panel.tsx b/apps/admin-dashboard/src/components/source-config-panel.tsx index bb2b658..0816c2d 100644 --- a/apps/admin-dashboard/src/components/source-config-panel.tsx +++ b/apps/admin-dashboard/src/components/source-config-panel.tsx @@ -408,6 +408,40 @@ function FieldInput({ ) } + if (field.type === "multiselect" && field.options) { + const selected = Array.isArray(value) ? (value as string[]) : [] + + function toggle(optValue: string) { + const next = selected.includes(optValue) + ? selected.filter((v) => v !== optValue) + : [...selected, optValue] + onChange(next) + } + + return ( +
+ +
+ {field.options!.map((opt) => { + const isSelected = selected.includes(opt.value) + return ( + !disabled && toggle(opt.value)} + > + {opt.label} + + ) + })} +
+
+ ) + } + if (field.type === "number") { return (
@@ -456,6 +490,8 @@ function buildInitialValues( values[name] = saved[name] } else if (field.defaultValue !== undefined) { values[name] = field.defaultValue + } else if (field.type === "multiselect") { + values[name] = [] } else { values[name] = field.type === "number" ? undefined : "" } diff --git a/apps/admin-dashboard/src/lib/api.ts b/apps/admin-dashboard/src/lib/api.ts index 41ef9f0..772b534 100644 --- a/apps/admin-dashboard/src/lib/api.ts +++ b/apps/admin-dashboard/src/lib/api.ts @@ -9,12 +9,12 @@ function serverBase() { } export interface ConfigFieldDef { - type: "string" | "number" | "select" + type: "string" | "number" | "select" | "multiselect" label: string required?: boolean description?: string secret?: boolean - defaultValue?: string | number + defaultValue?: string | number | string[] options?: { label: string; value: string }[] } @@ -54,6 +54,39 @@ const sourceDefinitions: SourceDefinition[] = [ dailyLimit: { type: "number", label: "Daily Forecast Limit", defaultValue: 7, description: "Number of daily forecasts to include" }, }, }, + { + id: "aelis.tfl", + name: "TfL", + description: "Transport for London tube line status alerts.", + fields: { + lines: { + type: "multiselect", + label: "Lines", + description: "Lines to monitor. Leave empty for all lines.", + defaultValue: [], + options: [ + { label: "Bakerloo", value: "bakerloo" }, + { label: "Central", value: "central" }, + { label: "Circle", value: "circle" }, + { label: "District", value: "district" }, + { label: "Hammersmith & City", value: "hammersmith-city" }, + { label: "Jubilee", value: "jubilee" }, + { label: "Metropolitan", value: "metropolitan" }, + { label: "Northern", value: "northern" }, + { label: "Piccadilly", value: "piccadilly" }, + { label: "Victoria", value: "victoria" }, + { label: "Waterloo & City", value: "waterloo-city" }, + { label: "Lioness", value: "lioness" }, + { label: "Mildmay", value: "mildmay" }, + { label: "Windrush", value: "windrush" }, + { label: "Weaver", value: "weaver" }, + { label: "Suffragette", value: "suffragette" }, + { label: "Liberty", value: "liberty" }, + { label: "Elizabeth", value: "elizabeth" }, + ], + }, + }, + }, ] export function fetchSources(): Promise { diff --git a/apps/admin-dashboard/src/routes/_dashboard.tsx b/apps/admin-dashboard/src/routes/_dashboard.tsx index bfbf00b..eba5b8f 100644 --- a/apps/admin-dashboard/src/routes/_dashboard.tsx +++ b/apps/admin-dashboard/src/routes/_dashboard.tsx @@ -6,6 +6,7 @@ import { CircleDot, CloudSun, Loader2, + TrainFront, LogOut, MapPin, Rss, @@ -41,6 +42,7 @@ const SOURCE_ICONS: Record> "aelis.weather": CloudSun, "aelis.caldav": CalendarDays, "aelis.google-calendar": Calendar, + "aelis.tfl": TrainFront, } export const Route = createRoute({