mirror of
https://github.com/InvoiceShelf/InvoiceShelf.git
synced 2026-04-18 10:44:08 +00:00
Now that the legacy v1 frontend (commit 064bdf53) is gone, the v2 directory is the only frontend and the v2 suffix is just noise. Renames resources/scripts-v2 to resources/scripts via git mv (so git records the move as renames, preserving blame and log --follow), then bulk-rewrites the 152 files that imported via @v2/... to use @/scripts/... instead. The existing @ alias (resources/) covers the new path with no extra config needed.
Drops the now-unused @v2 alias from vite.config.js and points the laravel-vite-plugin entry at resources/scripts/main.ts. Updates the only blade reference (resources/views/app.blade.php) to match. The package.json test script (eslint ./resources/scripts) automatically targets the right place after the rename without any edit.
Verified: npm run build exits clean and the Vite warning lines now reference resources/scripts/plugins/i18n.ts, confirming every import resolved through the new path. git log --follow on any moved file walks back through its scripts-v2 history.
336 lines
9.0 KiB
TypeScript
336 lines
9.0 KiB
TypeScript
import { defineStore } from 'pinia'
|
|
import { ref, computed } from 'vue'
|
|
import { useRoute } from 'vue-router'
|
|
import { customerService } from '../../../api/services/customer.service'
|
|
import type {
|
|
CustomerListParams,
|
|
CustomerListResponse,
|
|
CustomerStatsParams,
|
|
CustomerStatsResponse,
|
|
} from '../../../api/services/customer.service'
|
|
import { useNotificationStore } from '../../../stores/notification.store'
|
|
import { useGlobalStore } from '../../../stores/global.store'
|
|
import { useCompanyStore } from '../../../stores/company.store'
|
|
import { handleApiError } from '../../../utils/error-handling'
|
|
import type { Customer, CreateCustomerPayload } from '../../../types/domain/customer'
|
|
import type { Address } from '../../../types/domain/user'
|
|
import type { ApiResponse, DeletePayload } from '../../../types/api'
|
|
|
|
export interface CustomerFormAddress {
|
|
name: string | null
|
|
phone: string | null
|
|
address_street_1: string | null
|
|
address_street_2: string | null
|
|
city: string | null
|
|
state: string | null
|
|
country_id: number | null
|
|
zip: string | null
|
|
type: string | null
|
|
}
|
|
|
|
export interface CustomerForm {
|
|
id?: number
|
|
name: string
|
|
contact_name: string
|
|
email: string
|
|
phone: string | null
|
|
password: string
|
|
confirm_password: string
|
|
currency_id: number | null
|
|
website: string | null
|
|
prefix?: string | null
|
|
tax_id?: string | null
|
|
billing: CustomerFormAddress
|
|
shipping: CustomerFormAddress
|
|
customFields: unknown[]
|
|
fields: unknown[]
|
|
enable_portal: boolean
|
|
password_added?: boolean
|
|
}
|
|
|
|
export type CustomerViewData = Partial<Customer>
|
|
|
|
function createAddressStub(): CustomerFormAddress {
|
|
return {
|
|
name: null,
|
|
phone: null,
|
|
address_street_1: null,
|
|
address_street_2: null,
|
|
city: null,
|
|
state: null,
|
|
country_id: null,
|
|
zip: null,
|
|
type: null,
|
|
}
|
|
}
|
|
|
|
function createCustomerStub(): CustomerForm {
|
|
return {
|
|
name: '',
|
|
contact_name: '',
|
|
email: '',
|
|
phone: null,
|
|
password: '',
|
|
confirm_password: '',
|
|
currency_id: null,
|
|
website: null,
|
|
billing: createAddressStub(),
|
|
shipping: createAddressStub(),
|
|
customFields: [],
|
|
fields: [],
|
|
enable_portal: false,
|
|
}
|
|
}
|
|
|
|
export const useCustomerStore = defineStore('customer', () => {
|
|
// State
|
|
const customers = ref<Customer[]>([])
|
|
const totalCustomers = ref<number>(0)
|
|
const selectAllField = ref<boolean>(false)
|
|
const selectedCustomers = ref<number[]>([])
|
|
const selectedViewCustomer = ref<CustomerViewData>({})
|
|
const isFetchingInitialSettings = ref<boolean>(false)
|
|
const isFetchingViewData = ref<boolean>(false)
|
|
const currentCustomer = ref<CustomerForm>(createCustomerStub())
|
|
const editCustomer = ref<Customer | null>(null)
|
|
|
|
// Getters
|
|
const isEdit = computed<boolean>(() => !!currentCustomer.value.id)
|
|
|
|
// Actions
|
|
function resetCurrentCustomer(): void {
|
|
currentCustomer.value = createCustomerStub()
|
|
}
|
|
|
|
function copyAddress(fromBillingToShipping = true): void {
|
|
if (fromBillingToShipping) {
|
|
currentCustomer.value.shipping = {
|
|
...currentCustomer.value.billing,
|
|
type: 'shipping',
|
|
}
|
|
}
|
|
}
|
|
|
|
async function fetchCustomerInitialSettings(isEditMode: boolean): Promise<void> {
|
|
const route = useRoute()
|
|
const globalStore = useGlobalStore()
|
|
const companyStore = useCompanyStore()
|
|
|
|
isFetchingInitialSettings.value = true
|
|
|
|
const editActions: Promise<unknown>[] = []
|
|
if (isEditMode) {
|
|
editActions.push(fetchCustomer(Number(route.params.id)))
|
|
} else {
|
|
currentCustomer.value.currency_id =
|
|
companyStore.selectedCompanyCurrency?.id ?? null
|
|
}
|
|
|
|
try {
|
|
await Promise.all([
|
|
globalStore.fetchCurrencies(),
|
|
globalStore.fetchCountries(),
|
|
...editActions,
|
|
])
|
|
isFetchingInitialSettings.value = false
|
|
} catch (err: unknown) {
|
|
isFetchingInitialSettings.value = false
|
|
handleApiError(err)
|
|
}
|
|
}
|
|
|
|
async function fetchCustomers(params?: CustomerListParams): Promise<CustomerListResponse> {
|
|
try {
|
|
const response = await customerService.list(params)
|
|
customers.value = response.data
|
|
totalCustomers.value = response.meta.customer_total_count
|
|
return response
|
|
} catch (err: unknown) {
|
|
handleApiError(err)
|
|
throw err
|
|
}
|
|
}
|
|
|
|
async function fetchViewCustomer(
|
|
params: { id: number } & CustomerStatsParams
|
|
): Promise<CustomerStatsResponse> {
|
|
isFetchingViewData.value = true
|
|
try {
|
|
const { id, ...queryParams } = params
|
|
const response = await customerService.getStats(id, queryParams)
|
|
selectedViewCustomer.value = {}
|
|
Object.assign(selectedViewCustomer.value, response.data)
|
|
isFetchingViewData.value = false
|
|
return response
|
|
} catch (err: unknown) {
|
|
isFetchingViewData.value = false
|
|
handleApiError(err)
|
|
throw err
|
|
}
|
|
}
|
|
|
|
async function fetchCustomer(id: number): Promise<ApiResponse<Customer>> {
|
|
try {
|
|
const response = await customerService.get(id)
|
|
Object.assign(currentCustomer.value, response.data)
|
|
setAddressStub(response.data as unknown as Record<string, unknown>)
|
|
return response
|
|
} catch (err: unknown) {
|
|
handleApiError(err)
|
|
throw err
|
|
}
|
|
}
|
|
|
|
async function addCustomer(data: CustomerForm): Promise<ApiResponse<Customer>> {
|
|
try {
|
|
const response = await customerService.create(data as unknown as CreateCustomerPayload)
|
|
customers.value.push(response.data)
|
|
|
|
const notificationStore = useNotificationStore()
|
|
notificationStore.showNotification({
|
|
type: 'success',
|
|
message: 'customers.created_message',
|
|
})
|
|
|
|
return response
|
|
} catch (err: unknown) {
|
|
handleApiError(err)
|
|
throw err
|
|
}
|
|
}
|
|
|
|
async function updateCustomer(data: CustomerForm): Promise<ApiResponse<Customer>> {
|
|
try {
|
|
const response = await customerService.update(
|
|
data.id!,
|
|
data as unknown as Partial<CreateCustomerPayload>
|
|
)
|
|
|
|
if (response.data) {
|
|
const pos = customers.value.findIndex(
|
|
(customer) => customer.id === response.data.id
|
|
)
|
|
if (pos !== -1) {
|
|
customers.value[pos] = response.data
|
|
}
|
|
|
|
const notificationStore = useNotificationStore()
|
|
notificationStore.showNotification({
|
|
type: 'success',
|
|
message: 'customers.updated_message',
|
|
})
|
|
}
|
|
|
|
return response
|
|
} catch (err: unknown) {
|
|
handleApiError(err)
|
|
throw err
|
|
}
|
|
}
|
|
|
|
async function deleteCustomer(payload: DeletePayload): Promise<{ success: boolean }> {
|
|
try {
|
|
const response = await customerService.delete(payload)
|
|
|
|
const index = customers.value.findIndex(
|
|
(customer) => customer.id === payload.ids[0]
|
|
)
|
|
if (index !== -1) {
|
|
customers.value.splice(index, 1)
|
|
}
|
|
|
|
const notificationStore = useNotificationStore()
|
|
notificationStore.showNotification({
|
|
type: 'success',
|
|
message: 'customers.deleted_message',
|
|
})
|
|
|
|
return response
|
|
} catch (err: unknown) {
|
|
handleApiError(err)
|
|
throw err
|
|
}
|
|
}
|
|
|
|
async function deleteMultipleCustomers(): Promise<{ success: boolean }> {
|
|
try {
|
|
const response = await customerService.delete({ ids: selectedCustomers.value })
|
|
|
|
selectedCustomers.value.forEach((customerId) => {
|
|
const index = customers.value.findIndex(
|
|
(_customer) => _customer.id === customerId
|
|
)
|
|
if (index !== -1) {
|
|
customers.value.splice(index, 1)
|
|
}
|
|
})
|
|
|
|
const notificationStore = useNotificationStore()
|
|
notificationStore.showNotification({
|
|
type: 'success',
|
|
message: 'customers.deleted_message',
|
|
})
|
|
|
|
return response
|
|
} catch (err: unknown) {
|
|
handleApiError(err)
|
|
throw err
|
|
}
|
|
}
|
|
|
|
function setSelectAllState(data: boolean): void {
|
|
selectAllField.value = data
|
|
}
|
|
|
|
function selectCustomer(data: number[]): void {
|
|
selectedCustomers.value = data
|
|
selectAllField.value = selectedCustomers.value.length === customers.value.length
|
|
}
|
|
|
|
function selectAllCustomers(): void {
|
|
if (selectedCustomers.value.length === customers.value.length) {
|
|
selectedCustomers.value = []
|
|
selectAllField.value = false
|
|
} else {
|
|
selectedCustomers.value = customers.value.map((customer) => customer.id)
|
|
selectAllField.value = true
|
|
}
|
|
}
|
|
|
|
function setAddressStub(data: Record<string, unknown>): void {
|
|
if (!data.billing) {
|
|
currentCustomer.value.billing = createAddressStub()
|
|
}
|
|
if (!data.shipping) {
|
|
currentCustomer.value.shipping = createAddressStub()
|
|
}
|
|
}
|
|
|
|
return {
|
|
customers,
|
|
totalCustomers,
|
|
selectAllField,
|
|
selectedCustomers,
|
|
selectedViewCustomer,
|
|
isFetchingInitialSettings,
|
|
isFetchingViewData,
|
|
currentCustomer,
|
|
editCustomer,
|
|
isEdit,
|
|
resetCurrentCustomer,
|
|
copyAddress,
|
|
fetchCustomerInitialSettings,
|
|
fetchCustomers,
|
|
fetchViewCustomer,
|
|
fetchCustomer,
|
|
addCustomer,
|
|
updateCustomer,
|
|
deleteCustomer,
|
|
deleteMultipleCustomers,
|
|
setSelectAllState,
|
|
selectCustomer,
|
|
selectAllCustomers,
|
|
setAddressStub,
|
|
}
|
|
})
|