Files
BetiX/resources/js/components/ui/DatePicker.vue
Dolo 0280278978
Some checks failed
linter / quality (push) Has been cancelled
tests / ci (8.4) (push) Has been cancelled
tests / ci (8.5) (push) Has been cancelled
Initialer Laravel Commit für BetiX
2026-04-04 18:01:50 +02:00

73 lines
2.7 KiB
Vue

<script setup lang="ts">
import { ref, watch } from 'vue';
const props = defineProps<{
modelValue: string; // ISO Date String (YYYY-MM-DD)
error?: boolean;
}>();
const emit = defineEmits(['update:modelValue']);
// Internal state for raw input
const inputValue = ref('');
// Format: YYYY-MM-DD -> DD.MM.YYYY for display
const formatDate = (iso: string) => {
if (!iso) return '';
const [y, m, d] = iso.split('-');
return `${d}.${m}.${y}`;
};
// Initialize
watch(() => props.modelValue, (val) => {
// Only update if the formatted value is different to avoid cursor jumping
const formatted = formatDate(val);
if (inputValue.value !== formatted && val.length === 10) {
inputValue.value = formatted;
}
}, { immediate: true });
const onInput = (e: Event) => {
let val = (e.target as HTMLInputElement).value.replace(/\D/g, ''); // Remove non-digits
// Auto-insert dots
if (val.length > 2) val = val.slice(0, 2) + '.' + val.slice(2);
if (val.length > 5) val = val.slice(0, 5) + '.' + val.slice(5);
if (val.length > 10) val = val.slice(0, 10);
inputValue.value = val;
// Only emit if full date is entered
if (val.length === 10) {
const [d, m, y] = val.split('.');
// Basic validation
const day = parseInt(d);
const month = parseInt(m);
const year = parseInt(y);
if (day > 0 && day <= 31 && month > 0 && month <= 12 && year > 1900 && year < 2100) {
emit('update:modelValue', `${y}-${m}-${d}`);
}
} else if (val.length === 0) {
emit('update:modelValue', '');
}
};
</script>
<template>
<div class="relative w-full">
<input
type="text"
:value="inputValue"
@input="onInput"
placeholder="DD.MM.YYYY"
class="flex h-10 w-full rounded-md border bg-[#0a0a0a] px-3 py-2 text-sm text-white shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-[#00f2ff] disabled:cursor-not-allowed disabled:opacity-50 placeholder:text-[#444]"
:class="error ? 'border-red-500' : 'border-[#151515] hover:border-[#333]'"
maxlength="10"
/>
<div class="absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none text-[#666]">
<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="18" x="3" y="4" rx="2" ry="2"/><line x1="16" x2="16" y1="2" y2="6"/><line x1="8" x2="8" y1="2" y2="6"/><line x1="3" x2="21" y1="10" y2="10"/></svg>
</div>
</div>
</template>