Vitron-Front/app/routes/store.$storeId.tsx
Arda Samadi 4af143bccf Desktop: seller dashboard shell + gate carousel arrows to product gallery
- new store.$storeId.tsx layout: sticky admin sidebar (store/products/orders/
  financial/shipping/threads/settings) beside content at lg; mobile unchanged
- MyLayout: store/* gets a full-width desktop canvas (own sidebar), no shopper
  header/footer, mobile store-nav hidden at lg
- store home: hide the redundant mobile store header at lg
- ProductImageCarousel: prev/next arrows now opt-in (showArrows) so they only
  appear on the product gallery, not every masonry card
2026-06-17 12:28:59 +03:30

87 lines
3.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Link, Outlet, useLocation, useParams } from "@remix-run/react";
import {
LayoutGrid,
Package,
ClipboardList,
Wallet,
Truck,
MessageCircle,
Settings,
ArrowRight,
} from "lucide-react";
import { useSellerData } from "~/requestHandler/use-seller-hooks";
import SellerLogo from "~/components/SellerLogo";
/**
* Desktop layout for the seller dashboard. Renders a sticky admin sidebar
* next to the page content at lg+; on mobile it's just the page content
* (the existing mobile dashboard, with its store-mode bottom nav, is unchanged).
*/
export default function StoreLayout() {
const { storeId } = useParams();
const location = useLocation();
const { data } = useSellerData(storeId);
const base = `/store/${storeId}`;
const NAV = [
{ label: "فروشگاه", to: base, icon: LayoutGrid, exact: true },
{ label: "محصولات", to: `${base}/products`, icon: Package },
{ label: "سفارش‌ها", to: `${base}/orders`, icon: ClipboardList },
{ label: "مالی", to: `${base}/financial-dashboard`, icon: Wallet },
{ label: "روش ارسال", to: `${base}/shipping-method`, icon: Truck },
{ label: "پیام‌ها", to: `${base}/threads`, icon: MessageCircle },
{ label: "تنظیمات", to: `${base}/setting`, icon: Settings },
];
const isActive = (item: { to: string; exact?: boolean }) =>
item.exact
? location.pathname === item.to
: location.pathname.startsWith(item.to);
return (
<div className="lg:max-w-[1320px] lg:mx-auto lg:w-full lg:px-8 lg:py-8 lg:grid lg:grid-cols-[260px_1fr] lg:gap-7 lg:items-start">
{/* Desktop admin sidebar */}
<aside className="hidden lg:block lg:sticky lg:top-6 border border-WHITE3 rounded-2xl overflow-hidden">
<div className="p-4 border-b border-WHITE3 flex items-center gap-3">
<SellerLogo size="sm" src={data?.storeLogo} alt="store" />
<div className="min-w-0">
<p className="font-bold text-[15px] truncate">
{data?.storeName || "فروشگاه من"}
</p>
<p className="text-GRAY text-[12px]">پنل مدیریت</p>
</div>
</div>
<nav className="p-2.5 flex flex-col gap-0.5">
{NAV.map((n) => (
<Link
key={n.to}
to={n.to}
prefetch="intent"
className={`flex items-center gap-3 px-3.5 py-3 rounded-xl text-[14.5px] font-semibold transition-colors ${
isActive(n)
? "bg-BLACK text-white"
: "text-BLACK2 hover:bg-WHITE2"
}`}
>
<n.icon size={20} />
{n.label}
</Link>
))}
<Link
to="/"
className="flex items-center gap-3 px-3.5 py-3 rounded-xl text-[14.5px] font-semibold text-BLACK2 hover:bg-WHITE2 transition-colors"
>
<ArrowRight size={20} />
بازگشت به فروشگاه
</Link>
</nav>
</aside>
{/* Page content */}
<div className="min-w-0">
<Outlet />
</div>
</div>
);
}