#179-suspensions #188
@@ -1,18 +1,18 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import Button from '@/components/ui/button/Button.vue';
|
import Button from '@/components/ui/button/Button.vue';
|
||||||
import Checkbox from '@/components/ui/checkbox/Checkbox.vue';
|
import Checkbox from '@/components/ui/checkbox/Checkbox.vue';
|
||||||
|
import { useForm, Field as VeeField } from 'vee-validate';
|
||||||
import {
|
import {
|
||||||
FormControl,
|
Field,
|
||||||
FormDescription,
|
FieldContent,
|
||||||
FormField,
|
FieldDescription,
|
||||||
FormItem,
|
FieldGroup,
|
||||||
FormLabel,
|
FieldLabel,
|
||||||
FormMessage,
|
} from '@/components/ui/field'
|
||||||
} from '@/components/ui/form'
|
import FieldError from '@/components/ui/field/FieldError.vue';
|
||||||
import Input from '@/components/ui/input/Input.vue';
|
import Input from '@/components/ui/input/Input.vue';
|
||||||
import Textarea from '@/components/ui/textarea/Textarea.vue';
|
import Textarea from '@/components/ui/textarea/Textarea.vue';
|
||||||
import { toTypedSchema } from '@vee-validate/zod';
|
import { toTypedSchema } from '@vee-validate/zod';
|
||||||
import { Form } from 'vee-validate';
|
|
||||||
import { nextTick, onMounted, ref, watch } from 'vue';
|
import { nextTick, onMounted, ref, watch } from 'vue';
|
||||||
import * as z from 'zod';
|
import * as z from 'zod';
|
||||||
import DateInput from '../form/DateInput.vue';
|
import DateInput from '../form/DateInput.vue';
|
||||||
@@ -65,6 +65,15 @@ const emit = defineEmits(['submit']);
|
|||||||
|
|
||||||
const initialValues = ref<Record<string, unknown> | null>(null);
|
const initialValues = ref<Record<string, unknown> | null>(null);
|
||||||
|
|
||||||
|
const { handleSubmit, resetForm, values } = useForm({
|
||||||
|
validationSchema: formSchema,
|
||||||
|
validateOnMount: false,
|
||||||
|
});
|
||||||
|
|
||||||
|
const submitForm = handleSubmit(async (val) => {
|
||||||
|
await onSubmit(val);
|
||||||
|
});
|
||||||
|
|
||||||
async function onSubmit(val: any) {
|
async function onSubmit(val: any) {
|
||||||
emit('submit', val);
|
emit('submit', val);
|
||||||
}
|
}
|
||||||
@@ -80,6 +89,9 @@ onMounted(async () => {
|
|||||||
initialValues.value = { ...fallbackInitials };
|
initialValues.value = { ...fallbackInitials };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// apply the initial values to the vee-validate form
|
||||||
|
resetForm({ values: initialValues.value });
|
||||||
|
|
||||||
// CoCbox.value.innerHTML = await getCoC()
|
// CoCbox.value.innerHTML = await getCoC()
|
||||||
CoCString.value = await getCoC();
|
CoCString.value = await getCoC();
|
||||||
})
|
})
|
||||||
@@ -103,7 +115,7 @@ function enforceExternalLinks() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
watch(() => showCoC.value, async () => {
|
watch(() => showCoC.value, async () => {
|
||||||
if (showCoC) {
|
if (showCoC.value) {
|
||||||
await nextTick(); // wait for v-html to update
|
await nextTick(); // wait for v-html to update
|
||||||
enforceExternalLinks();
|
enforceExternalLinks();
|
||||||
}
|
}
|
||||||
@@ -126,215 +138,214 @@ function convertToAge(dob: string) {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Form v-if="initialValues" :validation-schema="formSchema" :initial-values="initialValues" @submit="onSubmit"
|
<form v-if="initialValues" @submit.prevent="submitForm" class="space-y-6">
|
||||||
class="space-y-6">
|
|
||||||
<!-- Age -->
|
<!-- Age -->
|
||||||
<FormField name="dob" v-slot="{ value, handleChange }">
|
<VeeField name="dob" v-slot="{ field, errors }">
|
||||||
<FormItem>
|
<Field>
|
||||||
<FormLabel>What is your date of birth?</FormLabel>
|
<FieldLabel>What is your date of birth?</FieldLabel>
|
||||||
<FormControl>
|
<FieldContent>
|
||||||
<template class="flex items-center gap-10">
|
<div class="flex items-center gap-10">
|
||||||
<DateInput :model-value="(value as string) ?? ''" :disabled="readOnly" @update:model-value="handleChange" />
|
<DateInput :model-value="(field.value as string) ?? ''" :disabled="readOnly" @update:model-value="field.onChange" />
|
||||||
<p v-if="props.readOnly" class="text-muted-foreground">Age: {{ convertToAge(value) }}</p>
|
<p v-if="props.readOnly" class="text-muted-foreground">Age: {{ convertToAge(field.value) }}</p>
|
||||||
</template>
|
|
||||||
</FormControl>
|
|
||||||
<div class="h-4">
|
|
||||||
<FormMessage class="text-destructive" />
|
|
||||||
</div>
|
</div>
|
||||||
</FormItem>
|
</FieldContent>
|
||||||
</FormField>
|
<div class="h-4">
|
||||||
|
<FieldError v-if="errors.length" :errors="errors" />
|
||||||
|
</div>
|
||||||
|
</Field>
|
||||||
|
</VeeField>
|
||||||
|
|
||||||
<!-- Name -->
|
<!-- Name -->
|
||||||
<FormField name="name" v-slot="{ value, handleChange }">
|
<VeeField name="name" v-slot="{ field, errors }">
|
||||||
<FormItem>
|
<Field>
|
||||||
<FormLabel>What name will you be going by within the community?</FormLabel>
|
<FieldLabel>What name will you be going by within the community?</FieldLabel>
|
||||||
<FormDescription>This name must be consistent across platforms.</FormDescription>
|
<FieldDescription>This name must be consistent across platforms.</FieldDescription>
|
||||||
<FormControl>
|
<FieldContent>
|
||||||
<Input :model-value="value" @update:model-value="handleChange" :disabled="readOnly" />
|
<Input :model-value="field.value" @update:model-value="field.onChange" :disabled="readOnly" />
|
||||||
</FormControl>
|
</FieldContent>
|
||||||
<div class="h-4">
|
<div class="h-4">
|
||||||
<FormMessage class="text-destructive" />
|
<FieldError v-if="errors.length" :errors="errors" />
|
||||||
</div>
|
</div>
|
||||||
</FormItem>
|
</Field>
|
||||||
</FormField>
|
</VeeField>
|
||||||
|
|
||||||
<!-- Playtime -->
|
<!-- Playtime -->
|
||||||
<FormField name="playtime" v-slot="{ value, handleChange }">
|
<VeeField name="playtime" v-slot="{ field, errors }">
|
||||||
<FormItem>
|
<Field>
|
||||||
<FormLabel>How long have you played Arma 3 for (in hours)?</FormLabel>
|
<FieldLabel>How long have you played Arma 3 for (in hours)?</FieldLabel>
|
||||||
<FormControl>
|
<FieldContent>
|
||||||
<Input type="number" :model-value="value" @update:model-value="handleChange" :disabled="readOnly" />
|
<Input type="number" :model-value="field.value" @update:model-value="field.onChange" :disabled="readOnly" />
|
||||||
</FormControl>
|
</FieldContent>
|
||||||
<div class="h-4">
|
<div class="h-4">
|
||||||
<FormMessage class="text-destructive" />
|
<FieldError v-if="errors.length" :errors="errors" />
|
||||||
</div>
|
</div>
|
||||||
</FormItem>
|
</Field>
|
||||||
</FormField>
|
</VeeField>
|
||||||
|
|
||||||
<!-- Hobbies -->
|
<!-- Hobbies -->
|
||||||
<FormField name="hobbies" v-slot="{ value, handleChange }">
|
<VeeField name="hobbies" v-slot="{ field, errors }">
|
||||||
<FormItem>
|
<Field>
|
||||||
<FormLabel>What hobbies do you like to participate in outside of gaming?</FormLabel>
|
<FieldLabel>What hobbies do you like to participate in outside of gaming?</FieldLabel>
|
||||||
<FormControl>
|
<FieldContent>
|
||||||
<Textarea rows="4" class="resize-none" :model-value="value" @update:model-value="handleChange"
|
<Textarea rows="4" class="resize-none" :model-value="field.value" @update:model-value="field.onChange"
|
||||||
:disabled="readOnly" />
|
:disabled="readOnly" />
|
||||||
</FormControl>
|
</FieldContent>
|
||||||
<div class="h-4">
|
<div class="h-4">
|
||||||
<FormMessage class="text-destructive" />
|
<FieldError v-if="errors.length" :errors="errors" />
|
||||||
</div>
|
</div>
|
||||||
</FormItem>
|
</Field>
|
||||||
</FormField>
|
</VeeField>
|
||||||
|
|
||||||
<!-- Military (boolean) -->
|
<!-- Military (boolean) -->
|
||||||
<FormField name="military" v-slot="{ value, handleChange }">
|
<VeeField name="military" v-slot="{ field, errors }">
|
||||||
<FormItem>
|
<Field>
|
||||||
<FormLabel>Have you ever served in the military?</FormLabel>
|
<FieldLabel>Have you ever served in the military?</FieldLabel>
|
||||||
<FormControl>
|
<FieldContent>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<Checkbox :model-value="value" @update:model-value="handleChange" :disabled="readOnly" />
|
<Checkbox :model-value="field.value" @update:model-value="field.onChange" :disabled="readOnly" />
|
||||||
<span>Yes (checked) / No (unchecked)</span>
|
<span>Yes (checked) / No (unchecked)</span>
|
||||||
</div>
|
</div>
|
||||||
</FormControl>
|
</FieldContent>
|
||||||
<div class="h-4">
|
<div class="h-4">
|
||||||
<FormMessage class="text-destructive" />
|
<FieldError v-if="errors.length" :errors="errors" />
|
||||||
</div>
|
</div>
|
||||||
</FormItem>
|
</Field>
|
||||||
</FormField>
|
</VeeField>
|
||||||
|
|
||||||
<!-- Other communities (freeform) -->
|
<!-- Other communities (freeform) -->
|
||||||
<FormField name="communities" v-slot="{ value, handleChange }">
|
<VeeField name="communities" v-slot="{ field, errors }">
|
||||||
<FormItem>
|
<Field>
|
||||||
<FormLabel>Are you a part of any other communities? If so, which ones? If none, type "No"</FormLabel>
|
<FieldLabel>Are you a part of any other communities? If so, which ones? If none, type "No"</FieldLabel>
|
||||||
<FormControl>
|
<FieldContent>
|
||||||
<Input :model-value="value" @update:model-value="handleChange" :disabled="readOnly" />
|
<Input :model-value="field.value" @update:model-value="field.onChange" :disabled="readOnly" />
|
||||||
</FormControl>
|
</FieldContent>
|
||||||
<div class="h-4">
|
<div class="h-4">
|
||||||
<FormMessage class="text-destructive" />
|
<FieldError v-if="errors.length" :errors="errors" />
|
||||||
</div>
|
</div>
|
||||||
</FormItem>
|
</Field>
|
||||||
</FormField>
|
</VeeField>
|
||||||
|
|
||||||
<!-- Why join -->
|
<!-- Why join -->
|
||||||
<FormField name="joinReason" v-slot="{ value, handleChange }">
|
<VeeField name="joinReason" v-slot="{ field, errors }">
|
||||||
<FormItem>
|
<Field>
|
||||||
<FormLabel>Why do you want to join our community?</FormLabel>
|
<FieldLabel>Why do you want to join our community?</FieldLabel>
|
||||||
<FormControl>
|
<FieldContent>
|
||||||
<Textarea rows="4" class="resize-none" :model-value="value" @update:model-value="handleChange"
|
<Textarea rows="4" class="resize-none" :model-value="field.value" @update:model-value="field.onChange"
|
||||||
:disabled="readOnly" />
|
:disabled="readOnly" />
|
||||||
</FormControl>
|
</FieldContent>
|
||||||
<div class="h-4">
|
<div class="h-4">
|
||||||
<FormMessage class="text-destructive" />
|
<FieldError v-if="errors.length" :errors="errors" />
|
||||||
</div>
|
</div>
|
||||||
</FormItem>
|
</Field>
|
||||||
</FormField>
|
</VeeField>
|
||||||
|
|
||||||
<!-- Attraction to milsim -->
|
<!-- Attraction to milsim -->
|
||||||
<FormField name="milsimAttraction" v-slot="{ value, handleChange }">
|
<VeeField name="milsimAttraction" v-slot="{ field, errors }">
|
||||||
<FormItem>
|
<Field>
|
||||||
<FormLabel>What attracts you to the Arma 3 milsim playstyle?</FormLabel>
|
<FieldLabel>What attracts you to the Arma 3 milsim playstyle?</FieldLabel>
|
||||||
<FormControl>
|
<FieldContent>
|
||||||
<Textarea rows="4" class="resize-none" :model-value="value" @update:model-value="handleChange"
|
<Textarea rows="4" class="resize-none" :model-value="field.value" @update:model-value="field.onChange"
|
||||||
:disabled="readOnly" />
|
:disabled="readOnly" />
|
||||||
</FormControl>
|
</FieldContent>
|
||||||
<div class="h-4">
|
<div class="h-4">
|
||||||
<FormMessage class="text-destructive" />
|
<FieldError v-if="errors.length" :errors="errors" />
|
||||||
</div>
|
</div>
|
||||||
</FormItem>
|
</Field>
|
||||||
</FormField>
|
</VeeField>
|
||||||
|
|
||||||
<!-- Referral (freeform) -->
|
<!-- Referral (freeform) -->
|
||||||
<FormField name="referral" v-slot="{ value, handleChange }">
|
<VeeField name="referral" v-slot="{ field, errors }">
|
||||||
<FormItem>
|
<Field>
|
||||||
<FormLabel>Where did you hear about us? (If another member, who?)</FormLabel>
|
<FieldLabel>Where did you hear about us? (If another member, who?)</FieldLabel>
|
||||||
<FormControl>
|
<FieldContent>
|
||||||
<Input placeholder="e.g., Reddit / Member: Alice" :model-value="value" @update:model-value="handleChange"
|
<Input placeholder="e.g., Reddit / Member: Alice" :model-value="field.value" @update:model-value="field.onChange"
|
||||||
:disabled="readOnly" />
|
:disabled="readOnly" />
|
||||||
</FormControl>
|
</FieldContent>
|
||||||
<div class="h-4">
|
<div class="h-4">
|
||||||
<FormMessage class="text-destructive" />
|
<FieldError v-if="errors.length" :errors="errors" />
|
||||||
</div>
|
</div>
|
||||||
</FormItem>
|
</Field>
|
||||||
</FormField>
|
</VeeField>
|
||||||
|
|
||||||
<!-- Steam profile -->
|
<!-- Steam profile -->
|
||||||
<FormField name="steamProfile" v-slot="{ value, handleChange }">
|
<VeeField name="steamProfile" v-slot="{ field, errors }">
|
||||||
<FormItem>
|
<Field>
|
||||||
<FormLabel>Steam profile link</FormLabel>
|
<FieldLabel>Steam profile link</FieldLabel>
|
||||||
<FormDescription>
|
<FieldDescription>
|
||||||
Format: <code>https://steamcommunity.com/id/USER/</code> or
|
Format: <code>https://steamcommunity.com/id/USER/</code> or
|
||||||
<code>https://steamcommunity.com/profiles/STEAMID64/</code>
|
<code>https://steamcommunity.com/profiles/STEAMID64/</code>
|
||||||
</FormDescription>
|
</FieldDescription>
|
||||||
<FormControl>
|
<FieldContent>
|
||||||
<Input type="url" placeholder="https://steamcommunity.com/profiles/7656119..." :model-value="value"
|
<Input type="url" placeholder="https://steamcommunity.com/profiles/7656119..." :model-value="field.value"
|
||||||
@update:model-value="handleChange" :disabled="readOnly" />
|
@update:model-value="field.onChange" :disabled="readOnly" />
|
||||||
</FormControl>
|
</FieldContent>
|
||||||
<div class="h-4">
|
<div class="h-4">
|
||||||
<FormMessage class="text-destructive" />
|
<FieldError v-if="errors.length" :errors="errors" />
|
||||||
</div>
|
</div>
|
||||||
</FormItem>
|
</Field>
|
||||||
</FormField>
|
</VeeField>
|
||||||
|
|
||||||
<!-- Timezone -->
|
<!-- Timezone -->
|
||||||
<FormField name="timezone" v-slot="{ value, handleChange }">
|
<VeeField name="timezone" v-slot="{ field, errors }">
|
||||||
<FormItem>
|
<Field>
|
||||||
<FormLabel>What time zone are you in?</FormLabel>
|
<FieldLabel>What time zone are you in?</FieldLabel>
|
||||||
<FormControl>
|
<FieldContent>
|
||||||
<Input placeholder="e.g., AEST, EST, UTC+10" :model-value="value" @update:model-value="handleChange"
|
<Input placeholder="e.g., AEST, EST, UTC+10" :model-value="field.value" @update:model-value="field.onChange"
|
||||||
:disabled="readOnly" />
|
:disabled="readOnly" />
|
||||||
</FormControl>
|
</FieldContent>
|
||||||
<div class="h-4">
|
<div class="h-4">
|
||||||
<FormMessage class="text-destructive" />
|
<FieldError v-if="errors.length" :errors="errors" />
|
||||||
</div>
|
</div>
|
||||||
</FormItem>
|
</Field>
|
||||||
</FormField>
|
</VeeField>
|
||||||
|
|
||||||
<!-- Attendance (boolean) -->
|
<!-- Attendance (boolean) -->
|
||||||
<FormField name="canAttendSaturday" v-slot="{ value, handleChange }">
|
<VeeField name="canAttendSaturday" v-slot="{ field, errors }">
|
||||||
<FormItem>
|
<Field>
|
||||||
<FormLabel>Are you able to attend weekly operations Saturdays @ 7pm CST?</FormLabel>
|
<FieldLabel>Are you able to attend weekly operations Saturdays @ 7pm CST?</FieldLabel>
|
||||||
<FormControl>
|
<FieldContent>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<Checkbox :model-value="value ?? false" @update:model-value="handleChange" :disabled="readOnly" />
|
<Checkbox :model-value="field.value ?? false" @update:model-value="field.onChange" :disabled="readOnly" />
|
||||||
<span>Yes (checked) / No (unchecked)</span>
|
<span>Yes (checked) / No (unchecked)</span>
|
||||||
</div>
|
</div>
|
||||||
</FormControl>
|
</FieldContent>
|
||||||
<div class="h-4">
|
<div class="h-4">
|
||||||
<FormMessage class="text-destructive" />
|
<FieldError v-if="errors.length" :errors="errors" />
|
||||||
</div>
|
</div>
|
||||||
</FormItem>
|
</Field>
|
||||||
</FormField>
|
</VeeField>
|
||||||
|
|
||||||
<!-- Interests / Playstyle (freeform) -->
|
<!-- Interests / Playstyle (freeform) -->
|
||||||
<FormField name="interests" v-slot="{ value, handleChange }">
|
<VeeField name="interests" v-slot="{ field, errors }">
|
||||||
<FormItem>
|
<Field>
|
||||||
<FormLabel>Which playstyles interest you?</FormLabel>
|
<FieldLabel>Which playstyles interest you?</FieldLabel>
|
||||||
<FormControl>
|
<FieldContent>
|
||||||
<Input placeholder="e.g., Rifleman; Medic; Pilot" :model-value="value" @update:model-value="handleChange"
|
<Input placeholder="e.g., Rifleman; Medic; Pilot" :model-value="field.value" @update:model-value="field.onChange"
|
||||||
:disabled="readOnly" />
|
:disabled="readOnly" />
|
||||||
</FormControl>
|
</FieldContent>
|
||||||
<div class="h-4">
|
<div class="h-4">
|
||||||
<FormMessage class="text-destructive" />
|
<FieldError v-if="errors.length" :errors="errors" />
|
||||||
</div>
|
</div>
|
||||||
</FormItem>
|
</Field>
|
||||||
</FormField>
|
</VeeField>
|
||||||
|
|
||||||
<!-- Code of Conduct (boolean, field name kept as-is) -->
|
<!-- Code of Conduct (boolean, field name kept as-is) -->
|
||||||
<FormField name="acknowledgeRules" v-slot="{ value, handleChange }">
|
<VeeField name="acknowledgeRules" v-slot="{ field, errors }">
|
||||||
<FormItem>
|
<Field>
|
||||||
<FormLabel>Community Code of Conduct</FormLabel>
|
<FieldLabel>Community Code of Conduct</FieldLabel>
|
||||||
<FormControl>
|
<FieldContent>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<Checkbox :model-value="value" @update:model-value="handleChange" :disabled="readOnly" />
|
<Checkbox :model-value="field.value" @update:model-value="field.onChange" :disabled="readOnly" />
|
||||||
<span>By checking this box, you accept the <Button variant="link" class="p-0 h-min"
|
<span>By checking this box, you accept the <Button variant="link" class="p-0 h-min"
|
||||||
@click.prevent.stop="showCoC = true">Code of
|
@click.prevent.stop="showCoC = true">Code of
|
||||||
Conduct</Button>.</span>
|
Conduct</Button>.</span>
|
||||||
</div>
|
</div>
|
||||||
</FormControl>
|
</FieldContent>
|
||||||
<div class="h-4">
|
<div class="h-4">
|
||||||
<FormMessage class="text-destructive" />
|
<FieldError v-if="errors.length" :errors="errors" />
|
||||||
</div>
|
</div>
|
||||||
</FormItem>
|
</Field>
|
||||||
</FormField>
|
</VeeField>
|
||||||
|
|
||||||
<div class="pt-2" v-if="!readOnly">
|
<div class="pt-2" v-if="!readOnly">
|
||||||
<Button type="submit" :disabled="readOnly">Submit Application</Button>
|
<Button type="submit" :disabled="readOnly">Submit Application</Button>
|
||||||
@@ -351,5 +362,5 @@ function convertToAge(dob: string) {
|
|||||||
</DialogContent>
|
</DialogContent>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
|
|
||||||
</Form>
|
</form>
|
||||||
</template>
|
</template>
|
||||||
Reference in New Issue
Block a user