81 lines
2.2 KiB
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>
|