Skip to content

Commit b0064ce

Browse files
committed
Work on filter
1 parent d1fcabb commit b0064ce

File tree

3 files changed

+164
-19
lines changed

3 files changed

+164
-19
lines changed

src/components/Product/ProductFilters.component.tsx

Lines changed: 37 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,29 @@
11
import { Dispatch, SetStateAction } from 'react';
22

3+
interface ProductType {
4+
id: string;
5+
name: string;
6+
checked: boolean;
7+
}
8+
9+
interface Product {
10+
allPaSizes?: {
11+
nodes: {
12+
name: string;
13+
}[];
14+
};
15+
}
16+
317
interface ProductFiltersProps {
418
selectedSizes: string[];
519
setSelectedSizes: Dispatch<SetStateAction<string[]>>;
620
selectedColors: string[];
721
setSelectedColors: Dispatch<SetStateAction<string[]>>;
822
priceRange: [number, number];
923
setPriceRange: Dispatch<SetStateAction<[number, number]>>;
24+
productTypes: ProductType[];
25+
toggleProductType: (id: string) => void;
26+
products: Product[];
1027
}
1128

1229
const ProductFilters = ({
@@ -16,8 +33,16 @@ const ProductFilters = ({
1633
setSelectedColors,
1734
priceRange,
1835
setPriceRange,
36+
productTypes,
37+
toggleProductType,
38+
products,
1939
}: ProductFiltersProps) => {
20-
const sizes = ['XS', 'S', 'M', 'L', 'XL', 'XXL'];
40+
// Get unique sizes from all products
41+
const sizes = Array.from(new Set(
42+
products.flatMap((product: Product) =>
43+
product.allPaSizes?.nodes.map((node: { name: string }) => node.name) || []
44+
)
45+
)).sort() as string[];
2146
const colors = [
2247
{ name: 'Svart', class: 'bg-black' },
2348
{ name: 'Brun', class: 'bg-brown-500' },
@@ -49,22 +74,17 @@ const ProductFilters = ({
4974
<div className="mb-8">
5075
<h3 className="font-semibold mb-4">PRODUKT TYPE</h3>
5176
<div className="space-y-2">
52-
<label className="flex items-center">
53-
<input type="checkbox" className="form-checkbox" />
54-
<span className="ml-2">T-Shirts</span>
55-
</label>
56-
<label className="flex items-center">
57-
<input type="checkbox" className="form-checkbox" />
58-
<span className="ml-2">Gensere</span>
59-
</label>
60-
<label className="flex items-center">
61-
<input type="checkbox" className="form-checkbox" />
62-
<span className="ml-2">Singlet</span>
63-
</label>
64-
<label className="flex items-center">
65-
<input type="checkbox" className="form-checkbox" />
66-
<span className="ml-2">Skjorter</span>
67-
</label>
77+
{productTypes.map((type) => (
78+
<label key={type.id} className="flex items-center">
79+
<input
80+
type="checkbox"
81+
className="form-checkbox"
82+
checked={type.checked}
83+
onChange={() => toggleProductType(type.id)}
84+
/>
85+
<span className="ml-2">{type.name}</span>
86+
</label>
87+
))}
6888
</div>
6989
</div>
7090

src/pages/products2.tsx

Lines changed: 105 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,24 @@ interface Variations {
2424
nodes: Node[];
2525
}
2626

27+
interface ProductCategory {
28+
name: string;
29+
slug: string;
30+
}
31+
32+
interface ColorNode {
33+
name: string;
34+
}
35+
36+
interface SizeNode {
37+
name: string;
38+
}
39+
40+
interface AttributeNode {
41+
name: string;
42+
value: string;
43+
}
44+
2745
interface Product {
2846
__typename: string;
2947
databaseId: number;
@@ -34,7 +52,31 @@ interface Product {
3452
price: string;
3553
regularPrice: string;
3654
salePrice?: string;
37-
variations: Variations;
55+
productCategories?: {
56+
nodes: ProductCategory[];
57+
};
58+
allPaColors?: {
59+
nodes: ColorNode[];
60+
};
61+
allPaSizes?: {
62+
nodes: SizeNode[];
63+
};
64+
variations: {
65+
nodes: Array<{
66+
price: string;
67+
regularPrice: string;
68+
salePrice?: string;
69+
attributes?: {
70+
nodes: AttributeNode[];
71+
};
72+
}>;
73+
};
74+
}
75+
76+
interface ProductType {
77+
id: string;
78+
name: string;
79+
checked: boolean;
3880
}
3981

4082
const Products2: NextPage = ({
@@ -45,6 +87,64 @@ const Products2: NextPage = ({
4587
const [selectedSizes, setSelectedSizes] = useState<string[]>([]);
4688
const [selectedColors, setSelectedColors] = useState<string[]>([]);
4789
const [priceRange, setPriceRange] = useState<[number, number]>([0, 1000]);
90+
const [productTypes, setProductTypes] = useState<ProductType[]>([
91+
{ id: 't-shirts', name: 'T-Shirts', checked: false },
92+
{ id: 'gensere', name: 'Gensere', checked: false },
93+
{ id: 'singlet', name: 'Singlet', checked: false },
94+
{ id: 'skjorter', name: 'Skjorter', checked: false }
95+
]);
96+
97+
const toggleProductType = (id: string) => {
98+
setProductTypes(prev => prev.map(type =>
99+
type.id === id ? { ...type, checked: !type.checked } : type
100+
));
101+
};
102+
103+
// Filter products based on selected filters
104+
const filteredProducts = products?.filter((product: Product) => {
105+
// Filter by price
106+
const productPrice = parseFloat(product.price.replace(/[^0-9.]/g, ''));
107+
const withinPriceRange = productPrice >= priceRange[0] && productPrice <= priceRange[1];
108+
if (!withinPriceRange) return false;
109+
110+
// Filter by product type
111+
const selectedTypes = productTypes.filter(t => t.checked).map(t => t.name.toLowerCase());
112+
if (selectedTypes.length > 0) {
113+
const productCategories = product.productCategories?.nodes.map((cat: ProductCategory) => cat.name.toLowerCase()) || [];
114+
if (!selectedTypes.some(type => productCategories.includes(type))) return false;
115+
}
116+
117+
// Filter by size
118+
if (selectedSizes.length > 0) {
119+
const productSizes = product.allPaSizes?.nodes.map((node: SizeNode) => node.name) || [];
120+
if (!selectedSizes.some(size => productSizes.includes(size))) return false;
121+
}
122+
123+
// Filter by color
124+
if (selectedColors.length > 0) {
125+
const productColors = product.allPaColors?.nodes.map((node: ColorNode) => node.name) || [];
126+
if (!selectedColors.some(color => productColors.includes(color))) return false;
127+
}
128+
129+
return true;
130+
});
131+
132+
// Sort products
133+
const sortedProducts = [...(filteredProducts || [])].sort((a, b) => {
134+
const priceA = parseFloat(a.price.replace(/[^0-9.]/g, ''));
135+
const priceB = parseFloat(b.price.replace(/[^0-9.]/g, ''));
136+
137+
switch (sortBy) {
138+
case 'price-low':
139+
return priceA - priceB;
140+
case 'price-high':
141+
return priceB - priceA;
142+
case 'newest':
143+
return b.databaseId - a.databaseId;
144+
default: // 'popular'
145+
return 0;
146+
}
147+
});
48148

49149
if (loading) return (
50150
<Layout title="Produkter">
@@ -77,6 +177,9 @@ const Products2: NextPage = ({
77177
setSelectedColors={setSelectedColors}
78178
priceRange={priceRange}
79179
setPriceRange={setPriceRange}
180+
productTypes={productTypes}
181+
toggleProductType={toggleProductType}
182+
products={products}
80183
/>
81184

82185
{/* Main Content */}
@@ -102,7 +205,7 @@ const Products2: NextPage = ({
102205
</div>
103206

104207
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
105-
{products.map((product: Product) => (
208+
{sortedProducts.map((product: Product) => (
106209
<ProductCard
107210
key={product.databaseId}
108211
databaseId={product.databaseId}

src/utils/gql/GQL_QUERIES.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,12 @@ export const FETCH_ALL_PRODUCTS_QUERY = gql`
117117
image {
118118
sourceUrl
119119
}
120+
productCategories {
121+
nodes {
122+
name
123+
slug
124+
}
125+
}
120126
... on SimpleProduct {
121127
databaseId
122128
price
@@ -128,11 +134,27 @@ export const FETCH_ALL_PRODUCTS_QUERY = gql`
128134
price
129135
regularPrice
130136
salePrice
137+
allPaColors {
138+
nodes {
139+
name
140+
}
141+
}
142+
allPaSizes {
143+
nodes {
144+
name
145+
}
146+
}
131147
variations {
132148
nodes {
133149
price
134150
regularPrice
135151
salePrice
152+
attributes {
153+
nodes {
154+
name
155+
value
156+
}
157+
}
136158
}
137159
}
138160
}

0 commit comments

Comments
 (0)