feat(admin): implement review and moderation center

New Reviews & Moderation feature (frontend only): moderation dashboard (real pending/approved/rejected/reported/spam counts, average rating, recent activity, moderation-health%, computed from the full review queue); reviews list with table/cards, density, saved column visibility, search/status/rating filters, bulk approve/reject/spam/hide/export; review detail shows customer/product/rating/text/photos/timeline/moderator-notes with a real moderation workflow (approve/reject/spam/hide/restore/pin/feature, feature disabled with an explanation unless the review is approved); reusable ReviewHealthWidget (rating/text/media/moderated/report-status/visible + completion%); reports queue lists reports against products/reviews/customers/categories with resolve/dismiss, and honestly renders 'Not available yet' rather than fabricating a value wherever a target can't be resolved (e.g. photos, customer-target reports). Backed by a new in-memory AdminModerationLocalGateway seeded from real product data - the same mock-gateway pattern already used by every other admin feature in this app (orders/products/categories), since no review/report backend exists to reuse. Replaced the 'Reviews' comingSoon nav placeholder with a working link; added full adminModeration i18n coverage.
This commit is contained in:
sdarbinyan
2026-07-18 22:01:16 +04:00
parent 097927f124
commit 3c9b425203
26 changed files with 1369 additions and 1 deletions

View File

@@ -1135,6 +1135,77 @@ export const ru: Translations = {
optionalDataMissingDescription: 'Необязательное конфигурационное значение отсутствует.',
optionalDataMissingResolution: 'Добавьте значение, если оно нужно UX.',
},
adminModeration: {
search: 'Поиск по клиенту, товару или тексту отзыва…',
allStatuses: 'Все статусы',
allRatings: 'Все оценки',
rating: 'Оценка',
customer: 'Клиент',
product: 'Товар',
reviewText: 'Отзыв',
photos: 'Фото',
workflow: 'Действия',
approve: 'Одобрить',
reject: 'Отклонить',
markSpam: 'Отметить как спам',
hide: 'Скрыть',
restore: 'Восстановить',
pin: 'Закрепить',
unpin: 'Открепить',
feature: 'Выделить',
unfeature: 'Убрать выделение',
featureDisabledHint: 'Выделять можно только одобренные отзывы.',
moderatorNotes: 'Заметки модератора',
notAvailable: 'Пока недоступно',
changeStatus: 'Изменить статус',
hideSelected: 'Скрыть',
archiveSelected: 'В архив',
reportsQueue: 'Очередь жалоб',
reportsColumn: 'Жалобы',
reportTarget: 'Объект жалобы',
reportType: 'Тип',
reportReason: 'Причина',
resolve: 'Решено',
dismiss: 'Отклонить',
reportsEmptyTitle: 'Жалоб нет',
reportsEmptyDescription: 'Жалобы клиентов на товары, отзывы или аккаунты появятся здесь.',
reportedCount: 'С жалобами',
averageRating: 'Средняя оценка',
moderationHealth: 'Состояние модерации',
emptyTitle: 'Отзывов пока нет',
emptyDescription: 'Отзывы появятся здесь после первых оценок от клиентов.',
emptyGuide: 'Клиенты оставляют оценку и текст после покупки. Новые отзывы получают статус «Ожидает» до одобрения, отклонения или пометки как спам модератором — одобренные отзывы становятся видны на витрине. Старайтесь регулярно разбирать очередь ожидающих отзывов.',
healthRating: 'Оценка',
healthText: 'Текст',
healthMedia: 'Медиа',
healthModeration: 'Промодерирован',
healthReportStatus: 'Нет открытых жалоб',
healthVisibility: 'Виден',
health: 'Состояние',
column_product: 'Товар',
column_rating: 'Оценка',
column_status: 'Статус',
column_reports: 'Жалобы',
column_created: 'Отправлен',
status: {
pending: 'Ожидает',
approved: 'Одобрен',
rejected: 'Отклонён',
spam: 'Спам',
},
targetType: {
product: 'Товар',
review: 'Отзыв',
customer: 'Клиент',
category: 'Категория',
unknown: 'Неизвестно',
},
reportStatus: {
open: 'Открыта',
resolved: 'Решена',
dismissed: 'Отклонена',
},
},
adminOrders: {
back: 'Назад к заказам',
search: 'Поиск по номеру заказа, имени, email или телефону…',
@@ -1536,6 +1607,7 @@ export const ru: Translations = {
categories: 'Категории',
orders: 'Заказы',
customers: 'Клиенты',
moderation: 'Отзывы и модерация',
transactions: 'Транзакции',
reviews: 'Отзывы',
reports: 'Отчёты',
@@ -1576,6 +1648,9 @@ export const ru: Translations = {
orderDetail: { title: 'Заказ', description: 'Детали и статус заказа' },
customers: { title: 'Клиенты', description: 'Все, кто оформлял заказ' },
customerDetail: { title: 'Клиент', description: 'Профиль клиента, заказы и активность' },
moderation: { title: 'Отзывы и модерация', description: 'Проверяйте и модерируйте отзывы клиентов' },
reviewDetail: { title: 'Отзыв', description: 'Детали отзыва и действия модерации' },
reportsQueue: { title: 'Очередь жалоб', description: 'Контент, на который пожаловались клиенты' },
transactions: { title: 'Транзакции', description: 'Платежи, возвраты и проверка мошенничества' },
media: { title: 'Медиатека', description: 'Изображения и файлы для товаров и страниц' },
users: { title: 'Пользователи', description: 'Команда администраторов и права доступа' },