diff --git a/components/backAnimatsiya/backAnimatsiya.tsx b/components/backAnimatsiya/backAnimatsiya.tsx index 23793d2..eeec628 100644 --- a/components/backAnimatsiya/backAnimatsiya.tsx +++ b/components/backAnimatsiya/backAnimatsiya.tsx @@ -2,7 +2,7 @@ import "./back.css"; export default function BackAnimatsiya() { return ( -
+
state.filter); + const toggleFilter = useFilter((state) => state.toggleFilter); + const hasData = useFilter((state) => state.hasFilter); + + const [dataExpanded, setDataExpanded] = useState(false); + const [numberExpanded, setNumberExpanded] = useState(false); + + const sectionData = [ + "SLT-Aqua", + "Вварное седло", + "Кран шаровый", + "Муфты", + "Муфты комбинированные", + "Муфты переходные", + "Тройник комбинированный", + "Тройники", + "Трубы SDR 6", + "Трубы SDR 7,4", + "Угол 45", + "Угол 90", + "Угольник комбинированный", + "Фланцы+бурты", + ]; + + const sectionNumber = [ + "25", '25х1/2"', '25х3/4"', "32", "32x25x25", "32x25x32", + '32х1"', '32х1/2"', "32х25", '32х3/4"', "40", "40x25x40", + "40x32x40", '40х1 1/4"', '40х1 3/4"', '40х1/2"', "40х25", + "40х32", "50", "50x25x50", "50x32x50", "50x40x50", + '50х1 1/2"', '50х1/2"', "50х25", "50х32", "50х40", "63", + "63x25x63", "63x32x63", "63x40x63", "63x50x63", '63х1/2"', + '63х2"', "63х25", "63х32", "63х40", "63х50", "75", + "75x25x75", "75x32x75", "75x40x75", "75x50x75", "75x63x75", + '75х1/2"', "75х32", "75х40", "75х50", "75х63", "90", + "90x40x90", "90x50x90", "90x63x90", "90x75x90", '90х1/2"', + "90х32", "90х40", "90х50", "90х63", "90х75", "110", + "110x50x110", "110x63x110", "110x75x110", "110x90x110", + '110х1/2"', "110х25", "110х32", "110х40", "110х50", + "110х63", "110х75", "110х90", "125", "160", + ]; + + // Bo'lim uchun ko'rsatiladigan itemlar + const visibleSectionData = dataExpanded ? sectionData : sectionData.slice(0, 5); + + // O'lcham uchun ko'rsatiladigan itemlar + const visibleSectionNumber = numberExpanded ? sectionNumber : sectionNumber.slice(0, 10); + + return ( +
+ {/* Bo'lim filtri */} +
+

+ Bo'lim +

+
+ {visibleSectionData.map((item) => ( +
toggleFilter(item)} + className="hover:cursor-pointer flex items-center gap-2" + > + + {hasData(item) && ( + + )} + +

{item}

+
+ ))} +
+ +
+ + {/* O'lcham filtri */} +
+

+ O'lcham +

+
+ {visibleSectionNumber.map((item) => ( +
toggleFilter(item)} + className="hover:cursor-pointer flex items-center gap-2" + > + + {hasData(item) && ( + + )} + +

{item}

+
+ ))} +
+ +
+
+ ); +} \ No newline at end of file diff --git a/components/pages/products/filterInfo.tsx b/components/pages/products/filterInfo.tsx new file mode 100644 index 0000000..8dd3202 --- /dev/null +++ b/components/pages/products/filterInfo.tsx @@ -0,0 +1,35 @@ +"use client"; + +import { useFilter } from "@/lib/filter-zustand"; +import { X } from "lucide-react"; + +export default function FilterInfo() { + const filtered = useFilter((state) => state.filter); + const resetFilter = useFilter((state) => state.resetFilter); + const togleFilter = useFilter((state) => state.toggleFilter); + if (filtered.length === 0) { + return null; + } + return ( +
+

Found: 20

+
+ {filtered && + filtered.map((item) => ( +
+ + {item} +
+ ))} +
+ +
+ ); +} diff --git a/components/pages/products/products.tsx b/components/pages/products/products.tsx index d8804e9..b70c960 100644 --- a/components/pages/products/products.tsx +++ b/components/pages/products/products.tsx @@ -1,22 +1,31 @@ +import Filter from "./filter"; +import FilterInfo from "./filterInfo"; import ProductCard from "./productCard"; export function Products() { return (
-
-
- {Array(9) - .fill(null) - .map((_, index) => ( - - ))} +
+
+ {/* filter part */} + + + {/* main products */} +
+ {Array(9) + .fill(null) + .map((_, index) => ( + + ))} +
+
diff --git a/lib/filter-zustand.ts b/lib/filter-zustand.ts new file mode 100644 index 0000000..8bc38b5 --- /dev/null +++ b/lib/filter-zustand.ts @@ -0,0 +1,33 @@ +import { create } from "zustand"; + +interface FilterZustandTypes { + filter: string[]; + removeFilter: (data: string) => void; + toggleFilter: (data: string) => void; + resetFilter: () => void; + hasFilter: (data: string) => boolean; +} + +export const useFilter = create((set, get) => ({ + filter: [], + + removeFilter: (data) => + set((state) => ({ + filter: state.filter.filter((item) => item !== data), + })), + + // Toggle: mavjud bo'lsa o'chirish, yo'q bo'lsa qo'shish + toggleFilter: (data) => + set((state) => { + if (state.filter.includes(data)) { + return { filter: state.filter.filter((item) => item !== data) }; + } + return { filter: [...state.filter, data] }; + }), + + resetFilter: () => set({ filter: [] }), + + hasFilter: (data) => { + return get().filter.includes(data); + }, +})); \ No newline at end of file diff --git a/package.json b/package.json index ae838ee..b789d31 100644 --- a/package.json +++ b/package.json @@ -64,7 +64,8 @@ "tailwind-merge": "^3.3.1", "tailwindcss-animate": "^1.0.7", "vaul": "^1.1.2", - "zod": "3.25.76" + "zod": "3.25.76", + "zustand": "^5.0.10" }, "devDependencies": { "@tailwindcss/postcss": "^4.1.9", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ee0d15f..06ce2ff 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -176,6 +176,9 @@ importers: zod: specifier: 3.25.76 version: 3.25.76 + zustand: + specifier: ^5.0.10 + version: 5.0.10(@types/react@19.2.9)(react@19.2.0)(use-sync-external-store@1.6.0(react@19.2.0)) devDependencies: '@tailwindcss/postcss': specifier: ^4.1.9 @@ -2006,6 +2009,24 @@ packages: zod@3.25.76: resolution: {integrity: sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==} + zustand@5.0.10: + resolution: {integrity: sha512-U1AiltS1O9hSy3rul+Ub82ut2fqIAefiSuwECWt6jlMVUGejvf+5omLcRBSzqbRagSM3hQZbtzdeRc6QVScXTg==} + engines: {node: '>=12.20.0'} + peerDependencies: + '@types/react': '>=18.0.0' + immer: '>=9.0.6' + react: '>=18.0.0' + use-sync-external-store: '>=1.2.0' + peerDependenciesMeta: + '@types/react': + optional: true + immer: + optional: true + react: + optional: true + use-sync-external-store: + optional: true + snapshots: '@alloc/quick-lru@5.2.0': {} @@ -3687,3 +3708,9 @@ snapshots: d3-timer: 3.0.1 zod@3.25.76: {} + + zustand@5.0.10(@types/react@19.2.9)(react@19.2.0)(use-sync-external-store@1.6.0(react@19.2.0)): + optionalDependencies: + '@types/react': 19.2.9 + react: 19.2.0 + use-sync-external-store: 1.6.0(react@19.2.0) diff --git a/public/images/products/products2.webp b/public/images/products/products2.webp new file mode 100644 index 0000000..0af9df9 Binary files /dev/null and b/public/images/products/products2.webp differ diff --git a/public/images/products/products3.webp b/public/images/products/products3.webp new file mode 100644 index 0000000..e60cd6d Binary files /dev/null and b/public/images/products/products3.webp differ diff --git a/public/images/products/products4.webp b/public/images/products/products4.webp new file mode 100644 index 0000000..54e688d Binary files /dev/null and b/public/images/products/products4.webp differ diff --git a/public/images/products/products5.webp b/public/images/products/products5.webp new file mode 100644 index 0000000..6a6f359 Binary files /dev/null and b/public/images/products/products5.webp differ diff --git a/public/images/products/products6.webp b/public/images/products/products6.webp new file mode 100644 index 0000000..506a358 Binary files /dev/null and b/public/images/products/products6.webp differ diff --git a/public/images/products/products7.webp b/public/images/products/products7.webp new file mode 100644 index 0000000..af34ef8 Binary files /dev/null and b/public/images/products/products7.webp differ diff --git a/public/images/products/products8.webp b/public/images/products/products8.webp new file mode 100644 index 0000000..4fabae4 Binary files /dev/null and b/public/images/products/products8.webp differ