feat(categories): implement professional category management experience
Categories dashboard (real total/visible/hidden/empty/root/subcategory/missing-image/missing-SEO/last-modified/completion% stats, recommended next action); tree view is now a real expand/collapse hierarchy (state persisted via LocalStorageService) with keyboard navigation (arrow keys, jump-to-parent), search that force-expands and keeps only matching branches + their ancestors/descendants instead of silently dropping deep matches; added Table/Cards views alongside the tree with density and saved column visibility; real bulk actions (show/hide/delete/assign parent/assign image via the Media Library picker/duplicate via the existing createCategory call/CSV export) plus the pre-existing single-item actions; reusable CategoryHealthWidget (image/SEO/description/valid-parent/visibility/products-assigned + completion%); editor reorganized into General/Media/SEO/Visibility/Navigation/Attributes/Advanced tabs, media now uses the shared ImageFieldComponent, SEO explains fields in plain language with a live preview, Navigation tab shows real breadcrumb/children/visibility-based nav status, Attributes uses the shared KeyValueEditorComponent. Filled in the adminCategories i18n namespace (previously only 2 of ~90 referenced keys existed) across en/ru/hy. Also fixed the pre-existing bug where a filtered/searched category list could silently drop a matched descendant whose ancestor's title didn't match, by loading the full catalog once and filtering client-side.
This commit is contained in:
@@ -1228,6 +1228,84 @@ export interface Translations {
|
||||
adminCategories: {
|
||||
chooseImage: string;
|
||||
replaceImage: string;
|
||||
search: string;
|
||||
showDeleted: string;
|
||||
create: string;
|
||||
edit: string;
|
||||
title: string;
|
||||
slug: string;
|
||||
slugTaken: string;
|
||||
parent: string;
|
||||
noParent: string;
|
||||
icon: string;
|
||||
image: string;
|
||||
imageHint: string;
|
||||
description: string;
|
||||
items: string;
|
||||
status: { draft: string; published: string };
|
||||
restore: string;
|
||||
saveDraft: string;
|
||||
publish: string;
|
||||
confirmDelete: string;
|
||||
confirmLeaveUnsaved: string;
|
||||
deleteBlocked: string;
|
||||
emptyTitle: string;
|
||||
emptyDescription: string;
|
||||
emptyGuide: string;
|
||||
viewTree: string;
|
||||
viewCards: string;
|
||||
expandAll: string;
|
||||
collapseAll: string;
|
||||
expandNode: string;
|
||||
collapseNode: string;
|
||||
jumpToParent: string;
|
||||
deletedBadge: string;
|
||||
column_slug: string;
|
||||
column_items: string;
|
||||
column_status: string;
|
||||
column_visibility: string;
|
||||
column_updated: string;
|
||||
bulkAssignParent: string;
|
||||
bulkAssignImage: string;
|
||||
groupGeneral: string;
|
||||
groupMedia: string;
|
||||
groupSeo: string;
|
||||
groupVisibility: string;
|
||||
groupNavigation: string;
|
||||
groupAttributes: string;
|
||||
groupAdvanced: string;
|
||||
visibilityExplain: string;
|
||||
navBreadcrumb: string;
|
||||
navRoot: string;
|
||||
navChildren: string;
|
||||
navNoChildren: string;
|
||||
navAppearsIn: string;
|
||||
navAppearsVisible: string;
|
||||
navAppearsHidden: string;
|
||||
itemsCountLabel: string;
|
||||
createdAtLabel: string;
|
||||
healthImage: string;
|
||||
healthSeo: string;
|
||||
healthDescription: string;
|
||||
healthParent: string;
|
||||
healthVisibility: string;
|
||||
healthProducts: string;
|
||||
totalCategories: string;
|
||||
visibleCount: string;
|
||||
hiddenCount: string;
|
||||
emptyCount: string;
|
||||
rootCount: string;
|
||||
subCount: string;
|
||||
missingImagesCount: string;
|
||||
missingSeoCount: string;
|
||||
lastModified: string;
|
||||
lastModifiedNever: string;
|
||||
completionLabel: string;
|
||||
recommendedNext: string;
|
||||
recommendAddImage: string;
|
||||
recommendAddSeo: string;
|
||||
recommendFillEmpty: string;
|
||||
recommendNone: string;
|
||||
};
|
||||
adminProducts: {
|
||||
emptyTitle: string;
|
||||
|
||||
Reference in New Issue
Block a user