mirror of
https://github.com/yawaflua/SusMarket.git
synced 2026-04-25 17:20:43 +03:00
Star rate in reviews, login menu & other fixes
Added star rate to reviews, coding login menu, coding review form & other fixes
This commit is contained in:
@@ -3,6 +3,7 @@ import { motion } from "framer-motion";
|
||||
import { Link } from "react-router-dom";
|
||||
import Logotype from "../assets/img/amongasik.png";
|
||||
import CatalogMenu from "./CatalogMenu";
|
||||
import LoginMenu from "./LoginMenu";
|
||||
|
||||
interface HeaderProps {
|
||||
togglePopupMap: () => void;
|
||||
@@ -12,17 +13,32 @@ interface HeaderCatalogMenuState {
|
||||
isCatalogMenuVisible: boolean;
|
||||
}
|
||||
|
||||
interface HeaderLoginMenuState {
|
||||
isLoginMenuVisible: boolean;
|
||||
}
|
||||
|
||||
export default function Header({ togglePopupMap }: HeaderProps): JSX.Element {
|
||||
const [state, setState] = useState<HeaderCatalogMenuState>({
|
||||
const [stateCatalog, setStateCatalog] = useState<HeaderCatalogMenuState>({
|
||||
isCatalogMenuVisible: false,
|
||||
});
|
||||
|
||||
const [stateLogin, setStateLogin] = useState<HeaderLoginMenuState>({
|
||||
isLoginMenuVisible: false,
|
||||
});
|
||||
|
||||
const toggleCatalogMenu = () => {
|
||||
setState((prevState) => ({
|
||||
setStateCatalog((prevState) => ({
|
||||
...prevState,
|
||||
isCatalogMenuVisible: !prevState.isCatalogMenuVisible,
|
||||
}));
|
||||
};
|
||||
|
||||
const toggleLoginMenu = () => {
|
||||
setStateLogin((prevState) => ({
|
||||
...prevState,
|
||||
isLoginMenuVisible: !prevState.isLoginMenuVisible,
|
||||
}));
|
||||
};
|
||||
|
||||
return(
|
||||
<header className="header">
|
||||
@@ -60,18 +76,17 @@ export default function Header({ togglePopupMap }: HeaderProps): JSX.Element {
|
||||
{/* Код для svg */}
|
||||
</div>
|
||||
</form>
|
||||
<Link
|
||||
to="/profile"
|
||||
<motion.button
|
||||
className="header__profile-a"
|
||||
whileTap={{scale: 0.9}}
|
||||
transition={{duration: 0.2, type: "spring"}}
|
||||
onClick={toggleLoginMenu}
|
||||
>
|
||||
{/* Код для svg */}
|
||||
<motion.svg width="48.000000" height="48.000000" viewBox="0 0 48 48" fill="none"
|
||||
whileTap={{scale: 0.9}}
|
||||
transition={{duration: 0.2, type: "spring"}}
|
||||
>
|
||||
<desc>
|
||||
Created with Pixso.
|
||||
</desc>
|
||||
<defs>
|
||||
<clipPath id="clip3_40">
|
||||
<rect id="person_FILL0_wght400_GRAD0_opsz48 1" width="48.000000" height="48.000000" fill="white" fillOpacity="0"/>
|
||||
@@ -83,7 +98,7 @@ export default function Header({ togglePopupMap }: HeaderProps): JSX.Element {
|
||||
</g>
|
||||
</motion.svg>
|
||||
{/* Код для svg */}
|
||||
</Link>
|
||||
</motion.button>
|
||||
<motion.button
|
||||
className="header__popupmap-button"
|
||||
whileTap={{scale: 0.9}}
|
||||
@@ -92,9 +107,6 @@ export default function Header({ togglePopupMap }: HeaderProps): JSX.Element {
|
||||
>
|
||||
{/* Код для svg */}
|
||||
<svg width="48.000000" height="48.000000" viewBox="0 0 48 48" fill="none">
|
||||
<desc>
|
||||
Created with Pixso.
|
||||
</desc>
|
||||
<defs>
|
||||
<clipPath id="clip3_51">
|
||||
<rect id="location_on_FILL0_wght400_GRAD0_opsz48 1" width="48.000000" height="48.000000" fill="white" fillOpacity="0"/>
|
||||
@@ -115,9 +127,6 @@ export default function Header({ togglePopupMap }: HeaderProps): JSX.Element {
|
||||
>
|
||||
{/* Код для svg */}
|
||||
<svg width="48.000000" height="48.000000" viewBox="0 0 48 48" fill="none">
|
||||
<desc>
|
||||
Created with Pixso.
|
||||
</desc>
|
||||
<defs>
|
||||
<clipPath id="clip6_70">
|
||||
<rect id="info_FILL0_wght400_GRAD0_opsz48 1" width="48.000000" height="48.000000" fill="white" fillOpacity="0"/>
|
||||
@@ -131,7 +140,8 @@ export default function Header({ togglePopupMap }: HeaderProps): JSX.Element {
|
||||
{/* Код для svg */}
|
||||
</motion.a>
|
||||
</nav>
|
||||
{state.isCatalogMenuVisible && <CatalogMenu toggleCatalogMenu={toggleCatalogMenu}/>}
|
||||
{stateCatalog.isCatalogMenuVisible && <CatalogMenu toggleCatalogMenu={toggleCatalogMenu}/>}
|
||||
{stateLogin.isLoginMenuVisible && <LoginMenu toggleLoginMenu={toggleLoginMenu}/>}
|
||||
</header>
|
||||
)
|
||||
}
|
||||
@@ -1,8 +1,42 @@
|
||||
import React from "react";
|
||||
import { motion } from "framer-motion";
|
||||
|
||||
export default function LoginMenu() {
|
||||
interface LoginMenuProps {
|
||||
toggleLoginMenu: () => void;
|
||||
}
|
||||
|
||||
export default function LoginMenu({ toggleLoginMenu }: LoginMenuProps): JSX.Element {
|
||||
return(
|
||||
<>
|
||||
<div className="background-blackout" onClick={toggleLoginMenu}></div>
|
||||
<form className="popup-login">
|
||||
<div className="popup-login__top-container">
|
||||
<div className="top-container__headings-text">
|
||||
<h5 className="popup-menu__heading">
|
||||
SusMarket <span>ID</span>
|
||||
</h5>
|
||||
<p className="top-container__text">
|
||||
Войдите с SusMarket ID
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="popup-login__inputs-container">
|
||||
<input type="text" name="userName" id="userName" className="popup-login__name-input" placeholder="Логин"/>
|
||||
<input type="password" name="userPassword" id="userPassword" className="popup-login__password-input" placeholder="Пароль"/>
|
||||
</div>
|
||||
<div className="popup-login__bottom-container">
|
||||
<p className="popup-menu__prompt-url">
|
||||
У вас нет аккаунта? <u>Зарегестрироваться</u>
|
||||
</p>
|
||||
<motion.button
|
||||
className="popup-login__login-button"
|
||||
whileTap={{scale: 0.98}}
|
||||
transition={{duration: 0.2, type: "spring"}}
|
||||
>
|
||||
Войти
|
||||
</motion.button>
|
||||
</div>
|
||||
</form>
|
||||
</>
|
||||
)
|
||||
}
|
||||
@@ -13,9 +13,44 @@ export default function Review() {
|
||||
Святослав Васильев
|
||||
</h4>
|
||||
</div>
|
||||
<div className="review-container__review-info">=
|
||||
<div className="review-container__review-info">
|
||||
<div className="review-info__star-rate">
|
||||
|
||||
<input
|
||||
type="radio"
|
||||
className="star-rate__star-radio"
|
||||
name="review-rating"
|
||||
value={1}
|
||||
aria-label="Плохо"
|
||||
/>
|
||||
<input
|
||||
type="radio"
|
||||
className="star-rate__star-radio"
|
||||
name="review-rating"
|
||||
value={2}
|
||||
aria-label="Удовлетворительно"
|
||||
/>
|
||||
<input
|
||||
type="radio"
|
||||
className="star-rate__star-radio"
|
||||
name="review-rating"
|
||||
value={3}
|
||||
aria-label="Нормально"
|
||||
/>
|
||||
<input
|
||||
type="radio"
|
||||
className="star-rate__star-radio"
|
||||
name="review-rating"
|
||||
value={4}
|
||||
aria-label="Хорошо"
|
||||
/>
|
||||
<input
|
||||
type="radio"
|
||||
className="star-rate__star-radio"
|
||||
name="review-rating"
|
||||
value={5}
|
||||
aria-label="Отлично"
|
||||
checked
|
||||
/>
|
||||
</div>
|
||||
<time className="review-info__review-date" dateTime="2019-09-09">
|
||||
09.09.2019
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
import React, { useState } from 'react';
|
||||
import '../ProductStyle.scss';
|
||||
import ImageAttachIcon from "../assets/icons/review-form__add-image-icon.svg";
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
interface ReviewState {
|
||||
text: string;
|
||||
rating: number;
|
||||
image: File | null;
|
||||
}
|
||||
|
||||
export default function ReviewForm() {
|
||||
const [review, setReview] = useState<ReviewState>({ text: '', rating: 1, image: null });
|
||||
|
||||
function handleTextChange(event: React.ChangeEvent<HTMLTextAreaElement>) {
|
||||
setReview({ ...review, text: event.target.value });
|
||||
}
|
||||
|
||||
function handleRatingChange(event: React.ChangeEvent<HTMLInputElement>) {
|
||||
setReview({ ...review, rating: Number(event.target.value) });
|
||||
}
|
||||
|
||||
function handleImageChange(event: React.ChangeEvent<HTMLInputElement>) {
|
||||
if (event.target.files) {
|
||||
setReview({ ...review, image: event.target.files[0] });
|
||||
}
|
||||
}
|
||||
|
||||
function handleSubmit(event: React.FormEvent) {
|
||||
event.preventDefault();
|
||||
console.log(review);
|
||||
}
|
||||
|
||||
return(
|
||||
<form className='product-page__review-form' onSubmit={handleSubmit}>
|
||||
<h5 className='review-form__heading'>
|
||||
Оставить отзыв
|
||||
</h5>
|
||||
<div className="review-form__stars-container">
|
||||
{[...Array(5)].map((_, index) => (
|
||||
<input
|
||||
key={index}
|
||||
type="radio"
|
||||
className="review-form__star-radio"
|
||||
name="rating"
|
||||
value={index + 1}
|
||||
aria-label={`Рейтинг ${index + 1}`}
|
||||
checked={review.rating === index + 1}
|
||||
onChange={handleRatingChange}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
<textarea
|
||||
className='review-form__textarea'
|
||||
cols={30}
|
||||
rows={5}
|
||||
placeholder='Комментарий'
|
||||
value={review.text}
|
||||
onChange={handleTextChange}
|
||||
/>
|
||||
<label htmlFor="review-image" className='review-form__image-attach'>
|
||||
<img src={ImageAttachIcon} alt="Прикрепить изображение"/>
|
||||
</label>
|
||||
<input
|
||||
className='review-form__image-input'
|
||||
type="file"
|
||||
name="review image"
|
||||
id="review-image"
|
||||
accept='.png, .jpg, .jpeg'
|
||||
onChange={handleImageChange}
|
||||
/>
|
||||
<motion.button
|
||||
className='review-form__send-button'
|
||||
type='submit'
|
||||
whileTap={{scale: 0.98}}
|
||||
transition={{duration: 0.2, type: "spring"}}
|
||||
>
|
||||
Отправить отзыв
|
||||
</motion.button>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user