PronounsPage/components/PersonalEventListInput.vue
Valentyne Stigloher b25afefc49 (fmt)
2024-10-29 10:56:32 +01:00

137 lines
3.8 KiB
Vue

<script setup lang="ts">
import datepicker from '@vuepic/vue-datepicker';
import type { CustomEvent } from '~/src/calendar/helpers.ts';
defineProps<{
maxitems: number;
}>();
const { $translator: translator } = useNuxtApp();
const config = useConfig();
const { isDark } = useDark();
const today = new Date();
const modelValue = defineModel<CustomEvent[]>();
const showIconSelector = ref<number | false>(false);
const maxDaysInMonths: Record<number, number> = {
1: 31,
2: 29,
3: 31,
4: 30,
5: 31,
6: 30,
7: 31,
8: 31,
9: 30,
10: 31,
11: 30,
12: 31,
};
const formatDate = (date: Date): string => {
return translator.translate(`calendar.dates.${date.getMonth() + 1}`, { day: date.getDate().toString() });
};
const prototype = () => {
return { name: '', month: '', day: '', comment: '' };
};
const validation = (v: CustomEvent): string | null => {
if (JSON.stringify(v) === JSON.stringify(prototype())) {
return null;
}
if (!v.name) {
return 'profile.calendar.customEvents.validation.missingName';
}
if (!v.month || !v.day) {
return 'profile.calendar.customEvents.validation.missingDate';
}
if (v.day < 1 || v.day > maxDaysInMonths[v.month]) {
return 'profile.calendar.customEvents.validation.invalidDate';
}
return null;
};
</script>
<template>
<ListInput
v-model="modelValue"
:prototype="prototype()"
:maxitems="maxitems"
disable-sorting
>
<template #default="s">
<datepicker
:model-value="new Date(today.getFullYear(), s.val.month - 1, s.val.day)"
:format="formatDate"
auto-apply
:enable-time-picker="false"
:clearable="false"
no-today
vertical
:dark="isDark"
:locale="config.locale"
@update:model-value="(date: Date) => {
s.val.month = date.getMonth() + 1;
s.val.day = date.getDate();
}"
/>
<button
type="button"
:class="['btn', 'btn-outline-secondary', showIconSelector === s.i ? 'btn-secondary text-white border' : '']"
@click="showIconSelector = showIconSelector === s.i ? false : s.i"
>
<Icon :v="s.val.icon" />
</button>
<input
v-model="s.val.name"
class="form-control"
required
maxlength="24"
:placeholder="$t('profile.calendar.customEvents.name')"
@keyup="s.update(s.val)"
@paste="$nextTick(() => s.update(s.val))"
@change="s.update(s.val)"
>
<input
v-model="s.val.comment"
class="form-control"
maxlength="128"
:placeholder="$t('profile.calendar.customEvents.comment')"
@keyup="s.update(s.val)"
@paste="$nextTick(() => s.update(s.val))"
@change="s.update(s.val)"
>
<IconSelector
v-if="showIconSelector === s.i"
class="hanging shadow shadow-lg border"
@change="s.update({ ...s.val, icon: $event }); showIconSelector = false"
/>
</template>
<template #validation="s">
<p v-if="validation(s.val)" class="small text-danger">
<Icon v="exclamation-triangle" />
<span class="ml-1">{{ $t(validation(s.val)!) }}</span>
</p>
</template>
</ListInput>
</template>
<style lang="scss" scoped>
.hanging {
position: absolute;
top: 100%;
left: 0;
width: 100%;
max-width: 500px;
z-index: 5000;
}
</style>