From 3c74a123accd9cf3ef9d5ee831ad69dc4d446bd1 Mon Sep 17 00:00:00 2001 From: riefive Date: Wed, 3 Sep 2025 15:39:06 +0700 Subject: [PATCH 1/6] feat (material): update validation of attribute stock --- app/components/app/material/list-cfg.ts | 6 +++--- app/components/flow/material/entry.vue | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/components/app/material/list-cfg.ts b/app/components/app/material/list-cfg.ts index 71ca97f6..b6ed7f4e 100644 --- a/app/components/app/material/list-cfg.ts +++ b/app/components/app/material/list-cfg.ts @@ -12,11 +12,11 @@ type SmallDetailDto = any const action = defineAsyncComponent(() => import('~/components/pub/custom-ui/data/dropdown-action-dud.vue')) -export const cols: Col[] = [{ width: 100 }, { width: 250 }, { width: 100 }, { width: 100 }, { width: 50 }] +export const cols: Col[] = [{ width: 100 }, { width: 250 }, { width: 100 }, { width: 100 }, { width: 100 }, { width: 50 }] -export const header: Th[][] = [[{ label: 'Kode' }, { label: 'Nama' }, { label: 'Item' }, { label: 'Satuan' }]] +export const header: Th[][] = [[{ label: 'Kode' }, { label: 'Nama' }, { label: 'Stok' }, { label: 'Item' }, { label: 'Satuan' }]] -export const keys = ['code', 'name', 'item_id', 'uom_code', 'action'] +export const keys = ['code', 'name', 'stock', 'item_id', 'uom_code', 'action'] export const delKeyNames: KeyLabel[] = [ { key: 'code', label: 'Kode' }, diff --git a/app/components/flow/material/entry.vue b/app/components/flow/material/entry.vue index b5c8c491..c68449e5 100644 --- a/app/components/flow/material/entry.vue +++ b/app/components/flow/material/entry.vue @@ -14,7 +14,7 @@ const schema = z.object({ code: z.string().min(1, 'Code must be at least 1 characters long'), name: z.string().min(1, 'Name must be at least 1 characters long'), type: z.string(), - stock: z.preprocess((val) => Number(val), z.number({ invalid_type_error: 'Stok harus berupa angka' })), + stock: z.preprocess((val) => Number(val), z.number({ invalid_type_error: 'Stock must be a number' }).min(1)), }) function onClick(type: string) { From 81fa38275abb3b0faaebbc4380274f5eff9a3648 Mon Sep 17 00:00:00 2001 From: riefive Date: Wed, 3 Sep 2025 15:41:55 +0700 Subject: [PATCH 2/6] feat (material): update validation with error label --- app/components/app/material/entry-form.vue | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/components/app/material/entry-form.vue b/app/components/app/material/entry-form.vue index 52214e3f..677de4b7 100644 --- a/app/components/app/material/entry-form.vue +++ b/app/components/app/material/entry-form.vue @@ -63,6 +63,10 @@ const items = [ + + + {{ props.errors.stock }} + From 209f78df0a2521b2aa08fc73099a44c197bcd748 Mon Sep 17 00:00:00 2001 From: riefive Date: Thu, 4 Sep 2025 14:56:23 +0700 Subject: [PATCH 3/6] feat(material): change menu material to equipment --- .../{material => equipment}/add.vue | 0 .../{material => equipment}/index.vue | 0 public/side-menu-items/sys.json | 12 ++++++++++++ 3 files changed, 12 insertions(+) rename app/pages/(features)/tools-equipment-src/{material => equipment}/add.vue (100%) rename app/pages/(features)/tools-equipment-src/{material => equipment}/index.vue (100%) diff --git a/app/pages/(features)/tools-equipment-src/material/add.vue b/app/pages/(features)/tools-equipment-src/equipment/add.vue similarity index 100% rename from app/pages/(features)/tools-equipment-src/material/add.vue rename to app/pages/(features)/tools-equipment-src/equipment/add.vue diff --git a/app/pages/(features)/tools-equipment-src/material/index.vue b/app/pages/(features)/tools-equipment-src/equipment/index.vue similarity index 100% rename from app/pages/(features)/tools-equipment-src/material/index.vue rename to app/pages/(features)/tools-equipment-src/equipment/index.vue diff --git a/public/side-menu-items/sys.json b/public/side-menu-items/sys.json index 2b803fc0..cbc252c8 100644 --- a/public/side-menu-items/sys.json +++ b/public/side-menu-items/sys.json @@ -85,6 +85,18 @@ "link": "/satusehat", "badge": "FHIR" }, + { + "title": "Peralatan dan Perlengkapan", + "icon": "i-lucide-dock", + "link": "/tools-equipment-src", + "children": [ + { + "title": "Perlengkapan (BMHP)", + "icon": "i-lucide-panel-bottom", + "link": "/tools-equipment-src/equipment" + } + ] + }, { "title": "Medical Records", "icon": "i-lucide-file-text", From 21d087e496af9c415a95fe06c4e2124ade362b23 Mon Sep 17 00:00:00 2001 From: riefive Date: Thu, 4 Sep 2025 15:55:32 +0700 Subject: [PATCH 4/6] refactor(material): add zod validation for stock field as number and display error message after submit in --- app/components/app/material/entry-form.vue | 180 ++++++++++++++------- app/components/flow/material/entry.vue | 68 ++------ app/components/flow/material/list.vue | 14 +- app/schemas/material.ts | 14 ++ 4 files changed, 155 insertions(+), 121 deletions(-) create mode 100644 app/schemas/material.ts diff --git a/app/components/app/material/entry-form.vue b/app/components/app/material/entry-form.vue index 677de4b7..65dd134b 100644 --- a/app/components/app/material/entry-form.vue +++ b/app/components/app/material/entry-form.vue @@ -1,74 +1,130 @@ diff --git a/app/components/flow/material/entry.vue b/app/components/flow/material/entry.vue index c68449e5..82e9021e 100644 --- a/app/components/flow/material/entry.vue +++ b/app/components/flow/material/entry.vue @@ -1,64 +1,28 @@ diff --git a/app/components/flow/material/list.vue b/app/components/flow/material/list.vue index 28fb6290..fa719f46 100644 --- a/app/components/flow/material/list.vue +++ b/app/components/flow/material/list.vue @@ -26,21 +26,21 @@ const recAction = ref('') const recItem = ref(null) const headerPrep: HeaderPrep = { - title: 'BMHP', - icon: 'i-lucide-paint-bucket', + title: 'Perlengkapan (BMHP)', + icon: 'i-lucide-panel-bottom', addNav: { label: 'Tambah', - onClick: () => navigateTo('/tools-equipment-src/material/add'), + onClick: () => navigateTo('/tools-equipment-src/equipment/add'), }, } async function getMaterialList() { isLoading.dataListLoading = true - const resp = await xfetch('/api/v1/material') - if (resp.success) { - data.value = (resp.body as Record).data - } + // const resp = await xfetch('/api/v1/material') + // if (resp.success) { + // data.value = (resp.body as Record).data + // } isLoading.dataListLoading = false } diff --git a/app/schemas/material.ts b/app/schemas/material.ts new file mode 100644 index 00000000..8b024471 --- /dev/null +++ b/app/schemas/material.ts @@ -0,0 +1,14 @@ +import { z } from 'zod' + +const schema = z.object({ + code: z.string({ required_error: 'Kode harus diisi' }).min(1, 'Kode minimum 1 karakter'), + name: z.string({ required_error: 'Nama harus diisi' }).min(1, 'Nama minimum 1 karakter'), + uom_code: z.string({ required_error: 'Kode unit harus diisi' }), + item_id: z.string({ required_error: 'Tipe harus diisi' }), + stock: z.preprocess((val) => Number(val), z.number({ invalid_type_error: 'Stok harus berupa angka' }).min(1)), +}) + +type formData = z.infer + +export { schema as MaterialSchema } +export type { formData as MaterialFormData } From ffa4a7d19191377de6a9ca522419e17c47fd149a Mon Sep 17 00:00:00 2001 From: riefive Date: Thu, 4 Sep 2025 16:21:10 +0700 Subject: [PATCH 5/6] refactor(material): modify validation uom and item --- app/components/app/material/entry-form.vue | 30 ++++++++++--------- app/components/flow/material/entry.vue | 23 ++++++++++---- app/components/pub/ui/select/Select.vue | 3 +- .../pub/ui/select/SelectTrigger.vue | 6 ++-- app/schemas/material.ts | 6 ++-- 5 files changed, 41 insertions(+), 27 deletions(-) diff --git a/app/components/app/material/entry-form.vue b/app/components/app/material/entry-form.vue index 65dd134b..d670f60c 100644 --- a/app/components/app/material/entry-form.vue +++ b/app/components/app/material/entry-form.vue @@ -11,6 +11,7 @@ import Label from '~/components/pub/custom-ui/form/label.vue' interface Props { isLoading: boolean schema: z.ZodSchema + uoms: any[] items: any[] } @@ -20,11 +21,13 @@ const emit = defineEmits<{ submit: [data: any] }>() -const { handleSubmit, defineField, errors, meta } = useForm({ +const { handleSubmit, defineField, errors } = useForm({ validationSchema: toTypedSchema(props.schema), initialValues: { code: '', name: '', + uom_code: '', + item_id: '', stock: 0, } as Partial, }) @@ -36,7 +39,6 @@ const [item, itemAttrs] = defineField('item_id') const [stock, stockAttrs] = defineField('stock') const onSubmit = handleSubmit(async (values) => { - console.log(errors) try { emit('submit', values) } catch (error) { @@ -77,30 +79,32 @@ const onSubmit = handleSubmit(async (values) => { - - {{ errors.uom }} + + {{ errors.item_id }}
@@ -117,10 +121,8 @@ const onSubmit = handleSubmit(async (values) => { {{ errors.stock }}
-
- +
+
- + diff --git a/app/components/pub/ui/select/Select.vue b/app/components/pub/ui/select/Select.vue index 3020ed97..dfde6ef8 100644 --- a/app/components/pub/ui/select/Select.vue +++ b/app/components/pub/ui/select/Select.vue @@ -19,6 +19,7 @@ interface Item { const props = defineProps< SelectRootProps & { items: Item[] + iconName?: string placeholder?: string label?: string separator?: boolean @@ -31,7 +32,7 @@ const forwarded = useForwardPropsEmits(props, emits)