Skip to content

PendingRequests Component

Overview

The PendingRequests component is a React component responsible for displaying and managing pending hostel transfer requests within the hostel administration system. It enables administrators to view request details and take action (approve or reject) on each request.

Component Architecture

This component uses React's state management to handle the UI for reviewing pending hostel transfer requests. It receives request data and an action handler as props from its parent component and provides a user-friendly interface for administrators to process these requests.

Technical Details

Props

Prop Type Description
requests Array List of pending hostel transfer requests to display
handleAction Function Callback function to process approval/rejection actions

State Management

The component maintains local state for handling rejection reasons:

State Variable Purpose
rejectionReasons Object that stores rejection reason text for each request by ID

Component Structure

PendingRequests
├── Empty state message (when no requests exist)
└── Request cards (for each pending request)
    ├── Request details (ID, roll number, hostels, reason)
    ├── Action buttons (Approve/Reject)
    └── Rejection form (conditionally rendered)

Workflow

  1. Initialization:
  2. Component receives pending requests data via props
  3. Sets up empty rejection reasons state object

  4. User Interaction:

  5. Admin can approve a request with a single click
  6. Admin can begin rejection process by clicking "Reject"
  7. When rejection initiated, a text area appears for providing a reason
  8. Admin submits the rejection with an explanation

  9. State Updates:

  10. Local rejection reasons state is updated as admin types
  11. Parent component handles the API communication when actions are submitted

Code Explanation

Component Definition and State Setup

const PendingRequests = ({ requests, handleAction }) => {
  const [rejectionReasons, setRejectionReasons] = useState({});

  const handleLocalReasonChange = (id, value) => {
    setRejectionReasons(prev => ({ ...prev, [id]: value }));
  };

  // ...
}

The component: 1. Accepts requests array and handleAction function as props 2. Initializes local state for tracking rejection reasons using an object where keys are request IDs 3. Defines a handler function to update the rejection reason for a specific request

Empty State Handling

if (requests.length === 0) {
  return (
    <div className="card bg-base-100 shadow border border-base-200 rounded-lg text-center text-gray-500 py-4">
      No pending requests.
    </div>
  );
}

This conditional rendering displays a message when there are no pending requests to process, providing clear feedback to administrators.

Request Card Rendering

return (
  <div className='card bg-base-100 shadow border border-base-200 p-6 rounded-lg'>
    {requests.map(request => (
      <div key={request.id} className="border rounded-lg shadow-sm mb-4 p-4">
        <div class="grid grid-cols-1 sm:grid-cols-2 gap-x-6 gap-y-1">
          {/* Request information display */}
          {/* ... */}
        </div>
      </div>
    ))}
  </div>
);

The main render method: 1. Creates a container for all request cards 2. Maps through the requests array to create individual cards 3. Uses CSS Grid for responsive layout with a single column on small screens and two columns on larger screens

Information Display

Each request card displays several pieces of information, each styled consistently with an icon and descriptive label:

<div class="flex items-center space-x-3 py-2">
  <div class="flex-shrink-0 w-10 h-10 rounded-full bg-indigo-100 flex items-center justify-center border border-indigo-200 shadow-sm">
    <svg stroke="currentColor" fill="currentColor" stroke-width="0" viewBox="0 0 384 512" class="w-5 h-5 text-indigo-600" height="1em" width="1em" xmlns="http://www.w3.org/2000/svg">
      {/* Icon path */}
    </svg>
  </div>
  <div>
    <div class="text-xs font-medium text-gray-500 uppercase tracking-wider mb-0.5">Roll No</div>
    <div class="text-sm font-semibold text-gray-800">{request.rollNo}</div>
  </div>
</div>

Each information block includes: 1. A container with flex layout for positioning 2. An icon wrapper with consistent styling 3. A label and value display section with appropriate typography styles

Action Buttons

<div className='flex justify-left mt-2'>
  <button
    onClick={() => handleAction(request.id, "Approved", "", request.requestedHostel, request.rollNo)}
    className="bg-green-500 max-h-10 shadow-sm text-white px-3 py-2 rounded mr-4 hover:scale-105 transition duration-200"
  >
    Approve
  </button>
  <button
    onClick={() => handleLocalReasonChange(request.id, '')}
    className="bg-red-500 max-h-10 shadow-sm text-white px-4 py-2 rounded hover:scale-105 transition duration-200"
  >
    Reject
  </button>
</div>

The action buttons: 1. "Approve" - Directly calls the parent component's handleAction function with approval parameters 2. "Reject" - Initiates the rejection flow by setting an empty reason for the specific request ID

Rejection Form

{rejectionReasons.hasOwnProperty(request.id) && (
  <div className="mt-2">
    <textarea
      value={rejectionReasons[request.id]}
      onChange={(e) => handleLocalReasonChange(request.id, e.target.value)}
      placeholder="Enter reason for rejection"
      className="w-full shadow-sm border border-gray-300 rounded p-2 mb-2"
    />
    <button
      onClick={() => {
        const newReason = rejectionReasons[request.id];
        handleAction(request.id, "Rejected", newReason, "", request.rollNo);
      }}
      className="bg-red-500 shadow-sm text-white px-4 py-2 rounded hover:scale-105 transition duration-200"
    >
      Submit Rejection
    </button>
  </div>
)}

The rejection form: 1. Is conditionally rendered only when a rejection reason exists for the current request ID 2. Provides a textarea for entering the rejection reason 3. Updates the local state as the admin types 4. Includes a submit button that calls the parent's handleAction with the rejection status and reason

Key Design Patterns

Conditional Rendering

The component uses conditional rendering in two ways: 1. To show an empty state message when no requests exist 2. To show/hide the rejection reason form based on user actions

Controlled Components

The textarea for rejection reasons is a controlled component, with its value managed by React state.

State Lifting

The component follows the "state lifting" pattern where the main action handling is managed by the parent component, but local UI state (rejection reasons) is managed internally.

Responsive Design

The component uses responsive design principles with CSS Grid to adjust layout based on screen size.