Polish business dashboard profile, FA layout, and pagination.

Add a real user profile page with multi-address CRUD, localize business profile, fix RTL category tree and login/sidebar logo fallbacks, and keep pagination controls centered with aligned page meta.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-08-03 10:40:56 +03:30
co-authored by Cursor
parent 26b6b0a1b6
commit d8c9c0b017
20 changed files with 1031 additions and 78 deletions
+157 -2
View File
@@ -12,6 +12,7 @@ const en = {
'nav.home': 'Home',
'nav.businessProfile': 'Business Profile',
'sidebar.addLogo': 'Add logo',
'nav.products': 'Products',
'nav.products.overview': 'Overview',
'nav.products.list': 'My Products',
@@ -62,6 +63,81 @@ const en = {
'header.setting': 'Setting',
'header.changePassword': 'Change password',
'profile.title': 'My Profile',
'profile.subtitle': 'Manage your personal information and contact details.',
'profile.section.general': 'General',
'profile.section.social': 'Social media',
'profile.firstName': 'First name (FA)',
'profile.lastName': 'Last name (FA)',
'profile.firstNameEn': 'First name (EN)',
'profile.lastNameEn': 'Last name (EN)',
'profile.mobile': 'Mobile number',
'profile.email': 'Email',
'profile.emailPlaceholder': 'you@example.com',
'profile.about': 'About yourself',
'profile.addresses': 'Addresses',
'profile.addresses.add': 'Add address',
'profile.addresses.loading': 'Loading addresses...',
'profile.addresses.remove': 'Remove address',
'profile.addresses.error.load': 'Unable to load addresses.',
'profile.addresses.error.incomplete': 'Complete province, city, and address for each row you start.',
'profile.province': 'Province',
'profile.city': 'City',
'profile.postalCode': 'Postal code',
'profile.address': 'Address',
'profile.landline': 'Landline',
'profile.selectProvince': 'Select province',
'profile.selectCity': 'Select city',
'profile.streetPlaceholder': 'Street address',
'profile.instagram': 'Instagram',
'profile.telegram': 'Telegram ID',
'profile.linkedin': 'LinkedIn',
'profile.save': 'Save changes',
'profile.saving': 'Saving...',
'profile.toast.success': 'Profile saved successfully.',
'profile.error.update': 'Unable to save profile.',
'bizProfile.subtitle': 'Manage your storefront identity, contact details, and social links.',
'bizProfile.loading': 'Loading business profile...',
'bizProfile.loadError': 'Unable to load business profile.',
'bizProfile.saveError': 'Unable to save business profile.',
'bizProfile.toast.saved': 'Business profile saved.',
'bizProfile.section.basic': 'Basic info',
'bizProfile.section.contact': 'Contact',
'bizProfile.section.social': 'Social media',
'bizProfile.logo': 'Logo',
'bizProfile.logo.upload': 'Upload logo',
'bizProfile.logo.hint': 'Transparent PNG recommended',
'bizProfile.logo.change': 'Change logo',
'bizProfile.categories': 'Activity categories',
'bizProfile.categories.placeholder': 'Select activity categories',
'bizProfile.nameFa': 'Name (FA)',
'bizProfile.nameEn': 'Name (EN)',
'bizProfile.email': 'Email address',
'bizProfile.about': 'About us',
'bizProfile.vision': 'Our vision',
'bizProfile.addresses': 'Addresses',
'bizProfile.addresses.add': 'Add address',
'bizProfile.province': 'Province',
'bizProfile.city': 'City',
'bizProfile.address': 'Address',
'bizProfile.postalCode': 'Postal code',
'bizProfile.landline': 'Landline',
'bizProfile.selectProvince': 'Select province',
'bizProfile.selectCity': 'Select city',
'bizProfile.streetPlaceholder': 'Street address',
'bizProfile.removeAddress': 'Remove address',
'bizProfile.phones': 'Phone numbers',
'bizProfile.phones.add': 'Add number',
'bizProfile.phones.type': 'Type',
'bizProfile.phones.number': 'Phone number',
'bizProfile.phones.cell': 'Cell number',
'bizProfile.phones.landline': 'Landline',
'bizProfile.phones.remove': 'Remove phone number',
'bizProfile.social.placeholder': '{name} link or ID',
'bizProfile.save': 'Save profile',
'bizProfile.saving': 'Saving...',
'bc.dashboard': 'Dashboard',
'bc.editProduct': 'Edit Product',
'bc.productDetails': 'Product Details',
@@ -193,7 +269,7 @@ const en = {
'products.form.save': 'Save Product',
'products.form.update': 'Update Product',
'categories.page.subtitle': 'Manage your digital product categories and subcategories.',
'categories.page.subtitle': 'Manage your product categories and subcategories.',
'categories.loading': 'Loading categories...',
'categories.empty': 'No categories yet. Use + or AI to add categories.',
'categories.add': 'Add Category',
@@ -873,6 +949,7 @@ const en = {
'title.signIn': 'Sign in',
'title.home': 'Home',
'title.profile': 'Profile',
'title.businessProfile': 'Business Profile',
'title.products': 'Products',
'title.myProducts': 'My Products',
@@ -993,6 +1070,7 @@ const fa: Record<MessageKey, string> = {
'nav.home': 'خانه',
'nav.businessProfile': 'پروفایل کسب‌وکار',
'sidebar.addLogo': 'افزودن لوگو',
'nav.products': 'محصولات',
'nav.products.overview': 'نمای کلی',
'nav.products.list': 'محصولات من',
@@ -1043,6 +1121,81 @@ const fa: Record<MessageKey, string> = {
'header.setting': 'تنظیمات',
'header.changePassword': 'تغییر رمز عبور',
'profile.title': 'پروفایل من',
'profile.subtitle': 'اطلاعات شخصی و راه‌های ارتباطی خود را مدیریت کنید.',
'profile.section.general': 'عمومی',
'profile.section.social': 'شبکه‌های اجتماعی',
'profile.firstName': 'نام (فارسی)',
'profile.lastName': 'نام خانوادگی (فارسی)',
'profile.firstNameEn': 'نام (انگلیسی)',
'profile.lastNameEn': 'نام خانوادگی (انگلیسی)',
'profile.mobile': 'شماره موبایل',
'profile.email': 'ایمیل',
'profile.emailPlaceholder': 'you@example.com',
'profile.about': 'درباره من',
'profile.addresses': 'آدرس‌ها',
'profile.addresses.add': 'افزودن آدرس',
'profile.addresses.loading': 'در حال بارگذاری آدرس‌ها...',
'profile.addresses.remove': 'حذف آدرس',
'profile.addresses.error.load': 'بارگذاری آدرس‌ها ممکن نشد.',
'profile.addresses.error.incomplete': 'برای هر ردیفی که شروع کرده‌اید، استان، شهر و آدرس را کامل کنید.',
'profile.province': 'استان',
'profile.city': 'شهر',
'profile.postalCode': 'کد پستی',
'profile.address': 'آدرس',
'profile.landline': 'تلفن ثابت',
'profile.selectProvince': 'انتخاب استان',
'profile.selectCity': 'انتخاب شهر',
'profile.streetPlaceholder': 'آدرس خیابان',
'profile.instagram': 'اینستاگرام',
'profile.telegram': 'آیدی تلگرام',
'profile.linkedin': 'لینکدین',
'profile.save': 'ذخیره تغییرات',
'profile.saving': 'در حال ذخیره...',
'profile.toast.success': 'پروفایل با موفقیت ذخیره شد.',
'profile.error.update': 'ذخیره پروفایل ممکن نشد.',
'bizProfile.subtitle': 'هویت فروشگاه، اطلاعات تماس و لینک‌های شبکه‌های اجتماعی را مدیریت کنید.',
'bizProfile.loading': 'در حال بارگذاری پروفایل کسب‌وکار...',
'bizProfile.loadError': 'بارگذاری پروفایل کسب‌وکار ممکن نشد.',
'bizProfile.saveError': 'ذخیره پروفایل کسب‌وکار ممکن نشد.',
'bizProfile.toast.saved': 'پروفایل کسب‌وکار ذخیره شد.',
'bizProfile.section.basic': 'اطلاعات پایه',
'bizProfile.section.contact': 'تماس',
'bizProfile.section.social': 'شبکه‌های اجتماعی',
'bizProfile.logo': 'لوگو',
'bizProfile.logo.upload': 'آپلود لوگو',
'bizProfile.logo.hint': 'PNG شفاف توصیه می‌شود',
'bizProfile.logo.change': 'تغییر لوگو',
'bizProfile.categories': 'دسته‌بندی‌های فعالیت',
'bizProfile.categories.placeholder': 'انتخاب دسته‌بندی‌های فعالیت',
'bizProfile.nameFa': 'نام (فارسی)',
'bizProfile.nameEn': 'نام (انگلیسی)',
'bizProfile.email': 'آدرس ایمیل',
'bizProfile.about': 'درباره ما',
'bizProfile.vision': 'چشم‌انداز ما',
'bizProfile.addresses': 'آدرس‌ها',
'bizProfile.addresses.add': 'افزودن آدرس',
'bizProfile.province': 'استان',
'bizProfile.city': 'شهر',
'bizProfile.address': 'آدرس',
'bizProfile.postalCode': 'کد پستی',
'bizProfile.landline': 'تلفن ثابت',
'bizProfile.selectProvince': 'انتخاب استان',
'bizProfile.selectCity': 'انتخاب شهر',
'bizProfile.streetPlaceholder': 'آدرس خیابان',
'bizProfile.removeAddress': 'حذف آدرس',
'bizProfile.phones': 'شماره‌های تماس',
'bizProfile.phones.add': 'افزودن شماره',
'bizProfile.phones.type': 'نوع',
'bizProfile.phones.number': 'شماره تلفن',
'bizProfile.phones.cell': 'شماره موبایل',
'bizProfile.phones.landline': 'تلفن ثابت',
'bizProfile.phones.remove': 'حذف شماره تماس',
'bizProfile.social.placeholder': 'لینک یا آیدی {name}',
'bizProfile.save': 'ذخیره پروفایل',
'bizProfile.saving': 'در حال ذخیره...',
'bc.dashboard': 'داشبورد',
'bc.editProduct': 'ویرایش محصول',
'bc.productDetails': 'جزئیات محصول',
@@ -1174,7 +1327,7 @@ const fa: Record<MessageKey, string> = {
'products.form.save': 'ذخیره محصول',
'products.form.update': 'به‌روزرسانی محصول',
'categories.page.subtitle': 'دسته‌بندی‌ها و زیردسته‌های محصولات دیجیتال خود را مدیریت کنید.',
'categories.page.subtitle': 'دسته‌بندی‌ها و زیردسته‌های محصولات خود را مدیریت کنید.',
'categories.loading': 'در حال بارگذاری دسته‌بندی‌ها...',
'categories.empty': 'هنوز دسته‌بندی‌ای نیست. با + یا هوش مصنوعی اضافه کنید.',
'categories.add': 'افزودن دسته‌بندی',
@@ -1853,6 +2006,7 @@ const fa: Record<MessageKey, string> = {
'title.signIn': 'ورود',
'title.home': 'خانه',
'title.profile': 'پروفایل',
'title.businessProfile': 'پروفایل کسب‌وکار',
'title.products': 'محصولات',
'title.myProducts': 'محصولات من',
@@ -2036,6 +2190,7 @@ export function getBusinessRouteTitleRules(locale: DashboardLocale): RouteTitleR
const t = (key: MessageKey) => translate(locale, key)
return [
{ match: '/login', labels: [t('title.signIn')] },
{ match: '/profile', labels: [t('title.profile')] },
{ match: '/business-profile', labels: [t('title.businessProfile')] },
{ match: '/products/categories', labels: [t('title.products'), t('title.categories')] },
{ match: '/products/brands', labels: [t('title.products'), t('title.brands')] },