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:
RailTH
2024-04-09 15:39:29 +11:00
parent 6db8b00965
commit 8a5d717386
12 changed files with 454 additions and 147 deletions
+25 -15
View File
@@ -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>
)
}
+35 -1
View File
@@ -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>
</>
)
}
+37 -2
View File
@@ -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
+82
View File
@@ -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>
)
}