use explicit scheduling levels
This commit is contained in:
parent
dfca13936a
commit
8e38b8f7e8
3 changed files with 33 additions and 34 deletions
|
|
@ -6,9 +6,9 @@ import { z } from 'zod'
|
|||
|
||||
import AuthenticatedHeader from '@/components/AuthenticatedHeader.vue'
|
||||
import { useSchedulesStore } from '@/stores/schedules'
|
||||
import { useSetLayoutStore, type SetElementNode } from '@/stores/setLayout'
|
||||
import { useSetLayoutStore } from '@/stores/setLayout'
|
||||
|
||||
type ScheduleField = 'elementKind' | 'startDate' | 'targetDate'
|
||||
type ScheduleField = 'levelId' | 'startDate' | 'targetDate'
|
||||
type ScheduleFieldErrors = Partial<Record<ScheduleField, string>>
|
||||
|
||||
const route = useRoute()
|
||||
|
|
@ -19,34 +19,24 @@ const { layout, loading, error, notFound } = storeToRefs(setLayoutStore)
|
|||
const { creating, createError } = storeToRefs(schedulesStore)
|
||||
const currentSetId = ref<number | null>(null)
|
||||
const form = reactive({
|
||||
elementKind: '',
|
||||
levelId: null as number | null,
|
||||
startDate: '',
|
||||
targetDate: '',
|
||||
})
|
||||
const fieldErrors = ref<ScheduleFieldErrors>({})
|
||||
|
||||
const levels = computed(() => {
|
||||
const counts = new Map<string, number>()
|
||||
|
||||
function countNodes(nodes: SetElementNode[]): void {
|
||||
for (const node of nodes) {
|
||||
counts.set(node.kind, (counts.get(node.kind) ?? 0) + 1)
|
||||
countNodes(node.children)
|
||||
}
|
||||
}
|
||||
|
||||
countNodes(layout.value?.elements ?? [])
|
||||
|
||||
return [...counts.entries()].map(([kind, count]) => ({
|
||||
kind,
|
||||
count,
|
||||
label: humanizeKind(kind),
|
||||
}))
|
||||
})
|
||||
const levels = computed(() =>
|
||||
(layout.value?.levels ?? [])
|
||||
.filter((level) => level.elementCount > 0)
|
||||
.map((level) => ({
|
||||
...level,
|
||||
label: humanizeKind(level.kind),
|
||||
})),
|
||||
)
|
||||
|
||||
const scheduleFormSchema = z
|
||||
.object({
|
||||
elementKind: z.string().min(1, 'Choose a level to schedule.'),
|
||||
levelId: z.number('Choose a level to schedule.').int().positive(),
|
||||
startDate: z.string().min(1, 'Choose a start date.'),
|
||||
targetDate: z.string().min(1, 'Choose a target date.'),
|
||||
})
|
||||
|
|
@ -82,7 +72,7 @@ async function submit(): Promise<void> {
|
|||
for (const issue of result.error.issues) {
|
||||
const field = issue.path[0]
|
||||
if (
|
||||
(field === 'elementKind' || field === 'startDate' || field === 'targetDate') &&
|
||||
(field === 'levelId' || field === 'startDate' || field === 'targetDate') &&
|
||||
errors[field] === undefined
|
||||
) {
|
||||
errors[field] = issue.message
|
||||
|
|
@ -95,10 +85,10 @@ async function submit(): Promise<void> {
|
|||
|
||||
if (
|
||||
currentSetId.value === null ||
|
||||
!levels.value.some((level) => level.kind === result.data.elementKind)
|
||||
!levels.value.some((level) => level.id === result.data.levelId)
|
||||
) {
|
||||
fieldErrors.value = {
|
||||
elementKind: 'Choose an available level to schedule.',
|
||||
levelId: 'Choose an available level to schedule.',
|
||||
}
|
||||
|
||||
return
|
||||
|
|
@ -166,18 +156,18 @@ function humanizeKind(kind: string): string {
|
|||
<label for="schedule-level">Level</label>
|
||||
<select
|
||||
id="schedule-level"
|
||||
v-model="form.elementKind"
|
||||
:aria-invalid="fieldErrors.elementKind !== undefined"
|
||||
:aria-describedby="fieldErrors.elementKind ? 'schedule-level-error' : undefined"
|
||||
v-model="form.levelId"
|
||||
:aria-invalid="fieldErrors.levelId !== undefined"
|
||||
:aria-describedby="fieldErrors.levelId ? 'schedule-level-error' : undefined"
|
||||
:disabled="creating"
|
||||
>
|
||||
<option value="">Choose a level</option>
|
||||
<option v-for="level in levels" :key="level.kind" :value="level.kind">
|
||||
{{ level.label }} ({{ level.count }})
|
||||
<option :value="null">Choose a level</option>
|
||||
<option v-for="level in levels" :key="level.id" :value="level.id">
|
||||
{{ level.label }} ({{ level.elementCount }})
|
||||
</option>
|
||||
</select>
|
||||
<p v-if="fieldErrors.elementKind" id="schedule-level-error" class="field-error">
|
||||
{{ fieldErrors.elementKind }}
|
||||
<p v-if="fieldErrors.levelId" id="schedule-level-error" class="field-error">
|
||||
{{ fieldErrors.levelId }}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue