chore: add handler parent

This commit is contained in:
riefive
2025-09-25 13:03:54 +07:00
parent 23c8282095
commit f0f32598f4
3 changed files with 155 additions and 119 deletions
+42
View File
@@ -0,0 +1,42 @@
// 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)
}
}
+68 -55
View File
@@ -1,5 +1,8 @@
import { ref } from 'vue' import { ref } from 'vue'
// Handlers
import { type ToastFn, handleAsyncAction } from '~/handlers/_handler'
// Services // Services
import { postSourceDevice, patchSourceDevice, removeSourceDevice } from '~/services/device.service' import { postSourceDevice, patchSourceDevice, removeSourceDevice } from '~/services/device.service'
@@ -16,65 +19,75 @@ function onResetState() {
recItem.value = null recItem.value = null
} }
export async function handleActionSave(values: any, refresh: () => void, reset: () => void) { export async function handleActionSave(
let isSuccess = false values: any,
isProcessing.value = true refresh: () => void,
try { reset: () => void,
const result = await postSourceDevice(values) toast: ToastFn
if (result.success) { ) {
isFormEntryDialogOpen.value = false isProcessing.value = true;
isSuccess = true await handleAsyncAction<[any], any>({
if (refresh) refresh() action: postSourceDevice,
} args: [values],
} catch (error) { toast,
console.warn('Error saving form:', error) successMessage: 'Data berhasil disimpan',
isSuccess = false errorMessage: 'Gagal menyimpan data',
} finally { onSuccess: () => {
if (isSuccess) { isFormEntryDialogOpen.value = false;
setTimeout(() => { if (refresh) refresh();
reset() },
}, 500) onFinally: (isSuccess: boolean) => {
} if (isSuccess) setTimeout(reset, 500);
isProcessing.value = false isProcessing.value = false;
} },
});
} }
export async function handleActionEdit(id: number | string, values: any, refresh: () => void, reset: () => void) { export async function handleActionEdit(
let isSuccess = false id: number | string,
isProcessing.value = true values: any,
try { refresh: () => void,
const result = await patchSourceDevice(id, values) reset: () => void,
if (result.success) { toast: ToastFn
isFormEntryDialogOpen.value = false ) {
isSuccess = true isProcessing.value = true;
if (refresh) refresh() await handleAsyncAction<[number | string, any], any>({
} action: patchSourceDevice,
} catch (error) { args: [id, values],
console.warn('Error editing form:', error) toast,
isSuccess = false successMessage: 'Data berhasil diubah',
} finally { errorMessage: 'Gagal mengubah data',
if (isSuccess) { onSuccess: () => {
setTimeout(() => { isFormEntryDialogOpen.value = false;
reset() if (refresh) refresh();
}, 500) },
} onFinally: (isSuccess: boolean) => {
isProcessing.value = false if (isSuccess) setTimeout(reset, 500);
} isProcessing.value = false;
},
});
} }
export async function handleActionRemove(id: number | string, refresh: () => void) { export async function handleActionRemove(
isProcessing.value = true id: number | string,
try { refresh: () => void,
const result = await removeSourceDevice(id) toast: ToastFn
if (result.success) { ) {
if (refresh) refresh() isProcessing.value = true;
} await handleAsyncAction<[number | string], any>({
} catch (error) { action: removeSourceDevice,
console.error('Error deleting record:', error) args: [id],
} finally { toast,
onResetState() successMessage: 'Data berhasil dihapus',
isProcessing.value = false errorMessage: 'Gagal menghapus data',
} onSuccess: () => {
if (refresh) refresh();
},
onFinally: () => {
onResetState();
isProcessing.value = false;
},
});
} }
export function handleCancelForm(reset: () => void) { export function handleCancelForm(reset: () => void) {
+45 -64
View File
@@ -1,5 +1,8 @@
import { ref } from 'vue' import { ref } from 'vue'
// Handlers
import { type ToastFn, handleAsyncAction } from '~/handlers/_handler'
// Services // Services
import { postSourceMaterial, patchSourceMaterial, removeSourceMaterial } from '~/services/material.service' import { postSourceMaterial, patchSourceMaterial, removeSourceMaterial } from '~/services/material.service'
@@ -17,36 +20,23 @@ function onResetState() {
recItem.value = null recItem.value = null
} }
export async function handleActionSave( export async function handleActionSave(values: any, refresh: () => void, reset: () => void, toast: ToastFn) {
values: any,
refresh: () => void,
reset: () => void,
toast: (params: any) => void,
) {
let isSuccess = false
isProcessing.value = true isProcessing.value = true
try { await handleAsyncAction<[any], any>({
const result = await postSourceMaterial(values) action: postSourceMaterial,
if (result.success) { args: [values],
toast({ title: 'Berhasil', description: 'Data berhasil disimpan', variant: 'default' }) toast,
successMessage: 'Data berhasil disimpan',
errorMessage: 'Gagal menyimpan data',
onSuccess: () => {
isFormEntryDialogOpen.value = false isFormEntryDialogOpen.value = false
isSuccess = true
if (refresh) refresh() if (refresh) refresh()
} else { },
toast({ title: 'Gagal', description: 'Gagal menyimpan data', variant: 'destructive' }) onFinally: (isSuccess: boolean) => {
} if (isSuccess) setTimeout(reset, 500)
} catch (error) { isProcessing.value = false
console.warn('Error saving form:', error) },
toast({ title: 'Gagal', description: 'Gagal menyimpan data', variant: 'destructive' }) })
isSuccess = false
} finally {
if (isSuccess) {
setTimeout(() => {
reset()
}, 500)
}
isProcessing.value = false
}
} }
export async function handleActionEdit( export async function handleActionEdit(
@@ -54,51 +44,42 @@ export async function handleActionEdit(
values: any, values: any,
refresh: () => void, refresh: () => void,
reset: () => void, reset: () => void,
toast: (params: any) => void, toast: ToastFn,
) { ) {
let isSuccess = false
isProcessing.value = true isProcessing.value = true
try { await handleAsyncAction<[number | string, any], any>({
const result = await patchSourceMaterial(id, values) action: patchSourceMaterial,
if (result.success) { args: [id, values],
toast({ title: 'Berhasil', description: 'Data berhasil diubah', variant: 'default' }) toast,
successMessage: 'Data berhasil diubah',
errorMessage: 'Gagal mengubah data',
onSuccess: () => {
isFormEntryDialogOpen.value = false isFormEntryDialogOpen.value = false
isSuccess = true
if (refresh) refresh() if (refresh) refresh()
} else { },
toast({ title: 'Gagal', description: 'Gagal mengubah data', variant: 'destructive' }) onFinally: (isSuccess: boolean) => {
} if (isSuccess) setTimeout(reset, 500)
} catch (error) { isProcessing.value = false
console.warn('Error editing form:', error) },
toast({ title: 'Gagal', description: 'Gagal mengubah data', variant: 'destructive' }) })
isSuccess = false
} finally {
if (isSuccess) {
setTimeout(() => {
reset()
}, 500)
}
isProcessing.value = false
}
} }
export async function handleActionRemove(id: number | string, refresh: () => void, toast: (params: any) => void) { export async function handleActionRemove(id: number | string, refresh: () => void, toast: ToastFn) {
isProcessing.value = true isProcessing.value = true
try { await handleAsyncAction<[number | string], any>({
const result = await removeSourceMaterial(id) action: removeSourceMaterial,
if (result.success) { args: [id],
toast({ title: 'Berhasil', description: 'Data berhasil dihapus', variant: 'default' }) toast,
successMessage: 'Data berhasil dihapus',
errorMessage: 'Gagal menghapus data',
onSuccess: () => {
if (refresh) refresh() if (refresh) refresh()
} else { },
toast({ title: 'Gagal', description: 'Gagal menghapus data', variant: 'destructive' }) onFinally: () => {
} onResetState()
} catch (error) { isProcessing.value = false
console.error('Error deleting record:', error) },
toast({ title: 'Gagal', description: 'Gagal menghapus data', variant: 'destructive' }) })
} finally {
onResetState()
isProcessing.value = false
}
} }
export function handleCancelForm(reset: () => void) { export function handleCancelForm(reset: () => void) {