refactor(installation): rename component and ensure installationId is number
Rename AppInstallationPositionEntry to AppInstallationPositionEntryDetail for better clarity and ensure installationId is properly typed as number. The new component includes form handling for installation position details.
This commit is contained in:
@@ -0,0 +1,192 @@
|
||||
<script setup lang="ts">
|
||||
// Components
|
||||
import Block from '~/components/pub/my-ui/doc-entry/block.vue'
|
||||
import Cell from '~/components/pub/my-ui/doc-entry/cell.vue'
|
||||
import Field from '~/components/pub/my-ui/doc-entry/field.vue'
|
||||
import Label from '~/components/pub/my-ui/doc-entry/label.vue'
|
||||
import Combobox from '~/components/pub/my-ui/combobox/combobox.vue'
|
||||
|
||||
// Types
|
||||
import type { InstallationPositionFormData } from '~/schemas/installation-position.schema'
|
||||
|
||||
// Helpers
|
||||
import type z from 'zod'
|
||||
import { toTypedSchema } from '@vee-validate/zod'
|
||||
import { useForm } from 'vee-validate'
|
||||
import { genBase } from '~/models/_base'
|
||||
import { genInstallationPosition } from '~/models/installation-position'
|
||||
|
||||
interface Props {
|
||||
schema: z.ZodSchema<any>
|
||||
installationId: number
|
||||
employees: any[]
|
||||
values: any
|
||||
isLoading?: boolean
|
||||
isReadonly?: boolean
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
|
||||
const isLoading = props.isLoading !== undefined ? props.isLoading : false
|
||||
const isReadonly = props.isReadonly !== undefined ? props.isReadonly : false
|
||||
const emit = defineEmits<{
|
||||
submit: [values: InstallationPositionFormData, resetForm: () => void]
|
||||
cancel: [resetForm: () => void]
|
||||
}>()
|
||||
|
||||
const { defineField, errors, meta } = useForm({
|
||||
validationSchema: toTypedSchema(props.schema),
|
||||
initialValues: genInstallationPosition() as Partial<InstallationPositionFormData>,
|
||||
})
|
||||
|
||||
const [code, codeAttrs] = defineField('code')
|
||||
const [name, nameAttrs] = defineField('name')
|
||||
const [employee, employeeAttrs] = defineField('employee_id')
|
||||
const [headStatus, headStatusAttrs] = defineField('headStatus')
|
||||
|
||||
// RadioGroup uses string values; expose a string computed that maps to the boolean field
|
||||
const headStatusStr = computed<string>({
|
||||
get() {
|
||||
if (headStatus.value === true) return 'true'
|
||||
if (headStatus.value === false) return 'false'
|
||||
return ''
|
||||
},
|
||||
set(v: string) {
|
||||
if (v === 'true') headStatus.value = true
|
||||
else if (v === 'false') headStatus.value = false
|
||||
else headStatus.value = undefined
|
||||
},
|
||||
})
|
||||
|
||||
// Fill fields from props.values if provided
|
||||
if (props.values) {
|
||||
if (props.values.code !== undefined) code.value = props.values.code
|
||||
if (props.values.name !== undefined) name.value = props.values.name
|
||||
if (props.values.employee_id !== undefined)
|
||||
employee.value = props.values.employee_id ? Number(props.values.employee_id) : null
|
||||
if (props.values.headStatus !== undefined) headStatus.value = !!props.values.headStatus
|
||||
}
|
||||
|
||||
const resetForm = () => {
|
||||
code.value = ''
|
||||
name.value = ''
|
||||
employee.value = null
|
||||
headStatus.value = false
|
||||
}
|
||||
|
||||
// Form submission handler
|
||||
function onSubmitForm() {
|
||||
const formData: InstallationPositionFormData = {
|
||||
...genBase(),
|
||||
name: name.value || '',
|
||||
code: code.value || '',
|
||||
|
||||
// readonly based on detail installation
|
||||
installation_id: props.installationId,
|
||||
|
||||
employee_id: employee.value || null,
|
||||
headStatus: headStatus.value !== undefined ? headStatus.value : undefined,
|
||||
}
|
||||
emit('submit', formData, resetForm)
|
||||
}
|
||||
|
||||
// Form cancel handler
|
||||
function onCancelForm() {
|
||||
emit('cancel', resetForm)
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<form
|
||||
id="form-installation-position"
|
||||
@submit.prevent
|
||||
>
|
||||
<Block
|
||||
labelSize="thin"
|
||||
class="!mb-2.5 !pt-0 xl:!mb-3"
|
||||
:colCount="1"
|
||||
>
|
||||
<Cell>
|
||||
<Label height="compact">Kode Jabatan</Label>
|
||||
<Field :errMessage="errors.code">
|
||||
<Input
|
||||
id="code"
|
||||
v-model="code"
|
||||
v-bind="codeAttrs"
|
||||
:disabled="isLoading || isReadonly"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label height="compact">Nama Jabatan</Label>
|
||||
<Field :errMessage="errors.name">
|
||||
<Input
|
||||
id="name"
|
||||
v-model="name"
|
||||
v-bind="nameAttrs"
|
||||
:disabled="isLoading || isReadonly"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label height="compact">Pengisi Jabatan</Label>
|
||||
<Field :errMessage="errors.employee_id">
|
||||
<Combobox
|
||||
id="employee"
|
||||
v-model="employee"
|
||||
v-bind="employeeAttrs"
|
||||
:items="employees"
|
||||
:is-disabled="isLoading || isReadonly"
|
||||
placeholder="Pilih Karyawan"
|
||||
search-placeholder="Cari Karyawan"
|
||||
empty-message="Item tidak ditemukan"
|
||||
/>
|
||||
</Field>
|
||||
</Cell>
|
||||
<Cell>
|
||||
<Label height="compact">Status Kepala</Label>
|
||||
<Field :errMessage="errors.headStatus">
|
||||
<RadioGroup
|
||||
v-model="headStatusStr"
|
||||
v-bind="headStatusAttrs"
|
||||
class="flex gap-4"
|
||||
>
|
||||
<div class="flex items-center space-x-2">
|
||||
<RadioGroupItem
|
||||
id="head-yes"
|
||||
value="true"
|
||||
/>
|
||||
<Label for="head-yes">Ya</Label>
|
||||
</div>
|
||||
<div class="flex items-center space-x-2">
|
||||
<RadioGroupItem
|
||||
id="head-no"
|
||||
value="false"
|
||||
/>
|
||||
<Label for="head-no">Tidak</Label>
|
||||
</div>
|
||||
</RadioGroup>
|
||||
</Field>
|
||||
</Cell>
|
||||
</Block>
|
||||
<div class="my-2 flex justify-end gap-2 py-2">
|
||||
<Button
|
||||
type="button"
|
||||
variant="secondary"
|
||||
class="w-[120px]"
|
||||
@click="onCancelForm"
|
||||
>
|
||||
Kembali
|
||||
</Button>
|
||||
<Button
|
||||
v-if="!isReadonly"
|
||||
type="button"
|
||||
class="w-[120px]"
|
||||
:disabled="isLoading || !meta.valid"
|
||||
@click="onSubmitForm"
|
||||
>
|
||||
Simpan
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</template>
|
||||
@@ -192,9 +192,9 @@ watch([recId, recAction], () => {
|
||||
}
|
||||
"
|
||||
>
|
||||
<AppInstallationPositionEntry
|
||||
<AppInstallationPositionEntryDetail
|
||||
:schema="InstallationPositionSchema"
|
||||
:installation-id="installationId"
|
||||
:installation-id="Number(installationId)"
|
||||
:employees="employees"
|
||||
:values="recItem"
|
||||
:is-loading="isProcessing"
|
||||
|
||||
Reference in New Issue
Block a user