Skip to content

Commit 2c2f53c

Browse files
authored
Merge pull request #1317 from w3bdesign/1314-improve-cart-design-on-mobile
Update CartContents.component.tsx
2 parents 0ae244c + 59961de commit 2c2f53c

File tree

3 files changed

+91
-103
lines changed

3 files changed

+91
-103
lines changed

src/components/Cart/CartContents.component.tsx

Lines changed: 89 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,43 @@
1-
/*eslint complexity: ["error", 20]*/
2-
// Imports
31
import { useContext, useEffect } from 'react';
42
import { useMutation, useQuery } from '@apollo/client';
53
import Link from 'next/link';
4+
import Image from 'next/image';
65
import { useRouter } from 'next/router';
76
import { v4 as uuidv4 } from 'uuid';
87

9-
// State
108
import { CartContext } from '@/stores/CartProvider';
11-
12-
// Components
139
import Button from '@/components/UI/Button.component';
1410
import LoadingSpinner from '../LoadingSpinner/LoadingSpinner.component';
1511

16-
// Utils
1712
import {
1813
getFormattedCart,
1914
getUpdatedItems,
2015
handleQuantityChange,
2116
IProductRootObject,
2217
} from '@/utils/functions/functions';
2318

24-
// GraphQL
2519
import { GET_CART } from '@/utils/gql/GQL_QUERIES';
2620
import { UPDATE_CART } from '@/utils/gql/GQL_MUTATIONS';
2721

28-
/**
29-
* Renders cart contents.
30-
* @function CartContents
31-
* @returns {JSX.Element} - Rendered component
32-
*/
3322
const CartContents = () => {
3423
const router = useRouter();
35-
3624
const { setCart } = useContext(CartContext);
37-
3825
const isCheckoutPage = router.pathname === '/kasse';
3926

40-
// Get cart data query
4127
const { data, refetch } = useQuery(GET_CART, {
4228
notifyOnNetworkStatusChange: true,
4329
onCompleted: () => {
44-
// Update cart in the localStorage.
4530
const updatedCart = getFormattedCart(data);
46-
4731
if (!updatedCart && !data.cart.contents.nodes.length) {
48-
// Clear the localStorage if we have no remote cart
49-
5032
localStorage.removeItem('woocommerce-cart');
5133
setCart(null);
5234
return;
5335
}
54-
5536
localStorage.setItem('woocommerce-cart', JSON.stringify(updatedCart));
56-
57-
// Update cart data in React Context.
5837
setCart(updatedCart);
5938
},
6039
});
6140

62-
// Update Cart Mutation.
6341
const [updateCart, { loading: updateCartProcessing }] = useMutation(
6442
UPDATE_CART,
6543
{
@@ -76,11 +54,8 @@ const CartContents = () => {
7654
cartKey: string,
7755
products: IProductRootObject[],
7856
) => {
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);
8459
updateCart({
8560
variables: {
8661
input: {
@@ -90,9 +65,7 @@ const CartContents = () => {
9065
},
9166
});
9267
}
93-
9468
refetch();
95-
9669
setTimeout(() => {
9770
refetch();
9871
}, 3000);
@@ -102,50 +75,46 @@ const CartContents = () => {
10275
refetch();
10376
}, [refetch]);
10477

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+
10587
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'
128101
}
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">
147117
<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"
149118
type="number"
150119
min="1"
151120
value={item.quantity}
@@ -158,41 +127,60 @@ const CartContents = () => {
158127
updateCartProcessing,
159128
);
160129
}}
130+
className="w-16 px-2 py-1 text-center border border-gray-300 rounded mr-2"
161131
/>
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>
171148
</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>
172155
</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+
)}
185163
</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 />
192180
</div>
193-
) : null}
194-
</div>
195-
</section>
181+
</div>
182+
)}
183+
</div>
196184
);
197185
};
198186

src/components/Layout/Layout.component.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ const Layout = ({ children, title }: ILayoutProps) => {
5656
}, [refetch]);
5757

5858
return (
59-
<div className="flex flex-col min-h-screen">
59+
<div className="flex flex-col min-h-screen container min-w-[140vw] md:min-w-[700px]">
6060
<Header title={title} />
6161
<PageTitle title={title} />
6262
<main className="flex-grow">

src/components/Product/SingleProduct.component.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ const SingleProduct = ({ product }: IProductRootObject) => {
115115
<select
116116
id="variant"
117117
name="variant"
118-
className="block w-full px-4 py-2 bg-white border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
118+
className="max-w-[14.375rem] block w-full px-4 py-2 bg-white border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
119119
onChange={(e) => {
120120
setSelectedVariation(Number(e.target.value));
121121
}}

0 commit comments

Comments
 (0)