Desktop: cart checkout two-column + profile account grid

- cart checkout (/cart/$cartId): steps on the left, sticky order summary on the
  right at lg (1320px container); CartSummary becomes an inline card on desktop
  (fixed bottom bar on mobile)
- profile (/profile): contained account layout; menu becomes a 2-col card grid
  on desktop with a heading
- MyLayout: desktop gate now includes /cart/* and /profile
This commit is contained in:
Arda Samadi 2026-06-16 11:19:55 +03:30
parent 7845ab5e75
commit 96034fe61a
4 changed files with 67 additions and 58 deletions

View File

@ -39,7 +39,9 @@ const MyLayout = React.memo(({ children }: { children: React.ReactNode }) => {
p.startsWith("/seller/") || p.startsWith("/seller/") ||
p === "/collections" || p === "/collections" ||
p.startsWith("/collection/") || p.startsWith("/collection/") ||
p === "/cart"; p === "/cart" ||
p.startsWith("/cart/") ||
p === "/profile";
// Auth pages get a full-width desktop canvas (so they can center their own // Auth pages get a full-width desktop canvas (so they can center their own
// card) but no shopping header/footer. // card) but no shopping header/footer.
const isAuth = p === "/login" || p === "/logout"; const isAuth = p === "/login" || p === "/logout";

View File

@ -15,7 +15,7 @@ export const CartSummary = ({
step, step,
isLoading, isLoading,
}: CartSummaryProps) => ( }: CartSummaryProps) => (
<div className="max-w-md mx-auto fixed flex flex-row gap-2 w-full bottom-[50px] left-0 right-0 border-t py-1 px-2 z-50 bg-WHITE"> <div className="max-w-md mx-auto fixed flex flex-row gap-2 w-full bottom-[50px] left-0 right-0 border-t py-1 px-2 z-50 bg-WHITE lg:static lg:max-w-none lg:mx-0 lg:bottom-auto lg:flex-col-reverse lg:gap-4 lg:border lg:border-WHITE3 lg:rounded-xl lg:p-5 lg:z-auto">
<Button <Button
variant="dark" variant="dark"
size="lg" size="lg"

View File

@ -262,63 +262,67 @@ export default function CartDetail() {
isError={isError} isError={isError}
onRetry={refetch} onRetry={refetch}
> >
<> <div className="lg:grid lg:grid-cols-[1fr_360px] lg:gap-7 lg:items-start lg:max-w-[1320px] lg:mx-auto lg:w-full lg:px-8 lg:py-6">
{step === 0 && ( <div className="flex flex-col w-full">
<div className="flex flex-col w-full"> {step === 0 && (
{cart?.items?.map((item, index) => ( <div className="flex flex-col w-full">
<CartItem {cart?.items?.map((item, index) => (
key={item.id} <CartItem
item={item} key={item.id}
onQuantityChange={handleQuantityChange} item={item}
onRemoveItem={handleRemoveItem} onQuantityChange={handleQuantityChange}
isLoading={removeMutation.isPending} onRemoveItem={handleRemoveItem}
hasBorder={ isLoading={removeMutation.isPending}
!!(cart?.items && index !== cart?.items?.length - 1) hasBorder={
} !!(cart?.items && index !== cart?.items?.length - 1)
/> }
))} />
</div> ))}
)} </div>
{step === 1 && ( )}
<ShippingInformation {step === 1 && (
sellerId={cart?.seller?.username || ""} <ShippingInformation
total={calculateTotal(cart)} sellerId={cart?.seller?.username || ""}
setSelectedAddressInfo={setSelectedAddressInfo} total={calculateTotal(cart)}
setSelectedCourierInfo={setSelectedCourierInfo} setSelectedAddressInfo={setSelectedAddressInfo}
setShippingInfoIsLoading={setShippingInfoIsLoading} setSelectedCourierInfo={setSelectedCourierInfo}
selectedAddressInfo={selectedAddressInfo} setShippingInfoIsLoading={setShippingInfoIsLoading}
cartId={cartId} selectedAddressInfo={selectedAddressInfo}
/> cartId={cartId}
)} />
{step === 2 && ( )}
<ReceiverInformation {step === 2 && (
discountValue={Number(cart?.discountValue) || null} <ReceiverInformation
cartItems={cart?.items || []} discountValue={Number(cart?.discountValue) || null}
selectedAddressInfo={selectedAddressInfo} cartItems={cart?.items || []}
selectedCourierInfo={selectedCourierInfo} selectedAddressInfo={selectedAddressInfo}
selectedCourierInfo={selectedCourierInfo}
total={calculateTotal(
cart,
selectedCourierInfo?.courierIsFreightCollect ? 0 : selectedCourierInfo?.deliveryPrice,
Number(cart?.discountValue)
)}
/>
)}
</div>
<div className="lg:sticky lg:top-[88px]">
<CartSummary
total={calculateTotal( total={calculateTotal(
cart, cart,
selectedCourierInfo?.courierIsFreightCollect ? 0 : selectedCourierInfo?.deliveryPrice, step === 2 && !selectedCourierInfo?.courierIsFreightCollect ? selectedCourierInfo?.deliveryPrice : 0,
Number(cart?.discountValue) step === 2 ? Number(cart?.discountValue) : 0
)} )}
onContinue={() => continueHandler()}
step={step}
isLoading={
isCreatingOrder ||
cashOutMutation.isPending ||
shippingInfoIsLoading
}
/> />
)} </div>
</div>
<CartSummary
total={calculateTotal(
cart,
step === 2 && !selectedCourierInfo?.courierIsFreightCollect ? selectedCourierInfo?.deliveryPrice : 0,
step === 2 ? Number(cart?.discountValue) : 0
)}
onContinue={() => continueHandler()}
step={step}
isLoading={
isCreatingOrder ||
cashOutMutation.isPending ||
shippingInfoIsLoading
}
/>
</>
</UiProvider> </UiProvider>
</div> </div>
</div> </div>

View File

@ -125,7 +125,10 @@ export default function Profile() {
]; ];
const navigate = useNavigate(); const navigate = useNavigate();
return ( return (
<div className="flex flex-col gap-0"> <div className="flex flex-col gap-0 lg:max-w-[1000px] lg:mx-auto lg:w-full lg:px-8 lg:py-8">
<h1 className="hidden lg:block text-[28px] font-extrabold mb-2">
حساب کاربری
</h1>
<ProfileTopBar user={user} /> <ProfileTopBar user={user} />
<div <div
className={`flex flex-row h-[55px] w-full items-center gap-2 justify-between px-[16px] active:bg-hover transition`} className={`flex flex-row h-[55px] w-full items-center gap-2 justify-between px-[16px] active:bg-hover transition`}
@ -181,7 +184,7 @@ const MenuItems = ({
}; };
return ( return (
<div className="flex flex-col gap-0 w-full"> <div className="flex flex-col gap-0 w-full lg:grid lg:grid-cols-2 lg:gap-3 lg:mt-4">
{items.map((item: MenuItemType, index: number) => { {items.map((item: MenuItemType, index: number) => {
// Special handling for "support" item // Special handling for "support" item
if (item.pageName === "support") { if (item.pageName === "support") {
@ -239,7 +242,7 @@ const MenuItem = ({
const MenuItemContent = ({ item }: { item: MenuItemType }) => { const MenuItemContent = ({ item }: { item: MenuItemType }) => {
return ( return (
<div <div
className={`flex flex-row gap-2 items-center justify-between px-[16px] active:bg-hover transition cursor-pointer ${item.hasBorder && "border-t-[2px]"} h-[55px] w-full`} className={`flex flex-row gap-2 items-center justify-between px-[16px] active:bg-hover transition cursor-pointer ${item.hasBorder && "border-t-[2px]"} h-[55px] w-full lg:h-auto lg:py-4 lg:px-5 lg:border lg:border-WHITE3 lg:rounded-xl lg:border-t lg:hover:bg-WHITE2`}
> >
<div className="flex flex-row gap-2 items-center"> <div className="flex flex-row gap-2 items-center">
{item.image} {item.image}