Add customer/manager access UI and tighten customers filters.

Business and super-admin can set Customer vs Manager roles (Admin only for super-admin), and the customers page drops clutter while filtering by all/customers/managers.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-08-10 21:31:28 +03:30
co-authored by Cursor
parent 404c008ced
commit f622e6d605
28 changed files with 1280 additions and 241 deletions
+134 -4
View File
@@ -407,6 +407,43 @@ const en = {
'products.card.remove': 'Remove product',
'products.card.draft': 'Draft',
'products.details.loading': 'Loading product...',
'products.details.notFound': 'Product not found.',
'products.details.errorLoad': 'Unable to load product.',
'products.details.back': 'Back to My Products',
'products.details.openGallery': 'Open image gallery',
'products.details.noImage': 'No image',
'products.details.viewImage': 'View image {index}',
'products.details.tabsAria': 'Product details',
'products.details.tab.technical': 'Technical Info',
'products.details.tab.comments': 'Comments',
'products.details.tab.reviews': 'Expert Reviews',
'products.details.technical.loading': 'Loading technical info...',
'products.details.technical.noForm':
'No technical form is defined for this product category.',
'products.details.technical.noData':
'No technical data has been added for this product yet.',
'products.details.technical.noCategory': 'Product has no category assigned.',
'products.details.technical.empty': 'No technical data available.',
'products.details.technical.errorLoad': 'Unable to load technical info.',
'products.details.comments.loading': 'Loading comments...',
'products.details.comments.empty': 'No comments yet for this product.',
'products.details.comments.errorLoad': 'Unable to load comments.',
'products.details.comments.errorApprove': 'Unable to update comment approval.',
'products.details.comments.errorDelete': 'Unable to delete comment.',
'products.details.reviews.loading': 'Loading expert reviews...',
'products.details.reviews.empty': 'No expert reviews yet.',
'products.details.reviews.errorLoad': 'Unable to load expert reviews.',
'products.details.reviews.errorApprove': 'Unable to update expert review approval.',
'products.details.reviews.errorDelete': 'Unable to delete expert review.',
'products.details.pending': 'Pending approval',
'products.details.approve': 'Approve',
'products.details.reject': 'Reject',
'products.details.remove': 'Remove',
'products.details.positivePoints': 'Positive points',
'products.details.negativePoints': 'Negative points',
'products.details.ratingAria': 'Rating {rate} out of 10',
'products.form.errorOptions': 'Unable to load form options.',
'products.form.errorSave': 'Unable to save product.',
'products.form.thumbnail': 'Thumbnail Image',
@@ -735,9 +772,13 @@ const en = {
'customers.filters': 'Filters',
'customers.filter.name': 'Search by name',
'customers.filter.cell': 'Cell number',
'customers.filter.access': 'User role',
'customers.filter.access.all': 'All users',
'customers.filter.access.customers': 'Customers',
'customers.filter.access.managers': 'Managers',
'customers.search': 'Search',
'customers.clearFilters': 'Clear filters',
'customers.listTitle': 'Customer list',
'customers.listTitle': 'User list',
'customers.showing': 'Showing {from} - {to} of {total}',
'customers.none': 'No customers',
'customers.empty': 'No results found.',
@@ -792,6 +833,29 @@ const en = {
'customers.addModal.error': 'Unable to add customer.',
'customers.addModal.errorPasswordMatch': 'Passwords do not match.',
'customers.addModal.errorPasswordLength': 'Password must be at least 8 characters.',
'customers.access.title': 'Change access',
'customers.access.subtitle': 'Choose customer or manager access for {name}.',
'customers.access.customer': 'Customer',
'customers.access.manager': 'Manager',
'customers.access.role.admin': 'Admin',
'customers.access.role.editor': 'Editor',
'customers.access.role.viewer': 'Viewer',
'customers.access.hintSuperAdmin':
'Admin can manage other managers (except other admins). Editor and viewer manage content only.',
'customers.access.hintBusiness':
'Managers can be Editor or Viewer. Only a super admin can assign Admin.',
'customers.access.cancel': 'Cancel',
'customers.access.save': 'Save',
'customers.access.error': 'Unable to update access.',
'customers.access.change': 'Change access',
'customers.access.ownerLocked': 'Business owner cannot be changed',
'customers.access.adminLocked': 'Only a super admin can change an admin',
'customers.access.badge.owner': 'Owner',
'customers.access.badge.admin': 'Admin',
'customers.access.badge.editor': 'Editor',
'customers.access.badge.viewer': 'Viewer',
'customers.access.badge.manager': 'Manager',
'customers.toast.accessUpdated': 'Access updated to {role}.',
'blog.page.subtitle': 'Create and manage blog posts and categories.',
'blog.card.list.desc': 'View, edit and manage all your blog posts.',
@@ -806,7 +870,9 @@ const en = {
'blog.list.subtitle': '{count} posts · View, edit and manage your blog content.',
'blog.list.loading': 'Loading blog posts...',
'blog.list.empty': 'No blog posts found.',
'blog.list.empty': 'No blog posts yet.',
'blog.list.emptyHint': 'Share news, stories, and updates with your audience.',
'blog.list.emptyCta': 'Write your first post',
'blog.list.errorLoad': 'Unable to load blog posts.',
'blog.list.errorDelete': 'Unable to delete blog post.',
'blog.list.errorVerify': 'Unable to update blog verification.',
@@ -1710,6 +1776,41 @@ const fa: Record<MessageKey, string> = {
'products.card.remove': 'حذف محصول',
'products.card.draft': 'پیش‌نویس',
'products.details.loading': 'در حال بارگذاری محصول...',
'products.details.notFound': 'محصول یافت نشد.',
'products.details.errorLoad': 'بارگذاری محصول ممکن نشد.',
'products.details.back': 'بازگشت به محصولات من',
'products.details.openGallery': 'باز کردن گالری تصاویر',
'products.details.noImage': 'بدون تصویر',
'products.details.viewImage': 'مشاهده تصویر {index}',
'products.details.tabsAria': 'جزئیات محصول',
'products.details.tab.technical': 'اطلاعات فنی',
'products.details.tab.comments': 'نظرات',
'products.details.tab.reviews': 'بررسی کارشناسان',
'products.details.technical.loading': 'در حال بارگذاری اطلاعات فنی...',
'products.details.technical.noForm': 'برای این دسته‌بندی فرم فنی تعریف نشده است.',
'products.details.technical.noData': 'هنوز اطلاعات فنی برای این محصول ثبت نشده است.',
'products.details.technical.noCategory': 'این محصول به دسته‌بندی اختصاص داده نشده است.',
'products.details.technical.empty': 'اطلاعات فنی موجود نیست.',
'products.details.technical.errorLoad': 'بارگذاری اطلاعات فنی ممکن نشد.',
'products.details.comments.loading': 'در حال بارگذاری نظرات...',
'products.details.comments.empty': 'هنوز نظری برای این محصول ثبت نشده است.',
'products.details.comments.errorLoad': 'بارگذاری نظرات ممکن نشد.',
'products.details.comments.errorApprove': 'به‌روزرسانی تأیید نظر ممکن نشد.',
'products.details.comments.errorDelete': 'حذف نظر ممکن نشد.',
'products.details.reviews.loading': 'در حال بارگذاری بررسی کارشناسان...',
'products.details.reviews.empty': 'هنوز بررسی کارشناسی ثبت نشده است.',
'products.details.reviews.errorLoad': 'بارگذاری بررسی کارشناسان ممکن نشد.',
'products.details.reviews.errorApprove': 'به‌روزرسانی تأیید بررسی ممکن نشد.',
'products.details.reviews.errorDelete': 'حذف بررسی کارشناسی ممکن نشد.',
'products.details.pending': 'در انتظار تأیید',
'products.details.approve': 'تأیید',
'products.details.reject': 'رد',
'products.details.remove': 'حذف',
'products.details.positivePoints': 'نقاط قوت',
'products.details.negativePoints': 'نقاط ضعف',
'products.details.ratingAria': 'امتیاز {rate} از ۱۰',
'products.form.errorOptions': 'بارگذاری گزینه‌های فرم ممکن نشد.',
'products.form.errorSave': 'ذخیره محصول ممکن نشد.',
'products.form.thumbnail': 'تصویر بندانگشتی',
@@ -2038,9 +2139,13 @@ const fa: Record<MessageKey, string> = {
'customers.filters': 'فیلترها',
'customers.filter.name': 'جستجو بر اساس نام',
'customers.filter.cell': 'شماره موبایل',
'customers.filter.access': 'نقش کاربر',
'customers.filter.access.all': 'تمام کاربران',
'customers.filter.access.customers': 'مشتریان',
'customers.filter.access.managers': 'مدیران سیستم',
'customers.search': 'جستجو',
'customers.clearFilters': 'پاک کردن فیلترها',
'customers.listTitle': 'فهرست مشتریان',
'customers.listTitle': 'فهرست کاربران',
'customers.showing': 'نمایش {from} تا {to} از {total}',
'customers.none': 'بدون مشتری',
'customers.empty': 'نتیجه‌ای یافت نشد.',
@@ -2095,6 +2200,29 @@ const fa: Record<MessageKey, string> = {
'customers.addModal.error': 'افزودن مشتری ممکن نشد.',
'customers.addModal.errorPasswordMatch': 'رمزهای عبور یکسان نیستند.',
'customers.addModal.errorPasswordLength': 'رمز عبور باید حداقل ۸ کاراکتر باشد.',
'customers.access.title': 'تغییر دسترسی',
'customers.access.subtitle': 'دسترسی مشتری یا مدیر را برای {name} انتخاب کنید.',
'customers.access.customer': 'مشتری',
'customers.access.manager': 'مدیر',
'customers.access.role.admin': 'ادمین',
'customers.access.role.editor': 'ویرایشگر',
'customers.access.role.viewer': 'بیننده',
'customers.access.hintSuperAdmin':
'ادمین می‌تواند مدیران دیگر را مدیریت کند (به‌جز ادمین‌های دیگر). ویرایشگر و بیننده فقط محتوا را مدیریت می‌کنند.',
'customers.access.hintBusiness':
'مدیران می‌توانند ویرایشگر یا بیننده باشند. فقط سوپرادمین می‌تواند ادمین تعیین کند.',
'customers.access.cancel': 'انصراف',
'customers.access.save': 'ذخیره',
'customers.access.error': 'به‌روزرسانی دسترسی ممکن نشد.',
'customers.access.change': 'تغییر دسترسی',
'customers.access.ownerLocked': 'نقش صاحب کسب‌وکار قابل تغییر نیست',
'customers.access.adminLocked': 'فقط سوپرادمین می‌تواند ادمین را تغییر دهد',
'customers.access.badge.owner': 'صاحب',
'customers.access.badge.admin': 'ادمین',
'customers.access.badge.editor': 'ویرایشگر',
'customers.access.badge.viewer': 'بیننده',
'customers.access.badge.manager': 'مدیر',
'customers.toast.accessUpdated': 'دسترسی به {role} به‌روزرسانی شد.',
'blog.page.subtitle': 'مطالب و دسته‌بندی‌های بلاگ را ایجاد و مدیریت کنید.',
'blog.card.list.desc': 'همه مطالب بلاگ را مشاهده، ویرایش و مدیریت کنید.',
@@ -2109,7 +2237,9 @@ const fa: Record<MessageKey, string> = {
'blog.list.subtitle': '{count} مطلب · مشاهده، ویرایش و مدیریت محتوای بلاگ.',
'blog.list.loading': 'در حال بارگذاری مطالب بلاگ...',
'blog.list.empty': 'مطلب بلاگی یافت نشد.',
'blog.list.empty': 'هنوز مطلب بلاگی ندارید.',
'blog.list.emptyHint': 'اخبار، داستان‌ها و به‌روزرسانی‌ها را با مخاطبان خود به اشتراک بگذارید.',
'blog.list.emptyCta': 'اولین مطلب را بنویسید',
'blog.list.errorLoad': 'بارگذاری مطالب بلاگ ممکن نشد.',
'blog.list.errorDelete': 'حذف مطلب بلاگ ممکن نشد.',
'blog.list.errorVerify': 'به‌روزرسانی وضعیت تأیید بلاگ ممکن نشد.',