From c2ede07e7399a9c8e3c94c7db25eb6e91c873002 Mon Sep 17 00:00:00 2001 From: Alireza Hassani Date: Wed, 9 Sep 2026 23:30:23 +0330 Subject: [PATCH] Add website schema settings, SEO meta overrides, and resilient bulk SMS. Business admins can configure site-wide Schema.org and optional per-item SEO title/description; mass SMS continues on failures with an end report. Co-authored-by: Cursor --- .../business/src/components/CategoryModal.tsx | 20 ++ .../src/components/SendCustomerSmsModal.tsx | 253 ++++++++++------ .../src/components/SeoMetaFields.module.css | 64 ++++ .../business/src/components/SeoMetaFields.tsx | 69 +++++ .../src/components/VariationsModal.module.css | 53 ++++ .../WebsiteSchemaSettingsSection.tsx | 278 ++++++++++++++++++ apps/business/src/data/categories.ts | 20 ++ apps/business/src/i18n/messages.ts | 73 +++++ .../src/pages/AddCustomerProductPage.tsx | 20 ++ apps/business/src/pages/AddNewBlogPage.tsx | 20 ++ .../src/pages/AddNewInstructionPage.tsx | 20 ++ .../src/pages/AddNewPortfolioPage.tsx | 20 ++ apps/business/src/pages/AddNewProductPage.tsx | 20 ++ apps/business/src/pages/AddNewVideoPage.tsx | 20 ++ .../business/src/pages/AddNewWorkshopPage.tsx | 20 ++ apps/business/src/pages/CustomersPage.tsx | 12 + .../src/pages/WebsiteSettingsPage.module.css | 192 ++++++++++++ .../src/pages/WebsiteSettingsPage.tsx | 15 + .../src/services/blogCategoryService.ts | 4 + apps/business/src/services/blogService.ts | 8 + apps/business/src/services/brandService.ts | 2 + apps/business/src/services/customerService.ts | 3 + .../services/instructionCategoryService.ts | 4 + .../src/services/instructionService.ts | 8 + .../src/services/portfolioCategoryService.ts | 4 + .../business/src/services/portfolioService.ts | 8 + .../src/services/productCategoryService.ts | 4 + apps/business/src/services/productService.ts | 8 + apps/business/src/services/settingsService.ts | 13 + .../src/services/userProductsService.ts | 4 + .../src/services/videoCategoryService.ts | 4 + apps/business/src/services/videoService.ts | 8 + .../src/services/workshopCategoryService.ts | 4 + apps/business/src/services/workshopService.ts | 8 + apps/business/src/types/category.ts | 10 + apps/business/src/utils/seoMeta.ts | 9 + docs/PROJECT_CONTEXT.md | 4 +- 37 files changed, 1217 insertions(+), 89 deletions(-) create mode 100644 apps/business/src/components/SeoMetaFields.module.css create mode 100644 apps/business/src/components/SeoMetaFields.tsx create mode 100644 apps/business/src/components/WebsiteSchemaSettingsSection.tsx create mode 100644 apps/business/src/utils/seoMeta.ts diff --git a/apps/business/src/components/CategoryModal.tsx b/apps/business/src/components/CategoryModal.tsx index 911f743..59c1f0e 100644 --- a/apps/business/src/components/CategoryModal.tsx +++ b/apps/business/src/components/CategoryModal.tsx @@ -6,6 +6,7 @@ import { useT } from '../i18n/useT' import type { Category, CategoryFormData } from '../types/category' import { flattenCategories } from '../utils/categories' import { SearchableSelect } from './SearchableSelect' +import { SeoMetaFields } from './SeoMetaFields' import styles from './CategoryModal.module.css' interface CategoryModalProps { @@ -41,6 +42,8 @@ export function CategoryModal({ const [nameEn, setNameEn] = useState('') const [nameFa, setNameFa] = useState('') const [description, setDescription] = useState('') + const [seoMetaTitle, setSeoMetaTitle] = useState('') + const [seoMetaDescription, setSeoMetaDescription] = useState('') useEffect(() => { if (open) { @@ -50,6 +53,8 @@ export function CategoryModal({ setNameEn(editingCategory?.nameEn ?? '') setNameFa(editingCategory?.nameFa ?? '') setDescription(editingCategory?.description ?? '') + setSeoMetaTitle(editingCategory?.seoMetaTitle ?? '') + setSeoMetaDescription(editingCategory?.seoMetaDescription ?? '') } else if (mounted) { setClosing(true) const timer = setTimeout(() => { @@ -78,6 +83,8 @@ export function CategoryModal({ nameFa: nameFa.trim(), nameEn: nameEn.trim(), description: description.trim(), + seoMetaTitle, + seoMetaDescription, }) } @@ -170,6 +177,19 @@ export function CategoryModal({ /> + +
- ))} +
-