fix bug
This commit is contained in:
@@ -9,28 +9,139 @@ const toNumber = (v: any): number => {
|
|||||||
return Number.isFinite(n) ? n : 0
|
return Number.isFinite(n) ? n : 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const cleanStr = (v: any) => {
|
||||||
|
if (v === null || v === undefined) return undefined
|
||||||
|
const s = String(v).trim()
|
||||||
|
return s === '' ? undefined : s
|
||||||
|
}
|
||||||
|
|
||||||
|
const cleanEmail = (v: any) => {
|
||||||
|
const s = cleanStr(v)
|
||||||
|
if (!s) return undefined
|
||||||
|
return s.replace(/\s+/g, '').replace(/\++$/g, '')
|
||||||
|
}
|
||||||
|
|
||||||
|
const parseDateToISO = (v: any) => {
|
||||||
|
const s = cleanStr(v)
|
||||||
|
if (!s) return undefined
|
||||||
|
|
||||||
|
// DD/MM/YYYY
|
||||||
|
const m = s.match(/^(\d{2})\/(\d{2})\/(\d{4})$/)
|
||||||
|
if (m) {
|
||||||
|
const dd = m[1]
|
||||||
|
const mm = m[2]
|
||||||
|
const yyyy = m[3]
|
||||||
|
const d = new Date(`${yyyy}-${mm}-${dd}T00:00:00.000Z`)
|
||||||
|
return isNaN(d.getTime()) ? undefined : d.toISOString()
|
||||||
|
}
|
||||||
|
|
||||||
|
const d = new Date(s)
|
||||||
|
return isNaN(d.getTime()) ? undefined : d.toISOString()
|
||||||
|
}
|
||||||
|
|
||||||
const normalizeEmployeeFromApi = (e: any) => {
|
const normalizeEmployeeFromApi = (e: any) => {
|
||||||
const basic = toNumber(e?.basicSalary ?? e?.baseSalary ?? e?.salary)
|
const basic = toNumber(e?.basicSalary ?? e?.baseSalary ?? e?.salary)
|
||||||
return {
|
return {
|
||||||
...e,
|
...e,
|
||||||
baseSalary: basic,
|
baseSalary: basic,
|
||||||
|
salary: basic,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const normalizeEmployeeToApi = (data: any) => {
|
const normalizeEmployeeToApi = (data: any) => {
|
||||||
const d = { ...(data || {}) }
|
const d: any = { ...(data || {}) }
|
||||||
|
|
||||||
|
if (d.department?.id && !d.departmentId) d.departmentId = d.department.id
|
||||||
|
if (d.position?.id && !d.positionId) d.positionId = d.position.id
|
||||||
|
if (d.reportingTo?.id && !d.reportingToId) d.reportingToId = d.reportingTo.id
|
||||||
|
|
||||||
if (d.baseSalary !== undefined) {
|
if (d.baseSalary !== undefined) {
|
||||||
d.basicSalary = toNumber(d.baseSalary)
|
d.basicSalary = toNumber(d.baseSalary)
|
||||||
delete d.baseSalary
|
} else if (d.salary !== undefined) {
|
||||||
}
|
|
||||||
|
|
||||||
if (d.salary !== undefined) {
|
|
||||||
d.basicSalary = toNumber(d.salary)
|
d.basicSalary = toNumber(d.salary)
|
||||||
delete d.salary
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return d
|
d.firstName = cleanStr(d.firstName)
|
||||||
|
d.lastName = cleanStr(d.lastName)
|
||||||
|
d.firstNameAr = cleanStr(d.firstNameAr)
|
||||||
|
d.lastNameAr = cleanStr(d.lastNameAr)
|
||||||
|
|
||||||
|
d.email = cleanEmail(d.email)
|
||||||
|
d.phone = cleanStr(d.phone)
|
||||||
|
d.mobile = cleanStr(d.mobile)
|
||||||
|
|
||||||
|
d.gender = cleanStr(d.gender)
|
||||||
|
d.nationality = cleanStr(d.nationality)
|
||||||
|
d.nationalId = cleanStr(d.nationalId)
|
||||||
|
d.passportNumber = cleanStr(d.passportNumber)
|
||||||
|
|
||||||
|
d.employmentType = cleanStr(d.employmentType)
|
||||||
|
d.contractType = cleanStr(d.contractType)
|
||||||
|
|
||||||
|
d.departmentId = cleanStr(d.departmentId)
|
||||||
|
d.positionId = cleanStr(d.positionId)
|
||||||
|
d.reportingToId = cleanStr(d.reportingToId)
|
||||||
|
|
||||||
|
d.currency = cleanStr(d.currency) ?? 'SAR'
|
||||||
|
d.status = cleanStr(d.status)
|
||||||
|
|
||||||
|
d.address = cleanStr(d.address)
|
||||||
|
d.city = cleanStr(d.city)
|
||||||
|
d.country = cleanStr(d.country)
|
||||||
|
|
||||||
|
d.terminationReason = cleanStr(d.terminationReason)
|
||||||
|
d.emergencyContactName = cleanStr(d.emergencyContactName)
|
||||||
|
d.emergencyContactPhone = cleanStr(d.emergencyContactPhone)
|
||||||
|
d.emergencyContactRelation = cleanStr(d.emergencyContactRelation)
|
||||||
|
|
||||||
|
d.hireDate = parseDateToISO(d.hireDate)
|
||||||
|
d.dateOfBirth = parseDateToISO(d.dateOfBirth)
|
||||||
|
d.endDate = parseDateToISO(d.endDate)
|
||||||
|
d.probationEndDate = parseDateToISO(d.probationEndDate)
|
||||||
|
d.terminationDate = parseDateToISO(d.terminationDate)
|
||||||
|
|
||||||
|
const allowed = [
|
||||||
|
'firstName',
|
||||||
|
'lastName',
|
||||||
|
'firstNameAr',
|
||||||
|
'lastNameAr',
|
||||||
|
'email',
|
||||||
|
'phone',
|
||||||
|
'mobile',
|
||||||
|
'dateOfBirth',
|
||||||
|
'gender',
|
||||||
|
'nationality',
|
||||||
|
'nationalId',
|
||||||
|
'passportNumber',
|
||||||
|
'employmentType',
|
||||||
|
'contractType',
|
||||||
|
'hireDate',
|
||||||
|
'endDate',
|
||||||
|
'probationEndDate',
|
||||||
|
'departmentId',
|
||||||
|
'positionId',
|
||||||
|
'reportingToId',
|
||||||
|
'basicSalary',
|
||||||
|
'currency',
|
||||||
|
'status',
|
||||||
|
'terminationDate',
|
||||||
|
'terminationReason',
|
||||||
|
'emergencyContactName',
|
||||||
|
'emergencyContactPhone',
|
||||||
|
'emergencyContactRelation',
|
||||||
|
'address',
|
||||||
|
'city',
|
||||||
|
'country',
|
||||||
|
'documents',
|
||||||
|
]
|
||||||
|
|
||||||
|
const payload: any = {}
|
||||||
|
for (const k of allowed) {
|
||||||
|
if (d[k] !== undefined) payload[k] = d[k]
|
||||||
|
}
|
||||||
|
|
||||||
|
return payload
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Employee {
|
export interface Employee {
|
||||||
@@ -60,7 +171,6 @@ export interface Employee {
|
|||||||
reportingTo?: any
|
reportingTo?: any
|
||||||
|
|
||||||
baseSalary: number
|
baseSalary: number
|
||||||
|
|
||||||
basicSalary?: any
|
basicSalary?: any
|
||||||
|
|
||||||
currency?: string
|
currency?: string
|
||||||
@@ -111,7 +221,6 @@ export interface EmployeesResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const employeesAPI = {
|
export const employeesAPI = {
|
||||||
// Get all employees with filters and pagination
|
|
||||||
getAll: async (filters: EmployeeFilters = {}): Promise<EmployeesResponse> => {
|
getAll: async (filters: EmployeeFilters = {}): Promise<EmployeesResponse> => {
|
||||||
const params = new URLSearchParams()
|
const params = new URLSearchParams()
|
||||||
if (filters.search) params.append('search', filters.search)
|
if (filters.search) params.append('search', filters.search)
|
||||||
@@ -135,33 +244,28 @@ export const employeesAPI = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// Get single employee by ID
|
|
||||||
getById: async (id: string): Promise<Employee> => {
|
getById: async (id: string): Promise<Employee> => {
|
||||||
const response = await api.get(`/hr/employees/${id}`)
|
const response = await api.get(`/hr/employees/${id}`)
|
||||||
return normalizeEmployeeFromApi(response.data.data)
|
return normalizeEmployeeFromApi(response.data.data)
|
||||||
},
|
},
|
||||||
|
|
||||||
// Create new employee
|
|
||||||
create: async (data: CreateEmployeeData): Promise<Employee> => {
|
create: async (data: CreateEmployeeData): Promise<Employee> => {
|
||||||
const payload = normalizeEmployeeToApi(data)
|
const payload = normalizeEmployeeToApi(data)
|
||||||
const response = await api.post('/hr/employees', payload)
|
const response = await api.post('/hr/employees', payload)
|
||||||
return normalizeEmployeeFromApi(response.data.data)
|
return normalizeEmployeeFromApi(response.data.data)
|
||||||
},
|
},
|
||||||
|
|
||||||
// Update existing employee
|
|
||||||
update: async (id: string, data: UpdateEmployeeData): Promise<Employee> => {
|
update: async (id: string, data: UpdateEmployeeData): Promise<Employee> => {
|
||||||
const payload = normalizeEmployeeToApi(data)
|
const payload = normalizeEmployeeToApi(data)
|
||||||
const response = await api.put(`/hr/employees/${id}`, payload)
|
const response = await api.put(`/hr/employees/${id}`, payload)
|
||||||
return normalizeEmployeeFromApi(response.data.data)
|
return normalizeEmployeeFromApi(response.data.data)
|
||||||
},
|
},
|
||||||
|
|
||||||
// Delete employee
|
|
||||||
delete: async (id: string): Promise<void> => {
|
delete: async (id: string): Promise<void> => {
|
||||||
await api.delete(`/hr/employees/${id}`)
|
await api.delete(`/hr/employees/${id}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Departments API
|
|
||||||
export const departmentsAPI = {
|
export const departmentsAPI = {
|
||||||
getAll: async (): Promise<any[]> => {
|
getAll: async (): Promise<any[]> => {
|
||||||
const response = await api.get('/hr/departments')
|
const response = await api.get('/hr/departments')
|
||||||
@@ -169,7 +273,6 @@ export const departmentsAPI = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Positions API
|
|
||||||
export const positionsAPI = {
|
export const positionsAPI = {
|
||||||
getAll: async (): Promise<any[]> => {
|
getAll: async (): Promise<any[]> => {
|
||||||
const response = await api.get('/hr/positions')
|
const response = await api.get('/hr/positions')
|
||||||
|
|||||||
Reference in New Issue
Block a user