refactor(patient-preview): comment out unused occupation field in patient preview fix(handler): return success response from update operation in crud handler fix search patient add handle del search char for ease use
278 lines
7.1 KiB
TypeScript
278 lines
7.1 KiB
TypeScript
import { ref } from 'vue'
|
|
|
|
// Factory for CRUD handler state and actions
|
|
export function createCrudHandler<T = any>(crud: {
|
|
post: (...args: any[]) => Promise<any>
|
|
patch: (...args: any[]) => Promise<any>
|
|
remove: (...args: any[]) => Promise<any>
|
|
}) {
|
|
const recId = ref<number>(0)
|
|
const recAction = ref<string>('')
|
|
const recItem = ref<T | null>(null)
|
|
const isReadonly = ref(false)
|
|
const isProcessing = ref(false)
|
|
const isFormEntryDialogOpen = ref(false)
|
|
const isRecordConfirmationOpen = ref(false)
|
|
|
|
function onResetState() {
|
|
recId.value = 0
|
|
recAction.value = ''
|
|
recItem.value = null
|
|
}
|
|
|
|
async function handleActionSave(values: any, refresh: () => void, reset: () => void, toast: ToastFn) {
|
|
isProcessing.value = true
|
|
await handleAsyncAction<[any], any>({
|
|
action: crud.post,
|
|
args: [values],
|
|
toast,
|
|
successMessage: 'Data berhasil disimpan',
|
|
errorMessage: 'Gagal menyimpan data',
|
|
onSuccess: () => {
|
|
isFormEntryDialogOpen.value = false
|
|
if (refresh) refresh()
|
|
},
|
|
onFinally: (isSuccess: boolean) => {
|
|
if (isSuccess) setTimeout(reset, 300)
|
|
onResetState()
|
|
isProcessing.value = false
|
|
},
|
|
})
|
|
}
|
|
|
|
async function handleActionEdit(
|
|
id: number | string,
|
|
values: any,
|
|
refresh: () => void,
|
|
reset: () => void,
|
|
toast: ToastFn,
|
|
) {
|
|
isProcessing.value = true
|
|
await handleAsyncAction<[number | string, any], any>({
|
|
action: crud.patch,
|
|
args: [id, values],
|
|
toast,
|
|
successMessage: 'Data berhasil diubah',
|
|
errorMessage: 'Gagal mengubah data',
|
|
onSuccess: () => {
|
|
isFormEntryDialogOpen.value = false
|
|
if (refresh) refresh()
|
|
},
|
|
onFinally: (isSuccess: boolean) => {
|
|
if (isSuccess) setTimeout(reset, 300)
|
|
onResetState()
|
|
isProcessing.value = false
|
|
},
|
|
})
|
|
}
|
|
|
|
async function handleActionRemove(id: number | string, refresh: () => void, toast: ToastFn) {
|
|
isProcessing.value = true
|
|
await handleAsyncAction<[number | string], any>({
|
|
action: crud.remove,
|
|
args: [id],
|
|
toast,
|
|
successMessage: 'Data berhasil dihapus',
|
|
errorMessage: 'Gagal menghapus data',
|
|
onSuccess: () => {
|
|
isRecordConfirmationOpen.value = false
|
|
if (refresh) refresh()
|
|
},
|
|
onFinally: () => {
|
|
setTimeout(refresh, 300)
|
|
onResetState()
|
|
isProcessing.value = false
|
|
},
|
|
})
|
|
}
|
|
|
|
function handleCancelForm(reset: () => void) {
|
|
isFormEntryDialogOpen.value = false
|
|
isReadonly.value = false
|
|
onResetState()
|
|
setTimeout(reset, 300)
|
|
}
|
|
|
|
return {
|
|
recId,
|
|
recAction,
|
|
recItem,
|
|
isReadonly,
|
|
isProcessing,
|
|
isFormEntryDialogOpen,
|
|
isRecordConfirmationOpen,
|
|
onResetState,
|
|
handleActionSave,
|
|
handleActionEdit,
|
|
handleActionRemove,
|
|
handleCancelForm,
|
|
}
|
|
}
|
|
|
|
// Factory for CRUD handler state and actions
|
|
export function genCrudHandler<T = any>(crud: {
|
|
create: (...args: any[]) => Promise<any>
|
|
update: (...args: any[]) => Promise<any>
|
|
remove: (...args: any[]) => Promise<any>
|
|
}) {
|
|
const recId = ref<number>(0)
|
|
const recAction = ref<string>('')
|
|
const recItem = ref<T | null>(null)
|
|
const isReadonly = ref(false)
|
|
const isProcessing = ref(false)
|
|
const isFormEntryDialogOpen = ref(false)
|
|
const isRecordConfirmationOpen = ref(false)
|
|
|
|
function onResetState() {
|
|
recId.value = 0
|
|
recAction.value = ''
|
|
recItem.value = null
|
|
}
|
|
|
|
async function handleActionSave(
|
|
values: any,
|
|
refresh: () => void,
|
|
reset: () => void,
|
|
toast: ToastFn,
|
|
): Promise<any | null> {
|
|
isProcessing.value = true
|
|
|
|
let successResponse: any = null
|
|
|
|
await handleAsyncAction<[any], any>({
|
|
action: crud.create,
|
|
args: [values],
|
|
toast,
|
|
successMessage: 'Data berhasil disimpan',
|
|
errorMessage: 'Gagal menyimpan data',
|
|
onSuccess: (result) => {
|
|
isFormEntryDialogOpen.value = false
|
|
if (refresh) refresh()
|
|
successResponse = result
|
|
},
|
|
onFinally: (isSuccess: boolean) => {
|
|
if (isSuccess) setTimeout(reset, 500)
|
|
isProcessing.value = false
|
|
},
|
|
})
|
|
|
|
return successResponse
|
|
}
|
|
|
|
async function handleActionEdit(
|
|
id: number | string,
|
|
values: any,
|
|
refresh: () => void,
|
|
reset: () => void,
|
|
toast: ToastFn,
|
|
): Promise<any | null> {
|
|
isProcessing.value = true
|
|
|
|
let successResponse: any = null
|
|
|
|
await handleAsyncAction<[number | string, any], any>({
|
|
action: crud.update,
|
|
args: [id, values],
|
|
toast,
|
|
successMessage: 'Data berhasil diubah',
|
|
errorMessage: 'Gagal mengubah data',
|
|
onSuccess: (result) => {
|
|
isFormEntryDialogOpen.value = false
|
|
successResponse = result
|
|
if (refresh) refresh()
|
|
},
|
|
onFinally: (isSuccess: boolean) => {
|
|
if (isSuccess) setTimeout(reset, 500)
|
|
isProcessing.value = false
|
|
},
|
|
})
|
|
|
|
return successResponse
|
|
}
|
|
|
|
async function handleActionRemove(id: number | string, refresh: () => void, toast: ToastFn) {
|
|
isProcessing.value = true
|
|
await handleAsyncAction<[number | string], any>({
|
|
action: crud.remove,
|
|
args: [id],
|
|
toast,
|
|
successMessage: 'Data berhasil dihapus',
|
|
errorMessage: 'Gagal menghapus data',
|
|
onSuccess: () => {
|
|
isRecordConfirmationOpen.value = false
|
|
if (refresh) refresh()
|
|
},
|
|
onFinally: () => {
|
|
setTimeout(refresh, 300)
|
|
onResetState()
|
|
isProcessing.value = false
|
|
},
|
|
})
|
|
}
|
|
|
|
function handleCancelForm(reset: () => void) {
|
|
isFormEntryDialogOpen.value = false
|
|
isReadonly.value = false
|
|
onResetState()
|
|
setTimeout(reset, 300)
|
|
}
|
|
|
|
return {
|
|
recId,
|
|
recAction,
|
|
recItem,
|
|
isReadonly,
|
|
isProcessing,
|
|
isFormEntryDialogOpen,
|
|
isRecordConfirmationOpen,
|
|
onResetState,
|
|
handleActionSave,
|
|
handleActionEdit,
|
|
handleActionRemove,
|
|
handleCancelForm,
|
|
}
|
|
}
|
|
|
|
// Reusable async handler for CRUD actions with toast and state management
|
|
export type ToastFn = (params: { title: string; description: string; variant: 'default' | 'destructive' }) => void
|
|
|
|
export interface HandleAsyncActionOptions<T extends any[], R> {
|
|
action: (...args: T) => Promise<R & { success: boolean }>
|
|
args?: T
|
|
toast: ToastFn
|
|
successMessage: string
|
|
errorMessage: string
|
|
onSuccess?: (result: R) => void
|
|
onError?: (error: unknown) => void
|
|
onFinally?: (isSuccess: boolean) => void
|
|
}
|
|
|
|
export async function handleAsyncAction<T extends any[], R>({
|
|
action,
|
|
args = [] as unknown as T,
|
|
toast,
|
|
successMessage,
|
|
errorMessage,
|
|
onSuccess,
|
|
onError,
|
|
onFinally,
|
|
}: HandleAsyncActionOptions<T, R>) {
|
|
let isSuccess = false
|
|
try {
|
|
const result = await action(...args)
|
|
if (result.success) {
|
|
toast({ title: 'Berhasil', description: successMessage, variant: 'default' })
|
|
isSuccess = true
|
|
if (onSuccess) onSuccess(result)
|
|
} else {
|
|
toast({ title: 'Gagal', description: errorMessage, variant: 'destructive' })
|
|
if (onError) onError(result)
|
|
}
|
|
} catch (error) {
|
|
toast({ title: 'Gagal', description: errorMessage, variant: 'destructive' })
|
|
if (onError) onError(error)
|
|
} finally {
|
|
if (onFinally) onFinally(isSuccess)
|
|
}
|
|
}
|