feat(catalog): add auto-category wizard with live preview and smart suggestions
- Add AutoCategoryDialog: pick furni (or empty page), suggest caption/icon/layout, live preview - Add createAutoCategory server action (page + offers in one export) with CatalogKind - Extend furni search API with interactionType - Share ShopTile and refactor inline-editor/items-shop-preview to use it - Add suggestion heuristics (suggestCategoryName/dIcon/layout) with tests - Add autoCategory translations (en/nl)
This commit is contained in:
1 parent
baeb54aeb5
commit
f832479e52
14 files changed
+2577
-567
No files matched your search
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { LayoutGrid, Search, X } from "lucide-react";
|
||||
import { LayoutGrid, Search, Wand2, X } from "lucide-react";
|
||||
import { useTranslations } from "next-intl";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
@@ -15,6 +15,7 @@ import { useLatestRequest } from "@/features/catalog/client/use-latest-request";
|
||||
import { CatalogSearch } from "@/features/catalog/components/catalog-search";
|
||||
import type { CatalogSearchResult } from "@/features/catalog/domain/search";
|
||||
import type { RootTab } from "@/types/catalog";
|
||||
import { AutoCategoryDialog } from "./auto-category-dialog";
|
||||
import { BreadcrumbBar } from "./breadcrumb-bar";
|
||||
import { InlineEditor, type PageUpdateData } from "./inline-editor";
|
||||
import { RootTabs } from "./root-tabs";
|
||||
@@ -165,6 +166,7 @@ function CatalogManagerInner({
|
||||
const rootRequests = useLatestRequest();
|
||||
const searchNavigation = useLatestRequest();
|
||||
const [searchOpen, setSearchOpen] = useState(false);
|
||||
const [autoOpen, setAutoOpen] = useState(false);
|
||||
const [searchTarget, setSearchTarget] = useState<{
|
||||
offerId: number | null;
|
||||
key: number;
|
||||
@@ -399,6 +401,23 @@ function CatalogManagerInner({
|
||||
{heading}
|
||||
</h2>
|
||||
<div className="flex items-center gap-1">
|
||||
{canEdit && catalogType === "normal" && (
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
aria-label={t("autoCategory.title")}
|
||||
title={t("autoCategory.title")}
|
||||
onClick={() => {
|
||||
if (!mayLeave()) return;
|
||||
setAutoOpen(true);
|
||||
}}
|
||||
>
|
||||
<Wand2 className="size-4" />
|
||||
<span className="hidden sm:inline">
|
||||
{t("autoCategory.title")}
|
||||
</span>
|
||||
</Button>
|
||||
)}
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
@@ -437,6 +456,16 @@ function CatalogManagerInner({
|
||||
</div>
|
||||
)}
|
||||
|
||||
<AutoCategoryDialog
|
||||
catalogType={catalogType}
|
||||
open={autoOpen}
|
||||
onOpenChange={setAutoOpen}
|
||||
onCreated={(pageId) => {
|
||||
void loadRootPages();
|
||||
handleSelectPage(pageId);
|
||||
}}
|
||||
/>
|
||||
|
||||
<BreadcrumbBar onSelectPage={handleSelectPage} />
|
||||
|
||||
<RootTabs
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
Reference in new issue
Block a user