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

@@ -1140,6 +1140,77 @@ export const en: Translations = {
optionalDataMissingDescription: 'Optional configuration data is absent.',
optionalDataMissingResolution: 'Add optional value if UX depends on it.',
},
adminModeration: {
search: 'Search by customer, product, or review text…',
allStatuses: 'All statuses',
allRatings: 'All ratings',
rating: 'Rating',
customer: 'Customer',
product: 'Product',
reviewText: 'Review',
photos: 'Photos',
workflow: 'Actions',
approve: 'Approve',
reject: 'Reject',
markSpam: 'Mark as spam',
hide: 'Hide',
restore: 'Restore',
pin: 'Pin',
unpin: 'Unpin',
feature: 'Feature',
unfeature: 'Unfeature',
featureDisabledHint: 'Only approved reviews can be featured.',
moderatorNotes: 'Moderator notes',
notAvailable: 'Not available yet',
changeStatus: 'Change status',
hideSelected: 'Hide',
archiveSelected: 'Archive',
reportsQueue: 'Reports queue',
reportsColumn: 'Reports',
reportTarget: 'Reported item',
reportType: 'Type',
reportReason: 'Reason',
resolve: 'Resolve',
dismiss: 'Dismiss',
reportsEmptyTitle: 'No reports',
reportsEmptyDescription: 'Customer reports about products, reviews, or accounts will show up here.',
reportedCount: 'Reported',
averageRating: 'Average rating',
moderationHealth: 'Moderation health',
emptyTitle: 'No reviews yet',
emptyDescription: 'Reviews will appear here once customers start leaving feedback.',
emptyGuide: 'Customers leave a star rating and text after purchase. New reviews start as Pending until a moderator approves, rejects, or marks them as spam — approved reviews become visible on the storefront. Aim to clear the pending queue regularly.',
healthRating: 'Rating',
healthText: 'Text',
healthMedia: 'Media',
healthModeration: 'Moderated',
healthReportStatus: 'No open reports',
healthVisibility: 'Visible',
health: 'Health',
column_product: 'Product',
column_rating: 'Rating',
column_status: 'Status',
column_reports: 'Reports',
column_created: 'Submitted',
status: {
pending: 'Pending',
approved: 'Approved',
rejected: 'Rejected',
spam: 'Spam',
},
targetType: {
product: 'Product',
review: 'Review',
customer: 'Customer',
category: 'Category',
unknown: 'Unknown',
},
reportStatus: {
open: 'Open',
resolved: 'Resolved',
dismissed: 'Dismissed',
},
},
adminOrders: {
back: 'Back to orders',
search: 'Search by order number, name, email, or phone…',
@@ -1542,6 +1613,7 @@ export const en: Translations = {
orders: 'Orders',
customers: 'Customers',
transactions: 'Transactions',
moderation: 'Reviews & Moderation',
reviews: 'Reviews',
reports: 'Reports',
content: 'Content',
@@ -1581,6 +1653,9 @@ export const en: Translations = {
orderDetail: { title: 'Order', description: 'Order details and status' },
customers: { title: 'Customers', description: 'Everyone who has placed an order' },
customerDetail: { title: 'Customer', description: 'Customer profile, orders, and activity' },
moderation: { title: 'Reviews & Moderation', description: 'Review and moderate customer feedback' },
reviewDetail: { title: 'Review', description: 'Review details and moderation actions' },
reportsQueue: { title: 'Reports queue', description: 'Content reported by customers' },
transactions: { title: 'Transactions', description: 'Payments, refunds, and fraud review' },
media: { title: 'Media Library', description: 'Images and files for products and pages' },
users: { title: 'Users', description: 'Admin team members and permissions' },