Commit Graph

91 Commits

Author SHA1 Message Date
sdarbinyan
14c72d1a6a feat: extract auth into @marketplaces/auth package, add backoffice admin provisioning spec
- ADR-0001: decision to extract auth/payment into shared @marketplaces/* packages
- Scaffold packages/auth, packages/payment; @marketplaces/auth now holds the real
  telegram (customer+admin QR/session) and ed25519 (future admin challenge/response)
  auth implementation, pushed to sources.vitanova.network/sdarbinyan/vitanovaPackages
- Rewire ~30 call sites to import from @marketplaces/auth; delete migrated originals
  from core/auth, core/admin-auth, services/, models/
- Replace environment coupling with AUTH_API_URL/TELEGRAM_BOT_USERNAME injection
  tokens and isDevMode(); wired as file:packages/auth pending registry publish
- Add TRACK-S §8: bootstrap per-marketplace admin login + marketplace-scoped
  sub-admin invite/role endpoints
- Build, arch:check:boundaries, and full test suite (103/103) all green

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-18 01:05:16 +04:00
sdarbinyan
0e16eecda6 feat: Phase 8 frontend - Customer identity core + standalone VK ID login button
core/identity (Customer/ExternalIdentity/ContactChannel models + VkIdGateway/
token/mock) and a standalone VkIdLoginComponent, per Sprint 0.1's "VK ID
first" decision and v3.1 §14. Against
docs/backend/PHASE-8-IDENTITY-MESSAGING-CONTRACT.md §1-2.

Deliberately not wired into TelegramLoginComponent's dialog - that's the
live, working QR-login surface for both customer and admin auth
(components/telegram-login/), and splicing a second provider into it
needs a real VK OAuth app to test against, not a mock bolt-on next to
nine other phases. The button is a standalone, ready-to-place component;
integrating it into checkout/login flows is follow-up work once VK
credentials exist.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-17 23:58:48 +04:00
sdarbinyan
0cadc1a642 fix: delivery-selector price/currency not converting on currency switch
Some checks failed
Architecture Governance / architecture (push) Has been cancelled
Component read item.currency (source) as both the display label and the
conversion target, so amounts never actually converted - only the label
technically matched. Now converts deliveryPrice/selectedDeliveryTotal via
CurrencyRatesService and labels with the shopper's selected currency.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-15 02:01:08 +04:00
sdarbinyan
4510eb769a feat: client-side currency conversion with admin-configurable rates
Some checks failed
Architecture Governance / architecture (push) Has been cancelled
- CurrencyRatesService: RUB-based rates, persisted via localStorage
- CurrencyConvertPipe: impure pipe converting item price to selected currency
- Admin settings page: editable currency rates form
- Applied conversion to product-card, product-information, quick-view-dialog,
  delivery-information, compare-table, cart totals + payment payload

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-15 01:45:12 +04:00
sdarbinyan
ce63931bc2 feat: dead-config sweep, test suite foundation, widget settingsSchema validation
Some checks failed
Architecture Governance / architecture (push) Has been cancelled
Sprint G: audited every BootstrapConfig field for a real runtime consumer
(docs/DEAD-CONFIG-AUDIT.md). Wired 3 previously-dead editable fields:
footer.logoUrl, company.address.street/contacts.phone, catalog.suggestionsEnabled.
Remaining dead fields needing a business/design decision tracked in
PRODUCT_BACKLOG.md/KNOWN-ISSUES.md, not silently left.

Sprint H: 6 new spec files (test count 57 -> 83), covering ProjectEditorFacade
(undo/redo, draft persistence, publish gating), AdminAnalyticsFacade
(never-fabricate-a-number contract), and regression coverage for this
session's carousel/hero/profile-toggle fixes.

Sprint I: widget settingsSchema (declared in widget-manifest.json, never
validated) now enforced via a new lightweight schema check in
ProjectValidator, surfaced through the existing issuesByField pipeline.
Same check reused in diagnostics so editor and diagnostics can't disagree.

Verification: tsc clean, ng build clean, 83/83 tests pass, barry-cache
validate clean (2 pre-existing unrelated warnings only).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-05 20:47:13 +04:00
sdarbinyan
48bcffa22c feat: close stub-page gaps - profile login/logout, admin Reports/Settings, Help/Docs links
Some checks failed
Architecture Governance / architecture (push) Has been cancelled
Sprint A: storefront header profile control (login/logout only, no menu),
wired to existing customer Telegram auth (AuthService).

Sprint B: backoffice/reports page, reuses AdminAnalyticsFacade (Sales,
Top Products, Marketplace Health cards + CSV export).

Sprint C: backoffice/settings page, admin UI density preference
(comfortable/compact), localStorage-persisted, applied to app-table
across all admin list pages.

Sprint D: admin bottom-nav Help -> mailto using existing supportEmail,
Documentation -> external link via new TenantConfig.documentationUrl.
AdminNavLink gains externalHref for non-routerLink nav entries.

Docs: docs/GLOBAL-SPRINT-PLAN.md tracks the full sprint breakdown.
docs/COMING-SOON-AUDIT.md removed, folded into docs/KNOWN-ISSUES.md.
docs/BACKEND.md updated with the new documentationUrl bootstrap field.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-05 17:48:50 +04:00
sdarbinyan
3300494309 chore(deps): update Angular core/cli/animations/common/compiler/forms/platform-browser/router/service-worker 21.1.5 -> 22.0.8
Ran via ng update @angular/core@22 @angular/cli@22 (schematics applied
automatically). TypeScript bumped 5.9.3 -> 6.0.3 as a required peer.

Migrations applied:
- provideHttpClient() calls gained withXhr() where HttpXhrBackend is used
  (app.config.ts)
- optional-chaining expressions wrapped in $safeNavigationMigration()
  (language-selector.component.html)
- nullishCoalescingNotNullable/optionalChainNotNullable extended
  diagnostics disabled in tsconfig.app.json/tsconfig.spec.json (matches
  the new stricter default the migration works around)

Next: ng update @angular/cdk@22, then verify tsc/build/tests.
2026-07-26 19:06:43 +04:00
sdarbinyan
59855b0fab fix(storefront): create missing footer payment-icon assets
bootstrap.json's footer.paymentIcons referenced /assets/images/
mir-logo.svg, visa-logo.svg, mastercard-logo.svg - none of that
directory's files existed until the RC-02 placeholder fix, and these
three were still missing. Site-wide broken-image icons in every page
footer. Added neutral labeled-badge SVGs (not reproductions of the
actual trademarked logo artwork) at the exact referenced paths, plus
an onerror fallback on the footer <img> for defense in depth.
2026-07-26 12:01:26 +04:00
sdarbinyan
3e54e88db7 fix(storefront): add missing placeholder image asset and onerror fallback
getMainImage() referenced /assets/images/placeholder.svg as the no-image
fallback, but src/assets/images/ never existed - any item with zero
photos rendered a browser broken-image icon instead of a placeholder.
Added the asset.

Also added an (error) handler (onImageError) on every dynamic <img> that
renders a user/admin-supplied URL (product card, cart line item, cart
payment QR code, product gallery main + thumbnails) so a 404'd/broken
image URL swaps to the shared placeholder instead of shipping broken.
2026-07-26 00:12:43 +04:00
sdarbinyan
1163bfd88a fix(storefront): replace hardcoded strings with i18n, neutral empty-state wording
- Route aria-label/alt/title strings (rating, discount, carousel arrows,
  hero slides, dialog close, toast dismiss, QR code, bank payment iframe,
  guest checkout fallback) through the translate pipe/service instead of
  literal English.
- Drop the "Oops!"/"Упс!" apology framing from category/subcategory empty
  states (en/ru/hy) - zero results is not an error.
2026-07-25 23:54:08 +04:00
sdarbinyan
fb1afb72d4 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
sdarbinyan
4bf0666fd1 perf(app): lazy-load i18n translation packs, drop dead items-carousel component
RC PERF-01 bundle audit follow-up on 61a5714.

- i18n: ru/en/hy translation packs (346 KB raw combined) were all
  statically imported in TranslateService and shipped in the initial
  bundle regardless of the visitor's language. Now only 'ru' (platform
  default) is bundled eagerly; 'en'/'hy' are dynamic import()s. The
  language route guard (languageGuard) awaits preloadLanguage() before
  activating the route, so translations are always fully loaded before
  any component renders - no flash of untranslated/fallback content.
- widget-host.service.ts: import UnknownWidgetComponent directly instead
  of via the widgets/ui barrel (index.ts re-exports 6 widgets).
- Deleted src/app/components/items-carousel/* - confirmed dead (zero
  references anywhere, verified via knip and grep), the only consumer
  of primeng/primeicons in the app. Removed the now-unused
  `@import 'primeicons/primeicons.css'` from styles.scss (no primeicons
  CSS classes used elsewhere). primeng/primeicons remain listed in
  package.json/package-lock.json - npm CLI in this environment is
  blocked by an unrelated, pre-existing broken `barry-cache` devDependency
  (ETARGET on `npm install`/`npm uninstall`), so the lockfile could not be
  safely regenerated. Flagged, not fixed.

Routes audit (app.routes.ts): all storefront/builder/backoffice feature
routes already use loadComponent/loadChildren; nothing eagerly imported.
No route changes needed.

Lucide icons (icon-registry.ts): already named/tree-shakeable imports
from @lucide/angular, not a full-library import. No change needed.

Before/after (npm run build, production):
- Initial bundle raw: 1.47 MB -> 1.12 MB (-350 KB / -24%)
- Initial bundle transfer (est.): 263.59 kB -> 221.51 kB (-42 kB / -16%)
- Budget overage: 769.22 kB over -> 416.84 kB over (still exceeds the
  700 KB budget; project-editor-page-component (320 kB),
  catalog-container-component (126 kB), product-details-container
  (88 kB), cart-component (61 kB) lazy chunks unchanged - no safe
  mechanical split identified within scope, see PERF-01 report for
  detail).

Verified: npx tsc --noEmit clean, npm run build green (warning only,
no errors).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-24 08:19:13 +04:00
sdarbinyan
99560202c3 fix(storefront): premium UX polish for cart, checkout
- cart.component.scss: normalize hardcoded hex colors to design tokens
  (--text-primary, --text-secondary, --bg-primary/--bg-secondary/
  --bg-tertiary, --border-color, --error-color, --success-color,
  --warning-color, --shadow-*, --transition-*, --radius-* fallbacks)
  across cart items, quantity controls, summary, login gate, terms
  checkbox, payment modal, payment-active QR screen, and bank-payment
  iframe modal
- cart.component.scss: deduplicate an accidental duplicate
  .close-modal-btn rule block (identical CSS repeated twice)
- cart.component.scss: add focus-visible rings to clear-cart, remove,
  quantity, checkout, close-modal, retry-payment, copy/open-link,
  telegram-login, and card-payment buttons
- cart.component.scss: delivery-required warning now pairs an icon
  with the text instead of relying on color/background alone
- cart.component.html: add warning icon + role="alert" to the
  delivery-required notice; add aria-live/aria-label to the quantity
  value so screen readers announce quantity changes
- delivery-selector.component.scss: normalize hardcoded hex colors to
  design tokens; remove dead :host-context(.cart-container.alt) rules
  left over after the .alt theme was removed from cart.component in
  RC-Visual-02 (cart-container never carries an .alt class anymore);
  add hover/focus-visible states to the delivery <select>

Build verified green via `npm run build`.

Out of scope / skipped:
- Did not restructure the payment modal or bank-payment iframe overlay
  into shared app-dialog - it has custom multi-step state (creating/
  waiting/success/error/timeout) and an already-implemented manual
  focus-trap; restructuring it is a composition change, not visual
  polish
- Did not convert clearCart()'s native confirm() to a custom
  confirm-remove dialog - no existing storefront confirm-dialog
  pattern to follow, and adding one is a composition/architecture
  change
- spinner-large/spinner-small left untouched per RC-Visual-02 guidance
  (in-progress action state, not content loading)
- .email-form block (email/phone capture after payment success) is
  dead CSS behind commented-out markup; left in place rather than
  deleting, since removing it is a code-cleanup call, not visual
  polish
- region-selector/language-selector are header-only, not part of the
  cart/checkout flow - left untouched
- no dedicated checkout page exists; checkout is the payment section
  of the cart page, covered above

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 11:57:23 +04:00
sdarbinyan
9ea8c98faf fix(storefront): premium UX polish for home, catalog, search
- product-card: normalize hardcoded hex colors to design tokens
  (--text-primary, --border-color, --primary-color, --bg-tertiary,
  --bg-secondary); stock bar and stock badge now use semantic
  --success-color/--warning-color/--error-color instead of
  near-duplicate literal hex; add-to-cart hover uses --primary-hover
  and --transition-* tokens; card hover shadow uses --shadow-lg
- product-card: add aria-pressed to favorite/compare toggle buttons
  so their selected state isn't color-only
- filters-panel: add aria-pressed to color/size/rating filter chips;
  add a visible checkmark glyph on selected color swatches plus a
  focus-style selection ring, so selection isn't conveyed by border
  color alone
- layout-switcher: add aria-pressed to the active layout button
- catalog-container: add aria-current to the mobile sort-sheet and
  grid-sheet option buttons; active sort option gets a checkmark
  and bold weight instead of color-only highlighting
- category-grid: normalize hardcoded border/background/text colors
  to tokens; align focus ring with the color-mix pattern used
  elsewhere in catalog
- search-results, sorting-control: normalize skeleton/select colors
  to tokens; sort <select> gets a hover border state
- home: convert loading-grid/empty-state spacing to --space-* tokens

Build verified green via `npm run build`.

Out of scope / skipped:
- pages/category and pages/search retain their existing hand-rolled
  skeleton markup (not app-skeleton) - replacing it is a composition
  change, not covered by this visual-polish pass
- product-card rating-stars color and legacy pages/category,
  pages/search hex literals left as-is where no exact token match
  exists, to avoid an unintended visual shift

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-23 11:34:20 +04:00
sdarbinyan
5c54541b4c style(design-system): normalize font-weight literals (400/500/600/700) to tokens
Mechanical, value-preserving: font-weight: 400/500/600/700 -> var(--font-weight-normal/medium/semibold/bold, <same value>) across src/app.
Note: cart.component.scss now sits ~771 bytes over its per-file budget
in angular.json due to longer var() strings; non-fatal build warning,
noted in docs/UI-DESIGN-REVIEW.md as a follow-up (either bump the
component style budget slightly or accept the warning).
2026-07-20 03:28:56 +04:00
sdarbinyan
be59db2e2d style(design-system): normalize exact-match border-radius literals to tokens
Mechanical sweep for border-radius: 4px/8px/12px/13px/999px replaced
with var(--radius-xs/sm/md/lg/full, <same value>) across src/app.
Only exact matches to existing token values were touched (20px, 16px,
10px, 6px, 3px, 2px etc. were left as-is since no token maps to them
without a visible size change on at least one tenant theme — see
docs/UI-DESIGN-REVIEW.md).
2026-07-20 03:27:25 +04:00
sdarbinyan
7cb1c8c3c6 style(design-system): roll out font-size scale across storefront/builder/backoffice
Mechanical, value-preserving substitution: every literal font-size
declaration across src/app (89 files) that matched one of the 9
typography scale steps introduced earlier (--font-size-xs..4xl) was
replaced with var(--font-size-STEP, <same-or-nearest-step-value>).

Values within ~0.03rem/1px of a scale step were snapped to that step
(e.g. 0.85rem and 0.8rem both -> --font-size-sm/0.8125rem; 0.9rem and
0.875rem -> --font-size-base/0.875rem) to consolidate roughly 15
near-duplicate sizes down to the 9-step scale, per the RC design-system
finalization brief. This eliminates most of the font-size fragmentation
found across the app (previously: 0.7/0.72/0.75/0.78/0.8/0.8125/0.85/
0.875/0.9/0.9375/0.95/1/1.05/1.1/1.125/1.15/1.2/1.25/1.3/1.35/1.4/1.5/
1.75/2rem all in live use simultaneously).

Not touched (deliberately, see docs/UI-DESIGN-REVIEW.md): 3rem+ display
sizes (too large a jump to any existing step, would need a --font-size-5xl
addition), font-size values expressed via clamp()/calc(), and any
component listed as intentionally distinct (code-editor syntax tokens,
theme brand colors).
2026-07-20 03:26:17 +04:00
sdarbinyan
fbe56015b5 fix(icons): icon-only button accessibility pass
Swept every icon-only button app-wide for an accessible name. Found
three relying on title-only (not reliably announced by screen
readers) or nothing at all: region-selector's detect-location button,
the carousel add-to-cart button, and the subcategories add-to-cart
button (had no label at all). All now have aria-label.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-20 03:02:14 +04:00
sdarbinyan
e1112bbd50 fix(icons): replace remaining hand-rolled inline SVGs with Lucide
telegram-login: close X and lock icons (auth-gate icon reused across
telegram-login and cart - same 'log in required' concept, now the
same lock icon in both instead of two different hand-drawn shapes);
retry/refresh icon (QR expired/error states, was duplicated). Added
missing aria-label on the close button (had none).

catalog-empty-state, category, subcategories, item-detail: empty-state
illustrations (package/search/grid), add-to-cart icons, success/error
status icons, and thumbs up/down vote icons replaced. Rating stars
(item-detail, both product rating and per-review rating) now use one
Star icon with a color input and a .dx-star--filled CSS class for the
solid/outline toggle, instead of hand-toggling raw fill/stroke SVG
attributes - fixes the same rating-star pattern being drawn two
different ways (outline-only in the carousel earlier, fill-toggling
here).

Added color input to app-icon (was stroke-only via currentColor
before) and four more icons to the registry: refresh, thumbsUp/Down,
locate/mapPin (added earlier this session).

Also fixed the currency-dropdown chevron in language-selector that a
prior replace_all missed (same markup, different [class.rotated]
binding target).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-20 02:53:52 +04:00
sdarbinyan
3837ddfb2d fix(icons): replace hand-rolled inline SVGs with Lucide (cart, selectors, carousel)
Cart: trash/X/plus/minus/lock icons replaced with app-icon. Removed
the standalone EmptyCartIconComponent entirely - it was a duplicate
80px shopping-cart glyph with no unique illustration, only ever used
in one place; now app-icon name="cart" inline.

Language/region selectors: dropdown chevrons (duplicated 3x with
identical path data across two components) unified on
chevronDown; region pin, locate (crosshair), and globe icons replaced.
New mapPin/locate icons added to the registry.

Items carousel: rating star and add-to-cart icons replaced.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-20 02:45:37 +04:00
sdarbinyan
6b0ad6455b fix(icons): replace hand-rolled inline SVGs with Lucide (header, search)
Header: same magnifying-glass path was hand-duplicated twice with two
different hex fills (#576463 desktop, #1e3c38 mobile) - now one
app-icon name="search", color inherited via currentColor. Wishlist/
compare buttons used bare '♥'/'⇄' text glyphs, entirely outside any
icon system - replaced with heart/scale icons. Cart icon, mobile-menu
home/catalog icons, and three duplicated inline chevron SVGs replaced
with app-icon equivalents. Cleaned up now-dead CSS that targeted the
old raw svg/path selectors.

Search: the same magnifying-glass path was hand-duplicated 4 times
(input icon, empty-query state, no-results state, no-query state) at
three sizes and three colors. Replaced all four with app-icon,
preserving each state's intended color via a color property on the
wrapper (icons default to currentColor).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-20 02:37:23 +04:00
sdarbinyan
ec1f95db09 fix(storefront): polish footer
Add explicit :focus-visible outline to footer nav links so keyboard
users get a clear, on-brand focus indicator instead of relying on
inconsistent browser default outlines against the dark footer bg.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-19 23:24:21 +04:00
sdarbinyan
f8dc0cfed4 fix(storefront): polish header
Fix keyboard-inaccessible mobile nav items (catalog + static pages):
were <a> with no href, activated only by (click), so not reachable
via Enter/Space or exposed correctly to assistive tech. Converted to
<button type="button"> matching the existing desktop nav-btn pattern.
Also drop the redundant inline cursor style now covered by the class.

Remove ~495 lines of dead .header/.alt-header CSS from two earlier
redesigns superseded by the current .platform-* template (verified
zero template references).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-19 23:22:40 +04:00
sdarbinyan
a39b3429ba fix(catalog): decode and strip stray markup from product descriptions
P0-5: some catalog listings (live backend data, proxied third-party
marketplace via novo.market) carry HTML-entity-encoded markup in
their description field, e.g. '&lt;attention&gt;...&lt;/attention&gt;'
and '&quot;AppStops&quot;' — rendered verbatim as visible text on
search-result cards and the PDP description tab.

Added a pure cleanDescription() util (item.utils.ts) that decodes
the common HTML entities and strips any resulting tag-like markup,
then wired it into ProductCardComponent (covers Home/Catalog/Search/
Wishlist/Compare/PDP-similar) and ProductDescriptionComponent (PDP
description tab). Output stays a plain string rendered via text
interpolation (never innerHTML), so this only cleans up display —
it introduces no HTML-rendering/XSS surface.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-19 22:56:12 +04:00
sdarbinyan
1a5d43523a fix(catalog): translate product-card stock badge and action-button labels
P0-1: stock badge rendered the raw item.remainings value ('High',
etc) untranslated on every product card sitewide. Now maps to
catalog.stockHigh/Medium/Low/Out via the translate pipe; the 'out'
class check is now case-insensitive to match.

P0-2: favorite/share/quick-view action-button aria-labels rendered
literal 'catalog.favorite'/'catalog.share'/'catalog.quickView' keys
because they never existed in translations.ts/en.ts/ru.ts/hy.ts
(only catalog.compare existed, and it was likewise unused). Added
all 4 keys to the Translations interface and all 3 locales.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-19 22:04:13 +04:00
sdarbinyan
b05278c061 fix(footer): stop generating collision-prone social-link ids, fragile track key
createSocialLinkRow derived the new id from the current array length
(social-${length+1}). Add/remove/add cycles reliably reproduce a duplicate
id: add,add -> social-1/social-2; remove social-1 -> array length 1; add
-> social-2 again, colliding with the surviving row. footer.component.html
tracks footer nav items by id (@for ... track item.id), so a duplicate id
there corrupts Angular's DOM reuse on the public storefront footer.

Also switched the payment-icon @for from track icon.src to track $index -
two icon rows sharing a src (most commonly two blank ones) hit the same bug.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-17 17:52:43 +04:00
sdarbinyan
d8456ecb9f feat(project-editor): header layout + sticky option
- HeaderConfig gains sticky (default true) and layout ('default'|'centered')
- header editor exposes layout select + sticky toggle
- runtime header component applies static/centered classes from config

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-17 15:29:55 +04:00
sdarbinyan
ee1cbdf38b style(ui): full UX/UI + motion pass across storefront, admin, editor
Some checks failed
Architecture Governance / architecture (push) Has been cancelled
- fix save-bar buttons to use shared app-button primitive (were unstyled)
- fix platform-nav-group border/radius via structural selectors, drop dead
  -middle/-right classes
- storefront widgets (hero/categories/product-carousel/footer-nav): design
  tokens, hover/focus states, 44px touch targets, entrance motion, reduced-
  motion guards
- admin dashboard cards + quick-actions: hover lift, entrance animation
- admin product-form gallery remove badge: hover/focus + expanded hit area
- project-editor section.shared button styles: hover/active/focus/disabled
  states + reduced-motion; section-switch fade-in motion

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-16 23:32:31 +04:00
sdarbinyan
325dc17911 feat(admin): sprint 19 admin dashboard, routing, i18n
- Add admin dashboard feature (models/gateway/facade/components/page)
- Wire admin/products routes and backoffice coming-soon placeholders
- Add lastPublishedAt to ProjectEditorFacade/state
- Add dashboard i18n keys (en/ru/hy) and docs/ADMIN.md

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-14 12:21:33 +04:00
sdarbinyan
6aec2ebcb2 fix(admin-auth): reuse exact same QR/session API and component for admin login
Some checks failed
Architecture Governance / architecture (push) Has been cancelled
- Removed invented adminAuthApiUrl endpoint and separate AdminLoginComponent.
  Admin login now uses the exact same Telegram session backend
  (TelegramSessionApiService, {authApiUrl}/users/sessions) and the exact
  same TelegramLoginComponent (mode="customer" | "admin" input) as customer
  login - only the storage (cookie/localStorage/signals) stays separate.
- Extracted the shared HTTP+normalization logic from AuthService into
  TelegramSessionApiService so both AuthService and AdminAuthService call it
  instead of duplicating request/parsing code.
- Documented the resulting backend gap in docs/Project-Editor.md: since the
  session API has no concept of "admin", server-side role enforcement is
  required when admin API calls are made - the frontend only decides where
  to store the session, not whether the user is actually an admin.
2026-07-14 10:13:59 +04:00
sdarbinyan
3877b70fdf feat(sprint18): editor autosave/reset, admin auth, QR reuse, Ed25519 prep
Some checks failed
Architecture Governance / architecture (push) Has been cancelled
- Project editor: persist draft to localStorage, restore on reload,
  last-saved/draft-restored status indicators, section/whole-draft reset
  with confirmation.
- Extract shared QR/polling/expiry engine from TelegramLoginComponent
  (shared/qr-login) and reuse it for a new admin login flow.
- Admin authentication kept fully separate from customer session:
  own cookie/localStorage keys, signals, guard, and header interceptor
  (core/admin-auth).
- ?login=true / ?adminLogin=true open the respective login dialog for
  manual testing.
- Ed25519 challenge/verify interfaces (fail-closed no-op binding) ready
  for backend delivery.
- Document autosave/reset/admin-auth/QR-reuse/Ed25519 model and the
  remaining full-field-coverage gap in docs/Project-Editor.md.
2026-07-14 09:50:03 +04:00
sdarbinyan
ee269a9e33 fixes
Some checks failed
Architecture Governance / architecture (push) Has been cancelled
2026-07-10 15:55:38 +04:00
sdarbinyan
7d6c09a346 feat(cms): add static pages module 2026-07-10 13:52:01 +04:00
sdarbinyan
e2c8747fcc feat(builder): add project editor 2026-07-10 13:43:53 +04:00
sdarbinyan
6409a91cb0 style(catalog): polish responsive UI 2026-07-09 02:43:39 +04:00
sdarbinyan
8d652c8259 feat(platform): sprint 11.5 standardization
Some checks failed
Architecture Governance / architecture (push) Has been cancelled
2026-07-09 02:29:12 +04:00
sdarbinyan
55216817b2 bug-fixes 2026-07-09 01:40:22 +04:00
sdarbinyan
92e1bdaff8 feat(ux): implement sprint 11 user experience module 2026-07-09 01:13:54 +04:00
sdarbinyan
1a8f916942 feat(catalog): implement sprint 10 advanced search experience
Some checks failed
Architecture Governance / architecture (push) Has been cancelled
2026-07-09 00:55:50 +04:00
sdarbinyan
c901ec1e49 refactor: finalize bootstrap-driven layout and widget runtime 2026-07-05 04:17:31 +04:00
sdarbinyan
6550250d13 cleanup: remove tenant variant logic and enforce config-driven UI 2026-07-05 04:07:25 +04:00
sdarbinyan
79a12c0ec2 fix DI errors and stabilize static page navigation 2026-07-05 03:41:13 +04:00
sdarbinyan
b0c5c5e051 feat static pages system with dynamic footer and safe html rendering 2026-07-05 03:37:35 +04:00
sdarbinyan
145a13857d fix local bootstrap startup and catalog widget UX 2026-07-05 02:44:04 +04:00
sdarbinyan
d4a5daeb4c product details implementation 2026-07-05 01:43:56 +04:00
sdarbinyan
0efcfb5225 product grid creating 2026-07-05 01:36:21 +04:00
sdarbinyan
d7d73c2a10 Add reusable marketplace product card 2026-07-05 01:05:48 +04:00
sdarbinyan
ae3512ad37 Route marketplace data through product facade 2026-07-05 01:03:37 +04:00
sdarbinyan
9cf508d319 clean up 2026-07-05 00:57:20 +04:00
sdarbinyan
58b5a4e996 clean up stage 1 2026-07-05 00:38:21 +04:00