Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Empty file removed .nvmrc
Empty file.
4,228 changes: 1,172 additions & 3,056 deletions bun.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions frontend/.nuxtrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
setups.@nuxt/test-utils="4.0.0"
4 changes: 2 additions & 2 deletions frontend/app/app.config.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export default defineAppConfig({
export default {
// https://ui.nuxt.com/getting-started/theme#design-system
ui: {
button: {
Expand Down Expand Up @@ -50,4 +50,4 @@ export default defineAppConfig({
props: { label: 'Wyślij', class: 'w-full flex justify-center' },
},
},
})
}
2 changes: 1 addition & 1 deletion frontend/app/components/AuthForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ if (route.query.redirect_from_confirmation === 'true' && import.meta.client) {
description: 'Pomyślnie aktywowano konto! Możesz się teraz zalogować',
color: 'success',
})
const query = Object.assign({}, route.query)
const query = { ...route.query }
delete query.redirect_from_confirmation
useRouter().replace({ query })
}
Expand Down
13 changes: 9 additions & 4 deletions frontend/app/components/panel/modal/ChangePasswordModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,17 @@ async function onSubmit(data: zInfer<typeof schema>) {
</script>

<template>
<UModal v-model:open="open" title="Ustawienia konta" description="Zmień hasło">
<template #body>
<AutoForm :schema="schema" @submit="onSubmit" />
<AutoFormModal
v-model:open="open"
title="Ustawienia konta"
description="Zmień hasło"
:schema="schema"
@submit="onSubmit"
>
<template #after-fields>
<NuxtLink class="link" to="/request_password_reset">
Zresetuj hasło
</NuxtLink>
</template>
</UModal>
</AutoFormModal>
</template>
14 changes: 8 additions & 6 deletions frontend/app/components/panel/modal/ConfirmDeleteModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const props = defineProps<{

const toast = useToast()
const open = defineModel<boolean>()
const schema = z.object({})

const { $auth } = useNuxtApp()

Expand All @@ -34,10 +35,11 @@ async function onSubmit() {
</script>

<template>
<UModal v-model:open="open" :title="modalTitle" :description="modalDescription" :ui="{ footer: 'justify-end' }">
<template #footer>
<UButton label="Anuluj" color="neutral" variant="outline" @click="open = false" />
<UButton label="Potwierdź" @click="onSubmit()" />
</template>
</UModal>
<AutoFormModal
v-model:open="open"
:schema="schema"
:title="modalTitle"
:description="modalDescription"
@submit="onSubmit"
/>
</template>
12 changes: 7 additions & 5 deletions frontend/app/components/panel/modal/CreateTeam.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ async function onSubmit(data: zInfer<typeof schema>) {
</script>

<template>
<UModal v-model:open="open" title="Stwórz team" description="Zbierz brygadę swoich potężnych team-matów do walki!">
<template #body>
<AutoForm :schema="schema" @submit="onSubmit" />
</template>
</UModal>
<AutoFormModal
v-model:open="open"
title="Stwórz team"
description="Zbierz brygadę swoich potężnych team-matów do walki!"
:schema="schema"
@submit="onSubmit"
/>
</template>
11 changes: 6 additions & 5 deletions frontend/app/components/panel/modal/InviteUser.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@ async function onSubmit(data: zInfer<typeof schema>) {
</script>

<template>
<UModal v-model:open="open" title="Zaproś użytkownika">
<template #body>
<AutoForm :schema="schema" @submit="onSubmit" />
</template>
</UModal>
<AutoFormModal
v-model:open="open"
title="Zaproś użytkownika"
:schema="schema"
@submit="onSubmit"
/>
</template>
56 changes: 29 additions & 27 deletions frontend/app/components/panel/modal/JoinExternalTeam.vue
Original file line number Diff line number Diff line change
@@ -1,30 +1,27 @@
<script setup lang="ts">
import type { FormSubmitEvent } from '@nuxt/ui'

const schema = z.object({
code: z.array(z.string({ error: 'Kod do rejestracji jest wymagany' })).length(6, 'Kod do rejestracji musi mieć 6 znaków'),
code: z.string({ error: 'Kod do rejestracji jest wymagany' }).length(6, 'Kod do rejestracji musi mieć 6 znaków').meta({ title: 'Kod rejestracji' }),
})

type Schema = zInfer<typeof schema>

const state = reactive<Partial<Schema>>({})
const qrCodeModal = ref(false)
const open = defineModel<boolean>()
const formRef = useTemplateRef('form')

async function onSubmit(event: FormSubmitEvent<Schema>) {
async function onSubmit(data: Schema) {
await useNuxtApp().$auth('/teams/external_invitations/join', {
method: 'POST',
body: {
code: event.data.code.join(''),
code: data.code,
},
})

useToast().add({ title: 'Sukces', description: 'Pomyślnie dołączyłeś team', color: 'success' })
open.value = false
await refreshNuxtData()
}

function codeScanned(code: string) {
function codeScanned(code: string, state?: Partial<Schema>) {
if (code.length !== 6) {
return useToast().add({
title: `Niepoprawny kod QR`,
Expand All @@ -33,29 +30,34 @@ function codeScanned(code: string) {
})
}

state.code = code.split('')
if (state) {
state.code = code
}

qrCodeModal.value = false
}
</script>

<template>
<UModal v-model:open="open" title="Dołącz do zespołu" description="Aby wziąć udział w tym wydarzeniu nauczyciel z Twojej szkoły musi zarejestrować drużyne!" :ui="{ footer: 'justify-end' }">
<template #body>
<LazyPanelModalQRCode v-model="qrCodeModal" hydrate-on-visible @code-scanned="codeScanned" />

<UForm ref="form" :schema="schema" :state="state" class="space-y-4" @submit="onSubmit">
<UFormField label="Kod rejestracji" name="code">
<div class="flex items-center space-x-2">
<UPinInput v-model="state.code" class="mr-5" :length="6" />
<UButton icon="lucide:qr-code" @click="qrCodeModal = true" />
</div>
</UFormField>
</UForm>
</template>

<template #footer>
<UButton label="Zamknij" color="neutral" variant="outline" @click="open = false" />
<UButton label="Dołącz" @click="formRef?.submit()" />
<AutoFormModal
v-model:open="open"
title="Dołącz do zespołu"
description="Aby wziąć udział w tym wydarzeniu nauczyciel z Twojej szkoły musi zarejestrować drużyne!"
:schema="schema"
@submit="onSubmit"
>
<template #code="{ field, state }">
<LazyPanelModalQRCode v-model="qrCodeModal" hydrate-on-idle @code-scanned="code => codeScanned(code, state)" />

<div class="flex items-center space-x-2">
<UPinInput
:model-value="state[field]?.split('') ?? []"
class="mr-5"
:length="6"
@update:model-value="value => state[field] = value.join('')"
/>
<UButton icon="lucide:qr-code" @click="qrCodeModal = true" />
</div>
</template>
</UModal>
</AutoFormModal>
</template>
20 changes: 17 additions & 3 deletions frontend/app/components/panel/modal/QRCode.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@ const emit = defineEmits<{

const open = defineModel<boolean>()

const schema = z.object({
code: z.string().meta({ title: 'Kod QR' }),
})

function onDetect(detectedCodes: DetectedBarcode[]) {
emit('codeScanned', detectedCodes[0]!.rawValue)
open.value = false
}

function onError(error: Error) {
Expand All @@ -22,12 +27,21 @@ function onError(error: Error) {
</script>

<template>
<UModal v-model:open="open" title="Zeskanuj kod QR">
<template #body>
<AutoFormModal
v-model:open="open"
title="Zeskanuj kod QR"
:schema="schema"
:config="{ submit: false }"
@submit="open = false"
>
<template #code>
<QrcodeStream
@detect="onDetect"
@error="onError"
/>
</template>
</UModal>
<template #footer="{ close }">
<UButton label="Zamknij" color="neutral" variant="outline" @click="close" />
</template>
</AutoFormModal>
</template>
12 changes: 7 additions & 5 deletions frontend/app/components/panel/modal/UpdateAccountModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ async function onSubmit(data: zInfer<typeof schema>) {
</script>

<template>
<UModal v-model:open="open" title="Ustawienia konta" description="Zmień ustawienia konta">
<template #body>
<AutoForm :schema="schema" @submit="onSubmit" />
</template>
</UModal>
<AutoFormModal
v-model:open="open"
title="Ustawienia konta"
description="Zmień ustawienia konta"
:schema="schema"
@submit="onSubmit"
/>
</template>
8 changes: 4 additions & 4 deletions frontend/app/error.vue
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,14 @@ watchEffect(() => {
}

const message = error.message?.toString().toLowerCase() || ''
errorTitle.value.title = error.statusCode.toString()
errorTitle.value.title = error.status?.toString() ?? ''

if (error.statusCode === 404) {
if (error.status === 404) {
if (message.includes('page not found')) {
errorTitle.value.message
= 'Uwaga rycerzu,\n ta strona zniknęła jak zamek w chmurach.\n Wróć na właściwą drogę!'
}
} else if (error.statusCode === 500) {
} else if (error.status === 500) {
errorTitle.value.message = 'Rycerz napotkał przeszkodę\n Na swojej drodze.\n Spróbuj ponownie później.'
}
})
Expand Down Expand Up @@ -80,7 +80,7 @@ async function finishTimer() {
<template #body>
<section class="flex flex-col text-lg space-y-5">
<div
v-for="(element, i) in [['Kod', error?.statusCode], ['Wiadomość', error?.statusMessage], ['Dane', error?.data]]"
v-for="(element, i) in [['Kod', error?.status], ['Wiadomość', error?.statusMessage], ['Dane', error?.data]]"
:key="i"
>
<h2 class="text-xl font-bold text-primary">
Expand Down
8 changes: 2 additions & 6 deletions frontend/app/pages/account/submit_personal_info.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
<script setup lang="ts">
definePageMeta({
layout: 'centered',
})

const REFERRAL_SOURCES = [
'Linkedin',
'Facebook',
Expand Down Expand Up @@ -107,9 +103,9 @@ async function onSubmit(data: zInfer<typeof schema>) {
</div>

<AutoForm :schema="schema" :initial-state="state" @submit="onSubmit">
<template #is_vegetarian="{ field, state: stateValue }">
<template #is_vegetarian="{ state: stateValue }">
<USelect
v-model="stateValue[field]"
v-model="stateValue.is_vegetarian"
:items="[
{
label: 'Dieta mięsna',
Expand Down
4 changes: 0 additions & 4 deletions frontend/app/pages/admin/register_external_team.vue
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
<script setup lang="ts">
definePageMeta({
layout: 'centered',
})

useSeoMeta({
title: 'Rejestracja drużyn',
})
Expand Down
4 changes: 0 additions & 4 deletions frontend/app/pages/docs/[...slug].vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@
const slug = useRoute('docs-slug').params.slug
const { data: page } = await useAsyncData(`docs-${slug}`, () => queryCollection('content').path(`/pages/${slug}`).first())

definePageMeta({
layout: 'static-page',
})

if (!page.value?.title) {
showError({
statusCode: 404,
Expand Down
3 changes: 1 addition & 2 deletions frontend/app/pages/login.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<script setup>
definePageMeta({
middleware: 'guest',
layout: 'centered',
})

useSeoMeta({
Expand All @@ -13,7 +12,7 @@ const route = useRoute()

if (route.query.error) {
await callOnce(() => useToast().add({ title: 'Nie udało się zalogować', description: route.query.error, color: 'error' }))
const query = Object.assign({}, route.query)
const query = { ...route.query }
delete query.error
useRouter().replace({ query })
}
Expand Down
2 changes: 0 additions & 2 deletions frontend/app/pages/panel/index.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
<script setup lang="ts">
definePageMeta({ layout: 'panel' })

useSeoMeta({
title: 'Panel użytkownika',
description: 'Zarządzaj swoim kontem i drużyną w naszym CTF-ie! Sprawdź swoje zadania i postępy!',
Expand Down
10 changes: 4 additions & 6 deletions frontend/app/pages/panel/profile.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
<script setup lang="ts">
definePageMeta({ layout: 'panel' })

const { $api } = useNuxtApp()

const { data: user } = await useAuth('/account/')
Expand All @@ -22,9 +20,9 @@ async function logout() {
</script>

<template>
<LazyPanelModalJoinExternalTeam v-model="joinExternalTeamModal" hydrate-on-visible />
<LazyPanelModalUpdateAccountModal v-model="updateAccountModal" hydrate-on-visible />
<LazyPanelModalChangePasswordModal v-model="changePasswordModal" hydrate-on-visible />
<LazyPanelModalJoinExternalTeam v-model="joinExternalTeamModal" hydrate-on-idle />
<LazyPanelModalUpdateAccountModal v-model="updateAccountModal" hydrate-on-idle />
<LazyPanelModalChangePasswordModal v-model="changePasswordModal" hydrate-on-idle />
<LazyPanelModalConfirmDeleteModal
v-model="deleteAccountModal"
url="/account/delete"
Expand All @@ -33,7 +31,7 @@ async function logout() {
toast-success-message="Pomyślnie usunięto konto"
:request-body="undefined"
redirect-to="/"
hydrate-on-visible
hydrate-on-idle
/>

<div class="grid grid-cols-[400px_1fr] divide-x m-10 border min-w-fit flex-1">
Expand Down
Loading
Loading