diff --git a/src/app/dish/[dishId]/loading.js b/src/app/dish/[dishId]/loading.js new file mode 100644 index 0000000..52e2907 --- /dev/null +++ b/src/app/dish/[dishId]/loading.js @@ -0,0 +1,6 @@ +import { Loader } from "@/components/loader/component"; + + +export default function Loading() { + return ; + } \ No newline at end of file diff --git a/src/app/dish/[dishId]/page.js b/src/app/dish/[dishId]/page.js new file mode 100644 index 0000000..82be48e --- /dev/null +++ b/src/app/dish/[dishId]/page.js @@ -0,0 +1,16 @@ + +import { DishContainer } from "@/components/dish/container"; +import styles from "./styles.module.scss"; +import { Ingredients } from "@/components/ingredients/component"; +import { getDishById } from "@/services/api"; + +export default async function DishPage({params}) { + const dish = await getDishById(params.dishId); + + return ( +
+ + +
+); +} diff --git a/src/app/dish/[dishId]/styles.module.scss b/src/app/dish/[dishId]/styles.module.scss new file mode 100644 index 0000000..e1f8f08 --- /dev/null +++ b/src/app/dish/[dishId]/styles.module.scss @@ -0,0 +1,10 @@ +// .root { +// background-color: rgb(209, 253, 253); +// height: 100%; +// display: grid; +// grid-template-rows: auto 1fr auto; +// min-height: 100vh; +// } +.root { + margin: 10px 20px; + } \ No newline at end of file diff --git a/src/app/page.js b/src/app/page.js index 82551a7..e9804da 100644 --- a/src/app/page.js +++ b/src/app/page.js @@ -1,11 +1,7 @@ -import styles from "./styles.module.scss"; +export default function HomePage() { + return ( +
HomePage
+ ) +} -export default function Home() { - return ( -
-
- Home page -
-
- ) -} \ No newline at end of file + \ No newline at end of file diff --git a/src/app/restaurants/[restaurantId]/layout.js b/src/app/restaurants/[restaurantId]/layout.js index 93ddd72..06c4c9c 100644 --- a/src/app/restaurants/[restaurantId]/layout.js +++ b/src/app/restaurants/[restaurantId]/layout.js @@ -4,7 +4,6 @@ import { Restaurant } from '@/components/restaurant/component'; const Layout = async ({ children, params }) => { const restaurant = await getRestaurantById(params.restaurantId); - return (
diff --git a/src/app/restaurants/[restaurantId]/loading.js b/src/app/restaurants/[restaurantId]/loading.js index 8cf4cb8..52e2907 100644 --- a/src/app/restaurants/[restaurantId]/loading.js +++ b/src/app/restaurants/[restaurantId]/loading.js @@ -2,5 +2,5 @@ import { Loader } from "@/components/loader/component"; export default function Loading() { - return + return ; } \ No newline at end of file diff --git a/src/app/restaurants/[restaurantId]/menu/layout.js b/src/app/restaurants/[restaurantId]/menu/layout.js deleted file mode 100644 index 93ddd72..0000000 --- a/src/app/restaurants/[restaurantId]/menu/layout.js +++ /dev/null @@ -1,16 +0,0 @@ - -import { getRestaurantById } from "@/services/api"; -import { Restaurant } from '@/components/restaurant/component'; - -const Layout = async ({ children, params }) => { - const restaurant = await getRestaurantById(params.restaurantId); - - return ( -
- - {children} -
- ); -}; - -export default Layout; diff --git a/src/app/restaurants/[restaurantId]/menu/loading.js b/src/app/restaurants/[restaurantId]/menu/loading.js index 8cf4cb8..20098cc 100644 --- a/src/app/restaurants/[restaurantId]/menu/loading.js +++ b/src/app/restaurants/[restaurantId]/menu/loading.js @@ -2,5 +2,5 @@ import { Loader } from "@/components/loader/component"; export default function Loading() { - return + return ; } \ No newline at end of file diff --git a/src/app/restaurants/[restaurantId]/page.js b/src/app/restaurants/[restaurantId]/page.js index 1c393d7..3fabc20 100644 --- a/src/app/restaurants/[restaurantId]/page.js +++ b/src/app/restaurants/[restaurantId]/page.js @@ -1,6 +1,8 @@ +import { redirect } from 'next/navigation'; -export default function RestaurantPage({ params }) { - return ( - null - ) - } \ No newline at end of file +const RestaurantPage = ({params}) => { + redirect(params.restaurantId+'/menu'); + +}; + +export default RestaurantPage; \ No newline at end of file diff --git a/src/app/restaurants/[restaurantId]/reviews/loading.js b/src/app/restaurants/[restaurantId]/reviews/loading.js index 8cf4cb8..52e2907 100644 --- a/src/app/restaurants/[restaurantId]/reviews/loading.js +++ b/src/app/restaurants/[restaurantId]/reviews/loading.js @@ -2,5 +2,5 @@ import { Loader } from "@/components/loader/component"; export default function Loading() { - return + return ; } \ No newline at end of file diff --git a/src/app/restaurants/[restaurantId]/reviews/page.js b/src/app/restaurants/[restaurantId]/reviews/page.js index fe62dca..648f2bf 100644 --- a/src/app/restaurants/[restaurantId]/reviews/page.js +++ b/src/app/restaurants/[restaurantId]/reviews/page.js @@ -1,10 +1,7 @@ -import { getReviewsByRestaurantId } from "@/services/api"; -import { Reviews } from '@/components/reviews/component'; +import { ReviewsContainer } from '@/components/reviews/container'; -export default async function ReviewPage({params}) { - const restaurantId = params.restaurantId; - const reviews = await getReviewsByRestaurantId(restaurantId); - return ( - - ) - } +export default async function ReviewPage({ params }) { + const restaurantId = params.restaurantId; + + return ; +} \ No newline at end of file diff --git a/src/app/restaurants/loading.js b/src/app/restaurants/loading.js index 9137f54..faad2d5 100644 --- a/src/app/restaurants/loading.js +++ b/src/app/restaurants/loading.js @@ -1,5 +1,5 @@ import { Loader } from "@/components/loader/component"; export default function Loading() { - return + return ; } \ No newline at end of file diff --git a/src/app/styles.module.scss b/src/app/styles.module.scss index 69b24f9..bbd49fe 100644 --- a/src/app/styles.module.scss +++ b/src/app/styles.module.scss @@ -4,4 +4,5 @@ display: grid; grid-template-rows: auto 1fr auto; min-height: 100vh; + } \ No newline at end of file diff --git a/src/components/button/component.jsx b/src/components/button/component.jsx index 667db48..4fdf585 100644 --- a/src/components/button/component.jsx +++ b/src/components/button/component.jsx @@ -1,4 +1,4 @@ -"use client"; +import { memo } from 'react'; import styles from './styles.module.scss'; import classNames from "classnames"; @@ -8,4 +8,6 @@ export const Button = ({ onClick, children, className, disabled, rootRef }) => { {children} ); -}; \ No newline at end of file +}; + +export const ButtonMemoized = memo(Button); diff --git a/src/components/button/styles.module.scss b/src/components/button/styles.module.scss index 9dd5282..3bf2e97 100644 --- a/src/components/button/styles.module.scss +++ b/src/components/button/styles.module.scss @@ -1,5 +1,6 @@ .root { - min-width: 30px; + min-width: fit-content; + width: 30px; cursor: pointer; border: none; border-radius: 10px; diff --git a/src/components/cart/container.jsx b/src/components/cart/container.jsx index bd3f944..ea9c119 100644 --- a/src/components/cart/container.jsx +++ b/src/components/cart/container.jsx @@ -4,6 +4,5 @@ import { selectCartProductIds } from "@/redux/ui/cart"; export const CartContainer = () => { const dishIds = useSelector(selectCartProductIds); - console.log(dishIds); return } \ No newline at end of file diff --git a/src/components/control-tabs/component.jsx b/src/components/control-tabs/component.jsx index 3f736c3..91a035e 100644 --- a/src/components/control-tabs/component.jsx +++ b/src/components/control-tabs/component.jsx @@ -1,19 +1,22 @@ - +"use client" ; import Link from 'next/link'; -import { Button } from '../button/component'; +import { ButtonMemoized } from '../button/component'; import styles from './styles.module.scss'; +import { usePathname } from 'next/navigation'; export const ControlTabs = ({ restaurantId }) => { - return ( -
+ const pathname = usePathname(); + const isActiveMenu = pathname.endsWith("/menu"); + const isActiveReview = pathname.endsWith("/reviews"); + return ( +
- + Menu - - + Review
); diff --git a/src/components/create-review-form/container.jsx b/src/components/create-review-form/container.jsx new file mode 100644 index 0000000..81d0d0e --- /dev/null +++ b/src/components/create-review-form/container.jsx @@ -0,0 +1,15 @@ +"use client"; +import { useContext } from 'react'; +import { UserContext } from "@/context/user-provider"; +import { ReviewForm } from "../review-form/component"; + +export const CreateReviewFormContainer = ({onSave }) => { + + const { name, id } = useContext(UserContext); + + if (!name) { + return null; + } + + return ; +} diff --git a/src/components/dish/cart-container.jsx b/src/components/dish/cart-container.jsx index 5dfc3ac..810e86e 100644 --- a/src/components/dish/cart-container.jsx +++ b/src/components/dish/cart-container.jsx @@ -1,29 +1,30 @@ import style from './styles.module.scss'; -import { Button } from '../button/component'; +import { ButtonMemoized } from '../button/component'; import { useDispatch, useSelector } from 'react-redux'; import { decrement, increment, selectProductAmountById } from '../../redux/ui/cart'; +import { useCallback } from 'react'; export const DishCartContainer = ({ dishId }) => { const amount = useSelector((state) => selectProductAmountById(state, dishId) ); const dispatch = useDispatch(); - const handleDecrement = () => { + + const handleDecrement = useCallback(() => { dispatch(decrement(dishId)); - }; + }, [dispatch, dishId]); - const handleIncrement = () => { + const handleIncrement = useCallback(() => { dispatch(increment(dishId)); - }; - + }, [dispatch, dishId]); return (
{dishId}
- + -

{amount}

- + +
); diff --git a/src/components/dish/component.jsx b/src/components/dish/component.jsx index 857298c..ff3d52d 100644 --- a/src/components/dish/component.jsx +++ b/src/components/dish/component.jsx @@ -1,9 +1,13 @@ +import Link from "next/link"; + export const Dish = ({ dish, className }) => { return (
-
{dish.name}
-
{dish.price}
+ +
{dish.name}
+
{dish.price}
+
); }; diff --git a/src/components/dish/container.jsx b/src/components/dish/container.jsx index 9ad0b4e..d8eac28 100644 --- a/src/components/dish/container.jsx +++ b/src/components/dish/container.jsx @@ -1,10 +1,11 @@ "use client"; import { decrement, increment, selectProductAmountById } from '@/redux/ui/cart'; -import { Button } from '../button/component'; +import { ButtonMemoized } from '../button/component'; import { Dish } from './component'; import styles from './styles.module.scss'; import { useDispatch, useSelector } from 'react-redux'; +import { useCallback } from 'react'; export const DishContainer = ({ dish, className }) => { const amount = useSelector((state) => @@ -12,24 +13,22 @@ export const DishContainer = ({ dish, className }) => { ); const dispatch = useDispatch(); - const handleDecrement = () => { + const handleDecrement = useCallback(() => { dispatch(decrement(dish.id)); - }; + }, [dispatch, dish.id]); - const handleIncrement = () => { + const handleIncrement = useCallback(() => { dispatch(increment(dish.id)); - }; + }, [dispatch, dish.id]); return (
- {/* */} - {/* */}
- + -

{amount}

- + +
); diff --git a/src/components/header/component.jsx b/src/components/header/component.jsx index 51c52f9..f49bf5a 100644 --- a/src/components/header/component.jsx +++ b/src/components/header/component.jsx @@ -1,11 +1,7 @@ import styles from './styles.module.scss'; import Link from 'next/link'; -import classNames from 'classnames'; import { User } from '../user/component'; import { CartButtonContainer } from '../cart-button/container'; -import { useSelector } from 'react-redux'; -import { selectProductAmount } from '@/redux/ui/cart'; - export const Header = () => { return ( @@ -14,10 +10,8 @@ export const Header = () => { Restaurants Contacts About us -
- - -
+ + ); }; \ No newline at end of file diff --git a/src/components/header/styles.module.scss b/src/components/header/styles.module.scss index 84b4228..7f0ca87 100644 --- a/src/components/header/styles.module.scss +++ b/src/components/header/styles.module.scss @@ -7,11 +7,6 @@ padding: 10px 20px; } -.user { - display: flex; - -} - .button { margin-right: 5px; } diff --git a/src/components/ingredients/component.jsx b/src/components/ingredients/component.jsx new file mode 100644 index 0000000..f5115fc --- /dev/null +++ b/src/components/ingredients/component.jsx @@ -0,0 +1,10 @@ + +export const Ingredients = ({ ingredients }) => { + return ( + <> +

Ingredients:

+ {ingredients.map((ingredient, index) => ( +
{ingredient}
+ ))} + +)}; diff --git a/src/components/loader/component.jsx b/src/components/loader/component.jsx index f4401ee..c7656a1 100644 --- a/src/components/loader/component.jsx +++ b/src/components/loader/component.jsx @@ -1,6 +1,6 @@ -import classNames from "classnames"; + import styles from "./styles.module.scss"; -export const Loader = ({className}) => { - return
; +export const Loader = () => { + return
; }; \ No newline at end of file diff --git a/src/components/loader/styles.module.scss b/src/components/loader/styles.module.scss index 41c7b43..3e35dcd 100644 --- a/src/components/loader/styles.module.scss +++ b/src/components/loader/styles.module.scss @@ -1,4 +1,3 @@ - .root { display: flex; width: 100%; diff --git a/src/components/modal-login-form/component.jsx b/src/components/modal-login-form/component.jsx index fe38eea..6164d21 100644 --- a/src/components/modal-login-form/component.jsx +++ b/src/components/modal-login-form/component.jsx @@ -1,8 +1,9 @@ -import { useContext, useEffect, useReducer, useRef } from 'react'; +import { useCallback, useContext, useEffect, useReducer, useRef } from 'react'; import styles from './styles.module.scss'; import { createPortal } from 'react-dom'; -import { Button } from '../button/component'; +import { ButtonMemoized } from '../button/component'; import { UserContext } from '@/context/user-provider'; +import classNames from 'classnames'; const reducer = (state, action) => { @@ -32,22 +33,22 @@ export const Modal = ({ isOpen, onClose }) => { const { name, email } = state; - const handleOkClick = () => { - updateUser({ name, email }); + const handleCancelClick = useCallback(() => { onClose(); - }; + }, [onClose]); - const handleCancelClick = () => { + const handleOkClick = () => { + updateUser({ name, email, id: "a304959a-76c0-4b34-954a-b38dbf310360" }); onClose(); }; - const handleNameChange = (event) => { + const handleNameChange = useCallback((event) => { dispatch({ type: 'change_name', payload: event.target.value }); - }; + }, [dispatch]); - const handleEmailChange = (event) => { + const handleEmailChange = useCallback((event) => { dispatch({ type: 'change_email', payload: event.target.value }); - }; + }, [dispatch]); if (!isOpen) { return null; @@ -58,7 +59,6 @@ export const Modal = ({ isOpen, onClose }) => { <>
-
- - + Cansel + Ok
-
, modalContainer.current) diff --git a/src/components/modal-login-form/styles.module.scss b/src/components/modal-login-form/styles.module.scss index 846d82a..bb2bd8a 100644 --- a/src/components/modal-login-form/styles.module.scss +++ b/src/components/modal-login-form/styles.module.scss @@ -3,6 +3,10 @@ top: 50vh; left: 50vw; transform: translate(-50%, -50%); + color: white; + background: rgb(46, 50, 94); + padding: 15px; + border-radius: 8px; } .overlay { @@ -14,13 +18,6 @@ background-color: rgba(0, 0, 0, 0.395); } -.modal { - color: white; - background: rgb(46, 50, 94); - padding: 15px; - border-radius: 8px; -} - .field { display: flex; justify-content: flex-end; diff --git a/src/components/review-form/component.jsx b/src/components/review-form/component.jsx index d52419f..e7c02e2 100644 --- a/src/components/review-form/component.jsx +++ b/src/components/review-form/component.jsx @@ -1,45 +1,61 @@ +'use client'; +import { useState } from "react"; import { Button } from "../button/component"; import styles from './styles.module.scss'; import { useReviewForm } from "./use-review-form"; +import { Loader } from "../loader/component"; -export const ReviewForm = ({ initialState, onSave, onClose, userName }) => { - const { form, setText, setRating } = useReviewForm(initialState); +export const ReviewForm = ({ initialState, onClose, onSave, userName, userId }) => { + const { form, setText, setRating } = useReviewForm(initialState, userId); + const [isLoading, setIsLoading] = useState(false); + + const handleSave = () => { + setIsLoading(true); + onSave(form).then(() => { + setIsLoading(false); + }).catch((error) => { + setIsLoading(false); + console.error("Error:", error); + }); + onClose(form); + }; return ( -
-
- - Имя: {userName} - -
-
- -