From 4c3bf8324e5b4f19d948c953223be95df0dcb671 Mon Sep 17 00:00:00 2001 From: Alireza Hassani Date: Tue, 8 Sep 2026 14:12:57 +0330 Subject: [PATCH] Add customer SMS/Excel tools, selection bar, and sticky import toasts. Bulk and single SMS from Users, row selection with overflow summary, persistent large import toasts, and business SMS sender in Super Admin. Co-authored-by: Cursor --- apps/business/src/components/BlogCard.tsx | 4 + .../CustomerActionsOverflowMenu.module.css | 90 ++++ .../CustomerActionsOverflowMenu.tsx | 193 ++++++++ .../src/components/InstructionCard.tsx | 4 + .../src/components/OpenOnWebsiteControl.tsx | 24 + .../business/src/components/PortfolioCard.tsx | 4 + apps/business/src/components/ProductCard.tsx | 4 + .../src/components/SendCustomerSmsModal.tsx | 196 ++++++++ apps/business/src/components/Toast.module.css | 42 ++ apps/business/src/components/VideoCard.tsx | 4 + apps/business/src/components/WorkshopCard.tsx | 4 + apps/business/src/context/ToastContext.tsx | 56 ++- apps/business/src/fonts/iranyekan.css | 27 +- apps/business/src/i18n/messages.ts | 60 +++ .../src/pages/CustomersPage.module.css | 122 ++++- apps/business/src/pages/CustomersPage.tsx | 417 +++++++++++++++--- apps/business/src/pages/StoreItemsPage.tsx | 1 + apps/business/src/services/customerService.ts | 83 +++- apps/business/src/utils/fitFixedPopover.ts | 35 ++ apps/business/src/utils/websiteLinks.ts | 80 ++++ apps/super-admin/src/fonts/iranyekan.css | 27 +- .../src/pages/BusinessesPage.module.css | 15 +- apps/super-admin/src/pages/BusinessesPage.tsx | 21 + .../src/pages/TemplatesPage.module.css | 2 +- apps/super-admin/src/pages/TemplatesPage.tsx | 4 +- .../src/services/businessService.ts | 1 + apps/super-admin/src/types/business.ts | 2 + docs/PROJECT_CONTEXT.md | 7 +- .../src/components/RichTextEditor.module.css | 60 +++ .../src/components/RichTextEditor.tsx | 157 ++++++- 30 files changed, 1597 insertions(+), 149 deletions(-) create mode 100644 apps/business/src/components/CustomerActionsOverflowMenu.module.css create mode 100644 apps/business/src/components/CustomerActionsOverflowMenu.tsx create mode 100644 apps/business/src/components/OpenOnWebsiteControl.tsx create mode 100644 apps/business/src/components/SendCustomerSmsModal.tsx create mode 100644 apps/business/src/utils/fitFixedPopover.ts diff --git a/apps/business/src/components/BlogCard.tsx b/apps/business/src/components/BlogCard.tsx index 72c82b3..ff7095e 100644 --- a/apps/business/src/components/BlogCard.tsx +++ b/apps/business/src/components/BlogCard.tsx @@ -9,6 +9,8 @@ import { } from '../services/blogService' import { useT } from '../i18n/useT' import { textLocaleAttrs } from '../utils/textLocale' +import { buildWebsiteContentUrl } from '../utils/websiteLinks' +import { OpenOnWebsiteControl } from './OpenOnWebsiteControl' import { Tooltip } from './Tooltip' import cardStyles from './BlogCard.module.css' import controlStyles from './ProductCard.module.css' @@ -47,6 +49,7 @@ export function BlogCard({ // In FA UI, keep cards RTL even when title/abstract are English. const titleDir = isFa ? 'rtl' : titleLocale.dir const abstractDir = isFa ? 'rtl' : abstractLocale.dir + const websiteUrl = buildWebsiteContentUrl('blog', blog) return (
@@ -120,6 +123,7 @@ export function BlogCard({ + + + + {open && + popoverPos && + createPortal( +
+ {items.map(({ key, label, icon: Icon, disabled: itemDisabled, onClick }) => ( + + ))} +
, + document.body, + )} + + ) +} diff --git a/apps/business/src/components/InstructionCard.tsx b/apps/business/src/components/InstructionCard.tsx index 43cde8b..594b847 100644 --- a/apps/business/src/components/InstructionCard.tsx +++ b/apps/business/src/components/InstructionCard.tsx @@ -9,6 +9,8 @@ import { } from '../services/instructionService' import { useT } from '../i18n/useT' import { textLocaleAttrs } from '../utils/textLocale' +import { buildWebsiteContentUrl } from '../utils/websiteLinks' +import { OpenOnWebsiteControl } from './OpenOnWebsiteControl' import { Tooltip } from './Tooltip' import cardStyles from './BlogCard.module.css' import controlStyles from './ProductCard.module.css' @@ -49,6 +51,7 @@ export function InstructionCard({ : video.videoProvider === 'aparat' ? 'Aparat' : null + const websiteUrl = buildWebsiteContentUrl('instruction', video) return (
@@ -118,6 +121,7 @@ export function InstructionCard({ + + {externalUrl ? ( + {showTranslationControls ? ( + + +
+ {error ?

{error}

: null} + +
+ +