Added support for challenges and tweaked qual awarding rules
This commit is contained in:
@@ -34,6 +34,7 @@ const { handleSubmit, resetForm, errors, values, setFieldValue } = useForm({
|
||||
validateOnMount: false,
|
||||
initialValues: {
|
||||
course_id: null,
|
||||
is_challenge: false,
|
||||
event_date: "",
|
||||
remarks: "",
|
||||
attendees: [],
|
||||
@@ -59,6 +60,17 @@ watch(() => values.course_id, (newCourseId, oldCourseId) => {
|
||||
});
|
||||
});
|
||||
|
||||
watch(() => values.is_challenge, (isChallenge) => {
|
||||
if (!isChallenge) {
|
||||
return;
|
||||
}
|
||||
|
||||
values.attendees.forEach((a, index) => {
|
||||
// @ts-ignore
|
||||
setFieldValue(`attendees[${index}].passed_bookwork`, false);
|
||||
});
|
||||
});
|
||||
|
||||
const submitForm = handleSubmit(onSubmit);
|
||||
|
||||
function toMySQLDateTime(date: Date): string {
|
||||
@@ -92,6 +104,15 @@ async function onSubmit(vals) {
|
||||
const { remove, push, fields } = useFieldArray('attendees');
|
||||
|
||||
const selectedCourse = computed<Course | undefined>(() => { return trainings.value?.find(c => c.id == values.course_id) })
|
||||
const bookworkDisabledMessage = computed(() => {
|
||||
if (values.is_challenge) {
|
||||
return "Bookwork is waived for challenge reports";
|
||||
}
|
||||
if (!selectedCourse.value?.hasBookwork) {
|
||||
return "This course does not have bookwork";
|
||||
}
|
||||
return "";
|
||||
});
|
||||
|
||||
const trainings = ref<Course[] | null>(null);
|
||||
const members = ref<MemberLight[] | null>(null);
|
||||
@@ -195,6 +216,24 @@ const filteredMembers = computed(() => {
|
||||
</VeeField>
|
||||
</FieldGroup>
|
||||
</div>
|
||||
|
||||
<div class="w-[190px]">
|
||||
<FieldGroup>
|
||||
<VeeField name="is_challenge">
|
||||
<Field>
|
||||
<FieldLabel class="scroll-m-20 text-lg tracking-tight">Challenge</FieldLabel>
|
||||
<div class="h-9 px-2 border rounded flex items-center gap-2">
|
||||
<Checkbox :model-value="values.is_challenge"
|
||||
@update:model-value="(v) => setFieldValue('is_challenge', !!v)"></Checkbox>
|
||||
<p class="text-sm text-muted-foreground">Mark report as challenge</p>
|
||||
</div>
|
||||
<FieldDescription class="mt-2 text-xs">
|
||||
Challenge waives bookwork, but qualification pass is still required.
|
||||
</FieldDescription>
|
||||
</Field>
|
||||
</VeeField>
|
||||
</FieldGroup>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<VeeFieldArray name="attendees" v-slot="{ fields, push, remove }">
|
||||
@@ -335,9 +374,9 @@ const filteredMembers = computed(() => {
|
||||
<VeeField v-slot="{ field }" :name="`attendees[${index}].passed_bookwork`" type="checkbox"
|
||||
:value="false" :unchecked-value="true">
|
||||
<div class="flex flex-col items-center">
|
||||
<Tooltip :open="!selectedCourse?.hasBookwork"
|
||||
message="This course does not have bookwork">
|
||||
<Checkbox :disabled="!selectedCourse?.hasBookwork"
|
||||
<Tooltip :open="!!bookworkDisabledMessage"
|
||||
:message="bookworkDisabledMessage">
|
||||
<Checkbox :disabled="!selectedCourse?.hasBookwork || values.is_challenge"
|
||||
:name="`attendees[${index}].passed_bookwork`" :model-value="!field.checked"
|
||||
@update:model-value="field['onUpdate:modelValue']">
|
||||
</Checkbox>
|
||||
|
||||
@@ -34,6 +34,7 @@ import {
|
||||
} from '@/components/ui/pagination'
|
||||
import Tooltip from '@/components/tooltip/Tooltip.vue';
|
||||
import { CopyLink } from '@/lib/copyLink';
|
||||
import Badge from '@/components/ui/badge/Badge.vue';
|
||||
|
||||
enum sidePanelState { view, create, closed };
|
||||
|
||||
@@ -187,6 +188,10 @@ function formatDate(date: Date | string): string {
|
||||
});
|
||||
}
|
||||
|
||||
function isChallengeReport(report: { is_challenge?: boolean | number | null }): boolean {
|
||||
return report?.is_challenge === true || Number(report?.is_challenge || 0) === 1;
|
||||
}
|
||||
|
||||
function setPageSize(size: number) {
|
||||
pageSize.value = size
|
||||
pageNum.value = 1;
|
||||
@@ -246,9 +251,12 @@ const expanded = ref<number>(null);
|
||||
<button v-for="report in trainingReports" :key="`mobile-report-${report.event_id}`"
|
||||
class="w-full rounded-lg border bg-card px-3 py-2 text-left transition-colors hover:bg-muted/40"
|
||||
@click="openTrainingReport(report.event_id)">
|
||||
<p class="font-semibold text-foreground">
|
||||
{{ report.course_name.length > 35 ? report.course_shortname : report.course_name }}
|
||||
</p>
|
||||
<div class="flex items-center gap-2">
|
||||
<p class="font-semibold text-foreground">
|
||||
{{ report.course_name.length > 35 ? report.course_shortname : report.course_name }}
|
||||
</p>
|
||||
<Badge v-if="isChallengeReport(report)" variant="outline" class="uppercase text-xs">Challenge</Badge>
|
||||
</div>
|
||||
<p class="mt-1 text-sm text-muted-foreground">{{ formatDate(report.date) }}</p>
|
||||
<div class="mt-2 flex items-center gap-2 text-xs text-muted-foreground">
|
||||
<span class="font-medium">Posted by:</span>
|
||||
@@ -274,8 +282,12 @@ const expanded = ref<number>(null);
|
||||
<TableBody v-if="loaded">
|
||||
<TableRow class="cursor-pointer" v-for="report in trainingReports" :key="report.event_id"
|
||||
@click="openTrainingReport(report.event_id)">
|
||||
<TableCell class="font-medium">{{ report.course_name.length > 30 ? report.course_shortname :
|
||||
report.course_name }}</TableCell>
|
||||
<TableCell class="font-medium">
|
||||
<div class="flex items-center gap-2">
|
||||
<span>{{ report.course_name.length > 30 ? report.course_shortname : report.course_name }}</span>
|
||||
<Badge v-if="isChallengeReport(report)" variant="outline" class="uppercase text-[10px]">Challenge</Badge>
|
||||
</div>
|
||||
</TableCell>
|
||||
<TableCell>{{ report.date.split('T')[0] }}</TableCell>
|
||||
<TableCell class="text-right">
|
||||
<MemberCard v-if="report.created_by" :member-id="report.created_by"></MemberCard>
|
||||
@@ -341,8 +353,10 @@ const expanded = ref<number>(null);
|
||||
</div>
|
||||
<div v-if="TRLoaded" :class="isMobile ? 'my-3 pb-8' : 'my-5 max-h-[70vh] overflow-y-auto overflow-x-hidden scrollbar-themed'">
|
||||
<div class="flex flex-col mb-5 border rounded-lg bg-muted/70 p-2 py-3 px-4">
|
||||
<p class="scroll-m-20 text-xl font-semibold tracking-tight">{{ focusedTrainingReport.course_name }}
|
||||
</p>
|
||||
<div class="flex items-center gap-2">
|
||||
<p class="scroll-m-20 text-xl font-semibold tracking-tight">{{ focusedTrainingReport.course_name }}</p>
|
||||
<Badge v-if="isChallengeReport(focusedTrainingReport)" variant="outline" class="uppercase text-xs">Challenge</Badge>
|
||||
</div>
|
||||
<div class="mt-2 flex flex-col gap-2 text-sm sm:flex-row sm:items-center sm:gap-10">
|
||||
<p class="text-muted-foreground">{{ formatDate(focusedTrainingReport.event_date) }}</p>
|
||||
<div class="flex gap-2 items-center">Created by:
|
||||
|
||||
Reference in New Issue
Block a user