From c749e91ffa3f39335b5ac58dc9f7d2a1991d5d49 Mon Sep 17 00:00:00 2001 From: Thanaphon Frappet Date: Mon, 1 Sep 2025 14:53:52 +0700 Subject: [PATCH] feat: add customer export --- src/pages/03_customer-management/MainPage.vue | 22 +++++++- src/stores/customer/index.ts | 49 +++++++++++++++++ src/stores/employee/index.ts | 52 +++++++++++++++++++ 3 files changed, 122 insertions(+), 1 deletion(-) diff --git a/src/pages/03_customer-management/MainPage.vue b/src/pages/03_customer-management/MainPage.vue index b482ab77..e02a381e 100644 --- a/src/pages/03_customer-management/MainPage.vue +++ b/src/pages/03_customer-management/MainPage.vue @@ -548,6 +548,19 @@ async function openSpecificEmployee(id: string) { employeeFormState.value.drawerModal = true; } +async function triggerExport() { + switch (currentTab.value) { + case 'employer': + customerStore.customerExport({ pageSize: 10000 }); + + break; + + case 'employee': + employeeStore.employeeExport({ pageSize: 10000 }); + break; + } +} + // TODO: When in employee form, if select address same as customer then auto fill watch( @@ -801,7 +814,7 @@ const emptyCreateDialog = ref(false); outlined dense :label="$t('general.search')" - class="col col-md-3" + class="col col-md-3 q-mr-sm" :bg-color="$q.dark.isActive ? 'dark' : 'white'" v-model="inputSearch" debounce="200" @@ -843,6 +856,13 @@ const emptyCreateDialog = ref(false); + +
{ @@ -472,6 +473,52 @@ const useCustomerStore = defineStore('api-customer', () => { return false; } + async function customerExport(params: { + customerType?: CustomerType; + query?: string; + status?: 'CREATED' | 'ACTIVE' | 'INACTIVE'; + page?: number; + pageSize?: number; + includeBranch?: boolean; + company?: boolean; + activeBranchOnly?: boolean; + startDate?: string | Date; + endDate?: string | Date; + }) { + let url = baseUrl + '/' + 'customer-export'; + + const queryParams = new URLSearchParams( + Object.keys(params).reduce((acc: Record, key) => { + const value = params[key as keyof typeof params]; + if (value !== undefined && value !== null && value !== '') { + const stringValue = + typeof value === 'boolean' || typeof value === 'number' + ? String(value) + : value instanceof Date + ? value.toISOString() + : String(value); + acc[key] = stringValue; + } + return acc; + }, {}), + ); + + url += '?' + queryParams.toString(); + + const res = await fetch(url, { + headers: { ['Authorization']: 'Bearer ' + (await getToken()) }, + }); + const text = await res.json(); + const blob = new Blob([text], { type: 'text/csv' }); + if (res.ok && blob) { + const a = document.createElement('a'); + a.download = 'customer-report' + '.csv'; + a.href = window.URL.createObjectURL(blob); + a.click(); + a.remove(); + } + } + return { data, @@ -498,6 +545,8 @@ const useCustomerStore = defineStore('api-customer', () => { fetchBranchEmployee, deleteAttachment, + + customerExport, ...attachmentManager, ...fileManager, ...metaManager, diff --git a/src/stores/employee/index.ts b/src/stores/employee/index.ts index 731ce902..f7128eb6 100644 --- a/src/stores/employee/index.ts +++ b/src/stores/employee/index.ts @@ -15,6 +15,7 @@ import { EmployeeVisaPayload, } from './types'; import { CustomerBranch } from '../customer/types'; +import { getToken } from 'src/services/keycloak'; import { baseUrl, manageAttachment, manageFile, manageMeta } from '../utils'; const useEmployeeStore = defineStore('api-employee', () => { @@ -469,6 +470,55 @@ const useEmployeeStore = defineStore('api-employee', () => { return false; } + async function employeeExport(params: { + zipCode?: string; + gender?: string; + status?: Status; + visa?: boolean; + passport?: boolean; + customerId?: string; + customerBranchId?: string; + query?: string; + page?: number; + pageSize?: number; + activeOnly?: boolean; + startDate?: string | Date; + endDate?: string | Date; + }) { + let url = baseUrl + '/' + 'employee-export'; + + const queryParams = new URLSearchParams( + Object.keys(params).reduce((acc: Record, key) => { + const value = params[key as keyof typeof params]; + if (value !== undefined && value !== null && value !== '') { + const stringValue = + typeof value === 'boolean' || typeof value === 'number' + ? String(value) + : value instanceof Date + ? value.toISOString() + : String(value); + acc[key] = stringValue; + } + return acc; + }, {}), + ); + + url += '?' + queryParams.toString(); + + const res = await fetch(url, { + headers: { ['Authorization']: 'Bearer ' + (await getToken()) }, + }); + const text = await res.json(); + const blob = new Blob([text], { type: 'text/csv' }); + if (res.ok && blob) { + const a = document.createElement('a'); + a.download = 'employee-report' + '.csv'; + a.href = window.URL.createObjectURL(blob); + a.click(); + a.remove(); + } + } + return { data, globalOption, @@ -512,6 +562,8 @@ const useEmployeeStore = defineStore('api-employee', () => { ...attachmentManager, ...fileManager, ...metaManager, + + employeeExport, }; });