1
- /*eslint complexity: ["error", 20]*/
2
- // Imports
3
1
import { useContext , useEffect } from 'react' ;
4
2
import { useMutation , useQuery } from '@apollo/client' ;
5
3
import Link from 'next/link' ;
4
+ import Image from 'next/image' ;
6
5
import { useRouter } from 'next/router' ;
7
6
import { v4 as uuidv4 } from 'uuid' ;
8
7
9
- // State
10
8
import { CartContext } from '@/stores/CartProvider' ;
11
-
12
- // Components
13
9
import Button from '@/components/UI/Button.component' ;
14
10
import LoadingSpinner from '../LoadingSpinner/LoadingSpinner.component' ;
15
11
16
- // Utils
17
12
import {
18
13
getFormattedCart ,
19
14
getUpdatedItems ,
20
15
handleQuantityChange ,
21
16
IProductRootObject ,
22
17
} from '@/utils/functions/functions' ;
23
18
24
- // GraphQL
25
19
import { GET_CART } from '@/utils/gql/GQL_QUERIES' ;
26
20
import { UPDATE_CART } from '@/utils/gql/GQL_MUTATIONS' ;
27
21
28
- /**
29
- * Renders cart contents.
30
- * @function CartContents
31
- * @returns {JSX.Element } - Rendered component
32
- */
33
22
const CartContents = ( ) => {
34
23
const router = useRouter ( ) ;
35
-
36
24
const { setCart } = useContext ( CartContext ) ;
37
-
38
25
const isCheckoutPage = router . pathname === '/kasse' ;
39
26
40
- // Get cart data query
41
27
const { data, refetch } = useQuery ( GET_CART , {
42
28
notifyOnNetworkStatusChange : true ,
43
29
onCompleted : ( ) => {
44
- // Update cart in the localStorage.
45
30
const updatedCart = getFormattedCart ( data ) ;
46
-
47
31
if ( ! updatedCart && ! data . cart . contents . nodes . length ) {
48
- // Clear the localStorage if we have no remote cart
49
-
50
32
localStorage . removeItem ( 'woocommerce-cart' ) ;
51
33
setCart ( null ) ;
52
34
return ;
53
35
}
54
-
55
36
localStorage . setItem ( 'woocommerce-cart' , JSON . stringify ( updatedCart ) ) ;
56
-
57
- // Update cart data in React Context.
58
37
setCart ( updatedCart ) ;
59
38
} ,
60
39
} ) ;
61
40
62
- // Update Cart Mutation.
63
- const [ updateCart , { loading : updateCartProcessing } ] = useMutation (
64
- UPDATE_CART ,
65
- {
66
- onCompleted : ( ) => {
41
+ const [ updateCart , { loading : updateCartProcessing } ] = useMutation ( UPDATE_CART , {
42
+ onCompleted : ( ) => {
43
+ refetch ( ) ;
44
+ setTimeout ( ( ) => {
67
45
refetch ( ) ;
68
- setTimeout ( ( ) => {
69
- refetch ( ) ;
70
- } , 3000 ) ;
71
- } ,
46
+ } , 3000 ) ;
72
47
} ,
73
- ) ;
48
+ } ) ;
74
49
75
- const handleRemoveProductClick = (
76
- cartKey : string ,
77
- products : IProductRootObject [ ] ,
78
- ) => {
50
+ const handleRemoveProductClick = ( cartKey : string , products : IProductRootObject [ ] ) => {
79
51
if ( products . length ) {
80
- // By passing the newQty to 0 in updateCart Mutation, it will remove the item.
81
- const newQty = 0 ;
82
- const updatedItems = getUpdatedItems ( products , newQty , cartKey ) ;
83
-
52
+ const updatedItems = getUpdatedItems ( products , 0 , cartKey ) ;
84
53
updateCart ( {
85
54
variables : {
86
55
input : {
@@ -90,9 +59,7 @@ const CartContents = () => {
90
59
} ,
91
60
} ) ;
92
61
}
93
-
94
62
refetch ( ) ;
95
-
96
63
setTimeout ( ( ) => {
97
64
refetch ( ) ;
98
65
} , 3000 ) ;
@@ -102,50 +69,31 @@ const CartContents = () => {
102
69
refetch ( ) ;
103
70
} , [ refetch ] ) ;
104
71
72
+ const cartTotal = data ?. cart ?. total || '0' ;
73
+
105
74
return (
106
- < section className = "py-8 mt-10" >
107
- < div className = "container flex flex-wrap items-center mx-auto" >
108
- { data ?. cart ?. contents ?. nodes . length ? (
109
- data . cart . contents . nodes . map ( ( item : IProductRootObject ) => (
110
- < div
111
- className = "container mx-auto mt-4 flex flex-wrap flex-row justify-around items-center content-center m-w-[1380px] border border-gray-300 rounded-lg shadow
112
- "
113
- key = { item . key }
114
- >
115
- < div className = "lg:m-2 xl:m-4 xl:w-1/6 lg:w-1/6 sm:m-2 w-auto" >
116
- < span className = "block mt-2 font-extrabold" >
117
- Slett: < br />
118
- </ span >
119
- < span className = "inline-block mt-4 w-20 h-12 md:w-full lg:w-full xl:w-full" >
120
- < Button
121
- color = "red"
122
- buttonDisabled = { updateCartProcessing }
123
- handleButtonClick = { ( ) =>
124
- handleRemoveProductClick (
125
- item . key ,
126
- data . cart . contents . nodes ,
127
- )
128
- }
129
- >
130
- Slett
131
- </ Button >
132
- </ span >
133
- </ div >
134
- < div className = "lg:m-2 xl:m-4 xl:w-1/6 lg:w-1/6 sm:m-2 w-auto" >
135
- < span className = "block mt-2 font-extrabold" >
136
- Navn: < br />
137
- </ span >
138
- < span className = "inline-block mt-4 w-20 h-12 md:w-full lg:w-full xl:w-full" >
139
- { item . product . node . name }
140
- </ span >
141
- </ div >
142
- < div className = "lg:m-2 xl:m-4 xl:w-1/6 lg:w-1/6 sm:m-2 w-auto" >
143
- < span className = "block mt-2 font-extrabold" >
144
- Antall: < br />
145
- </ span >
146
- < span className = "inline-block mt-4 w-20 h-12 md:w-full lg:w-full xl:w-full" >
75
+ < div className = "container mx-auto px-4 py-8" >
76
+ < h1 className = "text-3xl font-bold mb-8" > Handlekurv</ h1 >
77
+ { data ?. cart ?. contents ?. nodes . length ? (
78
+ < >
79
+ < div className = "bg-white rounded-lg shadow-md p-6 mb-8" >
80
+ { data . cart . contents . nodes . map ( ( item : IProductRootObject ) => (
81
+ < div key = { item . key } className = "flex items-center border-b border-gray-200 py-4" >
82
+ < div className = "flex-shrink-0 w-24 h-24 relative" >
83
+ < Image
84
+ src = { item . product . node . image ?. sourceUrl || '/placeholder.png' }
85
+ alt = { item . product . node . name }
86
+ layout = "fill"
87
+ objectFit = "cover"
88
+ className = "rounded"
89
+ />
90
+ </ div >
91
+ < div className = "flex-grow ml-4" >
92
+ < h2 className = "text-lg font-semibold" > { item . product . node . name } </ h2 >
93
+ < p className = "text-gray-600" > { item . product . node . price } </ p >
94
+ </ div >
95
+ < div className = "flex items-center" >
147
96
< input
148
- className = "bg-gray-50 border border-gray-300 text-gray-900 text-sm focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500"
149
97
type = "number"
150
98
min = "1"
151
99
value = { item . quantity }
@@ -158,41 +106,55 @@ const CartContents = () => {
158
106
updateCartProcessing ,
159
107
) ;
160
108
} }
109
+ className = "w-16 px-2 py-1 text-center border border-gray-300 rounded mr-2"
161
110
/>
162
- </ span >
163
- </ div >
164
- < div className = "lg:m-2 xl:m-4 xl:w-1/6 lg:w-1/6 sm:m-2 w-auto" >
165
- < span className = "block mt-2 font-extrabold" >
166
- Total: < br />
167
- </ span >
168
- < span className = "inline-block mt-4 w-20 h-12 md:w-full lg:w-full xl:w-full" >
169
- { item . subtotal }
170
- </ span >
111
+ < button
112
+ onClick = { ( ) => handleRemoveProductClick ( item . key , data . cart . contents . nodes ) }
113
+ className = "text-red-500 hover:text-red-700"
114
+ disabled = { updateCartProcessing }
115
+ >
116
+ Fjern
117
+ </ button >
118
+ </ div >
119
+ < div className = "ml-4" >
120
+ < p className = "text-lg font-semibold" > { item . subtotal } </ p >
121
+ </ div >
171
122
</ div >
123
+ ) ) }
124
+ </ div >
125
+ < div className = "bg-white rounded-lg shadow-md p-6" >
126
+ < div className = "flex justify-between mb-4" >
127
+ < span className = "font-semibold" > Subtotal:</ span >
128
+ < span > { cartTotal } </ span >
172
129
</ div >
173
- ) )
174
- ) : (
175
- < h1 className = "text-2xl font-bold mx-auto" >
176
- Ingen produkter i handlekurven
177
- </ h1 >
178
- ) }
179
- { updateCartProcessing && (
180
- < div className = "mt-4 w-full" >
181
- < div className = "text-xl mx-auto text-center" >
182
- Oppdaterer antall, vennligst vent ...
183
- < LoadingSpinner />
184
- </ div >
130
+ { ! isCheckoutPage && (
131
+ < Link href = "/kasse" passHref >
132
+ < Button className = "w-full bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" >
133
+ GÅ TIL KASSE
134
+ </ Button >
135
+ </ Link >
136
+ ) }
185
137
</ div >
186
- ) }
187
- { ! isCheckoutPage && data ?. cart ?. contents ?. nodes . length ? (
188
- < div className = "mt-4 mx-auto" >
189
- < Link href = "/kasse" passHref >
190
- < Button > GÅ TIL KASSE</ Button >
191
- </ Link >
138
+ </ >
139
+ ) : (
140
+ < div className = "text-center" >
141
+ < h2 className = "text-2xl font-bold mb-4" > Ingen produkter i handlekurven</ h2 >
142
+ < Link href = "/produkter" passHref >
143
+ < Button className = "bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded" >
144
+ Fortsett å handle
145
+ </ Button >
146
+ </ Link >
147
+ </ div >
148
+ ) }
149
+ { updateCartProcessing && (
150
+ < div className = "fixed inset-0 flex items-center justify-center bg-black bg-opacity-50" >
151
+ < div className = "bg-white p-4 rounded-lg" >
152
+ < p className = "text-lg mb-2" > Oppdaterer handlekurv...</ p >
153
+ < LoadingSpinner />
192
154
</ div >
193
- ) : null }
194
- </ div >
195
- </ section >
155
+ </ div >
156
+ ) }
157
+ </ div >
196
158
) ;
197
159
} ;
198
160
0 commit comments