Skip to content

Commit

Permalink
feat(admin): events management (#7)
Browse files Browse the repository at this point in the history
Co-authored-by: Ethan Chew <chew_ming_hong_ethan@s2019.ssts.edu.sg>
  • Loading branch information
qin-guan and Ethan-Chew authored Jan 6, 2024
1 parent ab41acf commit 2d019d2
Show file tree
Hide file tree
Showing 57 changed files with 3,496 additions and 3,056 deletions.
2 changes: 2 additions & 0 deletions app.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
<NuxtLayout>
<NuxtPage />
</NuxtLayout>

<UNotifications />
</div>
</template>

Expand Down
42 changes: 0 additions & 42 deletions components/admin/common/left-panel.vue

This file was deleted.

103 changes: 103 additions & 0 deletions components/admin/event/create-popup.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<script setup lang="ts">
import type { FormSubmitEvent } from '@nuxt/ui/dist/runtime/types'
import { z } from 'zod'
const visible = defineModel<boolean>('visible')
const dayjs = useDayjs()
const toast = useToast()
const schema = z.object({
name: z.string()
.min(1, 'Please enter a name'),
description: z.string(),
location: z.string(),
badgeImage: z.string()
.url('Please enter a URL'),
startDateTime: z.string()
.refine(val => dayjs(val).isAfter(dayjs()), 'Start date must be in the future')
.transform(d => dayjs(d).unix().toString()),
endDateTime: z.string()
.transform(d => dayjs(d).unix().toString()),
}).refine((val) => {
return Number.parseInt(val.startDateTime) < Number.parseInt(val.endDateTime)
}, {
message: 'Event must end after it starts',
path: ['endDateTime'],
})
type Schema = z.output<typeof schema>
const state = reactive({
name: '',
description: '',
location: '',
badgeImage: '',
startDateTime: '',
endDateTime: '',
})
const { mutate: createEventMutate, isPending: createEventIsPending } = useCreateEventMutation()
function createEvent({ data }: FormSubmitEvent<Schema>) {
createEventMutate(data, {
onSuccess() {
visible.value = false
},
onError(err) {
toast.add({
title: err.message,
})
},
})
}
</script>

<template>
<UModal v-model="visible">
<UCard>
<template #header>
<div class="flex justify-between items-start">
<div>
<h1 class="text-xl font-semibold">
Create event
</h1>
<p class="text-sm opacity-80">
Add a new event hosted by SSTAA!
</p>
</div>
<UButton color="gray" variant="ghost" icon="i-heroicons-x-mark-20-solid" @click="visible = false" />
</div>
</template>

<UForm :state="state" :schema="schema" class="space-y-7" @submit="createEvent">
<div class="space-y-5">
<UFormGroup label="Name" name="name">
<UInput v-model="state.name" placeholder="SST Homecoming" />
</UFormGroup>
<UFormGroup label="Description" name="description">
<UTextarea
v-model="state.description"
placeholder="Come back to 1 Technology Drive for our inaugural homecoming!"
/>
</UFormGroup>
<UFormGroup label="Location" name="location">
<UInput v-model="state.location" placeholder="1 Technology Drive, Singapore" />
</UFormGroup>
<UFormGroup label="Badge image" name="badgeImage">
<UInput v-model="state.badgeImage" type="url" placeholder="https://app.sstaa.org/cdn/logo.png" />
</UFormGroup>
<UFormGroup label="Start" name="startDateTime">
<UInput v-model="state.startDateTime" after="" type="datetime-local" />
</UFormGroup>
<UFormGroup label="End" name="endDateTime">
<UInput v-model="state.endDateTime" type="datetime-local" />
</UFormGroup>
</div>

<UButton type="submit" :loading="createEventIsPending">
Create event
</UButton>
</UForm>
</UCard>
</UModal>
</template>
9 changes: 0 additions & 9 deletions components/admin/event/page.vue

This file was deleted.

91 changes: 91 additions & 0 deletions components/admin/event/update-form.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<script setup lang="ts">
import type { FormSubmitEvent } from '@nuxt/ui/dist/runtime/types'
import { z } from 'zod'
const props = defineProps<{
id: string
name: string
description?: string | null
location?: string | null
badgeImage?: string | null
startDateTime: number
endDateTime: number
}>()
const toast = useToast()
const dayjs = useDayjs()
const state = reactive({
name: props.name,
description: props.description ?? '',
location: props.location ?? '',
badgeImage: props.badgeImage ?? '',
startDateTime: dayjs.unix(props.startDateTime).toISOString(),
endDateTime: dayjs.unix(props.endDateTime).toISOString(),
})
const schema = z.object({
name: z.string()
.min(1, 'Please enter a name'),
description: z.string(),
location: z.string(),
badgeImage: z.string()
.url('Please enter a URL'),
startDateTime: z.string()
.refine(val => dayjs(val).isAfter(dayjs()), 'Start date must be in the future')
.transform(d => dayjs(d).unix().toString()),
endDateTime: z.string()
.transform(d => dayjs(d).unix().toString()),
}).refine((val) => {
return dayjs(val.startDateTime).isBefore(val.endDateTime)
}, {
message: 'Event must end after it starts',
path: ['endDateTime'],
})
type Schema = z.output<typeof schema>
const { mutate: updateEventMutate, isPending: updateEventIsPending } = useUpdateEventMutation(props.id)
function updateEvent({ data }: FormSubmitEvent<Schema>) {
updateEventMutate(data, {
onError(err) {
toast.add({
title: err.message,
})
},
})
}
</script>

<template>
<UForm :state="state" :schema="schema" class="space-y-7" @submit="updateEvent">
<div class="space-y-5">
<UFormGroup label="Name" name="name">
<UInput v-model="state.name" placeholder="SST Homecoming" />
</UFormGroup>
<UFormGroup label="Description" name="description">
<UTextarea
v-model="state.description"
placeholder="Come back to 1 Technology Drive for our inaugural homecoming!"
/>
</UFormGroup>
<UFormGroup label="Location" name="location">
<UInput v-model="state.location" placeholder="1 Technology Drive, Singapore" />
</UFormGroup>
<UFormGroup label="Badge image" name="badgeImage">
<UInput v-model="state.badgeImage" type="url" placeholder="https://app.sstaa.org/cdn/logo.png" />
</UFormGroup>
<UFormGroup label="Start" name="startDateTime">
<UInput v-model="state.startDateTime" after="" type="datetime-local" />
</UFormGroup>
<UFormGroup label="End" name="endDateTime">
<UInput v-model="state.endDateTime" type="datetime-local" />
</UFormGroup>
</div>

<UButton type="submit" :loading="updateEventIsPending">
Update
</UButton>
</UForm>
</template>
13 changes: 13 additions & 0 deletions components/admin/forbidden.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<template>
<UContainer>
<h1 class="text-3xl">
Forbidden :/
</h1>
<p class="text-lg">
You do not have access to this page. That's all we know.
</p>
<UButton to="/app" target="_blank" size="lg" color="blue">
Return to app
</UButton>
</UContainer>
</template>
70 changes: 0 additions & 70 deletions components/admin/home/events-table.vue

This file was deleted.

21 changes: 0 additions & 21 deletions components/admin/home/forbidden.vue

This file was deleted.

Loading

0 comments on commit 2d019d2

Please # to comment.