From 6cd61fc873f00f8cf9a9dc0dcd28e21b6d6d9174 Mon Sep 17 00:00:00 2001 From: sdarbinyan Date: Sun, 26 Jul 2026 15:39:54 +0400 Subject: [PATCH] chore(cleanup): Phase 1 - remove dead code, fix orphaned SeoService wiring Ran knip to find unused exports/dependencies (deps already clean, no unused packages/files found). Removed genuinely dead code (verified zero references anywhere, including templates): - 4 unused constants in config/constants.ts (scroll/pagination/search thresholds never consumed) - isAdminRole(), toSearchResult(), createInitialSearchState(), getTranslatedCategoryName() - unused utility functions - DEFAULT_EDITOR_HEADER_CONFIG - unused constant - TelegramService - entire file deleted; cart.component.ts/ cart.service.ts already implement the same window.Telegram.WebApp access directly, this was an unused duplicate Real bug fix found during the sweep: SeoService has providedIn:'root' with a live effect() meant to sync /OG/canonical tags to tenant bootstrap config, but nothing in the app ever injected it, so Angular never instantiated it and the effect never ran - the SEO sync a prior sprint reported as "done and verified" was actually dead on arrival. Fixed by injecting SeoService in the root App component. Left alone: ~125 knip-flagged "unused exported types" - overwhelmingly config/schema interfaces for the widget/theme/admin domain models, high false-positive rate for this kind of interface-heavy Angular app, deleting blind risks breaking structural type contracts. Also left locally-used-but-over-exported helpers (toCssColor/toBackendColor, HTML_EDITOR_TOOLBAR*, HISTORY_LIMIT, DEFAULT_CATALOG_PAGE_SIZE) - real code, not dead, just exported wider than needed. tsc --noEmit and ng build --configuration=production both clean (only pre-existing bundle-budget warning, unrelated). Files changed: src/app/app.ts, src/app/config/constants.ts, src/app/core/auth/models/permission.model.ts, src/app/core/products/models/catalog-experience.model.ts, src/app/core/search/models/search-state.model.ts, src/app/features/project-editor/models/project-editor.model.ts, src/app/services/index.ts, src/app/utils/item.utils.ts, src/app/services/telegram.service.ts (deleted) --- src/app/app.ts | 2 + src/app/config/constants.ts | 8 ---- src/app/core/auth/models/permission.model.ts | 4 -- .../models/catalog-experience.model.ts | 17 -------- .../core/search/models/search-state.model.ts | 15 ------- .../models/project-editor.model.ts | 14 ------- src/app/services/index.ts | 1 - src/app/services/telegram.service.ts | 39 ------------------- src/app/utils/item.utils.ts | 16 -------- 9 files changed, 2 insertions(+), 114 deletions(-) delete mode 100644 src/app/services/telegram.service.ts diff --git a/src/app/app.ts b/src/app/app.ts index 0710511..839a486 100644 --- a/src/app/app.ts +++ b/src/app/app.ts @@ -14,6 +14,7 @@ import { TranslateService } from './i18n/translate.service'; import { PlatformRuntimeService } from './core/runtime/platform-runtime.service'; import { UiRuntimeFacade } from './facades/runtime/ui-runtime.facade'; import { ApiHealthService } from './services/api-health.service'; +import { SeoService } from './services/seo.service'; import { FloatingNotificationsComponent } from './features/website/user-experience/components/floating-notifications/floating-notifications.component'; import { AdminAuthService } from './core/admin-auth/admin-auth.service'; import { AuthService } from './services/auth.service'; @@ -42,6 +43,7 @@ export class App implements OnInit { private platformRuntime = inject(PlatformRuntimeService); private uiRuntime = inject(UiRuntimeFacade); private apiHealth = inject(ApiHealthService); + private seoService = inject(SeoService); private authService = inject(AuthService); private adminAuthService = inject(AdminAuthService); diff --git a/src/app/config/constants.ts b/src/app/config/constants.ts index 664d151..9b7f6f2 100644 --- a/src/app/config/constants.ts +++ b/src/app/config/constants.ts @@ -4,14 +4,6 @@ export const PAYMENT_MIN_POLL_SECONDS = 60; export const PAYMENT_TIMEOUT_CLOSE_MS = 3000; export const LINK_COPIED_DURATION_MS = 2000; -// Infinite scroll -export const SCROLL_THRESHOLD_PX = 1200; -export const SCROLL_DEBOUNCE_MS = 100; -export const ITEMS_PER_PAGE = 50; - -// Search -export const SEARCH_DEBOUNCE_MS = 300; - // Cache export const CACHE_DURATION_MS = 5 * 60 * 1000; export const CATEGORY_CACHE_DURATION_MS = 2 * 60 * 1000; diff --git a/src/app/core/auth/models/permission.model.ts b/src/app/core/auth/models/permission.model.ts index c7380ce..62fbb10 100644 --- a/src/app/core/auth/models/permission.model.ts +++ b/src/app/core/auth/models/permission.model.ts @@ -28,7 +28,3 @@ export const ROLE_PERMISSIONS: Readonly<Record<AdminRole, readonly Permission[]> Support: ['backoffice.read'], ReadOnly: ['backoffice.read', 'builder.read'] }; - -export function isAdminRole(value: unknown): value is AdminRole { - return typeof value === 'string' && value in ROLE_PERMISSIONS; -} diff --git a/src/app/core/products/models/catalog-experience.model.ts b/src/app/core/products/models/catalog-experience.model.ts index 06a8a8b..c43181d 100644 --- a/src/app/core/products/models/catalog-experience.model.ts +++ b/src/app/core/products/models/catalog-experience.model.ts @@ -67,20 +67,3 @@ export interface SearchResult { pageSize: number; summary: string; } - -export function toSearchResult(result: ProductListResult, criteria: SearchCriteria): SearchResult { - const pageSize = Math.max(1, criteria.pageSize ?? result.count ?? 24); - const page = Math.max(1, criteria.page ?? Math.floor((result.skip ?? 0) / pageSize) + 1); - const keyword = (criteria.keyword ?? '').trim(); - - return { - criteria, - items: result.items, - total: result.total, - page, - pageSize, - summary: keyword.length > 0 - ? `Results for "${keyword}" (${result.total})` - : `Products found: ${result.total}` - }; -} diff --git a/src/app/core/search/models/search-state.model.ts b/src/app/core/search/models/search-state.model.ts index e903935..3e69bf2 100644 --- a/src/app/core/search/models/search-state.model.ts +++ b/src/app/core/search/models/search-state.model.ts @@ -10,18 +10,3 @@ export interface SearchState { pageSize: number; filters: SearchFilterState; } - -export function createInitialSearchState(pageSize = 24): SearchState { - return { - text: '', - sort: 'relevance', - layout: 'grid', - page: 1, - pageSize, - filters: { - values: {}, - ranges: {}, - toggles: {}, - }, - }; -} diff --git a/src/app/features/project-editor/models/project-editor.model.ts b/src/app/features/project-editor/models/project-editor.model.ts index 60aa46e..78de028 100644 --- a/src/app/features/project-editor/models/project-editor.model.ts +++ b/src/app/features/project-editor/models/project-editor.model.ts @@ -53,17 +53,3 @@ export interface ProjectEditorWidgetPreset { type: string; label: string; } - -export const DEFAULT_EDITOR_HEADER_CONFIG: Required<HeaderConfig> = { - showLogo: true, - showSearch: true, - showCategories: true, - showLanguages: true, - showCart: true, - showProfile: false, - showWishlist: true, - showCompare: true, - showRegion: true, - sticky: true, - layout: 'default', -}; diff --git a/src/app/services/index.ts b/src/app/services/index.ts index cae9e7a..6a18977 100644 --- a/src/app/services/index.ts +++ b/src/app/services/index.ts @@ -1,6 +1,5 @@ export * from './api.service'; export * from './cart.service'; -export * from './telegram.service'; export * from './language.service'; export * from './seo.service'; export * from './location.service'; diff --git a/src/app/services/telegram.service.ts b/src/app/services/telegram.service.ts deleted file mode 100644 index 5bb1c77..0000000 --- a/src/app/services/telegram.service.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { Injectable } from '@angular/core'; -import type { } from '../types/telegram.types'; - -@Injectable({ - providedIn: 'root' -}) -export class TelegramService { - private tg = typeof window !== 'undefined' ? window.Telegram?.WebApp : null; - - isTelegramApp(): boolean { - return !!this.tg; - } - - getUser() { - return this.tg?.initDataUnsafe?.user || null; - } - - getUserId(): number | null { - return this.tg?.initDataUnsafe?.user?.id || null; - } - - getUsername(): string | null { - return this.tg?.initDataUnsafe?.user?.username || null; - } - - getFirstName(): string | null { - return this.tg?.initDataUnsafe?.user?.first_name || null; - } - - getFullName(): string | null { - const user = this.getUser(); - if (!user) return null; - return `${user.first_name}${user.last_name ? ' ' + user.last_name : ''}`; - } - - getDisplayName(): string { - return this.getUsername() || this.getFullName() || 'User'; - } -} diff --git a/src/app/utils/item.utils.ts b/src/app/utils/item.utils.ts index 13c73c4..256f91c 100644 --- a/src/app/utils/item.utils.ts +++ b/src/app/utils/item.utils.ts @@ -106,19 +106,3 @@ export function getTranslatedField( if (field === 'simpleDescription') return item.simpleDescription || item.description || ''; return ''; } - -/** - * Get translated category name for the current language. - */ -export function getTranslatedCategoryName(cat: Category, lang: string): string { - const translation = cat.translations?.[lang]; - if (translation?.name) return translation.name; - - if (cat.names?.length) { - const entry = cat.names.find(n => n.language === lang || n.language === lang.toUpperCase() || (lang === 'hy' && n.language === 'AM')); - const val = entry?.value || (entry as any)?.valuue || ''; - if (val) return val; - } - - return cat.name || ''; -}