733 lines
21 KiB
JavaScript
733 lines
21 KiB
JavaScript
import { defineStore } from 'pinia'
|
|
import { ref, computed } from 'vue'
|
|
import { customerRepository } from '@/services/repositories/CustomerRepository'
|
|
import { CUSTOMER_STATUS, CUSTOMER_TYPES, CUSTOMER_PRIORITY } from '@/types/customer'
|
|
|
|
export const useCustomersStore = defineStore('customers', () => {
|
|
// State
|
|
const customers = ref([])
|
|
const currentCustomer = ref(null)
|
|
const loading = ref(false)
|
|
const error = ref(null)
|
|
const searchCriteria = ref({})
|
|
const pagination = ref({
|
|
page: 0,
|
|
size: 20,
|
|
totalElements: 0,
|
|
totalPages: 0
|
|
})
|
|
const lastFetch = ref(null)
|
|
|
|
// Getters
|
|
const customersById = computed(() => {
|
|
return customers.value.reduce((acc, customer) => {
|
|
acc[customer.id] = customer
|
|
return acc
|
|
}, {})
|
|
})
|
|
|
|
const activeCustomers = computed(() => {
|
|
return customers.value.filter(customer => customer && customer.status === CUSTOMER_STATUS.ACTIVE)
|
|
})
|
|
|
|
const highPriorityCustomers = computed(() => {
|
|
return customers.value.filter(customer =>
|
|
customer &&
|
|
(customer.priority === CUSTOMER_PRIORITY.HIGH || customer.priority === CUSTOMER_PRIORITY.CRITICAL) &&
|
|
customer.status === CUSTOMER_STATUS.ACTIVE
|
|
)
|
|
})
|
|
|
|
const customersByType = computed(() => {
|
|
return Object.values(CUSTOMER_TYPES).reduce((acc, type) => {
|
|
acc[type] = customers.value.filter(customer => customer && customer.type === type)
|
|
return acc
|
|
}, {})
|
|
})
|
|
|
|
const customersByDepartment = computed(() => {
|
|
return customers.value.reduce((acc, customer) => {
|
|
if (customer && customer.department) {
|
|
if (!acc[customer.department]) {
|
|
acc[customer.department] = []
|
|
}
|
|
acc[customer.department].push(customer)
|
|
}
|
|
return acc
|
|
}, {})
|
|
})
|
|
|
|
const customersByLocation = computed(() => {
|
|
return customers.value.reduce((acc, customer) => {
|
|
if (customer && customer.location) {
|
|
if (!acc[customer.location]) {
|
|
acc[customer.location] = []
|
|
}
|
|
acc[customer.location].push(customer)
|
|
}
|
|
return acc
|
|
}, {})
|
|
})
|
|
|
|
const customerStats = computed(() => {
|
|
const total = customers.value.length
|
|
const active = customers.value.filter(c => c && c.status === CUSTOMER_STATUS.ACTIVE).length
|
|
const inactive = customers.value.filter(c => c && c.status === CUSTOMER_STATUS.INACTIVE).length
|
|
const pending = customers.value.filter(c => c && c.status === CUSTOMER_STATUS.PENDING).length
|
|
const suspended = customers.value.filter(c => c && c.status === CUSTOMER_STATUS.SUSPENDED).length
|
|
|
|
// Group by type
|
|
const byType = Object.values(CUSTOMER_TYPES).reduce((acc, type) => {
|
|
acc[type] = customers.value.filter(c => c && c.type === type).length
|
|
return acc
|
|
}, {})
|
|
|
|
// Group by priority
|
|
const byPriority = Object.values(CUSTOMER_PRIORITY).reduce((acc, priority) => {
|
|
acc[priority] = customers.value.filter(c => c && c.priority === priority).length
|
|
return acc
|
|
}, {})
|
|
|
|
// SLA levels
|
|
const slaLevels = customers.value.reduce((acc, customer) => {
|
|
if (customer && customer.slaLevel) {
|
|
acc[customer.slaLevel] = (acc[customer.slaLevel] || 0) + 1
|
|
}
|
|
return acc
|
|
}, {})
|
|
|
|
// Notification preferences
|
|
const emailNotifications = customers.value.filter(c => c && c.emailNotifications).length
|
|
const smsNotifications = customers.value.filter(c => c && c.smsNotifications).length
|
|
const selfServiceEnabled = customers.value.filter(c => c && c.allowSelfService).length
|
|
|
|
// Unique departments and locations
|
|
const departments = [...new Set(customers.value.map(c => c && c.department).filter(Boolean))]
|
|
const locations = [...new Set(customers.value.map(c => c && c.location).filter(Boolean))]
|
|
|
|
return {
|
|
total,
|
|
active,
|
|
inactive,
|
|
pending,
|
|
suspended,
|
|
byType,
|
|
byPriority,
|
|
slaLevels,
|
|
emailNotifications,
|
|
smsNotifications,
|
|
selfServiceEnabled,
|
|
departments: departments.length,
|
|
locations: locations.length
|
|
}
|
|
})
|
|
|
|
const getCustomerById = computed(() => (id) => {
|
|
return customersById.value[id] || null
|
|
})
|
|
|
|
const getCustomersByType = computed(() => (type) => {
|
|
return customersByType.value[type] || []
|
|
})
|
|
|
|
const getCustomersByDepartment = computed(() => (department) => {
|
|
return customersByDepartment.value[department] || []
|
|
})
|
|
|
|
const getCustomersByLocation = computed(() => (location) => {
|
|
return customersByLocation.value[location] || []
|
|
})
|
|
|
|
const filteredCustomers = computed(() => {
|
|
if (!searchCriteria.value || Object.keys(searchCriteria.value).length === 0) {
|
|
return customers.value
|
|
}
|
|
|
|
return customers.value.filter(customer => {
|
|
// Apply search filters
|
|
if (searchCriteria.value.search) {
|
|
const searchTerm = searchCriteria.value.search.toLowerCase()
|
|
const matchesName = customer.name.toLowerCase().includes(searchTerm)
|
|
const matchesCode = customer.code?.toLowerCase().includes(searchTerm)
|
|
const matchesContact = customer.contactPerson?.toLowerCase().includes(searchTerm)
|
|
const matchesEmail = customer.email?.toLowerCase().includes(searchTerm)
|
|
const matchesDepartment = customer.department?.toLowerCase().includes(searchTerm)
|
|
const matchesLocation = customer.location?.toLowerCase().includes(searchTerm)
|
|
|
|
if (!matchesName && !matchesCode && !matchesContact && !matchesEmail && !matchesDepartment && !matchesLocation) {
|
|
return false
|
|
}
|
|
}
|
|
|
|
if (searchCriteria.value.type && customer.type !== searchCriteria.value.type) {
|
|
return false
|
|
}
|
|
|
|
if (searchCriteria.value.status && customer.status !== searchCriteria.value.status) {
|
|
return false
|
|
}
|
|
|
|
if (searchCriteria.value.priority && customer.priority !== searchCriteria.value.priority) {
|
|
return false
|
|
}
|
|
|
|
if (searchCriteria.value.department && customer.department !== searchCriteria.value.department) {
|
|
return false
|
|
}
|
|
|
|
if (searchCriteria.value.location && customer.location !== searchCriteria.value.location) {
|
|
return false
|
|
}
|
|
|
|
if (searchCriteria.value.slaLevel && customer.slaLevel !== searchCriteria.value.slaLevel) {
|
|
return false
|
|
}
|
|
|
|
return true
|
|
})
|
|
})
|
|
|
|
// Actions
|
|
const initializeCustomers = async (force = false) => {
|
|
const cacheExpiry = 5 * 60 * 1000 // 5 minutes
|
|
const now = Date.now()
|
|
|
|
if (!force && lastFetch.value && (now - lastFetch.value) < cacheExpiry) {
|
|
return
|
|
}
|
|
|
|
loading.value = true
|
|
error.value = null
|
|
|
|
try {
|
|
const data = await customerRepository.getAll()
|
|
customers.value = data
|
|
lastFetch.value = now
|
|
} catch (err) {
|
|
error.value = err.message
|
|
console.error('Failed to initialize customers:', err)
|
|
throw err
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
const fetchCustomers = async (filters = {}) => {
|
|
loading.value = true
|
|
error.value = null
|
|
searchCriteria.value = { ...filters }
|
|
|
|
try {
|
|
const searchFilters = {
|
|
...filters,
|
|
page: filters.page || 0,
|
|
size: filters.size || 20
|
|
}
|
|
|
|
const response = await customerRepository.search(searchFilters)
|
|
|
|
if (response.content) {
|
|
// Paginated response
|
|
customers.value = response.content
|
|
pagination.value = {
|
|
page: response.number || 0,
|
|
size: response.size || 20,
|
|
totalElements: response.totalElements || 0,
|
|
totalPages: response.totalPages || 0
|
|
}
|
|
} else {
|
|
// Simple array response
|
|
customers.value = response
|
|
}
|
|
} catch (err) {
|
|
error.value = err.message
|
|
console.error('Failed to fetch customers:', err)
|
|
throw err
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
const createCustomer = async (customerData) => {
|
|
loading.value = true
|
|
error.value = null
|
|
|
|
try {
|
|
const newCustomer = await customerRepository.create(customerData)
|
|
customers.value.push(newCustomer)
|
|
return newCustomer
|
|
} catch (err) {
|
|
error.value = err.message
|
|
console.error('Failed to create customer:', err)
|
|
throw err
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
const updateCustomer = async (id, customerData) => {
|
|
loading.value = true
|
|
error.value = null
|
|
|
|
try {
|
|
const updatedCustomer = await customerRepository.update(id, customerData)
|
|
|
|
// Update in local state
|
|
const index = customers.value.findIndex(c => c.id === id)
|
|
if (index !== -1) {
|
|
customers.value[index] = updatedCustomer
|
|
}
|
|
|
|
// Update current customer if it's the one being edited
|
|
if (currentCustomer.value?.id === id) {
|
|
currentCustomer.value = updatedCustomer
|
|
}
|
|
|
|
return updatedCustomer
|
|
} catch (err) {
|
|
error.value = err.message
|
|
console.error('Failed to update customer:', err)
|
|
throw err
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
const deleteCustomer = async (id) => {
|
|
loading.value = true
|
|
error.value = null
|
|
|
|
try {
|
|
await customerRepository.delete(id)
|
|
|
|
// Remove from local state
|
|
customers.value = customers.value.filter(c => c.id !== id)
|
|
|
|
// Clear current customer if it's the one being deleted
|
|
if (currentCustomer.value?.id === id) {
|
|
currentCustomer.value = null
|
|
}
|
|
} catch (err) {
|
|
error.value = err.message
|
|
console.error('Failed to delete customer:', err)
|
|
throw err
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
const setCurrentCustomer = async (id) => {
|
|
if (!id) {
|
|
currentCustomer.value = null
|
|
return
|
|
}
|
|
|
|
// Check if customer is already in local state
|
|
const customer = getCustomerById.value(id)
|
|
if (customer) {
|
|
currentCustomer.value = customer
|
|
return customer
|
|
}
|
|
|
|
// Fetch from API
|
|
loading.value = true
|
|
error.value = null
|
|
|
|
try {
|
|
const customer = await customerRepository.getById(id)
|
|
currentCustomer.value = customer
|
|
|
|
// Add to local state if not already there
|
|
if (!customers.value.find(c => c.id === id)) {
|
|
customers.value.push(customer)
|
|
}
|
|
|
|
return customer
|
|
} catch (err) {
|
|
error.value = err.message
|
|
console.error('Failed to fetch customer:', err)
|
|
throw err
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
const updateCustomerStatus = async (id, status) => {
|
|
loading.value = true
|
|
error.value = null
|
|
|
|
try {
|
|
const updatedCustomer = await customerRepository.updateStatus(id, status)
|
|
|
|
// Update in local state
|
|
const index = customers.value.findIndex(c => c.id === id)
|
|
if (index !== -1) {
|
|
customers.value[index] = { ...customers.value[index], status }
|
|
}
|
|
|
|
return updatedCustomer
|
|
} catch (err) {
|
|
error.value = err.message
|
|
console.error('Failed to update customer status:', err)
|
|
throw err
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
const updateCustomerPriority = async (id, priority) => {
|
|
loading.value = true
|
|
error.value = null
|
|
|
|
try {
|
|
const updatedCustomer = await customerRepository.updatePriority(id, priority)
|
|
|
|
// Update in local state
|
|
const index = customers.value.findIndex(c => c.id === id)
|
|
if (index !== -1) {
|
|
customers.value[index] = { ...customers.value[index], priority }
|
|
}
|
|
|
|
return updatedCustomer
|
|
} catch (err) {
|
|
error.value = err.message
|
|
console.error('Failed to update customer priority:', err)
|
|
throw err
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
const updateNotificationSettings = async (id, settings) => {
|
|
loading.value = true
|
|
error.value = null
|
|
|
|
try {
|
|
const updatedCustomer = await customerRepository.updateNotificationSettings(id, settings)
|
|
|
|
// Update in local state
|
|
const index = customers.value.findIndex(c => c.id === id)
|
|
if (index !== -1) {
|
|
customers.value[index] = { ...customers.value[index], ...settings }
|
|
}
|
|
|
|
return updatedCustomer
|
|
} catch (err) {
|
|
error.value = err.message
|
|
console.error('Failed to update notification settings:', err)
|
|
throw err
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
const bulkUpdateCustomers = async (updates) => {
|
|
loading.value = true
|
|
error.value = null
|
|
|
|
try {
|
|
const updatedCustomers = await customerRepository.bulkUpdate(updates)
|
|
|
|
// Update local state
|
|
updatedCustomers.forEach(updatedCustomer => {
|
|
const index = customers.value.findIndex(c => c.id === updatedCustomer.id)
|
|
if (index !== -1) {
|
|
customers.value[index] = updatedCustomer
|
|
}
|
|
})
|
|
|
|
return updatedCustomers
|
|
} catch (err) {
|
|
error.value = err.message
|
|
console.error('Failed to bulk update customers:', err)
|
|
throw err
|
|
} finally {
|
|
loading.value = false
|
|
}
|
|
}
|
|
|
|
const validateCustomerCode = async (code, excludeId = null) => {
|
|
try {
|
|
const result = await customerRepository.validateCode(code, excludeId)
|
|
return result.isValid
|
|
} catch (err) {
|
|
console.error('Failed to validate customer code:', err)
|
|
return false
|
|
}
|
|
}
|
|
|
|
const getDepartments = async () => {
|
|
try {
|
|
return await customerRepository.getDepartments()
|
|
} catch (err) {
|
|
console.error('Failed to fetch departments:', err)
|
|
return []
|
|
}
|
|
}
|
|
|
|
const getLocations = async () => {
|
|
try {
|
|
return await customerRepository.getLocations()
|
|
} catch (err) {
|
|
console.error('Failed to fetch locations:', err)
|
|
return []
|
|
}
|
|
}
|
|
|
|
const refreshCustomers = async () => {
|
|
lastFetch.value = null
|
|
await initializeCustomers(true)
|
|
}
|
|
|
|
const clearError = () => {
|
|
error.value = null
|
|
}
|
|
|
|
const clearCurrentCustomer = () => {
|
|
currentCustomer.value = null
|
|
}
|
|
|
|
const clearCustomers = () => {
|
|
customers.value = []
|
|
currentCustomer.value = null
|
|
lastFetch.value = null
|
|
searchCriteria.value = {}
|
|
pagination.value = {
|
|
page: 0,
|
|
size: 20,
|
|
totalElements: 0,
|
|
totalPages: 0
|
|
}
|
|
}
|
|
|
|
const loadMockData = () => {
|
|
customers.value = [
|
|
{
|
|
id: 1,
|
|
customerCode: 'CUST-001',
|
|
name: 'ABC Corporation',
|
|
email: 'contact@abc-corp.com',
|
|
phone: '+1 (555) 123-4567',
|
|
type: CUSTOMER_TYPES.EXTERNAL,
|
|
priority: CUSTOMER_PRIORITY.HIGH,
|
|
status: CUSTOMER_STATUS.ACTIVE,
|
|
description: 'Large manufacturing company requiring 24/7 support',
|
|
serviceHours: '24x7',
|
|
sla: {
|
|
responseTime: '2h',
|
|
resolutionTime: '8h',
|
|
availability: 99.9
|
|
},
|
|
notifications: {
|
|
email: true,
|
|
sms: true,
|
|
phone: false,
|
|
portal: true
|
|
},
|
|
primaryContact: {
|
|
name: 'John Smith',
|
|
title: 'Facilities Manager',
|
|
email: 'j.smith@abc-corp.com',
|
|
phone: '+1 (555) 123-4568'
|
|
},
|
|
address: {
|
|
street: '123 Industrial Blvd',
|
|
city: 'Manufacturing City',
|
|
state: 'CA',
|
|
zipCode: '90210'
|
|
},
|
|
lastContactDate: '2024-01-15T10:30:00Z',
|
|
lastContactMethod: 'Email',
|
|
createdAt: '2023-06-15T09:00:00Z',
|
|
updatedAt: '2024-01-15T10:30:00Z'
|
|
},
|
|
{
|
|
id: 2,
|
|
customerCode: 'CUST-002',
|
|
name: 'City Health Department',
|
|
email: 'facilities@cityhealth.gov',
|
|
phone: '+1 (555) 987-6543',
|
|
type: CUSTOMER_TYPES.GOVERNMENT,
|
|
priority: CUSTOMER_PRIORITY.MEDIUM,
|
|
status: CUSTOMER_STATUS.ACTIVE,
|
|
description: 'Municipal health department with multiple facilities',
|
|
serviceHours: 'business',
|
|
sla: {
|
|
responseTime: '4h',
|
|
resolutionTime: '24h',
|
|
availability: 99.5
|
|
},
|
|
notifications: {
|
|
email: true,
|
|
sms: false,
|
|
phone: true,
|
|
portal: false
|
|
},
|
|
primaryContact: {
|
|
name: 'Sarah Johnson',
|
|
title: 'Operations Director',
|
|
email: 's.johnson@cityhealth.gov',
|
|
phone: '+1 (555) 987-6544'
|
|
},
|
|
address: {
|
|
street: '456 Government Plaza',
|
|
city: 'Capital City',
|
|
state: 'CA',
|
|
zipCode: '90211'
|
|
},
|
|
lastContactDate: '2024-01-10T14:15:00Z',
|
|
lastContactMethod: 'Phone',
|
|
createdAt: '2023-08-20T11:30:00Z',
|
|
updatedAt: '2024-01-10T14:15:00Z'
|
|
},
|
|
{
|
|
id: 3,
|
|
customerCode: 'CUST-003',
|
|
name: 'Tech Innovations LLC',
|
|
email: 'admin@techinnovations.com',
|
|
phone: '+1 (555) 456-7890',
|
|
type: CUSTOMER_TYPES.PARTNER,
|
|
priority: CUSTOMER_PRIORITY.LOW,
|
|
status: CUSTOMER_STATUS.INACTIVE,
|
|
description: 'Technology partner requiring occasional maintenance support',
|
|
serviceHours: 'extended',
|
|
sla: {
|
|
responseTime: '8h',
|
|
resolutionTime: '48h',
|
|
availability: 95.0
|
|
},
|
|
notifications: {
|
|
email: true,
|
|
sms: false,
|
|
phone: false,
|
|
portal: true
|
|
},
|
|
primaryContact: {
|
|
name: 'Mike Chen',
|
|
title: 'IT Manager',
|
|
email: 'm.chen@techinnovations.com',
|
|
phone: '+1 (555) 456-7891'
|
|
},
|
|
address: {
|
|
street: '789 Tech Park Dr',
|
|
city: 'Silicon Valley',
|
|
state: 'CA',
|
|
zipCode: '90212'
|
|
},
|
|
lastContactDate: '2023-12-05T16:45:00Z',
|
|
lastContactMethod: 'Portal',
|
|
createdAt: '2023-04-10T13:20:00Z',
|
|
updatedAt: '2023-12-05T16:45:00Z'
|
|
}
|
|
]
|
|
lastFetch.value = Date.now()
|
|
}
|
|
|
|
return {
|
|
// State
|
|
customers: computed(() => customers.value),
|
|
currentCustomer: computed(() => currentCustomer.value),
|
|
loading: computed(() => loading.value),
|
|
error: computed(() => error.value),
|
|
searchCriteria: computed(() => searchCriteria.value),
|
|
pagination: computed(() => pagination.value),
|
|
|
|
// Getters
|
|
customersById,
|
|
activeCustomers,
|
|
highPriorityCustomers,
|
|
customersByType,
|
|
customersByDepartment,
|
|
customersByLocation,
|
|
customerStats,
|
|
getCustomerById,
|
|
getCustomersByType,
|
|
getCustomersByDepartment,
|
|
getCustomersByLocation,
|
|
filteredCustomers,
|
|
|
|
// Options for dropdowns
|
|
customerTypeOptions: computed(() => {
|
|
return Object.values(CUSTOMER_TYPES).map(type => ({
|
|
label: type.charAt(0).toUpperCase() + type.slice(1),
|
|
value: type
|
|
}))
|
|
}),
|
|
|
|
priorityOptions: computed(() => {
|
|
return Object.values(CUSTOMER_PRIORITY).map(priority => ({
|
|
label: priority.charAt(0).toUpperCase() + priority.slice(1),
|
|
value: priority
|
|
}))
|
|
}),
|
|
|
|
statusOptions: computed(() => {
|
|
return Object.values(CUSTOMER_STATUS).map(status => ({
|
|
label: status.charAt(0).toUpperCase() + status.slice(1),
|
|
value: status
|
|
}))
|
|
}),
|
|
|
|
responseTimeOptions: computed(() => [
|
|
{ label: '1 Hour', value: '1h' },
|
|
{ label: '2 Hours', value: '2h' },
|
|
{ label: '4 Hours', value: '4h' },
|
|
{ label: '8 Hours', value: '8h' },
|
|
{ label: '24 Hours', value: '24h' },
|
|
{ label: '48 Hours', value: '48h' }
|
|
]),
|
|
|
|
resolutionTimeOptions: computed(() => [
|
|
{ label: '4 Hours', value: '4h' },
|
|
{ label: '8 Hours', value: '8h' },
|
|
{ label: '24 Hours', value: '24h' },
|
|
{ label: '48 Hours', value: '48h' },
|
|
{ label: '72 Hours', value: '72h' },
|
|
{ label: '1 Week', value: '1w' }
|
|
]),
|
|
|
|
serviceHoursOptions: computed(() => [
|
|
{ label: '24x7', value: '24x7' },
|
|
{ label: 'Business Hours (9AM-5PM)', value: 'business' },
|
|
{ label: 'Extended Hours (7AM-7PM)', value: 'extended' },
|
|
{ label: 'Custom', value: 'custom' }
|
|
]),
|
|
|
|
// Statistics
|
|
totalCustomers: computed(() => customers.value.length),
|
|
activeCustomersCount: computed(() => activeCustomers.value.length),
|
|
inactiveCustomersCount: computed(() => customers.value.filter(c => c && c.status === CUSTOMER_STATUS.INACTIVE).length),
|
|
highPriorityCustomersCount: computed(() => highPriorityCustomers.value.length),
|
|
averageResponseTime: computed(() => {
|
|
const responseTimes = customers.value
|
|
.map(c => c && c.sla?.responseTime)
|
|
.filter(Boolean)
|
|
.map(time => parseInt(time))
|
|
|
|
if (responseTimes.length === 0) return null
|
|
|
|
const avg = responseTimes.reduce((sum, time) => sum + time, 0) / responseTimes.length
|
|
return `${Math.round(avg)}h`
|
|
}),
|
|
|
|
// Actions
|
|
initializeCustomers,
|
|
fetchCustomers,
|
|
createCustomer,
|
|
updateCustomer,
|
|
deleteCustomer,
|
|
setCurrentCustomer,
|
|
updateCustomerStatus,
|
|
updateCustomerPriority,
|
|
updateNotificationSettings,
|
|
bulkUpdateCustomers,
|
|
validateCustomerCode,
|
|
getDepartments,
|
|
getLocations,
|
|
refreshCustomers,
|
|
clearError,
|
|
clearCurrentCustomer,
|
|
clearCustomers,
|
|
loadMockData
|
|
}
|
|
}) |