Provide a basic account system with login and server side session store identified by a cookie. Upon successful login a signed session cookie is set by the server with the session stored on the server identifying which account it is logged in as. The client uses a shared useFetch on the session endpoint to identify if it's logged in and which account it is logged in as, and refreshes this when loggin in or out.
179 lines
4.5 KiB
TypeScript
179 lines
4.5 KiB
TypeScript
import { Account } from "~/shared/types/account";
|
|
import { Schedule, TimeSlot } from "~/shared/types/schedule";
|
|
|
|
const locations = [
|
|
{
|
|
name: "Stage",
|
|
description: "Inside the main building."
|
|
},
|
|
{
|
|
name: "Clubhouse",
|
|
description: "That big red building in the middle of the park."
|
|
},
|
|
{
|
|
name: "Summerhouse",
|
|
description: "Next to the campfire by the lake"
|
|
},
|
|
{
|
|
name: "Campfire",
|
|
description: "Next to the big tree by the lake."
|
|
},
|
|
{
|
|
name: "Outside",
|
|
description: "Takes place somewhere outside."
|
|
}
|
|
]
|
|
|
|
const events = [
|
|
{
|
|
name: "Arcade",
|
|
description: "Play retro games!",
|
|
slots: [
|
|
"d1 12:00 4h clubhouse",
|
|
"d2 12:00 4h clubhouse",
|
|
"d3 12:00 4h clubhouse",
|
|
]
|
|
},
|
|
{
|
|
name: "Bonfire Stories",
|
|
description: "Share your stories as we sit cosily around the campfire.",
|
|
slots: ["d2 18:00 2h campfire"]
|
|
},
|
|
{ name: "DJ Alpha", slots: ["d2 20:00 2h stage"] },
|
|
{ name: "DJ Bravo", slots: ["d3 20:00 2h stage"] },
|
|
{ name: "DJ Charlie", slots: ["d3 22:00 2h stage"] },
|
|
{
|
|
name: "Fursuit Games",
|
|
description: "Playful time for the suiters.",
|
|
slots: ["d4 18:00 2h clubhouse"],
|
|
},
|
|
{ name: "Fishing Trip", slots: ["d3 12:00 3h30m outside"]},
|
|
{ name: "Opening", slots: ["d1 18:30 1h30m stage"]},
|
|
{ name: "Closing", slots: ["d5 16:00 1h stage"]},
|
|
{
|
|
name: "Board Games",
|
|
slots: [
|
|
"d1 12:00 4h summerhouse",
|
|
"d2 12:00 4h summerhouse",
|
|
"d3 12:00 4h summerhouse",
|
|
"d4 12:00 4h summerhouse",
|
|
]
|
|
},
|
|
{ name: "📷meet", slots: ["d3 19:00 1h10m summerhouse"]},
|
|
{
|
|
name: "Karaoke",
|
|
slots: [
|
|
"d3 21:00 2h clubhouse",
|
|
"d4 21:00 2h clubhouse",
|
|
],
|
|
},
|
|
{ name: "Dance", slots: ["d1 20:00 3h stage"]},
|
|
{ name: "Charity Auction", slots: ["d4 13:00 2h stage"]},
|
|
{ name: "Tournament", slots: ["d2 17:00 2h stage"]},
|
|
{ name: "Canoe Trip", slots: ["d4 11:00 4h30m outside"]},
|
|
{
|
|
name: "Dinner",
|
|
slots: [
|
|
"d1 16:00 1h campfire",
|
|
"d2 16:00 1h campfire",
|
|
"d3 16:00 1h campfire",
|
|
"d4 16:00 1h campfire",
|
|
],
|
|
},
|
|
{ name: "Film Night", slots: ["d4 21:00 2h stage"]},
|
|
{ name: "Photo", slots: ["d3 18:00 45m stage"]},
|
|
{ name: "Artist Alley", slots: ["d4 12:00 4h clubhouse"]},
|
|
{ name: "Feedback Panel", slots: ["d5 18:00 4h clubhouse"]},
|
|
];
|
|
|
|
function toId(name: string) {
|
|
return name.toLowerCase().replace(/ /g, "-");
|
|
}
|
|
|
|
function toIso(date: Date) {
|
|
return date.toISOString().replace(":00.000Z", "Z");
|
|
}
|
|
|
|
function toSlot(origin: Date, id: string, shorthand: string, index: number): TimeSlot {
|
|
const [day, start, duration, location] = shorthand.split(" ");
|
|
const [startHours, startMinutes] = start.split(":").map(time => parseInt(time, 10));
|
|
const dayNumber = parseInt(day.slice(1));
|
|
|
|
const startDate = new Date(origin);
|
|
startDate.setUTCDate(startDate.getUTCDate() + dayNumber);
|
|
startDate.setUTCHours(startDate.getUTCHours() + startHours);
|
|
startDate.setUTCMinutes(startDate.getUTCMinutes() + startMinutes);
|
|
|
|
const [_, durationHours, durationMinutes] = /(?:(\d+)h)?(?:(\d+)m)?/.exec(duration)!;
|
|
const durationTotal = parseInt(durationHours ?? "0") * 60 + parseInt(durationMinutes ?? "0")
|
|
const endDate = new Date(startDate.getTime() + durationTotal * 60e3);
|
|
|
|
return {
|
|
id: `${id}-${index}`,
|
|
start: toIso(startDate),
|
|
end: toIso(endDate),
|
|
locations: [location],
|
|
};
|
|
}
|
|
|
|
export function generateDemoSchedule(): Schedule {
|
|
const origin = new Date();
|
|
const utcOffset = 1;
|
|
origin.setUTCDate(origin.getUTCDate() - origin.getUTCDay() + 1); // Go to Monday
|
|
origin.setUTCHours(utcOffset);
|
|
origin.setUTCMinutes(0);
|
|
origin.setUTCSeconds(0);
|
|
origin.setUTCMilliseconds(0);
|
|
|
|
return {
|
|
events: events.map(
|
|
({ name, description, slots }) => ({
|
|
id: toId(name),
|
|
name,
|
|
description,
|
|
slots: slots.map((shorthand, index) => toSlot(origin, toId(name), shorthand, index))
|
|
})
|
|
),
|
|
locations: locations.map(
|
|
({ name, description }) => ({ id: toId(name), name, description })
|
|
),
|
|
};
|
|
}
|
|
|
|
const names = [
|
|
"Leo", "Lisa",
|
|
"Jack", "Emily",
|
|
"Roy", "Sofia",
|
|
"Adam", "Eve",
|
|
"Max", "Rose",
|
|
"Hugo", "Maria",
|
|
"David", "Zoe",
|
|
"Hunter", "Ria",
|
|
"Sonny", "Amy",
|
|
"Kai", "Megan",
|
|
"Toby", "Katie",
|
|
"Bob", "Lucy",
|
|
];
|
|
|
|
// MINSTD random implementation for reproducible random numbers.
|
|
let seed = 1;
|
|
function random() {
|
|
const a = 48271;
|
|
const c = 0;
|
|
const m = 2 ** 31 -1;
|
|
return (seed = (a * seed + c) % m | 0) / 2 ** 31;
|
|
}
|
|
|
|
export function generateDemoAccounts(): Account[] {
|
|
seed = 1;
|
|
const accounts: Account[] = [];
|
|
|
|
for (const name of names) {
|
|
accounts.push({
|
|
id: accounts.length,
|
|
name,
|
|
type: (["regular", "crew", "admin"] as const)[Math.floor(random() ** 5 * 3)],
|
|
});
|
|
}
|
|
return accounts;
|
|
}
|