Skip to content
Merged

up #7

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions apps/app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@
"@t3-oss/env-nextjs": "^0.13.8",
"@tanstack/react-query": "5.84.0",
"@tanstack/react-virtual": "^3.13.12",
"@trpc/client": "11.4.3",
"@trpc/server": "11.4.3",
"@trpc/tanstack-react-query": "11.4.3",
"@trpc/client": "11.4.4",
"@trpc/server": "11.4.4",
"@trpc/tanstack-react-query": "11.4.4",
"@udecode/plate": "^49.0.0",
"@udecode/plate-ai": "^49.0.0",
"@udecode/plate-alignment": "^49.0.0",
Expand Down Expand Up @@ -90,9 +90,9 @@
"react": "19.1.1",
"react-dom": "19.1.1",
"react-dropzone": "^14.3.8",
"react-hook-form": "7.61.1",
"react-hook-form": "7.62.0",
"recharts": "2.15.4",
"sonner": "^2.0.6",
"sonner": "^2.0.7",
"superjson": "2.2.2",
"tailwind-merge": "3.3.1",
"tailwind-scrollbar-hide": "^4.0.0",
Expand All @@ -102,7 +102,7 @@
"@qco/eslint-config": "workspace:*",
"@qco/prettier-config": "workspace:*",
"@qco/tsconfig": "workspace:*",
"@types/node": "24.1.0",
"@types/node": "24.2.0",
"@types/react": "19.1.9",
"@types/react-dom": "19.1.7",
"dotenv-cli": "10.0.0",
Expand Down
15 changes: 7 additions & 8 deletions apps/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,9 @@
"@radix-ui/react-tooltip": "1.2.7",
"@tailwindcss/postcss": "4.1.11",
"@tanstack/react-query": "5.84.0",
"@trpc/client": "11.4.3",
"@trpc/server": "11.4.3",
"@trpc/tanstack-react-query": "11.4.3",
"add": "^2.0.6",
"@trpc/client": "11.4.4",
"@trpc/server": "11.4.4",
"@trpc/tanstack-react-query": "11.4.4",
"autoprefixer": "^10.4.21",
"canvas-confetti": "1.9.3",
"class-variance-authority": "0.7.1",
Expand All @@ -65,12 +64,12 @@
"framer-motion": "^12.23.12",
"input-otp": "1.4.2",
"lucide-react": "0.535.0",
"next": "15.4.5",
"next": "15.4.6",
"next-themes": "latest",
"react": "19.1.1",
"react-day-picker": "8.10.1",
"react-dom": "19.1.1",
"react-hook-form": "7.61.1",
"react-hook-form": "7.62.0",
"react-resizable-panels": "^2.1.9",
"react-use": "latest",
"recharts": "2.15.4",
Expand All @@ -80,10 +79,10 @@
"tailwindcss-animate": "1.0.7",
"vaul": "^1.1.2",
"web-push": "^3.6.7",
"zod": "4.0.14"
"zod": "4.0.15"
},
"devDependencies": {
"@types/node": "24.1.0",
"@types/node": "24.2.0",
"@types/react": "19.1.9",
"@types/react-dom": "19.1.7",
"@types/web-push": "^3.6.4",
Expand Down
37 changes: 25 additions & 12 deletions apps/web/src/components/category-hero-section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -177,15 +177,28 @@ export default function CategoryHeroSection({
}`}
>
<div className="relative h-full flex items-center justify-center">
<div className="absolute inset-0 z-0">
<Image
src={slide.image || "/placeholder.svg"}
alt={slide.title}
fill
className="object-cover"
priority={index === 0}
/>
</div>
{/* Если есть ссылка и нет текста кнопки — кликабелен весь баннер */}
{slide.primaryLink && !slide.primaryButton ? (
<a href={slide.primaryLink} className="absolute inset-0 z-0 block">
<Image
src={slide.image || "/placeholder.svg"}
alt={slide.title}
fill
className="object-cover"
priority={index === 0}
/>
</a>
) : (
<div className="absolute inset-0 z-0">
<Image
src={slide.image || "/placeholder.svg"}
alt={slide.title}
fill
className="object-cover"
priority={index === 0}
/>
</div>
)}

{/* Контент слайда */}
<div className="relative z-10 text-center text-white px-4 md:px-8">
Expand All @@ -199,7 +212,7 @@ export default function CategoryHeroSection({
{slide.description}
</p>
)}
{/* Показываем кнопку только если есть ссылка */}
{/* Показываем кнопку только если есть ссылка и текст */}
{slide.primaryButton && slide.primaryLink && (
<div className="flex flex-col sm:flex-row gap-3 justify-center">
<a
Expand Down Expand Up @@ -255,8 +268,8 @@ export default function CategoryHeroSection({
key={`slide-indicator-${slide.id}-${index}`}
onClick={() => goToSlide(index)}
className={`w-3 h-3 rounded-full transition-all duration-300 ${index === currentSlide
? "bg-white scale-110"
: "bg-white/50 hover:bg-white/70"
? "bg-white scale-110"
: "bg-white/50 hover:bg-white/70"
}`}
/>
))}
Expand Down
143 changes: 83 additions & 60 deletions apps/web/src/components/hero-section.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -224,67 +224,90 @@ export default function HeroSection({ categorySlug }: HeroSectionProps) {
: "translate-x-full"
}`}
>
<div className="relative h-full flex items-center justify-center">
<div className="absolute inset-0 z-0 bg-gray-100">
{/* Desktop изображение */}
<Image
src={slide.desktopImage || "/placeholder.svg"}
alt={slide.title || "Banner image"}
fill
className="object-cover object-center hidden md:block"
priority={index === 0}
sizes="(max-width: 768px) 0vw, 100vw"
/>

{/* Mobile изображение */}
<Image
src={
slide.mobileImage ||
slide.desktopImage ||
"/placeholder.svg"
}
alt={slide.title || "Banner image"}
fill
className="object-cover object-center md:hidden"
priority={index === 0}
sizes="100vw"
/>
</div>

{/* Контент слайда */}
<div className="relative z-10 text-center text-white px-4 md:px-8">
{/* Убираем отображение заголовка */}
{slide.subtitle && (
<p className="text-lg md:text-xl mb-2 md:mb-4 font-medium">
{slide.subtitle}
</p>
)}
{slide.description && (
<p className="text-sm md:text-base mb-4 md:mb-6 max-w-2xl mx-auto">
{slide.description}
</p>
)}
{/* Показываем кнопку только если есть ссылка */}
{slide.primaryButton && slide.primaryLink && (
<div className="flex flex-col sm:flex-row gap-3 justify-center">
<a
href={slide.primaryLink}
className="inline-flex items-center justify-center px-6 py-3 bg-white text-black font-medium rounded-lg hover:bg-gray-100 transition-colors"
>
{slide.primaryButton}
</a>
{slide.secondaryButton && slide.secondaryLink && (
<a
href={slide.secondaryLink}
className="inline-flex items-center justify-center px-6 py-3 border border-white text-white font-medium rounded-lg hover:bg-white hover:text-black transition-colors"
>
{slide.secondaryButton}
</a>
{(() => {
const background = (
<div className="absolute inset-0 z-0 bg-gray-100">
{/* Desktop изображение */}
<Image
src={slide.desktopImage || "/placeholder.svg"}
alt={slide.title || "Banner image"}
fill
className="object-cover object-center hidden md:block"
priority={index === 0}
sizes="(max-width: 768px) 0vw, 100vw"
/>
{/* Mobile изображение */}
<Image
src={
slide.mobileImage ||
slide.desktopImage ||
"/placeholder.svg"
}
alt={slide.title || "Banner image"}
fill
className="object-cover object-center md:hidden"
priority={index === 0}
sizes="100vw"
/>
</div>
);

const textBase = (
<>
{slide.subtitle && (
<p className="text-lg md:text-xl mb-2 md:mb-4 font-medium">
{slide.subtitle}
</p>
)}
{slide.description && (
<p className="text-sm md:text-base mb-4 md:mb-6 max-w-2xl mx-auto">
{slide.description}
</p>
)}
</>
);

const hasFullLink = Boolean(slide.primaryLink && !slide.primaryButton);

if (hasFullLink) {
return (
<a href={slide.primaryLink!} className="relative h-full flex items-center justify-center block">
{background}
<div className="relative z-10 text-center text-white px-4 md:px-8">
{textBase}
</div>
</a>
);
}

return (
<div className="relative h-full flex items-center justify-center">
{background}
<div className="relative z-10 text-center text-white px-4 md:px-8">
{textBase}
{/* Показываем кнопку только если есть ссылка и есть текст */}
{slide.primaryButton && slide.primaryLink && (
<div className="flex flex-col sm:flex-row gap-3 justify-center">
<a
href={slide.primaryLink}
className="inline-flex items-center justify-center px-6 py-3 bg-white text-black font-medium rounded-lg hover:bg-gray-100 transition-colors"
>
{slide.primaryButton}
</a>
{slide.secondaryButton && slide.secondaryLink && (
<a
href={slide.secondaryLink}
className="inline-flex items-center justify-center px-6 py-3 border border-white text-white font-medium rounded-lg hover:bg-white hover:text-black transition-colors"
>
{slide.secondaryButton}
</a>
)}
</div>
)}
</div>
)}
</div>
</div>
</div>
);
})()}
</div>
))}

Expand Down Expand Up @@ -390,6 +413,6 @@ export default function HeroSection({ categorySlug }: HeroSectionProps) {
</div>
</div>
</div>
</section>
</section >
);
}
53 changes: 32 additions & 21 deletions apps/web/src/features/catalog/components/catalog-banners.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,40 @@ export function CatalogBanners({ banners }: CatalogBannersProps) {
<div className="mb-8">
<h2 className="text-xl font-semibold mb-4">Рекомендуем</h2>
<div className="grid md:grid-cols-3 gap-4">
{banners.map((banner) => (
<div
key={banner.id}
className="relative h-48 bg-gray-100 rounded-lg overflow-hidden"
>
{banner.files?.[0]?.file?.url && (
<Image
src={banner.files[0].file.url}
alt={banner.title}
fill
className="object-cover"
/>
)}
<div className="absolute inset-0 bg-black bg-opacity-30 flex items-end">
<div className="p-4 text-white">
<h3 className="font-semibold">{banner.title}</h3>
{banner.description && (
<p className="text-sm opacity-90">{banner.description}</p>
)}
{banners.map((banner) => {
const content = (
<>
{banner.files?.[0]?.file?.url && (
<Image
src={banner.files[0].file.url}
alt={banner.title || "Banner"}
fill
className="object-cover"
/>
)}
<div className="absolute inset-0 bg-black bg-opacity-30 flex items-end">
<div className="p-4 text-white">
<h3 className="font-semibold">{banner.title}</h3>
{banner.description && (
<p className="text-sm opacity-90">{banner.description}</p>
)}
</div>
</div>
</>
);

const wrapperClass = "relative h-48 bg-gray-100 rounded-lg overflow-hidden";

return banner.link && !banner.buttonText ? (
<a key={banner.id} href={banner.link} className={wrapperClass}>
{content}
</a>
) : (
<div key={banner.id} className={wrapperClass}>
{content}
</div>
</div>
))}
);
})}
</div>
</div>
);
Expand Down
Loading