store/resources/js/components/ui/date-picker/DatePicker.vue

81 lines
2.2 KiB
Vue

<script setup lang="ts">
import type { DateValue } from '@internationalized/date';
import { DateFormatter, getLocalTimeZone, parseDate, today } from '@internationalized/date';
import { CalendarIcon } from '@lucide/vue';
import type { HTMLAttributes } from 'vue';
import { computed } from 'vue';
import { Button } from '@/components/ui/button';
import { Calendar } from '@/components/ui/calendar';
import {
Popover,
PopoverContent,
PopoverTrigger,
} from '@/components/ui/popover';
import { cn } from '@/lib/utils';
const props = defineProps<{
id?: string;
modelValue?: string;
class?: HTMLAttributes['class'];
placeholder?: string;
disabled?: boolean;
}>();
const emit = defineEmits<{
(event: 'update:modelValue', value: string): void;
}>();
const defaultPlaceholder = today(getLocalTimeZone());
const df = new DateFormatter('id-ID', {
dateStyle: 'long',
});
const date = computed({
get: () => {
if (!props.modelValue) {
return undefined;
}
try {
return parseDate(props.modelValue);
} catch {
return undefined;
}
},
set: (value: DateValue | undefined) => {
emit('update:modelValue', value ? value.toString() : '');
},
});
</script>
<template>
<Popover v-slot="{ close }">
<PopoverTrigger as-child>
<Button
:id="id"
type="button"
variant="outline"
:disabled="disabled"
:class="cn(
'w-full justify-start text-left font-normal',
!date && 'text-muted-foreground',
props.class,
)"
>
<CalendarIcon class="size-4" />
{{ date ? df.format(date.toDate(getLocalTimeZone())) : (placeholder ?? 'Pilih tanggal') }}
</Button>
</PopoverTrigger>
<PopoverContent class="w-auto p-0" align="start">
<Calendar
v-model="date"
:default-placeholder="defaultPlaceholder"
layout="month-and-year"
initial-focus
@update:model-value="close"
/>
</PopoverContent>
</Popover>
</template>