From 821a1c6ba836e0338e8b9f89c5e052f0a66b4822 Mon Sep 17 00:00:00 2001 From: sdarbinyan Date: Sat, 18 Jul 2026 09:43:03 +0400 Subject: [PATCH] feat(builder): redesign marketplace builder experience and navigation Renamed the experience consistently to Marketplace Builder everywhere visible (page title/subtitle, breadcrumbs, sidebar, dashboard quick action/shortcut copy) - internal ProjectEditor class/selector names kept as-is to avoid regressions. builder.title/subtitle no longer say 'bootstrap-config editing surface' to end users. New business-oriented IA (builder-groups.model.ts): 12 existing ProjectEditorSectionIds regrouped into 8 groups (Marketplace, Branding and Design, Homepage, Content, Languages, Marketplace Features, Navigation and Search, Preview) - every existing section mapped to exactly one group, none dropped, no group points at a page that doesn't exist. New Builder landing page at /edit (was a redirect straight into the General form): readiness percent, recommended next step, one overview card per group (purpose + real complete/in-progress/not-started/unknown status, icon+text never color-alone), a Marketplace Readiness checklist, quick links. All derived from real facade/schema signals (required-field fill state, modifiedSections, staticPages, catalog counts via BackofficeDataService) or explicitly marked unknown (the "preview reviewed" check has no tracking - shown as unknown, never guessed). Section pages (/edit/:section) now share one consistent header: breadcrumb (Builder > Group > Section), draft/published + modified badges, and a contextual help panel (what is this / where visible / what happens if you skip it) sourced per group. Sidebar nav rewritten as grouped, icon-led sections with per-section and per-group status indicators; layout converted from a top pill-tab bar to a responsive sidebar (desktop 280px, tablet 72px icon rail, mobile drawer with Escape-to-close), matching the Sprint 1 admin shell pattern. Section form components themselves untouched. Routes: 'edit' is now its own landing route instead of redirecting to 'edit/general'; /builder and /project-editor redirect to 'edit'. Sprint 1/2 destinations that pointed at edit/general now point at the new edit landing page. Co-Authored-By: Claude Sonnet 5 --- src/app/app.routes.ts | 13 +- .../facade/admin-dashboard.facade.ts | 4 +- .../features/admin/shell/admin-nav.model.ts | 2 +- .../builder/builder-groups.model.ts | 122 ++++++++ .../project-editor-nav.component.html | 38 ++- .../project-editor-nav.component.scss | 149 ++++++--- .../project-editor-nav.component.ts | 105 +++++-- .../facade/project-editor.facade.ts | 92 +++++- .../models/project-editor.model.ts | 9 + .../builder-overview-page.component.html | 89 ++++++ .../builder-overview-page.component.scss | 280 +++++++++++++++++ .../pages/builder-overview-page.component.ts | 132 ++++++++ .../pages/project-editor-page.component.html | 140 ++++++--- .../pages/project-editor-page.component.scss | 295 +++++++++++++++++- .../pages/project-editor-page.component.ts | 55 +++- src/app/i18n/en.ts | 83 ++++- src/app/i18n/hy.ts | 83 ++++- src/app/i18n/ru.ts | 83 ++++- src/app/i18n/translations.ts | 77 +++++ 19 files changed, 1699 insertions(+), 152 deletions(-) create mode 100644 src/app/features/project-editor/builder/builder-groups.model.ts create mode 100644 src/app/features/project-editor/pages/builder-overview-page.component.html create mode 100644 src/app/features/project-editor/pages/builder-overview-page.component.scss create mode 100644 src/app/features/project-editor/pages/builder-overview-page.component.ts diff --git a/src/app/app.routes.ts b/src/app/app.routes.ts index 3febbe5..010b19f 100644 --- a/src/app/app.routes.ts +++ b/src/app/app.routes.ts @@ -43,6 +43,10 @@ const coreRoutes: Routes = [ path: 'search', loadComponent: () => import('./features/website/catalog/containers/catalog-container.component').then(m => m.CatalogContainerComponent) }, + { + path: 'edit', + loadComponent: () => import('./features/project-editor/pages/builder-overview-page.component').then(m => m.BuilderOverviewPageComponent) + }, { path: 'edit/:section', loadComponent: () => import('./features/project-editor/pages/project-editor-page.component').then(m => m.ProjectEditorPageComponent), @@ -202,19 +206,14 @@ const coreRoutes: Routes = [ { path: '**', redirectTo: 'dashboard' } ] }, - { - path: 'edit', - redirectTo: 'edit/general', - pathMatch: 'full' - }, { path: 'builder', - redirectTo: 'edit/general', + redirectTo: 'edit', pathMatch: 'full' }, { path: 'project-editor', - redirectTo: 'edit/general', + redirectTo: 'edit', pathMatch: 'full' }, { diff --git a/src/app/features/admin/dashboard/facade/admin-dashboard.facade.ts b/src/app/features/admin/dashboard/facade/admin-dashboard.facade.ts index af2ae70..0b3cc01 100644 --- a/src/app/features/admin/dashboard/facade/admin-dashboard.facade.ts +++ b/src/app/features/admin/dashboard/facade/admin-dashboard.facade.ts @@ -18,7 +18,7 @@ import { const QUICK_ACTIONS: AdminDashboardQuickAction[] = [ { id: 'add-product', icon: 'pi-plus-circle', labelKey: 'dashboard.actionAddProduct', descriptionKey: 'dashboard.actionAddProductDescription', route: ['backoffice', 'products', 'create'] }, { id: 'create-category', icon: 'pi-sitemap', labelKey: 'dashboard.actionCreateCategory', descriptionKey: 'dashboard.actionCreateCategoryDescription', route: ['backoffice', 'categories', 'create'] }, - { id: 'edit-project', icon: 'pi-th-large', labelKey: 'dashboard.actionEditProject', descriptionKey: 'dashboard.actionEditProjectDescription', route: ['edit', 'general'] }, + { id: 'edit-project', icon: 'pi-th-large', labelKey: 'dashboard.actionEditProject', descriptionKey: 'dashboard.actionEditProjectDescription', route: ['edit'] }, { id: 'edit-homepage', icon: 'pi-home', labelKey: 'dashboard.actionEditHomepage', descriptionKey: 'dashboard.actionEditHomepageDescription', route: ['edit', 'homepage'] }, { id: 'media-library', icon: 'pi-images', labelKey: 'dashboard.actionMediaLibrary', descriptionKey: 'dashboard.actionMediaLibraryDescription', route: ['backoffice', 'media'] }, { id: 'orders', icon: 'pi-shopping-cart', labelKey: 'dashboard.actionOrders', descriptionKey: 'dashboard.actionOrdersDescription', route: ['backoffice', 'orders'] }, @@ -27,7 +27,7 @@ const QUICK_ACTIONS: AdminDashboardQuickAction[] = [ const SHORTCUTS: AdminDashboardShortcut[] = [ { id: 'products', icon: 'pi-box', labelKey: 'dashboard.actionProducts', route: ['backoffice', 'products'] }, { id: 'categories', icon: 'pi-tags', labelKey: 'dashboard.actionCategories', route: ['backoffice', 'categories'] }, - { id: 'marketplace-builder', icon: 'pi-sitemap', labelKey: 'dashboard.shortcutMarketplaceBuilder', route: ['edit', 'general'] }, + { id: 'marketplace-builder', icon: 'pi-sitemap', labelKey: 'dashboard.shortcutMarketplaceBuilder', route: ['edit'] }, { id: 'static-pages', icon: 'pi-file-edit', labelKey: 'dashboard.actionStaticPages', route: ['backoffice', 'static-pages'] }, { id: 'orders', icon: 'pi-shopping-cart', labelKey: 'dashboard.actionOrders', route: ['backoffice', 'orders'] }, { id: 'users', icon: 'pi-users', labelKey: 'dashboard.actionUsers', route: ['backoffice', 'users'] }, diff --git a/src/app/features/admin/shell/admin-nav.model.ts b/src/app/features/admin/shell/admin-nav.model.ts index 1b57c52..f56c48f 100644 --- a/src/app/features/admin/shell/admin-nav.model.ts +++ b/src/app/features/admin/shell/admin-nav.model.ts @@ -36,7 +36,7 @@ export const ADMIN_NAV_PRIMARY: AdminNavEntry[] = [ { type: 'link', id: 'reports', icon: 'pi-chart-bar', labelKey: 'adminShell.nav.reports', comingSoon: true }, { type: 'link', id: 'content', icon: 'pi-file-edit', labelKey: 'adminShell.nav.content', absolutePath: ['edit', 'static-pages'] }, { type: 'link', id: 'media', icon: 'pi-images', labelKey: 'adminShell.nav.mediaLibrary', path: ['media'] }, - { type: 'link', id: 'marketplace-builder', icon: 'pi-sitemap', labelKey: 'adminShell.nav.marketplaceBuilder', absolutePath: ['edit', 'general'] }, + { type: 'link', id: 'marketplace-builder', icon: 'pi-sitemap', labelKey: 'adminShell.nav.marketplaceBuilder', absolutePath: ['edit'] }, { type: 'link', id: 'users', icon: 'pi-users', labelKey: 'adminShell.nav.users', path: ['users'] }, { type: 'link', id: 'settings', icon: 'pi-cog', labelKey: 'adminShell.nav.settings', comingSoon: true }, { type: 'link', id: 'monitoring', icon: 'pi-desktop', labelKey: 'adminShell.nav.monitoring', path: ['monitoring'] }, diff --git a/src/app/features/project-editor/builder/builder-groups.model.ts b/src/app/features/project-editor/builder/builder-groups.model.ts new file mode 100644 index 0000000..1fbaaa2 --- /dev/null +++ b/src/app/features/project-editor/builder/builder-groups.model.ts @@ -0,0 +1,122 @@ +import { ProjectEditorSectionId } from '../models/project-editor.model'; + +export type BuilderGroupId = + | 'marketplace' + | 'branding' + | 'homepage' + | 'content' + | 'languages' + | 'features' + | 'navigation' + | 'preview'; + +export interface BuilderGroup { + id: BuilderGroupId; + icon: string; + labelKey: string; + descriptionKey: string; + purposeKey: string; + whereKey: string; + skipKey: string; + sections: ProjectEditorSectionId[]; +} + +/** + * The Builder's business-oriented information architecture (Sprint 3). Maps + * every existing ProjectEditorSectionId to exactly one group - no section is + * dropped, no group points at a section that doesn't exist yet. `static-pages` + * routes here as "Content" (it's the same StaticPagesEditorComponent already + * wired at that section id, just relabeled for a non-technical audience). + */ +export const BUILDER_GROUPS: BuilderGroup[] = [ + { + id: 'marketplace', + icon: 'pi-shop', + labelKey: 'builder.groupMarketplaceLabel', + descriptionKey: 'builder.groupMarketplaceDescription', + purposeKey: 'builder.groupMarketplacePurpose', + whereKey: 'builder.groupMarketplaceWhere', + skipKey: 'builder.groupMarketplaceSkip', + sections: ['general'], + }, + { + id: 'branding', + icon: 'pi-palette', + labelKey: 'builder.groupBrandingLabel', + descriptionKey: 'builder.groupBrandingDescription', + purposeKey: 'builder.groupBrandingPurpose', + whereKey: 'builder.groupBrandingWhere', + skipKey: 'builder.groupBrandingSkip', + sections: ['branding', 'theme', 'header', 'footer'], + }, + { + id: 'homepage', + icon: 'pi-home', + labelKey: 'builder.groupHomepageLabel', + descriptionKey: 'builder.groupHomepageDescription', + purposeKey: 'builder.groupHomepagePurpose', + whereKey: 'builder.groupHomepageWhere', + skipKey: 'builder.groupHomepageSkip', + sections: ['homepage', 'widgets'], + }, + { + id: 'content', + icon: 'pi-file-edit', + labelKey: 'builder.groupContentLabel', + descriptionKey: 'builder.groupContentDescription', + purposeKey: 'builder.groupContentPurpose', + whereKey: 'builder.groupContentWhere', + skipKey: 'builder.groupContentSkip', + sections: ['static-pages'], + }, + { + id: 'languages', + icon: 'pi-globe', + labelKey: 'builder.groupLanguagesLabel', + descriptionKey: 'builder.groupLanguagesDescription', + purposeKey: 'builder.groupLanguagesPurpose', + whereKey: 'builder.groupLanguagesWhere', + skipKey: 'builder.groupLanguagesSkip', + sections: ['languages'], + }, + { + id: 'features', + icon: 'pi-sliders-h', + labelKey: 'builder.groupFeaturesLabel', + descriptionKey: 'builder.groupFeaturesDescription', + purposeKey: 'builder.groupFeaturesPurpose', + whereKey: 'builder.groupFeaturesWhere', + skipKey: 'builder.groupFeaturesSkip', + sections: ['features'], + }, + { + id: 'navigation', + icon: 'pi-compass', + labelKey: 'builder.groupNavigationLabel', + descriptionKey: 'builder.groupNavigationDescription', + purposeKey: 'builder.groupNavigationPurpose', + whereKey: 'builder.groupNavigationWhere', + skipKey: 'builder.groupNavigationSkip', + sections: ['navigation'], + }, + { + id: 'preview', + icon: 'pi-desktop', + labelKey: 'builder.groupPreviewLabel', + descriptionKey: 'builder.groupPreviewDescription', + purposeKey: 'builder.groupPreviewPurpose', + whereKey: 'builder.groupPreviewWhere', + skipKey: 'builder.groupPreviewSkip', + sections: ['preview'], + }, +]; + +export const SECTION_TO_GROUP: Record = BUILDER_GROUPS.reduce( + (map, group) => { + for (const section of group.sections) { + map[section] = group.id; + } + return map; + }, + {} as Record, +); diff --git a/src/app/features/project-editor/components/project-editor-nav.component.html b/src/app/features/project-editor/components/project-editor-nav.component.html index ddfedda..033c85b 100644 --- a/src/app/features/project-editor/components/project-editor-nav.component.html +++ b/src/app/features/project-editor/components/project-editor-nav.component.html @@ -1,10 +1,32 @@ -