refactor: standardize ticket detail card and tab styling

This commit is contained in:
2026-06-29 16:47:22 +05:30
parent 3e5dbd5893
commit adff2e2c41
16 changed files with 248 additions and 210 deletions

2
next-env.d.ts vendored
View File

@@ -1,6 +1,6 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
import "./.next/types/routes.d.ts";
import "./.next/dev/types/routes.d.ts";
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.

View File

@@ -1,51 +0,0 @@
import { Component } from 'lucide-react';
import { cn } from '@/lib/utils';
import type { TicketDefectClassTicketStatus } from '@/types';
export const DEFECT_CLASS_STATUS_CONFIG: Record<
TicketDefectClassTicketStatus,
{
label: string;
iconClassName: string;
}
> = {
unassigned: {
label: 'Unassigned',
iconClassName: 'text-zinc-500',
},
assigned: {
label: 'Assigned',
iconClassName: 'text-red-500',
},
under_review: {
label: 'Under Review',
iconClassName: 'text-violet-500',
},
approved: {
label: 'Approved',
iconClassName: 'text-emerald-500',
},
rejected: {
label: 'Rejected',
iconClassName: 'text-orange-500',
},
};
export function DefectClassStatusLegend() {
return (
<div className="flex flex-wrap items-center gap-2 pt-2">
{Object.entries(DEFECT_CLASS_STATUS_CONFIG).map(([status, item]) => (
<span
key={status}
className={cn(
'inline-flex items-center gap-1.5 rounded-full border border-border bg-muted/40 px-2.5 py-1 text-xs font-medium text-muted-foreground',
)}
>
<Component className={cn('size-3', item.iconClassName)} />
{item.label}
</span>
))}
</div>
);
}

View File

@@ -4,12 +4,13 @@ import { useEffect, useMemo, useState } from 'react';
import { usePathname, useRouter, useSearchParams } from 'next/navigation';
import { Component } from 'lucide-react';
import { Card, CardContent } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { DEFECT_CLASS_STATUS_CONFIG } from '@/constants/defectClassStatus';
import { cn } from '@/lib/utils';
import { useTicketDefectClassesQuery } from '../../hooks/useTicketQueries';
import { DEFECT_CLASS_STATUS_CONFIG } from './DefectClassStatusLegend';
interface TicketDefectClassTabsProps {
ticketId: string;
@@ -56,12 +57,15 @@ export function TicketDefectClassTabs({
if (defectClassesQuery.isLoading) {
return (
<Card>
<Card className="w-full">
<CardHeader>
<div className="h-5 w-24 animate-pulse rounded bg-muted" />
</CardHeader>
<CardContent className="flex flex-col gap-2">
{Array.from({ length: 3 }).map((_, index) => (
<div
key={index}
className="h-9 w-full animate-pulse rounded-full bg-muted"
className="h-11 w-full animate-pulse rounded-lg bg-muted"
/>
))}
</CardContent>
@@ -80,27 +84,45 @@ export function TicketDefectClassTabs({
orientation="vertical"
className="w-full"
>
<Card className="w-full py-0">
<CardContent className="py-4">
<Card className="w-full">
<CardHeader>
<CardTitle className="flex items-center gap-2 text-base">
<span>Issues</span>
<Badge className="min-w-5 justify-center rounded-full px-1.5 py-0.5 text-xs tabular-nums">
{defectClasses.length}
</Badge>
</CardTitle>
</CardHeader>
<CardContent>
<TabsList className="flex h-auto w-full flex-col items-stretch gap-2 bg-transparent p-0">
{defectClasses.map((item) => (
<TabsTrigger
key={item.class_name}
value={item.class_name}
className={cn(
'group h-9 w-full flex-none justify-start gap-2 rounded-full border border-border bg-muted/50 px-3 text-sm text-muted-foreground shadow-none after:hidden data-[state=active]:bg-muted data-[state=active]:font-semibold data-[state=active]:text-foreground',
)}
>
<Component
{defectClasses.map((item) => {
const statusConfig =
DEFECT_CLASS_STATUS_CONFIG[item.assignment_status];
return (
<TabsTrigger
key={item.class_name}
value={item.class_name}
className={cn(
'size-3.5 shrink-0',
DEFECT_CLASS_STATUS_CONFIG[item.assignment_status]
.iconClassName,
'group h-auto w-full flex-none items-center justify-between! gap-2 rounded-lg border border-border bg-muted/30 px-3 py-2.5 text-sm text-muted-foreground shadow-none after:hidden',
'data-[state=active]:bg-muted data-[state=active]:text-foreground',
)}
/>
{item.display_name}
</TabsTrigger>
))}
>
<span className="min-w-0 truncate text-left font-medium">
{item.display_name}
</span>
<Badge
className={cn(
'shrink-0 gap-1.5 rounded-full border-0 px-2.5 py-1 text-xs font-medium',
statusConfig.badgeClassName,
)}
>
<Component className="size-3" />
{statusConfig.label}
</Badge>
</TabsTrigger>
);
})}
</TabsList>
</CardContent>
</Card>

View File

@@ -10,7 +10,6 @@ import { PermissionGuard } from '@/guards';
import type { TicketDetail } from '@/types';
import { TicketStatusBadge } from '../../components/TicketStatusBadge';
import { DefectClassStatusLegend } from './DefectClassStatusLegend';
export function TicketDetailHeader({ ticket }: { ticket: TicketDetail }) {
const router = useRouter();
@@ -26,7 +25,6 @@ export function TicketDetailHeader({ ticket }: { ticket: TicketDetail }) {
<TicketStatusBadge status={ticket.status} />
</div>
<p className="text-xs ">Ticket: {ticketLabel}</p>
<DefectClassStatusLegend />
</div>
<div className="flex shrink-0 items-center gap-2">

View File

@@ -1,5 +1,6 @@
'use client';
import { Card, CardContent, CardHeader } from '@/components/ui/card';
import { Skeleton } from '@/components/ui/skeleton';
function OverviewSkeletonField() {
@@ -53,50 +54,61 @@ export function TicketDetailSkeleton() {
<div className="grid gap-5 xl:grid-cols-[minmax(0,7fr)_minmax(0,3fr)]">
<div className="space-y-5">
<section className="overflow-hidden rounded-xl border bg-card">
<div className="border-b px-4 py-2.5">
<Card>
<CardHeader>
<Skeleton className="h-4 w-20" />
</div>
<div className="grid grid-cols-2 gap-x-4 gap-y-6 p-4 md:grid-cols-4">
</CardHeader>
<CardContent className="grid grid-cols-2 gap-x-4 gap-y-6 md:grid-cols-4">
{Array.from({ length: 8 }).map((_, index) => (
<OverviewSkeletonField key={index} />
))}
</div>
</section>
</CardContent>
</Card>
<section className="space-y-5">
<div className="rounded-xl border bg-card p-5">
<Skeleton className="mb-4 h-5 w-40" />
<div className="space-y-3">
<Card>
<CardHeader>
<Skeleton className="h-5 w-40" />
</CardHeader>
<CardContent className="space-y-3">
<Skeleton className="h-4 w-full" />
<Skeleton className="h-4 w-5/6" />
<Skeleton className="h-4 w-2/3" />
</div>
</div>
<Skeleton className="aspect-video w-full rounded-xl border" />
</CardContent>
</Card>
<Card>
<CardHeader>
<Skeleton className="h-5 w-44" />
</CardHeader>
<CardContent>
<Skeleton className="aspect-video w-full rounded-lg" />
</CardContent>
</Card>
</section>
<section className="rounded-xl border bg-card p-5">
<div className="mb-5 flex items-center gap-2">
<Card>
<CardHeader className="flex-row items-center">
<Skeleton className="size-5 rounded-full" />
<Skeleton className="h-5 w-56" />
</div>
<div className="pl-0.5">
</CardHeader>
<CardContent className="pl-5.5">
<TimelineSkeletonItem />
<TimelineSkeletonItem />
<TimelineSkeletonItem isLast />
</div>
</section>
</CardContent>
</Card>
</div>
<aside className="self-start rounded-xl border bg-card p-5">
<Skeleton className="mb-4 h-5 w-36" />
<div className="space-y-3">
<Card className="self-start">
<CardHeader>
<Skeleton className="h-5 w-36" />
</CardHeader>
<CardContent className="space-y-3">
<Skeleton className="h-10 w-full" />
<Skeleton className="h-10 w-full" />
<Skeleton className="h-24 w-full" />
</div>
</aside>
</CardContent>
</Card>
</div>
</main>
);

View File

@@ -2,6 +2,7 @@
import { History, MessageSquareText } from 'lucide-react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { cn } from '@/lib/utils';
import type { TicketDetail, TicketHistoryItem, TicketStatus } from '@/types';
import { formatDate } from '@/utils/date';
@@ -93,31 +94,33 @@ export function TicketHistoryCard({ ticket }: { ticket: TicketDetail }) {
const history = ticket.history ?? [];
return (
<section className="rounded-xl border bg-card p-5">
<div className="mb-5 flex items-center gap-2">
<History className="size-5 text-primary" />
<h2 className="text-base font-semibold text-foreground">
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<History className="size-5 text-primary" />
Audit & Lifecycle Timeline
</h2>
</div>
</CardTitle>
</CardHeader>
{history.length ? (
<div className={cn('pl-0.5')}>
{history.map((item, index) => (
<HistoryEntry
key={item.id}
item={item}
isLast={index === history.length - 1}
/>
))}
</div>
) : (
<div className="rounded-lg border border-dashed border-border/80 bg-muted/10 px-4 py-8 text-center">
<p className="text-sm font-medium text-muted-foreground">
No timeline entries yet
</p>
</div>
)}
</section>
<CardContent>
{history.length ? (
<div className="pl-0.5">
{history.map((item, index) => (
<HistoryEntry
key={item.id}
item={item}
isLast={index === history.length - 1}
/>
))}
</div>
) : (
<div className="rounded-lg border border-dashed border-border/80 bg-muted/10 px-4 py-8 text-center">
<p className="text-sm font-medium text-muted-foreground">
No timeline entries yet
</p>
</div>
)}
</CardContent>
</Card>
);
}

View File

@@ -1,5 +1,12 @@
'use client';
import {
Card,
CardContent,
CardFooter,
CardHeader,
CardTitle,
} from '@/components/ui/card';
import type { TicketActor, TicketDetail } from '@/types';
import { formatDate } from '@/utils/date';
@@ -78,19 +85,19 @@ export function TicketOverviewCard({ ticket }: { ticket: TicketDetail }) {
const detectionCount = ticket.ai_result?.detection_count;
return (
<section className="overflow-hidden rounded-xl border bg-card">
<div className="border-b px-4 py-2.5">
<h2 className="text-xs font-medium ">Overview</h2>
</div>
<Card>
<CardHeader>
<CardTitle>Overview</CardTitle>
</CardHeader>
<div className="grid grid-cols-2 gap-x-4 gap-y-6 p-4 md:grid-cols-4">
<CardContent className="grid grid-cols-2 gap-x-4 gap-y-6 md:grid-cols-4">
<OverviewField label="Detection Count">
<MetaValue>
{detectionCount != null ? `${detectionCount} Occurrences` : '-'}
</MetaValue>
</OverviewField>
<OverviewField label="Chainage" >
<OverviewField label="Chainage">
<MetaValue>{ticket.chainage_name}</MetaValue>
</OverviewField>
@@ -103,13 +110,13 @@ export function TicketOverviewCard({ ticket }: { ticket: TicketDetail }) {
{formatCreatedDate(ticket.timestamps.created_at)}
</MetaValue>
</OverviewField>
</div>
</CardContent>
{ticket.ai_result?.completed_at ? (
<div className="border-t px-4 py-3 text-xs text-muted-foreground">
<CardFooter className="text-xs text-muted-foreground">
AI analysis completed {formatDate(ticket.ai_result.completed_at)}
</div>
</CardFooter>
) : null}
</section>
</Card>
);
}

View File

@@ -2,6 +2,7 @@
import { ImageIcon } from 'lucide-react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import type { TicketDetail } from '@/types';
import { RepairProofImagesGrid } from './repair-report/RepairProofImagesGrid';
@@ -21,17 +22,21 @@ export function TicketRepairReportCard({ ticket }: { ticket: TicketDetail }) {
<RepairVideoComparison ticket={ticket} />
<div className="space-y-3">
<h3 className="flex items-center gap-2 text-base font-semibold">
<ImageIcon className="size-5 text-primary" />
Repair Images
</h3>
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<ImageIcon className="size-5 text-primary" />
Repair Images
</CardTitle>
</CardHeader>
<RepairProofImagesGrid
imageUrls={repair?.proof_image_urls ?? []}
submittedAt={repair?.submitted_at ?? null}
/>
</div>
<CardContent>
<RepairProofImagesGrid
imageUrls={repair?.proof_image_urls ?? []}
submittedAt={repair?.submitted_at ?? null}
/>
</CardContent>
</Card>
</section>
);
}

View File

@@ -98,13 +98,13 @@ export function ClosedTicketAction({ ticket }: { ticket: TicketDetail }) {
const reviewedAt = reviewer?.reviewed_at ?? getClosedAt(ticket);
return (
<Card className="relative overflow-hidden border bg-card/80">
<CardHeader className="relative pb-4">
<Card>
<CardHeader>
<CardTitle className="text-lg">Resolution Details</CardTitle>
<CardDescription>Review record for {ticket.id}</CardDescription>
</CardHeader>
<CardContent className="relative space-y-5">
<CardContent className="space-y-5">
<div className="space-y-4 rounded-xl border bg-muted/20 p-4">
<MetaField
label="Reviewed By"

View File

@@ -20,7 +20,7 @@ export function TicketActionCard({
}: TicketActionCardProps) {
return (
<Card>
<CardHeader className="pb-4">
<CardHeader>
<CardTitle className="flex items-center gap-2 text-base">
<Icon className={cn('size-4 text-primary', iconClassName)} />
{title}

View File

@@ -1,7 +1,8 @@
'use client';
import { FileText, MessageSquareQuote, BadgeCheck } from 'lucide-react';
import { FileText, MessageSquareQuote } from 'lucide-react';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import type { TicketDetail } from '@/types';
import {
@@ -38,67 +39,70 @@ export function RepairReportPanel({ ticket }: { ticket: TicketDetail }) {
if (!repair) {
return (
<section className="space-y-4 rounded-xl border bg-card p-4 lg:p-6">
<div className="flex items-center gap-2 border-b border-border pb-4">
<FileText className="size-5 text-primary" />
<h3 className="text-lg font-semibold">Repair Report</h3>
</div>
<EmptyPanel
icon={MessageSquareQuote}
title="No repair report submitted yet"
description="Repair details will appear here once the assigned worker submits evidence."
className="py-10"
/>
</section>
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<FileText className="size-5 text-primary" />
Repair Report
</CardTitle>
</CardHeader>
<CardContent>
<EmptyPanel
icon={MessageSquareQuote}
title="No repair report submitted yet"
description="Repair details will appear here once the assigned worker submits evidence."
className="py-10"
/>
</CardContent>
</Card>
);
}
return (
<section className="space-y-4 rounded-xl border bg-card p-4 lg:p-6">
<div className="flex flex-col gap-2 border-b border-border pb-4 sm:flex-row sm:items-center sm:justify-between">
<h3 className="flex items-center gap-2 text-lg font-semibold">
<Card>
<CardHeader className="sm:grid-cols-[1fr_auto]">
<CardTitle className="flex items-center gap-2">
<FileText className="size-5 text-primary" />
Repair Report
</h3>
</CardTitle>
{repair.submitted_at ? (
<span className="text-xs text-muted-foreground italic">
<span className="text-xs text-muted-foreground italic sm:col-start-2 sm:row-start-1">
Completed {formatRepairDate(repair.submitted_at)}
</span>
) : null}
</div>
</CardHeader>
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
<ReportField label="Technician" value={getPersonLabel(ticket.worker)} />
<ReportField
label="Submitted At"
value={
repair.submitted_at ? formatRepairDate(repair.submitted_at) : null
}
/>
</div>
<CardContent className="space-y-5">
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2">
<ReportField
label="Technician"
value={getPersonLabel(ticket.worker)}
/>
<ReportField
label="Submitted At"
value={
repair.submitted_at ? formatRepairDate(repair.submitted_at) : null
}
/>
</div>
<div className="space-y-2 pt-1">
<MetaLabel>Repair Summary</MetaLabel>
{repair.notes?.trim() ? (
<>
<div className="space-y-2">
<MetaLabel>Repair Summary</MetaLabel>
{repair.notes?.trim() ? (
<div className="rounded-lg border bg-muted/15 px-4 py-3">
<p className="text-sm leading-relaxed text-foreground/90">
{repair.notes}
</p>
</div>
{/* <div className="flex items-center gap-2 text-xs text-muted-foreground">
<BadgeCheck className="size-3.5 text-primary" />
<span>Self-certified by {getPersonLabel(ticket.worker)}</span>
</div> */}
</>
) : (
<EmptyPanel
icon={MessageSquareQuote}
title="No repair notes added yet"
className="py-6"
/>
)}
</div>
</section>
) : (
<EmptyPanel
icon={MessageSquareQuote}
title="No repair notes added yet"
className="py-6"
/>
)}
</div>
</CardContent>
</Card>
);
}

View File

@@ -3,6 +3,7 @@
import { ShieldCheck } from 'lucide-react';
import { ProtectedVideoPlayer } from '@/components/media/ProtectedVideoPlayer';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import type { TicketDetail } from '@/types';
export function RepairVideoComparison({ ticket }: { ticket: TicketDetail }) {
@@ -10,13 +11,15 @@ export function RepairVideoComparison({ ticket }: { ticket: TicketDetail }) {
const repairVideoUrl = ticket.repair?.proof_video_url ?? null;
return (
<section className="space-y-4">
<h3 className="flex items-center gap-2 text-base font-semibold">
<ShieldCheck className="size-5 text-primary" />
Repair Verification
</h3>
<Card>
<CardHeader>
<CardTitle className="flex items-center gap-2">
<ShieldCheck className="size-5 text-primary" />
Repair Verification
</CardTitle>
</CardHeader>
<div className="grid grid-cols-1 gap-4 lg:grid-cols-2">
<CardContent className="grid grid-cols-1 gap-4 lg:grid-cols-2">
<ComparisonVideoItem
tooltip={ticket.video?.name ?? 'Original inspection video'}
videoLabel="Before"
@@ -41,8 +44,8 @@ export function RepairVideoComparison({ ticket }: { ticket: TicketDetail }) {
: 'Repair video will appear here once evidence is submitted.'
}
/>
</div>
</section>
</CardContent>
</Card>
);
}

View File

@@ -33,7 +33,7 @@ export function ReportSurface({
className?: string;
}) {
return (
<div className={cn('rounded-xl border bg-card p-4', className)}>
<div className={cn('rounded-lg border bg-muted/15 p-3', className)}>
{children}
</div>
);

View File

@@ -7,7 +7,7 @@ function Card({ className, ...props }: React.ComponentProps<'div'>) {
<div
data-slot="card"
className={cn(
'flex flex-col gap-6 rounded-xl border bg-card py-6 text-card-foreground',
'flex flex-col overflow-hidden rounded-xl border bg-card text-card-foreground',
className,
)}
{...props}
@@ -20,7 +20,7 @@ function CardHeader({ className, ...props }: React.ComponentProps<'div'>) {
<div
data-slot="card-header"
className={cn(
'@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6',
'@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-2 border-b px-5 py-4 has-data-[slot=card-action]:grid-cols-[1fr_auto]',
className,
)}
{...props}
@@ -32,7 +32,7 @@ function CardTitle({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
data-slot="card-title"
className={cn('leading-none font-semibold', className)}
className={cn('text-base leading-none font-semibold', className)}
{...props}
/>
);
@@ -65,7 +65,7 @@ function CardContent({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
data-slot="card-content"
className={cn('px-6', className)}
className={cn('px-5 py-5', className)}
{...props}
/>
);
@@ -75,7 +75,7 @@ function CardFooter({ className, ...props }: React.ComponentProps<'div'>) {
return (
<div
data-slot="card-footer"
className={cn('flex items-center px-6 [.border-t]:pt-6', className)}
className={cn('flex items-center border-t px-5 py-4', className)}
{...props}
/>
);

View File

@@ -65,9 +65,9 @@ function TabsTrigger({
data-slot="tabs-trigger"
className={cn(
"relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center gap-1.5 rounded-md border border-transparent px-2 py-1 text-sm font-medium whitespace-nowrap text-foreground/60 transition-all group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start hover:text-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 focus-visible:outline-1 focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-50 group-data-[variant=default]/tabs-list:data-[state=active]:shadow-sm group-data-[variant=line]/tabs-list:data-[state=active]:shadow-none dark:text-muted-foreground dark:hover:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
"group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent dark:group-data-[variant=line]/tabs-list:data-[state=active]:border-transparent dark:group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent",
"data-[state=active]:bg-background data-[state=active]:text-foreground dark:data-[state=active]:border-input dark:data-[state=active]:bg-input/30 dark:data-[state=active]:text-foreground",
"after:absolute after:bg-foreground after:opacity-0 after:transition-opacity group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:bottom-[-5px] group-data-[orientation=horizontal]/tabs:after:h-0.5 group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:-right-1 group-data-[orientation=vertical]/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-[state=active]:after:opacity-100",
"group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-[state=active]:border-transparent group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent dark:group-data-[variant=line]/tabs-list:data-[state=active]:border-transparent dark:group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent",
"data-[state=active]:border-primary data-[state=active]:bg-background data-[state=active]:text-foreground dark:data-[state=active]:border-primary dark:data-[state=active]:bg-input/30 dark:data-[state=active]:text-foreground",
"after:absolute after:bg-foreground after:opacity-0 after:transition-opacity group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:-bottom-1.25 group-data-[orientation=horizontal]/tabs:after:h-0.5 group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:-right-1 group-data-[orientation=vertical]/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-[state=active]:after:opacity-100",
className
)}
{...props}

View File

@@ -0,0 +1,35 @@
import type { TicketDefectClassTicketStatus } from '@/types';
export const DEFECT_CLASS_STATUS_CONFIG: Record<
TicketDefectClassTicketStatus,
{
label: string;
badgeClassName: string;
}
> = {
unassigned: {
label: 'Unassigned',
badgeClassName:
'bg-zinc-500/15 text-zinc-600 dark:bg-zinc-500/20 dark:text-zinc-300',
},
assigned: {
label: 'Assigned',
badgeClassName:
'bg-red-500/15 text-red-600 dark:bg-red-500/20 dark:text-red-400',
},
under_review: {
label: 'Under Review',
badgeClassName:
'bg-violet-500/15 text-violet-600 dark:bg-violet-500/20 dark:text-violet-400',
},
approved: {
label: 'Approved',
badgeClassName:
'bg-emerald-500/15 text-emerald-600 dark:bg-emerald-500/20 dark:text-emerald-400',
},
rejected: {
label: 'Rejected',
badgeClassName:
'bg-orange-500/15 text-orange-600 dark:bg-orange-500/20 dark:text-orange-400',
},
};