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

@@ -1138,6 +1138,77 @@ export interface Translations {
optionalDataMissingDescription: string;
optionalDataMissingResolution: string;
};
adminModeration: {
search: string;
allStatuses: string;
allRatings: string;
rating: string;
customer: string;
product: string;
reviewText: string;
photos: string;
workflow: string;
approve: string;
reject: string;
markSpam: string;
hide: string;
restore: string;
pin: string;
unpin: string;
feature: string;
unfeature: string;
featureDisabledHint: string;
moderatorNotes: string;
notAvailable: string;
changeStatus: string;
hideSelected: string;
archiveSelected: string;
reportsQueue: string;
reportsColumn: string;
reportTarget: string;
reportType: string;
reportReason: string;
resolve: string;
dismiss: string;
reportsEmptyTitle: string;
reportsEmptyDescription: string;
reportedCount: string;
averageRating: string;
moderationHealth: string;
emptyTitle: string;
emptyDescription: string;
emptyGuide: string;
healthRating: string;
healthText: string;
healthMedia: string;
healthModeration: string;
healthReportStatus: string;
healthVisibility: string;
health: string;
column_product: string;
column_rating: string;
column_status: string;
column_reports: string;
column_created: string;
status: {
pending: string;
approved: string;
rejected: string;
spam: string;
};
targetType: {
product: string;
review: string;
customer: string;
category: string;
unknown: string;
};
reportStatus: {
open: string;
resolved: string;
dismissed: string;
};
};
adminOrders: {
back: string;
search: string;
@@ -1550,6 +1621,7 @@ export interface Translations {
customers: string;
transactions: string;
reviews: string;
moderation: string;
reports: string;
content: string;
mediaLibrary: string;
@@ -1588,6 +1660,9 @@ export interface Translations {
orderDetail: { title: string; description: string };
customers: { title: string; description: string };
customerDetail: { title: string; description: string };
moderation: { title: string; description: string };
reviewDetail: { title: string; description: string };
reportsQueue: { title: string; description: string };
transactions: { title: string; description: string };
media: { title: string; description: string };
users: { title: string; description: string };