diff --git a/package-lock.json b/package-lock.json index a6c6675..695768e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,7 @@ "lodash": "^4.17.21", "next": "13.2.3", "next-redux-wrapper": "^8.1.0", + "nextjs-progressbar": "^0.0.16", "react": "18.2.0", "react-content-loader": "^6.2.1", "react-dom": "18.2.0", @@ -1051,6 +1052,11 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.6.tgz", "integrity": "sha512-93+VvleD3mXwlLI/xASjw0FzKcwzl3OdTCzm1LaRfqgS21gfFtK3zDXM5Op9TeeMsJVOaJ2VRDpT9q4Y3d0AvA==" }, + "node_modules/@types/nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@types/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha512-1cYJrqq9GezNFPsWTZpFut/d4CjpZqA0vhqDUPFWYKF1oIyBz5qnoYMzR+0C/T96t3ebLAC1SSnwrVOm5/j74A==" + }, "node_modules/@types/prop-types": { "version": "15.7.5", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", @@ -5789,6 +5795,20 @@ "react-redux": "*" } }, + "node_modules/nextjs-progressbar": { + "version": "0.0.16", + "resolved": "https://registry.npmjs.org/nextjs-progressbar/-/nextjs-progressbar-0.0.16.tgz", + "integrity": "sha512-GV0fD38EMD3vSDCmkq+tObmoup6QA91a6a9MxGuhJZuRk/9TNsrHGnIQQQ/sggkMkXuT4fBgF6jRjFwScDT3zA==", + "dependencies": { + "@types/nprogress": "^0.2.0", + "nprogress": "^0.2.0", + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "next": ">= 6.0.0", + "react": ">= 16.0.0" + } + }, "node_modules/node-libs-browser": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", @@ -5847,6 +5867,11 @@ "node": ">=0.10.0" } }, + "node_modules/nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==" + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -10401,6 +10426,11 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.6.tgz", "integrity": "sha512-93+VvleD3mXwlLI/xASjw0FzKcwzl3OdTCzm1LaRfqgS21gfFtK3zDXM5Op9TeeMsJVOaJ2VRDpT9q4Y3d0AvA==" }, + "@types/nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@types/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha512-1cYJrqq9GezNFPsWTZpFut/d4CjpZqA0vhqDUPFWYKF1oIyBz5qnoYMzR+0C/T96t3ebLAC1SSnwrVOm5/j74A==" + }, "@types/prop-types": { "version": "15.7.5", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", @@ -14073,6 +14103,16 @@ "integrity": "sha512-2hIau0hcI6uQszOtrvAFqgc0NkZegKYhBB7ZAKiG3jk7zfuQb4E7OV9jfxViqqojh3SEHdnFfPkN9KErttUKuw==", "requires": {} }, + "nextjs-progressbar": { + "version": "0.0.16", + "resolved": "https://registry.npmjs.org/nextjs-progressbar/-/nextjs-progressbar-0.0.16.tgz", + "integrity": "sha512-GV0fD38EMD3vSDCmkq+tObmoup6QA91a6a9MxGuhJZuRk/9TNsrHGnIQQQ/sggkMkXuT4fBgF6jRjFwScDT3zA==", + "requires": { + "@types/nprogress": "^0.2.0", + "nprogress": "^0.2.0", + "prop-types": "^15.8.1" + } + }, "node-libs-browser": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz", @@ -14124,6 +14164,11 @@ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" }, + "nprogress": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/nprogress/-/nprogress-0.2.0.tgz", + "integrity": "sha512-I19aIingLgR1fmhftnbWWO3dXc0hSxqHQHQb3H8m+K3TnEn/iSeTZZOyvKXWqQESMwuUVnatlCnZdLBZZt2VSA==" + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", diff --git a/package.json b/package.json index b7bd459..cde0e24 100644 --- a/package.json +++ b/package.json @@ -25,6 +25,7 @@ "lodash": "^4.17.21", "next": "13.2.3", "next-redux-wrapper": "^8.1.0", + "nextjs-progressbar": "^0.0.16", "react": "18.2.0", "react-content-loader": "^6.2.1", "react-dom": "18.2.0", diff --git a/src/components/layout/Layout.tsx b/src/components/layout/Layout.tsx index c9d2dab..af1098a 100644 --- a/src/components/layout/Layout.tsx +++ b/src/components/layout/Layout.tsx @@ -4,6 +4,9 @@ import Header from './header/Header'; import DrawCategory from '../ui/drawer/DrawCategory'; import { CategoryService } from '@/services/Server/ServerCategory'; import styled from 'styled-components'; +import { Spin } from 'antd'; + +import NextProgress from 'nextjs-progressbar'; interface ILayout { children?: React.ReactNode; @@ -17,11 +20,17 @@ const Section = styled.section` display: flex; `; -// TODO: change categories variable to object like {data, changeData, loading, error} or set 'em to redux storage +const LoaderWrapper = styled.div` + display: flex; + align-items: center; + justify-content: center; + width: 100vw; + height: 100vh; +`; const Layout: React.FC = ({ children }) => { const [categories, setCategories] = useState(null); - const [loading, setLoading] = useState(false); + const [loading, setLoading] = useState(true); useEffect(() => { setLoading(true); @@ -30,16 +39,31 @@ const Layout: React.FC = ({ children }) => { if (response) { setCategories(response); } else setCategories([]); - setLoading(false); })(); }, []); - if (loading) return
Loading...
; + useEffect(() => { + if (categories) setLoading(false); + }, [categories]); - // TODO: create recurcive function for fetching data + if (loading) + return ( + + + + ); return (
+
{children}
diff --git a/src/components/layout/auth/AuthModal.tsx b/src/components/layout/auth/AuthModal.tsx index aa314c3..ad51112 100644 --- a/src/components/layout/auth/AuthModal.tsx +++ b/src/components/layout/auth/AuthModal.tsx @@ -13,7 +13,7 @@ const AuthModal: React.FC = ({ shouldShow, setShouldShow }) => { return ( setShouldShow(false)} @@ -22,13 +22,13 @@ const AuthModal: React.FC = ({ shouldShow, setShouldShow }) => { {authType === 'login' ? ( ) : ( )} diff --git a/src/components/layout/auth/LoginForm.tsx b/src/components/layout/auth/LoginForm.tsx index 521bcff..13eb633 100644 --- a/src/components/layout/auth/LoginForm.tsx +++ b/src/components/layout/auth/LoginForm.tsx @@ -47,9 +47,7 @@ const LoginForm: React.FC = ({ children }) => { setStatus(''); }, 3000); - return ( - } title="Great, we successfuly logged!" /> - ); + return } title="Авторизовано!" />; } if (status === 'error') { @@ -60,8 +58,8 @@ const LoginForm: React.FC = ({ children }) => { return ( ); } @@ -69,14 +67,14 @@ const LoginForm: React.FC = ({ children }) => { return (
setEmail(e.target.value)} /> setPassword(e.target.value)} @@ -84,7 +82,7 @@ const LoginForm: React.FC = ({ children }) => { {children} - + ); diff --git a/src/components/layout/auth/RegisterForm.tsx b/src/components/layout/auth/RegisterForm.tsx index 044437c..f694ad9 100644 --- a/src/components/layout/auth/RegisterForm.tsx +++ b/src/components/layout/auth/RegisterForm.tsx @@ -81,12 +81,7 @@ const RegisterForm: React.FC = ({ children }) => { setStatus(''); }, 3000); - return ( - } - title="Great, we successfuly register!" - /> - ); + return } title="Вас зареєстровано!" />; } if (status === 'error') { @@ -97,8 +92,8 @@ const RegisterForm: React.FC = ({ children }) => { return ( ); } @@ -107,13 +102,13 @@ const RegisterForm: React.FC = ({ children }) => {
setData({ ...data, firstname: e.target.value })} /> setData({ ...data, lastname: e.target.value })} /> @@ -122,21 +117,21 @@ const RegisterForm: React.FC = ({ children }) => { setData({ ...data, phone: e.target.value })} /> setData({ ...data, email: e.target.value })} /> { setData({ ...data, birthdate: new Date(dateString) }); }} @@ -146,7 +141,7 @@ const RegisterForm: React.FC = ({ children }) => { setData({ ...data, password: e.target.value })} @@ -154,20 +149,20 @@ const RegisterForm: React.FC = ({ children }) => { setData({ ...data, repeatPassword: e.target.value })} /> {!validePassword && data.password ? ( - Passwords do not match + Паролі не співпадають ) : ( <> )} {children} - + ); diff --git a/src/components/screen/category/Category.tsx b/src/components/screen/category/Category.tsx index cc50892..7bbc062 100644 --- a/src/components/screen/category/Category.tsx +++ b/src/components/screen/category/Category.tsx @@ -77,7 +77,7 @@ const sortVariables = [ const Category: React.FC = ({ data, categoryId }) => { const [categoryResults, setCategoryResults] = useState(data); const [loading, setLoading] = useState(false); - const [refinements, setRefinements] = useState({}); + const [refinements, setRefinements] = useState(null); const filter = useTypedSelector((state) => state.product.filter); useEffect(() => { diff --git a/src/components/screen/user/Favourites.tsx b/src/components/screen/user/Favourites.tsx index aa0aa4f..771a666 100644 --- a/src/components/screen/user/Favourites.tsx +++ b/src/components/screen/user/Favourites.tsx @@ -58,14 +58,11 @@ const Favourites: React.FC = ({ user }) => { Список бажань - {loading ? ( - user.favourites?.map((fav) => ) - ) : ( - <> - )} - {products.map((product) => ( - - ))} + {loading + ? user.favourites?.map((fav) => ) + : products.map((product) => ( + + ))} ); diff --git a/src/components/screen/user/Orders.tsx b/src/components/screen/user/Orders.tsx index 0c88168..6fe26a6 100644 --- a/src/components/screen/user/Orders.tsx +++ b/src/components/screen/user/Orders.tsx @@ -164,7 +164,7 @@ const Orders: React.FC = ({ user }) => { key={product.id} alt="ordered-product" src={`https://diploma-server.vercel.app/${ - products.find((item) => item._id === product?.id)?.picture + products.find((item) => item?._id === product?.id)?.picture }`} /> ))} diff --git a/src/components/screen/user/User.tsx b/src/components/screen/user/User.tsx index a7aae10..3cd5718 100644 --- a/src/components/screen/user/User.tsx +++ b/src/components/screen/user/User.tsx @@ -9,6 +9,7 @@ import styled from 'styled-components'; import Personal from './Personal'; import Favourites from './Favourites'; import Orders from './Orders'; +import { useRouter } from 'next/router'; const Wrapper = styled.div` width: 100%; @@ -81,6 +82,8 @@ const User = () => { Number(window?.location?.search?.split('=')[1]) || 1 ); + const route = useRouter(); + const user = useTypedSelector((state) => state.user.user); const handleActive = (page: number) => { @@ -93,7 +96,10 @@ const User = () => { {controlItems.map((control, index) => ( handleActive(index + 1)} + onClick={() => { + handleActive(index + 1); + route.push(`/user?window=${index + 1}`); + }} active={active === index + 1} > {control.ico} {control.title} diff --git a/src/components/ui/card/Card.tsx b/src/components/ui/card/Card.tsx index 7e41e62..318a496 100644 --- a/src/components/ui/card/Card.tsx +++ b/src/components/ui/card/Card.tsx @@ -112,8 +112,8 @@ const Card: React.FC = ({ product }) => { diff --git a/src/components/ui/checkout/Eventually.tsx b/src/components/ui/checkout/Eventually.tsx index 729cf2b..e74c331 100644 --- a/src/components/ui/checkout/Eventually.tsx +++ b/src/components/ui/checkout/Eventually.tsx @@ -1,13 +1,11 @@ -import React, { useMemo, useRef, useState } from 'react'; +import React, { useMemo, useState } from 'react'; import { ShadowWrapper } from '../cart/ShadowWrapper'; import styled from 'styled-components'; import { Line } from '../common/Line'; import { Button } from 'antd'; import { useTypedSelector } from '@/hooks/useTypedSelector'; import { UserService } from '@/services/Server/SeverUser'; -import { useActions } from '@/hooks/useActions'; import Spinner from '../common/Spinner'; -import sha1 from 'js-sha1'; import { useRouter } from 'next/navigation'; @@ -41,15 +39,9 @@ const Eventually = () => { const items = useTypedSelector((state) => state.cart.items); const order = useTypedSelector((state) => state.order); const user = useTypedSelector((state) => state.user.user); - const [liqpay, setLiqpay] = useState({ - data: '', - signature: '', - }); const router = useRouter(); - const { clearCart } = useActions(); - const products = useMemo( () => items.map((item) => ({ @@ -80,12 +72,11 @@ const Eventually = () => { const createdOrder = await UserService.createOrder(data, { id: user._id }); - console.log(createdOrder); - if (createdOrder.order) router.push( `checkout/success?id=${createdOrder.order._id}&total=${createdOrder.order.total}` ); + setLoading(false); }; diff --git a/src/components/ui/checkout/Order.tsx b/src/components/ui/checkout/Order.tsx index f435c12..4254b1d 100644 --- a/src/components/ui/checkout/Order.tsx +++ b/src/components/ui/checkout/Order.tsx @@ -21,8 +21,6 @@ const Order = () => { return (

Замовлення:

- {/* TODO: Create special component for this */} - {/* Rewrite to grid */} {items && items.map((item) => ( @@ -42,7 +40,6 @@ const Order = () => {
{ > - + {/* */} ); }; -// AIzaSyAyJQV-jP5bxTFg5AFE5MC0pQyZXGUoWcs - export default Type; diff --git a/src/components/ui/refinements/Refinements.tsx b/src/components/ui/refinements/Refinements.tsx index d58e69a..821ad0a 100644 --- a/src/components/ui/refinements/Refinements.tsx +++ b/src/components/ui/refinements/Refinements.tsx @@ -1,7 +1,8 @@ import React, { useState } from 'react'; -import { Select } from 'antd'; +import { Select, Spin } from 'antd'; import styled from 'styled-components'; import { useActions } from '@/hooks/useActions'; +import Spinner from '../common/Spinner'; interface ICRefinements { data: any; @@ -72,7 +73,7 @@ const RefiWrapper = styled.div` p { font-size: 12pt; margin-bottom: 4px; - color: gray; + color: black; } .ant-select { @@ -86,6 +87,14 @@ const RefiWrapper = styled.div` } `; +const LoaderWrapper = styled.div` + display: flex; + align-items: center; + justify-content: center; + width: 100%; + height: 50vh; +`; + const attributesUA: { [key: string]: string } = { brand: 'Бренд', kind: 'Вид', @@ -95,7 +104,7 @@ const attributesUA: { [key: string]: string } = { strengths: 'Міцність (Abv)', }; -const Refinements: React.FC = ({ data }) => { +const Refinements: React.FC = ({ data = null }) => { const [shouldShow, setShouldShow] = useState(false); const [value, setValue] = useState({ brand: [], @@ -143,7 +152,9 @@ const Refinements: React.FC = ({ data }) => { )) ) : ( -
Loading...
+ + + )} Фільтрація diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx index bee9640..c4ca6c7 100644 --- a/src/pages/_app.tsx +++ b/src/pages/_app.tsx @@ -7,9 +7,12 @@ import { PersistGate } from 'redux-persist/integration/react'; import { store } from '@/store/store'; import { persistor } from '@/store/store'; import { ThemeProvider } from 'styled-components'; +import { useRouter } from 'next/router'; // import light from '@styles/themes/light.scss'; import Layout from '@/components/layout/Layout'; +import { useState, useEffect } from 'react'; +import { createPortal } from 'react-dom'; // TODO: Create a theme switcher, lazy load theme by an ask