Files
marketplaces/src/app/i18n/translations.ts

2146 lines
56 KiB
TypeScript
Raw Normal View History

2026-02-26 23:09:20 +04:00
export interface Translations {
header: {
home: string;
search: string;
about: string;
contacts: string;
searchPlaceholder: string;
catalog: string;
wishlist: string;
compare: string;
openMenu: string;
closeMenu: string;
login: string;
logout: string;
2026-02-26 23:09:20 +04:00
};
footer: {
description: string;
company: string;
aboutUs: string;
contacts: string;
requisites: string;
support: string;
faq: string;
delivery: string;
guarantee: string;
legal: string;
offer: string;
privacy: string;
returns: string;
info: string;
aboutCompany: string;
documents: string;
paymentRules: string;
returnPolicy: string;
publicOffer: string;
help: string;
payment: string;
allRightsReserved: string;
};
home: {
welcomeTo: string;
subtitle: string;
startSearch: string;
loading: string;
errorTitle: string;
retry: string;
categoriesTitle: string;
categoriesSubtitle: string;
categoriesEmpty: string;
categoriesEmptyDesc: string;
dexarHeroTitle: string;
dexarHeroSubtitle: string;
dexarHeroTagline: string;
goToCatalog: string;
findProduct: string;
loadingDexar: string;
catalogTitle: string;
emptyCategoriesDexar: string;
categoriesSoonDexar: string;
itemsCount: string;
};
cart: {
title: string;
clear: string;
empty: string;
emptyDesc: string;
goShopping: string;
total: string;
items: string;
deliveryLabel: string;
2026-06-21 23:13:01 +04:00
deliveryMethod: string;
selectDelivery: string;
deliveryPlace: string;
deliveryTime: string;
digitalDelivery: string;
deliveryRequired: string;
2026-02-26 23:09:20 +04:00
toPay: string;
agreeWith: string;
publicOffer: string;
returnPolicy: string;
guaranteeTerms: string;
privacyPolicy: string;
and: string;
checkout: string;
2026-06-29 00:06:18 +04:00
payViaQr: string;
payViaCard: string;
2026-02-26 23:09:20 +04:00
close: string;
creatingPayment: string;
waitFewSeconds: string;
scanQr: string;
amountToPay: string;
waitingPayment: string;
copied: string;
copyLink: string;
openNewTab: string;
paymentSuccess: string;
paymentSuccessDesc: string;
sending: string;
send: string;
2026-06-02 00:57:36 +04:00
paymentError: string;
paymentErrorDesc: string;
retryPayment: string;
2026-02-26 23:09:20 +04:00
paymentTimeout: string;
paymentTimeoutDesc: string;
autoClose: string;
confirmClear: string;
removeItem: string;
increaseQuantity: string;
decreaseQuantity: string;
paymentQrAlt: string;
2026-02-26 23:09:20 +04:00
acceptTerms: string;
copyError: string;
emailSuccess: string;
emailError: string;
phoneRequired: string;
phoneMoreDigits: string;
phoneTooMany: string;
emailRequired: string;
emailTooShort: string;
emailTooLong: string;
emailNeedsAt: string;
emailNeedsDomain: string;
emailInvalid: string;
telegramIdMissing: string;
paymentDescriptionFallback: string;
emailPlaceholder: string;
phonePlaceholder: string;
2026-03-24 00:09:11 +04:00
loginRequired: string;
loginRequiredDesc: string;
loginWithTelegram: string;
orScanQr: string;
2026-02-26 23:09:20 +04:00
};
search: {
title: string;
placeholder: string;
searchBarAria: string;
2026-02-26 23:09:20 +04:00
resultsCount: string;
searching: string;
retry: string;
noResults: string;
noResultsFor: string;
noResultsHint: string;
emptyResultsAria: string;
popularCategories: string;
recommendedProducts: string;
aiSuggestionHint: string;
suggestionType: {
product: string;
category: string;
brand: string;
collection: string;
seller: string;
'static-page': string;
ai: string;
};
2026-02-26 23:09:20 +04:00
addToCart: string;
loadingMore: string;
allLoaded: string;
emptyState: string;
2026-07-05 01:10:56 +04:00
minLength: string;
2026-02-26 23:09:20 +04:00
of: string;
};
category: {
retry: string;
addToCart: string;
loadingMore: string;
allLoaded: string;
emptyTitle: string;
emptyDesc: string;
goHome: string;
loading: string;
};
2026-07-05 01:36:21 +04:00
catalog: {
title: string;
breadcrumb: string;
allCategories: string;
products: string;
loading: string;
loadingProducts: string;
errorTitle: string;
error: string;
retry: string;
categoryHint: string;
productHint: string;
emptyTitle: string;
emptyCategories: string;
emptyProducts: string;
addToCart: string;
categoriesCount: string;
productsCount: string;
2026-07-09 01:40:22 +04:00
entriesCount: string;
categoryBannerPlaceholder: string;
navigationPlaceholder: string;
removeSavedSearch: string;
resetFilters: string;
filtersTitle: string;
from: string;
to: string;
2026-07-09 01:40:22 +04:00
minValue: string;
maxValue: string;
enabled: string;
searchPlaceholder: string;
searchSubmit: string;
clearSearch: string;
2026-07-09 01:40:22 +04:00
suggestionsTitle: string;
popularSearchesTitle: string;
2026-07-09 01:40:22 +04:00
recentSearchesTitle: string;
searchHistoryTitle: string;
clearHistory: string;
searchNoResultsHint: string;
searchProductsFound: string;
searchResultsSummary: string;
2026-07-10 15:55:38 +04:00
loadMore: string;
2026-07-09 01:40:22 +04:00
sortBy: string;
sortRelevance: string;
sortLatest: string;
sortPriceAsc: string;
sortPriceDesc: string;
sortRating: string;
sortPopular: string;
sortDiscount: string;
layoutGrid: string;
layoutLargeGrid: string;
layoutCompactGrid: string;
2026-07-10 15:55:38 +04:00
layoutGrid2: string;
layoutGrid3: string;
layoutGrid4: string;
layoutCompact: string;
2026-07-09 01:40:22 +04:00
layoutList: string;
noResults: string;
itemsCount: string;
emptyResultsTitle: string;
emptyResultsDescription: string;
previousPage: string;
nextPage: string;
pageOf: string;
emptyCategoryTitle: string;
emptyCategoryMessage: string;
2026-07-10 15:55:38 +04:00
goToParentCategory: string;
browseCategories: string;
2026-07-10 15:55:38 +04:00
offlineTitle: string;
offlineMessage: string;
noFilterMatchTitle: string;
noFilterMatchMessage: string;
clearFilters: string;
openFilters: string;
applyFilters: string;
close: string;
filtersDrawerAria: string;
sortSheetAria: string;
mobileToolbarAria: string;
gridCycle: string;
filtersPanelAria: string;
2026-07-09 01:40:22 +04:00
filterPrice: string;
filterAvailability: string;
filterInStock: string;
filterLowStock: string;
filterOutOfStock: string;
filterRating: string;
filterStars: string;
filterBrand: string;
filterCategory: string;
filterCategoryValue: string;
filterSubcategory: string;
filterDiscount: string;
filterNew: string;
filterColor: string;
filterSize: string;
filterAttributes: string;
favorite: string;
compare: string;
share: string;
quickView: string;
quickViewDetails: string;
stockHigh: string;
stockMedium: string;
stockLow: string;
stockOut: string;
2026-07-09 01:40:22 +04:00
};
productDetails: {
loading: string;
errorTitle: string;
retry: string;
missingTitle: string;
missingDescription: string;
backToCatalog: string;
tabsAria: string;
mediaAria: string;
ratingStarsAria: string;
selectRatingAria: string;
fix(storefront): premium UX polish for product, compare, wishlist - delivery-information, product-actions, product-description, product-gallery, product-information, related-products, variant-selector: normalize hardcoded hex colors to design tokens (--text-primary, --text-secondary, --border-color, --bg-primary/ --bg-secondary, --primary-color/--primary-hover); stock status and discount badge now use semantic --success-color/--warning-color/ --error-color instead of near-duplicate literal hex - product-actions: add aria-pressed to wishlist/compare toggle buttons; add hover/active/disabled states to action buttons - product-gallery: add aria-current + aria-label to active thumbnail button; add focus-visible ring and hover state on thumbnails and toolbar buttons - variant-selector: add aria-pressed to colour/size option buttons; add a visible checkmark glyph on the selected colour swatch so selection isn't color-only; add hover states - product-tabs: add role="tab"/aria-selected to tab buttons - star-selector: add per-star aria-label (new starsLabel i18n key added to en/hy/ru + translations.ts interface) - question-list: add aria-expanded to the ask-question disclosure toggle; swap plain empty-state <p> for app-empty-state; add hover/disabled states to pager buttons - review-list: swap plain empty-state <p> for app-empty-state; add hover/disabled states to pager and load-more buttons - question-card, question-form, review-form: normalize accepted/ success/error colors to semantic tokens; add focus-visible and hover/disabled states to inputs and submit buttons - compare-table: add scope="col"/scope="row" to table headers; make header row and attribute column sticky for easier comparison on long tables - compare-page: add hover/focus states to the remove-from-compare chip button Build verified green via `npm run build`. Out of scope / skipped: - src/app/pages/item-detail/* is dead code (not referenced by any route or component) - left untouched - wishlist page and product-details-container were already fully composed with shared skeleton/empty-state/button components from the RC-Visual-02 pass - no changes needed - stars.component display-only rating glyphs use a light gray not an exact token match - left as-is to avoid an unintended visual shift Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 11:47:57 +04:00
starsLabel: string;
2026-07-09 01:40:22 +04:00
reviewsEmpty: string;
questionsEmpty: string;
askQuestion: string;
hideQuestionForm: string;
questionFormTitle: string;
questionFormPlaceholder: string;
questionFormAnonymous: string;
submitQuestion: string;
reviewFormTitle: string;
reviewRatingLabel: string;
reviewTitleLabel: string;
reviewTitlePlaceholder: string;
reviewTextLabel: string;
reviewTextPlaceholder: string;
reviewAnonymous: string;
reviewUploadPlaceholder: string;
reviewRatingRequired: string;
reviewTextRequired: string;
reviewSuccess: string;
2026-07-09 01:40:22 +04:00
submitReview: string;
submitting: string;
loadMore: string;
showingOf: string;
questionsSubmissionFuture: string;
specificationsGeneral: string;
actionsAria: string;
buyNow: string;
wishlist: string;
compare: string;
share: string;
notifyMe: string;
notifyMeConfirmed: string;
zoom: string;
fullscreen: string;
pdfDocument: string;
manualDocument: string;
warrantyDocument: string;
openDocument: string;
2026-07-09 01:40:22 +04:00
specificationsEmpty: string;
warrantyTitle: string;
warrantyItem1: string;
warrantyItem2: string;
warrantyItem3: string;
verifiedPurchase: string;
officialSeller: string;
acceptedAnswer: string;
like: string;
dislike: string;
reviewsCountLabel: string;
previous: string;
next: string;
pageOf: string;
2026-07-05 01:36:21 +04:00
};
2026-02-26 23:09:20 +04:00
subcategories: {
loading: string;
retry: string;
emptyTitle: string;
emptyDesc: string;
goHome: string;
2026-03-24 00:09:11 +04:00
itemsInCategory: string;
2026-07-05 01:09:55 +04:00
childrenCount: string;
productsCount: string;
includesProducts: string;
2026-02-26 23:09:20 +04:00
};
itemDetail: {
loading: string;
loadingDexar: string;
back: string;
backHome: string;
noImage: string;
stock: string;
inStock: string;
lowStock: string;
lastItems: string;
mediumStock: string;
addToCart: string;
description: string;
specifications: string;
2026-02-26 23:09:20 +04:00
reviews: string;
yourReview: string;
leaveReview: string;
rating: string;
reviewPlaceholder: string;
reviewPlaceholderDexar: string;
anonymous: string;
submitting: string;
submit: string;
reviewSuccess: string;
reviewError: string;
defaultUser: string;
defaultUserDexar: string;
noReviews: string;
qna: string;
photo: string;
reviewsCount: string;
today: string;
yesterday: string;
daysAgo: string;
weeksAgo: string;
2026-03-24 00:09:11 +04:00
colour: string;
size: string;
2026-07-05 01:07:53 +04:00
relatedProducts: string;
2026-02-26 23:09:20 +04:00
};
app: {
connecting: string;
serverUnavailable: string;
serverError: string;
retryConnection: string;
pageTitle: string;
fix(storefront): WCAG 2.1 AA accessibility fixes RC A11Y-01 audit pass, storefront + shared app-shell chrome only. Builds on RC-Visual-02/RC-Premium-01/RC STORE-01 without redoing that work. - Skip link: added first-focusable "skip to main content" link (app.html, styles.scss .skip-link/.sr-only), targeting new #main-content landmark. New app.skipToContent i18n key in en/ru/hy. - Header: mobile menu items stayed keyboard-focusable and screen-reader reachable while visually collapsed (max-height:0 with no visibility toggle) - fixed with visibility:hidden + matched transition-delay. Desktop search input (readonly, click-to-navigate) had no keyboard activation - added aria-label + (keydown.enter). - Cart payment/bank-payment modals: custom (non-app-dialog) UI had no focus trap, no Escape handling, and never returned focus to the triggering element - ported app-dialog's confirmed-correct focus-trap/Escape/return-focus pattern directly onto cart.component.ts. Added role="dialog"/aria-modal/aria-label to both panels and role="status"|"alert"/aria-live to every payment-status screen so screen readers announce state changes (creating/waiting/success/ error/timeout). - Search combobox: suggestion listbox had no role="combobox" wiring on the input and suggestion buttons weren't role="option" - added aria-autocomplete, aria-controls, aria-activedescendant, aria-selected so the existing arrow-key navigation is announced to screen readers. - Product tabs: tablist/tab pattern was incomplete (no role="tablist", no tabpanel) - added role="tablist" + ids to product-tabs.component, role="tabpanel"/aria-labelledby to the content panel in product-details-container. - Review form: rating/text validation errors weren't associated with their controls (no aria-describedby, no role="alert") - fixed; added aria-required to the review textarea. - delivery-selector: added aria-required to the delivery <select> when a selection is mandatory. - Shared app-icon component: doc comment claimed "decorative by default (aria-hidden)" but no aria-hidden was ever applied - fixed to actually set aria-hidden="true" when undecorated, and role="img"/aria-label when ariaLabel is passed. Shared component, affects every icon-only usage app-wide, no visual change. - Color contrast: --text-light fails WCAG AA 4.5:1 for normal text in every theme (dexar 3.39:1, lavero/novo 2.54:1 against white). The two in-scope usages (company-details org-short/basis, review-form upload-placeholder) switched to --text-secondary (4.55:1-7.56:1, passes), same visual family, no layout change. Flagged, not fixed (design-system decisions, not polish): - --border-color fails WCAG 1.4.11 3:1 for UI-component boundaries in every theme (dexar 1.42:1, lavero/novo 1.24:1 vs white) - pervasive token used by hundreds of borders app-wide; needs theme-owner sign-off. - --success-color/--warning-color/--error-color/--info-color used as plain text-on-white in several places (product-information, question-card, review-form, compare-page) fail 4.5:1 (2.15-3.76:1) - genuine brand semantic colors, changing them to pass would visibly shift the palette; needs a deliberate token decision. - Header mobile-menu max-height/padding transition (pre-existing, unrelated to this fix) flagged by design lint as layout-thrashing; left as-is per the "no layout/business-logic changes" constraint. Verified: npx tsc --noEmit clean; npm run build green (only the pre-existing bundle-budget warning, unrelated to this pass). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-24 08:46:18 +04:00
skipToContent: string;
2026-02-26 23:09:20 +04:00
};
platform: {
loadingPage: string;
emptyConfig: string;
};
backoffice: {
title: string;
subtitle: string;
loading: string;
products: string;
categories: string;
otherDomains: string;
sku: string;
titleColumn: string;
price: string;
status: string;
itemsCount: string;
orders: string;
customers: string;
inventory: string;
media: string;
settings: string;
notAvailable: string;
};
builder: {
title: string;
subtitle: string;
2026-07-10 13:43:53 +04:00
general: string;
branding: string;
2026-07-10 13:43:53 +04:00
theme: string;
header: string;
footer: string;
homepage: string;
widgets: string;
2026-07-10 13:52:01 +04:00
staticPages: string;
2026-07-10 13:43:53 +04:00
marketplaceFeatures: string;
preview: string;
brandName: string;
2026-07-10 13:43:53 +04:00
marketplaceName: string;
domain: string;
descriptionLabel: string;
defaultLanguage: string;
supportedLanguages: string;
logo: string;
smallLogo: string;
favicon: string;
socialImage: string;
gallery: string;
addGalleryImage: string;
headerLayout: string;
headerLayoutDefault: string;
headerLayoutCentered: string;
headerSticky: string;
2026-07-10 13:43:53 +04:00
marketplaceTitle: string;
primaryColor: string;
secondaryColor: string;
backgroundColor: string;
surfaceColor: string;
textColor: string;
successColor: string;
warningColor: string;
dangerColor: string;
showLogo: string;
showSearch: string;
showCategories: string;
showLanguages: string;
showCart: string;
showProfile: string;
showWishlist: string;
showCompare: string;
showRegion: string;
companyName: string;
address: string;
phone: string;
email: string;
copyright: string;
paymentIcons: string;
socialLinks: string;
footerLogo: string;
addPaymentIcon: string;
removePaymentIcon: string;
iconAltLabel: string;
addSocialLink: string;
removeSocialLink: string;
socialLinkLabel: string;
socialLinkUrl: string;
invalidUrl: string;
2026-07-10 13:52:01 +04:00
createPage: string;
deletePage: string;
pageId: string;
slug: string;
iconLabel: string;
showInFooter: string;
showInHeader: string;
showInSitemap: string;
requiresAuthentication: string;
footerGroup: string;
orderLabel: string;
translationTitle: string;
htmlPreview: string;
seoSection: string;
seoTitle: string;
seoDescription: string;
seoKeywords: string;
seoCanonical: string;
seoOgTitle: string;
seoOgDescription: string;
seoOgImage: string;
2026-07-10 13:43:53 +04:00
visible: string;
layoutLabel: string;
columns: string;
height: string;
overlay: string;
autoplay: string;
cardsPerRow: string;
filtersLabel: string;
showBadges: string;
showRating: string;
showPrice: string;
widgetJson: string;
reviews: string;
questions: string;
comments: string;
recommendations: string;
recentlyViewed: string;
searchSuggestions: string;
searchHistory: string;
livePreview: string;
previewChangesTitle: string;
previewNoIssues: string;
previewNoChanges: string;
previewChangeField: string;
previewChangeBefore: string;
previewChangeAfter: string;
languagesTab: string;
addLanguage: string;
removeLanguage: string;
setDefaultLanguage: string;
defaultLanguageLabel: string;
navigationTab: string;
navigationHeader: string;
navigationFooter: string;
navigationFooterGrouped: string;
addLink: string;
insertPageLink: string;
linkedToPage: string;
removeLink: string;
linkLabel: string;
linkUrl: string;
2026-07-10 13:43:53 +04:00
exportBootstrap: string;
importBootstrap: string;
exportedBootstrap: string;
importSource: string;
importError: string;
featureFlags: string;
validationMissingLogo: string;
validationNoLanguages: string;
validationDefaultLocaleNotSupported: string;
validationInvalidUrl: string;
validationDuplicateSlugs: string;
validationEmptyHomepage: string;
validationMissingWidget: string;
validationDuplicateNavLinks: string;
validationInvalidColors: string;
validationMissingTranslations: string;
validationInvalidLayouts: string;
validationInvalidJson: string;
validationInvalidCss: string;
validationDuplicateRoutes: string;
validationInvalidWidgetConfig: string;
validationInvalidWidgetSettings: string;
validationInvalidContactEmail: string;
validationInvalidSocialLinkUrl: string;
validationIncompletePaymentIcon: string;
undo: string;
redo: string;
statusDraft: string;
statusPublished: string;
unsavedChanges: string;
save: string;
publish: string;
confirmLeaveUnsaved: string;
confirmPublish: string;
confirmRemoveLanguage: string;
promptLinkUrl: string;
promptImageUrl: string;
promptEmbedUrl: string;
htmlEditorInvalidHtml: string;
htmlEditorCode: string;
htmlEditorPreview: string;
lastSaved: string;
draftRestored: string;
dismiss: string;
resetDraft: string;
resetSection: string;
confirmResetDraft: string;
confirmResetSection: string;
marketplaceNameDesc: string;
domainDesc: string;
descriptionFieldDesc: string;
defaultLanguageDesc: string;
supportedLanguagesDesc: string;
logoDesc: string;
smallLogoDesc: string;
faviconDesc: string;
socialImageDesc: string;
galleryDesc: string;
headerLayoutDesc: string;
headerStickyDesc: string;
marketplaceTitleDesc: string;
primaryColorDesc: string;
secondaryColorDesc: string;
backgroundColorDesc: string;
surfaceColorDesc: string;
textColorDesc: string;
successColorDesc: string;
warningColorDesc: string;
dangerColorDesc: string;
themeModeLabel: string;
themeModeDesc: string;
themeModeLight: string;
themeModeLightDesc: string;
themeModeDark: string;
themeModeDarkDesc: string;
themeModeSystem: string;
themeModeSystemDesc: string;
siteLayoutLabel: string;
siteLayoutDesc: string;
siteLayoutDefault: string;
siteLayoutDefaultDesc: string;
siteLayoutSidebarLeft: string;
siteLayoutSidebarLeftDesc: string;
siteLayoutCarouselHome: string;
siteLayoutCarouselHomeDesc: string;
siteLayoutMinimal: string;
siteLayoutMinimalDesc: string;
showLogoDesc: string;
showSearchDesc: string;
showCategoriesDesc: string;
showLanguagesDesc: string;
showCartDesc: string;
showProfileDesc: string;
showWishlistDesc: string;
showCompareDesc: string;
showRegionDesc: string;
companyNameDesc: string;
addressDesc: string;
phoneDesc: string;
emailDesc: string;
copyrightDesc: string;
paymentIconsDesc: string;
socialLinksDesc: string;
footerLogoDesc: string;
iconAltLabelDesc: string;
socialLinkUrlDesc: string;
staticPagesFieldDesc: string;
feat(builder): visual footer builder with drag-and-drop columns Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> P0 user feedback: footer static pages were comma-separated text; no way to add extra phones/emails for different countries. - New FooterColumnConfig/FooterLinkConfig model (footer-config.model.ts): columns of links, each link pointing at an existing static page (resolved by key, so it survives route renames) or a custom URL - Footer Builder UI: add/remove columns and links, per-link toggle between 'existing page' (dropdown of real static pages) and 'custom URL', drag-and-drop reordering of both columns and links via @angular/cdk/drag-drop (same primitive already used by the homepage section builder) - Wired FooterResolverService (the service the real storefront footer actually renders through) to read footer.columns as the primary source when present - without this the builder would have saved data nobody ever displayed. Falls back to the existing legacy static-page auto-grouping when no columns are configured, so existing sites are unaffected - CompanyContactConfig gains additionalPhones/additionalEmails (primary phone/email field unchanged) with add/remove UI for country-specific support lines - Old comma-separated staticPageKeys input removed from the UI; field kept on the model as deprecated/read-compat only - New builder.* i18n keys (en/ru/hy); fixed an accidental duplicate-key collision with pre-existing navigation-section addLink/removeLink keys during the rename pass - Verified in browser: added column, added link, switched link source page->custom, added phone number - all reactive and error-free
2026-07-19 13:58:57 +04:00
additionalPhones: string;
additionalPhonesDesc: string;
addPhone: string;
removePhone: string;
additionalEmails: string;
additionalEmailsDesc: string;
addEmail: string;
removeEmail: string;
footerColumns: string;
footerColumnsDesc: string;
footerColumnTitlePlaceholder: string;
footerLinkLabelPlaceholder: string;
footerLinkExistingPage: string;
footerLinkCustomUrl: string;
addColumn: string;
removeColumn: string;
addColumnLink: string;
removeColumnLink: string;
sectionVisibleDesc: string;
layoutStrategyLabel: string;
layoutStrategyDesc: string;
layoutStrategyStack: string;
layoutStrategyStackDesc: string;
layoutStrategyGrid: string;
layoutStrategyGridDesc: string;
layoutStrategyHero: string;
layoutStrategyHeroDesc: string;
layoutStrategyCarousel: string;
layoutStrategyCarouselDesc: string;
layoutStrategySplit: string;
layoutStrategySplitDesc: string;
sectionColumnsDesc: string;
widgetLayoutDesc: string;
widgetHeightDesc: string;
widgetOverlayDesc: string;
widgetAutoplayDesc: string;
feat(builder): visual homepage blocks, merchant-language widget settings, real carousel arrows Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> P0 user feedback: homepage builder showed raw section.id like 'section-hero'/'section-categories'; hero widget exposed 'full-bleed'/'boxed' and raw px/vh as free text with no explanation; Overlay/Autoplay toggles made no sense without a slides concept; product carousel widgets rendered arrows nowhere near a working carousel. Homepage section (sections list -> visual blocks): - Replaced raw section.id display with a merchant-facing block catalog (icon + name + one-line explanation) for hero/categories/featured-products/product-carousel/recently-viewed/banner/partners/custom-html - Added block catalog picker to append new blocks (was fixed at whatever the seed data had - task asked 'what if we add manually? not fixed 3') - Added duplicate and remove per block, alongside the existing drag-to-reorder - Verified in browser: labels render correctly, add-block and duplicate both confirmed working end-to-end Widgets section (hero widget): - 'Layout' free-text replaced with a select (Full width / Boxed) instead of typing 'full-bleed'/'boxed' blind - 'Height' free-text replaced with a select (Compact/Medium/Tall/Full screen) mapped to real vh values - New Slides editor: title/subtitle pairs an admin can add/remove: this is the actual multi-slide data the Overlay/Autoplay toggles were referring to with nothing to point at before - HeroWidgetData contract gains slides[]/autoplay; HeroWidgetComponent now renders a real rotator (dots, click-to-jump, autoplay interval) when more than one slide exists - previously autoplay/overlay props existed but there was no slideshow behavior anywhere to control Carousel arrows root cause and fix: - widget-manifest.json offers 'carousel' as a layout option for product-collection/product-carousel widgets, and the admin UI let you select it, but ProductCarouselWidgetComponent always rendered a static CSS grid regardless - there was no carousel implementation to have arrows in the first place - Now renders a real horizontally-scrollable strip with working prev/next buttons (native scrollBy, disabled at each end) when section.layout.strategy === 'carousel'; falls back to the existing grid otherwise - Confirmed src/app/components/items-carousel (a PrimeNG p-carousel) is dead code, not wired into any route or widget - not the source of the reported bug New builder.* i18n keys (en/ru/hy), zero duplicate-key collisions verified via scan
2026-07-19 14:14:29 +04:00
heroLayoutFullBleed: string;
heroLayoutBoxed: string;
heroHeightCompact: string;
heroHeightMedium: string;
heroHeightTall: string;
heroHeightFullScreen: string;
heroSlides: string;
heroSlidesHint: string;
heroSlideTitlePlaceholder: string;
heroSlideSubtitlePlaceholder: string;
addSlide: string;
removeSlide: string;
widgetColumnsDesc: string;
widgetCardsPerRowDesc: string;
widgetFiltersDesc: string;
widgetShowBadgesDesc: string;
widgetShowRatingDesc: string;
widgetShowPriceDesc: string;
widgetJsonDesc: string;
widgetJsonInvalid: string;
wishlistFeatureDesc: string;
compareFeatureDesc: string;
reviewsFeatureDesc: string;
questionsFeatureDesc: string;
commentsFeatureDesc: string;
recommendationsFeatureDesc: string;
recentlyViewedFeatureDesc: string;
searchSuggestionsDesc: string;
searchHistoryDesc: string;
catalogNavigationModeLabel: string;
catalogNavigationModeDesc: string;
catalogNavDefault: string;
catalogNavDefaultDesc: string;
catalogNavLeftCategory: string;
catalogNavLeftCategoryDesc: string;
catalogNavMegaCategory: string;
catalogNavMegaCategoryDesc: string;
catalogNavTopCarousel: string;
catalogNavTopCarouselDesc: string;
fix(builder): WCAG 2.1 AA accessibility fixes RC A11Y-01 audit pass, Builder (project-editor) + content-management static pages editor. Builds on 4ebc15f's composition pass without redoing it. - Skip link: Builder's /edit and /edit/:section routes render outside the storefront app-shell (isAdminRoute() branch has no skip link/landmark, only a bare router-outlet, unlike the storefront's app.html) - added a "skip to content" link targeting a new #builder-main-content landmark on project-editor-page.component, reusing the existing adminShell.skipToContent key and global .skip-link style. Nav landmark already had aria-label (builder.appName) from the prior pass, verified correct. - Save bar: added role="status"/aria-live="polite" to the save/publish status block and role="status" to the draft-restored notice so save/publish state changes and draft recovery are announced to screen readers (previously silent DOM updates). - Media picker (shared, used by both Builder and static-pages editor): upload error message had no aria-live wiring - added role="alert". - HTML editor (marketplace-html-editor): the contenteditable rich-text surface had no accessible role/name - added role="textbox", aria-multiline="true", aria-label. - Drag-and-drop keyboard fallback (WCAG 2.1.1): homepage-section's block list and footer-section's column list + per-column link list use Angular CDK drag-drop (cdkDrag/cdkDropList), which has no built-in keyboard reordering. Added move-up/move-down icon buttons (disabled at the first/last boundary), matching the existing pattern already used by widgets-section and navigation-section. - Color picker: the swatch <input type="color"> had no accessible name (only the paired text input was labelled via app-form-field) - added explicit ariaLabel bindings to all 8 color-picker instances in theme-section. - Languages: the new-locale code input relied on a placeholder ("de") as its only accessible name - added ariaLabel + new builder.newLanguageLabel i18n key (en/ru/hy). - Undefined CSS var --color-primary (never defined anywhere, silently used its hardcoded hex fallback and never responded to tenant theming - same recurring bug class as 4ebc15f) - remapped to the real --primary-color token in marketplace-html-editor, homepage-section, and section.shared (7 usages). - role="alert" added to all 11 validation-error <p class="editor-error"> occurrences across footer/homepage/languages/navigation/preview/widgets sections and the static-pages editor, so field/section validation messages are announced. - scope="col" added to preview-section's change-summary table headers. Flagged, not fixed (design-system decisions, matching the storefront pass's precedent): - Save bar's --warning-color/--error-color/--info-color text fail WCAG AA 4.5:1 in some themes - same genuine brand semantic colors flagged (not fixed) in fb1afb7's storefront pass; needs a deliberate token decision, not a Builder-specific issue. - locale-tabs (app-locale-tabs, shared) has role="tablist"/"tab" and aria-selected but no roving-tabindex/arrow-key navigation - matches the same partial-tablist pattern already accepted for product-tabs in the storefront pass; all tabs remain natively Tab-focusable, so this meets 4.1.2/2.1.1 without the full ARIA authoring-practice pattern. Verified: npx tsc --noEmit clean; npm run build green (only the pre-existing bundle-budget warning, unrelated to this pass). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-24 09:01:38 +04:00
newLanguageLabel: string;
newLanguageDesc: string;
languageAlreadyAdded: string;
languagesTabDesc: string;
linkLabelDesc: string;
linkUrlDesc: string;
linkVisibleDesc: string;
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 <noreply@anthropic.com>
2026-07-18 09:43:03 +04:00
appName: string;
backToDashboard: string;
languagesSummaryDesc: string;
manageLanguages: string;
htmlToolBold: string;
htmlToolItalic: string;
htmlToolUnderline: string;
htmlToolHeading: string;
htmlToolSubheading: string;
htmlToolBulletList: string;
htmlToolNumberedList: string;
htmlToolLink: string;
htmlToolImage: string;
htmlToolTable: string;
htmlToolDivider: string;
htmlToolCodeBlock: string;
htmlToolEmbed: string;
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 <noreply@anthropic.com>
2026-07-18 09:43:03 +04:00
breadcrumbRoot: string;
statusComplete: string;
statusInProgress: string;
statusNotStarted: string;
statusUnknown: string;
draftBadge: string;
publishedBadge: string;
modifiedBadge: string;
helpToggleShow: string;
helpToggleHide: string;
helpWhatIsThis: string;
helpWhySkip: string;
helpWhereVisible: string;
helpWhatIfSkip: string;
helpWhenReturn: string;
openSidebar: string;
closeSidebar: string;
overviewTitle: string;
overviewSubtitle: string;
overviewReadinessLabel: string;
overviewReadinessHint: string;
overviewNextStepLabel: string;
overviewNextStepFallback: string;
overviewQuickLinksTitle: string;
overviewSectionsTitle: string;
overviewOpenSection: string;
overviewReadinessTitle: string;
readinessLogoUploaded: string;
readinessHomepageConfigured: string;
readinessThemeConfigured: string;
readinessLanguagesConfigured: string;
readinessContentPagesAdded: string;
readinessPreviewReviewed: string;
readinessPublished: string;
readinessCategoriesExist: string;
readinessProductsExist: string;
groupMarketplaceLabel: string;
groupMarketplaceDescription: string;
groupMarketplacePurpose: string;
groupMarketplaceWhere: string;
groupMarketplaceSkip: string;
groupBrandingLabel: string;
groupBrandingDescription: string;
groupBrandingPurpose: string;
groupBrandingWhere: string;
groupBrandingSkip: string;
groupHomepageLabel: string;
groupHomepageDescription: string;
groupHomepagePurpose: string;
groupHomepageWhere: string;
groupHomepageSkip: string;
groupContentLabel: string;
groupContentDescription: string;
groupContentPurpose: string;
groupContentWhere: string;
groupContentSkip: string;
groupLanguagesLabel: string;
groupLanguagesDescription: string;
groupLanguagesPurpose: string;
groupLanguagesWhere: string;
groupLanguagesSkip: string;
groupFeaturesLabel: string;
groupFeaturesDescription: string;
groupFeaturesPurpose: string;
groupFeaturesWhere: string;
groupFeaturesSkip: string;
groupNavigationLabel: string;
groupNavigationDescription: string;
groupNavigationPurpose: string;
groupNavigationWhere: string;
groupNavigationSkip: string;
groupPreviewLabel: string;
groupPreviewDescription: string;
groupPreviewPurpose: string;
groupPreviewWhere: string;
groupPreviewSkip: string;
feat(builder): implement professional brand management experience New BrandOverviewComponent, mounted at the top of the existing Branding section page (no route/schema/business-logic changes): - Completion ring + recommended next step + last-modified timestamp, computed from real facade signals (branding.logoUrl/faviconUrl/ socialImageUrl, theme.palette, theme.typography, lastSavedAt) - nothing fabricated. - Brand Health checklist (6 items: logo, favicon, colors, typography, social image, accessibility) - icon+text, never color alone. - Color palette preview: 10 swatches from the real ThemePaletteConfig (primary/secondary/accent/success/warning/danger/backgrounds/text/ border), each with a readable label. - Real WCAG contrast check (contrast.util.ts, relative-luminance formula) between configured text and background colors - shows an inline warning when below 4.5:1, never blocks publishing. - Typography live preview using the configured heading/body font families and base size. - Social share preview card (Open Graph-style) using the existing socialImageUrl + seo.default.title/description, with an explicit empty state when no image is set yet. Scope cut from the full brief given this session's cost already well over budget entering this sprint - see Known limitations in the final report (no multi-variant logo/favicon management, no live responsive device preview, no new media library/asset picker; all reuse the existing single-logo/single-favicon fields and image-field upload component as-is). Could not verify live in-browser this sprint: port 4200 is held by another chat's dev server. Verified via `tsc --noEmit` (clean) and manual template/binding review only; one binding (`--pct` custom- property style binding) was replaced with a plain computed string to remove an unverifiable risk rather than ship it unverified. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 10:13:35 +04:00
brandOverviewTitle: string;
brandOverviewSubtitle: string;
brandOverviewComplete: string;
brandLastModified: string;
brandFaviconUploaded: string;
brandColorsSelected: string;
brandTypographyConfigured: string;
brandSocialImageUploaded: string;
brandAccessibilityPassed: string;
brandColorsPreviewTitle: string;
brandTypographyPreviewTitle: string;
brandSocialPreviewTitle: string;
brandTypeSampleHeading: string;
brandTypeSampleBody: string;
brandContrastWarning: string;
brandSocialEmpty: string;
brandAccentColor: string;
brandBorderColor: string;
homepageOverviewTitle: string;
homepageOverviewSubtitle: string;
homepageOverviewComplete: string;
homepageActiveSections: string;
homepageDisabledSections: string;
homepageHealthHero: string;
homepageHealthCategories: string;
homepageHealthProducts: string;
homepageHealthPromotion: string;
homepageHealthNewsletter: string;
homepageHealthAnySections: string;
widgetTypeHero: string;
widgetTypeCategories: string;
widgetTypeProducts: string;
widgetHidden: string;
widgetVisible: string;
widgetMoveUp: string;
widgetMoveDown: string;
widgetDuplicate: string;
widgetRemove: string;
widgetRemoveConfirm: string;
widgetAdvancedSettings: string;
widgetsEmptyTitle: string;
widgetsEmptyDesc: string;
homepageEmptyTitle: string;
homepageEmptyDesc: string;
feat(builder): visual homepage blocks, merchant-language widget settings, real carousel arrows Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> P0 user feedback: homepage builder showed raw section.id like 'section-hero'/'section-categories'; hero widget exposed 'full-bleed'/'boxed' and raw px/vh as free text with no explanation; Overlay/Autoplay toggles made no sense without a slides concept; product carousel widgets rendered arrows nowhere near a working carousel. Homepage section (sections list -> visual blocks): - Replaced raw section.id display with a merchant-facing block catalog (icon + name + one-line explanation) for hero/categories/featured-products/product-carousel/recently-viewed/banner/partners/custom-html - Added block catalog picker to append new blocks (was fixed at whatever the seed data had - task asked 'what if we add manually? not fixed 3') - Added duplicate and remove per block, alongside the existing drag-to-reorder - Verified in browser: labels render correctly, add-block and duplicate both confirmed working end-to-end Widgets section (hero widget): - 'Layout' free-text replaced with a select (Full width / Boxed) instead of typing 'full-bleed'/'boxed' blind - 'Height' free-text replaced with a select (Compact/Medium/Tall/Full screen) mapped to real vh values - New Slides editor: title/subtitle pairs an admin can add/remove: this is the actual multi-slide data the Overlay/Autoplay toggles were referring to with nothing to point at before - HeroWidgetData contract gains slides[]/autoplay; HeroWidgetComponent now renders a real rotator (dots, click-to-jump, autoplay interval) when more than one slide exists - previously autoplay/overlay props existed but there was no slideshow behavior anywhere to control Carousel arrows root cause and fix: - widget-manifest.json offers 'carousel' as a layout option for product-collection/product-carousel widgets, and the admin UI let you select it, but ProductCarouselWidgetComponent always rendered a static CSS grid regardless - there was no carousel implementation to have arrows in the first place - Now renders a real horizontally-scrollable strip with working prev/next buttons (native scrollBy, disabled at each end) when section.layout.strategy === 'carousel'; falls back to the existing grid otherwise - Confirmed src/app/components/items-carousel (a PrimeNG p-carousel) is dead code, not wired into any route or widget - not the source of the reported bug New builder.* i18n keys (en/ru/hy), zero duplicate-key collisions verified via scan
2026-07-19 14:14:29 +04:00
homepageBlocksHint: string;
addBlockHint: string;
dragToReorder: string;
livePreviewTitle: string;
livePreviewHint: string;
livePreviewEmpty: string;
livePreviewButtonLabel: string;
usedByLabel: string;
usedByHeader: string;
usedByFooter: string;
usedBySeo: string;
usedByButtons: string;
usedByLinks: string;
usedByBadges: string;
usedByPageBackground: string;
resetField: string;
propertySearchLabel: string;
propertySearchPlaceholder: string;
propertySearchResultsLabel: string;
propertySearchNoResults: string;
unsavedChangesPanelTitle: string;
navigationHeaderEmptyTitle: string;
navigationHeaderEmptyDesc: string;
navigationFooterEmptyTitle: string;
navigationFooterEmptyDesc: string;
feat(builder): visual homepage blocks, merchant-language widget settings, real carousel arrows Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> P0 user feedback: homepage builder showed raw section.id like 'section-hero'/'section-categories'; hero widget exposed 'full-bleed'/'boxed' and raw px/vh as free text with no explanation; Overlay/Autoplay toggles made no sense without a slides concept; product carousel widgets rendered arrows nowhere near a working carousel. Homepage section (sections list -> visual blocks): - Replaced raw section.id display with a merchant-facing block catalog (icon + name + one-line explanation) for hero/categories/featured-products/product-carousel/recently-viewed/banner/partners/custom-html - Added block catalog picker to append new blocks (was fixed at whatever the seed data had - task asked 'what if we add manually? not fixed 3') - Added duplicate and remove per block, alongside the existing drag-to-reorder - Verified in browser: labels render correctly, add-block and duplicate both confirmed working end-to-end Widgets section (hero widget): - 'Layout' free-text replaced with a select (Full width / Boxed) instead of typing 'full-bleed'/'boxed' blind - 'Height' free-text replaced with a select (Compact/Medium/Tall/Full screen) mapped to real vh values - New Slides editor: title/subtitle pairs an admin can add/remove: this is the actual multi-slide data the Overlay/Autoplay toggles were referring to with nothing to point at before - HeroWidgetData contract gains slides[]/autoplay; HeroWidgetComponent now renders a real rotator (dots, click-to-jump, autoplay interval) when more than one slide exists - previously autoplay/overlay props existed but there was no slideshow behavior anywhere to control Carousel arrows root cause and fix: - widget-manifest.json offers 'carousel' as a layout option for product-collection/product-carousel widgets, and the admin UI let you select it, but ProductCarouselWidgetComponent always rendered a static CSS grid regardless - there was no carousel implementation to have arrows in the first place - Now renders a real horizontally-scrollable strip with working prev/next buttons (native scrollBy, disabled at each end) when section.layout.strategy === 'carousel'; falls back to the existing grid otherwise - Confirmed src/app/components/items-carousel (a PrimeNG p-carousel) is dead code, not wired into any route or widget - not the source of the reported bug New builder.* i18n keys (en/ru/hy), zero duplicate-key collisions verified via scan
2026-07-19 14:14:29 +04:00
blockRemoveConfirm: string;
blockHero: string;
blockHeroDesc: string;
blockCategories: string;
blockCategoriesDesc: string;
blockFeaturedProducts: string;
blockFeaturedProductsDesc: string;
blockProductCarousel: string;
blockProductCarouselDesc: string;
blockRecentlyViewed: string;
blockRecentlyViewedDesc: string;
blockBanner: string;
blockBannerDesc: string;
blockPartners: string;
blockPartnersDesc: string;
blockCustomHtml: string;
blockCustomHtmlDesc: string;
};
dashboard: {
title: string;
subtitle: string;
cardMarketplaceStatus: string;
cardProjectName: string;
cardCurrentTheme: string;
cardLanguages: string;
cardCategoriesCount: string;
cardProductsCount: string;
cardOrders: string;
cardRevenue: string;
cardLastPublish: string;
cardLastDraftSave: string;
cardBootstrapVersion: string;
cardActiveLayout: string;
cardEnabledWidgets: string;
stateLoading: string;
stateEmpty: string;
stateError: string;
statePendingBackend: string;
never: string;
quickActionsTitle: string;
actionEditProject: string;
actionCategories: string;
actionProducts: string;
actionStaticPages: string;
actionTransactions: string;
actionOrders: string;
actionMediaLibrary: string;
actionUsers: string;
actionMonitoring: string;
actionAnalytics: string;
actionPreviewMarketplace: string;
activityTitle: string;
activityEmpty: string;
activityDraftSaved: string;
activityPublished: string;
healthTitle: string;
healthAllClear: string;
healthBootstrapValid: string;
healthConfigurationValid: string;
healthMissingTranslations: string;
healthInvalidColors: string;
healthInvalidWidgetReferences: string;
healthInvalidLayouts: string;
comingSoonTitle: string;
comingSoonDescription: string;
backToDashboard: string;
feat(admin): redesign dashboard into professional SaaS homepage Replaced the placeholder dashboard with a real business homepage built on 6 new reusable widget components (DashboardSection, DashboardCard, DashboardMetric, DashboardStatusRow, DashboardTimeline, DashboardShortcutCard), all wired through shared app-card/app-skeleton/ app-empty-state. Sections: Welcome (tenant, env badge, current user, last publish/save - all real facade signals, never blank), Quick Actions (large cards: add product, create category, open builder, edit homepage, media, orders), Draft Status (real dirty/modifiedFields/publish/discard from ProjectEditorFacade), Marketplace Health (9 checks - config, product/ category counts, missing translations, draft, static-pages-unpublished, homepage/theme configured, all real; images-without-alt shown as 'not tracked yet' rather than fabricated), Recent Activity (existing localStorage-backed history service, loading/empty states), Useful Shortcuts, Documentation (honest coming-soon list, no dead links). 12-column responsive grid: 3-across cards on desktop, 2-column on tablet, single column on mobile, no horizontal scroll. Keyboard/focus/ ARIA per shortcut card and status row; health status never conveyed by color alone (icon + text every time). AdminDashboardHealthCheck (boolean 'healthy' shape) and its facade signal are untouched - AdminMonitoringPageComponent also consumes them. New richer status data lives in a separate homeHealthChecks signal/ AdminDashboardHomeHealthCheck type instead of widening the shared one. Added ~50 new dashboard.* / kept existing i18n strings across ru/en/hy; no raw keys. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-18 08:59:29 +04:00
welcomeEyebrow: string;
welcomeFallbackTenant: string;
envProduction: string;
envDevelopment: string;
factCurrentUser: string;
factTenant: string;
quickActionsDescription: string;
actionAddProduct: string;
actionAddProductDescription: string;
actionCreateCategory: string;
actionCreateCategoryDescription: string;
actionEditProjectDescription: string;
actionEditHomepage: string;
actionEditHomepageDescription: string;
actionMediaLibraryDescription: string;
actionOrdersDescription: string;
draftStatusTitle: string;
draftStatusHasChanges: string;
draftStatusAllPublished: string;
draftStatusMoreFields: string;
draftOpenBuilder: string;
draftPublish: string;
draftDiscard: string;
healthProductsCount: string;
healthCategoriesCount: string;
healthDraftExists: string;
healthImagesWithoutAlt: string;
healthStaticPagesUnpublished: string;
healthHomepageConfigured: string;
healthThemeConfigured: string;
statusHealthy: string;
statusAttention: string;
statusUnhealthy: string;
statusUnknown: string;
activityEmptyHint: string;
activityUnavailable: string;
activityUnavailableHint: string;
activityErrorHint: string;
shortcutsTitle: string;
shortcutsDescription: string;
shortcutMarketplaceBuilder: string;
shortcutSettings: string;
shortcutContent: string;
docTitle: string;
docDocumentation: string;
docKeyboardShortcuts: string;
docReportIssue: string;
docReleaseNotes: string;
};
2026-07-10 13:52:01 +04:00
staticPages: {
notFound: string;
backHome: string;
duplicateSlug: string;
emptyTitle: string;
feat(static-pages): CRUD completion + search/filter/bulk actions Milestone 2 of the Static Pages Module sprint. - StaticPagesEditorComponent: duplicate page, confirm-before-delete/bulk- delete (matches the resetDraft confirm pattern), route/enabled/customTemplate/ media(hero/thumbnail/gallery) fields wired into the card, per-page publish/ unpublish action, status + duplicate-route/invalid-html/invalid-seo badges. - Search (id/slug/route/title across all locales), filter by status (draft/published) and by locale (hides pages missing a translation for the selected locale) - all local computed() filters, no new service. - Bulk selection (per-row + select-all-visible checkboxes) with bulk delete/ enable/disable/publish/unpublish, one updateBootstrap() call each. - Correctness note: introduced `allPages` (unfiltered) vs `pages` (filtered view) computeds. Every mutation (create/duplicate/delete/move/bulk) reads from allPages(), never the filtered pages() - reading from the filtered view would have silently deleted whatever an active search/filter hid on the next persist(). Documented inline on persist() as a guardrail for future edits. - Fixed a template compile error found by the build gate: Angular templates don't support inline arrow functions in binding expressions ((ngModelChange)="...map(v => v.trim())..." failed to parse) - moved the gallery CSV-parsing into a component method (updateGallery). - SEO robots field added to the page card (validated against a known-token set from M1). - i18n: staticPages.* extended (search/filter/bulk/route/enabled/status/ media/robots/disabled labels) across the interface + en/ru/hy. Gate: tsc --noEmit, npm test (57/57), arch:check, build all green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 09:55:21 +04:00
duplicateRoute: string;
invalidHtml: string;
invalidSeo: string;
searchPlaceholder: string;
filterAll: string;
filterAllLocales: string;
confirmDeletePage: string;
confirmBulkDelete: string;
duplicatePage: string;
selectAll: string;
selectedCount: string;
bulkDelete: string;
bulkEnable: string;
bulkDisable: string;
bulkPublishAction: string;
bulkUnpublish: string;
routeLabel: string;
enabledLabel: string;
statusLabel: string;
publishPageAction: string;
unpublishPageAction: string;
heroImageLabel: string;
thumbnailLabel: string;
galleryLabel: string;
customTemplateLabel: string;
seoRobotsLabel: string;
disabledBadge: string;
previewDesktop: string;
previewTablet: string;
previewMobile: string;
previewToggle: string;
2026-07-10 13:52:01 +04:00
};
contentManagement: {
publishedPages: string;
draftPages: string;
missingLegalPages: string;
seoHealth: string;
lastEdited: string;
lastEditedNever: string;
completionLabel: string;
recommendedNext: string;
recommendAddTitles: string;
recommendFixSeo: string;
recommendPublish: string;
recommendNone: string;
openAction: string;
backToPages: string;
groupContent: string;
groupSeo: string;
groupSharing: string;
groupAdvanced: string;
groupAdvancedHtml: string;
pageContentLabel: string;
pageContentDesc: string;
seoExplainDesc: string;
seoTitleHelp: string;
seoDescriptionHelp: string;
seoCanonicalHelp: string;
seoRobotsHelp: string;
sharingExplain: string;
mediaSelect: string;
mediaReplace: string;
mediaRemove: string;
mediaAlt: string;
mediaCaption: string;
emptyStateGuideTitle: string;
emptyStateGuideBody: string;
seoStatusGood: string;
seoStatusPartial: string;
seoStatusWarning: string;
seoStatusMissing: string;
needsAttention: string;
legal: {
about: { label: string; why: string };
contacts: { label: string; why: string };
privacy: { label: string; why: string };
terms: { label: string; why: string };
cookies: { label: string; why: string };
delivery: { label: string; why: string };
returns: { label: string; why: string };
faq: { label: string; why: string };
};
};
widgets: {
unavailable: string;
};
2026-02-26 23:09:20 +04:00
carousel: {
loading: string;
addToCart: string;
};
common: {
retry: string;
loading: string;
remove: string;
fix(backoffice): add error+retry states to Users, Monitoring, Analytics, Reports Phase 8 (RC-01): these 4 list/dashboard pages had no error-state handling on their primary data-load subscriptions — on a gateway error, `loading` was either never reset (Users, Monitoring, Analytics: genuine infinite- spinner risk, nested subscribe chain in Analytics never resolved on failure) or there was no loading/empty/error handling at all (Reports queue: raw table with zero skeleton or fallback). - admin-users.facade.ts, admin-monitoring.facade.ts: add `error` signal, error callback on the primary load subscribe so `loading` always resolves. - admin-analytics.facade.ts: add `error` signal; every level of the 4-deep nested gateway subscribe chain (orders -> products -> categories -> reviews) now has an error handler that resolves loading instead of leaving it stuck true. - admin-moderation.facade.ts: add `reportsLoading`/`reportsError` signals (reports list had none previously). - Templates: reuse existing `app-skeleton`/`app-empty-state`/`app-button` primitives for the new error branch, `common.retry` label, two new generic `common.errorTitle`/`common.errorDescription` i18n keys added to en/ru/hy (reused across all 4 fixes instead of one-off per-page copy). Verified: tsc --noEmit clean, `npm run build` green (pre-existing bundle- budget warning only, unrelated). Live-checked Home (375px) and Backoffice Products (1024px) — no console errors, tables/cards render without overflow. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-25 21:31:30 +04:00
errorTitle: string;
errorDescription: string;
ratingLabel: string;
discountLabel: string;
slideLabel: string;
slidesLabel: string;
previousProducts: string;
nextProducts: string;
previousSlide: string;
nextSlide: string;
closeDialog: string;
dismiss: string;
qrCode: string;
bankCardPayment: string;
guest: string;
cancel: string;
confirm: string;
2026-02-26 23:09:20 +04:00
};
2026-02-28 17:18:24 +04:00
location: {
allRegions: string;
chooseRegion: string;
detectAuto: string;
};
auth: {
loginRequired: string;
loginDescription: string;
checking: string;
loginWithTelegram: string;
orScanQr: string;
loginNote: string;
2026-03-25 15:32:50 +04:00
qrExpired: string;
2026-06-01 00:47:26 +04:00
qrError: string;
2026-02-28 17:18:24 +04:00
};
ux: {
items: string;
wishlistTitle: string;
wishlistEmptyTitle: string;
wishlistEmptyDescription: string;
clearWishlist: string;
wishlistCleared: string;
compareTitle: string;
compareEmptyTitle: string;
compareEmptyDescription: string;
clearCompare: string;
removeFromCompare: string;
hideIdentical: string;
highlightDifferences: string;
clearRecentlyViewed: string;
recentlyViewedEmpty: string;
saveSearch: string;
goToCatalog: string;
2026-07-09 01:40:22 +04:00
wishlistAdded: string;
wishlistRemoved: string;
compareAdded: string;
compareRemoved: string;
compareLimitReached: string;
productShared: string;
productLinkCopied: string;
sharingUnsupported: string;
addedToCart: string;
2026-07-09 01:40:22 +04:00
enterQueryBeforeSave: string;
savedSearchNamed: string;
recentlyViewedTitle: string;
compareAttribute: string;
comparePrice: string;
compareRating: string;
compareStock: string;
compareDiscount: string;
compareColor: string;
compareSize: string;
compareUnknown: string;
};
2026-07-10 13:34:25 +04:00
diagnostics: {
title: string;
disabledTitle: string;
disabledDescription: string;
generatedAt: string;
healthScore: string;
summary: string;
passedChecks: string;
warnings: string;
errors: string;
critical: string;
healthChecks: string;
results: string;
noIssues: string;
ok: string;
failed: string;
affectedComponent: string;
suggestedResolution: string;
severity: {
info: string;
warning: string;
error: string;
critical: string;
};
checks: {
bootstrapLoaded: string;
tenantResolved: string;
runtimeInitialized: string;
themeLoaded: string;
widgetManifestLoaded: string;
sectionEngineInitialized: string;
configurationEngineInitialized: string;
translationResourcesAvailable: string;
requiredAssetsAvailable: string;
};
bootstrapMissingTitle: string;
bootstrapMissingDescription: string;
bootstrapMissingResolution: string;
requiredPropertyMissingTitle: string;
requiredPropertyMissingDescription: string;
requiredPropertyMissingResolution: string;
unknownWidgetTypeTitle: string;
unknownWidgetTypeDescription: string;
unknownWidgetTypeResolution: string;
widgetSettingsSchemaMismatchTitle: string;
widgetSettingsSchemaMismatchDescription: string;
widgetSettingsSchemaMismatchResolution: string;
2026-07-10 13:34:25 +04:00
duplicateIdTitle: string;
duplicatePageIdDescription: string;
duplicateSectionIdDescription: string;
duplicateWidgetIdDescription: string;
duplicateIdResolution: string;
unknownLayoutTitle: string;
unknownLayoutDescription: string;
unknownLayoutResolution: string;
invalidFeatureFlagTitle: string;
invalidFeatureFlagDescription: string;
invalidFeatureFlagResolution: string;
brokenPageDefinitionTitle: string;
brokenPageDefinitionDescription: string;
brokenPageDefinitionResolution: string;
invalidNavigationTargetTitle: string;
invalidNavigationTargetDescription: string;
invalidNavigationTargetResolution: string;
missingTranslationTitle: string;
missingTranslationDescription: string;
missingTranslationResolution: string;
missingMediaTitle: string;
missingMediaDescription: string;
missingMediaResolution: string;
runtimeNotInitializedTitle: string;
runtimeNotInitializedDescription: string;
runtimeNotInitializedResolution: string;
configFallbackUsageTitle: string;
configFallbackUsageDescription: string;
configFallbackUsageResolution: string;
missingDatasourceTitle: string;
missingDatasourceDescription: string;
missingDatasourceResolution: string;
widgetRenderFailureTitle: string;
widgetRenderFailureDescription: string;
widgetRenderFailureResolution: string;
brokenRouteTitle: string;
brokenRouteDescription: string;
brokenRouteResolution: string;
imageLoadFailedTitle: string;
imageLoadFailedDescription: string;
imageLoadFailedResolution: string;
optionalDataMissingTitle: string;
optionalDataMissingDescription: string;
optionalDataMissingResolution: string;
};
adminModeration: {
search: string;
selectAllRows: string;
itemsCount: string;
allStatuses: string;
allRatings: string;
rating: string;
customer: string;
product: string;
reviewText: string;
photos: string;
workflow: string;
approve: string;
reject: string;
markSpam: string;
hide: string;
restore: string;
pin: string;
unpin: string;
feature: string;
unfeature: string;
featureDisabledHint: string;
moderatorNotes: string;
notAvailable: string;
changeStatus: string;
hideSelected: string;
deleteSelected: string;
confirmBulkDelete: string;
reportsQueue: string;
reportsColumn: string;
reportTarget: string;
reportType: string;
reportReason: string;
resolve: string;
dismiss: string;
reportsEmptyTitle: string;
reportsEmptyDescription: string;
reportedCount: string;
averageRating: string;
moderationHealth: string;
emptyTitle: string;
emptyDescription: string;
emptyGuide: string;
healthRating: string;
healthText: string;
healthMedia: string;
healthModeration: string;
healthReportStatus: string;
healthVisibility: string;
health: string;
column_product: string;
column_rating: string;
column_status: string;
column_reports: string;
column_created: string;
status: {
pending: string;
approved: string;
rejected: string;
spam: string;
};
timelineEvent: {
submitted: string;
statusChanged: string;
restored: string;
hidden: string;
};
actor: {
admin: string;
customer: string;
};
targetType: {
product: string;
review: string;
customer: string;
category: string;
unknown: string;
};
reportStatus: {
open: string;
resolved: string;
dismissed: string;
};
};
adminOrders: {
bulkDeleteTitle: string;
confirmBulkDelete: string;
back: string;
search: string;
export: string;
selectAllRows: string;
selectRow: string;
view: string;
orderNumber: string;
customer: string;
payment: string;
delivery: string;
trackingNumber: string;
createdAt: string;
items: string;
timeline: string;
timelineEvent: {
created: string;
statusChanged: string;
refundRequested: string;
};
notes: string;
internalNotes: string;
addNote: string;
changeStatus: string;
applyStatus: string;
archiveSelected: string;
printSelected: string;
printInvoice: string;
requestRefund: string;
cancelOrder: string;
confirmCancel: string;
confirmRefund: string;
emptyTitle: string;
emptyDescription: string;
column_customer: string;
column_status: string;
column_payment: string;
column_total: string;
column_created: string;
status: {
all: string;
pending: string;
processing: string;
shipped: string;
delivered: string;
cancelled: string;
refunded: string;
};
paymentStatus: {
unpaid: string;
paid: string;
refund_requested: string;
refunded: string;
};
itemsCount: string;
ordersToday: string;
paidCount: string;
customersCount: string;
returningCustomers: string;
averageOrder: string;
recentActivity: string;
noRecentActivity: string;
alertStuckPending: string;
alertRefundRequested: string;
};
adminCustomers: {
back: string;
search: string;
name: string;
email: string;
phone: string;
orderCount: string;
lifetimeValue: string;
returning: string;
profile: string;
statistics: string;
firstOrder: string;
lastOrder: string;
addresses: string;
notes: string;
notesUnavailable: string;
orders: string;
activity: string;
emptyTitle: string;
emptyDescription: string;
};
mediaLibrary: {
title: string;
upload: string;
uploading: string;
searchPlaceholder: string;
delete: string;
deleteConfirmTitle: string;
deleteConfirmBody: string;
cancel: string;
confirm: string;
emptyTitle: string;
emptyDescription: string;
allFolders: string;
newFolder: string;
editTags: string;
totalAssets: string;
logos: string;
unused: string;
storageUsed: string;
altCoverage: string;
allTypes: string;
typeImage: string;
typeSvg: string;
typePdf: string;
sortRecent: string;
sortName: string;
sortSize: string;
viewMode: string;
viewGrid: string;
viewList: string;
dropHint: string;
cancelUpload: string;
retry: string;
errorTooLarge: string;
errorUnsupportedType: string;
errorGeneric: string;
selectedCount: string;
download: string;
exportMetadata: string;
bulkDelete: string;
bulkDeleteConfirm: string;
clearSelection: string;
guideCopy: string;
missingAlt: string;
usageCount: string;
detailsTitle: string;
filename: string;
format: string;
fileSize: string;
dimensions: string;
uploadDate: string;
lastUsed: string;
usageCountLabel: string;
usedIn: string;
notUsed: string;
unknownValue: string;
altText: string;
altTextHelp: string;
decorative: string;
missingAltWarning: string;
caption: string;
description: string;
usage: {
brand: string;
theme: string;
header: string;
footer: string;
staticPage: string;
homepage: string;
catalog: string;
productPage: string;
widget: string;
company: string;
seo: string;
navigation: string;
other: string;
};
};
// Sprint 28: only the new empty-state copy this sprint's skeleton/empty-
// state consistency fix introduces - NOT the full adminProducts/
// adminUsers/adminMonitoring/adminAnalytics translation surface, which is
// still missing entirely (see docs/KNOWN-ISSUES.md, deferred to Sprint 29).
fix(static-pages): backfill enabled/status in export, fix missing i18n key Independent review pass over the Static Pages Module sprint (M1-M7), including live browser E2E per the task's own verification checklist. - ProjectEditorFacade.normalize() now backfills enabled/status on record-format static pages (defaulting missing values to enabled+published, same rule ContentPageService.normalizePage applies for display - mirrored rather than imported, to avoid a project-editor <-> content-management circular dependency since ContentManagementFacade already depends on this facade). Found live: exporting a page that predates this sprint and was never touched/re-saved in the current session produced JSON missing enabled/status entirely - the editor UI and storefront resolver both normalize-on-read so nothing was actually broken live, but Export/Import fidelity should match what the editor shows. Verified fixed live (export now includes "enabled":true,"status":"published" for an untouched legacy page) and via the full gate. - Added the missing adminCategories.chooseImage i18n key (interface + en/ru/hy). Found live: the media-picker "choose image" button rendered as the literal string "adminCategories.chooseImage" - a pre-existing, repo-wide bug (5 templates reference this key; none of the locale files ever defined it) that I propagated into a 3rd/4th/5th... well, 2 new occurrences by copying the existing branding-section/footer-section pattern into static-pages-editor. Fixed the actual defect (missing translation) rather than renaming the key, which would have required touching 2 unrelated admin components outside this sprint's scope. Live-verified this pass: Static Pages editor renders with all new fields; create page works (page count 4->confirmed); device preview toggles desktop/tablet/mobile widths correctly; navigation "Insert page link" creates a real type:'staticPage' nav item end-to-end (confirmed in the exported JSON); export includes all Sprint X+2 fields after the fix; no console errors throughout. Gate: tsc --noEmit, npm test (57/57), arch:check, build all green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 11:27:29 +04:00
// Shared across branding/footer/static-pages/admin-product/admin-category media
// pickers - despite the namespace name, this is a generic "choose image" label,
// not category-specific. Renaming is a separate cleanup outside this sprint's
// scope; the key was previously referenced by 5 templates but never defined
// anywhere, so it rendered as the literal string "adminCategories.chooseImage".
adminCategories: {
chooseImage: string;
replaceImage: string;
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.
2026-07-18 17:04:11 +04:00
search: string;
showDeleted: string;
selectAllRows: string;
selectRow: string;
toggleVisibility: string;
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.
2026-07-18 17:04:11 +04:00
create: string;
edit: string;
title: string;
slug: string;
slugTaken: string;
slugCheckError: string;
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.
2026-07-18 17:04:11 +04:00
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;
confirmBulkDelete: string;
deleteTitle: string;
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.
2026-07-18 17:04:11 +04:00
confirmLeaveUnsaved: string;
deleteBlocked: string;
emptyTitle: string;
emptyDescription: string;
emptyGuide: string;
viewTree: string;
viewCards: string;
expandAll: string;
collapseAll: string;
expandNode: string;
collapseNode: string;
fix(backoffice): WCAG 2.1 AA accessibility fixes RC A11Y-01 audit pass, Backoffice (admin/*) area. Builds on 712a7b4/63c9cee's composition pass (scope="col", skeletons, empty-states) without redoing that work. - Sidebar nav landmark: admin-layout's <nav aria-label> reused the "Dashboard" nav-item translation key as its landmark label, misleadingly announcing the whole sidebar as "Dashboard" - added a dedicated adminShell.sidebarLabel key ("Admin sidebar navigation") in en/ru/hy. Skip link, #admin-content main landmark, Escape handling, and mobile-drawer focus management were already correct - verified, not touched. - Categories tree drag-and-drop keyboard fallback (WCAG 2.1.1): the category tree's native HTML5 DnD (draggable/dragstart/drop) reorders siblings with no keyboard equivalent - existing arrow-key tree navigation only expands/ collapses/selects, never reorders. Added per-row move-up/move-down icon buttons (disabled at sibling boundaries), reusing the existing `reorder` output so the facade's reorder logic is untouched; new adminCategories.moveUp/moveDown keys in en/ru/hy. - Screen-reader loading announcements: skeleton-row loading states across Products, Categories, Customers, Orders, Transactions, Users, Reviews, Monitoring (webhooks/events), and Analytics (summary cards + top products) were purely visual (app-skeleton is aria-hidden by design) with no accessible "loading" text, unlike the storefront/product-details pattern - added role="status"/aria-live="polite"/aria-busy + sr-only text using the existing common.loading key. - Table row headers: added scope="row" to the primary identifying cell (product/category/customer name, order number, transaction order number, user name, review customer, report target, top-products/low-stock product name, webhook endpoint) on 9 tables that only had scope="col". Added matching `tbody th[scope='row'] { font-weight/color/text-align/ vertical-align }` + last-row border resets in each component's own scss so the semantic change doesn't alter visuals (the shared app-table stylesheet styles all <th> as bold/muted by default). Verified via `git show --stat` of fb1afb7/a03260e and `docs/UI-COMPOSITION- REVIEW.md`'s Backoffice sections first, per instructions - confirmed scope="col" coverage already complete, all admin modals already route through the shared app-dialog (focus-trap/Escape/return-focus already correct, nothing to fix), and the bare-<select> filters still carry aria-label per the accepted Sprint 28 decision (not re-migrated to app-select). Flagged, not fixed: - No toast/notification system exists anywhere in this codebase (product/ category save and delete call the gateway with no success/error UI at all, not even a subscribe error handler) - there is nothing to wire aria-live onto without adding a new UI mechanism, which is out of scope for an a11y-only pass. A prerequisite feature-level fix, not an a11y regression. - Dashboard's per-card metric/status-row/timeline skeletons (dashboard- metric, dashboard-status-row, dashboard-timeline) were left without aria-live wiring - wrapping each of the ~10 simultaneous mini-widgets in its own live region would fire a burst of redundant announcements; needs a single page-level "loading dashboard" region instead, a larger change than this surgical pass. - Monitoring's events table and the notifications dropdown (role="menu" with a static empty-state message, aria-haspopup="true") were left as-is - matches the same partial-widget-pattern precedent already accepted for locale-tabs/product-tabs in the storefront and builder passes. - Analytics `lowStockProducts` table's missing loading-skeleton branch (already flagged, not fixed, in the RC-Visual-02 pass) - untouched again here for the same reason. Verified: npx tsc --noEmit clean; npm run build green (only the pre-existing 768.57 kB vs 700 kB initial-bundle budget warning, unrelated to this pass). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-24 09:18:09 +04:00
moveUp: string;
moveDown: string;
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.
2026-07-18 17:04:11 +04:00
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;
navBreadcrumbHint: string;
iconHint: string;
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.
2026-07-18 17:04:11 +04:00
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;
fix(static-pages): backfill enabled/status in export, fix missing i18n key Independent review pass over the Static Pages Module sprint (M1-M7), including live browser E2E per the task's own verification checklist. - ProjectEditorFacade.normalize() now backfills enabled/status on record-format static pages (defaulting missing values to enabled+published, same rule ContentPageService.normalizePage applies for display - mirrored rather than imported, to avoid a project-editor <-> content-management circular dependency since ContentManagementFacade already depends on this facade). Found live: exporting a page that predates this sprint and was never touched/re-saved in the current session produced JSON missing enabled/status entirely - the editor UI and storefront resolver both normalize-on-read so nothing was actually broken live, but Export/Import fidelity should match what the editor shows. Verified fixed live (export now includes "enabled":true,"status":"published" for an untouched legacy page) and via the full gate. - Added the missing adminCategories.chooseImage i18n key (interface + en/ru/hy). Found live: the media-picker "choose image" button rendered as the literal string "adminCategories.chooseImage" - a pre-existing, repo-wide bug (5 templates reference this key; none of the locale files ever defined it) that I propagated into a 3rd/4th/5th... well, 2 new occurrences by copying the existing branding-section/footer-section pattern into static-pages-editor. Fixed the actual defect (missing translation) rather than renaming the key, which would have required touching 2 unrelated admin components outside this sprint's scope. Live-verified this pass: Static Pages editor renders with all new fields; create page works (page count 4->confirmed); device preview toggles desktop/tablet/mobile widths correctly; navigation "Insert page link" creates a real type:'staticPage' nav item end-to-end (confirmed in the exported JSON); export includes all Sprint X+2 fields after the fix; no console errors throughout. Gate: tsc --noEmit, npm test (57/57), arch:check, build all green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-17 11:27:29 +04:00
};
adminProducts: {
fix(admin): products canDeactivate guard, unblock npm, drop dead deps RC-01 Phase 1 mechanical fixes (verified against current repo state, not blindly reapplied from TODO.md): - admin/products create/edit/duplicate now protected by an unsaved- changes guard (adminProductDirtyGuard), mirroring the existing categories pattern. AdminProductsFacade had zero dirty-tracking before this - added a dirty signal, set true on updateDraft(), cleared on load/create/successful save. Added confirmLeaveUnsaved to the adminProducts i18n section (en/ru/hy) - categories already had its own copy of this key, products didn't. - barry-cache bumped ^0.1.0 -> ^0.9.3 (the pinned range no longer resolved on the registry - ETARGET - which had been silently blocking every npm install/uninstall all cycle). - Removed primeng/primeicons (npm uninstall, now unblocked) - the only consumer (items-carousel) was already deleted in RC PERF-01. - Removed core/search/services/search-history.service.ts, a dead 1-line re-export with zero importers (verified: the real implementation is features/search/services/search-history.service.ts, used by search.facade.ts). Left core/search/models/* alone - those ARE live, imported by catalog components. Verified before touching: HeaderConfig.showProfile toggle is already removed from the header-section editor template (TODO.md was stale on this one) - no change needed, will correct the tracking doc separately. tsc --noEmit clean, npm run build green (bundle unchanged, primeng was already tree-shaken out, this just removes the dead dependency declaration itself). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-25 20:04:51 +04:00
confirmLeaveUnsaved: string;
deleteTitle: string;
confirmDelete: string;
confirmBulkDelete: string;
emptyTitle: string;
emptyDescription: string;
emptyGuide: string;
selectAllRows: string;
selectRow: string;
search: string;
category: string;
allCategories: string;
visibility: string;
allVisibility: string;
visible: string;
hidden: string;
stockStatus: string;
allStock: string;
inStock: string;
lowStock: string;
outOfStock: string;
sortTitle: string;
sortPrice: string;
sortPriority: string;
sortStock: string;
sortUpdated: string;
showArchived: string;
infiniteScroll: string;
viewMode: string;
viewTable: string;
viewGrid: string;
density: string;
densityComfortable: string;
densityCompact: string;
columns: string;
column_sku: string;
column_brand: string;
column_price: string;
column_stock: string;
column_visibility: string;
column_updated: string;
create: string;
edit: string;
duplicate: string;
selectedCount: string;
bulkShow: string;
bulkHide: string;
bulkAssignCategory: string;
bulkAssignTags: string;
bulkDuplicateAction: string;
bulkExportAction: string;
bulkDelete: string;
tagsPlaceholder: string;
name: string;
brand: string;
healthColumn: string;
actions: string;
archive: string;
delete: string;
items: string;
loadMore: string;
noImage: string;
slug: string;
barcode: string;
priority: string;
shortDescription: string;
translations: string;
primaryImage: string;
primaryImageHint: string;
gallery: string;
galleryHint: string;
moveLeft: string;
moveRight: string;
videos: string;
discount: string;
currency: string;
stockQuantity: string;
stockQuantityHint: string;
availabilityStatus: string;
availabilityStatusHint: string;
availabilityNote: string;
availabilityNoteHint: string;
reservedNote: string;
relatedProducts: string;
specifications: string;
attributes: string;
addRow: string;
removeRow: string;
rowKey: string;
rowValue: string;
addVariant: string;
variantName: string;
variantsHint: string;
variants: string;
feat(admin): Shopify-style variant attributes matching production data shape Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> P0 user feedback: variants were just free-text name+price, and the user shared the real production payload - a flat array of {color, size, price, currency, remaining} rows, colors as '0x8B4513' hex. - New model: AdminProductVariantAttributeDef (key/label/isColor/values) + AdminProductVariant (attributes: Record<string,string>, sku, image, remaining, prices: {currency,price}[]) - this IS the production shape, grouped by combo with one row per currency instead of flattened, so admins edit one variant card instead of 4 duplicate rows - Attribute manager: add custom attributes (Color, Size, or anything), color attributes get a native color picker + live swatch preview instead of typing hex; other attributes get plain value chips - 'Generate variants' computes the cartesian product of attribute values (Color x Size = 4 combos for 1 color x 4 sizes) and preserves existing sku/price/stock data for combos that still exist after regeneration - Multi-currency pricing per variant (matches prod: same combo priced in RUB/USD/EUR/AMD) with per-currency add/remove - Color hex kept in the exact '0x8B4513' production format (toBackendColor/toCssColor conversion helpers) - Fixed an Angular v21 control-flow parser bug hit while building this: an @if/@else block whose only content is a bare {{ interpolation }} touching the block's closing brace fails to parse (NG5002 'Unclosed block for' cascading from a completely unrelated line) - worked around by keeping interpolation in its own element - Verified end-to-end in browser: added Color (color picker) + Size (S/M/L/XL) attributes, generated 4 variant combos, added all 4 currencies to a variant - matches the shared production JSON exactly
2026-07-19 13:40:51 +04:00
variantAttributes: string;
variantAttributesHint: string;
colorAttribute: string;
removeAttribute: string;
removeValue: string;
pickColor: string;
newValuePlaceholder: string;
addValue: string;
newAttributePlaceholder: string;
addAttribute: string;
generateVariants: string;
variantsList: string;
remaining: string;
variantImage: string;
archived: string;
slugHint: string;
skuHint: string;
generate: string;
seoGenerate: string;
seoGenerateHint: string;
translationsHint: string;
badgesHint: string;
addBadge: string;
removeBadge: string;
customBadgePlaceholder: string;
seoExplain: string;
searchTitle: string;
searchTitleHint: string;
searchDescription: string;
searchDescriptionHint: string;
seoMissingTitle: string;
seoMissingDescription: string;
keywords: string;
featured: string;
recommended: string;
new: string;
bestseller: string;
badges: string;
htmlDescription: string;
customer: string;
reviewsReadonly: string;
noReviews: string;
questionsReadonly: string;
noQuestions: string;
save: string;
groupGeneral: string;
groupMedia: string;
groupPricing: string;
groupInventory: string;
groupCategories: string;
groupAttributes: string;
groupSeo: string;
groupVisibility: string;
groupAdvanced: string;
healthImages: string;
healthSeo: string;
healthPrice: string;
healthCategory: string;
healthDescription: string;
healthInventory: string;
totalProducts: string;
publishedCount: string;
draftsCount: string;
outOfStockCount: string;
hiddenCount: string;
missingImagesCount: string;
missingSeoCount: string;
lowQualityCount: string;
recentlyEdited: string;
recommendedNext: string;
openAction: string;
recommendAddImages: string;
recommendAddSeo: string;
recommendRestock: string;
recommendNone: string;
};
adminUsers: {
emptyTitle: string;
emptyDescription: string;
invitationsEmptyTitle: string;
title: string;
name: string;
email: string;
scope: string;
role: string;
roles: string;
lastLogin: string;
sessions: string;
currentSession: string;
invite: string;
sendInvite: string;
revoke: string;
passwordlessHint: string;
confirmSuspend: string;
suspend: string;
reactivate: string;
scopeValue: {
marketplace: string;
office: string;
};
statusValue: {
active: string;
invited: string;
suspended: string;
};
invitationStatus: {
pending: string;
accepted: string;
expired: string;
revoked: string;
};
roleValue: {
owner: string;
admin: string;
editor: string;
viewer: string;
};
permission: {
all: string;
productsManage: string;
productsView: string;
categoriesManage: string;
ordersManage: string;
ordersView: string;
mediaManage: string;
};
actor: {
admin: string;
};
audit: {
roleChanged: string;
statusChanged: string;
};
};
adminTransactions: {
search: string;
type: string;
method: string;
itemsCount: string;
fraud: string;
flagged: string;
flag: string;
clearFlag: string;
retry: string;
audit: string;
emptyTitle: string;
emptyDescription: string;
status: {
all: string;
pending: string;
success: string;
failed: string;
retried: string;
};
typeValue: {
all: string;
payment: string;
refund: string;
qr_payment: string;
};
methodValue: {
card: string;
qr: string;
cash_on_delivery: string;
};
};
adminMonitoring: {
eventsEmptyTitle: string;
eventsEmptyDescription: string;
health: string;
queues: string;
depth: string;
webhooks: string;
endpoint: string;
event: string;
events: string;
category: string;
level: string;
message: string;
technicalDetails: string;
categoryValue: {
all: string;
audit: string;
security: string;
login: string;
failed_login: string;
api: string;
error: string;
warning: string;
};
queueStatus: {
healthy: string;
degraded: string;
down: string;
};
webhookStatus: {
delivered: string;
failed: string;
pending: string;
};
levelValue: {
info: string;
warning: string;
error: string;
};
systemState: string;
backendConnectivity: string;
connected: string;
loading: string;
draftState: string;
unsavedChanges: string;
noDraft: string;
lastSaved: string;
lastPublished: string;
syncStatus: string;
};
adminReports: {
sales: string;
topProducts: string;
marketplaceHealth: string;
};
adminSettings: {
density: string;
densityExplain: string;
densityCompact: string;
};
adminAnalytics: {
topProductsEmptyTitle: string;
topProductsEmptyDescription: string;
topProducts: string;
print: string;
tabsLabel: string;
tab: {
overview: string;
health: string;
products: string;
customers: string;
search: string;
traffic: string;
recommendations: string;
};
revenue: string;
orders: string;
customers: string;
avgOrderValue: string;
conversion: string;
completionPercent: string;
unknown: string;
salesChart: string;
quantitySold: string;
lowStock: string;
lowStockEmptyTitle: string;
quantity: string;
status: string;
recentActivity: string;
recentActivityEmptyTitle: string;
activityDraftSaved: string;
activityPublished: string;
warnings: string;
topViewed: string;
hiddenProducts: string;
archivedProducts: string;
mostReviewed: string;
worstRated: string;
noReviewedProducts: string;
reviewCount: string;
avgRating: string;
newCustomers: string;
returningCustomers: string;
averageSpend: string;
retention: string;
searchAnalytics: string;
trafficAnalytics: string;
availableAfterBackend: string;
pendingBackend: string;
pendingBackendHint: string;
funnelsHeatmaps: string;
visitors: string;
products: string;
categories: string;
};
adminMarketplaceHealth: {
title: string;
complete: string;
recommendationsTitle: string;
recommendNone: string;
checkImages: string;
checkSeo: string;
checkCategories: string;
checkReviews: string;
checkOrders: string;
checkTranslations: string;
checkHomepage: string;
checkBackend: string;
checkPerformance: string;
recommendImages: string;
recommendImagesCount: string;
recommendSeo: string;
recommendSeoCount: string;
recommendCategory: string;
recommendCategoryCount: string;
recommendEmptyCategories: string;
recommendEmptyCategoriesCount: string;
recommendHomepage: string;
recommendStaticPages: string;
severity: {
info: string;
warning: string;
critical: string;
};
};
adminShell: {
skipToContent: string;
fix(backoffice): WCAG 2.1 AA accessibility fixes RC A11Y-01 audit pass, Backoffice (admin/*) area. Builds on 712a7b4/63c9cee's composition pass (scope="col", skeletons, empty-states) without redoing that work. - Sidebar nav landmark: admin-layout's <nav aria-label> reused the "Dashboard" nav-item translation key as its landmark label, misleadingly announcing the whole sidebar as "Dashboard" - added a dedicated adminShell.sidebarLabel key ("Admin sidebar navigation") in en/ru/hy. Skip link, #admin-content main landmark, Escape handling, and mobile-drawer focus management were already correct - verified, not touched. - Categories tree drag-and-drop keyboard fallback (WCAG 2.1.1): the category tree's native HTML5 DnD (draggable/dragstart/drop) reorders siblings with no keyboard equivalent - existing arrow-key tree navigation only expands/ collapses/selects, never reorders. Added per-row move-up/move-down icon buttons (disabled at sibling boundaries), reusing the existing `reorder` output so the facade's reorder logic is untouched; new adminCategories.moveUp/moveDown keys in en/ru/hy. - Screen-reader loading announcements: skeleton-row loading states across Products, Categories, Customers, Orders, Transactions, Users, Reviews, Monitoring (webhooks/events), and Analytics (summary cards + top products) were purely visual (app-skeleton is aria-hidden by design) with no accessible "loading" text, unlike the storefront/product-details pattern - added role="status"/aria-live="polite"/aria-busy + sr-only text using the existing common.loading key. - Table row headers: added scope="row" to the primary identifying cell (product/category/customer name, order number, transaction order number, user name, review customer, report target, top-products/low-stock product name, webhook endpoint) on 9 tables that only had scope="col". Added matching `tbody th[scope='row'] { font-weight/color/text-align/ vertical-align }` + last-row border resets in each component's own scss so the semantic change doesn't alter visuals (the shared app-table stylesheet styles all <th> as bold/muted by default). Verified via `git show --stat` of fb1afb7/a03260e and `docs/UI-COMPOSITION- REVIEW.md`'s Backoffice sections first, per instructions - confirmed scope="col" coverage already complete, all admin modals already route through the shared app-dialog (focus-trap/Escape/return-focus already correct, nothing to fix), and the bare-<select> filters still carry aria-label per the accepted Sprint 28 decision (not re-migrated to app-select). Flagged, not fixed: - No toast/notification system exists anywhere in this codebase (product/ category save and delete call the gateway with no success/error UI at all, not even a subscribe error handler) - there is nothing to wire aria-live onto without adding a new UI mechanism, which is out of scope for an a11y-only pass. A prerequisite feature-level fix, not an a11y regression. - Dashboard's per-card metric/status-row/timeline skeletons (dashboard- metric, dashboard-status-row, dashboard-timeline) were left without aria-live wiring - wrapping each of the ~10 simultaneous mini-widgets in its own live region would fire a burst of redundant announcements; needs a single page-level "loading dashboard" region instead, a larger change than this surgical pass. - Monitoring's events table and the notifications dropdown (role="menu" with a static empty-state message, aria-haspopup="true") were left as-is - matches the same partial-widget-pattern precedent already accepted for locale-tabs/product-tabs in the storefront and builder passes. - Analytics `lowStockProducts` table's missing loading-skeleton branch (already flagged, not fixed, in the RC-Visual-02 pass) - untouched again here for the same reason. Verified: npx tsc --noEmit clean; npm run build green (only the pre-existing 768.57 kB vs 700 kB initial-bundle budget warning, unrelated to this pass). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-24 09:18:09 +04:00
sidebarLabel: string;
openSidebar: string;
closeSidebar: string;
collapseSidebar: string;
expandSidebar: string;
nav: {
dashboard: string;
catalogGroup: string;
products: string;
categories: string;
orders: string;
customers: string;
transactions: string;
reviews: string;
moderation: string;
reports: string;
feat(admin): Seller Management Phase 1 UI - Partners section, empty state, request/learn-more dialogs No backend, no CRUD, no API, no business logic - production-quality UI only, built entirely from existing shared components (app-dialog, app-empty-state, app-button, app-form-field, app-input, app-icon, app-badge). Gated per ADR-011: reads modules.sellerManagement.enabled from bootstrap (always false today, no backend sets it) rather than hardcoding disabled state. New: - AdminSellerManagementPageComponent (features/admin/seller-management/ pages/) - renders the specified empty state (title/description/ Request Access + Learn More buttons) using existing shared/ui primitives only, no new UI infrastructure. - Request Access dialog: Company/Email/Message form via app-form-field + app-input + a plain textarea (no dedicated textarea component exists yet, styled to match app-input's own tokens exactly). Submission is mocked (setTimeout), no API call. On submit: closes and opens a success dialog ("Thank you..."). - Learn More dialog: 6 capability bullets (seller dashboards, storefronts, permissions, analytics, product ownership, marketplace administration) under a "Coming Soon" badge. - New admin nav group "Partners" > "Seller Management" link (admin-nav.model.ts), new route /backoffice/partners/seller-management (app.routes.ts), using the same loadComponent/breadcrumb pattern as every other admin route. Translations: full en/ru/hy coverage, zero hardcoded strings - new adminShell.nav.{partnersGroup,sellerManagement}, adminShell.pages.sellerManagement, and a new adminSellerManagement.* namespace (emptyState/requestDialog/requestSuccessDialog/ learnMoreDialog) added to translations.ts (types) and all three locale files. Accessibility: inherited from app-dialog (role="dialog", aria-modal, focus trap on Tab/Shift+Tab, Escape to close, focus restored to trigger on close) - no new a11y code needed, reused as-is. Responsive: existing --space-*/--font-size-* tokens throughout, flex-wrap on button row, mobile breakpoint stacks actions full-width. Verified live (ru locale, devBypassAdmin): nav group/link render correctly, breadcrumb shows "Управление продавцами", empty state copy matches spec exactly, Request Access dialog opens with all 3 fields + Cancel/Send Request, filled + submitted -> success dialog with exact spec copy, Learn More dialog shows all 6 bullets + Coming Soon badge, no console errors, verified again at 375px mobile viewport. tsc --noEmit clean, ng build clean (pre-existing bundle- budget warning only), arch:check (boundaries + cycles) clean.
2026-07-26 20:47:18 +04:00
partnersGroup: string;
sellerManagement: string;
content: string;
mediaLibrary: string;
marketplaceBuilder: string;
users: string;
settings: string;
monitoring: string;
analytics: string;
documentation: string;
help: string;
logout: string;
comingSoonBadge: string;
};
topbar: {
searchLabel: string;
searchPlaceholder: string;
notifications: string;
notificationsEmpty: string;
account: string;
tenantSelector: string;
tenantSelectorComingSoon: string;
quickPublish: string;
quickPublishComingSoon: string;
};
breadcrumbHome: string;
pages: {
dashboard: { title: string; description: string };
products: { title: string; description: string };
productCreate: { title: string; description: string };
productEdit: { title: string; description: string };
productDuplicate: { title: string; description: string };
categories: { title: string; description: string };
categoryCreate: { title: string; description: string };
categoryEdit: { title: string; description: string };
orders: { title: string; description: string };
orderDetail: { title: string; description: string };
customers: { title: string; description: string };
customerDetail: { title: string; description: string };
moderation: { title: string; description: string };
reviewDetail: { title: string; description: string };
reportsQueue: { title: string; description: string };
transactions: { title: string; description: string };
media: { title: string; description: string };
users: { title: string; description: string };
monitoring: { title: string; description: string };
analytics: { title: string; description: string };
feat(admin): Seller Management Phase 1 UI - Partners section, empty state, request/learn-more dialogs No backend, no CRUD, no API, no business logic - production-quality UI only, built entirely from existing shared components (app-dialog, app-empty-state, app-button, app-form-field, app-input, app-icon, app-badge). Gated per ADR-011: reads modules.sellerManagement.enabled from bootstrap (always false today, no backend sets it) rather than hardcoding disabled state. New: - AdminSellerManagementPageComponent (features/admin/seller-management/ pages/) - renders the specified empty state (title/description/ Request Access + Learn More buttons) using existing shared/ui primitives only, no new UI infrastructure. - Request Access dialog: Company/Email/Message form via app-form-field + app-input + a plain textarea (no dedicated textarea component exists yet, styled to match app-input's own tokens exactly). Submission is mocked (setTimeout), no API call. On submit: closes and opens a success dialog ("Thank you..."). - Learn More dialog: 6 capability bullets (seller dashboards, storefronts, permissions, analytics, product ownership, marketplace administration) under a "Coming Soon" badge. - New admin nav group "Partners" > "Seller Management" link (admin-nav.model.ts), new route /backoffice/partners/seller-management (app.routes.ts), using the same loadComponent/breadcrumb pattern as every other admin route. Translations: full en/ru/hy coverage, zero hardcoded strings - new adminShell.nav.{partnersGroup,sellerManagement}, adminShell.pages.sellerManagement, and a new adminSellerManagement.* namespace (emptyState/requestDialog/requestSuccessDialog/ learnMoreDialog) added to translations.ts (types) and all three locale files. Accessibility: inherited from app-dialog (role="dialog", aria-modal, focus trap on Tab/Shift+Tab, Escape to close, focus restored to trigger on close) - no new a11y code needed, reused as-is. Responsive: existing --space-*/--font-size-* tokens throughout, flex-wrap on button row, mobile breakpoint stacks actions full-width. Verified live (ru locale, devBypassAdmin): nav group/link render correctly, breadcrumb shows "Управление продавцами", empty state copy matches spec exactly, Request Access dialog opens with all 3 fields + Cancel/Send Request, filled + submitted -> success dialog with exact spec copy, Learn More dialog shows all 6 bullets + Coming Soon badge, no console errors, verified again at 375px mobile viewport. tsc --noEmit clean, ng build clean (pre-existing bundle- budget warning only), arch:check (boundaries + cycles) clean.
2026-07-26 20:47:18 +04:00
sellerManagement: { title: string; description: string };
reports: { title: string; description: string };
settings: { title: string; description: string };
feat(admin): Seller Management Phase 1 UI - Partners section, empty state, request/learn-more dialogs No backend, no CRUD, no API, no business logic - production-quality UI only, built entirely from existing shared components (app-dialog, app-empty-state, app-button, app-form-field, app-input, app-icon, app-badge). Gated per ADR-011: reads modules.sellerManagement.enabled from bootstrap (always false today, no backend sets it) rather than hardcoding disabled state. New: - AdminSellerManagementPageComponent (features/admin/seller-management/ pages/) - renders the specified empty state (title/description/ Request Access + Learn More buttons) using existing shared/ui primitives only, no new UI infrastructure. - Request Access dialog: Company/Email/Message form via app-form-field + app-input + a plain textarea (no dedicated textarea component exists yet, styled to match app-input's own tokens exactly). Submission is mocked (setTimeout), no API call. On submit: closes and opens a success dialog ("Thank you..."). - Learn More dialog: 6 capability bullets (seller dashboards, storefronts, permissions, analytics, product ownership, marketplace administration) under a "Coming Soon" badge. - New admin nav group "Partners" > "Seller Management" link (admin-nav.model.ts), new route /backoffice/partners/seller-management (app.routes.ts), using the same loadComponent/breadcrumb pattern as every other admin route. Translations: full en/ru/hy coverage, zero hardcoded strings - new adminShell.nav.{partnersGroup,sellerManagement}, adminShell.pages.sellerManagement, and a new adminSellerManagement.* namespace (emptyState/requestDialog/requestSuccessDialog/ learnMoreDialog) added to translations.ts (types) and all three locale files. Accessibility: inherited from app-dialog (role="dialog", aria-modal, focus trap on Tab/Shift+Tab, Escape to close, focus restored to trigger on close) - no new a11y code needed, reused as-is. Responsive: existing --space-*/--font-size-* tokens throughout, flex-wrap on button row, mobile breakpoint stacks actions full-width. Verified live (ru locale, devBypassAdmin): nav group/link render correctly, breadcrumb shows "Управление продавцами", empty state copy matches spec exactly, Request Access dialog opens with all 3 fields + Cancel/Send Request, filled + submitted -> success dialog with exact spec copy, Learn More dialog shows all 6 bullets + Coming Soon badge, no console errors, verified again at 375px mobile viewport. tsc --noEmit clean, ng build clean (pre-existing bundle- budget warning only), arch:check (boundaries + cycles) clean.
2026-07-26 20:47:18 +04:00
};
};
adminSellerManagement: {
emptyState: {
title: string;
description: string;
requestAccess: string;
learnMore: string;
};
requestDialog: {
title: string;
companyLabel: string;
companyPlaceholder: string;
emailLabel: string;
emailPlaceholder: string;
messageLabel: string;
messagePlaceholder: string;
cancel: string;
send: string;
};
requestSuccessDialog: {
title: string;
message: string;
close: string;
};
learnMoreDialog: {
title: string;
comingSoonBadge: string;
features: {
sellerDashboards: string;
sellerStorefronts: string;
sellerPermissions: string;
sellerAnalytics: string;
productOwnership: string;
marketplaceAdministration: string;
};
close: string;
};
};
2026-02-26 23:09:20 +04:00
}