revert fb8e77bb68
Local Build and Deploy / deploy (push) Successful in 1m11s

revert style: clean up code with prettier and eslint
This commit is contained in:
remco committed 2026-07-12 21:02:03 +02:00
1 parent 27de078f54
commit e85e4d74ea
378 files changed
+20710 -22428

No files matched your search

@@ -1,4 +1,4 @@
"use client";
'use client'
import {
closestCenter,
@@ -9,93 +9,105 @@ import {
PointerSensor,
useSensor,
useSensors,
} from "@dnd-kit/core";
import { arrayMove, horizontalListSortingStrategy, SortableContext, useSortable } from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities";
import { Loader2, Pencil, Plus, Power, PowerOff, Trash2 } from "lucide-react";
import { useCallback, useState } from "react";
import { toast } from "sonner";
import { deleteTreePage, reorderTreePage, toggleCatalogPage } from "@/actions/catalog";
import { CatalogIcon } from "@/components/admin/catalog-tree";
import { Button } from "@/components/ui/button";
} from '@dnd-kit/core'
import {
arrayMove,
horizontalListSortingStrategy,
SortableContext,
useSortable,
} from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
import { Loader2, Pencil, Plus, Power, PowerOff, Trash2 } from 'lucide-react'
import { useCallback, useState } from 'react'
import { toast } from 'sonner'
import { deleteTreePage, reorderTreePage, toggleCatalogPage } from '@/actions/catalog'
import { CatalogIcon } from '@/components/admin/catalog-tree'
import { Button } from '@/components/ui/button'
import {
ContextMenu,
ContextMenuContent,
ContextMenuItem,
ContextMenuSeparator,
ContextMenuTrigger,
} from "@/components/ui/context-menu";
import { Tooltip, TooltipContent, TooltipTrigger } from "@/components/ui/tooltip";
import { cn } from "@/lib/utils";
} from '@/components/ui/context-menu'
import { Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui/tooltip'
import { cn } from '@/lib/utils'
export type { RootTab } from "@/types/catalog";
export type { RootTab } from '@/types/catalog'
import type { RootTab } from "@/types/catalog";
import type { RootTab } from '@/types/catalog'
interface RootTabsProps {
tabs: RootTab[];
activeTabId: number | null;
onTabClick: (id: number) => void;
onEditTab: (id: number) => void;
onCreateRoot: () => void;
loading?: boolean;
tabs: RootTab[]
activeTabId: number | null
onTabClick: (id: number) => void
onEditTab: (id: number) => void
onCreateRoot: () => void
loading?: boolean
}
export function RootTabs({ tabs, activeTabId, onTabClick, onEditTab, onCreateRoot, loading }: RootTabsProps) {
const [activeDragId, setActiveDragId] = useState<number | null>(null);
const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 8 } }));
export function RootTabs({
tabs,
activeTabId,
onTabClick,
onEditTab,
onCreateRoot,
loading,
}: RootTabsProps) {
const [activeDragId, setActiveDragId] = useState<number | null>(null)
const sensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 8 } }))
const handleDragStart = useCallback((event: DragStartEvent) => {
setActiveDragId(event.active.id as number);
}, []);
setActiveDragId(event.active.id as number)
}, [])
const handleDragEnd = useCallback(
async (event: DragEndEvent) => {
const { active, over } = event;
setActiveDragId(null);
if (!over || active.id === over.id) return;
const { active, over } = event
setActiveDragId(null)
if (!over || active.id === over.id) return
const oldIndex = tabs.findIndex((t) => t.id === active.id);
const newIndex = tabs.findIndex((t) => t.id === over.id);
if (oldIndex === -1 || newIndex === -1) return;
const oldIndex = tabs.findIndex((t) => t.id === active.id)
const newIndex = tabs.findIndex((t) => t.id === over.id)
if (oldIndex === -1 || newIndex === -1) return
const newOrder = arrayMove(tabs, oldIndex, newIndex);
const newOrder = arrayMove(tabs, oldIndex, newIndex)
// Batch reorder
try {
const results = await Promise.allSettled(
newOrder.map((tab, idx) => reorderTreePage({ pageId: tab.id, newOrderNum: idx + 1 })),
);
const failed = results.filter((r) => r.status === "rejected").length;
if (failed) toast.error(`${failed} reorder(s) failed`);
else toast.success("Tabs reordered");
)
const failed = results.filter((r) => r.status === 'rejected').length
if (failed) toast.error(`${failed} reorder(s) failed`)
else toast.success('Tabs reordered')
} catch {
toast.error("Failed to reorder tabs");
toast.error('Failed to reorder tabs')
}
},
[tabs],
);
)
const handleToggle = async (tab: RootTab) => {
try {
await toggleCatalogPage({ id: tab.id, action: "toggleEnabled" });
toast.success(`${tab.caption} ${tab.enabled === "1" ? "disabled" : "enabled"}`);
await toggleCatalogPage({ id: tab.id, action: 'toggleEnabled' })
toast.success(`${tab.caption} ${tab.enabled === '1' ? 'disabled' : 'enabled'}`)
} catch {
toast.error("Failed to toggle");
toast.error('Failed to toggle')
}
};
}
const handleDelete = async (tab: RootTab) => {
if (!confirm(`Delete root page "${tab.caption}"? Children will be reparented.`)) return;
if (!confirm(`Delete root page "${tab.caption}"? Children will be reparented.`)) return
try {
await deleteTreePage({ pageId: tab.id, mode: "reparent" });
toast.success(`"${tab.caption}" deleted`);
await deleteTreePage({ pageId: tab.id, mode: 'reparent' })
toast.success(`"${tab.caption}" deleted`)
} catch {
toast.error("Failed to delete");
toast.error('Failed to delete')
}
};
}
const draggedTab = activeDragId ? tabs.find((t) => t.id === activeDragId) : null;
const draggedTab = activeDragId ? tabs.find((t) => t.id === activeDragId) : null
return (
<div className="flex items-center gap-1 border-b bg-muted/30 px-2 py-1.5 overflow-x-auto shrink-0">
@@ -120,12 +132,19 @@ export function RootTabs({ tabs, activeTabId, onTabClick, onEditTab, onCreateRoo
))}
</SortableContext>
<DragOverlay>
{draggedTab && <TabButton tab={draggedTab} isActive={activeTabId === draggedTab.id} isOverlay />}
{draggedTab && (
<TabButton tab={draggedTab} isActive={activeTabId === draggedTab.id} isOverlay />
)}
</DragOverlay>
</DndContext>
<Tooltip>
<TooltipTrigger asChild>
<Button variant="ghost" size="icon" className="h-7 w-7 shrink-0 ml-1" onClick={onCreateRoot}>
<Button
variant="ghost"
size="icon"
className="h-7 w-7 shrink-0 ml-1"
onClick={onCreateRoot}
>
<Plus className="h-3.5 w-3.5" />
</Button>
</TooltipTrigger>
@@ -134,7 +153,7 @@ export function RootTabs({ tabs, activeTabId, onTabClick, onEditTab, onCreateRoo
</TooltipContent>
</Tooltip>
</div>
);
)
}
// ── Sortable root tab ─────────────────────────────────────────
@@ -147,22 +166,22 @@ function SortableRootTab({
onToggle,
onDelete,
}: {
tab: RootTab;
isActive: boolean;
onClick: () => void;
onEdit: () => void;
onToggle: () => void;
onDelete: () => void;
tab: RootTab
isActive: boolean
onClick: () => void
onEdit: () => void
onToggle: () => void
onDelete: () => void
}) {
const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({
id: tab.id,
});
})
const style: React.CSSProperties = {
transform: CSS.Transform.toString(transform),
transition,
opacity: isDragging ? 0.3 : 1,
};
}
return (
<ContextMenu>
@@ -178,12 +197,12 @@ function SortableRootTab({
</ContextMenuItem>
<ContextMenuSeparator />
<ContextMenuItem onClick={onToggle}>
{tab.enabled === "1" ? (
{tab.enabled === '1' ? (
<PowerOff className="mr-2 h-3.5 w-3.5" />
) : (
<Power className="mr-2 h-3.5 w-3.5" />
)}
{tab.enabled === "1" ? "Disable" : "Enable"}
{tab.enabled === '1' ? 'Disable' : 'Enable'}
</ContextMenuItem>
<ContextMenuSeparator />
<ContextMenuItem className="text-destructive focus:text-destructive" onClick={onDelete}>
@@ -192,7 +211,7 @@ function SortableRootTab({
</ContextMenuItem>
</ContextMenuContent>
</ContextMenu>
);
)
}
// ── Tab button render ─────────────────────────────────────────
@@ -204,11 +223,11 @@ function TabButton({
onClick,
onDoubleClick,
}: {
tab: RootTab;
isActive: boolean;
isOverlay?: boolean;
onClick?: () => void;
onDoubleClick?: () => void;
tab: RootTab
isActive: boolean
isOverlay?: boolean
onClick?: () => void
onDoubleClick?: () => void
}) {
return (
<button
@@ -216,16 +235,16 @@ function TabButton({
onClick={onClick}
onDoubleClick={onDoubleClick}
className={cn(
"flex items-center gap-1.5 px-3 py-1.5 rounded-md text-sm font-medium transition-colors whitespace-nowrap shrink-0",
'flex items-center gap-1.5 px-3 py-1.5 rounded-md text-sm font-medium transition-colors whitespace-nowrap shrink-0',
isActive
? "bg-primary text-primary-foreground shadow-sm"
: "hover:bg-accent text-muted-foreground hover:text-foreground",
tab.enabled !== "1" && "opacity-50",
isOverlay && "bg-card shadow-lg border",
? 'bg-primary text-primary-foreground shadow-sm'
: 'hover:bg-accent text-muted-foreground hover:text-foreground',
tab.enabled !== '1' && 'opacity-50',
isOverlay && 'bg-card shadow-lg border',
)}
>
<CatalogIcon iconImage={tab.iconImage} size={16} />
<span className="max-w-32 truncate">{tab.caption}</span>
</button>
);
)
}