From b909a195f7f1e1ec72e361a74fb7b23812590a8b Mon Sep 17 00:00:00 2001 From: sdarbinyan Date: Sat, 25 Jul 2026 21:20:37 +0400 Subject: [PATCH] fix(backoffice): wording quality pass across orders, moderation, transactions, users, customers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Replaced hardcoded English audit/timeline text (order status changes, review moderation events, user role/status changes) with proper adminXxx.timelineEvent.*/adminUsers.audit.* i18n keys, so Recent Activity/Timeline/Audit panels no longer mix English into ru/hy UI. - Translated raw internal codes rendered directly to users: transaction payment method ('card'/'qr'/'cash_on_delivery' -> adminTransactions.methodValue.*) and user roles/permissions ('products.manage' etc -> adminUsers.roleValue.*/ adminUsers.permission.*), replacing developer-facing enum leakage with real copy. - Fixed wrong-noun list-footer counts: Orders/Transactions/Moderation list pages all reused adminProducts.items ("N товаров"/"N products") regardless of what was actually listed; each now has its own itemsCount key ("N заказов", "N транзакций", "N отзывов"). - Fixed customer detail page's "Back" button reusing adminOrders.back ("Back to orders") instead of a customers-specific label. - Added translation keys to en/ru/hy + translations.ts interface for all of the above. Co-Authored-By: Claude Sonnet 5 --- .../admin-customer-detail-page.component.html | 2 +- .../admin-customer-detail-page.component.ts | 11 ++++- .../moderation-dashboard.component.html | 2 +- .../moderation-dashboard.component.ts | 10 +++- .../facade/admin-moderation.facade.ts | 4 +- .../moderation/models/admin-review.model.ts | 7 ++- .../admin-review-detail-page.component.ts | 11 ++++- .../admin-reviews-list-page.component.html | 2 +- .../admin-moderation-local.gateway.ts | 9 ++-- .../order-timeline.component.ts | 1 + .../orders-dashboard.component.html | 2 +- .../orders-dashboard.component.ts | 11 ++++- .../orders/facade/admin-orders.facade.ts | 12 ++--- .../admin/orders/models/admin-order.model.ts | 4 +- .../admin-order-detail-page.component.html | 2 +- .../admin-order-detail-page.component.ts | 16 ++++++- .../admin-orders-list-page.component.html | 2 +- .../admin-orders-gateway.interface.ts | 2 +- .../services/admin-orders-local.gateway.ts | 10 ++-- ...dmin-transactions-list-page.component.html | 4 +- .../admin/users/models/admin-user.model.ts | 4 +- .../pages/admin-users-page.component.html | 10 ++-- .../users/pages/admin-users-page.component.ts | 27 +++++++++++ .../services/admin-users-local.gateway.ts | 4 +- src/app/i18n/en.ts | 46 +++++++++++++++++++ src/app/i18n/hy.ts | 46 +++++++++++++++++++ src/app/i18n/ru.ts | 46 +++++++++++++++++++ src/app/i18n/translations.ts | 46 +++++++++++++++++++ 28 files changed, 311 insertions(+), 42 deletions(-) diff --git a/src/app/features/admin/customers/pages/admin-customer-detail-page.component.html b/src/app/features/admin/customers/pages/admin-customer-detail-page.component.html index 2a107e7..f8698e7 100644 --- a/src/app/features/admin/customers/pages/admin-customer-detail-page.component.html +++ b/src/app/features/admin/customers/pages/admin-customer-detail-page.component.html @@ -1,7 +1,7 @@ @if (facade.selected(); as customer) {
- {{ 'adminOrders.back' | translate }} + {{ 'adminCustomers.back' | translate }}

{{ customer.name }}

@if (customer.orderCount > 1) { {{ 'adminCustomers.returning' | translate }} diff --git a/src/app/features/admin/customers/pages/admin-customer-detail-page.component.ts b/src/app/features/admin/customers/pages/admin-customer-detail-page.component.ts index aa01ed0..5f1a98c 100644 --- a/src/app/features/admin/customers/pages/admin-customer-detail-page.component.ts +++ b/src/app/features/admin/customers/pages/admin-customer-detail-page.component.ts @@ -3,6 +3,7 @@ import { CommonModule } from '@angular/common'; import { ActivatedRoute, Router } from '@angular/router'; import { AdminCustomersFacade } from '../facade/admin-customers.facade'; import { TranslatePipe } from '../../../../i18n/translate.pipe'; +import { TranslateService } from '../../../../i18n/translate.service'; import { LanguageService } from '../../../../services/language.service'; import { ButtonComponent } from '../../../../shared/ui/button/button.component'; import { BadgeComponent } from '../../../../shared/ui/badge/badge.component'; @@ -21,12 +22,20 @@ export class AdminCustomerDetailPageComponent { private readonly route = inject(ActivatedRoute); private readonly router = inject(Router); private readonly languageService = inject(LanguageService); + private readonly translate = inject(TranslateService); readonly activity = computed(() => { const customer = this.facade.selected(); if (!customer) return []; return customer.orders - .flatMap(order => order.timeline.map(entry => ({ status: entry.status, timestamp: entry.timestamp, note: entry.note, orderNumber: order.orderNumber }))) + .flatMap(order => order.timeline.map(entry => ({ + status: entry.status, + timestamp: entry.timestamp, + note: this.translate.t('adminOrders.timelineEvent.' + entry.eventKey, { + status: this.translate.t('adminOrders.status.' + entry.status), + }), + orderNumber: order.orderNumber, + }))) .sort((a, b) => b.timestamp.localeCompare(a.timestamp)); }); diff --git a/src/app/features/admin/moderation/components/moderation-dashboard/moderation-dashboard.component.html b/src/app/features/admin/moderation/components/moderation-dashboard/moderation-dashboard.component.html index 75b7240..fdbdce3 100644 --- a/src/app/features/admin/moderation/components/moderation-dashboard/moderation-dashboard.component.html +++ b/src/app/features/admin/moderation/components/moderation-dashboard/moderation-dashboard.component.html @@ -16,7 +16,7 @@ } @else {
    @for (entry of stats().recentActivity; track entry.timestamp + entry.reviewId) { -
  • {{ entry.timestamp | date:'short' }} — {{ entry.productName }} — {{ entry.action }}
  • +
  • {{ entry.timestamp | date:'short' }} — {{ entry.productName }} — {{ activityText(entry) }}
  • }
} diff --git a/src/app/features/admin/moderation/components/moderation-dashboard/moderation-dashboard.component.ts b/src/app/features/admin/moderation/components/moderation-dashboard/moderation-dashboard.component.ts index 43a5695..f25fa50 100644 --- a/src/app/features/admin/moderation/components/moderation-dashboard/moderation-dashboard.component.ts +++ b/src/app/features/admin/moderation/components/moderation-dashboard/moderation-dashboard.component.ts @@ -1,6 +1,7 @@ -import { ChangeDetectionStrategy, Component, input } from '@angular/core'; +import { ChangeDetectionStrategy, Component, inject, input } from '@angular/core'; import { DatePipe } from '@angular/common'; import { TranslatePipe } from '../../../../../i18n/translate.pipe'; +import { TranslateService } from '../../../../../i18n/translate.service'; import { CardComponent } from '../../../../../shared/ui/card/card.component'; import { DashboardMetricComponent } from '../../../dashboard/components/dashboard-metric.component'; import { AdminModerationDashboardStats } from '../../facade/admin-moderation.facade'; @@ -14,5 +15,12 @@ import { AdminModerationDashboardStats } from '../../facade/admin-moderation.fac changeDetection: ChangeDetectionStrategy.OnPush, }) export class ModerationDashboardComponent { + private readonly translate = inject(TranslateService); + readonly stats = input.required(); + + activityText(entry: AdminModerationDashboardStats['recentActivity'][number]): string { + const status = entry.status ? this.translate.t('adminModeration.status.' + entry.status) : ''; + return this.translate.t('adminModeration.timelineEvent.' + entry.eventKey, { status }); + } } diff --git a/src/app/features/admin/moderation/facade/admin-moderation.facade.ts b/src/app/features/admin/moderation/facade/admin-moderation.facade.ts index 92d5bb6..5e82698 100644 --- a/src/app/features/admin/moderation/facade/admin-moderation.facade.ts +++ b/src/app/features/admin/moderation/facade/admin-moderation.facade.ts @@ -28,7 +28,7 @@ export interface AdminModerationDashboardStats { reported: number; spam: number; averageRating: number | null; - recentActivity: { reviewId: string; productName: string; action: string; timestamp: string }[]; + recentActivity: { reviewId: string; productName: string; eventKey: string; status?: AdminReviewStatus; timestamp: string }[]; moderationHealthPercent: number; } @@ -197,7 +197,7 @@ export class AdminModerationFacade { const averageRating = rated.length > 0 ? Math.round((rated.reduce((sum, review) => sum + review.rating, 0) / rated.length) * 10) / 10 : null; const recentActivity = reviews - .flatMap(review => review.timeline.map(entry => ({ reviewId: review.id, productName: review.productName, action: entry.action, timestamp: entry.timestamp }))) + .flatMap(review => review.timeline.map(entry => ({ reviewId: review.id, productName: review.productName, eventKey: entry.eventKey, status: entry.status, timestamp: entry.timestamp }))) .sort((a, b) => b.timestamp.localeCompare(a.timestamp)) .slice(0, 8); diff --git a/src/app/features/admin/moderation/models/admin-review.model.ts b/src/app/features/admin/moderation/models/admin-review.model.ts index 5ea49fe..b2febb2 100644 --- a/src/app/features/admin/moderation/models/admin-review.model.ts +++ b/src/app/features/admin/moderation/models/admin-review.model.ts @@ -1,8 +1,11 @@ export type AdminReviewStatus = 'pending' | 'approved' | 'rejected' | 'spam'; +export type AdminReviewTimelineEventKey = 'submitted' | 'statusChanged' | 'restored' | 'hidden'; +export type AdminReviewTimelineActor = 'admin' | 'customer'; export interface AdminReviewTimelineEntry { - action: string; - actor: string; + eventKey: AdminReviewTimelineEventKey; + actor: AdminReviewTimelineActor; + status?: AdminReviewStatus; note: string; timestamp: string; } diff --git a/src/app/features/admin/moderation/pages/admin-review-detail-page.component.ts b/src/app/features/admin/moderation/pages/admin-review-detail-page.component.ts index b451e2b..b06e055 100644 --- a/src/app/features/admin/moderation/pages/admin-review-detail-page.component.ts +++ b/src/app/features/admin/moderation/pages/admin-review-detail-page.component.ts @@ -4,6 +4,7 @@ import { FormsModule } from '@angular/forms'; import { ActivatedRoute, Router } from '@angular/router'; import { AdminModerationFacade } from '../facade/admin-moderation.facade'; import { TranslatePipe } from '../../../../i18n/translate.pipe'; +import { TranslateService } from '../../../../i18n/translate.service'; import { LanguageService } from '../../../../services/language.service'; import { ButtonComponent } from '../../../../shared/ui/button/button.component'; import { BadgeComponent } from '../../../../shared/ui/badge/badge.component'; @@ -22,6 +23,7 @@ export class AdminReviewDetailPageComponent { private readonly route = inject(ActivatedRoute); private readonly router = inject(Router); private readonly languageService = inject(LanguageService); + private readonly translate = inject(TranslateService); readonly noteDraft = signal(''); @@ -34,7 +36,14 @@ export class AdminReviewDetailPageComponent { timelineEntries(): OrderTimelineEntry[] { const review = this.facade.selected(); - return review ? review.timeline.map(entry => ({ timestamp: entry.timestamp, note: `${entry.action}${entry.note ? ' — ' + entry.note : ''} (${entry.actor})` })) : []; + if (!review) return []; + return review.timeline.map(entry => { + const status = entry.status ? this.translate.t('adminModeration.status.' + entry.status) : ''; + const eventText = this.translate.t('adminModeration.timelineEvent.' + entry.eventKey, { status }); + const actor = this.translate.t('adminModeration.actor.' + entry.actor); + const note = entry.note ? `${eventText} — ${entry.note}` : eventText; + return { timestamp: entry.timestamp, note: `${note} (${actor})` }; + }); } back(): void { diff --git a/src/app/features/admin/moderation/pages/admin-reviews-list-page.component.html b/src/app/features/admin/moderation/pages/admin-reviews-list-page.component.html index 42438cc..a257208 100644 --- a/src/app/features/admin/moderation/pages/admin-reviews-list-page.component.html +++ b/src/app/features/admin/moderation/pages/admin-reviews-list-page.component.html @@ -127,7 +127,7 @@ @if (facade.reviews().length > 0) {
- {{ facade.total() }} {{ 'adminProducts.items' | translate }} + {{ facade.total() }} {{ 'adminModeration.itemsCount' | translate }}
} diff --git a/src/app/features/admin/moderation/services/admin-moderation-local.gateway.ts b/src/app/features/admin/moderation/services/admin-moderation-local.gateway.ts index b9533d0..40c2889 100644 --- a/src/app/features/admin/moderation/services/admin-moderation-local.gateway.ts +++ b/src/app/features/admin/moderation/services/admin-moderation-local.gateway.ts @@ -3,7 +3,7 @@ import { Observable, of } from 'rxjs'; import { delay } from 'rxjs/operators'; import { BackofficeDataService } from '../../../../core/backoffice/backoffice-data.service'; import { ProductCardConfig } from '../../../../shared/models/ui'; -import { AdminReview, AdminReviewListFilters, AdminReviewsListResult, AdminReviewStatus } from '../models/admin-review.model'; +import { AdminReview, AdminReviewListFilters, AdminReviewsListResult, AdminReviewStatus, AdminReviewTimelineEventKey } from '../models/admin-review.model'; import { AdminReport, AdminReportStatus } from '../models/admin-report.model'; import { AdminModerationGateway } from './admin-moderation-gateway.interface'; @@ -61,16 +61,17 @@ export class AdminModerationLocalGateway implements AdminModerationGateway { ...review, status, updatedAt: new Date().toISOString(), - timeline: [...review.timeline, { action: `Status set to ${status}`, actor: 'Admin', note, timestamp: new Date().toISOString() }], + timeline: [...review.timeline, { eventKey: 'statusChanged' as const, status, actor: 'admin' as const, note, timestamp: new Date().toISOString() }], })); } setReviewVisible(id: string, visible: boolean): Observable { + const eventKey: AdminReviewTimelineEventKey = visible ? 'restored' : 'hidden'; return this.mutate(id, review => ({ ...review, visible, updatedAt: new Date().toISOString(), - timeline: [...review.timeline, { action: visible ? 'Restored' : 'Hidden', actor: 'Admin', note: '', timestamp: new Date().toISOString() }], + timeline: [...review.timeline, { eventKey, actor: 'admin' as const, note: '', timestamp: new Date().toISOString() }], })); } @@ -158,7 +159,7 @@ export class AdminModerationLocalGateway implements AdminModerationGateway { featured: false, reportCount, moderatorNotes: '', - timeline: [{ action: 'Submitted', actor: 'Customer', note: '', timestamp: createdAt }], + timeline: [{ eventKey: 'submitted' as const, actor: 'customer' as const, note: '', timestamp: createdAt }], createdAt, updatedAt: createdAt, }; diff --git a/src/app/features/admin/orders/components/order-timeline/order-timeline.component.ts b/src/app/features/admin/orders/components/order-timeline/order-timeline.component.ts index 1d93e50..54ea8f9 100644 --- a/src/app/features/admin/orders/components/order-timeline/order-timeline.component.ts +++ b/src/app/features/admin/orders/components/order-timeline/order-timeline.component.ts @@ -5,6 +5,7 @@ import { TranslatePipe } from '../../../../../i18n/translate.pipe'; export interface OrderTimelineEntry { status?: string; timestamp: string; + /** Pre-resolved, already-translated display text for this event. */ note: string; orderNumber?: string; } diff --git a/src/app/features/admin/orders/components/orders-dashboard/orders-dashboard.component.html b/src/app/features/admin/orders/components/orders-dashboard/orders-dashboard.component.html index 21a6c22..fc04cf3 100644 --- a/src/app/features/admin/orders/components/orders-dashboard/orders-dashboard.component.html +++ b/src/app/features/admin/orders/components/orders-dashboard/orders-dashboard.component.html @@ -25,7 +25,7 @@ } @else {
    @for (entry of stats().recentActivity; track entry.timestamp + entry.orderId) { -
  • {{ entry.timestamp | date:'short' }} — {{ entry.orderNumber }} — {{ entry.note }}
  • +
  • {{ entry.timestamp | date:'short' }} — {{ entry.orderNumber }} — {{ activityText(entry) }}
  • }
} diff --git a/src/app/features/admin/orders/components/orders-dashboard/orders-dashboard.component.ts b/src/app/features/admin/orders/components/orders-dashboard/orders-dashboard.component.ts index 59a2d14..183efc8 100644 --- a/src/app/features/admin/orders/components/orders-dashboard/orders-dashboard.component.ts +++ b/src/app/features/admin/orders/components/orders-dashboard/orders-dashboard.component.ts @@ -1,6 +1,7 @@ -import { ChangeDetectionStrategy, Component, input } from '@angular/core'; +import { ChangeDetectionStrategy, Component, inject, input } from '@angular/core'; import { DatePipe } from '@angular/common'; import { TranslatePipe } from '../../../../../i18n/translate.pipe'; +import { TranslateService } from '../../../../../i18n/translate.service'; import { CardComponent } from '../../../../../shared/ui/card/card.component'; import { BadgeComponent } from '../../../../../shared/ui/badge/badge.component'; import { DashboardMetricComponent } from '../../../dashboard/components/dashboard-metric.component'; @@ -15,5 +16,13 @@ import { AdminOrdersDashboardStats } from '../../facade/admin-orders.facade'; changeDetection: ChangeDetectionStrategy.OnPush, }) export class OrdersDashboardComponent { + private readonly translate = inject(TranslateService); + readonly stats = input.required(); + + activityText(entry: AdminOrdersDashboardStats['recentActivity'][number]): string { + return this.translate.t('adminOrders.timelineEvent.' + entry.eventKey, { + status: this.translate.t('adminOrders.status.' + entry.status), + }); + } } diff --git a/src/app/features/admin/orders/facade/admin-orders.facade.ts b/src/app/features/admin/orders/facade/admin-orders.facade.ts index dbac20f..002688f 100644 --- a/src/app/features/admin/orders/facade/admin-orders.facade.ts +++ b/src/app/features/admin/orders/facade/admin-orders.facade.ts @@ -20,7 +20,7 @@ export interface AdminOrdersDashboardStats { returningCustomers: number; averageOrder: number; currency: string; - recentActivity: { orderNumber: string; orderId: string; note: string; status: AdminOrderStatus; timestamp: string }[]; + recentActivity: { orderNumber: string; orderId: string; eventKey: string; status: AdminOrderStatus; timestamp: string }[]; alerts: { labelKey: string; count: number }[]; } @@ -99,12 +99,12 @@ export class AdminOrdersFacade { this.gateway.loadOrder(id).pipe(take(1)).subscribe({ next: order => this.selected.set(order) }); } - setStatus(id: string, status: AdminOrderStatus, note: string): void { - this.gateway.updateStatus(id, status, note).pipe(take(1)).subscribe({ next: order => this.selected.set(order) }); + setStatus(id: string, status: AdminOrderStatus): void { + this.gateway.updateStatus(id, status).pipe(take(1)).subscribe({ next: order => this.selected.set(order) }); } cancelOrder(id: string): void { - this.setStatus(id, 'cancelled', 'Cancelled by admin'); + this.setStatus(id, 'cancelled'); } requestRefund(id: string): void { @@ -118,7 +118,7 @@ export class AdminOrdersFacade { applyBulkStatus(status: AdminOrderStatus): void { const ids = [...this.selectedIds()]; - ids.forEach(id => this.gateway.updateStatus(id, status, `Bulk status change to ${status}`).pipe(take(1)).subscribe()); + ids.forEach(id => this.gateway.updateStatus(id, status).pipe(take(1)).subscribe()); this.clearSelection(); this.loadList(); this.loadDashboardStats(); @@ -185,7 +185,7 @@ export class AdminOrdersFacade { const averageOrder = orders.length > 0 ? Math.round(total / orders.length) : 0; const recentActivity = orders - .flatMap(order => order.timeline.map(entry => ({ orderNumber: order.orderNumber, orderId: order.id, note: entry.note, status: entry.status, timestamp: entry.timestamp }))) + .flatMap(order => order.timeline.map(entry => ({ orderNumber: order.orderNumber, orderId: order.id, eventKey: entry.eventKey, status: entry.status, timestamp: entry.timestamp }))) .sort((a, b) => b.timestamp.localeCompare(a.timestamp)) .slice(0, 8); diff --git a/src/app/features/admin/orders/models/admin-order.model.ts b/src/app/features/admin/orders/models/admin-order.model.ts index 46f8a4d..afb4d51 100644 --- a/src/app/features/admin/orders/models/admin-order.model.ts +++ b/src/app/features/admin/orders/models/admin-order.model.ts @@ -27,10 +27,12 @@ export interface AdminOrderItem { price: number; } +export type AdminOrderTimelineEventKey = 'created' | 'statusChanged' | 'refundRequested'; + export interface AdminOrderTimelineEntry { status: AdminOrderStatus; timestamp: string; - note: string; + eventKey: AdminOrderTimelineEventKey; } export interface AdminOrder { diff --git a/src/app/features/admin/orders/pages/admin-order-detail-page.component.html b/src/app/features/admin/orders/pages/admin-order-detail-page.component.html index d929b20..1d71d18 100644 --- a/src/app/features/admin/orders/pages/admin-order-detail-page.component.html +++ b/src/app/features/admin/orders/pages/admin-order-detail-page.component.html @@ -68,7 +68,7 @@

{{ 'adminOrders.timeline' | translate }}

- +
diff --git a/src/app/features/admin/orders/pages/admin-order-detail-page.component.ts b/src/app/features/admin/orders/pages/admin-order-detail-page.component.ts index f61e3ef..7c74dc2 100644 --- a/src/app/features/admin/orders/pages/admin-order-detail-page.component.ts +++ b/src/app/features/admin/orders/pages/admin-order-detail-page.component.ts @@ -9,7 +9,7 @@ import { TranslateService } from '../../../../i18n/translate.service'; import { LanguageService } from '../../../../services/language.service'; import { ButtonComponent } from '../../../../shared/ui/button/button.component'; import { BadgeComponent } from '../../../../shared/ui/badge/badge.component'; -import { OrderTimelineComponent } from '../components/order-timeline/order-timeline.component'; +import { OrderTimelineComponent, OrderTimelineEntry } from '../components/order-timeline/order-timeline.component'; const WORKFLOW_STEPS: AdminOrderStatus[] = ['pending', 'processing', 'shipped', 'delivered']; const TERMINAL_STATUSES: AdminOrderStatus[] = ['cancelled', 'refunded']; @@ -45,6 +45,18 @@ export class AdminOrderDetailPageComponent { return WORKFLOW_STEPS.indexOf(order.status); }); + readonly timelineEntries = computed(() => { + const order = this.facade.selected(); + if (!order) return []; + return order.timeline.map(entry => ({ + status: entry.status, + timestamp: entry.timestamp, + note: this.translate.t('adminOrders.timelineEvent.' + entry.eventKey, { + status: this.translate.t('adminOrders.status.' + entry.status), + }), + })); + }); + constructor() { const id = this.route.snapshot.paramMap.get('id'); if (id) { @@ -61,7 +73,7 @@ export class AdminOrderDetailPageComponent { } setStatus(id: string, status: AdminOrderStatus): void { - this.facade.setStatus(id, status, `Status changed to ${status}`); + this.facade.setStatus(id, status); } cancel(id: string): void { diff --git a/src/app/features/admin/orders/pages/admin-orders-list-page.component.html b/src/app/features/admin/orders/pages/admin-orders-list-page.component.html index 760f605..fce1a75 100644 --- a/src/app/features/admin/orders/pages/admin-orders-list-page.component.html +++ b/src/app/features/admin/orders/pages/admin-orders-list-page.component.html @@ -89,7 +89,7 @@
- {{ facade.total() }} {{ 'adminProducts.items' | translate }} + {{ facade.total() }} {{ 'adminOrders.itemsCount' | translate }}
} diff --git a/src/app/features/admin/orders/services/admin-orders-gateway.interface.ts b/src/app/features/admin/orders/services/admin-orders-gateway.interface.ts index 2bec462..4ba4334 100644 --- a/src/app/features/admin/orders/services/admin-orders-gateway.interface.ts +++ b/src/app/features/admin/orders/services/admin-orders-gateway.interface.ts @@ -4,7 +4,7 @@ import { AdminOrder, AdminOrderListFilters, AdminOrdersListResult, AdminOrderSta export interface AdminOrdersGateway { loadOrders(filters: AdminOrderListFilters): Observable; loadOrder(id: string): Observable; - updateStatus(id: string, status: AdminOrderStatus, note: string): Observable; + updateStatus(id: string, status: AdminOrderStatus): Observable; requestRefund(id: string): Observable; addNote(id: string, note: string, internal: boolean): Observable; archiveOrder(id: string): Observable; diff --git a/src/app/features/admin/orders/services/admin-orders-local.gateway.ts b/src/app/features/admin/orders/services/admin-orders-local.gateway.ts index 7348b65..6420a19 100644 --- a/src/app/features/admin/orders/services/admin-orders-local.gateway.ts +++ b/src/app/features/admin/orders/services/admin-orders-local.gateway.ts @@ -31,12 +31,12 @@ export class AdminOrdersLocalGateway implements AdminOrdersGateway { return of(this.ensureData().find(order => order.id === id) ?? null).pipe(delay(50)); } - updateStatus(id: string, status: AdminOrderStatus, note: string): Observable { + updateStatus(id: string, status: AdminOrderStatus): Observable { return this.mutate(id, order => ({ ...order, status, updatedAt: new Date().toISOString(), - timeline: [...order.timeline, { status, timestamp: new Date().toISOString(), note }], + timeline: [...order.timeline, { status, timestamp: new Date().toISOString(), eventKey: 'statusChanged' as const }], })); } @@ -45,7 +45,7 @@ export class AdminOrdersLocalGateway implements AdminOrdersGateway { ...order, payment: { ...order.payment, status: 'refund_requested' }, updatedAt: new Date().toISOString(), - timeline: [...order.timeline, { status: order.status, timestamp: new Date().toISOString(), note: 'Refund requested' }], + timeline: [...order.timeline, { status: order.status, timestamp: new Date().toISOString(), eventKey: 'refundRequested' as const }], })); } @@ -122,8 +122,8 @@ export class AdminOrdersLocalGateway implements AdminOrdersGateway { notes: '', internalNotes: '', timeline: [ - { status: 'pending', timestamp: createdAt, note: 'Order created' }, - ...(status !== 'pending' ? [{ status, timestamp: createdAt, note: `Status set to ${status}` }] : []), + { status: 'pending', timestamp: createdAt, eventKey: 'created' }, + ...(status !== 'pending' ? [{ status, timestamp: createdAt, eventKey: 'statusChanged' as const }] : []), ], archived: false, createdAt, diff --git a/src/app/features/admin/transactions/pages/admin-transactions-list-page.component.html b/src/app/features/admin/transactions/pages/admin-transactions-list-page.component.html index acf1d1e..cd19f32 100644 --- a/src/app/features/admin/transactions/pages/admin-transactions-list-page.component.html +++ b/src/app/features/admin/transactions/pages/admin-transactions-list-page.component.html @@ -42,7 +42,7 @@ {{ tx.orderNumber }} {{ ('adminTransactions.typeValue.' + tx.type) | translate }} - {{ tx.method }} + {{ ('adminTransactions.methodValue.' + tx.method) | translate }} {{ ('adminTransactions.status.' + tx.status) | translate }} {{ tx.amount }} {{ tx.currency }} @@ -63,7 +63,7 @@
- {{ facade.total() }} {{ 'adminProducts.items' | translate }} + {{ facade.total() }} {{ 'adminTransactions.itemsCount' | translate }}
} diff --git a/src/app/features/admin/users/models/admin-user.model.ts b/src/app/features/admin/users/models/admin-user.model.ts index 5e3ee6c..b62e1d3 100644 --- a/src/app/features/admin/users/models/admin-user.model.ts +++ b/src/app/features/admin/users/models/admin-user.model.ts @@ -41,7 +41,9 @@ export interface AdminSession { } export interface AdminUserAuditEntry { - action: string; + eventKey: 'roleChanged' | 'statusChanged'; + roleId?: string; + status?: AdminUserStatus; actor: string; timestamp: string; } diff --git a/src/app/features/admin/users/pages/admin-users-page.component.html b/src/app/features/admin/users/pages/admin-users-page.component.html index df97c14..1cbe1ca 100644 --- a/src/app/features/admin/users/pages/admin-users-page.component.html +++ b/src/app/features/admin/users/pages/admin-users-page.component.html @@ -28,7 +28,7 @@ @@ -53,7 +53,7 @@