(Feat): Initial Commit
This commit is contained in:
207
src/services/api.ts
Normal file
207
src/services/api.ts
Normal file
@@ -0,0 +1,207 @@
|
||||
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'http://localhost:3000/api';
|
||||
|
||||
class ApiService {
|
||||
private baseURL: string;
|
||||
|
||||
constructor(baseURL: string) {
|
||||
this.baseURL = baseURL;
|
||||
}
|
||||
|
||||
private getToken(): string | null {
|
||||
return localStorage.getItem('token');
|
||||
}
|
||||
|
||||
private async request<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
|
||||
const token = this.getToken();
|
||||
const headers: HeadersInit = {
|
||||
'Content-Type': 'application/json',
|
||||
...options.headers,
|
||||
};
|
||||
|
||||
if (token) {
|
||||
headers['Authorization'] = `Bearer ${token}`;
|
||||
}
|
||||
|
||||
const response = await fetch(`${this.baseURL}${endpoint}`, {
|
||||
...options,
|
||||
headers,
|
||||
});
|
||||
|
||||
if (response.status === 401) {
|
||||
localStorage.removeItem('token');
|
||||
localStorage.removeItem('user');
|
||||
window.location.href = '/';
|
||||
throw new Error('Unauthorized');
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
const error = await response.json().catch(() => ({ error: 'Request failed' }));
|
||||
throw new Error(error.error || 'Request failed');
|
||||
}
|
||||
|
||||
return response.json();
|
||||
}
|
||||
|
||||
// Auth
|
||||
async login(username: string, password: string) {
|
||||
return this.request<{ token: string; user: any }>('/auth/login', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ username, password }),
|
||||
});
|
||||
}
|
||||
|
||||
async getMe() {
|
||||
return this.request<any>('/auth/me');
|
||||
}
|
||||
|
||||
async changePassword(currentPassword: string, newPassword: string) {
|
||||
return this.request<{ message: string }>('/auth/change-password', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ currentPassword, newPassword }),
|
||||
});
|
||||
}
|
||||
|
||||
// Users
|
||||
async getUsers(params?: { role?: string; departmentId?: number }) {
|
||||
const query = new URLSearchParams(params as any).toString();
|
||||
return this.request<any[]>(`/users${query ? `?${query}` : ''}`);
|
||||
}
|
||||
|
||||
async getUser(id: number) {
|
||||
return this.request<any>(`/users/${id}`);
|
||||
}
|
||||
|
||||
async createUser(data: any) {
|
||||
return this.request<any>('/users', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
}
|
||||
|
||||
async updateUser(id: number, data: any) {
|
||||
return this.request<any>(`/users/${id}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
}
|
||||
|
||||
async deleteUser(id: number) {
|
||||
return this.request<{ message: string }>(`/users/${id}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
||||
// Departments
|
||||
async getDepartments() {
|
||||
return this.request<any[]>('/departments');
|
||||
}
|
||||
|
||||
async getDepartment(id: number) {
|
||||
return this.request<any>(`/departments/${id}`);
|
||||
}
|
||||
|
||||
async getSubDepartments(departmentId: number) {
|
||||
return this.request<any[]>(`/departments/${departmentId}/sub-departments`);
|
||||
}
|
||||
|
||||
async createDepartment(name: string) {
|
||||
return this.request<any>('/departments', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ name }),
|
||||
});
|
||||
}
|
||||
|
||||
// Work Allocations
|
||||
async getWorkAllocations(params?: { employeeId?: number; status?: string; departmentId?: number }) {
|
||||
const query = new URLSearchParams(params as any).toString();
|
||||
return this.request<any[]>(`/work-allocations${query ? `?${query}` : ''}`);
|
||||
}
|
||||
|
||||
async getWorkAllocation(id: number) {
|
||||
return this.request<any>(`/work-allocations/${id}`);
|
||||
}
|
||||
|
||||
async createWorkAllocation(data: any) {
|
||||
return this.request<any>('/work-allocations', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
}
|
||||
|
||||
async updateWorkAllocationStatus(id: number, status: string, completionDate?: string) {
|
||||
return this.request<any>(`/work-allocations/${id}/status`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify({ status, completionDate }),
|
||||
});
|
||||
}
|
||||
|
||||
async deleteWorkAllocation(id: number) {
|
||||
return this.request<{ message: string }>(`/work-allocations/${id}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
|
||||
// Attendance
|
||||
async getAttendance(params?: { employeeId?: number; startDate?: string; endDate?: string; status?: string }) {
|
||||
const query = new URLSearchParams(params as any).toString();
|
||||
return this.request<any[]>(`/attendance${query ? `?${query}` : ''}`);
|
||||
}
|
||||
|
||||
async checkIn(employeeId: number, workDate: string) {
|
||||
return this.request<any>('/attendance/check-in', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ employeeId, workDate }),
|
||||
});
|
||||
}
|
||||
|
||||
async checkOut(employeeId: number, workDate: string) {
|
||||
return this.request<any>('/attendance/check-out', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ employeeId, workDate }),
|
||||
});
|
||||
}
|
||||
|
||||
async getAttendanceSummary(params?: { startDate?: string; endDate?: string; departmentId?: number }) {
|
||||
const query = new URLSearchParams(params as any).toString();
|
||||
return this.request<any[]>(`/attendance/summary/stats${query ? `?${query}` : ''}`);
|
||||
}
|
||||
|
||||
// Contractor Rates
|
||||
async getContractorRates(params?: { contractorId?: number; subDepartmentId?: number }) {
|
||||
const query = params ? new URLSearchParams(params as any).toString() : '';
|
||||
return this.request<any[]>(`/contractor-rates${query ? `?${query}` : ''}`);
|
||||
}
|
||||
|
||||
async getCurrentRate(contractorId: number, subDepartmentId?: number) {
|
||||
const query = subDepartmentId ? `?subDepartmentId=${subDepartmentId}` : '';
|
||||
return this.request<any>(`/contractor-rates/contractor/${contractorId}/current${query}`);
|
||||
}
|
||||
|
||||
async setContractorRate(data: {
|
||||
contractorId: number;
|
||||
subDepartmentId?: number;
|
||||
activity?: string;
|
||||
rate: number;
|
||||
effectiveDate: string
|
||||
}) {
|
||||
return this.request<any>('/contractor-rates', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
}
|
||||
|
||||
async updateContractorRate(id: number, data: { rate?: number; activity?: string; effectiveDate?: string }) {
|
||||
return this.request<any>(`/contractor-rates/${id}`, {
|
||||
method: 'PUT',
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
}
|
||||
|
||||
async deleteContractorRate(id: number) {
|
||||
return this.request<{ message: string }>(`/contractor-rates/${id}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const api = new ApiService(API_BASE_URL);
|
||||
Reference in New Issue
Block a user