responsive
This commit is contained in:
@@ -14,10 +14,10 @@ const CategoryHero: FC = () => {
|
|||||||
backgroundImage: "linear-gradient(108.5deg, rgba(33, 88, 140, 0.1) 89.65%, rgba(237, 243, 248, 0.3) 100%)",
|
backgroundImage: "linear-gradient(108.5deg, rgba(33, 88, 140, 0.1) 89.65%, rgba(237, 243, 248, 0.3) 100%)",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div className="flex flex-col lg:flex-row lg:items-center gap-6 lg:gap-10">
|
<div className="flex flex-col gap-6 lg:flex-row lg:items-center lg:gap-10">
|
||||||
<div className="flex-1 space-y-3 sm:space-y-4">
|
<div className="min-w-0 flex-1 space-y-3 sm:space-y-4">
|
||||||
<h1 className="text-[#0A1B2C] text-2xl sm:text-3xl lg:text-[32px] font-bold">{CATEGORY_TITLE}</h1>
|
<h1 className="text-2xl font-bold text-[#0A1B2C] sm:text-3xl lg:text-[32px]">{CATEGORY_TITLE}</h1>
|
||||||
<p className="text-sm text-[#0A1B2C]/80 leading-7 max-w-140">{CATEGORY_DESCRIPTION}</p>
|
<p className="max-w-140 text-sm leading-7 text-[#0A1B2C]/80">{CATEGORY_DESCRIPTION}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="relative z-10 mx-auto shrink-0 lg:mx-0 lg:-mb-28">
|
<div className="relative z-10 mx-auto shrink-0 lg:mx-0 lg:-mb-28">
|
||||||
@@ -27,13 +27,13 @@ const CategoryHero: FC = () => {
|
|||||||
width={360}
|
width={360}
|
||||||
height={360}
|
height={360}
|
||||||
priority
|
priority
|
||||||
className="aspect-square w-55 sm:w-70 lg:w-[320px] rounded-2xl sm:rounded-3xl object-cover shadow-[0px_-4px_12px_0px_rgba(0,0,0,0.12)]"
|
className="aspect-square w-48 rounded-2xl object-cover shadow-[0px_-4px_12px_0px_rgba(0,0,0,0.12)] sm:w-60 sm:rounded-3xl lg:w-80"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<nav aria-label="مسیر صفحه" className="relative z-0 flex items-center justify-start gap-2 bg-secondary px-4 sm:px-8 lg:px-30 py-3 text-sm text-[#3F4D5A]">
|
<nav aria-label="مسیر صفحه" className="relative z-0 flex items-center justify-start gap-2 overflow-x-auto bg-secondary px-4 py-3 text-sm whitespace-nowrap text-[#3F4D5A] sm:px-8 lg:px-30">
|
||||||
<Link href="/" className="transition-colors hover:text-primary">
|
<Link href="/" className="transition-colors hover:text-primary">
|
||||||
صفحه اصلی
|
صفحه اصلی
|
||||||
</Link>
|
</Link>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { CATEGORY_PRODUCTS } from "../constants";
|
|||||||
|
|
||||||
const CategoryProducts: FC = () => {
|
const CategoryProducts: FC = () => {
|
||||||
return (
|
return (
|
||||||
<GridWrapper desktop={4} mobile={2} gapDesktop={24} gapMobile={12}>
|
<GridWrapper desktop={4} mobile={2} gapDesktop={24} gapMobile={12} className="sm:gap-4">
|
||||||
{CATEGORY_PRODUCTS.map((title, index) => (
|
{CATEGORY_PRODUCTS.map((title, index) => (
|
||||||
<ProductCard key={`${title}-${index}`} title={title} />
|
<ProductCard key={`${title}-${index}`} title={title} />
|
||||||
))}
|
))}
|
||||||
|
|||||||
@@ -5,13 +5,13 @@ import { SORT_OPTIONS } from "../constants";
|
|||||||
|
|
||||||
const CategoryToolbar: FC = () => {
|
const CategoryToolbar: FC = () => {
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center gap-4">
|
<div className="flex flex-col gap-3 sm:flex-row sm:items-center sm:gap-4">
|
||||||
<div className="max-w-50">
|
<div className="min-w-0 flex-1">
|
||||||
<Input variant="search" placeholder="جستجو..." className="rounded-xl border-[#E9EFF4]" />
|
<Input variant="search" placeholder="جستجو..." className="rounded-xl border-[#E9EFF4]" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="max-w-50">
|
<div className="min-w-0 w-full sm:w-auto sm:max-w-50">
|
||||||
<Select options={SORT_OPTIONS} placeholder="مرتبسازی" className="min-w-50 rounded-xl border-[#E9EFF4]" />
|
<Select options={SORT_OPTIONS} placeholder="مرتبسازی" className="w-full rounded-xl border-[#E9EFF4] sm:min-w-50" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -9,14 +9,12 @@ const CategoryDetailPage = () => {
|
|||||||
<div>
|
<div>
|
||||||
<CategoryHero />
|
<CategoryHero />
|
||||||
|
|
||||||
<div className="space-y-4 px-4 mt-10 sm:space-y-5 sm:px-8 lg:px-30 pt-8 sm:pt-10 pb-8 sm:pb-10">
|
<div className="px-4 pb-8 pt-8 sm:px-8 sm:pb-10 sm:pt-10 lg:px-30 lg:pb-10 lg:pt-16">
|
||||||
<div className="lg:grid lg:gap-x-6">
|
|
||||||
<CategoryToolbar />
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex flex-col gap-4 lg:flex-row lg:items-start lg:gap-6">
|
<div className="flex flex-col gap-4 lg:flex-row lg:items-start lg:gap-6">
|
||||||
<CategoryFilters />
|
<CategoryFilters />
|
||||||
<div className="min-w-0 flex-1">
|
|
||||||
|
<div className="min-w-0 flex-1 space-y-4 sm:space-y-5">
|
||||||
|
<CategoryToolbar />
|
||||||
<CategoryProducts />
|
<CategoryProducts />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { BREADCRUMB_ITEMS } from "../constants";
|
|||||||
|
|
||||||
const ProductBreadcrumb: FC = () => {
|
const ProductBreadcrumb: FC = () => {
|
||||||
return (
|
return (
|
||||||
<nav aria-label="مسیر صفحه" className="flex items-center justify-start gap-2 bg-secondary px-4 py-3 text-sm text-[#3F4D5A] sm:px-8 lg:px-30">
|
<nav aria-label="مسیر صفحه" className="flex items-center justify-start gap-2 overflow-x-auto bg-secondary px-4 py-3 text-sm whitespace-nowrap text-[#3F4D5A] sm:px-8 lg:px-30">
|
||||||
{BREADCRUMB_ITEMS.map((item, index) => (
|
{BREADCRUMB_ITEMS.map((item, index) => (
|
||||||
<Fragment key={item.label}>
|
<Fragment key={item.label}>
|
||||||
{index > 0 && <ArrowLeft2 size={14} color="currentColor" className="shrink-0" />}
|
{index > 0 && <ArrowLeft2 size={14} color="currentColor" className="shrink-0" />}
|
||||||
|
|||||||
@@ -17,19 +17,21 @@ const ProductDetail: FC = () => {
|
|||||||
<>
|
<>
|
||||||
<ProductBreadcrumb />
|
<ProductBreadcrumb />
|
||||||
|
|
||||||
<div className="px-4 py-6 sm:px-8 sm:py-8 lg:px-30">
|
<div className="pb-28 lg:pb-0">
|
||||||
<div className="flex flex-col items-start gap-8 lg:flex-row lg:items-start lg:gap-10">
|
<div className="px-4 py-6 sm:px-8 sm:py-8 lg:px-30">
|
||||||
<ProductGallery images={PRODUCT_GALLERY_IMAGES} alt={PRODUCT_TITLE} />
|
<div className="flex flex-col items-start gap-6 sm:gap-8 lg:flex-row lg:items-start lg:gap-10">
|
||||||
<div className="flex w-full min-w-0 flex-1 flex-col items-end">
|
<ProductGallery images={PRODUCT_GALLERY_IMAGES} alt={PRODUCT_TITLE} />
|
||||||
<ProductPurchaseOptions selectedTier={selectedTier} onSelectTier={setSelectedTier} />
|
<div className="flex w-full min-w-0 flex-1 flex-col">
|
||||||
<ProductOrderActions selectedTier={selectedTier} />
|
<ProductPurchaseOptions selectedTier={selectedTier} onSelectTier={setSelectedTier} />
|
||||||
|
<ProductOrderActions selectedTier={selectedTier} />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<ProductTabs />
|
<ProductTabs />
|
||||||
<ProductRelated />
|
<ProductRelated />
|
||||||
<ContactCtaSection />
|
<ContactCtaSection />
|
||||||
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -13,12 +13,12 @@ const ProductGallery: FC<ProductGalleryProps> = ({ images, alt }) => {
|
|||||||
const [activeIndex, setActiveIndex] = useState(0);
|
const [activeIndex, setActiveIndex] = useState(0);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex w-full shrink-0 flex-col gap-3 lg:w-[45%] lg:max-w-120">
|
<div className="flex w-full shrink-0 flex-col gap-3 sm:gap-4 lg:w-[45%] lg:max-w-120">
|
||||||
<div className="relative aspect-square w-full overflow-hidden rounded-2xl bg-[#F7FAFC]">
|
<div className="relative aspect-square w-full overflow-hidden rounded-xl bg-[#F7FAFC] sm:rounded-2xl">
|
||||||
<Image src={images[activeIndex]} alt={alt} fill priority className="object-contain p-4" sizes="(max-width: 1024px) 100vw, 480px" />
|
<Image src={images[activeIndex]} alt={alt} fill priority className="object-contain p-4" sizes="(max-width: 1024px) 100vw, 480px" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="grid grid-cols-4 gap-2.5">
|
<div className="grid grid-cols-4 gap-2 sm:gap-2.5">
|
||||||
{images.slice(0, 4).map((image, index) => (
|
{images.slice(0, 4).map((image, index) => (
|
||||||
<button
|
<button
|
||||||
key={index}
|
key={index}
|
||||||
|
|||||||
@@ -10,18 +10,18 @@ type ProductOrderActionsProps = {
|
|||||||
|
|
||||||
const ProductOrderActions = ({ selectedTier }: ProductOrderActionsProps) => {
|
const ProductOrderActions = ({ selectedTier }: ProductOrderActionsProps) => {
|
||||||
return (
|
return (
|
||||||
<div className="mt-5 flex w-full flex-col gap-3 self-end rounded-t-2xl bg-white px-4 py-4 shadow-[0px_-4px_34px_0px_#1A456C14] sm:flex-row sm:items-center sm:justify-between sm:gap-5 sm:px-5 sm:py-4">
|
<div className="fixed inset-x-0 bottom-0 z-40 flex w-full flex-col gap-3 rounded-t-2xl bg-white px-4 py-3 shadow-[0px_-4px_34px_0px_#1A456C14] sm:flex-row sm:items-center sm:justify-between sm:gap-4 sm:px-8 sm:py-4 lg:relative lg:inset-auto lg:mt-5 lg:gap-5 lg:rounded-t-2xl lg:px-5 lg:shadow-[0px_-4px_34px_0px_#1A456C14]">
|
||||||
<div className="space-y-1 text-right">
|
<div className="space-y-1 text-right">
|
||||||
<p className="text-base font-bold text-[#0A1B2C] sm:text-lg">{formatPrice(selectedTier.totalPrice)}﷼</p>
|
<p className="text-base font-bold text-[#0A1B2C] sm:text-lg">{formatPrice(selectedTier.totalPrice)}﷼</p>
|
||||||
<div className="flex items-center justify-end gap-2">
|
<div className="flex flex-wrap items-center justify-end gap-2">
|
||||||
<span className="text-xs text-[#0A1B2C] sm:text-sm">{formatPrice(selectedTier.unitPrice)} ﷼ به ازای هر عدد</span>
|
<span className="text-xs text-[#0A1B2C] sm:text-sm">{formatPrice(selectedTier.unitPrice)} ﷼ به ازای هر عدد</span>
|
||||||
<span className="rounded-lg bg-[#00893E] px-2 py-0.5 text-[10px] font-medium text-white sm:text-xs">{PRODUCT_PROFIT_PERCENT}٪ سود</span>
|
<span className="rounded-lg bg-[#00893E] px-2 py-0.5 text-[10px] font-medium text-white sm:text-xs">{PRODUCT_PROFIT_PERCENT}٪ سود</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="hidden h-16 w-0 shrink-0 border-s-2 border-primary sm:block" />
|
<div className="hidden h-16 w-0 shrink-0 border-s-2 border-primary lg:block" />
|
||||||
|
|
||||||
<div className="flex flex-col gap-2 sm:flex-row sm:items-end sm:gap-5">
|
<div className="flex flex-col gap-2 sm:flex-row sm:items-end sm:gap-4 lg:gap-5">
|
||||||
<div className="w-full space-y-1 sm:w-32">
|
<div className="w-full space-y-1 sm:w-32">
|
||||||
<span className="block text-right text-xs font-medium text-[#0A1B2C]">تعداد</span>
|
<span className="block text-right text-xs font-medium text-[#0A1B2C]">تعداد</span>
|
||||||
<Select options={[...STICKY_QUANTITY_OPTIONS]} defaultValue="1000" className="h-10 rounded-xl border-[#E9EEF2] text-sm" />
|
<Select options={[...STICKY_QUANTITY_OPTIONS]} defaultValue="1000" className="h-10 rounded-xl border-[#E9EEF2] text-sm" />
|
||||||
|
|||||||
@@ -14,11 +14,11 @@ type ProductPurchaseOptionsProps = {
|
|||||||
|
|
||||||
const ProductPurchaseOptions: FC<ProductPurchaseOptionsProps> = ({ selectedTier, onSelectTier }) => {
|
const ProductPurchaseOptions: FC<ProductPurchaseOptionsProps> = ({ selectedTier, onSelectTier }) => {
|
||||||
return (
|
return (
|
||||||
<div className="flex w-full min-w-0 flex-1 flex-col items-end gap-4">
|
<div className="flex w-full min-w-0 flex-1 flex-col gap-4">
|
||||||
<div className="w-full space-y-2 text-right">
|
<div className="w-full space-y-2 text-right">
|
||||||
<h1 className="text-xl font-bold text-[#0A1B2C] sm:text-2xl">{PRODUCT_TITLE}</h1>
|
<h1 className="text-xl font-bold text-[#0A1B2C] sm:text-2xl">{PRODUCT_TITLE}</h1>
|
||||||
|
|
||||||
<div className="flex items-center gap-2">
|
<div className="flex items-center justify-end gap-2">
|
||||||
<Rating initialValue={PRODUCT_RATING} size={16} readonly rtl allowFraction SVGstyle={{ display: "inline-block" }} />
|
<Rating initialValue={PRODUCT_RATING} size={16} readonly rtl allowFraction SVGstyle={{ display: "inline-block" }} />
|
||||||
<span className="text-sm font-medium text-[#0A1B2C]">{PRODUCT_RATING}</span>
|
<span className="text-sm font-medium text-[#0A1B2C]">{PRODUCT_RATING}</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -55,17 +55,19 @@ const ProductPurchaseOptions: FC<ProductPurchaseOptionsProps> = ({ selectedTier,
|
|||||||
type="button"
|
type="button"
|
||||||
onClick={() => onSelectTier(tier)}
|
onClick={() => onSelectTier(tier)}
|
||||||
className={cn(
|
className={cn(
|
||||||
"flex h-10 w-full items-center justify-between gap-2 rounded-xl border border-[#E9EEF2] px-3 transition-colors",
|
"flex min-h-10 w-full items-center justify-between gap-1.5 rounded-xl border border-[#E9EEF2] px-2.5 transition-colors sm:gap-2 sm:px-3",
|
||||||
isSelected ? "bg-secondary" : "bg-white hover:bg-secondary/50",
|
isSelected ? "bg-secondary" : "bg-white hover:bg-secondary/50",
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<span className="w-6 shrink-0 text-end text-xs font-medium text-[#0A1B2C]">{tier.quantity}</span>
|
<span className="hidden w-6 shrink-0 text-end text-xs font-medium text-[#0A1B2C] sm:inline">{tier.quantity}</span>
|
||||||
|
|
||||||
<div className="flex min-w-0 flex-1 items-center justify-center gap-2">
|
<div className="flex min-w-0 flex-1 items-center justify-between gap-1.5 sm:justify-center sm:gap-2">
|
||||||
<span className="text-[11px] text-[#0A1B2C] sm:text-xs">{formatPrice(tier.unitPrice)}﷼ / هر عدد</span>
|
<span className="text-[10px] text-[#0A1B2C] sm:text-xs">{formatPrice(tier.unitPrice)}﷼ / هر عدد</span>
|
||||||
<span className="text-xs font-medium text-[#0A1B2C]">{formatPrice(tier.totalPrice)}﷼</span>
|
<span className="text-[11px] font-medium text-[#0A1B2C] sm:text-xs">{formatPrice(tier.totalPrice)}﷼</span>
|
||||||
</div>
|
</div>
|
||||||
<span className={cn("w-6 shrink-0 text-start text-xs font-medium", tier.discount ? "text-[#DC0000]" : "text-[#0A1B2C]")}>{tier.discount ? `-${tier.discount}%` : tier.quantity}</span>
|
<span className={cn("w-8 shrink-0 text-start text-[10px] font-medium sm:w-6 sm:text-xs", tier.discount ? "text-[#DC0000]" : "text-[#0A1B2C]")}>
|
||||||
|
{tier.discount ? `-${tier.discount}%` : tier.quantity}
|
||||||
|
</span>
|
||||||
</button>
|
</button>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { RELATED_PRODUCTS } from "../constants";
|
|||||||
|
|
||||||
const ProductRelated: FC = () => {
|
const ProductRelated: FC = () => {
|
||||||
return (
|
return (
|
||||||
<section className="mt-10 px-4 sm:mt-12 sm:px-8 lg:px-30">
|
<section className="mt-8 px-4 sm:mt-10 sm:px-8 lg:mt-12 lg:px-30">
|
||||||
<Carousel slidesPerView={{ base: 1.4, md: 3, lg: 5 }} gap={{ base: 12, md: 16, lg: 24 }}>
|
<Carousel slidesPerView={{ base: 1.4, md: 3, lg: 5 }} gap={{ base: 12, md: 16, lg: 24 }}>
|
||||||
<div className="flex items-center justify-between gap-4">
|
<div className="flex items-center justify-between gap-4">
|
||||||
<h2 className="text-lg font-bold text-[#0A1B2C] sm:text-xl">محصولات مرتبط</h2>
|
<h2 className="text-lg font-bold text-[#0A1B2C] sm:text-xl">محصولات مرتبط</h2>
|
||||||
|
|||||||
Reference in New Issue
Block a user