Re_Figma_Code/src/pages/MyRequests/components/RequestCard.tsx

124 lines
5.7 KiB
TypeScript

/**
* Request Card Component
* Displays a single request card in the My Requests list
*/
import { Card, CardContent } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
import { ArrowRight, User, TrendingUp, Clock, FileText } from 'lucide-react';
import { motion } from 'framer-motion';
import { MyRequest } from '../types/myRequests.types';
import { getPriorityConfig, getStatusConfig } from '../utils/configMappers';
import { formatDateDDMMYYYY } from '@/utils/dateFormatter';
interface RequestCardProps {
request: MyRequest;
index: number;
onViewRequest: (requestId: string, requestTitle?: string, status?: string) => void;
}
export function RequestCard({ request, index, onViewRequest }: RequestCardProps) {
const statusConfig = getStatusConfig(request.status);
const priorityConfig = getPriorityConfig(request.priority);
const StatusIcon = statusConfig.icon;
const PriorityIcon = priorityConfig.icon;
return (
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ delay: index * 0.1 }}
>
<Card
className="group hover:shadow-lg transition-all duration-300 cursor-pointer border border-gray-200 shadow-sm hover:shadow-md"
onClick={() => onViewRequest(request.id, request.title, request.status)}
data-testid={`request-card-${request.id}`}
>
<CardContent className="p-3 sm:p-6">
<div className="space-y-3 sm:space-y-4">
{/* Header with Title and Status Badges */}
<div className="flex items-start justify-between gap-2">
<div className="flex-1 min-w-0">
<h4
className="text-base sm:text-lg font-semibold text-gray-900 mb-2 group-hover:text-blue-600 transition-colors line-clamp-2"
data-testid="request-title"
>
{request.title}
</h4>
<div className="flex flex-wrap items-center gap-1.5 sm:gap-2 mb-2">
<Badge
variant="outline"
className={`${statusConfig.color} border font-medium text-xs shrink-0`}
data-testid="status-badge"
>
<StatusIcon className="w-3 h-3 mr-1" />
<span className="capitalize">{request.status}</span>
</Badge>
<Badge
variant="outline"
className={`${priorityConfig.color} border font-medium text-xs capitalize shrink-0`}
data-testid="priority-badge"
>
<PriorityIcon className="w-3 h-3 mr-1" />
{request.priority}
</Badge>
{request.templateType && (
<Badge
variant="secondary"
className="bg-purple-100 text-purple-700 text-xs shrink-0 hidden sm:inline-flex"
data-testid="template-badge"
>
<FileText className="w-3 h-3 mr-1" />
Template: {request.templateName}
</Badge>
)}
</div>
<p className="text-xs sm:text-sm text-gray-600 mb-2 sm:mb-3 line-clamp-2" data-testid="request-description">
{request.description}
</p>
<div className="flex flex-col sm:flex-row sm:items-center gap-1 sm:gap-4 text-xs sm:text-sm text-gray-500">
<span className="truncate" data-testid="request-id-display">
<span className="font-medium">ID:</span> {request.displayId || request.id}
</span>
<span className="truncate" data-testid="submitted-date">
<span className="font-medium">Submitted:</span>{' '}
{formatDateDDMMYYYY(request.submittedDate)}
</span>
</div>
</div>
<ArrowRight className="w-4 h-4 sm:w-5 sm:h-5 text-gray-400 group-hover:text-blue-600 transition-colors flex-shrink-0 mt-1" />
</div>
{/* Current Approver and Level Info */}
<div className="flex flex-col sm:flex-row sm:items-center sm:justify-between gap-2 sm:gap-4 pt-3 border-t border-gray-100">
<div className="flex flex-col sm:flex-row sm:items-center gap-2 sm:gap-4">
<div className="flex items-center gap-2 min-w-0">
<User className="w-3.5 h-3.5 sm:w-4 sm:h-4 text-gray-400 flex-shrink-0" />
<span className="text-xs sm:text-sm truncate" data-testid="current-approver">
<span className="text-gray-500">Current Approver:</span>{' '}
<span className="text-gray-900 font-medium">{request.currentApprover}</span>
</span>
</div>
<div className="flex items-center gap-2">
<TrendingUp className="w-3.5 h-3.5 sm:w-4 sm:h-4 text-gray-400 flex-shrink-0" />
<span className="text-xs sm:text-sm" data-testid="approval-level">
<span className="text-gray-500">Approval Level:</span>{' '}
<span className="text-gray-900 font-medium">{request.approverLevel}</span>
</span>
</div>
</div>
<div className="flex items-center gap-1.5 text-xs text-gray-500">
<Clock className="w-3.5 h-3.5 flex-shrink-0" />
<span data-testid="submitted-timestamp">
Submitted: {formatDateDDMMYYYY(request.submittedDate)}
</span>
</div>
</div>
</div>
</CardContent>
</Card>
</motion.div>
);
}