Star rate in reviews, login menu & other fixes
Added star rate to reviews, coding login menu, coding review form & other fixes
@@ -77,62 +77,12 @@ $accent-color: #EB5E28;
|
||||
border: 2px solid $main-color;
|
||||
border-radius: 12px;
|
||||
|
||||
.rating-div__stars-container {
|
||||
position: relative;
|
||||
width: 150px;
|
||||
height: 30px;
|
||||
background-image: url(assets/icons/rating__star-icon.svg);
|
||||
background-size: 30px auto;
|
||||
background-repeat: repeat-x;
|
||||
|
||||
.rating-div__star-radio {
|
||||
appearance: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.rating-div__star-radio:checked, .rating-div__star-radio:hover {
|
||||
background-image: url(assets/icons/rating__filled-star-icon.svg);
|
||||
background-size: 30px auto;
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
|
||||
.rating-div__star-radio:hover ~ .rating-div__star-radio {
|
||||
background-image: url(assets/icons/rating__star-icon.svg);
|
||||
background-size: 30px auto;
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
|
||||
.rating-div__star-radio:nth-of-type(1) {
|
||||
z-index: 5;
|
||||
width: 30px;
|
||||
}
|
||||
.rating-div__star-radio:nth-of-type(2) {
|
||||
z-index: 4;
|
||||
width: 60px;
|
||||
}
|
||||
.rating-div__star-radio:nth-of-type(3) {
|
||||
z-index: 3;
|
||||
width: 90px;
|
||||
}
|
||||
.rating-div__star-radio:nth-of-type(4) {
|
||||
z-index: 2;
|
||||
width: 120px;
|
||||
}
|
||||
.rating-div__star-radio:nth-of-type(5) {
|
||||
z-index: 1;
|
||||
width: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
.rating-div__rate-value {
|
||||
color: white;
|
||||
font-size: 24px;
|
||||
font-weight: 400;
|
||||
line-height: 29px;
|
||||
letter-spacing: 0%;
|
||||
letter-spacing: 0px;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
@@ -196,7 +146,7 @@ $accent-color: #EB5E28;
|
||||
font-size: 20px;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
letter-spacing: 0%;
|
||||
letter-spacing: 0px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
@@ -215,7 +165,7 @@ $accent-color: #EB5E28;
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
line-height: 29px;
|
||||
letter-spacing: 0%;
|
||||
letter-spacing: 0px;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
@@ -232,16 +182,18 @@ $accent-color: #EB5E28;
|
||||
gap: 20px;
|
||||
margin-top: 48px;
|
||||
width: 310px;
|
||||
|
||||
.rate-block__rating {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20px;
|
||||
|
||||
.rate-block__rate-number {
|
||||
color: white;
|
||||
font-size: 36px;
|
||||
font-weight: 600;
|
||||
line-height: 44px;
|
||||
letter-spacing: 0%;
|
||||
letter-spacing: 0px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
@@ -291,7 +243,7 @@ $accent-color: #EB5E28;
|
||||
font-size: 20px;
|
||||
font-weight: 400;
|
||||
line-height: 24px;
|
||||
letter-spacing: 0%;
|
||||
letter-spacing: 0px;
|
||||
text-align: left;
|
||||
|
||||
.progressbars-group__progressbar-container {
|
||||
@@ -324,10 +276,107 @@ $accent-color: #EB5E28;
|
||||
}
|
||||
}
|
||||
|
||||
.product-page__review-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: 48px;
|
||||
gap: 20px;
|
||||
|
||||
.review-form__heading {
|
||||
color: white;
|
||||
font-size: 26px;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.review-form__stars-container {
|
||||
position: relative;
|
||||
width: 150px;
|
||||
height: 30px;
|
||||
background-image: url(assets/icons/rating__star-icon.svg);
|
||||
background-size: 30px auto;
|
||||
background-repeat: repeat-x;
|
||||
|
||||
.review-form__star-radio {
|
||||
appearance: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.review-form__star-radio:checked, .review-form__star-radio:hover {
|
||||
background-image: url(assets/icons/rating__filled-star-icon.svg);
|
||||
background-size: 30px auto;
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
|
||||
.review-form__star-radio:hover ~ .review-form__star-radio {
|
||||
background-image: url(assets/icons/rating__star-icon.svg);
|
||||
background-size: 30px auto;
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
|
||||
.review-form__star-radio:nth-of-type(1) {
|
||||
z-index: 5;
|
||||
width: 30px;
|
||||
}
|
||||
.review-form__star-radio:nth-of-type(2) {
|
||||
z-index: 4;
|
||||
width: 60px;
|
||||
}
|
||||
.review-form__star-radio:nth-of-type(3) {
|
||||
z-index: 3;
|
||||
width: 90px;
|
||||
}
|
||||
.review-form__star-radio:nth-of-type(4) {
|
||||
z-index: 2;
|
||||
width: 120px;
|
||||
}
|
||||
.review-form__star-radio:nth-of-type(5) {
|
||||
z-index: 1;
|
||||
width: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
.review-form__textarea {
|
||||
width: 100%;
|
||||
border: 2px solid $main-color;
|
||||
border-radius: 15px;
|
||||
color: white;
|
||||
padding: 10px;
|
||||
font-size: 24px;
|
||||
}
|
||||
|
||||
.review-form__image-attach {
|
||||
width: 34px;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.review-form__image-input {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.review-form__send-button {
|
||||
padding: 20px;
|
||||
border-radius: 15px;
|
||||
background-color: $accent-color;
|
||||
font-size: 20px;
|
||||
color: white;
|
||||
font-weight: 500;
|
||||
letter-spacing: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.product-page__reviews-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: 50px;
|
||||
margin-bottom: 30px;
|
||||
gap: 50px;
|
||||
}
|
||||
}
|
||||
@@ -337,7 +386,7 @@ $accent-color: #EB5E28;
|
||||
font-size: 32px;
|
||||
font-weight: 500;
|
||||
line-height: 39px;
|
||||
letter-spacing: 0%;
|
||||
letter-spacing: 0px;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,4 @@
|
||||
<svg width="48.000000" height="48.000000" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<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" fill-opacity="0"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.8 KiB |
@@ -1,7 +1,4 @@
|
||||
<svg width="48.000000" height="48.000000" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<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" fill-opacity="0"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
@@ -1,7 +1,4 @@
|
||||
<svg width="48.000000" height="48.000000" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<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" fill-opacity="0"/>
|
||||
|
||||
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 -960 960 960" width="24"><path d="M720-330q0 104-73 177T470-80q-104 0-177-73t-73-177v-370q0-75 52.5-127.5T400-880q75 0 127.5 52.5T580-700v350q0 46-32 78t-78 32q-46 0-78-32t-32-78v-330q0-17 11.5-28.5T400-720q17 0 28.5 11.5T440-680v330q0 13 8.5 21.5T470-320q13 0 21.5-8.5T500-350v-350q-1-42-29.5-71T400-800q-42 0-71 29t-29 71v370q-1 71 49 120.5T470-160q70 0 119-49.5T640-330v-350q0-17 11.5-28.5T680-720q17 0 28.5 11.5T720-680v350Z" fill="#CCC5B9"/></svg>
|
||||
|
After Width: | Height: | Size: 515 B |
@@ -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
|
||||
|
||||
82
reactapp/src/components/ReviewForm.tsx
Normal 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>
|
||||
)
|
||||
}
|
||||
@@ -340,7 +340,7 @@ body {
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
line-height: 29px;
|
||||
letter-spacing: 0%;
|
||||
letter-spacing: 0px;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
@@ -352,7 +352,53 @@ body {
|
||||
width: 100%;
|
||||
|
||||
.review-info__star-rate {
|
||||
display: flex;
|
||||
position: relative;
|
||||
width: 150px;
|
||||
height: 30px;
|
||||
background-image: url(assets/icons/rating__star-icon.svg);
|
||||
background-size: 30px auto;
|
||||
background-repeat: repeat-x;
|
||||
|
||||
.star-rate__star-radio {
|
||||
appearance: none;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 30px;
|
||||
}
|
||||
|
||||
.star-rate__star-radio:checked, .rating-div__star-radio:hover {
|
||||
background-image: url(assets/icons/rating__filled-star-icon.svg);
|
||||
background-size: 30px auto;
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
|
||||
.star-rate__star-radio:hover ~ .rating-div__star-radio {
|
||||
background-image: url(assets/icons/rating__star-icon.svg);
|
||||
background-size: 30px auto;
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
|
||||
.star-rate__star-radio:nth-of-type(1) {
|
||||
z-index: 5;
|
||||
width: 30px;
|
||||
}
|
||||
.star-rate__star-radio:nth-of-type(2) {
|
||||
z-index: 4;
|
||||
width: 60px;
|
||||
}
|
||||
.star-rate__star-radio:nth-of-type(3) {
|
||||
z-index: 3;
|
||||
width: 90px;
|
||||
}
|
||||
.star-rate__star-radio:nth-of-type(4) {
|
||||
z-index: 2;
|
||||
width: 120px;
|
||||
}
|
||||
.star-rate__star-radio:nth-of-type(5) {
|
||||
z-index: 1;
|
||||
width: 150px;
|
||||
}
|
||||
}
|
||||
|
||||
.review-info__review-date {
|
||||
@@ -360,7 +406,7 @@ body {
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
line-height: 29px;
|
||||
letter-spacing: 0%;
|
||||
letter-spacing: 0px;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
@@ -371,7 +417,7 @@ body {
|
||||
font-size: 24px;
|
||||
font-weight: 400;
|
||||
line-height: 29px;
|
||||
letter-spacing: 0%;
|
||||
letter-spacing: 0px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
@@ -379,4 +425,119 @@ body {
|
||||
max-width: 300px;
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
.popup-login {
|
||||
width: 450px;
|
||||
display: flex;
|
||||
position: fixed;
|
||||
left: 50%;
|
||||
top: 108px;
|
||||
transform:translateX(-50%);
|
||||
flex-direction: column;
|
||||
gap: 40px;
|
||||
padding: 30px;
|
||||
box-sizing: border-box;
|
||||
border-radius: 20px;
|
||||
box-shadow: 4px 4px 10px 0px rgba(0, 0, 0, 0.25);
|
||||
background: $background-color;
|
||||
|
||||
.popup-login__top-container {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
.popup-login__close-button {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 50px;
|
||||
background: rgb(53, 52, 49);
|
||||
}
|
||||
|
||||
.top-container__headings-text {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
|
||||
.popup-menu__heading {
|
||||
color: white;
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
line-height: 29px;
|
||||
letter-spacing: 0px;
|
||||
text-align: left;
|
||||
|
||||
span {
|
||||
color: $accent-color;
|
||||
}
|
||||
}
|
||||
|
||||
.top-container__text {
|
||||
color: $main-color;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
line-height: 20px;
|
||||
letter-spacing: 0px;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.popup-login__inputs-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
width: 100%;
|
||||
|
||||
.popup-login__name-input, .popup-login__password-input {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
height: 70px;
|
||||
align-items: center;
|
||||
padding: 0px 20px;
|
||||
box-sizing: border-box;
|
||||
border: 2px solid $main-color;
|
||||
border-radius: 15px;
|
||||
color: white;
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
line-height: 29px;
|
||||
letter-spacing: 0px;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
.popup-login__bottom-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 20px;
|
||||
|
||||
.popup-menu__prompt-url {
|
||||
color: $main-color;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
line-height: 20px;
|
||||
letter-spacing: 0px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.popup-login__login-button {
|
||||
width: 100%;
|
||||
height: 70px;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
border-radius: 15px;
|
||||
background: rgb(235, 94, 40);
|
||||
color: white;
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
line-height: 29px;
|
||||
letter-spacing: 0%;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,15 @@
|
||||
import React, { useState } from 'react';
|
||||
import React from 'react';
|
||||
import Review from '../components/Review';
|
||||
import '../ProductStyle.scss';
|
||||
import ProductImage from "../assets/img/product-image-1.webp";
|
||||
import ShareIcon from "../assets/icons/share-icon.svg";
|
||||
import ReviewForm from '../components/ReviewForm';
|
||||
|
||||
interface StarRatingProps {
|
||||
value: number;
|
||||
}
|
||||
|
||||
export default function ProductPage({ value }: StarRatingProps) {
|
||||
const [selectedRating, setSelectedRating] = useState(1);
|
||||
|
||||
const handleRatingChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
||||
setSelectedRating(Number(event.target.value));
|
||||
};
|
||||
|
||||
return(
|
||||
<section className="product-page">
|
||||
<section className="product-page__main-section">
|
||||
@@ -32,54 +27,6 @@ export default function ProductPage({ value }: StarRatingProps) {
|
||||
</span>
|
||||
<div className="product-page__container-div">
|
||||
<div className="product-page__rating-share-div">
|
||||
<div className="product-page__rating-div">
|
||||
<div className="rating-div__stars-container">
|
||||
<input
|
||||
type="radio"
|
||||
className="rating-div__star-radio"
|
||||
name="rating" value={1}
|
||||
aria-label="Плохо"
|
||||
checked={selectedRating === 1}
|
||||
onChange={handleRatingChange}
|
||||
/>
|
||||
<input
|
||||
type="radio"
|
||||
className="rating-div__star-radio"
|
||||
name="rating" value={2}
|
||||
aria-label="Удовлетворительно"
|
||||
checked={selectedRating === 2}
|
||||
onChange={handleRatingChange}
|
||||
/>
|
||||
<input
|
||||
type="radio"
|
||||
className="rating-div__star-radio"
|
||||
name="rating" value={3}
|
||||
aria-label="Нормально" checked={selectedRating === 3}
|
||||
onChange={handleRatingChange}
|
||||
/>
|
||||
<input
|
||||
type="radio"
|
||||
className="rating-div__star-radio"
|
||||
name="rating"
|
||||
value={4}
|
||||
aria-label="Хорошо"
|
||||
checked={selectedRating === 4}
|
||||
onChange={handleRatingChange}
|
||||
/>
|
||||
<input
|
||||
type="radio"
|
||||
className="rating-div__star-radio"
|
||||
name="rating"
|
||||
value={5}
|
||||
aria-label="Отлично"
|
||||
checked={selectedRating === 5}
|
||||
onChange={handleRatingChange}
|
||||
/>
|
||||
</div>
|
||||
<span className="rating-div__rate-value">
|
||||
{selectedRating}
|
||||
</span>
|
||||
</div>
|
||||
<button className="product-page__share-button">
|
||||
<img src={ShareIcon as unknown as string} alt="" />
|
||||
</button>
|
||||
@@ -182,12 +129,9 @@ export default function ProductPage({ value }: StarRatingProps) {
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<ReviewForm />
|
||||
<div className='product-page__reviews-container'>
|
||||
<Review />
|
||||
<Review />
|
||||
<Review />
|
||||
<Review />
|
||||
<Review />
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
|
||||
2
reactapp/src/utils/custom.d.ts
vendored
@@ -1,5 +1,5 @@
|
||||
declare module "*.svg" {
|
||||
const content: React.FunctionComponent<React.SVGAttributes<SVGElement>>;
|
||||
const content: any;
|
||||
export default content;
|
||||
}
|
||||
|
||||
|
||||