refactor: video section ui modification

This commit is contained in:
2026-06-23 10:29:09 +05:30
parent 664d80809a
commit a731fca5e0
17 changed files with 668 additions and 378 deletions

View File

@@ -0,0 +1,155 @@
'use client';
import type { ReactNode } from 'react';
import { Lock, MessageSquare } from 'lucide-react';
import { Avatar, AvatarFallback } from '@/components/ui/avatar';
import { Button } from '@/components/ui/button';
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle,
} from '@/components/ui/card';
import { cn } from '@/lib/utils';
import type { TicketDetail } from '@/types';
function getInitials(name?: string | null, email?: string | null) {
const source = name || email || '?';
return source
.split(/[\s@._-]+/)
.filter(Boolean)
.slice(0, 2)
.map((part) => part.charAt(0).toUpperCase())
.join('');
}
function getPersonLabel(person: TicketDetail['reviewer']) {
return person?.name || person?.email || 'Unknown';
}
function formatReviewDate(value: string | null | undefined) {
if (!value) return '-';
return new Intl.DateTimeFormat('en-IN', { dateStyle: 'medium' }).format(
new Date(value),
);
}
function getClosedAt(ticket: TicketDetail) {
const closedEntry = ticket.history?.find(
(item) => item.to_status === 'closed',
);
return (
closedEntry?.created_at ??
ticket.reviewer?.reviewed_at ??
ticket.timestamps.updated_at
);
}
function MetaField({
label,
value,
valueClassName,
}: {
label: string;
value: ReactNode;
valueClassName?: string;
}) {
return (
<div className="space-y-1">
<p className="text-xs font-medium tracking-wide text-muted-foreground">
{label}
</p>
<div
className={cn('text-sm font-semibold text-foreground', valueClassName)}
>
{value}
</div>
</div>
);
}
function FinalCommentsPanel({
comment,
}: {
comment: string | null | undefined;
}) {
if (!comment?.trim()) {
return (
<div className="flex min-h-28 flex-col items-center justify-center rounded-lg border border-dashed border-border bg-muted/10 px-4 py-6 text-center">
<MessageSquare className="mb-2 size-5 text-muted-foreground" />
<p className="text-sm text-muted-foreground">No comments added yet</p>
</div>
);
}
return (
<div className="rounded-lg border bg-muted/20 px-4 py-3">
<p className="text-sm leading-relaxed text-foreground">
{comment.trim()}
</p>
</div>
);
}
export function ClosedTicketAction({ ticket }: { ticket: TicketDetail }) {
const reviewer = ticket.reviewer;
const reviewedAt = reviewer?.reviewed_at ?? getClosedAt(ticket);
return (
<Card className="relative overflow-hidden border bg-card/80">
<CardHeader className="relative pb-4">
<CardTitle className="text-lg">Resolution Details</CardTitle>
<CardDescription>Review record for {ticket.id}</CardDescription>
</CardHeader>
<CardContent className="relative space-y-5">
<div className="space-y-4 rounded-xl border bg-muted/20 p-4">
<MetaField
label="Reviewed By"
value={
<div className="flex min-w-0 items-center gap-3">
<Avatar className="size-10 border border-primary/30">
<AvatarFallback className="bg-primary/15 text-sm text-primary">
{getInitials(reviewer?.name, reviewer?.email)}
</AvatarFallback>
</Avatar>
<div className="min-w-0">
<p className="truncate">{getPersonLabel(reviewer)}</p>
{reviewer?.email ? (
<p className="mt-0.5 truncate text-xs font-medium text-muted-foreground">
{reviewer.email}
</p>
) : null}
</div>
</div>
}
/>
<MetaField
label="Reviewed Date"
value={formatReviewDate(reviewedAt)}
/>
</div>
<div className="space-y-2">
<p className="text-xs font-medium tracking-wide text-muted-foreground">
Review Comment
</p>
<FinalCommentsPanel comment={reviewer?.review_comment} />
</div>
<Button
type="button"
variant="secondary"
className="w-full text-muted-foreground"
disabled
>
<Lock className="size-4" />
Ticket Finalized
</Button>
</CardContent>
</Card>
);
}