This guide shows how to integrate the frontend with the backend API.
The API client is already set up in frontend/src/services/api.js. Here's how to use it:
import { employeeAPI } from '../services/api';
export default function Employees() {
const [employees, setEmployees] = useState([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
useEffect(() => {
const fetchEmployees = async () => {
try {
setLoading(true);
const response = await employeeAPI.getAll();
setEmployees(response.data);
} catch (err) {
setError(err.response?.data?.message || 'Error fetching employees');
} finally {
setLoading(false);
}
};
fetchEmployees();
}, []);
if (loading) return <div>Loading...</div>;
if (error) return <div>Error: {error}</div>;
return (
<div>
{employees.map(emp => (
<div key={emp._id}>{emp.name}</div>
))}
</div>
);
}import { employeeAPI } from '../services/api';
const handleAddEmployee = async (formData) => {
try {
const response = await employeeAPI.create(formData);
alert('Employee created successfully!');
// Refresh employee list
fetchEmployees();
} catch (error) {
alert(error.response?.data?.message || 'Error creating employee');
}
};import { employeeAPI } from '../services/api';
const handleUpdateEmployee = async (employeeId, updatedData) => {
try {
const response = await employeeAPI.update(employeeId, updatedData);
alert('Employee updated successfully!');
// Refresh employee list
fetchEmployees();
} catch (error) {
alert(error.response?.data?.message || 'Error updating employee');
}
};import { employeeAPI } from '../services/api';
const handleDeleteEmployee = async (employeeId) => {
try {
await employeeAPI.delete(employeeId);
alert('Employee deleted successfully!');
// Refresh employee list
fetchEmployees();
} catch (error) {
alert(error.response?.data?.message || 'Error deleting employee');
}
};import { attendanceAPI } from '../services/api';
const handleMarkAttendance = async (employeeId, date, status) => {
try {
const response = await attendanceAPI.mark({
employeeId,
date,
status,
remarks: 'Optional remarks'
});
alert('Attendance marked successfully!');
// Refresh attendance list
fetchAttendance();
} catch (error) {
alert(error.response?.data?.message || 'Error marking attendance');
}
};import { attendanceAPI } from '../services/api';
const handleGetAttendanceByDate = async (date) => {
try {
const response = await attendanceAPI.getByDate(date);
setAttendanceRecords(response.data);
} catch (error) {
console.error('Error fetching attendance:', error);
}
};import { leaveAPI } from '../services/api';
const handleRequestLeave = async (leaveData) => {
try {
const response = await leaveAPI.create({
employeeId: selectedEmployeeId,
fromDate: leaveData.fromDate,
toDate: leaveData.toDate,
reason: leaveData.reason,
leaveType: leaveData.leaveType // 'Casual', 'Sick', 'Earned', 'Unpaid'
});
alert('Leave request submitted successfully!');
} catch (error) {
alert(error.response?.data?.message || 'Error submitting leave request');
}
};import { leaveAPI } from '../services/api';
const handleGetPendingLeaves = async () => {
try {
const response = await leaveAPI.getPending();
setPendingLeaves(response.data);
} catch (error) {
console.error('Error fetching pending leaves:', error);
}
};import { leaveAPI } from '../services/api';
const handleApproveLeave = async (leaveId, remarks) => {
try {
const response = await leaveAPI.update(leaveId, {
status: 'Approved',
remarks: remarks,
approvedBy: currentAdminId
});
alert('Leave approved!');
// Refresh leaves list
fetchLeaves();
} catch (error) {
alert(error.response?.data?.message || 'Error approving leave');
}
};
const handleRejectLeave = async (leaveId, remarks) => {
try {
const response = await leaveAPI.update(leaveId, {
status: 'Rejected',
remarks: remarks
});
alert('Leave rejected!');
// Refresh leaves list
fetchLeaves();
} catch (error) {
alert(error.response?.data?.message || 'Error rejecting leave');
}
};import apiClient from '../services/api';
const fetchWithErrorHandling = async (apiCall) => {
try {
const response = await apiCall();
return { success: true, data: response.data };
} catch (error) {
const errorMessage = error.response?.data?.message || error.message;
const errorCode = error.response?.status;
if (errorCode === 404) {
return { success: false, error: 'Record not found' };
} else if (errorCode === 409) {
return { success: false, error: 'Record already exists' };
} else if (errorCode === 500) {
return { success: false, error: 'Server error. Please try again.' };
}
return { success: false, error: errorMessage };
}
};import { useState, useEffect } from 'react';
import { employeeAPI } from '../services/api';
export default function EmployeeList() {
const [employees, setEmployees] = useState([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
useEffect(() => {
loadEmployees();
}, []);
const loadEmployees = async () => {
setLoading(true);
setError(null);
try {
const response = await employeeAPI.getAll();
setEmployees(response.data);
} catch (err) {
setError(err.response?.data?.message || 'Failed to load employees');
} finally {
setLoading(false);
}
};
return (
<div>
{loading && <p>Loading employees...</p>}
{error && <p className="text-red-600">Error: {error}</p>}
{!loading && !error && (
<table>
<tbody>
{employees.map(emp => (
<tr key={emp._id}>
<td>{emp.name}</td>
<td>{emp.email}</td>
<td>{emp.department}</td>
</tr>
))}
</tbody>
</table>
)}
</div>
);
}import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { employeeAPI } from '../services/api';
// Fetch employees query
const useEmployees = () => {
return useQuery({
queryKey: ['employees'],
queryFn: () => employeeAPI.getAll()
});
};
// Create employee mutation
const useCreateEmployee = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: (data) => employeeAPI.create(data),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['employees'] });
}
});
};
// Usage in component
export default function AddEmployeeForm() {
const { mutate, isLoading } = useCreateEmployee();
const handleSubmit = (formData) => {
mutate(formData, {
onSuccess: () => alert('Employee created!'),
onError: (error) => alert('Error: ' + error.message)
});
};
return (
<form onSubmit={handleSubmit}>
{/* Form fields */}
<button disabled={isLoading}>
{isLoading ? 'Creating...' : 'Add Employee'}
</button>
</form>
);
}const handleApiCall = async (apiFunction) => {
try {
const response = await apiFunction();
return { success: true, data: response.data };
} catch (error) {
if (error.response) {
// Server responded with error status
console.error('Server error:', error.response.status, error.response.data);
return { success: false, error: error.response.data.message };
} else if (error.request) {
// Request made but no response
console.error('No response from server');
return { success: false, error: 'Server is not responding' };
} else {
// Error in request setup
console.error('Error:', error.message);
return { success: false, error: error.message };
}
}
};- Create a new request
- Select method (GET, POST, PUT, DELETE)
- Enter URL:
http://localhost:5000/api/employees - For POST/PUT requests, go to Body tab:
- Select "raw" → "JSON"
- Enter JSON data
{
"name": "John Doe",
"email": "john@example.com",
"phone": "9876543210",
"department": "Engineering",
"role": "Senior Developer",
"salary": 120000,
"joiningDate": "2020-01-15",
"address": "123 Main Street"
}Note: Always ensure the backend is running on port 5000 before making API calls from the frontend.