Skip to content

Commit d9d21d3

Browse files
committed
feat: add success payment page
1 parent 763cad0 commit d9d21d3

File tree

15 files changed

+250
-39
lines changed

15 files changed

+250
-39
lines changed

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
"react-dom": "^18",
3737
"react-hook-form": "^7.51.3",
3838
"react-hot-toast": "^2.4.1",
39+
"react-lottie": "^1.2.10",
3940
"react-otp-input": "^3.1.1",
4041
"react-swipeable-views": "^0.14.0",
4142
"sharp": "^0.33.5",
@@ -57,6 +58,7 @@
5758
"@types/node": "^20",
5859
"@types/react": "^18",
5960
"@types/react-dom": "^18",
61+
"@types/react-lottie": "^1",
6062
"@types/react-swipeable-views": "^0",
6163
"@types/stylis": "^4.2.5",
6264
"babel-jest": "^29.7.0",

public/assets/json/checked.json

Lines changed: 1 addition & 0 deletions
Large diffs are not rendered by default.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
'use client';
2+
3+
import { Box } from '@mui/material';
4+
import React from 'react';
5+
import Lottie from 'react-lottie';
6+
7+
const CheckedAnimation = () => {
8+
return (
9+
<Box
10+
sx={{
11+
display: 'flex',
12+
justifyContent: 'center',
13+
alignItems: 'center',
14+
}}
15+
>
16+
<Lottie
17+
options={
18+
{
19+
loop: false,
20+
autoplay: true,
21+
path: '/assets/json/checked.json',
22+
rendererSettings: {
23+
preserveAspectRatio: 'xMidYMid slice',
24+
},
25+
} as any
26+
}
27+
height={150}
28+
width={150}
29+
isStopped={false}
30+
isPaused={false}
31+
/>
32+
</Box>
33+
);
34+
};
35+
36+
export default CheckedAnimation;
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
'use client';
2+
3+
import { Link } from '@/navigation';
4+
import { ContentCopyOutlined } from '@mui/icons-material';
5+
import { Button, Stack, Typography } from '@mui/material';
6+
import { useTranslations } from 'next-intl';
7+
import { FC } from 'react';
8+
import toast from 'react-hot-toast';
9+
import CheckedAnimation from './CheckedAnimation';
10+
11+
export interface OrderDetailsProps {
12+
orderId: number | string;
13+
transactionId: number | string;
14+
}
15+
16+
const OrderDetails: FC<OrderDetailsProps> = ({ orderId, transactionId }) => {
17+
const t = useTranslations();
18+
19+
const handleClickOnCopy = () => {
20+
navigator.clipboard
21+
.writeText(transactionId.toString())
22+
.then(() => {
23+
toast.success(t('messages.copied'));
24+
})
25+
.catch((err) => {});
26+
};
27+
28+
return (
29+
<Stack
30+
spacing={3}
31+
alignItems="center"
32+
justifyContent="center"
33+
sx={{
34+
textAlign: 'center',
35+
}}
36+
>
37+
<CheckedAnimation />
38+
<Typography variant="h5" gutterBottom>
39+
{t('order.payment.successful.title')}
40+
</Typography>
41+
<Typography variant="body1" color="textSecondary">
42+
{t('order.payment.successful.description')}
43+
</Typography>
44+
45+
<Stack direction="row" alignItems="center" spacing={1}>
46+
<Typography variant="body2" color="textSecondary" gutterBottom>
47+
{t('order.payment.successful.transactionId')}{' '}
48+
</Typography>
49+
<Button
50+
onClick={handleClickOnCopy}
51+
variant="outlined"
52+
endIcon={<ContentCopyOutlined fontSize="small" />}
53+
>
54+
<Typography variant="h6">{transactionId}</Typography>
55+
</Button>
56+
</Stack>
57+
<Button
58+
sx={{
59+
width: 'fit-content',
60+
}}
61+
LinkComponent={Link}
62+
href={`/profile/orders/${orderId}`}
63+
variant="contained"
64+
color="primary"
65+
size="large"
66+
>
67+
{t('order.view')}
68+
</Button>
69+
</Stack>
70+
);
71+
};
72+
73+
export default OrderDetails;
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import { getClient } from '@/graphql/clients/serverSideClient';
2+
import { GET_IS_PAYED_ORDER } from '@/graphql/queries/order';
3+
import { GetIsPayedOrderQuery } from '@/graphql/types/graphql';
4+
import { redirect } from '@/navigation';
5+
import { Card, CardContent } from '@mui/material';
6+
import { FC } from 'react';
7+
import OrderDetails from './components/OrderDetails';
8+
9+
interface PageProps {
10+
params: { id: string };
11+
}
12+
13+
const Page: FC<PageProps> = async (props) => {
14+
const orderId = +props.params.id;
15+
16+
try {
17+
const { data, error } = await getClient().query<GetIsPayedOrderQuery>({
18+
query: GET_IS_PAYED_ORDER,
19+
variables: {
20+
id: orderId,
21+
},
22+
});
23+
24+
if (!data.order?.datePaid) {
25+
throw new Error('Order not payed!');
26+
}
27+
28+
return (
29+
<Card variant="outlined" sx={{ width: '100%' }}>
30+
<CardContent>
31+
<OrderDetails
32+
transactionId={data.order.transactionId!}
33+
orderId={orderId}
34+
/>
35+
</CardContent>
36+
</Card>
37+
);
38+
} catch (error) {
39+
return redirect(`/profile/orders/${orderId}`);
40+
}
41+
};
42+
43+
export default Page;

src/components/ColumnFilters/ColumnFilters.tsx

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

33
import { GET_ALL_CATEGORIES_QUERY } from '@/graphql/queries/categories';
4-
import { CategoriesQuery } from '@/graphql/types/graphql';
4+
import { GetAllCategoriesQuery } from '@/graphql/types/graphql';
55
import useCustomSearchParams from '@/hooks/useCustomSearchParams';
6+
import { SearchPageParamsKeys } from '@/utils/params';
67
import { useQuery } from '@apollo/client';
78
import { ExpandLess, ExpandMore } from '@mui/icons-material';
89
import {
@@ -20,19 +21,18 @@ import { FC, useState } from 'react';
2021
import Categories from './components/Categories';
2122
import { ListItem } from './components/ListItem';
2223
import { Title } from './components/Title';
23-
import { SearchPageParamsKeys } from '@/utils/params';
2424

2525
export interface ColumnFiltersProps {}
2626

2727
const ColumnFilters: FC<ColumnFiltersProps> = () => {
2828
const t = useTranslations();
2929

30-
const { data: categoriesData } = useQuery<CategoriesQuery>(
30+
const { data: categoriesData } = useQuery<GetAllCategoriesQuery>(
3131
GET_ALL_CATEGORIES_QUERY,
3232
);
3333

3434
const categories = [
35-
{ id: -1, parentId: -1, name: t('categories.all') },
35+
{ id: -1, parentId: -1, name: t('categories.all'), image: {} as any },
3636
...(categoriesData?.productCategories?.nodes ?? []),
3737
];
3838

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { CategoriesQuery } from '@/graphql/types/graphql';
1+
import { GetAllCategoriesQuery } from '@/graphql/types/graphql';
22

33
export type ProductCategoryOptions = NonNullable<
4-
CategoriesQuery['productCategories']
4+
GetAllCategoriesQuery['productCategories']
55
>['nodes'];

src/components/InlineFilters/InlineFilters.tsx

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

3-
import { CategoriesQuery } from '@/graphql/types/graphql';
3+
import { GetAllCategoriesQuery } from '@/graphql/types/graphql';
44
import { sortOptions } from '@/static/sortOptions';
55
import { SortOutlined } from '@mui/icons-material';
66
import KeyboardArrowDownIcon from '@mui/icons-material/KeyboardArrowDown';
@@ -9,7 +9,7 @@ import { useTranslations } from 'next-intl';
99
import { FC } from 'react';
1010

1111
export interface InlineFiltersProps {
12-
categories?: NonNullable<CategoriesQuery['productCategories']>['nodes'];
12+
categories?: NonNullable<GetAllCategoriesQuery['productCategories']>['nodes'];
1313
}
1414
const InlineFilters: FC<InlineFiltersProps> = ({ categories }) => {
1515
const t = useTranslations();

src/data/i18n/en.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,13 @@
226226
"paidAmount": "Paid Amount",
227227
"yourProfit": "Your Profit from this Purchase"
228228
},
229-
"noRowsToShow": "No orders have been placed."
229+
"noRowsToShow": "No orders have been placed.",
230+
"payment": {
231+
"successful": {
232+
"title": "Payment Successful",
233+
"description": "Thank you for your purchase. Your payment has been successfully processed, and your order is now being prepared.",
234+
"transactionId": "Transaction ID"
235+
}
236+
}
230237
}
231238
}

src/data/i18n/fa.json

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,13 @@
226226
"paidAmount": "مبلغ پرداخت شده",
227227
"yourProfit": "سود شما از این خرید"
228228
},
229-
"noRowsToShow": "تاکنون سفارشی ثبت نشده است."
229+
"noRowsToShow": "تاکنون سفارشی ثبت نشده است.",
230+
"payment": {
231+
"successful": {
232+
"title": "پرداخت موفق",
233+
"description": "از خرید شما متشکریم. پرداخت شما با موفقیت انجام شده و سفارش شما در حال آماده‌سازی است.",
234+
"transactionId": "شناسه تراکنش"
235+
}
236+
}
230237
}
231238
}

0 commit comments

Comments
 (0)