151 lines
4.3 KiB
TypeScript
151 lines
4.3 KiB
TypeScript
"use client"
|
|
|
|
import { useMemo, type ReactNode } from "react"
|
|
import {
|
|
Clock,
|
|
Inbox,
|
|
Send,
|
|
FileEdit,
|
|
ShieldAlert,
|
|
Trash2,
|
|
} from "lucide-react"
|
|
import {
|
|
DropdownMenuItem,
|
|
DropdownMenuSeparator,
|
|
} from "@/components/ui/dropdown-menu"
|
|
import type { FolderTreeNode } from "@/lib/sidebar-nav-data"
|
|
|
|
export type MailMoveTargets = {
|
|
recents: MoveTarget[]
|
|
system: MoveTarget[]
|
|
folders: MoveTarget[]
|
|
}
|
|
|
|
export type MoveTarget = {
|
|
id: string
|
|
label: string
|
|
icon?: ReactNode
|
|
depth: number
|
|
isFolder?: boolean
|
|
isRecent?: boolean
|
|
color?: string
|
|
}
|
|
|
|
const SYSTEM_DESTINATIONS: MoveTarget[] = [
|
|
{ id: "inbox", label: "Boîte de réception", icon: <Inbox className="size-4 shrink-0 text-[#5f6368]" strokeWidth={1.5} />, depth: 0 },
|
|
{ id: "sent", label: "Messages envoyés", icon: <Send className="size-4 shrink-0 text-[#5f6368]" strokeWidth={1.5} />, depth: 0 },
|
|
{ id: "drafts", label: "Brouillons", icon: <FileEdit className="size-4 shrink-0 text-[#5f6368]" strokeWidth={1.5} />, depth: 0 },
|
|
{ id: "spam", label: "Spam", icon: <ShieldAlert className="size-4 shrink-0 text-[#5f6368]" strokeWidth={1.5} />, depth: 0 },
|
|
{ id: "trash", label: "Corbeille", icon: <Trash2 className="size-4 shrink-0 text-[#5f6368]" strokeWidth={1.5} />, depth: 0 },
|
|
]
|
|
|
|
function flattenFolderTree(
|
|
nodes: FolderTreeNode[],
|
|
depth: number = 0
|
|
): MoveTarget[] {
|
|
const out: MoveTarget[] = []
|
|
for (const n of nodes) {
|
|
out.push({
|
|
id: n.id,
|
|
label: n.label,
|
|
icon: (
|
|
<span
|
|
className={`inline-block size-3 shrink-0 rounded-sm ${n.color ?? "bg-slate-400"}`}
|
|
/>
|
|
),
|
|
depth,
|
|
isFolder: true,
|
|
color: n.color,
|
|
})
|
|
if (n.children?.length) {
|
|
out.push(...flattenFolderTree(n.children, depth + 1))
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
export function useMoveTargets({
|
|
folderTree,
|
|
recentMoveTargets,
|
|
currentFolderId,
|
|
}: {
|
|
folderTree: FolderTreeNode[]
|
|
recentMoveTargets: string[]
|
|
currentFolderId: string
|
|
}): { recents: MoveTarget[]; system: MoveTarget[]; folders: MoveTarget[] } {
|
|
return useMemo(() => {
|
|
const allSystem = SYSTEM_DESTINATIONS.filter((d) => d.id !== currentFolderId)
|
|
const allFolders = flattenFolderTree(folderTree).filter(
|
|
(f) => f.id !== currentFolderId
|
|
)
|
|
const allById = new Map<string, MoveTarget>()
|
|
for (const t of allSystem) allById.set(t.id, t)
|
|
for (const t of allFolders) allById.set(t.id, t)
|
|
|
|
const recents: MoveTarget[] = []
|
|
for (const rid of recentMoveTargets) {
|
|
if (rid === currentFolderId) continue
|
|
const target = allById.get(rid)
|
|
if (target) recents.push({ ...target, isRecent: true, depth: 0 })
|
|
}
|
|
|
|
return { recents, system: allSystem, folders: allFolders }
|
|
}, [folderTree, recentMoveTargets, currentFolderId])
|
|
}
|
|
|
|
export function MoveToDropdownItems({
|
|
targets,
|
|
onMoveTo,
|
|
}: {
|
|
targets: MailMoveTargets
|
|
onMoveTo: (targetId: string) => void
|
|
}) {
|
|
return (
|
|
<>
|
|
{targets.recents.length > 0 && (
|
|
<>
|
|
<div className="px-3 py-1.5 text-[11px] font-medium uppercase tracking-wide text-[#5f6368]">
|
|
Récents
|
|
</div>
|
|
{targets.recents.map((t) => (
|
|
<DropdownMenuItem key={`recent-${t.id}`} onSelect={() => onMoveTo(t.id)}>
|
|
<span className="flex items-center gap-2">
|
|
{t.icon}
|
|
<Clock className="size-3 shrink-0 text-[#9aa0a6]" strokeWidth={1.5} />
|
|
</span>
|
|
{t.label}
|
|
</DropdownMenuItem>
|
|
))}
|
|
<DropdownMenuSeparator />
|
|
</>
|
|
)}
|
|
{targets.system.map((t) => (
|
|
<DropdownMenuItem key={t.id} onSelect={() => onMoveTo(t.id)}>
|
|
{t.icon}
|
|
{t.label}
|
|
</DropdownMenuItem>
|
|
))}
|
|
{targets.folders.length > 0 && (
|
|
<>
|
|
<DropdownMenuSeparator />
|
|
<div className="px-3 py-1.5 text-[11px] font-medium uppercase tracking-wide text-[#5f6368]">
|
|
Dossiers
|
|
</div>
|
|
{targets.folders.map((t) => (
|
|
<DropdownMenuItem
|
|
key={t.id}
|
|
onSelect={() => onMoveTo(t.id)}
|
|
style={{ paddingLeft: `${12 + t.depth * 16}px` }}
|
|
>
|
|
{t.icon}
|
|
{t.label}
|
|
</DropdownMenuItem>
|
|
))}
|
|
</>
|
|
)}
|
|
</>
|
|
)
|
|
}
|
|
|
|
export { SYSTEM_DESTINATIONS, flattenFolderTree }
|