| import { Box } from '@mui/system'; | import { Box } from '@mui/system'; | ||||
| import { ReactNode } from 'react'; | |||||
| interface CardContainerProps { | interface CardContainerProps { | ||||
| children: JSX.Element; | |||||
| children: ReactNode; | |||||
| } | } | ||||
| const CardContainer: React.FC<CardContainerProps> = ({ children }) => { | 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; | export default CardContainer; |
| import { Box, Card, Typography } from '@mui/material'; | import { Box, Card, Typography } from '@mui/material'; | ||||
| import Image from 'next/image'; | import Image from 'next/image'; | ||||
| import { ProductDataDB } from '../../../utils/interface/productInterface'; | |||||
| import { ProductData } from '../../../utils/interface/productInterface'; | |||||
| interface DataCardProps { | interface DataCardProps { | ||||
| data: ProductDataDB; | |||||
| quantity: number; | |||||
| data: ProductData; | |||||
| quantity: number; | |||||
| } | } | ||||
| const DataCard: React.FC<DataCardProps> = ({ data, quantity }) => { | 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={{ | 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; | export default DataCard; |
| import { Card, Divider, Typography } from '@mui/material'; | import { Card, Divider, Typography } from '@mui/material'; | ||||
| import { Box } from '@mui/system'; | import { Box } from '@mui/system'; | ||||
| import { useTranslation } from 'next-i18next'; | import { useTranslation } from 'next-i18next'; | ||||
| import { OrderCard } from '../../../utils/interface/orderInterface'; | |||||
| interface OrderCardProps { | interface OrderCardProps { | ||||
| data: OrderCard; | |||||
| data: { | |||||
| date: string; | |||||
| name: string; | |||||
| totalPrice: number; | |||||
| }; | |||||
| } | } | ||||
| const OrderCard: React.FC<OrderCardProps> = ({ data }) => { | 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; | export default OrderCard; |
| <ContentContainer> | <ContentContainer> | ||||
| <Box flexGrow={1} sx={{ minWidth: '65%' }}> | <Box flexGrow={1} sx={{ minWidth: '65%' }}> | ||||
| <ShippingDetailsForm | <ShippingDetailsForm | ||||
| enableBtn={false} | |||||
| enableBtn={true} | |||||
| backBtn={true} | backBtn={true} | ||||
| isCheckout={true} | isCheckout={true} | ||||
| submitHandler={submitHandler} | submitHandler={submitHandler} |
| import { Box, Button, Paper, TextField } from '@mui/material'; | import { Box, Button, Paper, TextField } from '@mui/material'; | ||||
| import { useFormik } from 'formik'; | import { useFormik } from 'formik'; | ||||
| import React, { useState } from 'react'; | |||||
| import React, { useState, FC } from 'react'; | |||||
| import { contactSchema } from '../../../schemas/contactSchema'; | import { contactSchema } from '../../../schemas/contactSchema'; | ||||
| import { useCheckoutData } from '../../../store/checkout-context'; | import { useCheckoutData } from '../../../store/checkout-context'; | ||||
| import ErrorMessageComponent from '../../mui/ErrorMessageComponent'; | 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; | export default ContactForm; |
| import { | 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 | <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> | </Box> | ||||
| </Container> | |||||
| ); | |||||
| }; | |||||
| export default ContactPageForm; | |||||
| </Box> | |||||
| </Container> | |||||
| ); | |||||
| }; | |||||
| export default ContactPageForm; |
| import { useState, FC } from 'react'; | import { useState, FC } from 'react'; | ||||
| import { registerSchema } from '../../../schemas/shippingDetailsSchema'; | import { registerSchema } from '../../../schemas/shippingDetailsSchema'; | ||||
| import { useUserData } from '../../../store/user-context'; | import { useUserData } from '../../../store/user-context'; | ||||
| import { ShippingData } from '../../../utils/interface/orderInterface'; | |||||
| import ErrorMessageComponent from '../../mui/ErrorMessageComponent'; | import ErrorMessageComponent from '../../mui/ErrorMessageComponent'; | ||||
| interface FormValues { | |||||
| export interface FormValues { | |||||
| fullName: string; | fullName: string; | ||||
| address: string; | address: string; | ||||
| address2: string; | address2: string; | ||||
| } | } | ||||
| interface Props { | interface Props { | ||||
| submitHandler: (x: FormValues) => void; | |||||
| submitHandler: (x: FormValues | ShippingData) => void; | |||||
| backBtn: boolean; | backBtn: boolean; | ||||
| isCheckout: boolean; | isCheckout: boolean; | ||||
| enableBtn: boolean; | enableBtn: boolean; | ||||
| const { userStorage } = useUserData(); | const { userStorage } = useUserData(); | ||||
| const router = useRouter(); | const router = useRouter(); | ||||
| const formikSubmitHandler = async (values: FormValues) => { | |||||
| const formikSubmitHandler = async (values: FormValues | ShippingData) => { | |||||
| submitHandler(values); | submitHandler(values); | ||||
| }; | }; | ||||
| import { Box } from '@mui/system'; | import { Box } from '@mui/system'; | ||||
| import { useSession } from 'next-auth/react'; | import { useSession } from 'next-auth/react'; | ||||
| import { useTranslation } from 'next-i18next'; | import { useTranslation } from 'next-i18next'; | ||||
| import { useState } from 'react'; | |||||
| import { useState, FC } from 'react'; | |||||
| import { updateUser } from '../../requests/user/userUpdateRequest'; | import { updateUser } from '../../requests/user/userUpdateRequest'; | ||||
| import { useUserUpdate } from '../../store/user-context'; | import { useUserUpdate } from '../../store/user-context'; | ||||
| import { OrderDataDB } from '../../utils/interface/orderInterface'; | |||||
| import CardContainer from '../cards/card-container/CardContainer'; | import CardContainer from '../cards/card-container/CardContainer'; | ||||
| import OrderCard from '../cards/order-card/OrderCard'; | import OrderCard from '../cards/order-card/OrderCard'; | ||||
| import ShippingDetailsForm from '../forms/shipping-details/ShippingDetailsForm'; | import ShippingDetailsForm from '../forms/shipping-details/ShippingDetailsForm'; | ||||
| import StepTitle from '../layout/steps-title/StepTitle'; | import StepTitle from '../layout/steps-title/StepTitle'; | ||||
| import Notification from '../notification/Notification'; | 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; | export default ProfileContent; |
| useCheckoutData, | useCheckoutData, | ||||
| useCheckoutDataUpdate, | useCheckoutDataUpdate, | ||||
| } from '../../store/checkout-context'; | } from '../../store/checkout-context'; | ||||
| import { OrderData } from '../../utils/interface/orderInterface'; | |||||
| import PageWrapper from '../layout/page-wrapper/PageWrapper'; | import PageWrapper from '../layout/page-wrapper/PageWrapper'; | ||||
| import StepTitle from '../layout/steps-title/StepTitle'; | import StepTitle from '../layout/steps-title/StepTitle'; | ||||
| const { checkoutStorage } = useCheckoutData(); | const { checkoutStorage } = useCheckoutData(); | ||||
| const { parseCheckoutValue, clearCheckout } = useCheckoutDataUpdate(); | const { parseCheckoutValue, clearCheckout } = useCheckoutDataUpdate(); | ||||
| const { clearCart } = useStoreUpdate(); | const { clearCart } = useStoreUpdate(); | ||||
| const [orderData, setOrderData] = useState({}); | |||||
| const [orderData, setOrderData] = useState<OrderData>({} as OrderData); | |||||
| const router = useRouter(); | const router = useRouter(); | ||||
| > | > | ||||
| <Typography sx={{ fontSize: 18, fontWeight: 600 }}> | <Typography sx={{ fontSize: 18, fontWeight: 600 }}> | ||||
| {t('review:date')} | {t('review:date')} | ||||
| {orderData.time} | |||||
| {orderData?.time?.toLocaleDateString()} | |||||
| </Typography> | </Typography> | ||||
| </Box> | </Box> | ||||
| <Box | <Box |
| import { setCookie } from 'nookies'; | import { setCookie } from 'nookies'; | ||||
| import { useEffect, useState } from 'react'; | import { useEffect, useState } from 'react'; | ||||
| import { | import { | ||||
| CheckoutData, | |||||
| useCheckoutData, | useCheckoutData, | ||||
| useCheckoutDataUpdate, | useCheckoutDataUpdate, | ||||
| } from '../../store/checkout-context'; | } from '../../store/checkout-context'; | ||||
| import { stripe } from '../../utils/helpers/stripe'; | import { stripe } from '../../utils/helpers/stripe'; | ||||
| import { ShippingData as IShippingData } from '../../utils/interface/orderInterface'; | |||||
| import CardContainer from '../cards/card-container/CardContainer'; | import CardContainer from '../cards/card-container/CardContainer'; | ||||
| import DataCard from '../cards/data-card/DataCard'; | import DataCard from '../cards/data-card/DataCard'; | ||||
| import { FormValues } from '../forms/shipping-details/ShippingDetailsForm'; | |||||
| import ContentContainer from '../layout/content-wrapper/ContentContainer'; | import ContentContainer from '../layout/content-wrapper/ContentContainer'; | ||||
| import PageWrapper from '../layout/page-wrapper/PageWrapper'; | import PageWrapper from '../layout/page-wrapper/PageWrapper'; | ||||
| import StepTitle from '../layout/steps-title/StepTitle'; | import StepTitle from '../layout/steps-title/StepTitle'; | ||||
| const { checkoutStorage } = useCheckoutData(); | const { checkoutStorage } = useCheckoutData(); | ||||
| const { changeContact, changeShippingData } = useCheckoutDataUpdate(); | const { changeContact, changeShippingData } = useCheckoutDataUpdate(); | ||||
| const [open, setOpen] = useState({ isOpen: false, type: '' }); | const [open, setOpen] = useState({ isOpen: false, type: '' }); | ||||
| const [checkoutData, setCheckoutData] = useState({}); | |||||
| const [checkoutData, setCheckoutData] = useState<CheckoutData>( | |||||
| {} as CheckoutData | |||||
| ); | |||||
| const router = useRouter(); | const router = useRouter(); | ||||
| setCheckoutData(checkoutStorage); | setCheckoutData(checkoutStorage); | ||||
| }, [checkoutStorage]); | }, [checkoutStorage]); | ||||
| const handleOpen = (type) => setOpen({ isOpen: true, type }); | |||||
| const handleOpen = (type: string) => setOpen({ isOpen: true, type }); | |||||
| const handleClose = () => setOpen({ isOpen: false, type: '' }); | const handleClose = () => setOpen({ isOpen: false, type: '' }); | ||||
| const handleChangeShipping = (values) => { | |||||
| changeShippingData(values); | |||||
| const handleChangeShipping = (values: IShippingData | FormValues) => { | |||||
| changeShippingData(values as IShippingData); | |||||
| handleClose(); | handleClose(); | ||||
| }; | }; | ||||
| const handleChangeContact = (values) => { | |||||
| const handleChangeContact = (values: string) => { | |||||
| changeContact(values); | changeContact(values); | ||||
| handleClose(); | handleClose(); | ||||
| }; | }; | ||||
| price: el.product.stripeID, | price: el.product.stripeID, | ||||
| quantity: el.quantity, | quantity: el.quantity, | ||||
| })), | })), | ||||
| userInfo: checkoutData.userInfo, | |||||
| }); | }); | ||||
| setCookie(null, 'review-session', 'active', { | setCookie(null, 'review-session', 'active', { | ||||
| maxAge: 3600, | maxAge: 3600, |
| import { Box, Button } from '@mui/material'; | import { Box, Button } from '@mui/material'; | ||||
| import { useTranslation } from 'next-i18next'; | 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; | export default ButtonGroup; |
| import { Button, Typography } from '@mui/material'; | import { Button, Typography } from '@mui/material'; | ||||
| import { Box } from '@mui/system'; | import { Box } from '@mui/system'; | ||||
| import { useTranslation } from 'next-i18next'; | 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; | export default ShippingData; |
| import { Modal } from '@mui/material'; | import { Modal } from '@mui/material'; | ||||
| import { Box } from '@mui/system'; | import { Box } from '@mui/system'; | ||||
| import ContactForm from '../../forms/contact/ContactForm'; | 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, | open, | ||||
| handleClose, | handleClose, | ||||
| handleChangeShipping, | handleChangeShipping, | ||||
| }} | }} | ||||
| > | > | ||||
| {open.type === 'Shipping' && ( | {open.type === 'Shipping' && ( | ||||
| <ShippingDetailsForm submitHandler={handleChangeShipping} /> | |||||
| <ShippingDetailsForm | |||||
| submitHandler={handleChangeShipping} | |||||
| backBtn={false} | |||||
| isCheckout={false} | |||||
| enableBtn={true} | |||||
| /> | |||||
| )} | )} | ||||
| {open.type === 'Contact' && ( | {open.type === 'Contact' && ( | ||||
| <ContactForm submitHandler={handleChangeContact} /> | <ContactForm submitHandler={handleChangeContact} /> |
| import type { NextPage } from 'next'; | |||||
| import type { NextPage, GetStaticProps } from 'next'; | |||||
| import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; | import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; | ||||
| import ContactPageForm from '../../components/forms/contact/ContactPageForm'; | import ContactPageForm from '../../components/forms/contact/ContactPageForm'; | ||||
| return <ContactPageForm />; | return <ContactPageForm />; | ||||
| }; | }; | ||||
| export const getStaticProps = async ({ locale }: any) => { | |||||
| export const getStaticProps: GetStaticProps = async ({ locale }: any) => { | |||||
| return { | return { | ||||
| props: { | props: { | ||||
| ...(await serverSideTranslations(locale, ['contact'])), | ...(await serverSideTranslations(locale, ['contact'])), | ||||
| }, | }, | ||||
| }; | }; | ||||
| } | |||||
| }; | |||||
| export default Contact; | export default Contact; |
| import { NextPage } from 'next'; | |||||
| import { NextPage, GetServerSideProps } from 'next'; | |||||
| import { getSession } from 'next-auth/react'; | import { getSession } from 'next-auth/react'; | ||||
| import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; | import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; | ||||
| import ProfileContent from '../../components/profile-content/ProfileContent'; | import ProfileContent from '../../components/profile-content/ProfileContent'; | ||||
| import { LOGIN_PAGE } from '../../constants/pages'; | import { LOGIN_PAGE } from '../../constants/pages'; | ||||
| import { getOrdersForOwner } from '../../requests/orders/getOrdersForOwnerRequest'; | 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>; | 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 }); | const session = await getSession({ req: context.req }); | ||||
| if (!session) { | if (!session) { | ||||
| orders, | orders, | ||||
| }, | }, | ||||
| }; | }; | ||||
| } | |||||
| }; | |||||
| export default ProfilePage; | export default ProfilePage; |
| import { NextPage } from 'next'; | |||||
| import { NextPage, GetServerSideProps } from 'next'; | |||||
| import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; | import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; | ||||
| import nookies from 'nookies'; | import nookies from 'nookies'; | ||||
| import ReviewContent from '../../components/review-content/ReviewContent'; | import ReviewContent from '../../components/review-content/ReviewContent'; | ||||
| const ReviewPage: NextPage = () => { | 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 { | return { | ||||
| props: { | |||||
| ...(await serverSideTranslations(ctx.locale, ['review'])), | |||||
| }, | |||||
| redirect: { | |||||
| destination: '/cart', | |||||
| permanent: false, | |||||
| }, | |||||
| }; | }; | ||||
| } | |||||
| return { | |||||
| props: { | |||||
| ...(await serverSideTranslations(ctx.locale, ['review'])), | |||||
| }, | |||||
| }; | |||||
| }; | }; | ||||
| export default ReviewPage; | export default ReviewPage; |
| import { NextPage } from 'next'; | |||||
| import { NextPage, GetServerSideProps } from 'next'; | |||||
| import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; | import { serverSideTranslations } from 'next-i18next/serverSideTranslations'; | ||||
| import nookies from 'nookies'; | import nookies from 'nookies'; | ||||
| import ShippingContent from '../../components/shipping-content/ShippingContent'; | import ShippingContent from '../../components/shipping-content/ShippingContent'; | ||||
| const ShippingPage: NextPage = () => { | 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 { | return { | ||||
| props: { | |||||
| ...(await serverSideTranslations(ctx.locale, [ | |||||
| 'shipping', | |||||
| 'addressForm', | |||||
| ])), | |||||
| }, | |||||
| redirect: { | |||||
| destination: '/cart', | |||||
| permanent: false, | |||||
| }, | |||||
| }; | }; | ||||
| } | |||||
| return { | |||||
| props: { | |||||
| ...(await serverSideTranslations(ctx.locale, [ | |||||
| 'shipping', | |||||
| 'addressForm', | |||||
| ])), | |||||
| }, | |||||
| }; | |||||
| }; | }; | ||||
| export default ShippingPage; | export default ShippingPage; |
| "note": "Thank you for placing your order with us. We wll get to work on sending your order as soon as possible", | "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", | "title": "Order Summary", | ||||
| "date": "Order placed on: ", | "date": "Order placed on: ", | ||||
| "email": "Email", | |||||
| "email": "Email: ", | |||||
| "total": "Total: $", | "total": "Total: $", | ||||
| "shipping": "Shipping Address: ", | "shipping": "Shipping Address: ", | ||||
| "back": "Back to Home" | "back": "Back to Home" |
| import { createContext, useContext, useState, FC, ReactNode } from 'react'; | import { createContext, useContext, useState, FC, ReactNode } from 'react'; | ||||
| import { getSStorage, setSStorage } from '../utils/helpers/storage'; | 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 { ProductData } from '../utils/interface/productInterface'; | ||||
| import { UserData } from '../utils/interface/userInterface'; | |||||
| interface Props { | interface Props { | ||||
| children: ReactNode; | children: ReactNode; | ||||
| quantity: number; | quantity: number; | ||||
| } | } | ||||
| interface CheckoutData { | |||||
| export interface CheckoutData { | |||||
| products: Products[]; | products: Products[]; | ||||
| userInfo: ShippingData; | userInfo: ShippingData; | ||||
| userID: string; | userID: string; | ||||
| } | } | ||||
| interface OrderData { | |||||
| products: Array<ProductData>; | |||||
| time: string; | |||||
| shippingAddress: ShippingData; | |||||
| totalPrice: number; | |||||
| numberOfItems: number; | |||||
| fulfilled: boolean; | |||||
| owner: string; | |||||
| stripeCheckoutId: string; | |||||
| } | |||||
| interface ICheckout { | interface ICheckout { | ||||
| checkoutStorage: CheckoutData; | checkoutStorage: CheckoutData; | ||||
| } | } | ||||
| const date = new Date(); | const date = new Date(); | ||||
| const dataToStore = { | const dataToStore = { | ||||
| products: items?.products?.map((el) => el.product), | products: items?.products?.map((el) => el.product), | ||||
| time: date.toLocaleDateString(), | |||||
| time: date, | |||||
| shippingAddress: items?.userInfo, | shippingAddress: items?.userInfo, | ||||
| totalPrice: items?.products | totalPrice: items?.products | ||||
| ?.map((entry) => entry?.product.price * entry?.quantity) | ?.map((entry) => entry?.product.price * entry?.quantity) |
| const storedItems = window.localStorage.getItem(key); | 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) => { | export const removeStorage = (key: string) => { |
| totalPrice: number; | totalPrice: number; | ||||
| numberOfItems: number; | numberOfItems: number; | ||||
| fulfilled: boolean; | fulfilled: boolean; | ||||
| owner: ObjectId; | |||||
| owner: ObjectId | string; | |||||
| stripeCheckoutId: string; | stripeCheckoutId: string; | ||||
| } | } | ||||