Skip to content

Commit 4af7eb1

Browse files
committed
refactor: separate cart page components
1 parent 2aa32ea commit 4af7eb1

File tree

3 files changed

+137
-115
lines changed

3 files changed

+137
-115
lines changed
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import Image from '@/components/common/Image';
2+
import { Link } from '@/navigation';
3+
import { Box, Button, Stack, Typography } from '@mui/material';
4+
import { useTranslations } from 'next-intl';
5+
import React from 'react';
6+
7+
const EmptyCart = () => {
8+
const t = useTranslations();
9+
const links = [
10+
{
11+
title: t('buttons.products'),
12+
href: '/search',
13+
},
14+
{
15+
title: t('header.navigation.bestSelling'),
16+
href: '/best-selling',
17+
},
18+
{
19+
title: t('header.navigation.categories'),
20+
href: '/categories',
21+
},
22+
];
23+
24+
return (
25+
<Box
26+
sx={{
27+
display: 'flex',
28+
flexDirection: 'column',
29+
alignItems: 'center',
30+
justifyContent: 'center',
31+
textAlign: 'center',
32+
gap: 2,
33+
border: '1px solid',
34+
borderColor: 'divider',
35+
borderRadius: 1,
36+
p: 2,
37+
}}
38+
>
39+
<Box
40+
sx={{
41+
opacity: 0.7,
42+
filter: 'grayscale(100%)',
43+
}}
44+
>
45+
<Image
46+
src="/assets/images/cart/unsuccess.svg"
47+
alt="NotFound"
48+
width={105}
49+
height={105}
50+
/>
51+
</Box>
52+
<Typography variant="h6">{t('messages.cart.isEmpty')}</Typography>
53+
<Typography variant="caption">
54+
{t('messages.cart.shortDescription')}
55+
</Typography>
56+
<Stack spacing={2} direction="row">
57+
{links.map((link) => {
58+
return (
59+
<Link href={link.href} key={link.href}>
60+
<Button variant="outlined">{link.title}</Button>
61+
</Link>
62+
);
63+
})}
64+
</Stack>
65+
</Box>
66+
);
67+
};
68+
69+
export default EmptyCart;
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import CartItemSkeleton from '@/components/CartItem/components/CartItemSkeleton';
2+
import {
3+
Card,
4+
CardContent,
5+
Divider,
6+
Grid,
7+
Skeleton,
8+
Stack,
9+
} from '@mui/material';
10+
import React from 'react';
11+
12+
const Loading = () => {
13+
const skeletonLength = 4;
14+
return (
15+
<Grid container spacing={2}>
16+
<Grid item lg={9} md={6} xs={12}>
17+
<Card variant="outlined">
18+
<CardContent>
19+
<Grid container spacing={2}>
20+
{new Array(skeletonLength).fill(0).map((item, index) => {
21+
const isLast = skeletonLength === index + 1;
22+
return (
23+
<Grid item xs={12} key={index}>
24+
<Stack spacing={2}>
25+
<CartItemSkeleton />
26+
{!isLast && <Divider />}
27+
</Stack>
28+
</Grid>
29+
);
30+
})}
31+
</Grid>
32+
</CardContent>
33+
</Card>
34+
</Grid>
35+
36+
<Grid item lg={3} md={6} xs={12}>
37+
<Stack spacing={2}>
38+
<Card variant="outlined">
39+
<CardContent>
40+
<Stack spacing={1}>
41+
{new Array(3).fill(1).map((item, index) => {
42+
return (
43+
<Stack
44+
key={index}
45+
direction="row"
46+
spacing={1}
47+
justifyContent="space-between"
48+
>
49+
<Skeleton variant="text" width={80} />
50+
<Skeleton variant="text" width={80} />
51+
</Stack>
52+
);
53+
})}
54+
<Skeleton variant="rectangular" height={45} />
55+
</Stack>
56+
</CardContent>
57+
</Card>
58+
</Stack>
59+
</Grid>
60+
</Grid>
61+
);
62+
};
63+
64+
export default Loading;

src/app/[locale]/(main)/(container)/cart/page.tsx

Lines changed: 4 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
'use client';
22

33
import CartItem from '@/components/CartItem/CartItem';
4-
import CartItemSkeleton from '@/components/CartItem/components/CartItemSkeleton';
54
import CartItemController from '@/components/CartItemController/CartItemController';
65
import OutOfStock from '@/components/common/OutOfStock';
76
import PriceLabel from '@/components/common/PriceLabel';
@@ -13,7 +12,6 @@ import {
1312
StockStatusEnum,
1413
} from '@/graphql/types/graphql';
1514
import useCartQuery from '@/hooks/useCartQuery';
16-
import { Link as NextLink } from '@/navigation';
1715
import { cartAtom } from '@/store/atoms';
1816
import {
1917
Box,
@@ -23,134 +21,25 @@ import {
2321
CardContent,
2422
Divider,
2523
Grid,
26-
Skeleton,
2724
Stack,
2825
Typography,
2926
} from '@mui/material';
3027
import { useAtomValue } from 'jotai';
3128
import { useTranslations } from 'next-intl';
32-
import Image from 'next/image';
29+
import Loading from '../loading';
3330
import CheckoutBox, { CheckoutBoxProps } from './components/CheckoutBox';
3431
import Header from './components/Header';
32+
import EmptyCart from './components/EmptyCart';
3533

3634
const Page = () => {
3735
const t = useTranslations();
3836
const { loading } = useCartQuery();
3937

4038
const cart = useAtomValue(cartAtom);
4139

42-
if (loading) {
43-
const skeletonLength = 4;
44-
return (
45-
<Grid container spacing={2}>
46-
<Grid item lg={9} md={6} xs={12}>
47-
<Card variant="outlined">
48-
<CardContent>
49-
<Grid container spacing={2}>
50-
{new Array(skeletonLength).fill(0).map((item, index) => {
51-
const isLast = skeletonLength === index + 1;
52-
return (
53-
<Grid item xs={12} key={index}>
54-
<Stack spacing={2}>
55-
<CartItemSkeleton />
56-
{!isLast && <Divider />}
57-
</Stack>
58-
</Grid>
59-
);
60-
})}
61-
</Grid>
62-
</CardContent>
63-
</Card>
64-
</Grid>
65-
66-
<Grid item lg={3} md={6} xs={12}>
67-
<Stack spacing={2}>
68-
<Card variant="outlined">
69-
<CardContent>
70-
<Stack spacing={1}>
71-
{new Array(3).fill(1).map((item, index) => {
72-
return (
73-
<Stack
74-
key={index}
75-
direction="row"
76-
spacing={1}
77-
justifyContent="space-between"
78-
>
79-
<Skeleton variant="text" width={80} />
80-
<Skeleton variant="text" width={80} />
81-
</Stack>
82-
);
83-
})}
84-
<Skeleton variant="rectangular" height={45} />
85-
</Stack>
86-
</CardContent>
87-
</Card>
88-
</Stack>
89-
</Grid>
90-
</Grid>
91-
);
92-
}
40+
if (loading) return <Loading />;
9341

94-
if (!cart?.contents?.itemCount) {
95-
const links = [
96-
{
97-
title: t('buttons.products'),
98-
href: '/search',
99-
},
100-
{
101-
title: t('header.navigation.bestSelling'),
102-
href: '/best-selling',
103-
},
104-
{
105-
title: t('header.navigation.categories'),
106-
href: '/categories',
107-
},
108-
];
109-
110-
return (
111-
<Box
112-
sx={{
113-
display: 'flex',
114-
flexDirection: 'column',
115-
alignItems: 'center',
116-
justifyContent: 'center',
117-
textAlign: 'center',
118-
gap: 2,
119-
border: '1px solid',
120-
borderColor: 'divider',
121-
borderRadius: 1,
122-
p: 2,
123-
}}
124-
>
125-
<Box
126-
sx={{
127-
opacity: 0.7,
128-
filter: 'grayscale(100%)',
129-
}}
130-
>
131-
<Image
132-
src="/assets/images/cart/unsuccess.svg"
133-
alt="NotFound"
134-
width={105}
135-
height={105}
136-
/>
137-
</Box>
138-
<Typography variant="h6">{t('messages.cart.isEmpty')}</Typography>
139-
<Typography variant="caption">
140-
{t('messages.cart.shortDescription')}
141-
</Typography>
142-
<Stack spacing={2} direction="row">
143-
{links.map((link) => {
144-
return (
145-
<NextLink href={link.href} key={link.href}>
146-
<Button variant="outlined">{link.title}</Button>
147-
</NextLink>
148-
);
149-
})}
150-
</Stack>
151-
</Box>
152-
);
153-
}
42+
if (!cart?.contents?.itemCount) return <EmptyCart />;
15443

15544
const checkoutBoxItems: CheckoutBoxProps['items'] = [
15645
{

0 commit comments

Comments
 (0)