Admin Drop Requests Component
Overview
The AdminDropRequests component provides an administrative interface for reviewing and processing student course drop requests. This component allows academic administrators to view all drop requests in a tabular format and take appropriate actions (approve or reject).
Component Structure
The component presents a simple, structured view with: - A header section with title - Loading and error states - A table displaying all drop requests - Action buttons for pending requests
Dependencies
import React from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import newRequest from '../../utils/newRequest';
import { FaCheck, FaTimes, FaClock } from 'react-icons/fa';
Data Fetching
The component uses React Query to fetch drop request data:
const { isLoading, error, data: dropRequests = [] } = useQuery({
queryKey: ['adminDropRequests'],
queryFn: () =>
newRequest.get('/acadadmin/drop-requests').then((res) => res.data),
});
State Management
The component relies on React Query for state management, with:
- isLoading: Tracks loading state
- error: Captures any errors during data fetching
- dropRequests: Stores the request data
Mutations
The component includes a mutation for updating drop request status:
const updateRequestStatus = useMutation({
mutationFn: ({ requestId, status, remarks }) =>
newRequest.patch(`/acadadmin/drop-requests/${requestId}`, { status, remarks }),
onSuccess: () => {
queryClient.invalidateQueries(['adminDropRequests']);
},
});
Utility Functions
handleStatusUpdate
Handles the status change workflow, prompting for admin remarks:
const handleStatusUpdate = (requestId, newStatus) => {
const remarks = prompt("Enter remarks for this decision:");
if (remarks !== null) {
updateRequestStatus.mutate({ requestId, status: newStatus, remarks });
}
};
getStatusColor
Returns appropriate CSS class based on request status:
const getStatusColor = (status) => {
switch (status) {
case 'Pending': return 'text-yellow-500';
case 'Approved': return 'text-green-500';
case 'Rejected': return 'text-red-500';
default: return 'text-gray-500';
}
};
UI Components
Loading State
Displays a spinner while data is being fetched:
{isLoading ? (
<div className="text-center">
<div className="animate-spin rounded-full h-12 w-12 border-b-2 border-gray-900 mx-auto"></div>
<p className="mt-4">Loading requests...</p>
</div>
) : null}
Error State
Displays error message if data fetching fails:
{error ? (
<div className="text-red-500 text-center">
Error loading requests: {error.message}
</div>
) : null}
Drop Requests Table
Displays all drop requests in a tabular format:
<table className="min-w-full bg-white">
<thead className="bg-gray-100">
<tr>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Student</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Roll Number</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Course</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Request Date</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Status</th>
<th className="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">Actions</th>
</tr>
</thead>
<tbody className="divide-y divide-gray-200">
{/* Row mapping logic */}
</tbody>
</table>
Status Indicator
Shows the current status with appropriate icon and color:
<span className={`px-2 inline-flex text-xs leading-5 font-semibold rounded-full ${getStatusColor(request.status)}`}>
{request.status === 'Pending' ? <FaClock className="mr-1" /> :
request.status === 'Approved' ? <FaCheck className="mr-1" /> :
<FaTimes className="mr-1" />}
{request.status}
</span>
Action Buttons
Provides appropriate action buttons for pending requests:
{request.status === 'Pending' ? (
<>
<button
onClick={() => handleStatusUpdate(request._id, 'Approved')}
className="text-green-600 hover:text-green-900 mr-4"
>
Approve
</button>
<button
onClick={() => handleStatusUpdate(request._id, 'Rejected')}
className="text-red-600 hover:text-red-900"
>
Reject
</button>
</>
) : (
<span className="text-gray-500">No actions available</span>
)}
Expected Data Structure
The component expects drop request data in the following format:
[
{
_id: "requestId123",
studentName: "John Doe",
rollNo: "B20CS001",
courseId: "CS101",
courseName: "Introduction to Computer Science",
requestDate: "2025-04-10T14:30:00.000Z",
status: "Pending" | "Approved" | "Rejected",
// Other request properties
},
// More requests...
]
API Endpoints
The component interacts with two API endpoints:
GET /acadadmin/drop-requests- Fetches all drop requestsPATCH /acadadmin/drop-requests/:requestId- Updates a drop request status
Workflow
- The component loads and displays all drop requests from the system
- For pending requests, admin can choose to approve or reject
- When an action is taken, admin is prompted to enter remarks
- The status is updated and the list is refreshed automatically
- Processed requests (approved/rejected) show their status but no longer have action buttons
Error Handling
The component implements basic error handling: - Displays error messages if API requests fail - Uses default empty array for drop requests if data is undefined - Checks for null response when prompting for remarks
Styling
The component uses Tailwind CSS for styling: - Color-coded status indicators (yellow for pending, green for approved, red for rejected) - Responsive table with appropriate spacing - Clear action buttons - Loading spinner for better UX during data fetching
Accessibility
The component includes: - Semantic HTML structure with proper table markup - Visual indicators with text labels - Informative button text