75 lines
2.3 KiB
TypeScript
75 lines
2.3 KiB
TypeScript
import { fail, redirect } from '@sveltejs/kit';
|
|
import type { Actions, PageServerLoad } from './$types';
|
|
import { requireUser } from '#lib/server/auth.js';
|
|
import { createShow, listShows, listShowTemplates } from '#lib/server/shows.js';
|
|
|
|
function berlinLocalToUtc(value: string): string | null {
|
|
if (!value) return null;
|
|
const match = /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})$/.exec(value);
|
|
if (!match) throw new Error('INVALID_TIMESTAMP');
|
|
const parts = match.slice(1).map(Number);
|
|
const localMilliseconds = Date.UTC(parts[0], parts[1] - 1, parts[2], parts[3], parts[4]);
|
|
let candidate = localMilliseconds;
|
|
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
const formatted = new Intl.DateTimeFormat('en-CA', {
|
|
timeZone: 'Europe/Berlin',
|
|
year: 'numeric',
|
|
month: '2-digit',
|
|
day: '2-digit',
|
|
hour: '2-digit',
|
|
minute: '2-digit',
|
|
hourCycle: 'h23'
|
|
}).formatToParts(new Date(candidate));
|
|
const read = (type: Intl.DateTimeFormatPartTypes) =>
|
|
Number(formatted.find((part) => part.type === type)?.value);
|
|
const represented = Date.UTC(
|
|
read('year'),
|
|
read('month') - 1,
|
|
read('day'),
|
|
read('hour'),
|
|
read('minute')
|
|
);
|
|
candidate += localMilliseconds - represented;
|
|
}
|
|
return new Date(candidate).toISOString();
|
|
}
|
|
|
|
export const load: PageServerLoad = ({ locals }) => {
|
|
requireUser(locals.user);
|
|
return { shows: listShows(), templates: listShowTemplates() };
|
|
};
|
|
|
|
export const actions = {
|
|
create: async ({ locals, request }) => {
|
|
requireUser(locals.user);
|
|
const data = await request.formData();
|
|
const title = String(data.get('title') || '');
|
|
const startsAt = String(data.get('startsAt') || '');
|
|
const templateId = String(data.get('templateId') || '') || null;
|
|
let id: string;
|
|
try {
|
|
id = createShow({ title, startsAtUtc: berlinLocalToUtc(startsAt), templateId }).id;
|
|
} catch (cause) {
|
|
const code = cause instanceof Error ? cause.message : '';
|
|
if (code === 'INVALID_TITLE') {
|
|
return fail(400, { error: 'Bitte einen Titel eingeben.', title, startsAt, templateId });
|
|
}
|
|
if (code === 'INVALID_TIMESTAMP') {
|
|
return fail(400, {
|
|
error: 'Bitte einen gültigen Termin eingeben.',
|
|
title,
|
|
startsAt,
|
|
templateId
|
|
});
|
|
}
|
|
return fail(400, {
|
|
error: 'Die Sendung konnte nicht angelegt werden.',
|
|
title,
|
|
startsAt,
|
|
templateId
|
|
});
|
|
}
|
|
redirect(303, `/sendungen/${id}`);
|
|
}
|
|
} satisfies Actions;
|