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 === "/collections" ||
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
// card) but no shopping header/footer.
const isAuth = p === "/login" || p === "/logout";

View File

@ -15,7 +15,7 @@ export const CartSummary = ({
step,
isLoading,
}: 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
variant="dark"
size="lg"

View File

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

View File

@ -125,7 +125,10 @@ export default function Profile() {
];
const navigate = useNavigate();
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} />
<div
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 (
<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) => {
// Special handling for "support" item
if (item.pageName === "support") {
@ -239,7 +242,7 @@ const MenuItem = ({
const MenuItemContent = ({ item }: { item: MenuItemType }) => {
return (
<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">
{item.image}