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
41
const [ updateCart , { loading : updateCartProcessing } ] = useMutation (
64
42
UPDATE_CART ,
65
43
{
@@ -76,11 +54,8 @@ const CartContents = () => {
76
54
cartKey : string ,
77
55
products : IProductRootObject [ ] ,
78
56
) => {
79
- 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
-
57
+ if ( products ?. length ) {
58
+ const updatedItems = getUpdatedItems ( products , 0 , cartKey ) ;
84
59
updateCart ( {
85
60
variables : {
86
61
input : {
@@ -90,9 +65,7 @@ const CartContents = () => {
90
65
} ,
91
66
} ) ;
92
67
}
93
-
94
68
refetch ( ) ;
95
-
96
69
setTimeout ( ( ) => {
97
70
refetch ( ) ;
98
71
} , 3000 ) ;
@@ -102,50 +75,46 @@ const CartContents = () => {
102
75
refetch ( ) ;
103
76
} , [ refetch ] ) ;
104
77
78
+ const cartTotal = data ?. cart ?. total || '0' ;
79
+
80
+ const getUnitPrice = ( subtotal : string , quantity : number ) => {
81
+ const numericSubtotal = parseFloat ( subtotal . replace ( / [ ^ 0 - 9 . - ] + / g, '' ) ) ;
82
+ return isNaN ( numericSubtotal )
83
+ ? 'N/A'
84
+ : ( numericSubtotal / quantity ) . toFixed ( 2 ) ;
85
+ } ;
86
+
105
87
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
- )
88
+ < div className = "container mx-auto px-4 py-8" >
89
+ { data ?. cart ?. contents ?. nodes ?. length ? (
90
+ < >
91
+ < div className = "bg-white rounded-lg shadow-md p-6 mb-8 md:w-full" >
92
+ { data . cart . contents . nodes . map ( ( item : IProductRootObject ) => (
93
+ < div
94
+ key = { item . key }
95
+ className = "flex items-center border-b border-gray-200 py-4"
96
+ >
97
+ < div className = "flex-shrink-0 w-24 h-24 relative" >
98
+ < Image
99
+ src = {
100
+ item . product . node . image ?. sourceUrl || '/placeholder.png'
128
101
}
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" >
102
+ alt = { item . product . node . name }
103
+ layout = "fill"
104
+ objectFit = "cover"
105
+ className = "rounded"
106
+ />
107
+ </ div >
108
+ < div className = "flex-grow ml-4" >
109
+ < h2 className = "text-lg font-semibold" >
110
+ { item . product . node . name }
111
+ </ h2 >
112
+ < p className = "text-gray-600" >
113
+ kr { getUnitPrice ( item . subtotal , item . quantity ) }
114
+ </ p >
115
+ </ div >
116
+ < div className = "flex items-center" >
147
117
< 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
118
type = "number"
150
119
min = "1"
151
120
value = { item . quantity }
@@ -158,41 +127,60 @@ const CartContents = () => {
158
127
updateCartProcessing ,
159
128
) ;
160
129
} }
130
+ className = "w-16 px-2 py-1 text-center border border-gray-300 rounded mr-2"
161
131
/>
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 >
132
+ < Button
133
+ handleButtonClick = { ( ) =>
134
+ handleRemoveProductClick (
135
+ item . key ,
136
+ data . cart . contents . nodes ,
137
+ )
138
+ }
139
+ color = "red"
140
+ buttonDisabled = { updateCartProcessing }
141
+ >
142
+ Fjern
143
+ </ Button >
144
+ </ div >
145
+ < div className = "ml-4" >
146
+ < p className = "text-lg font-semibold" > { item . subtotal } </ p >
147
+ </ div >
171
148
</ div >
149
+ ) ) }
150
+ </ div >
151
+ < div className = "bg-white rounded-lg shadow-md p-6 md:w-full" >
152
+ < div className = "flex justify-end mb-4" >
153
+ < span className = "font-semibold pr-2" > Subtotal:</ span >
154
+ < span > { cartTotal } </ span >
172
155
</ 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 >
156
+ { ! isCheckoutPage && (
157
+ < div className = "flex justify-center mb-4" >
158
+ < Link href = "/kasse" passHref >
159
+ < Button fullWidth > GÅ TIL KASSE</ Button >
160
+ </ Link >
161
+ </ div >
162
+ ) }
185
163
</ 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 >
164
+ </ >
165
+ ) : (
166
+ < div className = "text-center" >
167
+ < h2 className = "text-2xl font-bold mb-4" >
168
+ Ingen produkter i handlekurven
169
+ </ h2 >
170
+ < Link href = "/produkter" passHref >
171
+ < Button > Fortsett å handle</ Button >
172
+ </ Link >
173
+ </ div >
174
+ ) }
175
+ { updateCartProcessing && (
176
+ < div className = "fixed inset-0 flex items-center justify-center bg-black bg-opacity-50" >
177
+ < div className = "bg-white p-4 rounded-lg" >
178
+ < p className = "text-lg mb-2" > Oppdaterer handlekurv...</ p >
179
+ < LoadingSpinner />
192
180
</ div >
193
- ) : null }
194
- </ div >
195
- </ section >
181
+ </ div >
182
+ ) }
183
+ </ div >
196
184
) ;
197
185
} ;
198
186
0 commit comments