From e652c255c956acddb59bfe1ac52a0c744f0cc1ec Mon Sep 17 00:00:00 2001 From: payacom <59262811+payacom@users.noreply.github.com> Date: Wed, 16 Sep 2026 14:06:57 +0330 Subject: [PATCH] Fix Projects nav double-click, shop verify badge, add send-to-users everywhere MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - new-project/layout.tsx was hardcoding currentPage="/projects" while the real route is /new-project, so TabNavigation's isExactRoot guard thought it was already on the Projects tab and preventDefault'd the first click with no navigation — now passes the real path (isActive's highlight logic already had a dedicated case for /new-project, so nothing else changes) - resolveShopVerificationTier: shop verify checkmarks always render green regardless of the underlying tier, applied at all 3 shop render sites - Add a "send to users" icon/button next to share on the product detail page, the owner product-manage page, and the shop profile pages (public + owner), reusing/mirroring the existing SendProductModal pattern - New SendShopModal + sharedShop chat-bubble kind (ChatMessageCard via SharedShopBubble) so a whole shop can be sent into a chat, not just one product — backed by the new POST /shops/:id/send endpoint Co-Authored-By: Claude Sonnet 5 --- src/app/(projects)/new-project/layout.tsx | 45 ++-- src/app/shops/[shopId]/page.tsx | 28 ++- .../[shopId]/products/[listingId]/page.tsx | 18 ++ .../[listingId]/ListingDetailClient.tsx | 21 ++ .../profile/[shopId]/ShopProfileClient.tsx | 28 ++- src/components/chat/ChatMessageCard.tsx | 12 + src/components/chat/SharedShopBubble.tsx | 45 ++++ src/components/main/VerificationBadge.tsx | 8 + src/components/shops/SendShopModal.tsx | 205 ++++++++++++++++++ src/components/shops/ShopProductAuthor.tsx | 9 +- src/locales/en/common.json | 4 + src/locales/fa/common.json | 4 + 12 files changed, 401 insertions(+), 26 deletions(-) create mode 100644 src/components/chat/SharedShopBubble.tsx create mode 100644 src/components/shops/SendShopModal.tsx diff --git a/src/app/(projects)/new-project/layout.tsx b/src/app/(projects)/new-project/layout.tsx index a255eea..963148b 100644 --- a/src/app/(projects)/new-project/layout.tsx +++ b/src/app/(projects)/new-project/layout.tsx @@ -1,20 +1,25 @@ -import Header from "@/components/main/Header"; -import TabNavigation from "@/components/TabNavigation"; -import LocalePageShell from "@/components/i18n/LocalePageShell"; -import { generateSeoPageMetadata } from "@/lib/i18n/server"; - -export async function generateMetadata() { - return generateSeoPageMetadata("newProject", { - index: false, - }); -} - -export default function Layout({ children }: { children: React.ReactNode }) { - return ( -
-
- {children} - -
- ); -} +import Header from "@/components/main/Header"; +import TabNavigation from "@/components/TabNavigation"; +import LocalePageShell from "@/components/i18n/LocalePageShell"; +import { generateSeoPageMetadata } from "@/lib/i18n/server"; + +export async function generateMetadata() { + return generateSeoPageMetadata("newProject", { + index: false, + }); +} + +export default function Layout({ children }: { children: React.ReactNode }) { + return ( +
+
+ {children} + {/* واقعاً توی /new-project هستیم، نه /projects — قبلاً اینجا "/projects" هاردکد + شده بود که باعث می‌شد تبِ پروژه‌ها فکر کنه از قبل توی روتِ خودشه (isExactRoot) + و اولین کلیک روی اون تب preventDefault بشه بدون navigate (کاربر مجبور می‌شد + دوبار بزنه). isActive توی TabNavigation.tsx از قبل شرطِ جداگانه برای + "/new-project" داره، پس هایلایتِ تب دست‌نخورده می‌مونه */} + +
+ ); +} diff --git a/src/app/shops/[shopId]/page.tsx b/src/app/shops/[shopId]/page.tsx index 8fd5e82..e6467d2 100644 --- a/src/app/shops/[shopId]/page.tsx +++ b/src/app/shops/[shopId]/page.tsx @@ -6,9 +6,12 @@ import LocalePageShell from "@/components/i18n/LocalePageShell"; import Header from "@/components/main/Header"; import { IMAGE_BASE_URL, staticIconUrl } from "@/components/main/BaseUrl"; import ShareShopModal from "@/components/shops/ShareShopModal"; +import SendShopModal from "@/components/shops/SendShopModal"; import ShopProductListRow from "@/components/shops/ShopProductListRow"; import PageTitle from "@/components/settings/PageTitle"; -import VerificationBadge from "@/components/main/VerificationBadge"; +import VerificationBadge, { + resolveShopVerificationTier, +} from "@/components/main/VerificationBadge"; import BoldIcon from "@/components/ui/BoldIcon"; import TabNavigation from "@/components/TabNavigation"; import useAxios from "@/hooks/useAxios"; @@ -40,6 +43,7 @@ export default function ShopProductsPage() { const [search, setSearch] = useState(""); const [onlyInStock, setOnlyInStock] = useState(false); const [showShareModal, setShowShareModal] = useState(false); + const [showSendModal, setShowSendModal] = useState(false); useEffect(() => { request<{ shop: ShopHeader }>("GET", `/shops/${shopId}`) @@ -114,9 +118,20 @@ export default function ShopProductsPage() { )} > {shop?.name} - + + + + ); + })} + + )} + + + + + )} + + ); +} diff --git a/src/components/shops/ShopProductAuthor.tsx b/src/components/shops/ShopProductAuthor.tsx index 5db7607..67695d2 100644 --- a/src/components/shops/ShopProductAuthor.tsx +++ b/src/components/shops/ShopProductAuthor.tsx @@ -1,7 +1,9 @@ "use client"; import { IMAGE_BASE_URL } from "@/components/main/BaseUrl"; -import VerificationBadge from "@/components/main/VerificationBadge"; +import VerificationBadge, { + resolveShopVerificationTier, +} from "@/components/main/VerificationBadge"; type ShopProductAuthorProps = { shopName: string; @@ -28,7 +30,10 @@ export default function ShopProductAuthor({ )} {shopName} - + ); diff --git a/src/locales/en/common.json b/src/locales/en/common.json index 92dddd0..76179a2 100644 --- a/src/locales/en/common.json +++ b/src/locales/en/common.json @@ -2851,6 +2851,7 @@ "editShopButton": "Edit shop", "viewPublicProfile": "View shop page", "viewProduct": "View product", + "viewShop": "View shop", "myOrdersFromShop": "My orders from this shop", "noOrdersFromShop": "You haven't ordered from this shop yet", "satisfactionLabel": "Product satisfaction", @@ -2869,6 +2870,9 @@ "sendProductTitle": "Send product", "sentProductToCount": "Product sent to {{count}} people", "sendProductError": "Failed to send product", + "sendShopTitle": "Send shop", + "sentShopToCount": "Shop sent to {{count}} people", + "sendShopError": "Failed to send shop", "noChatMessagesYet": "No messages yet", "performance": { "totalRevenue": "Total revenue (Toman)", diff --git a/src/locales/fa/common.json b/src/locales/fa/common.json index e3c8f10..8cb749c 100644 --- a/src/locales/fa/common.json +++ b/src/locales/fa/common.json @@ -2856,6 +2856,7 @@ "editShopButton": "ویرایش فروشگاه", "viewPublicProfile": "نمایش صفحه فروشگاه", "viewProduct": "مشاهده کالا", + "viewShop": "مشاهده فروشگاه", "myOrdersFromShop": "پیگیری سفارشات من", "noOrdersFromShop": "هنوز سفارشی از این فروشگاه ثبت نکرده‌اید", "satisfactionLabel": "رضایت از کالاها", @@ -2874,6 +2875,9 @@ "sendProductTitle": "ارسال کالا", "sentProductToCount": "کالا به {{count}} نفر ارسال شد", "sendProductError": "خطا در ارسال کالا", + "sendShopTitle": "ارسال فروشگاه", + "sentShopToCount": "فروشگاه به {{count}} نفر ارسال شد", + "sendShopError": "خطا در ارسال فروشگاه", "noChatMessagesYet": "هنوز پیامی رد و بدل نشده است", "performance": { "totalRevenue": "درآمد کل (تومان)",