| import { Box } from '@mui/system'; | import { Box } from '@mui/system'; | ||||
| import { useTranslation } from 'next-i18next'; | import { useTranslation } from 'next-i18next'; | ||||
| import Image from 'next/image'; | import Image from 'next/image'; | ||||
| const CompanyInfo: React.FC = () => { | const CompanyInfo: React.FC = () => { | ||||
| const { t } = useTranslation('home'); | const { t } = useTranslation('home'); | ||||
| return ( | return ( |
| import { Box } from '@mui/system'; | import { Box } from '@mui/system'; | ||||
| import ProductType from '../product-type/ProductType'; | import ProductType from '../product-type/ProductType'; | ||||
| import Sort from '../sort/Sort'; | import Sort from '../sort/Sort'; | ||||
| import { SelectChangeEvent } from "@mui/material"; | |||||
| interface FilterSortProps { | interface FilterSortProps { | ||||
| sort: string; | sort: string; | ||||
| handleSortChange: () => void; | |||||
| handleSortChange: (e: SelectChangeEvent) => void; | |||||
| productType: string; | productType: string; | ||||
| handleProductTypeChange: () => void; | |||||
| handleProductTypeChange: (e: SelectChangeEvent) => void; | |||||
| } | } | ||||
| const FilterSort: React.FC<FilterSortProps> = ({ | const FilterSort: React.FC<FilterSortProps> = ({ |
| import { forgotPasswordSchema } from '../../../schemas/forgotPasswordSchema'; | import { forgotPasswordSchema } from '../../../schemas/forgotPasswordSchema'; | ||||
| const ForgotPasswordForm = () => { | const ForgotPasswordForm = () => { | ||||
| const { t } = useTranslation('forms', 'forgotPass', 'common'); | |||||
| const { t } = useTranslation(['forms', 'forgotPass', 'common']); | |||||
| const handleSubmit = (values) => { | |||||
| const handleSubmit = (values: {email: string}) => { | |||||
| console.log('Values', values); | console.log('Values', values); | ||||
| }; | }; | ||||
| import { loginSchema } from '../../../schemas/loginSchema'; | import { loginSchema } from '../../../schemas/loginSchema'; | ||||
| import ErrorMessageComponent from '../../mui/ErrorMessageComponent'; | import ErrorMessageComponent from '../../mui/ErrorMessageComponent'; | ||||
| interface Values { | |||||
| username: string; | |||||
| password: string; | |||||
| } | |||||
| const LoginForm = () => { | const LoginForm = () => { | ||||
| const { t } = useTranslation('forms', 'login'); | |||||
| const { t } = useTranslation(['forms', 'login']); | |||||
| const [showPassword, setShowPassword] = useState(false); | const [showPassword, setShowPassword] = useState(false); | ||||
| const handleClickShowPassword = () => setShowPassword(!showPassword); | const handleClickShowPassword = () => setShowPassword(!showPassword); | ||||
| const handleMouseDownPassword = () => setShowPassword(!showPassword); | const handleMouseDownPassword = () => setShowPassword(!showPassword); | ||||
| const router = useRouter(); | const router = useRouter(); | ||||
| const [error, setError] = useState({ hasError: false, errorMessage: '' }); | const [error, setError] = useState({ hasError: false, errorMessage: '' }); | ||||
| const submitHandler = async (values) => { | |||||
| const submitHandler = async (values: Values) => { | |||||
| const result = await signIn('credentials', { | const result = await signIn('credentials', { | ||||
| redirect: false, | redirect: false, | ||||
| username: values.username, | username: values.username, | ||||
| password: values.password, | password: values.password, | ||||
| }); | }); | ||||
| if (!result.error) { | |||||
| if (!result?.error) { | |||||
| router.replace(BASE_PAGE); | router.replace(BASE_PAGE); | ||||
| } else { | } else { | ||||
| setError({ hasError: true, errorMessage: result.error }); | |||||
| setError({ hasError: true, errorMessage: result?.error }); | |||||
| } | } | ||||
| }; | }; | ||||
| import { registerSchema } from '../../../schemas/registerSchema'; | import { registerSchema } from '../../../schemas/registerSchema'; | ||||
| import ErrorMessageComponent from '../../mui/ErrorMessageComponent'; | import ErrorMessageComponent from '../../mui/ErrorMessageComponent'; | ||||
| interface Values { | |||||
| fullName: string; | |||||
| username: string; | |||||
| email: string; | |||||
| password: string; | |||||
| address: string; | |||||
| address2: string; | |||||
| city: string; | |||||
| country: string; | |||||
| postcode: string; | |||||
| } | |||||
| const RegisterForm = () => { | const RegisterForm = () => { | ||||
| const { t } = useTranslation('forms', 'register'); | |||||
| const { t } = useTranslation(['forms', 'register']); | |||||
| const router = useRouter(); | const router = useRouter(); | ||||
| const [showPassword, setShowPassword] = useState(false); | const [showPassword, setShowPassword] = useState(false); | ||||
| const [error, setError] = useState({ hasError: false, errorMessage: '' }); | const [error, setError] = useState({ hasError: false, errorMessage: '' }); | ||||
| const submitHandler = async (values) => { | |||||
| const submitHandler = async (values: Values) => { | |||||
| try { | try { | ||||
| const result = await createUser( | const result = await createUser( | ||||
| values.fullName, | values.fullName, | ||||
| ); | ); | ||||
| router.push(LOGIN_PAGE); | router.push(LOGIN_PAGE); | ||||
| } catch (error) { | } catch (error) { | ||||
| setError({ hasError: true, errorMessage: error.message }); | |||||
| if (error instanceof Error) { | |||||
| setError({ hasError: true, errorMessage: error?.message }); | |||||
| } | |||||
| } | } | ||||
| }; | }; | ||||
| import { Grid } from '@mui/material'; | import { Grid } from '@mui/material'; | ||||
| const GridItem = ({ children }) => { | |||||
| interface Props { | |||||
| children: JSX.Element | |||||
| } | |||||
| const GridItem: React.FC<Props> = ({ children }) => { | |||||
| return ( | return ( | ||||
| <Grid item md={4} sm={6} xs={12} sx={{ mb: '100px' }}> | <Grid item md={4} sm={6} xs={12} sx={{ mb: '100px' }}> | ||||
| {children} | {children} |
| import { useRouter } from 'next/router'; | import { useRouter } from 'next/router'; | ||||
| import { PRODUCTS_PAGE } from '../../constants/pages'; | import { PRODUCTS_PAGE } from '../../constants/pages'; | ||||
| const Hero = () => { | |||||
| const Hero: React.FC = () => { | |||||
| const { t } = useTranslation('home'); | const { t } = useTranslation('home'); | ||||
| const router = useRouter(); | const router = useRouter(); |
| const { CircularProgress, Box } = require('@mui/material'); | const { CircularProgress, Box } = require('@mui/material'); | ||||
| const LoadingSpinner = () => { | |||||
| const LoadingSpinner: React.FC = () => { | |||||
| return ( | return ( | ||||
| <Box display="flex" justifyContent="center" sx={{ mt: 5 }}> | <Box display="flex" justifyContent="center" sx={{ mt: 5 }}> | ||||
| <CircularProgress /> | <CircularProgress /> |
| import { FormControl, InputLabel, MenuItem, Select } from '@mui/material'; | |||||
| import { FormControl, InputLabel, MenuItem, Select, SelectChangeEvent } from '@mui/material'; | |||||
| import { useTranslation } from 'next-i18next'; | import { useTranslation } from 'next-i18next'; | ||||
| interface ProductTypeProps { | interface ProductTypeProps { | ||||
| productType: string; | productType: string; | ||||
| handleProductTypeChange: () => void; | |||||
| handleProductTypeChange: (e: SelectChangeEvent) => void; | |||||
| } | } | ||||
| const ProductType: React.FC<ProductTypeProps> = ({ productType, handleProductTypeChange }) => { | const ProductType: React.FC<ProductTypeProps> = ({ productType, handleProductTypeChange }) => { |
| import { SelectChangeEvent } from '@mui/material'; | |||||
| import { Box } from '@mui/system'; | import { Box } from '@mui/system'; | ||||
| import Head from 'next/head'; | import Head from 'next/head'; | ||||
| import { useState } from 'react'; | import { useState } from 'react'; | ||||
| import LoadingSpinner from '../loader/basic-spinner/LoadSpinner'; | import LoadingSpinner from '../loader/basic-spinner/LoadSpinner'; | ||||
| import ProductsGrid from '../products-grid/ProductsGrid'; | import ProductsGrid from '../products-grid/ProductsGrid'; | ||||
| import ProductsHero from '../products-hero/ProductsHero'; | import ProductsHero from '../products-hero/ProductsHero'; | ||||
| import { SelectChangeEvent } from "@mui/material"; | |||||
| const ProductsContent = () => { | |||||
| const ProductsContent: React.FC = () => { | |||||
| const [filter, setFilter] = useState<string>(''); | const [filter, setFilter] = useState<string>(''); | ||||
| const [sort, setSort] = useState<string>(''); | const [sort, setSort] = useState<string>(''); | ||||
| const { data, isLoading, fetchNextPage, hasNextPage, isFetchingNextPage } = | const { data, isLoading, fetchNextPage, hasNextPage, isFetchingNextPage } = | ||||
| useInfiniteProducts(filter, sort); | useInfiniteProducts(filter, sort); | ||||
| const handleProductTypeChange = () => { | |||||
| return (event: SelectChangeEvent) => { | |||||
| const filterText = event.target.value; | |||||
| setFilter(filterText); | |||||
| } | |||||
| const handleProductTypeChange = (event: SelectChangeEvent) => { | |||||
| const filterText = event.target.value; | |||||
| setFilter(filterText); | |||||
| }; | }; | ||||
| const handleSortChange = () => { | |||||
| return (event: SelectChangeEvent) => { | |||||
| const sort = event.target.value; | |||||
| setSort(sort); | |||||
| } | |||||
| const handleSortChange = (event: SelectChangeEvent) => { | |||||
| const sort = event.target.value; | |||||
| setSort(sort); | |||||
| }; | }; | ||||
| return ( | return ( |
| import { Container, Grid } from '@mui/material'; | import { Container, Grid } from '@mui/material'; | ||||
| import { Box } from '@mui/system'; | import { Box } from '@mui/system'; | ||||
| import { ProductDataDB } from '../../utils/interface/productInterface'; | |||||
| import LoadMore from '../buttons/load-more/LoadMore'; | import LoadMore from '../buttons/load-more/LoadMore'; | ||||
| import GridItem from '../grid-item/GridItem'; | import GridItem from '../grid-item/GridItem'; | ||||
| import ProductCard from '../product-card/ProductCard'; | import ProductCard from '../product-card/ProductCard'; | ||||
| const ProductsGrid = ({ | |||||
| interface PageProps { | |||||
| message: string; | |||||
| next: string; | |||||
| prevous: string; | |||||
| product: ProductDataDB[]; | |||||
| productCount: number; | |||||
| } | |||||
| interface ProductsProps { | |||||
| pages: PageProps[]; | |||||
| } | |||||
| interface Props { | |||||
| allProducts: ProductsProps | |||||
| hasNextPage: boolean; | |||||
| isFetchingNextPage: boolean; | |||||
| fetchNextPage: () => void; | |||||
| } | |||||
| const ProductsGrid: React.FC<Props> = ({ | |||||
| allProducts, | allProducts, | ||||
| hasNextPage, | hasNextPage, | ||||
| fetchNextPage, | fetchNextPage, |
| import { Box } from '@mui/system'; | import { Box } from '@mui/system'; | ||||
| import { useTranslation } from 'next-i18next'; | import { useTranslation } from 'next-i18next'; | ||||
| const ProductsHero = () => { | |||||
| const ProductsHero: React.FC = () => { | |||||
| const { t } = useTranslation('products'); | const { t } = useTranslation('products'); | ||||
| return ( | return ( | ||||
| <Box | <Box |
| import { useTranslation } from 'next-i18next'; | import { useTranslation } from 'next-i18next'; | ||||
| import Image from 'next/image'; | import Image from 'next/image'; | ||||
| import { useState } from 'react'; | import { useState } from 'react'; | ||||
| import { ProductDataDB } from '../../../utils/interface/productInterface'; | |||||
| interface DataProps { | interface DataProps { | ||||
| name: string; | name: string; |
| import { FormControl, InputLabel, MenuItem, Select } from '@mui/material'; | |||||
| import { FormControl, InputLabel, MenuItem, Select, SelectChangeEvent } from '@mui/material'; | |||||
| import { useTranslation } from 'next-i18next'; | import { useTranslation } from 'next-i18next'; | ||||
| interface SortProps { | interface SortProps { | ||||
| sort: string; | sort: string; | ||||
| handleSortChange: () => void; | |||||
| handleSortChange: (e: SelectChangeEvent) => void; | |||||
| } | } | ||||
| const Sort: React.FC<SortProps> = ({ sort, handleSortChange }) => { | const Sort: React.FC<SortProps> = ({ sort, handleSortChange }) => { |
| ), | ), | ||||
| { | { | ||||
| getNextPageParam: (lastPage, pages) => { | getNextPageParam: (lastPage, pages) => { | ||||
| if (lastPage.next !== null) { | |||||
| if (lastPage.next !== '') { | |||||
| return pages.length + 1; | return pages.length + 1; | ||||
| } | } | ||||
| }, | }, |
| import { useUserUpdate } from '../store/user-context'; | import { useUserUpdate } from '../store/user-context'; | ||||
| import { getStorage } from '../utils/helpers/storage'; | import { getStorage } from '../utils/helpers/storage'; | ||||
| import { useEffect } from 'react'; | import { useEffect } from 'react'; | ||||
| import { ProductDataDB } from '../utils/interface/productInterface'; | |||||
| interface Props { | |||||
| data: { featuredProducts: ProductDataDB[], message: string }; | |||||
| } | |||||
| const Home: NextPage = ({ featuredProducts }) => { | |||||
| const Home: NextPage<Props> = ({ data }) => { | |||||
| const { data: session } = useSession(); | const { data: session } = useSession(); | ||||
| const { addUser } = useUserUpdate(); | const { addUser } = useUserUpdate(); | ||||
| </Head> | </Head> | ||||
| <Hero /> | <Hero /> | ||||
| <FeaturedProductsList | <FeaturedProductsList | ||||
| featuredProducts={featuredProducts} | |||||
| featuredProducts={data.featuredProducts} | |||||
| ></FeaturedProductsList> | ></FeaturedProductsList> | ||||
| <Features /> | <Features /> | ||||
| <CompanyInfo /> | <CompanyInfo /> | ||||
| export async function getStaticProps({ locale }: any) { | export async function getStaticProps({ locale }: any) { | ||||
| try { | try { | ||||
| const { message, featuredProducts } = await getFeaturedProducts(); | |||||
| const data = await getFeaturedProducts(); | |||||
| return { | return { | ||||
| props: { | props: { | ||||
| ...(await serverSideTranslations(locale, ["home"])), | ...(await serverSideTranslations(locale, ["home"])), | ||||
| message, | |||||
| featuredProducts, | |||||
| data: data | |||||
| }, | }, | ||||
| }; | }; | ||||
| } catch (error) { | } catch (error) { | ||||
| return { | return { | ||||
| props: { | props: { | ||||
| ...(await serverSideTranslations(locale, ['home'])), | ...(await serverSideTranslations(locale, ['home'])), | ||||
| errorMessage: error, | |||||
| featuredProducts: [], | featuredProducts: [], | ||||
| }, | }, | ||||
| }; | }; |
| import { useFetchSingleProduct } from '../../hooks/useFetchProductData'; | import { useFetchSingleProduct } from '../../hooks/useFetchProductData'; | ||||
| import { getProductData } from '../../requests/products/producDataRequest'; | import { getProductData } from '../../requests/products/producDataRequest'; | ||||
| import { useStore, useStoreUpdate } from '../../store/cart-context'; | import { useStore, useStoreUpdate } from '../../store/cart-context'; | ||||
| import { SingleProductResponseGet } from '../../utils/interface/productInterface'; | |||||
| const SingleProduct: NextPage = () => { | |||||
| interface Props { | |||||
| data: SingleProductResponseGet; | |||||
| } | |||||
| const SingleProduct: NextPage<Props> = ({ data }) => { | |||||
| const { t } = useTranslation('products'); | const { t } = useTranslation('products'); | ||||
| const { addCartValue } = useStoreUpdate(); | const { addCartValue } = useStoreUpdate(); | ||||
| const { cartStorage } = useStore(); | const { cartStorage } = useStore(); | ||||
| const router = useRouter(); | const router = useRouter(); | ||||
| const { customId } = router.query; | |||||
| const customId = router.query.customId ? router.query.customId as string : undefined; | |||||
| const { data, isLoading } = useFetchSingleProduct(customId); | |||||
| // const { data, isLoading } = useFetchSingleProduct(customId); | |||||
| const addProductToCart = (quantity) => addCartValue(data.product, quantity); | |||||
| const addProductToCart = (quantity: number) => addCartValue(data?.product, quantity); | |||||
| const inCart = | const inCart = | ||||
| cartStorage?.length > 0 | cartStorage?.length > 0 | ||||
| ? cartStorage?.some((item) => item.product.customID === product.customID) | |||||
| ? cartStorage?.some((item) => item.product.customID === data?.product.customID) | |||||
| ? true | ? true | ||||
| : false | : false | ||||
| : false; | : false; | ||||
| if (isLoading) { | |||||
| return <Loader loading={isLoading} />; | |||||
| } | |||||
| return ( | return ( | ||||
| <Box | <Box | ||||
| sx={{ | sx={{ | ||||
| fontSize="32px" | fontSize="32px" | ||||
| sx={{ mt: 25, height: '100%', color: 'primary.main' }} | sx={{ mt: 25, height: '100%', color: 'primary.main' }} | ||||
| > | > | ||||
| {data.product.name} | |||||
| {data?.product.name} | |||||
| </Typography> | </Typography> | ||||
| <Grid container spacing={2}> | <Grid container spacing={2}> | ||||
| <Grid sx={{ display: 'flex' }} item md={6} sm={12}> | <Grid sx={{ display: 'flex' }} item md={6} sm={12}> | ||||
| <Image | <Image | ||||
| src={data.product.image} | |||||
| src={data?.product.image} | |||||
| alt="product" | alt="product" | ||||
| width={900} | width={900} | ||||
| height={700} | height={700} | ||||
| {t('products:similar')} | {t('products:similar')} | ||||
| </Typography> | </Typography> | ||||
| <Grid container spacing={2}> | <Grid container spacing={2}> | ||||
| {data.similarProducts.map((product) => ( | |||||
| {data?.similarProducts.map((product) => ( | |||||
| <GridItem key={product._id}> | <GridItem key={product._id}> | ||||
| <ProductCard product={product} /> | <ProductCard product={product} /> | ||||
| </GridItem> | </GridItem> | ||||
| const { params } = context; | const { params } = context; | ||||
| const { customId } = params; | const { customId } = params; | ||||
| console.log(customId); | |||||
| const queryClient = new QueryClient(); | const queryClient = new QueryClient(); | ||||
| await queryClient.prefetchQuery( | |||||
| const data = await queryClient.fetchQuery( | |||||
| ['product', customId], | |||||
| async () => await getProductData(customId) | |||||
| ); | |||||
| await queryClient.fetchQuery( | |||||
| ['product', customId], | ['product', customId], | ||||
| async () => await getProductData(customId) | async () => await getProductData(customId) | ||||
| ); | ); | ||||
| return { | return { | ||||
| props: { | props: { | ||||
| data: data, | |||||
| dehydratatedState: dehydrate(queryClient), | dehydratatedState: dehydrate(queryClient), | ||||
| ...(await serverSideTranslations(context.locale, ['products'])), | ...(await serverSideTranslations(context.locale, ['products'])), | ||||
| }, | }, |
| product: ProductData; | product: ProductData; | ||||
| } | } | ||||
| interface SingleProductResponseGet { | |||||
| export interface SingleProductResponseGet { | |||||
| message: string; | message: string; | ||||
| product: ProductDataDB; | product: ProductDataDB; | ||||
| similarProducts: Array<ProductDataDB>; | similarProducts: Array<ProductDataDB>; | ||||
| | ProductsResponseError; | | ProductsResponseError; | ||||
| export type FeaturedProductsResponse = | export type FeaturedProductsResponse = | ||||
| | FeaturedProductsResponseGet | |||||
| FeaturedProductsResponseGet | |||||
| | ProductsResponseError; | | ProductsResponseError; |