import { useState } from 'react' import type { ColumnDef } from '@tanstack/react-table' import { Blend, FileText, HelpCircle, ImageIcon, Maximize2, Move, Paintbrush, RefreshCw, Scissors, Shuffle, Upload, UserRound, Video, WandSparkles, ZoomIn, type LucideIcon, } from 'lucide-react' import { useTranslation } from 'react-i18next' import { formatTimestampToDate } from '@/lib/format' import { DataTableColumnHeader } from '@/components/data-table' import { StatusBadge } from '@/components/status-badge' import { MJ_TASK_TYPES } from '../../constants' import { mjTaskTypeMapper, mjStatusMapper, mjSubmitResultMapper, } from '../../lib/mappers' import type { MidjourneyLog } from '../../types' import { ImageDialog } from '../dialogs/image-dialog' import { PromptDialog } from '../dialogs/prompt-dialog' import { createDurationColumn, createChannelColumn, createProgressColumn, createFailReasonColumn, } from './column-helpers' const drawingTypeIconMap: Record = { [MJ_TASK_TYPES.IMAGINE]: ImageIcon, [MJ_TASK_TYPES.UPSCALE]: Maximize2, [MJ_TASK_TYPES.VIDEO]: Video, [MJ_TASK_TYPES.EDITS]: Paintbrush, [MJ_TASK_TYPES.VARIATION]: Shuffle, [MJ_TASK_TYPES.HIGH_VARIATION]: Shuffle, [MJ_TASK_TYPES.LOW_VARIATION]: Shuffle, [MJ_TASK_TYPES.PAN]: Move, [MJ_TASK_TYPES.DESCRIBE]: FileText, [MJ_TASK_TYPES.BLEND]: Blend, [MJ_TASK_TYPES.UPLOAD]: Upload, [MJ_TASK_TYPES.SHORTEN]: Scissors, [MJ_TASK_TYPES.REROLL]: RefreshCw, [MJ_TASK_TYPES.INPAINT]: WandSparkles, [MJ_TASK_TYPES.SWAP_FACE]: UserRound, [MJ_TASK_TYPES.ZOOM]: ZoomIn, [MJ_TASK_TYPES.CUSTOM_ZOOM]: ZoomIn, } function getDrawingTypeIcon(action: string): LucideIcon { return drawingTypeIconMap[action] ?? HelpCircle } export function useDrawingLogsColumns( isAdmin: boolean ): ColumnDef[] { const { t } = useTranslation() const columns: ColumnDef[] = [ { accessorKey: 'submit_time', header: ({ column }) => ( ), cell: ({ row }) => { const log = row.original const submitTime = row.getValue('submit_time') as number return (
{formatTimestampToDate(submitTime)}
) }, meta: { label: t('Submit Time') }, }, ] if (isAdmin) { columns.push( createChannelColumn({ headerLabel: t('Channel') }) ) } columns.push({ accessorKey: 'action', header: ({ column }) => ( ), cell: ({ row }) => { const action = row.getValue('action') as string return ( ) }, meta: { label: t('Type') }, }) columns.push({ accessorKey: 'mj_id', header: ({ column }) => ( ), cell: ({ row }) => { const mjId = row.getValue('mj_id') as string if (!mjId) { return - } return (
) }, meta: { label: t('Task ID'), mobileTitle: true }, }) columns.push( createDurationColumn({ submitTimeKey: 'submit_time', finishTimeKey: 'finish_time', headerLabel: t('Duration'), }) ) if (isAdmin) { columns.push({ accessorKey: 'code', header: ({ column }) => ( ), cell: ({ row }) => { const code = row.getValue('code') as number return ( ) }, meta: { label: t('Submit Result') }, }) } columns.push( createProgressColumn({ headerLabel: t('Progress') }), { accessorKey: 'image_url', header: ({ column }) => ( ), cell: function ImageCell({ row }) { const log = row.original const imageUrl = row.getValue('image_url') as string const [dialogOpen, setDialogOpen] = useState(false) if (!imageUrl) { return - } return ( <> ) }, meta: { label: t('Image'), mobileHidden: true }, }, { accessorKey: 'prompt', header: ({ column }) => ( ), cell: function PromptCell({ row }) { const log = row.original const prompt = row.getValue('prompt') as string const [dialogOpen, setDialogOpen] = useState(false) if (!prompt) { return - } return ( <> ) }, meta: { label: t('Prompt'), mobileHidden: true }, size: 200, maxSize: 220, }, createFailReasonColumn({ headerLabel: t('Fail Reason'), cellTitle: t('Click to view full error message'), }) ) return columns }