| @@ -1,28 +1,29 @@ | |||
| import { Box } from '@mui/system'; | |||
| import { ReactNode } from 'react'; | |||
| interface CardContainerProps { | |||
| children: JSX.Element; | |||
| children: ReactNode; | |||
| } | |||
| const CardContainer: React.FC<CardContainerProps> = ({ children }) => { | |||
| return ( | |||
| <Box | |||
| sx={{ | |||
| ml: { md: 2 }, | |||
| mt: { xs: 5, md: 0 }, | |||
| display: 'flex', | |||
| flexDirection: { | |||
| xs: 'column', | |||
| sm: 'row', | |||
| lg: 'column', | |||
| }, | |||
| justifyContent: { sm: 'flex-start' }, | |||
| flexWrap: 'wrap', | |||
| }} | |||
| > | |||
| {children} | |||
| </Box> | |||
| ); | |||
| return ( | |||
| <Box | |||
| sx={{ | |||
| ml: { md: 2 }, | |||
| mt: { xs: 5, md: 0 }, | |||
| display: 'flex', | |||
| flexDirection: { | |||
| xs: 'column', | |||
| sm: 'row', | |||
| lg: 'column', | |||
| }, | |||
| justifyContent: { sm: 'flex-start' }, | |||
| flexWrap: 'wrap', | |||
| }} | |||
| > | |||
| {children} | |||
| </Box> | |||
| ); | |||
| }; | |||
| export default CardContainer; | |||
| @@ -1,74 +1,74 @@ | |||
| import { Box, Card, Typography } from '@mui/material'; | |||
| import Image from 'next/image'; | |||
| import { ProductDataDB } from '../../../utils/interface/productInterface'; | |||
| import { ProductData } from '../../../utils/interface/productInterface'; | |||
| interface DataCardProps { | |||
| data: ProductDataDB; | |||
| quantity: number; | |||
| data: ProductData; | |||
| quantity: number; | |||
| } | |||
| const DataCard: React.FC<DataCardProps> = ({ data, quantity }) => { | |||
| return ( | |||
| <Card | |||
| return ( | |||
| <Card | |||
| sx={{ | |||
| backgroundColor: '#f2f2f2', | |||
| mb: 2, | |||
| p: 2, | |||
| mx: { xs: 0, sm: 1 }, | |||
| width: { xs: '100%', sm: '44%', md: '100%', lg: '100%' }, | |||
| }} | |||
| > | |||
| <Box | |||
| sx={{ | |||
| display: 'flex', | |||
| flexDirection: { xs: 'column', lg: 'row' }, | |||
| }} | |||
| > | |||
| <Box sx={{ display: 'flex', justifyContent: 'center' }}> | |||
| <Image src={data.image} alt="profile" width={200} height={200} /> | |||
| </Box> | |||
| <Box | |||
| sx={{ | |||
| width: '100%', | |||
| display: 'flex', | |||
| flexDirection: 'column', | |||
| alignItems: 'center', | |||
| justifyItems: 'center', | |||
| }} | |||
| > | |||
| <Typography | |||
| sx={{ | |||
| backgroundColor: '#f2f2f2', | |||
| mb: 2, | |||
| p: 2, | |||
| mx: { xs: 0, sm: 1 }, | |||
| width: { xs: '100%', sm: '44%', md: '100%', lg: '100%' }, | |||
| textAlign: 'center', | |||
| fontWeight: 600, | |||
| fontSize: { md: 20, xs: 16 }, | |||
| pt: { xs: 2 }, | |||
| }} | |||
| > | |||
| <Box | |||
| sx={{ | |||
| display: 'flex', | |||
| flexDirection: { xs: 'column', lg: 'row' }, | |||
| }} | |||
| > | |||
| <Box sx={{ display: 'flex', justifyContent: 'center' }}> | |||
| <Image src={data.image} alt="profile" width={200} height={200} /> | |||
| </Box> | |||
| <Box | |||
| sx={{ | |||
| width: '100%', | |||
| display: 'flex', | |||
| flexDirection: 'column', | |||
| alignItems: 'center', | |||
| justifyItems: 'center', | |||
| }} | |||
| > | |||
| <Typography | |||
| sx={{ | |||
| textAlign: 'center', | |||
| fontWeight: 600, | |||
| fontSize: { md: 20, xs: 16 }, | |||
| pt: { xs: 2 }, | |||
| }} | |||
| > | |||
| {data.name} | |||
| </Typography> | |||
| <Typography | |||
| sx={{ | |||
| width: '100%', | |||
| textAlign: 'center', | |||
| fontWeight: 600, | |||
| fontSize: { md: 20, xs: 16 }, | |||
| }} | |||
| > | |||
| x{quantity} | |||
| </Typography> | |||
| <Typography | |||
| sx={{ | |||
| mt: { lg: 3, xs: 1 }, | |||
| textAlign: 'center', | |||
| fontSize: 14, | |||
| }} | |||
| > | |||
| ${data.price} (per unit) | |||
| </Typography> | |||
| </Box> | |||
| </Box> | |||
| </Card> | |||
| ); | |||
| > | |||
| {data.name} | |||
| </Typography> | |||
| <Typography | |||
| sx={{ | |||
| width: '100%', | |||
| textAlign: 'center', | |||
| fontWeight: 600, | |||
| fontSize: { md: 20, xs: 16 }, | |||
| }} | |||
| > | |||
| x{quantity} | |||
| </Typography> | |||
| <Typography | |||
| sx={{ | |||
| mt: { lg: 3, xs: 1 }, | |||
| textAlign: 'center', | |||
| fontSize: 14, | |||
| }} | |||
| > | |||
| ${data.price} (per unit) | |||
| </Typography> | |||
| </Box> | |||
| </Box> | |||
| </Card> | |||
| ); | |||
| }; | |||
| export default DataCard; | |||
| @@ -1,51 +1,53 @@ | |||
| import { Card, Divider, Typography } from '@mui/material'; | |||
| import { Box } from '@mui/system'; | |||
| import { useTranslation } from 'next-i18next'; | |||
| import { OrderCard } from '../../../utils/interface/orderInterface'; | |||
| interface OrderCardProps { | |||
| data: OrderCard; | |||
| data: { | |||
| date: string; | |||
| name: string; | |||
| totalPrice: number; | |||
| }; | |||
| } | |||
| const OrderCard: React.FC<OrderCardProps> = ({ data }) => { | |||
| const { t } = useTranslation('profile'); | |||
| return ( | |||
| <Card | |||
| sx={{ | |||
| backgroundColor: '#f2f2f2', | |||
| mb: 2, | |||
| p: 2, | |||
| mx: { xs: 0, sm: 1 }, | |||
| width: { xs: '100%', sm: '47%', md: '100%', lg: '100%' }, | |||
| height: "100%" | |||
| }} | |||
| > | |||
| <Box | |||
| sx={{ | |||
| display: 'flex', | |||
| flexDirection: 'column', | |||
| alignItems: { xs: 'center', md: 'flex-start' }, | |||
| }} | |||
| > | |||
| <Typography sx={{ fontWeight: 600 }}> | |||
| <> | |||
| {t('profile:orderDate')} | |||
| {data.date} | |||
| </> | |||
| </Typography> | |||
| <Divider /> | |||
| <Typography sx={{ mt: 1 }}> | |||
| {t('profile:by')} | |||
| {data.name} | |||
| </Typography> | |||
| <Typography> | |||
| {t('profile:total')} | |||
| {data.totalPrice.toFixed(2)} | |||
| </Typography> | |||
| </Box> | |||
| </Card> | |||
| ); | |||
| const { t } = useTranslation('profile'); | |||
| return ( | |||
| <Card | |||
| sx={{ | |||
| backgroundColor: '#f2f2f2', | |||
| mb: 2, | |||
| p: 2, | |||
| mx: { xs: 0, sm: 1 }, | |||
| width: { xs: '100%', sm: '47%', md: '100%', lg: '100%' }, | |||
| height: '100%', | |||
| }} | |||
| > | |||
| <Box | |||
| sx={{ | |||
| display: 'flex', | |||
| flexDirection: 'column', | |||
| alignItems: { xs: 'center', md: 'flex-start' }, | |||
| }} | |||
| > | |||
| <Typography sx={{ fontWeight: 600 }}> | |||
| <> | |||
| {t('profile:orderDate')} | |||
| {data.date} | |||
| </> | |||
| </Typography> | |||
| <Divider /> | |||
| <Typography sx={{ mt: 1 }}> | |||
| {t('profile:by')} | |||
| {data.name} | |||
| </Typography> | |||
| <Typography> | |||
| {t('profile:total')} | |||
| {data.totalPrice.toFixed(2)} | |||
| </Typography> | |||
| </Box> | |||
| </Card> | |||
| ); | |||
| }; | |||
| export default OrderCard; | |||
| @@ -73,7 +73,7 @@ const CheckoutContent = () => { | |||
| <ContentContainer> | |||
| <Box flexGrow={1} sx={{ minWidth: '65%' }}> | |||
| <ShippingDetailsForm | |||
| enableBtn={false} | |||
| enableBtn={true} | |||
| backBtn={true} | |||
| isCheckout={true} | |||
| submitHandler={submitHandler} | |||
| @@ -1,75 +1,78 @@ | |||
| import { Box, Button, Paper, TextField } from '@mui/material'; | |||
| import { useFormik } from 'formik'; | |||
| import React, { useState } from 'react'; | |||
| import React, { useState, FC } from 'react'; | |||
| import { contactSchema } from '../../../schemas/contactSchema'; | |||
| import { useCheckoutData } from '../../../store/checkout-context'; | |||
| import ErrorMessageComponent from '../../mui/ErrorMessageComponent'; | |||
| const ContactForm = ({ submitHandler }) => { | |||
| const [error] = useState({ hasError: false, errorMessage: '' }); | |||
| const { checkoutStorage } = useCheckoutData(); | |||
| interface Props { | |||
| submitHandler: (x: string) => void; | |||
| } | |||
| const ContactForm: FC<Props> = ({ submitHandler }) => { | |||
| const [error] = useState({ hasError: false, errorMessage: '' }); | |||
| const { checkoutStorage } = useCheckoutData(); | |||
| const handleSubmit = async (values) => { | |||
| submitHandler(values.email); | |||
| }; | |||
| const handleSubmit = async (values: { email: string }) => { | |||
| submitHandler(values.email); | |||
| }; | |||
| const formik = useFormik({ | |||
| initialValues: { | |||
| email: checkoutStorage ? checkoutStorage.userInfo.email : '', | |||
| }, | |||
| validationSchema: contactSchema, | |||
| onSubmit: handleSubmit, | |||
| validateOnBlur: true, | |||
| enableReinitialize: true, | |||
| }); | |||
| const formik = useFormik({ | |||
| initialValues: { | |||
| email: checkoutStorage ? checkoutStorage.userInfo.email : '', | |||
| }, | |||
| validationSchema: contactSchema, | |||
| onSubmit: handleSubmit, | |||
| validateOnBlur: true, | |||
| enableReinitialize: true, | |||
| }); | |||
| return ( | |||
| <Paper | |||
| sx={{ p: 3, width: '90%', ml: 12, mt: 2, backgroundColor: '#f2f2f2' }} | |||
| elevation={3} | |||
| return ( | |||
| <Paper | |||
| sx={{ p: 3, width: '90%', ml: 12, mt: 2, backgroundColor: '#f2f2f2' }} | |||
| elevation={3} | |||
| > | |||
| <Box | |||
| sx={{ | |||
| width: '100%', | |||
| display: 'flex', | |||
| flexDirection: 'column', | |||
| }} | |||
| > | |||
| {error.hasError && <ErrorMessageComponent error={error.errorMessage} />} | |||
| <Box | |||
| component="form" | |||
| onSubmit={formik.handleSubmit} | |||
| sx={{ position: 'relative', mt: 1, p: 1 }} | |||
| > | |||
| <Box | |||
| sx={{ | |||
| width: '100%', | |||
| display: 'flex', | |||
| flexDirection: 'column', | |||
| }} | |||
| > | |||
| {error.hasError && <ErrorMessageComponent error={error.errorMessage} />} | |||
| <Box | |||
| component="form" | |||
| onSubmit={formik.handleSubmit} | |||
| sx={{ position: 'relative', mt: 1, p: 1 }} | |||
| > | |||
| <TextField | |||
| name="email" | |||
| label="Email" | |||
| margin="normal" | |||
| value={formik.values.email} | |||
| onChange={formik.handleChange} | |||
| error={formik.touched.email && Boolean(formik.errors.email)} | |||
| helperText={formik.touched.email && formik.errors.email} | |||
| fullWidth | |||
| /> | |||
| <Button | |||
| type="submit" | |||
| variant="contained" | |||
| sx={{ | |||
| mt: 3, | |||
| mb: 2, | |||
| backgroundColor: '#CBA213', | |||
| height: 50, | |||
| width: 150, | |||
| textTransform: 'none', | |||
| color: 'white', | |||
| }} | |||
| > | |||
| Submit Details | |||
| </Button> | |||
| </Box> | |||
| </Box> | |||
| </Paper> | |||
| ); | |||
| <TextField | |||
| name="email" | |||
| label="Email" | |||
| margin="normal" | |||
| value={formik.values.email} | |||
| onChange={formik.handleChange} | |||
| error={formik.touched.email && Boolean(formik.errors.email)} | |||
| helperText={formik.touched.email && formik.errors.email} | |||
| fullWidth | |||
| /> | |||
| <Button | |||
| type="submit" | |||
| variant="contained" | |||
| sx={{ | |||
| mt: 3, | |||
| mb: 2, | |||
| backgroundColor: '#CBA213', | |||
| height: 50, | |||
| width: 150, | |||
| textTransform: 'none', | |||
| color: 'white', | |||
| }} | |||
| > | |||
| Submit Details | |||
| </Button> | |||
| </Box> | |||
| </Box> | |||
| </Paper> | |||
| ); | |||
| }; | |||
| export default ContactForm; | |||
| @@ -1,135 +1,135 @@ | |||
| import { | |||
| Box, | |||
| Button, | |||
| Container, | |||
| Grid, | |||
| TextField, | |||
| Typography, | |||
| } from '@mui/material'; | |||
| import { useFormik } from 'formik'; | |||
| import { useTranslation } from 'next-i18next'; | |||
| import Link from 'next/link'; | |||
| import React, { useState } from 'react'; | |||
| import { BASE_PAGE } from '../../../constants/pages'; | |||
| import { postQuestion } from '../../../requests/question/postQuestionRequest'; | |||
| import { contactPageSchema } from '../../../schemas/contactSchema'; | |||
| import Notification from '../../notification/Notification'; | |||
| const ContactPageForm = () => { | |||
| const { t } = useTranslation('contact'); | |||
| const [open, setOpen] = useState(false); | |||
| const handleSubmit = async (values) => { | |||
| try { | |||
| postQuestion(values); | |||
| setOpen(true); | |||
| } catch (error) { | |||
| console.log(error); | |||
| } | |||
| }; | |||
| const handleCloseNotification = () => { | |||
| setOpen(false); | |||
| }; | |||
| const formik = useFormik({ | |||
| initialValues: { | |||
| firstName: '', | |||
| lastName: '', | |||
| email: '', | |||
| message: '', | |||
| }, | |||
| validationSchema: contactPageSchema, | |||
| onSubmit: handleSubmit, | |||
| validateOnBlur: true, | |||
| enableReinitialize: true, | |||
| }); | |||
| return ( | |||
| <Container component="main" maxWidth="md" sx={{ mb: '60px' }}> | |||
| <Notification | |||
| open={open} | |||
| notification={t('contact:notification')} | |||
| handleCloseNotification={handleCloseNotification} | |||
| /> | |||
| Box, | |||
| Button, | |||
| Container, | |||
| Grid, | |||
| TextField, | |||
| Typography, | |||
| } from '@mui/material'; | |||
| import { useFormik } from 'formik'; | |||
| import { useTranslation } from 'next-i18next'; | |||
| import Link from 'next/link'; | |||
| import React, { useState } from 'react'; | |||
| import { BASE_PAGE } from '../../../constants/pages'; | |||
| import { postQuestion } from '../../../requests/question/postQuestionRequest'; | |||
| import { contactPageSchema } from '../../../schemas/contactSchema'; | |||
| import { QuestionData } from '../../../utils/interface/questionInterface'; | |||
| import Notification from '../../notification/Notification'; | |||
| const ContactPageForm = () => { | |||
| const { t } = useTranslation('contact'); | |||
| const [open, setOpen] = useState(false); | |||
| const handleSubmit = async (values: QuestionData) => { | |||
| try { | |||
| postQuestion(values); | |||
| setOpen(true); | |||
| } catch (error) { | |||
| console.log(error); | |||
| } | |||
| }; | |||
| const handleCloseNotification = () => { | |||
| setOpen(false); | |||
| }; | |||
| const formik = useFormik({ | |||
| initialValues: { | |||
| firstName: '', | |||
| lastName: '', | |||
| email: '', | |||
| message: '', | |||
| }, | |||
| validationSchema: contactPageSchema, | |||
| onSubmit: handleSubmit, | |||
| validateOnBlur: true, | |||
| enableReinitialize: true, | |||
| }); | |||
| return ( | |||
| <Container component="main" maxWidth="md" sx={{ mb: '60px' }}> | |||
| <Notification | |||
| open={open} | |||
| notification={t('contact:notification')} | |||
| handleCloseNotification={handleCloseNotification} | |||
| /> | |||
| <Box | |||
| sx={{ | |||
| marginTop: 32, | |||
| display: 'flex', | |||
| flexDirection: 'column', | |||
| alignItems: 'center', | |||
| }} | |||
| > | |||
| <Typography fontSize={48}>{t('contact:title')}</Typography> | |||
| <Box | |||
| sx={{ | |||
| marginTop: 32, | |||
| display: 'flex', | |||
| flexDirection: 'column', | |||
| alignItems: 'center', | |||
| }} | |||
| component="form" | |||
| onSubmit={formik.handleSubmit} | |||
| sx={{ position: 'relative', mt: 1, p: 1 }} | |||
| > | |||
| <Typography fontSize={48}>{t('contact:title')}</Typography> | |||
| <Box | |||
| component="form" | |||
| onSubmit={formik.handleSubmit} | |||
| sx={{ position: 'relative', mt: 1, p: 1 }} | |||
| <TextField | |||
| name="firstName" | |||
| label={t('contact:firstName')} | |||
| margin="normal" | |||
| value={formik.values.firstName} | |||
| onChange={formik.handleChange} | |||
| error={formik.touched.firstName && Boolean(formik.errors.firstName)} | |||
| helperText={formik.touched.firstName && formik.errors.firstName} | |||
| autoFocus | |||
| fullWidth | |||
| /> | |||
| <TextField | |||
| name="lastName" | |||
| label={t('contact:lastName')} | |||
| margin="normal" | |||
| value={formik.values.lastName} | |||
| onChange={formik.handleChange} | |||
| error={formik.touched.lastName && Boolean(formik.errors.lastName)} | |||
| helperText={formik.touched.lastName && formik.errors.lastName} | |||
| autoFocus | |||
| fullWidth | |||
| /> | |||
| <TextField | |||
| name="email" | |||
| label={t('contact:email')} | |||
| margin="normal" | |||
| value={formik.values.email} | |||
| onChange={formik.handleChange} | |||
| error={formik.touched.email && Boolean(formik.errors.email)} | |||
| helperText={formik.touched.email && formik.errors.email} | |||
| autoFocus | |||
| fullWidth | |||
| /> | |||
| <TextField | |||
| name="message" | |||
| label={t('contact:message')} | |||
| multiline | |||
| margin="normal" | |||
| value={formik.values.message} | |||
| onChange={formik.handleChange} | |||
| error={formik.touched.message && Boolean(formik.errors.message)} | |||
| helperText={formik.touched.message && formik.errors.message} | |||
| rows={4} | |||
| autoFocus | |||
| fullWidth | |||
| /> | |||
| <Button | |||
| type="submit" | |||
| variant="contained" | |||
| sx={{ mt: 3, mb: 2 }} | |||
| fullWidth | |||
| > | |||
| <TextField | |||
| name="firstName" | |||
| label={t('contact:firstName')} | |||
| margin="normal" | |||
| value={formik.values.firstName} | |||
| onChange={formik.handleChange} | |||
| error={formik.touched.firstName && Boolean(formik.errors.firstName)} | |||
| helperText={formik.touched.firstName && formik.errors.firstName} | |||
| autoFocus | |||
| fullWidth | |||
| /> | |||
| <TextField | |||
| name="lastName" | |||
| label={t('contact:lastName')} | |||
| margin="normal" | |||
| value={formik.values.lastName} | |||
| onChange={formik.handleChange} | |||
| error={formik.touched.lastName && Boolean(formik.errors.lastName)} | |||
| helperText={formik.touched.lastName && formik.errors.lastName} | |||
| autoFocus | |||
| fullWidth | |||
| /> | |||
| <TextField | |||
| name="email" | |||
| label={t('contact:email')} | |||
| margin="normal" | |||
| value={formik.values.email} | |||
| onChange={formik.handleChange} | |||
| error={formik.touched.email && Boolean(formik.errors.email)} | |||
| helperText={formik.touched.email && formik.errors.email} | |||
| autoFocus | |||
| fullWidth | |||
| /> | |||
| <TextField | |||
| name="message" | |||
| label={t('contact:message')} | |||
| multiline | |||
| margin="normal" | |||
| value={formik.values.message} | |||
| onChange={formik.handleChange} | |||
| error={formik.touched.message && Boolean(formik.errors.message)} | |||
| helperText={formik.touched.message && formik.errors.message} | |||
| rows={4} | |||
| autoFocus | |||
| fullWidth | |||
| /> | |||
| <Button | |||
| type="submit" | |||
| variant="contained" | |||
| sx={{ mt: 3, mb: 2 }} | |||
| fullWidth | |||
| > | |||
| {t('contact:sendBtn')} | |||
| </Button> | |||
| <Grid container justifyContent="center"> | |||
| <Link href={BASE_PAGE}> | |||
| <Typography>{t('contact:back')}</Typography> | |||
| </Link> | |||
| </Grid> | |||
| </Box> | |||
| {t('contact:sendBtn')} | |||
| </Button> | |||
| <Grid container justifyContent="center"> | |||
| <Link href={BASE_PAGE}> | |||
| <Typography>{t('contact:back')}</Typography> | |||
| </Link> | |||
| </Grid> | |||
| </Box> | |||
| </Container> | |||
| ); | |||
| }; | |||
| export default ContactPageForm; | |||
| </Box> | |||
| </Container> | |||
| ); | |||
| }; | |||
| export default ContactPageForm; | |||
| @@ -5,9 +5,10 @@ import { useRouter } from 'next/router'; | |||
| import { useState, FC } from 'react'; | |||
| import { registerSchema } from '../../../schemas/shippingDetailsSchema'; | |||
| import { useUserData } from '../../../store/user-context'; | |||
| import { ShippingData } from '../../../utils/interface/orderInterface'; | |||
| import ErrorMessageComponent from '../../mui/ErrorMessageComponent'; | |||
| interface FormValues { | |||
| export interface FormValues { | |||
| fullName: string; | |||
| address: string; | |||
| address2: string; | |||
| @@ -17,7 +18,7 @@ interface FormValues { | |||
| } | |||
| interface Props { | |||
| submitHandler: (x: FormValues) => void; | |||
| submitHandler: (x: FormValues | ShippingData) => void; | |||
| backBtn: boolean; | |||
| isCheckout: boolean; | |||
| enableBtn: boolean; | |||
| @@ -34,7 +35,7 @@ const ShippingDetailsForm: FC<Props> = ({ | |||
| const { userStorage } = useUserData(); | |||
| const router = useRouter(); | |||
| const formikSubmitHandler = async (values: FormValues) => { | |||
| const formikSubmitHandler = async (values: FormValues | ShippingData) => { | |||
| submitHandler(values); | |||
| }; | |||
| @@ -2,9 +2,10 @@ import { Typography } from '@mui/material'; | |||
| import { Box } from '@mui/system'; | |||
| import { useSession } from 'next-auth/react'; | |||
| import { useTranslation } from 'next-i18next'; | |||
| import { useState } from 'react'; | |||
| import { useState, FC } from 'react'; | |||
| import { updateUser } from '../../requests/user/userUpdateRequest'; | |||
| import { useUserUpdate } from '../../store/user-context'; | |||
| import { OrderDataDB } from '../../utils/interface/orderInterface'; | |||
| import CardContainer from '../cards/card-container/CardContainer'; | |||
| import OrderCard from '../cards/order-card/OrderCard'; | |||
| import ShippingDetailsForm from '../forms/shipping-details/ShippingDetailsForm'; | |||
| @@ -13,76 +14,93 @@ import PageWrapper from '../layout/page-wrapper/PageWrapper'; | |||
| import StepTitle from '../layout/steps-title/StepTitle'; | |||
| import Notification from '../notification/Notification'; | |||
| const ProfileContent = ({ orders }) => { | |||
| const { t } = useTranslation('profile'); | |||
| const { data: session } = useSession(); | |||
| const { updateUserInfo } = useUserUpdate(); | |||
| const [enableBtn, setEnableBtn] = useState(true); | |||
| const [open, setOpen] = useState(false); | |||
| interface Props { | |||
| orders: Array<OrderDataDB>; | |||
| } | |||
| const updateUserHandler = async (values) => { | |||
| try { | |||
| setEnableBtn(false); | |||
| updateUserInfo(values); | |||
| await updateUser(values, session.user._id); | |||
| setOpen(true); | |||
| setTimeout(() => { | |||
| setEnableBtn(true); | |||
| }, 5000); | |||
| } catch (error) { | |||
| console.log(error); | |||
| setTimeout(() => { | |||
| setEnableBtn(true); | |||
| }, 3000); | |||
| } | |||
| }; | |||
| interface FormValues { | |||
| fullName: string; | |||
| address: string; | |||
| address2: string; | |||
| city: string; | |||
| country: string; | |||
| postcode: string; | |||
| } | |||
| const handleCloseNotification = () => { | |||
| setOpen(false); | |||
| }; | |||
| const ProfileContent: FC<Props> = ({ orders }) => { | |||
| const { t } = useTranslation('profile'); | |||
| const { data: session } = useSession(); | |||
| const { updateUserInfo } = useUserUpdate(); | |||
| const [enableBtn, setEnableBtn] = useState(true); | |||
| const [open, setOpen] = useState(false); | |||
| const mapOrdersToDom = () => | |||
| orders.slice(-4).map((order, i) => ( | |||
| <OrderCard | |||
| key={i} | |||
| data={{ | |||
| date: order.time.split('T')[0], | |||
| name: order.shippingAddress.fullName, | |||
| totalPrice: order.totalPrice, | |||
| }} | |||
| ></OrderCard> | |||
| )); | |||
| const updateUserHandler = async (values: FormValues) => { | |||
| if (session?.user) { | |||
| try { | |||
| setEnableBtn(false); | |||
| updateUserInfo(values); | |||
| await updateUser(values, session.user._id); | |||
| setOpen(true); | |||
| setTimeout(() => { | |||
| setEnableBtn(true); | |||
| }, 5000); | |||
| } catch (error) { | |||
| console.log(error); | |||
| setTimeout(() => { | |||
| setEnableBtn(true); | |||
| }, 3000); | |||
| } | |||
| } | |||
| }; | |||
| return ( | |||
| <PageWrapper> | |||
| <StepTitle title={t('profile:title')} /> | |||
| <Notification | |||
| open={open} | |||
| handleCloseNotification={handleCloseNotification} | |||
| notification={t('profile:notification')} | |||
| /> | |||
| const handleCloseNotification = () => { | |||
| setOpen(false); | |||
| }; | |||
| <ContentContainer> | |||
| <Box flexGrow={1} sx={{ minWidth: '65%' }}> | |||
| <Typography sx={{ fontSize: 20, mb: 3 }}> | |||
| {t('profile:subtitle1')} | |||
| </Typography> | |||
| <ShippingDetailsForm | |||
| submitHandler={updateUserHandler} | |||
| enableBtn={enableBtn} | |||
| ></ShippingDetailsForm> | |||
| </Box> | |||
| <Box sx={{ mt: { xs: 5, md: 0 } }}> | |||
| <Typography | |||
| sx={{ fontSize: 20, mb: { xs: -2, md: 3 }, ml: { md: 3 } }} | |||
| > | |||
| {t('profile:subtitle2')} | |||
| </Typography> | |||
| <CardContainer>{mapOrdersToDom()}</CardContainer> | |||
| </Box> | |||
| </ContentContainer> | |||
| </PageWrapper> | |||
| ); | |||
| const mapOrdersToDom = () => | |||
| orders.slice(-4).map((order, i) => ( | |||
| <OrderCard | |||
| key={i} | |||
| data={{ | |||
| date: order.time.toLocaleString().split('T')[0], | |||
| name: order.shippingAddress.fullName, | |||
| totalPrice: order.totalPrice, | |||
| }} | |||
| ></OrderCard> | |||
| )); | |||
| return ( | |||
| <PageWrapper> | |||
| <StepTitle title={t('profile:title')} breadcrumbsArray={[]} /> | |||
| <Notification | |||
| open={open} | |||
| handleCloseNotification={handleCloseNotification} | |||
| notification={t('profile:notification')} | |||
| /> | |||
| <ContentContainer> | |||
| <Box flexGrow={1} sx={{ minWidth: '65%' }}> | |||
| <Typography sx={{ fontSize: 20, mb: 3 }}> | |||
| {t('profile:subtitle1')} | |||
| </Typography> | |||
| <ShippingDetailsForm | |||
| submitHandler={updateUserHandler} | |||
| enableBtn={enableBtn} | |||
| backBtn={false} | |||
| isCheckout={false} | |||
| ></ShippingDetailsForm> | |||
| </Box> | |||
| <Box sx={{ mt: { xs: 5, md: 0 } }}> | |||
| <Typography | |||
| sx={{ fontSize: 20, mb: { xs: -2, md: 3 }, ml: { md: 3 } }} | |||
| > | |||
| {t('profile:subtitle2')} | |||
| </Typography> | |||
| <CardContainer>{mapOrdersToDom()}</CardContainer> | |||
| </Box> | |||
| </ContentContainer> | |||
| </PageWrapper> | |||
| ); | |||
| }; | |||
| export default ProfileContent; | |||
| @@ -11,6 +11,7 @@ import { | |||
| useCheckoutData, | |||
| useCheckoutDataUpdate, | |||
| } from '../../store/checkout-context'; | |||
| import { OrderData } from '../../utils/interface/orderInterface'; | |||
| import PageWrapper from '../layout/page-wrapper/PageWrapper'; | |||
| import StepTitle from '../layout/steps-title/StepTitle'; | |||
| @@ -21,7 +22,7 @@ const ReviewContent = () => { | |||
| const { checkoutStorage } = useCheckoutData(); | |||
| const { parseCheckoutValue, clearCheckout } = useCheckoutDataUpdate(); | |||
| const { clearCart } = useStoreUpdate(); | |||
| const [orderData, setOrderData] = useState({}); | |||
| const [orderData, setOrderData] = useState<OrderData>({} as OrderData); | |||
| const router = useRouter(); | |||
| @@ -104,7 +105,7 @@ const ReviewContent = () => { | |||
| > | |||
| <Typography sx={{ fontSize: 18, fontWeight: 600 }}> | |||
| {t('review:date')} | |||
| {orderData.time} | |||
| {orderData?.time?.toLocaleDateString()} | |||
| </Typography> | |||
| </Box> | |||
| <Box | |||
| @@ -5,12 +5,15 @@ import { useRouter } from 'next/router'; | |||
| import { setCookie } from 'nookies'; | |||
| import { useEffect, useState } from 'react'; | |||
| import { | |||
| CheckoutData, | |||
| useCheckoutData, | |||
| useCheckoutDataUpdate, | |||
| } from '../../store/checkout-context'; | |||
| import { stripe } from '../../utils/helpers/stripe'; | |||
| import { ShippingData as IShippingData } from '../../utils/interface/orderInterface'; | |||
| import CardContainer from '../cards/card-container/CardContainer'; | |||
| import DataCard from '../cards/data-card/DataCard'; | |||
| import { FormValues } from '../forms/shipping-details/ShippingDetailsForm'; | |||
| import ContentContainer from '../layout/content-wrapper/ContentContainer'; | |||
| import PageWrapper from '../layout/page-wrapper/PageWrapper'; | |||
| import StepTitle from '../layout/steps-title/StepTitle'; | |||
| @@ -24,7 +27,9 @@ const ShippingContent = () => { | |||
| const { checkoutStorage } = useCheckoutData(); | |||
| const { changeContact, changeShippingData } = useCheckoutDataUpdate(); | |||
| const [open, setOpen] = useState({ isOpen: false, type: '' }); | |||
| const [checkoutData, setCheckoutData] = useState({}); | |||
| const [checkoutData, setCheckoutData] = useState<CheckoutData>( | |||
| {} as CheckoutData | |||
| ); | |||
| const router = useRouter(); | |||
| @@ -32,15 +37,15 @@ const ShippingContent = () => { | |||
| setCheckoutData(checkoutStorage); | |||
| }, [checkoutStorage]); | |||
| const handleOpen = (type) => setOpen({ isOpen: true, type }); | |||
| const handleOpen = (type: string) => setOpen({ isOpen: true, type }); | |||
| const handleClose = () => setOpen({ isOpen: false, type: '' }); | |||
| const handleChangeShipping = (values) => { | |||
| changeShippingData(values); | |||
| const handleChangeShipping = (values: IShippingData | FormValues) => { | |||
| changeShippingData(values as IShippingData); | |||
| handleClose(); | |||
| }; | |||
| const handleChangeContact = (values) => { | |||
| const handleChangeContact = (values: string) => { | |||
| changeContact(values); | |||
| handleClose(); | |||
| }; | |||
| @@ -51,7 +56,6 @@ const ShippingContent = () => { | |||
| price: el.product.stripeID, | |||
| quantity: el.quantity, | |||
| })), | |||
| userInfo: checkoutData.userInfo, | |||
| }); | |||
| setCookie(null, 'review-session', 'active', { | |||
| maxAge: 3600, | |||
| @@ -1,50 +1,56 @@ | |||
| import { Box, Button } from '@mui/material'; | |||
| import { useTranslation } from 'next-i18next'; | |||
| import { FC } from 'react'; | |||
| const ButtonGroup = ({ handleBackToCart, handleStripePayment }) => { | |||
| const { t } = useTranslation('shipping'); | |||
| return ( | |||
| <Box | |||
| sx={{ | |||
| display: 'flex', | |||
| mb: 2, | |||
| borderRadius: 2, | |||
| }} | |||
| > | |||
| <Button | |||
| variant="contained" | |||
| sx={{ | |||
| mt: 3, | |||
| mb: 2, | |||
| height: 50, | |||
| width: 150, | |||
| textTransform: 'none', | |||
| backgroundColor: 'primary.main', | |||
| color: 'white', | |||
| mr: 2, | |||
| }} | |||
| onClick={handleBackToCart} | |||
| > | |||
| {t('shipping:back')} | |||
| </Button> | |||
| <Button | |||
| type="submit" | |||
| variant="contained" | |||
| sx={{ | |||
| mt: 3, | |||
| mb: 2, | |||
| backgroundColor: '#CBA213', | |||
| height: 50, | |||
| width: 200, | |||
| textTransform: 'none', | |||
| color: 'white', | |||
| }} | |||
| onClick={handleStripePayment} | |||
| > | |||
| {t('shipping:continue')} | |||
| </Button> | |||
| </Box> | |||
| ); | |||
| interface Props { | |||
| handleBackToCart: () => void; | |||
| handleStripePayment: () => void; | |||
| } | |||
| const ButtonGroup: FC<Props> = ({ handleBackToCart, handleStripePayment }) => { | |||
| const { t } = useTranslation('shipping'); | |||
| return ( | |||
| <Box | |||
| sx={{ | |||
| display: 'flex', | |||
| mb: 2, | |||
| borderRadius: 2, | |||
| }} | |||
| > | |||
| <Button | |||
| variant="contained" | |||
| sx={{ | |||
| mt: 3, | |||
| mb: 2, | |||
| height: 50, | |||
| width: 150, | |||
| textTransform: 'none', | |||
| backgroundColor: 'primary.main', | |||
| color: 'white', | |||
| mr: 2, | |||
| }} | |||
| onClick={handleBackToCart} | |||
| > | |||
| {t('shipping:back')} | |||
| </Button> | |||
| <Button | |||
| type="submit" | |||
| variant="contained" | |||
| sx={{ | |||
| mt: 3, | |||
| mb: 2, | |||
| backgroundColor: '#CBA213', | |||
| height: 50, | |||
| width: 200, | |||
| textTransform: 'none', | |||
| color: 'white', | |||
| }} | |||
| onClick={handleStripePayment} | |||
| > | |||
| {t('shipping:continue')} | |||
| </Button> | |||
| </Box> | |||
| ); | |||
| }; | |||
| export default ButtonGroup; | |||
| @@ -1,84 +1,99 @@ | |||
| import { Button, Typography } from '@mui/material'; | |||
| import { Box } from '@mui/system'; | |||
| import { useTranslation } from 'next-i18next'; | |||
| import { FC } from 'react'; | |||
| const ShippingData = ({ email, address, city, postcode, handleOpen }) => { | |||
| const { t } = useTranslation('shipping'); | |||
| interface Props { | |||
| email: string; | |||
| address: string; | |||
| city: string; | |||
| postcode: string; | |||
| handleOpen: (x: string) => void; | |||
| } | |||
| return ( | |||
| <> | |||
| <Box | |||
| sx={{ | |||
| display: 'flex', | |||
| justifyContent: 'space-between', | |||
| backgroundColor: '#f2f2f2', | |||
| alignItems: 'center', | |||
| mb: 2, | |||
| borderRadius: 2, | |||
| p: 1, | |||
| }} | |||
| > | |||
| <Typography sx={{ fontSize: 18, fontWeight: 600 }}> | |||
| {t('shipping:contact')} | |||
| </Typography> | |||
| <Typography>{email}</Typography> | |||
| <Button | |||
| sx={{ | |||
| height: 35, | |||
| minWidth: { md: 125, xs: 90 }, | |||
| fontSize: 15, | |||
| textTransform: 'none', | |||
| backgroundColor: '#CBA213', | |||
| color: 'white', | |||
| }} | |||
| onClick={() => { | |||
| handleOpen('Contact'); | |||
| }} | |||
| > | |||
| {t('shipping:changeBtn')} | |||
| </Button> | |||
| </Box> | |||
| <Box | |||
| sx={{ | |||
| display: 'flex', | |||
| justifyContent: 'space-between', | |||
| backgroundColor: '#f2f2f2', | |||
| alignItems: 'center', | |||
| mb: 2, | |||
| borderRadius: 2, | |||
| p: 1, | |||
| }} | |||
| > | |||
| <Typography | |||
| sx={{ | |||
| fontSize: { md: 18, xs: 16 }, | |||
| fontWeight: 600, | |||
| mr: { xs: 1, sm: 0 }, | |||
| }} | |||
| > | |||
| {t('shipping:shipping')} | |||
| </Typography> | |||
| <Typography> | |||
| {address} | {city} | {postcode} | |||
| </Typography> | |||
| <Button | |||
| sx={{ | |||
| height: 35, | |||
| minWidth: { md: 125, xs: 90 }, | |||
| fontSize: 15, | |||
| textTransform: 'none', | |||
| backgroundColor: '#CBA213', | |||
| color: 'white', | |||
| }} | |||
| onClick={() => { | |||
| handleOpen('Shipping'); | |||
| }} | |||
| > | |||
| {t('shipping:changeBtn')} | |||
| </Button> | |||
| </Box> | |||
| </> | |||
| ); | |||
| const ShippingData: FC<Props> = ({ | |||
| email, | |||
| address, | |||
| city, | |||
| postcode, | |||
| handleOpen, | |||
| }) => { | |||
| const { t } = useTranslation('shipping'); | |||
| return ( | |||
| <> | |||
| <Box | |||
| sx={{ | |||
| display: 'flex', | |||
| justifyContent: 'space-between', | |||
| backgroundColor: '#f2f2f2', | |||
| alignItems: 'center', | |||
| mb: 2, | |||
| borderRadius: 2, | |||
| p: 1, | |||
| }} | |||
| > | |||
| <Typography sx={{ fontSize: 18, fontWeight: 600 }}> | |||
| {t('shipping:contact')} | |||
| </Typography> | |||
| <Typography>{email}</Typography> | |||
| <Button | |||
| sx={{ | |||
| height: 35, | |||
| minWidth: { md: 125, xs: 90 }, | |||
| fontSize: 15, | |||
| textTransform: 'none', | |||
| backgroundColor: '#CBA213', | |||
| color: 'white', | |||
| }} | |||
| onClick={() => { | |||
| handleOpen('Contact'); | |||
| }} | |||
| > | |||
| {t('shipping:changeBtn')} | |||
| </Button> | |||
| </Box> | |||
| <Box | |||
| sx={{ | |||
| display: 'flex', | |||
| justifyContent: 'space-between', | |||
| backgroundColor: '#f2f2f2', | |||
| alignItems: 'center', | |||
| mb: 2, | |||
| borderRadius: 2, | |||
| p: 1, | |||
| }} | |||
| > | |||
| <Typography | |||
| sx={{ | |||
| fontSize: { md: 18, xs: 16 }, | |||
| fontWeight: 600, | |||
| mr: { xs: 1, sm: 0 }, | |||
| }} | |||
| > | |||
| {t('shipping:shipping')} | |||
| </Typography> | |||
| <Typography> | |||
| {address} | {city} | {postcode} | |||
| </Typography> | |||
| <Button | |||
| sx={{ | |||
| height: 35, | |||
| minWidth: { md: 125, xs: 90 }, | |||
| fontSize: 15, | |||
| textTransform: 'none', | |||
| backgroundColor: '#CBA213', | |||
| color: 'white', | |||
| }} | |||
| onClick={() => { | |||
| handleOpen('Shipping'); | |||
| }} | |||
| > | |||
| {t('shipping:changeBtn')} | |||
| </Button> | |||
| </Box> | |||
| </> | |||
| ); | |||
| }; | |||
| export default ShippingData; | |||
| @@ -1,9 +1,20 @@ | |||
| import { Modal } from '@mui/material'; | |||
| import { Box } from '@mui/system'; | |||
| import ContactForm from '../../forms/contact/ContactForm'; | |||
| import ShippingDetailsForm from '../../forms/shipping-details/ShippingDetailsForm'; | |||
| import ShippingDetailsForm, { | |||
| FormValues, | |||
| } from '../../forms/shipping-details/ShippingDetailsForm'; | |||
| import { FC } from 'react'; | |||
| import { ShippingData } from '../../../utils/interface/orderInterface'; | |||
| const ShippingModal = ({ | |||
| interface Props { | |||
| open: { isOpen: boolean; type: string }; | |||
| handleClose: () => void; | |||
| handleChangeShipping: (x: ShippingData | FormValues) => void; | |||
| handleChangeContact: (values: string) => void; | |||
| } | |||
| const ShippingModal: FC<Props> = ({ | |||
| open, | |||
| handleClose, | |||
| handleChangeShipping, | |||
| @@ -26,7 +37,12 @@ const ShippingModal = ({ | |||
| }} | |||
| > | |||
| {open.type === 'Shipping' && ( | |||
| <ShippingDetailsForm submitHandler={handleChangeShipping} /> | |||
| <ShippingDetailsForm | |||
| submitHandler={handleChangeShipping} | |||
| backBtn={false} | |||
| isCheckout={false} | |||
| enableBtn={true} | |||
| /> | |||
| )} | |||
| {open.type === 'Contact' && ( | |||
| <ContactForm submitHandler={handleChangeContact} /> | |||
| @@ -1,4 +1,4 @@ | |||
| import type { NextPage } from 'next'; | |||
| import type { NextPage, GetStaticProps } from 'next'; | |||
| import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; | |||
| import ContactPageForm from '../../components/forms/contact/ContactPageForm'; | |||
| @@ -7,12 +7,12 @@ const Contact: NextPage = () => { | |||
| return <ContactPageForm />; | |||
| }; | |||
| export const getStaticProps = async ({ locale }: any) => { | |||
| export const getStaticProps: GetStaticProps = async ({ locale }: any) => { | |||
| return { | |||
| props: { | |||
| ...(await serverSideTranslations(locale, ['contact'])), | |||
| }, | |||
| }; | |||
| } | |||
| }; | |||
| export default Contact; | |||
| @@ -1,15 +1,16 @@ | |||
| import { NextPage } from 'next'; | |||
| import { NextPage, GetServerSideProps } from 'next'; | |||
| import { getSession } from 'next-auth/react'; | |||
| import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; | |||
| import ProfileContent from '../../components/profile-content/ProfileContent'; | |||
| import { LOGIN_PAGE } from '../../constants/pages'; | |||
| import { getOrdersForOwner } from '../../requests/orders/getOrdersForOwnerRequest'; | |||
| import { OrderResponseGet } from '../../utils/interface/orderInterface'; | |||
| const ProfilePage: NextPage = (props) => { | |||
| const ProfilePage: NextPage = (props: any) => { | |||
| return <ProfileContent orders={props.orders.orders}></ProfileContent>; | |||
| }; | |||
| export async function getServerSideProps(context: any) { | |||
| export const getServerSideProps: GetServerSideProps = async (context: any) => { | |||
| const session = await getSession({ req: context.req }); | |||
| if (!session) { | |||
| @@ -32,6 +33,6 @@ export async function getServerSideProps(context: any) { | |||
| orders, | |||
| }, | |||
| }; | |||
| } | |||
| }; | |||
| export default ProfilePage; | |||
| @@ -1,29 +1,29 @@ | |||
| import { NextPage } from 'next'; | |||
| import { NextPage, GetServerSideProps } from 'next'; | |||
| import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; | |||
| import nookies from 'nookies'; | |||
| import ReviewContent from '../../components/review-content/ReviewContent'; | |||
| const ReviewPage: NextPage = () => { | |||
| return <ReviewContent></ReviewContent>; | |||
| return <ReviewContent></ReviewContent>; | |||
| }; | |||
| export const getServerSideProps = async (ctx: any) => { | |||
| const cookies = nookies.get(ctx); | |||
| if (!cookies['review-session']) { | |||
| return { | |||
| redirect: { | |||
| destination: '/cart', | |||
| permanent: false, | |||
| }, | |||
| }; | |||
| } | |||
| export const getServerSideProps: GetServerSideProps = async (ctx: any) => { | |||
| const cookies = nookies.get(ctx); | |||
| if (!cookies['review-session']) { | |||
| return { | |||
| props: { | |||
| ...(await serverSideTranslations(ctx.locale, ['review'])), | |||
| }, | |||
| redirect: { | |||
| destination: '/cart', | |||
| permanent: false, | |||
| }, | |||
| }; | |||
| } | |||
| return { | |||
| props: { | |||
| ...(await serverSideTranslations(ctx.locale, ['review'])), | |||
| }, | |||
| }; | |||
| }; | |||
| export default ReviewPage; | |||
| @@ -1,31 +1,31 @@ | |||
| import { NextPage } from 'next'; | |||
| import { NextPage, GetServerSideProps } from 'next'; | |||
| import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; | |||
| import nookies from 'nookies'; | |||
| import ShippingContent from '../../components/shipping-content/ShippingContent'; | |||
| const ShippingPage: NextPage = () => { | |||
| return <ShippingContent></ShippingContent>; | |||
| return <ShippingContent></ShippingContent>; | |||
| }; | |||
| export const getServerSideProps = async (ctx: any) => { | |||
| const cookies = nookies.get(ctx); | |||
| if (!cookies['shipping-session']) { | |||
| return { | |||
| redirect: { | |||
| destination: '/cart', | |||
| permanent: false, | |||
| }, | |||
| }; | |||
| } | |||
| export const getServerSideProps: GetServerSideProps = async (ctx: any) => { | |||
| const cookies = nookies.get(ctx); | |||
| if (!cookies['shipping-session']) { | |||
| return { | |||
| props: { | |||
| ...(await serverSideTranslations(ctx.locale, [ | |||
| 'shipping', | |||
| 'addressForm', | |||
| ])), | |||
| }, | |||
| redirect: { | |||
| destination: '/cart', | |||
| permanent: false, | |||
| }, | |||
| }; | |||
| } | |||
| return { | |||
| props: { | |||
| ...(await serverSideTranslations(ctx.locale, [ | |||
| 'shipping', | |||
| 'addressForm', | |||
| ])), | |||
| }, | |||
| }; | |||
| }; | |||
| export default ShippingPage; | |||
| @@ -3,7 +3,7 @@ | |||
| "note": "Thank you for placing your order with us. We wll get to work on sending your order as soon as possible", | |||
| "title": "Order Summary", | |||
| "date": "Order placed on: ", | |||
| "email": "Email", | |||
| "email": "Email: ", | |||
| "total": "Total: $", | |||
| "shipping": "Shipping Address: ", | |||
| "back": "Back to Home" | |||
| @@ -1,8 +1,7 @@ | |||
| import { createContext, useContext, useState, FC, ReactNode } from 'react'; | |||
| import { getSStorage, setSStorage } from '../utils/helpers/storage'; | |||
| import { ShippingData } from '../utils/interface/orderInterface'; | |||
| import { OrderData, ShippingData } from '../utils/interface/orderInterface'; | |||
| import { ProductData } from '../utils/interface/productInterface'; | |||
| import { UserData } from '../utils/interface/userInterface'; | |||
| interface Props { | |||
| children: ReactNode; | |||
| @@ -13,23 +12,12 @@ interface Products { | |||
| quantity: number; | |||
| } | |||
| interface CheckoutData { | |||
| export interface CheckoutData { | |||
| products: Products[]; | |||
| userInfo: ShippingData; | |||
| userID: string; | |||
| } | |||
| interface OrderData { | |||
| products: Array<ProductData>; | |||
| time: string; | |||
| shippingAddress: ShippingData; | |||
| totalPrice: number; | |||
| numberOfItems: number; | |||
| fulfilled: boolean; | |||
| owner: string; | |||
| stripeCheckoutId: string; | |||
| } | |||
| interface ICheckout { | |||
| checkoutStorage: CheckoutData; | |||
| } | |||
| @@ -94,7 +82,7 @@ const useCheckout = () => { | |||
| const date = new Date(); | |||
| const dataToStore = { | |||
| products: items?.products?.map((el) => el.product), | |||
| time: date.toLocaleDateString(), | |||
| time: date, | |||
| shippingAddress: items?.userInfo, | |||
| totalPrice: items?.products | |||
| ?.map((entry) => entry?.product.price * entry?.quantity) | |||
| @@ -9,7 +9,11 @@ export const getStorage = (key: string) => { | |||
| const storedItems = window.localStorage.getItem(key); | |||
| return storedItems ? JSON.parse(storedItems) : []; | |||
| return storedItems | |||
| ? Object.keys(JSON.parse(storedItems)).length | |||
| ? JSON.parse(storedItems) | |||
| : [] | |||
| : []; | |||
| }; | |||
| export const removeStorage = (key: string) => { | |||
| @@ -13,7 +13,7 @@ export interface OrderData { | |||
| totalPrice: number; | |||
| numberOfItems: number; | |||
| fulfilled: boolean; | |||
| owner: ObjectId; | |||
| owner: ObjectId | string; | |||
| stripeCheckoutId: string; | |||
| } | |||