import { Trash2, ExternalLink, Download, MapPin, Ticket, StickyNote, Star, RotateCcw, Pencil } from 'lucide-react'
import type { TripFile } from '../../types'
import type { FileManagerState } from './useFileManager'
import { TRANSPORT_TYPES } from './FileManager.constants'
import { getFileIcon, isImage, formatSize, formatDateWithLocale, transportIcon, triggerDownload } from './FileManager.helpers'
import { AuthedImg } from './FileManagerAuthedImg'
import { AvatarChip } from './FileManagerAvatarChip'
import { Tooltip } from '../shared/Tooltip'
import { SourceBadge } from './FileManagerSourceBadge'
import { DESKTOP_FILE_LINK_LIST_RULES, linkedFileTargets } from './fileListRules'
export function FileRow(p: FileManagerState & { file: TripFile; isTrash?: boolean }) {
const {
file, isTrash = false, places, reservations, t, locale, can, trip,
handleStar, handleRestore, handlePermanentDelete, handleDelete, openFile, setAssignFileId,
} = p
const FileIcon = getFileIcon(file.mime_type)
const linked = linkedFileTargets(file, places, reservations, TRANSPORT_TYPES, DESKTOP_FILE_LINK_LIST_RULES)
return (
{/* Icon or thumbnail */}
!isTrash && openFile(file)}
style={{
flexShrink: 0, width: 36, height: 36, borderRadius: 10, padding: 0,
background: 'var(--bg-card)', boxShadow: '0 1px 2px rgba(0,0,0,0.06)', display: 'flex', alignItems: 'center', justifyContent: 'center',
cursor: isTrash ? 'default' : 'pointer', overflow: 'hidden',
}}
>
{isImage(file.mime_type)
?
: (() => {
const ext = (file.original_name || '').split('.').pop()?.toUpperCase() || '?'
const isPdf = file.mime_type === 'application/pdf'
return (
{ext}
)
})()
}
{/* Info */}
{file.uploaded_by_name && (
)}
{!isTrash && file.starred ?
: null}
!isTrash && openFile(file)}
style={{ fontWeight: 500, fontSize: 'calc(13px * var(--fs-scale-body, 1))', color: 'var(--text-primary)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', cursor: isTrash ? 'default' : 'pointer', textAlign: 'start', minWidth: 0 }}
>
{file.original_name}
{file.description && (
{file.description}
)}
{!!file.file_size && {formatSize(file.file_size)} }
{formatDateWithLocale(file.created_at, locale)}
{linked.places.map(p => (
))}
{linked.reservations.map(({ reservation: r, transport }) => (
transport
?
:
))}
{!!file.note_id && (
)}
{/* Actions — always visible on mobile, hover on desktop */}
{isTrash ? (
<>
{can('file_delete', trip) &&
handleRestore(file.id)}> }
{can('file_delete', trip) &&
handlePermanentDelete(file.id)}> }
>
) : (
<>
handleStar(file.id)}>
{can('file_edit', trip) &&
setAssignFileId(file.id)}> }
openFile(file)}>
triggerDownload(file.url, file.original_name)}>
{can('file_delete', trip) &&
handleDelete(file.id)}> }
>
)}
)
}
const STAR_ON = 'text-[#facc15]' // theme-lint-disable: the star keeps its gold
const TONE_HOVER = { plain: 'hover:text-content', success: 'hover:text-success', danger: 'hover:text-danger', star: 'hover:text-[#facc15]' } as const // theme-lint-disable: the star keeps its gold
/** A small action at the end of a file row, named by its tooltip. */
function RowAction({ label, onClick, tone = 'plain', active = false, children }: {
label: string; onClick: () => void; tone?: keyof typeof TONE_HOVER; active?: boolean; children: React.ReactNode
}) {
return (
{children}
)
}