Skip to content

Commit

Permalink
feat: add event creation page
Browse files Browse the repository at this point in the history
  • Loading branch information
Thechi2000 committed Aug 9, 2024
1 parent c45363e commit 053d51b
Show file tree
Hide file tree
Showing 6 changed files with 242 additions and 4 deletions.
113 changes: 110 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,14 @@
"@directus/sdk": "^15.0.0",
"@prisma/client": "^5.15.0",
"@types/jsonwebtoken": "^9.0.6",
"formik": "^2.4.6",
"jsonwebtoken": "^9.0.2",
"next": "^14.1.1",
"next-i18n-router": "^5.5.1",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-markdown": "^9.0.1"
"react-markdown": "^9.0.1",
"yup": "^1.4.0"
},
"devDependencies": {
"@types/node": "20.4.5",
Expand Down
86 changes: 86 additions & 0 deletions src/app/[lang]/admin/new/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
'use client';

import { ErrorMessage, Field, Form, Formik } from 'formik';
import { useRef } from 'react';
import * as Yup from 'yup';
import { createEvent } from '../../../../db/events';

const validator = Yup.object({
name: Yup.string()
.required('Required')
.min(5, 'Must be at least 5 characters')
.max(50, 'Must be at most 50 characters')
.matches(
/^(\w|\d)+( (\w|\d)+)*$/,
'Must only contain alphanumeric characters and spaces'
),
slug: Yup.string().matches(
/^[a-z0-9]+(?:-[a-z0-9]+)*$/,
'Must be pascal-case'
),
directusId: Yup.number().required('Required').min(0),
startTime: Yup.date().required('Required'),
endTime: Yup.date().required('Required'),
staffingSlotSize: Yup.number().required('Required').min(15),
});

export default function Page() {
const slugInput = useRef<HTMLInputElement>(null);

return (
<Formik
initialValues={{
name: '',
slug: '',
directusId: 0,
startTime: '',
endTime: '',
staffingSlotSize: 15,
}}
onSubmit={(v) => createEvent(v)}
validationSchema={validator}
validateOnBlur
validateOnMount
validateOnChange
>
<Form>
<label htmlFor="name">Name:</label>
<Field id="name" name="name" placeholder="My event" />
<ErrorMessage name="name" />
<br />

<label htmlFor="slug">Slug (leave empty for default):</label>
<Field
id="slug"
name="slug"
placeholder="my-event"
innerRef={slugInput}
/>
<ErrorMessage name="slug" />
<br />

<label htmlFor="directusId">Directus id:</label>
<Field id="directusId" name="directusId" type="number" />
<ErrorMessage name="directusId" />
<br />

<label htmlFor="startTime">Start:</label>
<Field id="startTime" name="startTime" type="datetime-local" />
<ErrorMessage name="startTime" />
<br />

<label htmlFor="endTime">End:</label>
<Field id="endTime" name="endTime" type="datetime-local" />
<ErrorMessage name="endTime" />
<br />

<label htmlFor="staffingSlotSize">Staffing slot size:</label>
<Field id="staffingSlotSize" name="staffingSlotSize" type="number" />
<ErrorMessage name="staffingSlotSize" />
<br />

<button type="submit">Create</button>
</Form>
</Formik>
);
}
38 changes: 38 additions & 0 deletions src/db/events.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
'use server';

import prisma from '../db';
import { hasValidAdminSession } from '../session';
import { ApiError, ApiResult, Err, Ok } from '../utils';

function convertNameToSlug(name: string) {
return name.replaceAll(/[_ ]/g, '-').toLocaleLowerCase();
}

export async function createEvent(event: {
name: string;
slug: string;
directusId: number;
startTime: string;
endTime: string;
}): Promise<ApiResult<Event>> {
if (!(await hasValidAdminSession())) {
return Err(ApiError.Forbidden);
}

console.log(event.startTime, typeof event.startTime);

const e: Event = await prisma.event.create({
data: {
name: event.name,
slug: event.slug || convertNameToSlug(event.name),
directusId: event.directusId.toString(),
mailTemplate: '',
eventStartTime: new Date(event.startTime).toISOString(),
eventEndTime: new Date(event.endTime).toISOString(),
staffingTimeSlotSize: 30,
data: {},
},
});

return Ok(e);
}
4 changes: 4 additions & 0 deletions src/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,7 @@ export async function deleteAdminSession() {
cookies().delete(ADMIN_SESSION_COOKIE);
revalidatePath('/admin', 'layout');
}

export async function hasValidAdminSession(): Promise<boolean> {
return (await getVerifiedAdminSession()) !== null;
}
1 change: 1 addition & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,4 +91,5 @@ export async function Err<R>(error: ApiError): Promise<ApiResult<R>> {

export enum ApiError {
AlreadyRegistered = 'already_registered',
Forbidden = 'forbidden',
}

0 comments on commit 053d51b

Please sign in to comment.