"use client" import { useMemo, useState } from "react" import { useRouter } from "next/navigation" import { useQueryClient } from "@tanstack/react-query" import { toast } from "sonner" import { useDriveList, useDriveMutations } from "@/lib/api/hooks/use-drive-queries" import { uploadFile } from "@/lib/api/upload" import { nextUntitledName } from "@/lib/drive/drive-default-name" import { buildDriveEditHref } from "@/lib/drive/drive-url" export type DriveNewKind = "document" | "spreadsheet" | "presentation" | "folder" export const DRIVE_NEW_KIND_META: Record< DriveNewKind, { ext: string; typeLabel: string; menuLabel: string } > = { document: { ext: ".docx", typeLabel: "Document", menuLabel: "Document" }, spreadsheet: { ext: ".xlsx", typeLabel: "Tableur", menuLabel: "Tableur" }, presentation: { ext: ".pptx", typeLabel: "Présentation", menuLabel: "Présentation" }, folder: { ext: "", typeLabel: "Dossier", menuLabel: "Dossier" }, } export const DRIVE_NEW_MENU_ITEM_CLASS = "gap-3 rounded-md py-2.5 pr-3 pl-3 text-[15px] focus:bg-accent/80 [&_svg]:size-5" async function importFolderTree( files: FileList, parentPath: string, createFolder: ReturnType["createFolder"] ) { const base = parentPath === "/" ? "" : parentPath const created = new Set() const ensureDir = async (dirPath: string) => { if (created.has(dirPath)) return try { await createFolder.mutateAsync(dirPath) } catch { /* dossier peut déjà exister */ } created.add(dirPath) } for (const file of Array.from(files)) { const rel = file.webkitRelativePath if (!rel) continue const segments = rel.split("/") const name = segments.pop() if (!name) continue let dirAcc = base for (const segment of segments) { dirAcc = `${dirAcc}/${segment}` await ensureDir(dirAcc) } await uploadFile(`${dirAcc}/${name}`, file) } } export function useDriveNewMenu(parentPath: string) { const router = useRouter() const queryClient = useQueryClient() const { createFolder, createFile } = useDriveMutations() const base = parentPath === "/" ? "" : parentPath const list = useDriveList(parentPath) const siblingNames = useMemo( () => (list.data?.files ?? []).map((f) => f.name), [list.data?.files] ) const [pendingKind, setPendingKind] = useState(null) const refresh = () => queryClient.invalidateQueries({ queryKey: ["drive"] }) const pendingMeta = pendingKind ? DRIVE_NEW_KIND_META[pendingKind] : null const defaultName = pendingMeta && pendingKind ? nextUntitledName(siblingNames, pendingMeta.typeLabel, pendingMeta.ext) : "" const confirmNew = async (rawName: string) => { if (!pendingKind || !pendingMeta) return const name = rawName.trim().replace(/\//g, "") if (!name) return if (pendingKind === "folder") { try { await createFolder.mutateAsync(`${base}/${name}`) toast.success("Dossier créé") await refresh() } catch { toast.error("Impossible de créer le dossier") throw new Error("folder create failed") } return } const fileName = name.endsWith(pendingMeta.ext) ? name : name + pendingMeta.ext try { const { path } = await createFile.mutateAsync({ parent_path: parentPath, name: fileName, kind: pendingKind, }) toast.success("Fichier créé") const returnTo = typeof window !== "undefined" ? window.location.pathname + window.location.search : undefined router.push(buildDriveEditHref(path, returnTo)) } catch { toast.error("Impossible de créer le fichier") throw new Error("file create failed") } } const uploadFiles = async (files: FileList | null) => { if (!files?.length) return for (const file of Array.from(files)) { try { await uploadFile(`${base}/${file.name}`, file) } catch { toast.error(`Échec : ${file.name}`) } } await refresh() toast.success("Import terminé") } const importFolder = async (files: FileList | null) => { if (!files?.length) return try { await importFolderTree(files, parentPath, createFolder) await refresh() toast.success("Dossier importé") } catch { toast.error("Impossible d'importer le dossier") } } const pickKind = (kind: DriveNewKind) => setPendingKind(kind) const closeNameDialog = () => setPendingKind(null) return { pendingKind, pendingMeta, defaultName, confirmNew, uploadFiles, importFolder, pickKind, closeNameDialog, } }