diff --git a/web/src/components/events/EventContainer.tsx b/web/src/components/events/EventContainer.tsx
index 8429d16..31a86c7 100644
--- a/web/src/components/events/EventContainer.tsx
+++ b/web/src/components/events/EventContainer.tsx
@@ -1,6 +1,11 @@
"use client";
-import { useQueryState, parseAsStringLiteral, parseAsString } from "nuqs";
+import {
+ useQueryState,
+ parseAsStringLiteral,
+ parseAsString,
+ parseAsArrayOf,
+} from "nuqs";
import { EventItem } from "./EventItem";
import { EventFilter, EventFilterExplained } from "./EventFilter";
import {
@@ -44,12 +49,15 @@ export const EventContainer = ({
"mode",
parseAsStringLiteral(["list", "calendar"]).withDefault("list")
);
- const [category, setCategory] = useQueryState("category", parseAsString);
+ const [categories, setCategories] = useQueryState(
+ "category",
+ parseAsArrayOf(parseAsString, ",")
+ );
const [organizer, setOrganizer] = useQueryState("organizer", parseAsString);
const [venue, setVenue] = useQueryState("venue", parseAsString);
const resetFilters = () => {
- setCategory(null);
+ setCategories(null);
setOrganizer(null);
setVenue(null);
};
@@ -105,10 +113,10 @@ export const EventContainer = ({
)
.filter(
(x) =>
- !category ||
+ !categories ||
x.categories
.map((eventCategory) => eventCategory.slug)
- .includes(category)
+ .filter((x) => categories.includes(x)).length !== 0
)
.filter(
(x) =>
@@ -147,7 +155,7 @@ export const EventContainer = ({
- {(category || organizer || venue) && (
+ {(categories || organizer || venue) && (
{
if (events.length === 0) {
- return (
- Ingen kommende arrangementer.
- );
+ return Ingen kommende arrangementer.
;
}
return (
diff --git a/web/src/components/events/EventFilter.tsx b/web/src/components/events/EventFilter.tsx
index 362be5a..e46ac99 100644
--- a/web/src/components/events/EventFilter.tsx
+++ b/web/src/components/events/EventFilter.tsx
@@ -2,12 +2,12 @@ import { EventCategory, EventOrganizer } from "@/lib/event";
import styles from "./eventFilter.module.scss";
import { VenueFragment } from "@/gql/graphql";
-import { Icon } from "../general/Icon";
+import { formatHumanReadableList } from "@/lib/common";
export const EventFilter = ({
eventCategories,
- setCategory,
- activeCategory,
+ setCategories,
+ activeCategories,
eventOrganizers,
setOrganizer,
activeOrganizer,
@@ -17,8 +17,8 @@ export const EventFilter = ({
isVisible,
}: {
eventCategories: EventCategory[];
- setCategory: (slug: string | null) => void;
- activeCategory: string | null;
+ setCategories: (slug: string[] | null) => void;
+ activeCategories: string[] | null;
eventOrganizers: EventOrganizer[];
setOrganizer: (slug: string | null) => void;
activeOrganizer: string | null;
@@ -35,6 +35,12 @@ export const EventFilter = ({
const venue = e.target.value;
setVenue(venue === "" ? null : venue);
};
+ const toggleCategory = (category: string) => {
+ const newCategories = activeCategories?.includes(category)
+ ? activeCategories?.filter((x) => x !== category)
+ : [...(activeCategories ?? []), category];
+ setCategories(newCategories.length === 0 ? null : newCategories);
+ };
return (
@@ -48,12 +54,8 @@ export const EventFilter = ({
-
@@ -102,34 +104,38 @@ export const EventFilter = ({
export const EventFilterExplained = ({
eventCategories,
- activeCategory,
+ activeCategories,
eventOrganizers,
activeOrganizer,
venues,
activeVenue,
}: {
eventCategories: EventCategory[];
- activeCategory: string | null;
+ activeCategories: string[] | null;
eventOrganizers: EventOrganizer[];
activeOrganizer: string | null;
venues: VenueFragment[];
activeVenue: string | null;
}) => {
- const category =
- activeCategory && eventCategories.find((x) => x.slug === activeCategory);
+ const categories = eventCategories.filter((x) =>
+ activeCategories?.includes(x.slug)
+ );
const organizer =
activeOrganizer && eventOrganizers.find((x) => x.slug === activeOrganizer);
const venue = activeVenue && venues.find((x) => x.slug === activeVenue);
+ const categoryList = formatHumanReadableList(categories.map((x) => x.name));
+ const hasCategories = categoryList.length !== 0;
+
let text = "";
- if (category && organizer && venue) {
- text = `${category.name} av ${organizer.name} ${venue.preposition} ${venue.title}`;
- } else if (category && organizer) {
- text = `${category.name} av ${organizer.name}`;
- } else if (category && venue) {
- text = `${category.name} ${venue.preposition} ${venue.title}`;
- } else if (category) {
- text = `${category.name}`;
+ if (hasCategories && organizer && venue) {
+ text = `${categoryList} av ${organizer.name} ${venue.preposition} ${venue.title}`;
+ } else if (hasCategories && organizer) {
+ text = `${categoryList} av ${organizer.name}`;
+ } else if (hasCategories && venue) {
+ text = `${categoryList} ${venue.preposition} ${venue.title}`;
+ } else if (hasCategories) {
+ text = `${categoryList}`;
} else if (organizer && venue) {
text = `Arrangeres av ${organizer.name} ${venue.preposition} ${venue.title}`;
} else if (organizer) {
diff --git a/web/src/lib/common.ts b/web/src/lib/common.ts
index 72265af..6111bed 100644
--- a/web/src/lib/common.ts
+++ b/web/src/lib/common.ts
@@ -76,6 +76,21 @@ export function formatNorwegianPhoneNumber(phone: string): string {
return phone;
}
+export function formatHumanReadableList(array: (string | number)[]): string {
+ const length = array.length;
+
+ if (length === 0) {
+ return "";
+ }
+ if (length === 1) {
+ return array[0].toString();
+ }
+ if (length === 2) {
+ return array.join(" og ");
+ }
+ return array.slice(0, -1).join(", ") + " og " + array[length - 1];
+}
+
const OneLevelOfBlocksFragmentDefinition = graphql(`
fragment OneLevelOfBlocks on StreamFieldInterface {
id