Skip to content

PendingRequests Component

Overview

The PendingRequests component is a React component designed to display and manage pending hostel transfer requests. It provides administrators with the ability to view request details and take action on them (approve or reject). The component handles both the display of requests and the collection of rejection reasons when an administrator chooses to reject a request.

Component Structure

Dependencies

import React from 'react';

The component only requires React as a dependency.

Props

Prop Type Description
requests Array Array of pending hostel transfer request objects
onApprove Function Handler function called when a request is approved
onReject Function Handler function called when a request is rejected with a reason
rejectionReasons Object Key-value pairs mapping request IDs to rejection reason text
handleReasonChange Function Handler function called when rejection reason text changes

Technical Implementation

Empty State Handling

The component first checks if there are any pending requests:

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 ensures a clear message is shown when there are no requests to process.

Request Items Display

When requests exist, the component maps through them to create individual request cards:

{requests.map(request => (
  <div key={request.id} className="border rounded-lg shadow-sm mb-4 p-4">
    {/* Request details */}
  </div>
))}

Each request card contains: - Student information (name and roll number) - Hostel transfer details (current hostel and reason) - Action buttons for approval or rejection - Conditional textarea for rejection reasons

Rejection Flow

The component implements a two-step rejection process:

  1. Click "Reject" button to show rejection reason textarea:

    <button
      onClick={() => handleReasonChange(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>
    

  2. Enter rejection reason and submit:

    {rejectionReasons.hasOwnProperty(request.id) && (
      <div className="mt-2">
        <textarea
          value={rejectionReasons[request.id]}
          onChange={(e) => handleReasonChange(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={() => onReject(request)}
          className="bg-red-500 shadow-sm text-white px-4 py-2 rounded hover:scale-105 transition duration-200"
        >
          Submit Rejection
        </button>
      </div>
    )}
    

This design ensures administrators provide a reason when rejecting a request.

Data Structure

Each request object in the requests array is expected to have the following properties:

Property Type Description
id String Unique identifier for the request
studentName String Name of the student making the transfer request
studentId String Roll number of the student
currentHostel String The student's current hostel assignment
reason String The student's stated reason for requesting a transfer

The rejectionReasons object maps request IDs to strings:

{
  "request123": "Room not available in requested hostel",
  "request456": "Insufficient documentation provided"
}

UI Components

Request Card

Each request is presented in a card with a consistent layout: - Rounded borders and subtle shadow - Grid layout for information display - Visual icons for each information type - Consistent spacing and alignment

Information Items

Each piece of information follows a consistent pattern:

<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 icon */}
  </div>
  <div>
    <div class="text-xs font-medium text-gray-500 uppercase tracking-wider mb-0.5">{Label}</div>
    <div class="text-sm font-semibold text-gray-800">{Value}</div>
  </div>
</div>

This design creates a consistent, scannable interface with: - Circular icon container with indigo accent colors - Two-level text hierarchy (label and value) - Consistent spacing

Action Buttons

The component provides clearly distinguished action buttons: - Green "Approve" button for positive action - Red "Reject" button for negative action - Hover animations for better interactivity - Consistent styling with the application design system

Code Explanation

Component Function

The component is structured as a function that accepts props and returns JSX:

const PendingRequests = ({ requests, onApprove, onReject, rejectionReasons, handleReasonChange }) => {
  // Component logic and rendering
};

This follows React's functional component pattern, using destructuring to access props directly.

Conditional Rendering

The component uses conditional rendering in two places:

  1. To show an empty state message when no requests exist:

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

  2. To show or hide the rejection reason textarea:

    {rejectionReasons.hasOwnProperty(request.id) && (
      <div className="mt-2">
        {/* Rejection reason textarea and submit button */}
      </div>
    )}
    

This ensures the UI shows only relevant elements based on the current state.

Event Handling

The component delegates event handling to parent components through props:

  • onApprove(request) is called when an approval button is clicked
  • handleReasonChange(request.id, '') is called when a rejection button is clicked
  • handleReasonChange(request.id, e.target.value) is called when rejection reason text changes
  • onReject(request) is called when a rejection is submitted with a reason

This pattern follows React's unidirectional data flow, where child components notify parents of actions but don't modify state directly.

Visual Design

The component uses Tailwind CSS classes for styling: - Card and container elements use rounded-lg, shadow-sm, and border for consistent styling - Text uses a hierarchy with text-xs/text-sm sizes and font-medium/font-semibold weights - Colors follow a consistent palette with indigo-600 for icons, green-500 for approve, and red-500 for reject - Spacing is consistent with space-x-3, py-2, etc. - Interactive elements have hover effects (hover:scale-105) for better user feedback