diff --git a/app/App.tsx b/app/App.tsx
index cd44f77..7db29cb 100644
--- a/app/App.tsx
+++ b/app/App.tsx
@@ -1,43 +1,73 @@
"use client";
-import { useState } from "react";
+import { useState, useEffect } from "react";
import Map from "./Map";
import RoomSelect from "./RoomSelect";
+import MapSelect from "./MapSelect";
import InfoPanel from "./InfoPanel";
import config from "./config";
-import { Room } from "./config.types";
-import { set } from "ol/transform";
+import { Map as MapConfig, Room } from "./config.types";
-export default function App({ roomId }: { roomId?: string }) {
- const room = config.map.rooms.find((room) => room.id === roomId);
+export default function App({
+ mapId,
+ roomId,
+}: {
+ mapId?: string;
+ roomId?: string;
+}) {
+ const map = config.maps.find((m) => m.id === mapId) || config.maps[0];
+ const room = map.rooms.find((room) => room.id === roomId);
+ const [selectedMap, setSelectedMap] = useState {room.label}
- {room.aliases.join(", ")}
+ {secondaryText.join(", ")}
{config.attributions.map((attribution, i) => (
@@ -29,7 +48,9 @@ export default function About() {
← {t("back")}
{t.rich("powered-by", {
GitHubLink: () => (
diff --git a/app/config.ts b/app/config.ts
index 43f309c..d1cac65 100644
--- a/app/config.ts
+++ b/app/config.ts
@@ -26,46 +26,49 @@ const config: Config = {
accent: "rgb(8,114,50)",
disabled: "#cbd5e1",
},
- map: {
- src: "/map.png",
- rooms: [
- {
- id: "silent-room",
- label: "Silent room",
- aliases: ["Jackfield Boardroom"],
- description: `
+ maps: [
+ {
+ id: "ground",
+ label: "Ground floor",
+ src: "/ground.png",
+ rooms: [
+ {
+ id: "silent-room",
+ label: "Silent room",
+ aliases: ["Jackfield Boardroom"],
+ description: `
This is a room intended for sitting in silence, where no activities
are allowed (including reading or using your phone). This will be
available each day from 11am. Note, there may be noise leaking from
neighbouring rooms, and the aircon makes some noise, so do bring noise
cancelling headphones if you need complete silence.
`,
- area: [
- [202, 499],
- [255, 499],
- [255, 550],
- [202, 550],
- ],
- },
- {
- id: "pattingham",
- label: "Pattingham",
- aliases: ["Programme"],
- description: `
+ area: [
+ [373, 551],
+ [426, 551],
+ [426, 602],
+ [373, 602],
+ ],
+ },
+ {
+ id: "pattingham",
+ label: "Pattingham",
+ aliases: ["Programme"],
+ description: `
[Programme schedule](https://guide.example.co.uk/pattingham)
`,
- area: [
- [262, 470],
- [363, 470],
- [363, 550],
- [262, 550],
- ],
- },
- {
- id: "ops-help-desk",
- label: "Ops Help Desk",
- aliases: ["Beckbury 1", "Beckbury 2"],
- description: `
+ area: [
+ [433, 522],
+ [534, 522],
+ [534, 602],
+ [433, 602],
+ ],
+ },
+ {
+ id: "ops-help-desk",
+ label: "Ops Help Desk",
+ aliases: ["Beckbury 1", "Beckbury 2"],
+ description: `
If you need help with anything, this is the place to go. We can help
with lost property, lost people, and any other issues you might have.
This is also where the volunteers desk is.
@@ -80,121 +83,128 @@ const config: Config = {
Monday: 9:30am-11pm
`,
- area: [
- [270, 655],
- [363, 655],
- [363, 728],
- [270, 728],
- ],
- },
- {
- id: "newsletter",
- label: "Newsletter",
- aliases: ["Beckbury 3"],
- description: `
+ area: [
+ [441, 707],
+ [534, 707],
+ [534, 780],
+ [441, 780],
+ ],
+ },
+ {
+ id: "newsletter",
+ label: "Newsletter",
+ aliases: ["Beckbury 3"],
+ description: `
Office for the newsletter team. If you want to submit something to the
newsletter, email
[newsletter@example.org](mailto:newsletter@example.org).
`,
- area: [
- [371, 655],
- [414, 655],
- [414, 728],
- [371, 728],
- ],
- },
- {
- id: "quiet-activities",
- label: "Quiet activities",
- aliases: ["Beckbury 4"],
- description: `
+ area: [
+ [542, 707],
+ [585, 707],
+ [585, 780],
+ [542, 780],
+ ],
+ },
+ {
+ id: "quiet-activities",
+ label: "Quiet activities",
+ aliases: ["Beckbury 4"],
+ description: `
A place where you may do a jigsaw or read a book/electronic item, but
may not make phone calls.
`,
- area: [
- [422, 655],
- [462, 655],
- [462, 728],
- [422, 728],
- ],
- },
- {
- id: "games",
- label: "Games",
- aliases: ["Ryton"],
- description: `
+ area: [
+ [593, 707],
+ [633, 707],
+ [633, 780],
+ [593, 780],
+ ],
+ },
+ {
+ id: "games",
+ label: "Games",
+ aliases: ["Ryton"],
+ description: `
Play games with friends, or make new friends by joining a game. There
will be a selection of games available, or you can bring your own.
`,
- area: [
- [884, 500],
- [942, 500],
- [942, 550],
- [884, 550],
- ],
- },
- {
- id: "toilets-ground-floor",
- label: "Toilets (ground floor)",
- aliases: [
- "Male toilets",
- "Female toilets",
- "Accessible toilets",
- "Disabled toilets",
- ],
- description: `
+ area: [
+ [1055, 552],
+ [1113, 552],
+ [1113, 602],
+ [1055, 602],
+ ],
+ },
+ {
+ id: "toilets-ground-floor",
+ label: "Toilets (ground floor)",
+ aliases: [
+ "Male toilets",
+ "Female toilets",
+ "Accessible toilets",
+ "Disabled toilets",
+ ],
+ description: `
Gender neutral toilets are available on the first floor.
`,
- area: [
- [852, 344],
- [1055, 344],
- [1055, 382],
- [852, 382],
- ],
- },
- {
- id: "stairs-ground",
- label: "Stairs (ground floor)",
- area: [
- [311, 585],
- [484, 585],
- [484, 615],
- [311, 615],
- ],
- },
- {
- id: "lift-small-ground",
- label: "Lift (small, ground floor)",
- description: `
+ area: [
+ [1023, 396],
+ [1226, 396],
+ [1226, 434],
+ [1023, 434],
+ ],
+ },
+ {
+ id: "stairs-ground",
+ label: "Stairs (ground floor)",
+ description: `
+ Connects to [first floor](/map/first/room/stairs-first).
+ `,
+ area: [
+ [482, 637],
+ [655, 637],
+ [655, 667],
+ [482, 667],
+ ],
+ },
+ {
+ id: "lift-small-ground",
+ label: "Lift (small, ground floor)",
+ description: `
This lift is small and can only fit one wheelchair user at a time.
If you are able to, please take the stairs. If you need a larger lift,
please use the lift near the E4 entrance.
+
+ Connects to [first floor](/map/first/room/lift-small-first).
`,
- area: [
- [590, 585],
- [621, 585],
- [621, 615],
- [590, 615],
- ],
- },
- {
- id: "lift-large-ground",
- label: "Lift (large, ground floor)",
- description: `
+ area: [
+ [761, 637],
+ [792, 637],
+ [792, 667],
+ [761, 667],
+ ],
+ },
+ {
+ id: "lift-large-ground",
+ label: "Lift (large, ground floor)",
+ description: `
You will need to ask a member of staff to call the lift for you.
+
+ Connects to [first floor](/map/first/room/lift-large-first).
`,
- area: [
- [1123, 149],
- [1193, 149],
- [1193, 209],
- [1123, 209],
- ],
- },
- {
- id: "e1",
- label: "E1",
- aliases: ["Entrance 1", "Car park"],
- description: `
+ area: [
+ [1294, 201],
+ [1364, 201],
+ [1364, 261],
+ [1294, 261],
+ ],
+ },
+ {
+ id: "e1",
+ label: "E1",
+ aliases: ["Entrance 1", "Car park"],
+ description: `
# Opening times
Friday: 9:30am - 11:00pm
@@ -205,18 +215,18 @@ const config: Config = {
Monday: 9:30am-11pm
`,
- area: [
- [1008, 690],
- [1170, 690],
- [1170, 808],
- [1008, 808],
- ],
- },
- {
- id: "e2",
- label: "E2",
- aliases: ["Entrance 2"],
- description: `
+ area: [
+ [1179, 742],
+ [1341, 742],
+ [1341, 860],
+ [1179, 860],
+ ],
+ },
+ {
+ id: "e2",
+ label: "E2",
+ aliases: ["Entrance 2"],
+ description: `
# Opening times
Friday: 9:30am - 11:00pm
@@ -227,29 +237,29 @@ const config: Config = {
Monday: 9:30am-11pm
`,
- area: [
- [470, 654],
- [632, 654],
- [632, 808],
- [470, 808],
- ],
- },
- {
- id: "e3",
- label: "E3",
- aliases: ["Entrance 3"],
- area: [
- [44, 706],
- [233, 655],
- [233, 808],
- [44, 808],
- ],
- },
- {
- id: "e4",
- label: "E4",
- aliases: ["Entrance 4", "Hotels"],
- description: `
+ area: [
+ [641, 706],
+ [803, 706],
+ [803, 860],
+ [641, 860],
+ ],
+ },
+ {
+ id: "e3",
+ label: "E3",
+ aliases: ["Entrance 3"],
+ area: [
+ [215, 758],
+ [404, 707],
+ [404, 860],
+ [215, 860],
+ ],
+ },
+ {
+ id: "e4",
+ label: "E4",
+ aliases: ["Entrance 4", "Hotels"],
+ description: `
# Opening times
Friday: 9:30am - 11:00pm
@@ -260,32 +270,39 @@ const config: Config = {
Monday: 9:30am-11pm
`,
- area: [
- [1008, 35],
- [1170, 35],
- [1170, 150],
- [1008, 150],
- ],
- },
- {
- id: "ironbridge",
- label: "Ironbridge",
- aliases: ["Programme"],
- description: `
+ area: [
+ [1179, 87],
+ [1341, 87],
+ [1341, 202],
+ [1179, 202],
+ ],
+ },
+ ],
+ },
+ {
+ id: "first",
+ label: "First floor",
+ src: "/first.png",
+ rooms: [
+ {
+ id: "ironbridge",
+ label: "Ironbridge",
+ aliases: ["Programme"],
+ description: `
[Programme schedule](https://guide.example.co.uk/ironbridge)
`,
- area: [
- [1321, 363],
- [1457, 363],
- [1457, 613],
- [1332, 647],
- [1321, 565],
- ],
- },
- {
- id: "dealers",
- label: "Dealers & Fan Tables",
- description: `
+ area: [
+ [86, 413],
+ [222, 413],
+ [222, 663],
+ [97, 697],
+ [86, 615],
+ ],
+ },
+ {
+ id: "dealers",
+ label: "Dealers & Fan Tables",
+ description: `
A selection of dealers and fan tables will be available for you to
browse. Please note that some dealers may only accept cash.
@@ -299,33 +316,33 @@ const config: Config = {
Monday: 10am-2pm
`,
- area: [
- [1465, 363],
- [1576, 363],
- [1576, 426],
- [1608, 426],
- [1608, 544],
- [1465, 581],
- ],
- },
- {
- id: "childcare",
- label: "Childcare",
- description: `
+ area: [
+ [230, 413],
+ [341, 413],
+ [341, 476],
+ [373, 476],
+ [373, 594],
+ [230, 631],
+ ],
+ },
+ {
+ id: "childcare",
+ label: "Childcare",
+ description: `
Childcare must have been pre-booked. If you have not pre-booked, you
will not be able to use this service.
`,
- area: [
- [1576, 363],
- [1576, 426],
- [1639, 426],
- [1639, 363],
- ],
- },
- {
- id: "art-show",
- label: "Art show",
- description: `
+ area: [
+ [341, 413],
+ [341, 476],
+ [404, 476],
+ [404, 413],
+ ],
+ },
+ {
+ id: "art-show",
+ label: "Art show",
+ description: `
The art show will be open from 10am-6pm each day. Please note that
some pieces may be for sale.
@@ -337,143 +354,151 @@ const config: Config = {
Sunday: 10am-5pm (collection of purchased art, 4pm-6:30pm)
`,
- area: [
- [1639, 363],
- [1752, 363],
- [1752, 505],
- [1608, 544],
- [1608, 426],
- [1639, 426],
- ],
- },
- {
- id: "toilets-first-floor",
- label: "Toilets (first floor)",
- aliases: ["Urinals", "Without urinals", "Accessible"],
- description: `
+ area: [
+ [404, 413],
+ [517, 413],
+ [517, 555],
+ [373, 594],
+ [373, 476],
+ [404, 476],
+ ],
+ },
+ {
+ id: "toilets-first-floor",
+ label: "Toilets (first floor)",
+ aliases: ["Urinals", "Without urinals", "Accessible"],
+ description: `
Gender neutral toilets with and without urinals.
`,
- area: [
- [1760, 434],
- [1867, 434],
- [1867, 504],
- [1760, 504],
- ],
- },
- {
- id: "green-room",
- label: "Green room",
- description: `
+ area: [
+ [525, 484],
+ [632, 484],
+ [632, 554],
+ [525, 554],
+ ],
+ },
+ {
+ id: "green-room",
+ label: "Green room",
+ description: `
Programme participants should arrive at the green room 15 minutes
before their item starts. Here you will meet with your fellow
panellists (both in-person and online) and discuss the item before it
starts. You will also be offered a complementary drink.
`,
- area: [
- [1584, 674],
- [1677, 674],
- [1677, 747],
- [1584, 747],
- ],
- },
- {
- id: "Wenlock",
- label: "Wenlock",
- aliases: ["Programme"],
- description: `
+ area: [
+ [349, 724],
+ [442, 724],
+ [442, 797],
+ [349, 797],
+ ],
+ },
+ {
+ id: "Wenlock",
+ label: "Wenlock",
+ aliases: ["Programme"],
+ description: `
[Programme schedule](https://guide.example.co.uk/wenlock)
`,
- area: [
- [1685, 674],
- [1776, 674],
- [1776, 747],
- [1685, 747],
- ],
- },
- {
- id: "stairs-first",
- label: "Stairs (first floor)",
- area: [
- [1754, 588],
- [1933, 588],
- [1933, 618],
- [1754, 618],
- ],
- },
- {
- id: "lift-small-first",
- label: "Lift (small, first floor)",
- description: `
+ area: [
+ [450, 724],
+ [541, 724],
+ [541, 797],
+ [450, 797],
+ ],
+ },
+ {
+ id: "stairs-first",
+ label: "Stairs (first floor)",
+ description: `
+ Connects to [ground floor](/map/ground/room/stairs-ground).
+ `,
+ area: [
+ [519, 638],
+ [698, 638],
+ [698, 668],
+ [519, 668],
+ ],
+ },
+ {
+ id: "lift-small-first",
+ label: "Lift (small, first floor)",
+ description: `
This lift is small and can only fit one wheelchair user at a time. If
you are able to, please take the stairs. If you need a larger lift,
please use the lift near the E4 entrance.
+
+ Connects to [ground floor](/map/ground/room/lift-small-ground).
`,
- area: [
- [1993, 602],
- [2024, 593],
- [2024, 623],
- [1993, 623],
- ],
- },
- {
- id: "coalport",
- label: "Coalport",
- aliases: ["Programme"],
- description: `
+ area: [
+ [758, 652],
+ [789, 643],
+ [789, 673],
+ [758, 673],
+ ],
+ },
+ {
+ id: "coalport",
+ label: "Coalport",
+ aliases: ["Programme"],
+ description: `
[Programme schedule](https://guide.example.co.uk/coalport)
`,
- area: [
- [1875, 434],
- [1977, 434],
- [1977, 504],
- [1875, 504],
- ],
- },
- {
- id: "gallary",
- label: "Gallary",
- aliases: ["Food & Drink", "Social space"],
- description: `
+ area: [
+ [640, 484],
+ [742, 484],
+ [742, 554],
+ [640, 554],
+ ],
+ },
+ {
+ id: "gallary",
+ label: "Gallary",
+ aliases: ["Food & Drink", "Social space"],
+ description: `
A place to sit and chat with friends, or to grab a bite to eat. There
will be a selection of food and drink available, including vegan and
gluten free options.
`,
- area: [
- [2029, 363],
- [2288, 363],
- [2288, 499],
- [2029, 499],
- ],
- },
- {
- id: "atcham",
- label: "Atcham",
- aliases: ["Programme"],
- description: `
+ area: [
+ [794, 413],
+ [1053, 413],
+ [1053, 549],
+ [794, 549],
+ ],
+ },
+ {
+ id: "atcham",
+ label: "Atcham",
+ aliases: ["Programme"],
+ description: `
[Programme schedule](https://guide.example.co.uk/atcham)
`,
- area: [
- [2296, 363],
- [2397, 363],
- [2397, 493],
- [2296, 493],
- ],
- },
- {
- id: "lift-large-first",
- label: "Lift (large, first floor)",
- description: `
+ area: [
+ [1061, 413],
+ [1162, 413],
+ [1162, 543],
+ [1061, 543],
+ ],
+ },
+ {
+ id: "lift-large-first",
+ label: "Lift (large, first floor)",
+ description: `
You will need to ask a member of staff to call the lift for you.
+
+ Connects to [ground floor](/map/ground/room/lift-large-ground).
`,
- area: [
- [2405, 320],
- [2468, 320],
- [2468, 369],
- [2405, 369],
- ],
- },
- ],
- },
+ area: [
+ [1170, 370],
+ [1233, 370],
+ [1233, 419],
+ [1170, 419],
+ ],
+ },
+ ],
+ },
+ ],
};
export default config;
diff --git a/app/config.types.ts b/app/config.types.ts
index 488697b..2a26dd1 100644
--- a/app/config.types.ts
+++ b/app/config.types.ts
@@ -1,4 +1,4 @@
-export interface Config {
+export type Config = {
/**
* Name of the event. Displayed in titles and about pages.
*/
@@ -66,23 +66,39 @@ export interface Config {
};
/**
- * The map to display.
+ * Maps to use for the event.
+ * If there is more than one map, a floor selector will be shown.
+ * The first map in the list is the default map.
*/
- map: {
- /**
- * Path of the map image.
- * Should be as high resolution as possible.
- */
- src: string;
- rooms: Room[];
- };
-}
+ maps: Map[];
+};
+
+export type Map = {
+ /**
+ * Unique identifier for the map. Appears in the URL.
+ */
+ id: string;
+
+ /**
+ * Label for the map. Appears in the floor selector if there are multiple maps.
+ */
+ label: string;
+
+ /**
+ * Path of the map image.
+ * Should be as high resolution as possible.
+ */
+ src: string;
-export interface Map {}
+ /**
+ * List of rooms on the map.
+ */
+ rooms: Room[];
+};
-export interface Room {
+export type Room = {
/**
- * Unique identififer for the room. Appears in the URL.
+ * Unique identifier for the room. Appears in the URL.
*/
id: string;
@@ -115,4 +131,4 @@ export interface Room {
* In the image co-oordinates; the origin is the top left corner of the image.
*/
area: [number, number][];
-}
+};
diff --git a/app/map/[map]/page.tsx b/app/map/[map]/page.tsx
new file mode 100644
index 0000000..7974c9d
--- /dev/null
+++ b/app/map/[map]/page.tsx
@@ -0,0 +1,17 @@
+import App from "../../App";
+import config from "../../config";
+
+export function generateStaticParams() {
+ return config.maps.map((map) => {
+ return { map: map.id };
+ });
+}
+
+export default async function Map({
+ params,
+}: {
+ params: Promise<{ map: string }>;
+}) {
+ const { map } = await params;
+ return