125 lines
4.5 KiB
TypeScript
125 lines
4.5 KiB
TypeScript
/**
|
|
* Quick Actions Sidebar Component
|
|
*/
|
|
|
|
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
|
import { Button } from '@/components/ui/button';
|
|
import { Avatar, AvatarFallback } from '@/components/ui/avatar';
|
|
import { UserPlus, Eye, CheckCircle, XCircle } from 'lucide-react';
|
|
|
|
interface QuickActionsSidebarProps {
|
|
request: any;
|
|
isInitiator: boolean;
|
|
isSpectator: boolean;
|
|
currentApprovalLevel: any;
|
|
onAddApprover: () => void;
|
|
onAddSpectator: () => void;
|
|
onApprove: () => void;
|
|
onReject: () => void;
|
|
}
|
|
|
|
export function QuickActionsSidebar({
|
|
request,
|
|
isInitiator,
|
|
isSpectator,
|
|
currentApprovalLevel,
|
|
onAddApprover,
|
|
onAddSpectator,
|
|
onApprove,
|
|
onReject,
|
|
}: QuickActionsSidebarProps) {
|
|
return (
|
|
<div className="space-y-4 sm:space-y-6">
|
|
{/* Quick Actions Card - Hide entire card for spectators and closed requests */}
|
|
{!isSpectator && request.status !== 'closed' && (
|
|
<Card data-testid="quick-actions-card">
|
|
<CardHeader className="pb-2">
|
|
<CardTitle className="text-sm sm:text-base">Quick Actions</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="space-y-2">
|
|
{/* Add Approver */}
|
|
{isInitiator && request.status !== 'closed' && (
|
|
<Button
|
|
variant="outline"
|
|
className="w-full justify-start gap-2 bg-white text-gray-700 border-gray-300 hover:bg-gray-50 hover:text-gray-900 h-9 sm:h-10 text-xs sm:text-sm"
|
|
onClick={onAddApprover}
|
|
data-testid="add-approver-button"
|
|
>
|
|
<UserPlus className="w-3.5 h-3.5 sm:w-4 sm:h-4" />
|
|
Add Approver
|
|
</Button>
|
|
)}
|
|
|
|
{/* Add Spectator */}
|
|
{request.status !== 'closed' && (
|
|
<Button
|
|
variant="outline"
|
|
className="w-full justify-start gap-2 bg-white text-gray-700 border-gray-300 hover:bg-gray-50 hover:text-gray-900 h-9 sm:h-10 text-xs sm:text-sm"
|
|
onClick={onAddSpectator}
|
|
data-testid="add-spectator-button"
|
|
>
|
|
<Eye className="w-3.5 h-3.5 sm:w-4 sm:h-4" />
|
|
Add Spectator
|
|
</Button>
|
|
)}
|
|
|
|
{/* Approve/Reject Buttons */}
|
|
<div className="pt-3 sm:pt-4 space-y-2">
|
|
{currentApprovalLevel && (
|
|
<>
|
|
<Button
|
|
className="w-full bg-green-600 hover:bg-green-700 text-white h-9 sm:h-10 text-xs sm:text-sm"
|
|
onClick={onApprove}
|
|
data-testid="approve-request-button"
|
|
>
|
|
<CheckCircle className="w-3.5 h-3.5 sm:w-4 sm:h-4 mr-2" />
|
|
Approve Request
|
|
</Button>
|
|
<Button
|
|
variant="destructive"
|
|
className="w-full h-9 sm:h-10 text-xs sm:text-sm"
|
|
onClick={onReject}
|
|
data-testid="reject-request-button"
|
|
>
|
|
<XCircle className="w-3.5 h-3.5 sm:w-4 sm:h-4 mr-2" />
|
|
Reject Request
|
|
</Button>
|
|
</>
|
|
)}
|
|
</div>
|
|
</CardContent>
|
|
</Card>
|
|
)}
|
|
|
|
{/* Spectators Card */}
|
|
<Card data-testid="spectators-card">
|
|
<CardHeader className="pb-2">
|
|
<CardTitle className="text-sm sm:text-base">Spectators</CardTitle>
|
|
</CardHeader>
|
|
<CardContent className="space-y-3">
|
|
{request.spectators && request.spectators.length > 0 ? (
|
|
request.spectators.map((spectator: any, index: number) => (
|
|
<div key={index} className="flex items-center gap-3" data-testid={`spectator-${index}`}>
|
|
<Avatar className="h-8 w-8">
|
|
<AvatarFallback className="bg-blue-100 text-blue-800 text-xs font-semibold">
|
|
{spectator.avatar}
|
|
</AvatarFallback>
|
|
</Avatar>
|
|
<div className="flex-1 min-w-0">
|
|
<p className="text-sm font-medium text-gray-900">{spectator.name}</p>
|
|
<p className="text-xs text-gray-500 truncate">{spectator.role}</p>
|
|
</div>
|
|
</div>
|
|
))
|
|
) : (
|
|
<div className="py-4 text-center">
|
|
<p className="text-sm text-gray-500">No spectators added</p>
|
|
</div>
|
|
)}
|
|
</CardContent>
|
|
</Card>
|
|
</div>
|
|
);
|
|
}
|
|
|