feat: remove 'code' field from Business Type; update filters and form validation

This commit is contained in:
Yoga Pangestu 2026-07-24 12:09:04 +07:00
parent a71be47b58
commit 8c7002a326
3 changed files with 50 additions and 31 deletions

View File

@ -13,7 +13,6 @@ import {
export interface BusinessType { export interface BusinessType {
id: string id: string
code: string
name: string name: string
description: string | null description: string | null
is_active: boolean | number is_active: boolean | number
@ -23,11 +22,10 @@ export function copy(id: string) {
navigator.clipboard.writeText(id) navigator.clipboard.writeText(id)
} }
const nameAndCodeFilter: FilterFn<BusinessType> = (row, _columnId, filterValue) => { const nameFilter: FilterFn<BusinessType> = (row, _columnId, filterValue) => {
const search = (filterValue as string).toLowerCase() const search = (filterValue as string).toLowerCase()
const name = (row.original.name as string).toLowerCase() const name = (row.original.name as string).toLowerCase()
const code = (row.original.code as string).toLowerCase() return name.includes(search)
return name.includes(search) || code.includes(search)
} }
const booleanFilter: FilterFn<BusinessType> = (row, columnId, filterValue) => { const booleanFilter: FilterFn<BusinessType> = (row, columnId, filterValue) => {
@ -44,27 +42,17 @@ export function getColumns(callbacks: {
onToggleStatus: (businessType: BusinessType, value: boolean) => void onToggleStatus: (businessType: BusinessType, value: boolean) => void
}): ColumnDef<BusinessType>[] { }): ColumnDef<BusinessType>[] {
return [ return [
{
accessorKey: 'code',
header: ({ column }) => {
return h(Button, {
variant: 'ghost',
onClick: () => column.toggleSorting(column.getIsSorted() === 'asc'),
}, () => ['Kode', h(ArrowUpDown, { class: 'ml-2 h-4 w-4' })])
},
cell: ({ row }) => h('div', { class: 'font-medium' }, row.getValue('code')),
},
{ {
id: 'name_search', id: 'name_search',
accessorFn: row => `${row.name} ${row.code}`, accessorFn: row => row.name,
header: ({ column }) => { header: ({ column }) => {
return h(Button, { return h(Button, {
variant: 'ghost', variant: 'ghost',
onClick: () => column.toggleSorting(column.getIsSorted() === 'asc'), onClick: () => column.toggleSorting(column.getIsSorted() === 'asc'),
}, () => ['Nama', h(ArrowUpDown, { class: 'ml-2 h-4 w-4' })]) }, () => ['Nama', h(ArrowUpDown, { class: 'ml-2 h-4 w-4' })])
}, },
cell: ({ row }) => h('div', {}, row.original.name), cell: ({ row }) => h('div', { class: 'font-medium' }, row.original.name),
filterFn: nameAndCodeFilter, filterFn: nameFilter,
enableHiding: false, enableHiding: false,
}, },
{ {

View File

@ -57,12 +57,11 @@ const formMode = ref<FormMode>('create')
const selectedBusinessType = ref<BusinessType | null>(null) const selectedBusinessType = ref<BusinessType | null>(null)
interface FormData { interface FormData {
code: string
name: string name: string
description: string description: string
} }
const form = ref<FormData>({ code: '', name: '', description: '' }) const form = ref<FormData>({ name: '', description: '' })
// --- Loading states --- // --- Loading states ---
const formLoading = ref(false) const formLoading = ref(false)
@ -75,7 +74,7 @@ const formTitle = computed(() => formMode.value === 'create' ? 'Tambah Jenis Bis
function openCreateForm() { function openCreateForm() {
formMode.value = 'create' formMode.value = 'create'
selectedBusinessType.value = null selectedBusinessType.value = null
form.value = { code: '', name: '', description: '' } form.value = { name: '', description: '' }
formOpen.value = true formOpen.value = true
} }
@ -83,7 +82,6 @@ function handleEdit(bt: BusinessType) {
formMode.value = 'edit' formMode.value = 'edit'
selectedBusinessType.value = bt selectedBusinessType.value = bt
form.value = { form.value = {
code: bt.code,
name: bt.name, name: bt.name,
description: bt.description ?? '', description: bt.description ?? '',
} }
@ -116,8 +114,8 @@ const columns = computed(() => getColumns({ onEdit: handleEdit, onDelete: handle
// --- CRUD operations --- // --- CRUD operations ---
async function handleFormSubmit() { async function handleFormSubmit() {
if (!form.value.code.trim() || !form.value.name.trim()) { if (!form.value.name.trim()) {
toast.error('Kode dan nama wajib diisi') toast.error('Nama wajib diisi')
return return
} }
@ -127,7 +125,6 @@ async function handleFormSubmit() {
await $fetch(`${config.public.apiBase}/business-types`, { await $fetch(`${config.public.apiBase}/business-types`, {
method: 'POST', method: 'POST',
body: { body: {
code: form.value.code.trim(),
name: form.value.name.trim(), name: form.value.name.trim(),
description: form.value.description.trim() || null, description: form.value.description.trim() || null,
}, },
@ -137,7 +134,6 @@ async function handleFormSubmit() {
await $fetch(`${config.public.apiBase}/business-types/${selectedBusinessType.value!.id}`, { await $fetch(`${config.public.apiBase}/business-types/${selectedBusinessType.value!.id}`, {
method: 'PUT', method: 'PUT',
body: { body: {
code: form.value.code.trim(),
name: form.value.name.trim(), name: form.value.name.trim(),
description: form.value.description.trim() || null, description: form.value.description.trim() || null,
}, },
@ -195,7 +191,7 @@ function resetFilters(table: any) {
// --- Reset on dialog close --- // --- Reset on dialog close ---
watch(formOpen, (val) => { watch(formOpen, (val) => {
if (!val) { if (!val) {
form.value = { code: '', name: '', description: '' } form.value = { name: '', description: '' }
selectedBusinessType.value = null selectedBusinessType.value = null
} }
}) })
@ -232,7 +228,7 @@ watch(deleteOpen, (val) => {
<DataTable v-else ref="tableRef" :columns="columns" :data="businessTypes ?? []"> <DataTable v-else ref="tableRef" :columns="columns" :data="businessTypes ?? []">
<template #filters="{ table }"> <template #filters="{ table }">
<div class="flex items-center gap-2 py-4"> <div class="flex items-center gap-2 py-4">
<Input class="max-w-sm" placeholder="Cari nama atau kode..." <Input class="max-w-sm" placeholder="Cari nama..."
:model-value="(table.getColumn('name_search')?.getFilterValue() as string) ?? ''" :model-value="(table.getColumn('name_search')?.getFilterValue() as string) ?? ''"
@update:model-value="table.getColumn('name_search')?.setFilterValue($event)" /> @update:model-value="table.getColumn('name_search')?.setFilterValue($event)" />
<Select :model-value="getStatusFilter(table)" <Select :model-value="getStatusFilter(table)"
@ -296,10 +292,6 @@ watch(deleteOpen, (val) => {
</DialogHeader> </DialogHeader>
<form id="businessTypeForm" @submit.prevent="handleFormSubmit"> <form id="businessTypeForm" @submit.prevent="handleFormSubmit">
<FieldGroup class="gap-4"> <FieldGroup class="gap-4">
<Field>
<FieldLabel for="form-code">Kode <span class="text-red-500">*</span></FieldLabel>
<Input id="form-code" v-model="form.code" placeholder="Masukkan kode" :disabled="formLoading" />
</Field>
<Field> <Field>
<FieldLabel for="form-name">Nama <span class="text-red-500">*</span></FieldLabel> <FieldLabel for="form-name">Nama <span class="text-red-500">*</span></FieldLabel>
<Input id="form-name" v-model="form.name" placeholder="Masukkan nama" :disabled="formLoading" /> <Input id="form-name" v-model="form.name" placeholder="Masukkan nama" :disabled="formLoading" />

View File

@ -0,0 +1,39 @@
# Hapus Kolom Code dari Business Type (Frontend)
**Tanggal:** 2026-07-24
**Status:** Selesai
## Tujuan
Menghapus kolom `code` dari tampilan dan form data Jenis Bisnis di admin panel.
## Yang Dikerjakan
### 1. DataTable Columns
- Hapus kolom `code` dari tabel
- `nameAndCodeFilter``nameFilter` (hanya filter berdasarkan nama)
- `accessorFn` diubah dari `` row => `${row.name} ${row.code}` `` → `row => row.name`
- Placeholder search diubah dari "Cari nama atau kode..." → "Cari nama..."
### 2. Form Dialog
- Hapus field `code` dari form create/edit
- Hapus `code` dari interface `FormData`
- Sebelum: form fields = Kode (wajib), Nama (wajib), Deskripsi
- Sesudah: form fields = Nama (wajib), Deskripsi
### 3. CRUD Operations
- Hapus `code` dari body POST (create) dan PUT (update)
- Validasi diubah dari "Kode dan nama wajib diisi" → "Nama wajib diisi"
### 4. TypeScript Interface
- Hapus `code` dari `BusinessType` interface
## File yang Diubah
| File | Aksi | Detail |
|------|------|--------|
| `web2/app/pages/admin/business-types/columns.ts` | Diubah | Hapus kolom code, filter, accessorFn |
| `web2/app/pages/admin/business-types/index.vue` | Diubah | Hapus code dari form, body, validasi |
## Notes
- Search hanya berdasarkan nama setelah perubahan ini
- Tidak ada perubahan pada toggle status atau delete dialog