diff --git a/aleksis/apps/alsijil/frontend/components/coursebook/absences/TardinessField.vue b/aleksis/apps/alsijil/frontend/components/coursebook/absences/TardinessField.vue index 74a85ae09018fcc810950e6b10a52a8e5a948607..6e23c2394874ed2b42921fd90ba4aeaf418b3f89 100644 --- a/aleksis/apps/alsijil/frontend/components/coursebook/absences/TardinessField.vue +++ b/aleksis/apps/alsijil/frontend/components/coursebook/absences/TardinessField.vue @@ -2,12 +2,12 @@ import { DateTime } from "luxon"; import documentationPartMixin from "../documentation/documentationPartMixin"; import ConfirmDialog from "aleksis.core/components/generic/dialogs/ConfirmDialog.vue"; -import PositiveSmallIntegerField from "aleksis.core/components/generic/forms/PositiveSmallIntegerField.vue"; +import formRulesMixin from "aleksis.core/mixins/formRulesMixin.js"; export default { name: "TardinessField", - components: { ConfirmDialog, PositiveSmallIntegerField }, - mixins: [documentationPartMixin], + components: { ConfirmDialog }, + mixins: [documentationPartMixin, formRulesMixin], props: { value: { type: Number, @@ -27,6 +27,40 @@ export default { let diff = lessonEnd.diff(lessonStart, "minutes"); return diff.toObject().minutes; }, + defaultTimes() { + const lessonStart = DateTime.fromISO(this.documentation.datetimeStart); + const lessonEnd = DateTime.fromISO(this.documentation.datetimeEnd); + const now = DateTime.now(); + + let current = []; + + if (now >= lessonStart && now <= lessonEnd) { + const diff = parseInt( + now.diff(lessonStart, "minutes").toObject().minutes, + ); + + current.push({ + text: diff, + value: diff, + current: true, + }); + } + + return current.concat([ + { + text: 5, + value: 5, + }, + { + text: 10, + value: 10, + }, + { + text: 15, + value: 15, + }, + ]); + }, }, methods: { lessonLengthRule(time) { @@ -46,14 +80,23 @@ export default { cancel() { this.saveValue(this.previousValue); }, + processValueObjectOptional(value) { + if (Object.hasOwn(value, "value")) { + return value.value; + } + + return value; + }, set(newValue) { - if (!newValue) { + newValue = this.processValueObjectOptional(newValue); + + if (!newValue || parseInt(newValue) === 0) { // this is a DELETE action, show the dialog, ... this.showDeleteConfirm = true; return; } - this.saveValue(newValue); + this.saveValue(parseInt(newValue)); }, }, data() { @@ -69,17 +112,40 @@ export default { </script> <template> - <positive-small-integer-field + <v-combobox outlined class="mt-1" prepend-inner-icon="mdi-clock-alert-outline" :suffix="$t('time.minutes')" :label="$t('alsijil.personal_notes.tardiness')" - :rules="[lessonLengthRule]" + :rules=" + $rules() + .isANumber.isAWholeNumber.isGreaterThan(0) + .build([lessonLengthRule]) + .map((f) => (v) => f(this.processValueObjectOptional(v))) + " + :items="defaultTimes" :value="value" @change="set($event)" v-bind="$attrs" > + <template #item="{ item }"> + <v-list-item-icon v-if="item.current"> + <v-icon>mdi-shimmer</v-icon> + </v-list-item-icon> + <v-list-item-content> + <v-list-item-title> + {{ + $tc( + item.current + ? "alsijil.personal_notes.minutes_late_current" + : "time.minutes_n", + item.value, + ) + }} + </v-list-item-title> + </v-list-item-content> + </template> <template #append> <confirm-dialog v-model="showDeleteConfirm" @@ -99,7 +165,7 @@ export default { </template> </confirm-dialog> </template> - </positive-small-integer-field> + </v-combobox> </template> <style scoped>