# TASK-FE-006: RFA Management UI **ID:** TASK-FE-006 **Title:** RFA List, Create, View & Workflow UI **Category:** Business Modules **Priority:** P1 (High) **Effort:** 5-7 days **Dependencies:** TASK-FE-003, TASK-FE-005, TASK-BE-007 **Assigned To:** Frontend Developer --- ## 📋 Overview Build comprehensive UI for Request for Approval (RFA) management including list with filters, create/edit forms with items, detail view, and approval workflow. --- ## 🎯 Objectives 1. Create RFA list with status filtering 2. Implement RFA creation form with multiple items 3. Build detail view showing items and approval history 4. Add approval workflow UI (Approve/Reject with comments) 5. Implement revision management 6. Add response tracking --- ## ✅ Acceptance Criteria - [ ] List displays RFAs with pagination and filters - [ ] Create form allows adding multiple RFA items - [ ] Detail view shows items, attachments, and workflow history - [ ] Approve/Reject dialog with comments functional - [ ] Revision history visible - [ ] Response tracking works (Approved/Rejected/Approved with Comments) --- ## 🔧 Implementation Steps ### Step 1: RFA List Page ```typescript // File: src/app/(dashboard)/rfas/page.tsx import { RFAList } from '@/components/rfas/list'; import { RFAFilters } from '@/components/rfas/filters'; import { Button } from '@/components/ui/button'; import Link from 'next/link'; import { Plus } from 'lucide-react'; export default async function RFAsPage({ searchParams, }: { searchParams: { page?: string; status?: string }; }) { return (

RFAs (Request for Approval)

Manage approval requests and submissions

); } ``` ### Step 2: RFA Form with Items ```typescript // File: src/components/rfas/form.tsx 'use client'; import { useForm, useFieldArray } from 'react-hook-form'; import { zodResolver } from '@hookform/resolvers/zod'; import { z } from 'zod'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Card } from '@/components/ui/card'; import { Plus, Trash2 } from 'lucide-react'; const rfaItemSchema = z.object({ item_no: z.string(), description: z.string().min(5), quantity: z.number().min(0), unit: z.string(), drawing_reference: z.string().optional(), }); const rfaSchema = z.object({ subject: z.string().min(5), description: z.string().optional(), contract_id: z.number(), discipline_id: z.number(), items: z.array(rfaItemSchema).min(1, 'At least one item required'), }); type RFAFormData = z.infer; export function RFAForm() { const { register, control, handleSubmit, formState: { errors }, } = useForm({ resolver: zodResolver(rfaSchema), defaultValues: { items: [{ item_no: '1', description: '', quantity: 0, unit: '' }], }, }); const { fields, append, remove } = useFieldArray({ control, name: 'items', }); const onSubmit = async (data: RFAFormData) => { console.log(data); // Submit to API }; return (
{/* Basic Info */}

RFA Information

{errors.subject && (

{errors.subject.message}

)}
{/* RFA Items */}

RFA Items

{fields.map((field, index) => (

Item #{index + 1}

{fields.length > 1 && ( )}
))}
{errors.items?.root && (

{errors.items.root.message}

)}
{/* Actions */}
); } ``` ### Step 3: RFA Detail with Approval Actions ```typescript // File: src/components/rfas/detail.tsx 'use client'; import { useState } from 'react'; import { Card } from '@/components/ui/card'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { Textarea } from '@/components/ui/textarea'; import { Dialog, DialogContent, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import { CheckCircle, XCircle } from 'lucide-react'; export function RFADetail({ data }: { data: any }) { const [approvalDialog, setApprovalDialog] = useState< 'approve' | 'reject' | null >(null); const [comments, setComments] = useState(''); const handleApproval = async (action: 'approve' | 'reject') => { // Call API console.log({ action, comments }); setApprovalDialog(null); }; return (
{/* Header */}

{data.subject}

{data.status} RFA No: {data.rfa_number}
{data.status === 'PENDING' && (
)}
{/* RFA Items */}

RFA Items

{data.items?.map((item: any) => ( ))}
Item No. Description Quantity Unit Status
{item.item_no} {item.description} {item.quantity} {item.unit} {item.status}
{/* Approval Dialog */} setApprovalDialog(null)} > {approvalDialog === 'approve' ? 'Approve RFA' : 'Reject RFA'}