@@ -10,9 +10,7 @@ import Button from '@/components/UI/Button.component';
10
10
11
11
import {
12
12
getFormattedCart ,
13
- getUpdatedItems ,
14
13
handleQuantityChange ,
15
- IProductRootObject ,
16
14
} from '@/utils/functions/functions' ;
17
15
18
16
import { GET_CART } from '@/utils/gql/GQL_QUERIES' ;
@@ -23,146 +21,113 @@ const CartContents = () => {
23
21
const { cart, setCart } = useCartStore ( ) ;
24
22
const isCheckoutPage = router . pathname === '/kasse' ;
25
23
26
- const { data } = useQuery ( GET_CART , {
24
+ useQuery ( GET_CART , {
27
25
notifyOnNetworkStatusChange : true ,
28
26
onCompleted : ( data ) => {
27
+ // Only update if there's a significant difference to avoid unnecessary re-renders
29
28
const updatedCart = getFormattedCart ( data ) as RootObject | undefined ;
30
- setCart ( updatedCart || null ) ;
29
+ if ( ! cart || cart . totalProductsCount !== updatedCart ?. totalProductsCount ) {
30
+ setCart ( updatedCart || null ) ;
31
+ }
31
32
} ,
32
33
} ) ;
33
34
34
- const [ updateCart ] = useMutation ( UPDATE_CART , {
35
- refetchQueries : [ { query : GET_CART } ] ,
36
- awaitRefetchQueries : true ,
37
- } ) ;
38
-
39
- const handleRemoveProductClick = (
40
- cartKey : string ,
41
- products : IProductRootObject [ ] ,
42
- ) => {
43
- if ( products ?. length ) {
44
- // Optimistically update local state
45
- const currentCart = cart ;
46
- if ( currentCart ) {
47
- const updatedProducts = currentCart . products . filter ( ( p : Product ) => p . cartKey !== cartKey ) ;
48
- setCart ( {
49
- ...currentCart ,
50
- products : updatedProducts ,
51
- totalProductsCount : currentCart . totalProductsCount - 1
52
- } ) ;
53
- }
35
+ const [ updateCart ] = useMutation ( UPDATE_CART ) ;
54
36
55
- // Update remote state in background
56
- const updatedItems = getUpdatedItems ( products , 0 , cartKey ) ;
57
- updateCart ( {
58
- variables : {
59
- input : {
60
- clientMutationId : uuidv4 ( ) ,
61
- items : updatedItems ,
62
- } ,
63
- } ,
37
+ const handleRemoveProductClick = ( cartKey : string ) => {
38
+ // Optimistically update local state
39
+ if ( cart ) {
40
+ const updatedProducts = cart . products . filter ( ( p : Product ) => p . cartKey !== cartKey ) ;
41
+ const removedProduct = cart . products . find ( ( p : Product ) => p . cartKey === cartKey ) ;
42
+ const qtyRemoved = removedProduct ?. qty || 0 ;
43
+
44
+ setCart ( {
45
+ ...cart ,
46
+ products : updatedProducts ,
47
+ totalProductsCount : cart . totalProductsCount - qtyRemoved
64
48
} ) ;
65
49
}
66
- } ;
67
50
68
- const cartTotal = data ?. cart ?. total || '0' ;
69
-
70
- const getUnitPrice = ( subtotal : string , quantity : number ) => {
71
- const numericSubtotal = parseFloat ( subtotal . replace ( / [ ^ 0 - 9 . - ] + / g, '' ) ) ;
72
- return isNaN ( numericSubtotal )
73
- ? 'N/A'
74
- : ( numericSubtotal / quantity ) . toFixed ( 2 ) ;
51
+ // Update remote state in background
52
+ updateCart ( {
53
+ variables : {
54
+ input : {
55
+ clientMutationId : uuidv4 ( ) ,
56
+ items : [ {
57
+ key : cartKey ,
58
+ quantity : 0
59
+ } ] ,
60
+ } ,
61
+ } ,
62
+ } ) ;
75
63
} ;
76
64
77
65
return (
78
66
< div className = "container mx-auto px-4 py-8" >
79
- { data ?. cart ?. contents ?. nodes ?. length ? (
67
+ { cart ?. products ?. length ? (
80
68
< >
81
69
< div className = "bg-white rounded-lg p-6 mb-8 md:w-full" >
82
- { data . cart . contents . nodes . map ( ( item : IProductRootObject ) => (
70
+ { cart . products . map ( ( item : Product ) => (
83
71
< div
84
- key = { item . key }
72
+ key = { item . cartKey }
85
73
className = "flex items-center border-b border-gray-200 py-4"
86
74
>
87
75
< div className = "flex-shrink-0 w-24 h-24 relative hidden md:block" >
88
76
< Image
89
- src = {
90
- item . product . node . image ?. sourceUrl || '/placeholder.png'
91
- }
92
- alt = { item . product . node . name }
77
+ src = { item . image ?. sourceUrl || '/placeholder.png' }
78
+ alt = { item . name }
93
79
layout = "fill"
94
80
objectFit = "cover"
95
81
className = "rounded"
96
82
/>
97
83
</ div >
98
84
< div className = "flex-grow ml-4" >
99
85
< h2 className = "text-lg font-semibold" >
100
- { item . product . node . name }
86
+ { item . name }
101
87
</ h2 >
102
88
< p className = "text-gray-600" >
103
- kr { getUnitPrice ( item . subtotal , item . quantity ) }
89
+ kr { item . price }
104
90
</ p >
105
91
</ div >
106
92
< div className = "flex items-center" >
107
93
< input
108
94
type = "number"
109
95
min = "1"
110
- value = { item . quantity }
96
+ value = { item . qty }
111
97
onChange = { ( event : ChangeEvent < HTMLInputElement > ) => {
112
98
const newQty = parseInt ( event . target . value , 10 ) ;
113
99
if ( isNaN ( newQty ) || newQty < 1 ) return ;
114
100
115
- // Optimistically update local state
116
- if ( cart ) {
117
- const oldProduct = cart . products . find ( ( p : Product ) => p . cartKey === item . key ) ;
118
- const oldQty = oldProduct ?. qty || 0 ;
119
- const updatedProducts = cart . products . map ( ( p : Product ) =>
120
- p . cartKey === item . key ? { ...p , qty : newQty } : p
121
- ) ;
122
-
123
- // Calculate new total count
124
- const qtyDiff = newQty - oldQty ;
125
- const newTotalCount = cart . totalProductsCount + qtyDiff ;
126
-
127
- setCart ( {
128
- ...cart ,
129
- products : updatedProducts ,
130
- totalProductsCount : newTotalCount
131
- } ) ;
132
- }
101
+ // Update local state
102
+ useCartStore . getState ( ) . updateProductQuantity ( item . cartKey , newQty ) ;
133
103
134
104
// Update remote state in background
135
105
handleQuantityChange (
136
106
event ,
137
- item . key ,
138
- data . cart . contents . nodes ,
107
+ item . cartKey ,
108
+ newQty ,
139
109
updateCart
140
110
) ;
141
111
} }
142
112
className = "w-16 px-2 py-1 text-center border border-gray-300 rounded mr-2"
143
113
/>
144
114
< Button
145
- handleButtonClick = { ( ) =>
146
- handleRemoveProductClick (
147
- item . key ,
148
- data . cart . contents . nodes ,
149
- )
150
- }
115
+ handleButtonClick = { ( ) => handleRemoveProductClick ( item . cartKey ) }
151
116
variant = "secondary"
152
117
>
153
118
Fjern
154
119
</ Button >
155
120
</ div >
156
121
< div className = "ml-4" >
157
- < p className = "text-lg font-semibold" > { item . subtotal } </ p >
122
+ < p className = "text-lg font-semibold" > { item . totalPrice } </ p >
158
123
</ div >
159
124
</ div >
160
125
) ) }
161
126
</ div >
162
127
< div className = "bg-white rounded-lg p-6 md:w-full" >
163
128
< div className = "flex justify-end mb-4" >
164
129
< span className = "font-semibold pr-2" > Subtotal:</ span >
165
- < span > { cartTotal } </ span >
130
+ < span > { cart . totalProductsPrice } </ span >
166
131
</ div >
167
132
{ ! isCheckoutPage && (
168
133
< div className = "flex justify-center mb-4" >
0 commit comments