fix(backoffice): wording quality pass across orders, moderation, transactions, users, customers

- 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 <noreply@anthropic.com>
This commit is contained in:
sdarbinyan
2026-07-25 21:20:37 +04:00
parent 72846b44b1
commit b909a195f7
28 changed files with 311 additions and 42 deletions

View File

@@ -28,7 +28,7 @@
<td>
<select [attr.aria-label]="'adminUsers.role' | translate" [ngModel]="user.roleId" (ngModelChange)="facade.setRole(user.id, $event)">
@for (role of facade.roles(); track role.id) {
<option [value]="role.id">{{ role.name }}</option>
<option [value]="role.id">{{ roleLabel(role.id) }}</option>
}
</select>
</td>
@@ -53,7 +53,7 @@
<app-input type="email" [ngModel]="inviteEmail()" (ngModelChange)="inviteEmail.set($event)" [placeholder]="'adminUsers.email' | translate" />
<select [attr.aria-label]="'adminUsers.role' | translate" [ngModel]="inviteRoleId()" (ngModelChange)="inviteRoleId.set($event)">
@for (role of facade.roles(); track role.id) {
<option [value]="role.id">{{ role.name }}</option>
<option [value]="role.id">{{ roleLabel(role.id) }}</option>
}
</select>
<select [attr.aria-label]="'adminUsers.scope' | translate" [ngModel]="inviteScope()" (ngModelChange)="inviteScope.set($event)">
@@ -77,7 +77,7 @@
@for (invite of facade.invitations(); track invite.id) {
<tr>
<th scope="row">{{ invite.email }}</th>
<td>{{ facade.roleName(invite.roleId) }}</td>
<td>{{ roleLabel(invite.roleId) }}</td>
<td><app-badge variant="neutral">{{ ('adminUsers.invitationStatus.' + invite.status) | translate }}</app-badge></td>
<td>
@if (invite.status === 'pending') {
@@ -96,7 +96,7 @@
<div class="card">
<h2>{{ 'adminUsers.roles' | translate }}</h2>
@for (role of facade.roles(); track role.id) {
<p><strong>{{ role.name }}</strong> — {{ role.permissions.join(', ') }}</p>
<p><strong>{{ roleLabel(role.id) }}</strong> — {{ role.permissions.map(permissionLabel).join(', ') }}</p>
}
</div>
@@ -111,7 +111,7 @@
<app-dialog [open]="!!facade.auditTarget()" [titleText]="'adminTransactions.audit' | translate" size="sm" (closed)="facade.closeAudit()">
@for (entry of facade.audit(); track $index) {
<p>{{ entry.timestamp | date:'short' }} — {{ entry.actor }} — {{ entry.action }}</p>
<p>{{ entry.timestamp | date:'short' }} — {{ ('adminUsers.actor.' + entry.actor) | translate }} — {{ auditText(entry) }}</p>
}
</app-dialog>
</section>