feat(seller): mobile brand header redesign (cover + overlapping logo)

Bring the seller page mobile header in line with the design / desktop:
replace the plain top bar + centered logo with a cover banner, a floating
circular back button (safe-area aware), an overlapping rounded logo, the
store name + verified badge + @handle, a clean borderless stats row
(محصول / دنبال‌کننده / امتیاز), the description, and follow + message-icon
actions. Search bar and product masonry unchanged. Desktop untouched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Arda Samadi 2026-06-27 21:44:20 +03:30
parent 252d3f8f50
commit e6574b1e9e

View File

@ -19,8 +19,9 @@ import {
UserMinus, UserMinus,
Shirt, Shirt,
BadgeCheck, BadgeCheck,
ArrowRight,
MessageCircle,
} from "lucide-react"; } from "lucide-react";
import HeaderWithSupport from "../components/HeaderWithSupport";
import { useState, useEffect } from "react"; import { useState, useEffect } from "react";
import { DrawerContent, Drawer } from "../components/ui/drawer"; import { DrawerContent, Drawer } from "../components/ui/drawer";
import { Button } from "../components/ui/button"; import { Button } from "../components/ui/button";
@ -283,96 +284,115 @@ export default function Seller() {
<div className="border-b border-WHITE3 mt-6" /> <div className="border-b border-WHITE3 mt-6" />
</div> </div>
{/* Mobile header */} {/* Mobile brand header (cover + overlapping logo + stats + actions) */}
<div className="relative lg:hidden"> <div className="lg:hidden">
<HeaderWithSupport {/* Cover */}
title={seller?.storeName || ""} <div className="relative h-[150px] bg-gradient-to-br from-VITROWN_BLUE to-[#14213d]">
onBack={handleBack} <div className="absolute inset-0 bg-gradient-to-t from-black/35 to-transparent" />
/> <button
<div className="flex flex-col items-center justify-center gap-2 pt-2"> type="button"
<SellerLogo src={seller?.storeLogo} alt="store logo" /> onClick={handleBack}
aria-label="بازگشت"
className="absolute z-20 right-4 w-10 h-10 rounded-full bg-WHITE/90 backdrop-blur shadow-md flex items-center justify-center text-BLACK"
style={{ top: "calc(env(safe-area-inset-top, 0px) + 12px)" }}
>
<ArrowRight size={22} />
</button>
</div>
{/* Head */}
<div className="px-4 -mt-10 relative z-10">
<div className="w-[84px] h-[84px] rounded-[24px] border-4 border-WHITE shadow-md overflow-hidden bg-WHITE3">
{seller?.storeLogo ? (
<img
src={seller.storeLogo}
alt={seller?.storeName || "store"}
className="w-full h-full object-cover"
/>
) : null}
</div>
<h1 className="flex items-center gap-1.5 text-[21px] font-extrabold mt-3">
{seller?.storeName}
{seller?.isVerified ? (
<BadgeCheck className="text-BLUE" size={18} />
) : null}
</h1>
{seller?.username ? (
<p className="text-GRAY text-[13px] mt-0.5" dir="ltr">
@{seller.username}
</p>
) : null}
{/* Stats */}
<div className="flex gap-8 py-3.5 mt-3 border-y border-WHITE3">
<div>
<b className="block text-[17px] font-extrabold">
{seller?.productCount ?? 0}
</b>
<span className="text-GRAY text-[11.5px]">محصول</span>
</div>
<div>
<b className="block text-[17px] font-extrabold">
{seller?.followerCount ?? 0}
</b>
<span className="text-GRAY text-[11.5px]">دنبالکننده</span>
</div>
<div>
<b className="flex items-center gap-1 text-[17px] font-extrabold">
{seller?.productReviewsCount ? seller?.reviewAverage : "—"}
{seller?.productReviewsCount ? (
<Star size={14} className="fill-BLACK" />
) : null}
</b>
<span className="text-GRAY text-[11.5px]">امتیاز</span>
</div>
</div>
{/* Description */}
{seller?.storeDescription ? (
<div className="mt-3">
<ReadMoreText
sellerData={seller}
text={seller?.storeDescription || ""}
maxLength={150}
/>
</div>
) : null}
{/* Actions */}
<div className="flex gap-2.5 mt-4">
<Button
variant="dark"
size="lg"
className="flex-1"
onClick={handleFollowToggle}
disabled={isFollowMutating || isFollowStatusLoading}
>
{isFollowed ? (
<>
<Check size={22} />
دنبال شده
</>
) : (
<>
<UserPlus size={22} />
دنبال کردن
</>
)}
</Button>
<Button
variant="outline"
size="lg"
className="shrink-0 px-4"
aria-label="ارسال پیام"
onClick={() => {
handleCreateChatThread();
}}
disabled={!seller?.id || isCreatingChatThread}
>
<MessageCircle size={22} />
</Button>
</div>
</div> </div>
</div> </div>
<div className="w-full"> <div className="w-full">
<div className="w-full p-4 lg:hidden">
<div className="flex px-4 border bg-WHITE3 rounded-[10px] w-full py-2">
<div className="w-full border-l flex-2 flex flex-col items-center justify-center">
<p className="text-R12">{seller?.followerCount}</p>
<p className="text-R12">دنبال کننده</p>
</div>
<div className="w-full flex-3 flex flex-col items-center justify-center">
{seller?.productReviewsCount ? (
<>
<div className="flex items-center gap-1">
<p className="text-R12">{seller?.reviewAverage}</p>
<p className="text-R8">
(از {seller?.productReviewsCount} نظر)
</p>
</div>
<div className="flex flex-1 items-center flex-row-reverse">
{Array.from({ length: 5 }).map((_, index) => (
<Star
key={index}
className={
index < (seller?.reviewAverage || 0)
? "fill-BLACK"
: "fill-White"
}
size={12}
/>
))}
</div>
</>
) : (
<p className="text-R12">بدون امتیاز</p>
)}
</div>
<div className="w-full border-r flex-2 flex flex-col items-center justify-center">
<p className="text-R12">{seller?.productCount}</p>
<p className="text-R12">تعداد محصولات</p>
</div>
</div>
</div>
<div className="mt-6 px-4 lg:hidden">
<ReadMoreText
sellerData={seller}
text={seller?.storeDescription || ""}
maxLength={150}
/>
</div>
<div className="mt-4 px-4 w-full flex py-4 gap-4 lg:hidden">
<Button
variant="dark"
size="lg"
className="w-full"
onClick={handleFollowToggle}
disabled={isFollowMutating || isFollowStatusLoading}
>
{isFollowed ? (
<>
<Check size={24} />
دنبال شده
</>
) : (
<>
<UserPlus size={24} />
دنبال کردن
</>
)}
</Button>
<Button
variant="primary"
onClick={() => {
handleCreateChatThread();
}}
disabled={!seller?.id || isCreatingChatThread}
size="lg"
className="w-full"
>
{isCreatingChatThread ? "در حال اتصال..." : "ارسال پیام"}
</Button>
</div>
{/* Search Bar (mobile) */} {/* Search Bar (mobile) */}
<div className="lg:hidden"> <div className="lg:hidden">
<SearchTopBar <SearchTopBar