1- import { useState } from 'react' ;
21import Head from 'next/head' ;
32import Layout from '@/components/Layout/Layout.component' ;
4- import ProductCard from '@/components/Product/ProductCard.component' ;
5- import ProductFilters from '@/components/Product/ProductFilters.component' ;
3+ import ProductList from '@/components/Product/ProductList.component' ;
64import client from '@/utils/apollo/ApolloClient' ;
75import { FETCH_ALL_PRODUCTS_QUERY } from '@/utils/gql/GQL_QUERIES' ;
86import type { NextPage , GetStaticProps , InferGetStaticPropsType } from 'next' ;
9-
10- import { Product , ProductCategory , ProductType , SizeNode , ColorNode } from '@/types/product' ;
11- import { getUniqueProductTypes } from '@/utils/functions/productUtils' ;
7+ import { Product } from '@/types/product' ;
128
139const Products2 : NextPage = ( {
1410 products,
1511 loading,
1612} : InferGetStaticPropsType < typeof getStaticProps > ) => {
17- const [ sortBy , setSortBy ] = useState ( 'popular' ) ;
18- const [ selectedSizes , setSelectedSizes ] = useState < string [ ] > ( [ ] ) ;
19- const [ selectedColors , setSelectedColors ] = useState < string [ ] > ( [ ] ) ;
20- const [ priceRange , setPriceRange ] = useState < [ number , number ] > ( [ 0 , 1000 ] ) ;
21- const [ productTypes , setProductTypes ] = useState < ProductType [ ] > ( ( ) =>
22- products ? getUniqueProductTypes ( products ) : [ ]
23- ) ;
24-
25- const toggleProductType = ( id : string ) => {
26- setProductTypes ( prev => prev . map ( type =>
27- type . id === id ? { ...type , checked : ! type . checked } : type
28- ) ) ;
29- } ;
30-
31- const resetFilters = ( ) => {
32- setSelectedSizes ( [ ] ) ;
33- setSelectedColors ( [ ] ) ;
34- setPriceRange ( [ 0 , 1000 ] ) ;
35- setProductTypes ( prev => prev . map ( type => ( { ...type , checked : false } ) ) ) ;
36- } ;
37-
38- // Filter products based on selected filters
39- const filteredProducts = products ?. filter ( ( product : Product ) => {
40- // Filter by price
41- const productPrice = parseFloat ( product . price . replace ( / [ ^ 0 - 9 . ] / g, '' ) ) ;
42- const withinPriceRange = productPrice >= priceRange [ 0 ] && productPrice <= priceRange [ 1 ] ;
43- if ( ! withinPriceRange ) return false ;
44-
45- // Filter by product type
46- const selectedTypes = productTypes . filter ( t => t . checked ) . map ( t => t . name . toLowerCase ( ) ) ;
47- if ( selectedTypes . length > 0 ) {
48- const productCategories = product . productCategories ?. nodes . map ( ( cat : ProductCategory ) => cat . name . toLowerCase ( ) ) || [ ] ;
49- if ( ! selectedTypes . some ( type => productCategories . includes ( type ) ) ) return false ;
50- }
51-
52- // Filter by size
53- if ( selectedSizes . length > 0 ) {
54- const productSizes = product . allPaSizes ?. nodes . map ( ( node : SizeNode ) => node . name ) || [ ] ;
55- if ( ! selectedSizes . some ( size => productSizes . includes ( size ) ) ) return false ;
56- }
57-
58- // Filter by color
59- if ( selectedColors . length > 0 ) {
60- const productColors = product . allPaColors ?. nodes . map ( ( node : ColorNode ) => node . name ) || [ ] ;
61- if ( ! selectedColors . some ( color => productColors . includes ( color ) ) ) return false ;
62- }
63-
64- return true ;
65- } ) ;
66-
67- // Sort products
68- const sortedProducts = [ ...( filteredProducts || [ ] ) ] . sort ( ( a , b ) => {
69- const priceA = parseFloat ( a . price . replace ( / [ ^ 0 - 9 . ] / g, '' ) ) ;
70- const priceB = parseFloat ( b . price . replace ( / [ ^ 0 - 9 . ] / g, '' ) ) ;
71-
72- switch ( sortBy ) {
73- case 'price-low' :
74- return priceA - priceB ;
75- case 'price-high' :
76- return priceB - priceA ;
77- case 'newest' :
78- return b . databaseId - a . databaseId ;
79- default : // 'popular'
80- return 0 ;
81- }
82- } ) ;
83-
84- if ( loading ) return (
85- < Layout title = "Produkter" >
86- < div className = "flex justify-center items-center min-h-screen" >
87- < div className = "animate-spin rounded-full h-32 w-32 border-t-2 border-b-2 border-gray-900" > </ div >
88- </ div >
89- </ Layout >
90- ) ;
91-
92- if ( ! products ) return (
93- < Layout title = "Produkter" >
94- < div className = "flex justify-center items-center min-h-screen" >
95- < p className = "text-red-500" > Ingen produkter funnet</ p >
96- </ div >
97- </ Layout >
98- ) ;
13+ if ( loading )
14+ return (
15+ < Layout title = "Produkter" >
16+ < div className = "flex justify-center items-center min-h-screen" >
17+ < div className = "animate-spin rounded-full h-32 w-32 border-t-2 border-b-2 border-gray-900" > </ div >
18+ </ div >
19+ </ Layout >
20+ ) ;
21+
22+ if ( ! products )
23+ return (
24+ < Layout title = "Produkter" >
25+ < div className = "flex justify-center items-center min-h-screen" >
26+ < p className = "text-red-500" > Ingen produkter funnet</ p >
27+ </ div >
28+ </ Layout >
29+ ) ;
9930
10031 return (
10132 < Layout title = "Produkter" >
@@ -104,56 +35,7 @@ const Products2: NextPage = ({
10435 </ Head >
10536
10637 < div className = "container mx-auto px-4 py-8" >
107- < div className = "flex flex-col md:flex-row gap-8" >
108- < ProductFilters
109- selectedSizes = { selectedSizes }
110- setSelectedSizes = { setSelectedSizes }
111- selectedColors = { selectedColors }
112- setSelectedColors = { setSelectedColors }
113- priceRange = { priceRange }
114- setPriceRange = { setPriceRange }
115- productTypes = { productTypes }
116- toggleProductType = { toggleProductType }
117- products = { products }
118- resetFilters = { resetFilters }
119- />
120-
121- { /* Main Content */ }
122- < div className = "flex-1" >
123- < div className = "flex justify-between items-center mb-8" >
124- < h1 className = "text-2xl font-medium" >
125- Herreklær < span className = "text-gray-500" > ({ sortedProducts . length } )</ span >
126- </ h1 >
127-
128- < div className = "flex items-center gap-4" >
129- < label className = "text-sm" > Vis produkter:</ label >
130- < select
131- value = { sortBy }
132- onChange = { ( e ) => setSortBy ( e . target . value ) }
133- className = "border rounded-md px-3 py-1"
134- >
135- < option value = "popular" > Populær</ option >
136- < option value = "price-low" > Pris: Lav til Høy</ option >
137- < option value = "price-high" > Pris: Høy til Lav</ option >
138- < option value = "newest" > Nyeste</ option >
139- </ select >
140- </ div >
141- </ div >
142-
143- < div className = "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8" >
144- { sortedProducts . map ( ( product : Product ) => (
145- < ProductCard
146- key = { product . databaseId }
147- databaseId = { product . databaseId }
148- name = { product . name }
149- price = { product . price }
150- slug = { product . slug }
151- image = { product . image }
152- />
153- ) ) }
154- </ div >
155- </ div >
156- </ div >
38+ < ProductList products = { products } title = "Herreklær" />
15739 </ div >
15840 </ Layout >
15941 ) ;
0 commit comments