Files
marketplaces/src/app/app.routes.ts
sdarbinyan 7d65913245 feat(admin): transaction management
Sprint 24.

New features/admin/transactions/ module. AdminTransactionsLocalGateway
derives one synthetic transaction per Sprint 23's seeded mock order rather
than a separate dataset, keeping order numbers/totals consistent across
the two mock feature areas.

- list: search, status filter, type filter (payment/refund/qr_payment),
  pagination, CSV export
- retry failed transactions (appends an audit entry)
- fraud flag toggle
- per-transaction audit log (creation/retry/fraud-flag-change), viewed via
  dialog - intentionally separate from the system-wide audit/security log
  planned for Sprint 26 (Monitoring)
- wired into /:lang/backoffice/transactions, replacing the coming-soon
  placeholder

docs/ADMIN.md + docs/BACKEND.md (new item 13) updated.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-15 10:57:29 +04:00

173 lines
6.5 KiB
TypeScript

import { Routes } from '@angular/router';
import { languageGuard } from './guards/language.guard';
import { projectEditorDirtyGuard } from './features/project-editor/guards/project-editor-dirty.guard';
import { adminAuthGuard } from './core/admin-auth/admin-auth.guard';
import { adminCategoryDirtyGuard } from './features/admin/categories/guards/admin-category-dirty.guard';
import { environment } from '../environments/environment';
// Core routes (same across all brands)
const coreRoutes: Routes = [
{
path: '',
loadComponent: () => import('./pages/home/home.component').then(m => m.HomeComponent)
},
{
path: 'catalog',
loadComponent: () => import('./features/website/catalog/containers/catalog-container.component').then(m => m.CatalogContainerComponent)
},
{
path: 'catalog/:id',
loadComponent: () => import('./features/website/catalog/containers/catalog-container.component').then(m => m.CatalogContainerComponent)
},
{
path: 'category/:id',
redirectTo: 'catalog/:id',
pathMatch: 'full'
},
{
path: 'category/:id/items',
redirectTo: 'catalog/:id',
pathMatch: 'full'
},
{
path: 'product/:id',
loadComponent: () => import('./features/website/product/containers/product-details-container.component').then(m => m.ProductDetailsContainerComponent)
},
{
path: 'item/:id',
redirectTo: 'product/:id',
pathMatch: 'full'
},
{
path: 'search',
loadComponent: () => import('./features/website/catalog/containers/catalog-container.component').then(m => m.CatalogContainerComponent)
},
{
path: 'edit/:section',
loadComponent: () => import('./features/project-editor/pages/project-editor-page.component').then(m => m.ProjectEditorPageComponent),
canDeactivate: [projectEditorDirtyGuard]
},
{
path: 'backoffice',
canActivate: [adminAuthGuard],
children: [
{ path: '', redirectTo: 'dashboard', pathMatch: 'full' },
{
path: 'dashboard',
loadComponent: () => import('./features/admin/dashboard/pages/admin-dashboard-page.component').then(m => m.AdminDashboardPageComponent)
},
{
path: 'products',
loadComponent: () => import('./features/admin/products/pages/admin-products-list-page.component').then(m => m.AdminProductsListPageComponent)
},
{
path: 'products/create',
loadComponent: () => import('./features/admin/products/pages/admin-product-editor-page.component').then(m => m.AdminProductEditorPageComponent)
},
{
path: 'products/:id/edit',
loadComponent: () => import('./features/admin/products/pages/admin-product-editor-page.component').then(m => m.AdminProductEditorPageComponent)
},
{
path: 'products/:id/duplicate',
loadComponent: () => import('./features/admin/products/pages/admin-product-editor-page.component').then(m => m.AdminProductEditorPageComponent)
},
{
path: 'categories',
loadComponent: () => import('./features/admin/categories/pages/admin-categories-list-page.component').then(m => m.AdminCategoriesListPageComponent)
},
{
path: 'categories/create',
loadComponent: () => import('./features/admin/categories/pages/admin-category-editor-page.component').then(m => m.AdminCategoryEditorPageComponent),
canDeactivate: [adminCategoryDirtyGuard]
},
{
path: 'categories/:id/edit',
loadComponent: () => import('./features/admin/categories/pages/admin-category-editor-page.component').then(m => m.AdminCategoryEditorPageComponent),
canDeactivate: [adminCategoryDirtyGuard]
},
{
path: 'static-pages',
loadComponent: () => import('./features/backoffice/shared/backoffice-coming-soon-page.component').then(m => m.BackofficeComingSoonPageComponent),
data: { titleKey: 'dashboard.actionStaticPages' }
},
{
path: 'transactions',
loadComponent: () => import('./features/admin/transactions/pages/admin-transactions-list-page.component').then(m => m.AdminTransactionsListPageComponent)
},
{
path: 'orders',
loadComponent: () => import('./features/admin/orders/pages/admin-orders-list-page.component').then(m => m.AdminOrdersListPageComponent)
},
{
path: 'orders/:id',
loadComponent: () => import('./features/admin/orders/pages/admin-order-detail-page.component').then(m => m.AdminOrderDetailPageComponent)
},
{
path: 'media',
loadComponent: () => import('./features/backoffice/media/media-library-page.component').then(m => m.MediaLibraryPageComponent),
data: { titleKey: 'dashboard.actionMediaLibrary' }
},
{ path: '**', redirectTo: 'dashboard' }
]
},
{
path: 'edit',
redirectTo: 'edit/general',
pathMatch: 'full'
},
{
path: 'builder',
redirectTo: 'edit/general',
pathMatch: 'full'
},
{
path: 'project-editor',
redirectTo: 'edit/general',
pathMatch: 'full'
},
{
path: 'wishlist',
loadComponent: () => import('./features/website/user-experience/wishlist/containers/wishlist-page.component').then(m => m.WishlistPageComponent)
},
{
path: 'compare',
loadComponent: () => import('./features/website/user-experience/compare/containers/compare-page.component').then(m => m.ComparePageComponent)
},
{
path: 'cart',
loadComponent: () => import('./pages/cart/cart.component').then(m => m.CartComponent)
},
{
path: 'page/:key',
loadComponent: () => import('./pages/static-page/static-page.component').then(m => m.StaticPageComponent)
},
{
path: ':staticPath',
loadComponent: () => import('./pages/static-page/static-page.component').then(m => m.StaticPageComponent)
}
];
// TODO(CMS): Resolve informational/legal pages from backend content configuration here.
// Disabled hardcoded pages: about, contacts, faq, delivery, guarantee,
// company-details, payment-terms, return-policy, public-offer, privacy-policy.
const cmsContentRoutes: Routes = [];
// All routes sit under a :lang prefix (e.g. /ru/cart, /en/product/5)
export const routes: Routes = [
...(environment.production ? [] : [{
path: '__diagnostics',
loadComponent: () => import('./features/diagnostics/components/diagnostics-page.component').then(m => m.DiagnosticsPageComponent)
}]),
{
path: ':lang',
canActivate: [languageGuard],
children: [
...coreRoutes,
...cmsContentRoutes,
{ path: '**', redirectTo: '' }
]
},
// URLs without a language prefix → redirect to default language
{ path: '**', redirectTo: 'ru' }
];