From 076ed897e7226d18bc6094043f1ac15e783d3e2e Mon Sep 17 00:00:00 2001 From: Maurice Date: Fri, 9 Oct 2026 10:16:13 +0200 Subject: [PATCH] refactor(files): share the file trash, paste and link rules between desktop and phone useFileTrash holds the trashed files with their restore, permanent delete and empty actions; the desktop trash view loads it on demand and the phone sheet while it is open. fileActions holds the clipboard file picking and the two tier link toggle (own column first, then link records) that the desktop assign dialog and the phone link sheet both ran on their own. --- .../Files/FileManagerAssignModal.tsx | 66 ++------ .../src/components/Files/fileActions.test.ts | 110 ++++++++++++ client/src/components/Files/fileActions.ts | 86 ++++++++++ client/src/components/Files/useFileManager.ts | 63 ++----- .../src/components/Files/useFileTrash.test.ts | 158 ++++++++++++++++++ client/src/components/Files/useFileTrash.ts | 92 ++++++++++ .../screens/trip/tabs/MFileLinkSheet.tsx | 59 +------ .../screens/trip/tabs/MFileTrashSheet.tsx | 49 ++---- .../mobile/screens/trip/tabs/MFilesTab.tsx | 11 +- 9 files changed, 500 insertions(+), 194 deletions(-) create mode 100644 client/src/components/Files/fileActions.test.ts create mode 100644 client/src/components/Files/fileActions.ts create mode 100644 client/src/components/Files/useFileTrash.test.ts create mode 100644 client/src/components/Files/useFileTrash.ts diff --git a/client/src/components/Files/FileManagerAssignModal.tsx b/client/src/components/Files/FileManagerAssignModal.tsx index a515288c8..0f4c1f353 100644 --- a/client/src/components/Files/FileManagerAssignModal.tsx +++ b/client/src/components/Files/FileManagerAssignModal.tsx @@ -1,10 +1,10 @@ import { useId } from 'react' import { MapPin, Ticket, Check, Paperclip } from 'lucide-react' -import { filesApi } from '../../api/client' -import type { Place, Reservation, Day } from '../../types' +import type { Place, Reservation, Day, TripFile } from '../../types' import type { FileManagerState } from './useFileManager' import { TRANSPORT_TYPES } from './FileManager.constants' import { transportIcon } from './FileManager.helpers' +import { planFileLinkToggle, runFileLinkRecordStep, type FileLinkField } from './fileActions' import { DialogHeader, DialogShell, DialogTile, NEUTRAL_TINT } from '../shared/DialogShell' import { EditorField, INPUT } from '../shared/dialogParts' @@ -12,6 +12,20 @@ export function AssignModal(S: FileManagerState) { const { files, assignFileId, setAssignFileId, t, days, assignments, places, reservations, tripId, handleAssign, refreshFiles } = S const labelId = useId() const close = () => setAssignFileId(null) + // The file's own column goes through handleAssign, which toasts a failure. + const toggleLink = async (file: TripFile, field: FileLinkField, targetId: number) => { + const step = planFileLinkToggle(file, field, targetId) + if (step.kind === 'update') { + await handleAssign(file.id, step.data) + return + } + try { + await runFileLinkRecordStep(tripId, file.id, field, targetId, step.kind) + refreshFiles() + } catch { + // A failed link record change stays quiet. + } + } return ( { const isLinked = file.place_id === p.id || (file.linked_place_ids || []).includes(p.id) return ( -