112 lines
3.2 KiB
TypeScript
112 lines
3.2 KiB
TypeScript
import { ArrowLeft, ChevronLeft, ChevronRight } from 'lucide-react';
|
|
|
|
import { Badge } from '@/components/ui/badge';
|
|
import { Button } from '@/components/ui/button';
|
|
|
|
import type { ProofStatusFilter } from './reviewTypes';
|
|
|
|
const PROOF_STATUS_FILTERS: Array<{
|
|
value: ProofStatusFilter;
|
|
label: string;
|
|
}> = [
|
|
{ value: 'all', label: 'All' },
|
|
{ value: 'pending', label: 'Pending' },
|
|
{ value: 'approved', label: 'Approved' },
|
|
{ value: 'rejected', label: 'Rejected' },
|
|
];
|
|
|
|
interface IssueReviewHeaderProps {
|
|
ticketLabel: string;
|
|
currentIndex: number;
|
|
total: number;
|
|
proofStatus: ProofStatusFilter;
|
|
onBack: () => void;
|
|
onPrevious: () => void;
|
|
onNext: () => void;
|
|
onProofStatusChange: (status: ProofStatusFilter) => void;
|
|
}
|
|
|
|
export function IssueReviewHeader({
|
|
ticketLabel,
|
|
currentIndex,
|
|
total,
|
|
proofStatus,
|
|
onBack,
|
|
onPrevious,
|
|
onNext,
|
|
onProofStatusChange,
|
|
}: IssueReviewHeaderProps) {
|
|
return (
|
|
<header className="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
|
|
<div className="flex min-w-0 items-start gap-3">
|
|
<Button
|
|
type="button"
|
|
variant="secondary"
|
|
size="icon"
|
|
onClick={onBack}
|
|
aria-label="Back to ticket"
|
|
className="shrink-0"
|
|
>
|
|
<ArrowLeft />
|
|
</Button>
|
|
<div className="min-w-0 space-y-1">
|
|
<div className="flex flex-wrap items-center gap-2">
|
|
<h1 className="truncate text-2xl font-semibold tracking-tight">
|
|
Repair Review
|
|
</h1>
|
|
<Badge variant="secondary">{ticketLabel}</Badge>
|
|
</div>
|
|
<div
|
|
className="flex max-w-full flex-nowrap items-center gap-1.5 overflow-x-auto pt-1 pb-1"
|
|
aria-label="Filter issues by repair proof status"
|
|
>
|
|
{PROOF_STATUS_FILTERS.map((filter) => {
|
|
const isActive = proofStatus === filter.value;
|
|
|
|
return (
|
|
<Button
|
|
key={filter.value}
|
|
type="button"
|
|
size="sm"
|
|
variant={isActive ? 'default' : 'outline'}
|
|
aria-pressed={isActive}
|
|
onClick={() => onProofStatusChange(filter.value)}
|
|
className="h-7 shrink-0 rounded-full px-3 text-xs"
|
|
>
|
|
{filter.label}
|
|
</Button>
|
|
);
|
|
})}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="flex items-center gap-2 self-end lg:self-auto">
|
|
<Button
|
|
type="button"
|
|
variant="outline"
|
|
size="icon"
|
|
disabled={total === 0 || currentIndex <= 0}
|
|
onClick={onPrevious}
|
|
aria-label="Previous issue"
|
|
>
|
|
<ChevronLeft />
|
|
</Button>
|
|
<div className="min-w-16 text-center text-sm font-semibold">
|
|
{total === 0 ? '0 of 0' : `${currentIndex + 1} of ${total}`}
|
|
</div>
|
|
<Button
|
|
type="button"
|
|
variant="outline"
|
|
size="icon"
|
|
disabled={total === 0 || currentIndex >= total - 1}
|
|
onClick={onNext}
|
|
aria-label="Next issue"
|
|
>
|
|
<ChevronRight />
|
|
</Button>
|
|
</div>
|
|
</header>
|
|
);
|
|
}
|