import { useMemo, type ComponentType, type SVGAttributes } from 'react' import type { VaultEntry } from '../types' import { cn } from '@/lib/utils' import { Wrench, Flask, Target, ArrowsClockwise, Users, CalendarBlank, Tag, FileText, StackSimple, } from '@phosphor-icons/react' import { getTypeColor, getTypeLightColor } from '../utils/typeColors' import { resolveIcon } from './TypeCustomizePopover' import { relativeDate, getDisplayDate } from '../utils/noteListHelpers' const TYPE_ICON_MAP: Record>> = { Project: Wrench, Experiment: Flask, Responsibility: Target, Procedure: ArrowsClockwise, Person: Users, Event: CalendarBlank, Topic: Tag, Type: StackSimple, } // eslint-disable-next-line react-refresh/only-export-components -- utility co-located with component export function getTypeIcon(isA: string | null, customIcon?: string | null): ComponentType> { if (customIcon) return resolveIcon(customIcon) return (isA && TYPE_ICON_MAP[isA]) || FileText } const THIRTY_DAYS_SECS = 86400 * 30 function TrashDateLine({ entry }: { entry: VaultEntry }) { const { isExpired, suffix } = useMemo(() => { // eslint-disable-next-line react-hooks/purity -- Date.now() intentionally memoized on trashedAt const trashedAge = entry.trashedAt ? (Date.now() / 1000 - entry.trashedAt) : 0 const expired = trashedAge >= THIRTY_DAYS_SECS return { isExpired: expired, suffix: expired ? ' — will be permanently deleted' : '', } }, [entry.trashedAt]) const style = isExpired ? { color: 'var(--destructive)', fontWeight: 500 } as const : undefined return (
Trashed {relativeDate(entry.trashedAt)}{suffix}
) } export function NoteItem({ entry, isSelected, typeEntryMap, onClickNote }: { entry: VaultEntry isSelected: boolean typeEntryMap: Record onClickNote: (entry: VaultEntry, e: React.MouseEvent) => void }) { const te = typeEntryMap[entry.isA ?? ''] const typeColor = getTypeColor(entry.isA ?? 'Note', te?.color) const typeLightColor = getTypeLightColor(entry.isA ?? 'Note', te?.color) const TypeIcon = useMemo(() => getTypeIcon(entry.isA, te?.icon), [entry.isA, te?.icon]) return (
onClickNote(entry, e)} > {/* eslint-disable-next-line react-hooks/static-components -- icon lookup from static map, no internal state */}
{entry.title} {entry.archived && ( ARCHIVED )} {entry.trashed && ( TRASHED )}
{entry.snippet}
{entry.trashed && entry.trashedAt ? :
{relativeDate(getDisplayDate(entry))}
}
) }