137 lines
3.8 KiB
TypeScript
137 lines
3.8 KiB
TypeScript
'use client';
|
|
|
|
import { useMemo } from 'react';
|
|
import type { ColumnDef } from '@tanstack/react-table';
|
|
import { Video } from 'lucide-react';
|
|
|
|
import { ENV_CONSTANT } from '@/constants/secrect.constant';
|
|
import { Badge } from '@/components/ui/badge';
|
|
import type { UploadListItem } from '@/types';
|
|
import { formatDate } from '@/utils/date';
|
|
|
|
import { UploadResultCell } from './UploadResultCell';
|
|
import { UploadStatusBadge } from './UploadStatusBadge';
|
|
|
|
function resolveThumbnailUrl(value: string | null) {
|
|
if (!value) return null;
|
|
if (/^https?:\/\//i.test(value)) return value;
|
|
|
|
const baseUrl = ENV_CONSTANT.BASE_API_URL?.replace(/\/$/, '');
|
|
const path = value.startsWith('/') ? value : `/${value}`;
|
|
return baseUrl ? `${baseUrl}${path}` : path;
|
|
}
|
|
|
|
export function useUploadListColumns(): ColumnDef<UploadListItem>[] {
|
|
return useMemo(
|
|
() => [
|
|
{
|
|
id: 'thumbnail',
|
|
header: 'Thumbnail',
|
|
size: 104,
|
|
minSize: 96,
|
|
enableSorting: false,
|
|
meta: { disableTruncate: true },
|
|
cell: ({ row }) => {
|
|
const thumbnail = resolveThumbnailUrl(row.original.thumbnail);
|
|
|
|
return (
|
|
<div
|
|
className="flex aspect-video w-20 items-center justify-center overflow-hidden rounded-lg border bg-muted bg-cover bg-center"
|
|
style={
|
|
thumbnail
|
|
? { backgroundImage: `url("${thumbnail}")` }
|
|
: undefined
|
|
}
|
|
role={thumbnail ? 'img' : undefined}
|
|
aria-label={thumbnail ? 'Upload thumbnail' : undefined}
|
|
>
|
|
{!thumbnail ? (
|
|
<Video className="size-5 text-muted-foreground" />
|
|
) : null}
|
|
</div>
|
|
);
|
|
},
|
|
},
|
|
{
|
|
id: 'uploaded_by',
|
|
header: 'Uploader',
|
|
size: 190,
|
|
cell: ({ row }) => (
|
|
<div>
|
|
<p className="font-medium">
|
|
{row.original.uploaded_by.name ?? '—'}
|
|
</p>
|
|
<p className="text-xs text-muted-foreground">
|
|
{row.original.uploaded_by.email ?? '—'}
|
|
</p>
|
|
</div>
|
|
),
|
|
},
|
|
{
|
|
accessorKey: 'project',
|
|
header: 'Project',
|
|
size: 165,
|
|
cell: ({ row }) => row.original.project ?? '—',
|
|
},
|
|
{
|
|
accessorKey: 'package',
|
|
header: 'Package',
|
|
size: 110,
|
|
cell: ({ row }) => row.original.package ?? '—',
|
|
},
|
|
{
|
|
accessorKey: 'segment',
|
|
header: 'Segment',
|
|
size: 140,
|
|
cell: ({ row }) => row.original.segment ?? '—',
|
|
},
|
|
{
|
|
accessorKey: 'chainage',
|
|
header: 'Chainage',
|
|
size: 155,
|
|
cell: ({ row }) => row.original.chainage ?? '—',
|
|
},
|
|
{
|
|
accessorKey: 'uploaded_at',
|
|
header: 'Uploaded At',
|
|
size: 175,
|
|
cell: ({ row }) => formatDate(row.original.uploaded_at),
|
|
},
|
|
{
|
|
accessorKey: 'is_uploaded',
|
|
header: 'Upload Status',
|
|
size: 125,
|
|
meta: { disableTruncate: true },
|
|
cell: ({ row }) =>
|
|
row.original.is_uploaded ? (
|
|
<Badge className="bg-emerald-500/15 text-emerald-600 dark:text-emerald-400">
|
|
Uploaded
|
|
</Badge>
|
|
) : (
|
|
<span className="text-muted-foreground">—</span>
|
|
),
|
|
},
|
|
{
|
|
id: 'status',
|
|
header: 'Analysis Status',
|
|
size: 145,
|
|
meta: { disableTruncate: true },
|
|
cell: ({ row }) => (
|
|
<UploadStatusBadge
|
|
status={row.original.status}
|
|
progress={row.original.progress}
|
|
/>
|
|
),
|
|
},
|
|
{
|
|
id: 'result',
|
|
header: 'Result',
|
|
size: 170,
|
|
meta: { disableTruncate: true },
|
|
cell: ({ row }) => <UploadResultCell item={row.original} />,
|
|
},
|
|
],
|
|
[],
|
|
);
|
|
}
|