Skip to content

Latest commit

 

History

History
386 lines (322 loc) · 9.16 KB

File metadata and controls

386 lines (322 loc) · 9.16 KB

API Integration Examples

This guide shows how to integrate the frontend with the backend API.

Basic Setup

The API client is already set up in frontend/src/services/api.js. Here's how to use it:

1. Fetch All Employees

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>
  );
}

2. Create New Employee

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');
  }
};

3. Update 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');
  }
};

4. Delete 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');
  }
};

5. Mark Attendance

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');
  }
};

6. Get Attendance for Specific Date

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);
  }
};

7. Request Leave

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');
  }
};

8. Get Pending Leaves

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);
  }
};

9. Approve/Reject Leave

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');
  }
};

Advanced Usage

Custom Error Handling

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 };
  }
};

Using with Loading States

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>
  );
}

Using with React Query (Recommended for Production)

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>
  );
}

Error Handling Best Practices

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 };
    }
  }
};

Testing API Endpoints

Using Postman

  1. Create a new request
  2. Select method (GET, POST, PUT, DELETE)
  3. Enter URL: http://localhost:5000/api/employees
  4. For POST/PUT requests, go to Body tab:
    • Select "raw" → "JSON"
    • Enter JSON data

Example POST Request Body

{
  "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.