diff --git a/apps/web/src/app/brand/[id]/catalog/BrandCatalogContent.module.scss b/apps/web/src/app/brand/[id]/catalog/BrandCatalogContent.module.scss
new file mode 100644
index 0000000..7b4114c
--- /dev/null
+++ b/apps/web/src/app/brand/[id]/catalog/BrandCatalogContent.module.scss
@@ -0,0 +1,35 @@
+.main {
+ flex: 1;
+}
+
+.header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: var(--space-md);
+}
+
+.count {
+ font-size: 12px;
+ color: var(--color-slate-400);
+}
+
+.grid {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: var(--space-md);
+
+ @media (max-width: 1024px) {
+ grid-template-columns: repeat(2, 1fr);
+ }
+
+ @media (max-width: 640px) {
+ grid-template-columns: 1fr;
+ }
+}
+
+.empty {
+ text-align: center;
+ color: var(--color-text-muted);
+ padding: var(--space-2xl) 0;
+}
diff --git a/apps/web/src/app/brand/[id]/catalog/BrandCatalogContent.tsx b/apps/web/src/app/brand/[id]/catalog/BrandCatalogContent.tsx
index f244c22..8a91bcd 100644
--- a/apps/web/src/app/brand/[id]/catalog/BrandCatalogContent.tsx
+++ b/apps/web/src/app/brand/[id]/catalog/BrandCatalogContent.tsx
@@ -1,7 +1,9 @@
import { notFound } from 'next/navigation';
import { filterProducts, parseSearchParams } from '@/lib/filterProducts';
-import { CatalogView } from '@/components/CatalogView/CatalogView';
+import { Breadcrumb } from '@/components/Breadcrumb/Breadcrumb';
+import { ProductCard } from '@/components/ProductCard/ProductCard';
import { getBrands, getProducts } from '@/lib/api';
+import styles from './BrandCatalogContent.module.scss';
export async function BrandCatalogContent({
id,
@@ -21,21 +23,29 @@ export async function BrandCatalogContent({
const brandProducts = products.filter((p) => p.brand === brand.name);
const filtered = filterProducts(brandProducts, filters);
- const basePath = `/brand/${id}/catalog`;
-
- const breadcrumbItems = [
- { label: 'Главная', href: '/' },
- { label: 'Каталог', href: '/catalog' },
- { label: brand.name, href: `/brand/${id}` },
- { label: 'Каталог' },
- ];
-
return (
-
+
+
+
+ {filtered.length} позиций
+
+
+ {filtered.map((p) => (
+
+ ))}
+
+ {filtered.length === 0 && (
+
+ По выбранным фильтрам ничего не найдено.
+
+ )}
+
);
}
diff --git a/apps/web/src/app/brand/[id]/catalog/page.module.scss b/apps/web/src/app/brand/[id]/catalog/page.module.scss
new file mode 100644
index 0000000..b32ed28
--- /dev/null
+++ b/apps/web/src/app/brand/[id]/catalog/page.module.scss
@@ -0,0 +1,7 @@
+.layout {
+ max-width: var(--max-width);
+ margin: 0 auto;
+ padding: var(--space-lg);
+ display: flex;
+ gap: var(--space-lg);
+}
diff --git a/apps/web/src/app/brand/[id]/catalog/page.tsx b/apps/web/src/app/brand/[id]/catalog/page.tsx
index 3a31b3a..85617b7 100644
--- a/apps/web/src/app/brand/[id]/catalog/page.tsx
+++ b/apps/web/src/app/brand/[id]/catalog/page.tsx
@@ -1,7 +1,9 @@
import { Suspense } from 'react';
import { getBrands } from '@/lib/api';
+import { CatalogSidebar } from '@/components/CatalogSidebar/CatalogSidebar';
import { CatalogSkeleton } from '@/components/Skeleton/Skeleton';
import { BrandCatalogContent } from './BrandCatalogContent';
+import styles from './page.module.scss';
export async function generateMetadata({
params,
@@ -28,10 +30,14 @@ export default async function BrandCatalogPage({
const { id } = await params;
const sp = await searchParams;
const key = JSON.stringify(sp);
+ const basePath = `/brand/${id}/catalog`;
return (
- }>
-
-
+
+
+ }>
+
+
+
);
}
diff --git a/apps/web/src/app/catalog/CatalogContent.module.scss b/apps/web/src/app/catalog/CatalogContent.module.scss
new file mode 100644
index 0000000..7b4114c
--- /dev/null
+++ b/apps/web/src/app/catalog/CatalogContent.module.scss
@@ -0,0 +1,35 @@
+.main {
+ flex: 1;
+}
+
+.header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ margin-bottom: var(--space-md);
+}
+
+.count {
+ font-size: 12px;
+ color: var(--color-slate-400);
+}
+
+.grid {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: var(--space-md);
+
+ @media (max-width: 1024px) {
+ grid-template-columns: repeat(2, 1fr);
+ }
+
+ @media (max-width: 640px) {
+ grid-template-columns: 1fr;
+ }
+}
+
+.empty {
+ text-align: center;
+ color: var(--color-text-muted);
+ padding: var(--space-2xl) 0;
+}
diff --git a/apps/web/src/app/catalog/CatalogContent.tsx b/apps/web/src/app/catalog/CatalogContent.tsx
index 89b4a25..5256f12 100644
--- a/apps/web/src/app/catalog/CatalogContent.tsx
+++ b/apps/web/src/app/catalog/CatalogContent.tsx
@@ -1,6 +1,8 @@
import { filterProducts, parseSearchParams } from '@/lib/filterProducts';
-import { CatalogView } from '@/components/CatalogView/CatalogView';
+import { Breadcrumb } from '@/components/Breadcrumb/Breadcrumb';
+import { ProductCard } from '@/components/ProductCard/ProductCard';
import { getProducts } from '@/lib/api';
+import styles from './CatalogContent.module.scss';
export async function CatalogContent({
params,
@@ -11,15 +13,27 @@ export async function CatalogContent({
const filters = parseSearchParams(params);
const filtered = filterProducts(products, filters);
- const breadcrumbItems = [
- { label: 'Главная', href: '/' },
- { label: 'Каталог' },
- ];
-
return (
-
+
+
+
+ {filtered.length} позиций
+
+
+ {filtered.map((p) => (
+
+ ))}
+
+ {filtered.length === 0 && (
+
+ По выбранным фильтрам ничего не найдено.
+
+ )}
+
);
}
diff --git a/apps/web/src/app/catalog/page.module.scss b/apps/web/src/app/catalog/page.module.scss
new file mode 100644
index 0000000..b32ed28
--- /dev/null
+++ b/apps/web/src/app/catalog/page.module.scss
@@ -0,0 +1,7 @@
+.layout {
+ max-width: var(--max-width);
+ margin: 0 auto;
+ padding: var(--space-lg);
+ display: flex;
+ gap: var(--space-lg);
+}
diff --git a/apps/web/src/app/catalog/page.tsx b/apps/web/src/app/catalog/page.tsx
index 4926b35..803da1c 100644
--- a/apps/web/src/app/catalog/page.tsx
+++ b/apps/web/src/app/catalog/page.tsx
@@ -1,7 +1,9 @@
import { Suspense } from 'react';
import { categoryNameMap, CategorySlug } from '@/types';
+import { CatalogSidebar } from '@/components/CatalogSidebar/CatalogSidebar';
import { CatalogSkeleton } from '@/components/Skeleton/Skeleton';
import { CatalogContent } from './CatalogContent';
+import styles from './page.module.scss';
export async function generateMetadata({
searchParams,
@@ -30,8 +32,11 @@ export default async function CatalogPage({
const key = JSON.stringify(params);
return (
- }>
-
-
+
+
+ }>
+
+
+
);
}
diff --git a/apps/web/src/components/Skeleton/Skeleton.module.scss b/apps/web/src/components/Skeleton/Skeleton.module.scss
index eadd90f..a2dccb3 100644
--- a/apps/web/src/components/Skeleton/Skeleton.module.scss
+++ b/apps/web/src/components/Skeleton/Skeleton.module.scss
@@ -59,33 +59,22 @@
.catalogGrid {
display: grid;
- grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
+ grid-template-columns: repeat(3, 1fr);
gap: var(--space-md);
- padding: var(--space-md) 0;
+
+ @media (max-width: 1024px) {
+ grid-template-columns: repeat(2, 1fr);
+ }
+
+ @media (max-width: 640px) {
+ grid-template-columns: 1fr;
+ }
}
.catalogCard {
height: 180px;
}
-.catalogLayout {
- display: flex;
- gap: var(--space-xl);
- max-width: 1280px;
- margin: 0 auto;
- padding: var(--space-xl);
-}
-
-.catalogSidebar {
- width: 240px;
- height: 400px;
- flex-shrink: 0;
-
- @media (max-width: 768px) {
- display: none;
- }
-}
-
.catalogMain {
flex: 1;
}
diff --git a/apps/web/src/components/Skeleton/Skeleton.tsx b/apps/web/src/components/Skeleton/Skeleton.tsx
index ed2e481..62af89a 100644
--- a/apps/web/src/components/Skeleton/Skeleton.tsx
+++ b/apps/web/src/components/Skeleton/Skeleton.tsx
@@ -30,15 +30,12 @@ export function BrandLogosSkeleton() {
export function CatalogSkeleton() {
return (
-
-
-
-
-
- {Array.from({ length: 6 }).map((_, i) => (
-
- ))}
-
+
+
+
+ {Array.from({ length: 6 }).map((_, i) => (
+
+ ))}
);