141 lines
3.8 KiB
Vue
141 lines
3.8 KiB
Vue
<script setup lang="ts">
|
|
import type { FormErrors } from '~/types/error'
|
|
import { differenceInDays, differenceInMonths, differenceInYears, parseISO } from 'date-fns'
|
|
import { Input } from '~/components/pub/ui/input'
|
|
import { cn } from '~/lib/utils'
|
|
|
|
import * as DE from '~/components/pub/my-ui/doc-entry'
|
|
|
|
const props = defineProps<{
|
|
fieldName?: string
|
|
label?: string
|
|
placeholder?: string
|
|
errors?: FormErrors
|
|
class?: string
|
|
selectClass?: string
|
|
fieldGroupClass?: string
|
|
labelClass?: string
|
|
isRequired?: boolean
|
|
}>()
|
|
|
|
const {
|
|
fieldName = 'birthDate',
|
|
label = 'Tanggal Lahir',
|
|
placeholder = 'Pilih tanggal lahir',
|
|
errors,
|
|
class: containerClass,
|
|
fieldGroupClass,
|
|
labelClass,
|
|
} = props
|
|
|
|
// Reactive variables for age calculation
|
|
const patientAge = ref<string>('Masukkan tanggal lahir')
|
|
|
|
// Function to calculate age with years, months, and days
|
|
function calculateAge(birthDate: string | Date | undefined): string {
|
|
if (!birthDate) {
|
|
return 'Masukkan tanggal lahir'
|
|
}
|
|
|
|
try {
|
|
let dateObj: Date
|
|
|
|
if (typeof birthDate === 'string') {
|
|
dateObj = parseISO(birthDate)
|
|
} else {
|
|
dateObj = birthDate
|
|
}
|
|
|
|
const today = new Date()
|
|
|
|
// Calculate years, months, and days
|
|
const totalYears = differenceInYears(today, dateObj)
|
|
|
|
// Calculate remaining months after years
|
|
const yearsPassed = new Date(dateObj)
|
|
yearsPassed.setFullYear(yearsPassed.getFullYear() + totalYears)
|
|
const remainingMonths = differenceInMonths(today, yearsPassed)
|
|
|
|
// Calculate remaining days after years and months
|
|
const monthsPassed = new Date(yearsPassed)
|
|
monthsPassed.setMonth(monthsPassed.getMonth() + remainingMonths)
|
|
const remainingDays = differenceInDays(today, monthsPassed)
|
|
|
|
// Format the result
|
|
const parts = []
|
|
if (totalYears > 0) parts.push(`${totalYears} Tahun`)
|
|
if (remainingMonths > 0) parts.push(`${remainingMonths} Bulan`)
|
|
if (remainingDays > 0) parts.push(`${remainingDays} Hari`)
|
|
|
|
return parts.length > 0 ? parts.join(' ') : '0 Hari'
|
|
} catch {
|
|
return 'Masukkan tanggal lahir'
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<DE.Cell :class="cn('select-field-group', fieldGroupClass, containerClass)">
|
|
<DE.Label
|
|
:label-for="fieldName"
|
|
:class="cn('select-field-label', labelClass)"
|
|
:is-required="isRequired"
|
|
>
|
|
{{ label }}
|
|
</DE.Label>
|
|
<DE.Field
|
|
:id="fieldName"
|
|
:errors="errors"
|
|
:class="cn('select-field-wrapper')"
|
|
>
|
|
<FormField
|
|
v-slot="{ componentField }"
|
|
:name="fieldName"
|
|
>
|
|
<FormItem>
|
|
<FormControl>
|
|
<Input
|
|
id="birthDate"
|
|
type="date"
|
|
min="1900-01-01"
|
|
:max="new Date().toISOString().split('T')[0]"
|
|
v-bind="componentField"
|
|
:placeholder="placeholder"
|
|
@update:model-value="
|
|
(value: string | number) => {
|
|
const dateStr = typeof value === 'number' ? String(value) : value
|
|
patientAge = calculateAge(dateStr)
|
|
}
|
|
"
|
|
/>
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
</FormField>
|
|
</DE.Field>
|
|
</DE.Cell>
|
|
<DE.Cell>
|
|
<DE.Label label-for="patientAge">Usia</DE.Label>
|
|
<DE.Field id="patientAge">
|
|
<FormField name="patientAge">
|
|
<FormItem>
|
|
<FormControl>
|
|
<Input
|
|
:value="patientAge"
|
|
disabled
|
|
readonly
|
|
placeholder="Masukkan tanggal lahir"
|
|
:class="
|
|
cn(
|
|
'cursor-not-allowed bg-gray-50 focus:border-primary focus:ring-2 focus:ring-primary focus:ring-offset-0',
|
|
)
|
|
"
|
|
/>
|
|
</FormControl>
|
|
<FormMessage />
|
|
</FormItem>
|
|
</FormField>
|
|
</DE.Field>
|
|
</DE.Cell>
|
|
</template>
|