Fixes & commentaries

This commit is contained in:
RailTH
2024-05-09 18:23:47 +11:00
parent 9cfbe9c68a
commit 01fd3c087a
15 changed files with 78 additions and 100 deletions

View File

@@ -1,7 +1,7 @@
{
"files": {
"main.css": "/static/css/main.b9cb408a.css",
"main.js": "/static/js/main.08d74509.js",
"main.js": "/static/js/main.d5c997c3.js",
"static/media/scam-image.png": "/static/media/scam-image.c6c14289dc251ba2d2b1.png",
"static/media/info-page__railth-avatar.png": "/static/media/info-page__railth-avatar.cbf11c43b5ef243b38c0.png",
"static/media/add.webp": "/static/media/add.cd69f1e2a8c91109db0f.webp",
@@ -14,10 +14,10 @@
"static/media/rating__filled-star-icon.svg": "/static/media/rating__filled-star-icon.dc7d908d4d943b7f3b56.svg",
"index.html": "/index.html",
"main.b9cb408a.css.map": "/static/css/main.b9cb408a.css.map",
"main.08d74509.js.map": "/static/js/main.08d74509.js.map"
"main.d5c997c3.js.map": "/static/js/main.d5c997c3.js.map"
},
"entrypoints": [
"static/css/main.b9cb408a.css",
"static/js/main.08d74509.js"
"static/js/main.d5c997c3.js"
]
}

View File

@@ -1 +1 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>SusMarket</title><link rel="manifest" href="/manifest.json"/><script defer="defer" src="/static/js/main.08d74509.js"></script><link href="/static/css/main.b9cb408a.css" rel="stylesheet"></head><body><div id="root"></div></body></html>
<!doctype html><html lang="en"><head><meta charset="utf-8"/><meta name="viewport" content="width=device-width,initial-scale=1"/><title>SusMarket</title><link rel="manifest" href="/manifest.json"/><script defer="defer" src="/static/js/main.d5c997c3.js"></script><link href="/static/css/main.b9cb408a.css" rel="stylesheet"></head><body><div id="root"></div></body></html>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -60,7 +60,7 @@ export default function App() {
{state.isPopupMapVisible && <PopupMap togglePopupMap={togglePopupMap}/>}
<main className="main">
<Routes>
<Route path="/" element={<HomePage products={filteredProducts} selectedCategory={selectedCategory}/>}/>
<Route path="/" element={<HomePage products={filteredProducts}/>}/>
<Route path="profile/*" element={<ProfilePage />}/>
<Route path="product/:id" element={<ProductPage/>}/>
<Route path="payment" element={<PaymentPage />}/>

View File

@@ -8,21 +8,20 @@ interface CatalogMenuProps {
}
export default function CatalogMenu({ toggleCatalogMenu, onSelectCategory }: CatalogMenuProps): JSX.Element {
const [categories, setCategories] = useState<Category[]>([]);
const [categories, setCategories] = useState<Category[]>([]); //состояние для категорий
useEffect(() => {
useEffect(() => { //запрос к api для получения категорий
const fetchCategories = async () => {
try {
try {
const response = await axios.get('http://127.0.0.1:8000/api/get/category');
setCategories(response.data.categories);
console.log(response.data);
} catch (error) {
} catch (error) {
console.error(`There was an error retrieving the data: ${error}`);
}
}
};
fetchCategories();
}, []);
}, []);
return(
<>

View File

@@ -1,13 +1,7 @@
import React from 'react';
import { DeveloperCard } from "../utils/types"
interface DeveloperCardProps {
avatar: string;
name: string;
info: string;
url: string;
}
export default function DevCard({ avatar, name, info, url }: DeveloperCardProps) {
export default function DevCard({ avatar, name, info, url }: DeveloperCard) {
return (
<div className="info-page__dev-card">
<div className="dev-card__inner">

View File

@@ -7,8 +7,8 @@ type ReviewProps = {
review: Reviews;
};
export default function Review({ review }: ReviewProps) {
const readableDate = new Date(review.date).toLocaleDateString('ru-RU');
export default function Review({ review }: ReviewProps) { //соответствие типов данных в review с указанными типами и свойствами в интерфейсе Reviews
const readableDate = new Date(review.date).toLocaleDateString('ru-RU'); //приводит дату отзыва из запроса к api в читаемый вид (чч/мм/гг)
return(
<article className="review-article">

View File

@@ -2,15 +2,14 @@ import React from "react";
import '../HomeStyle.scss';
import ProductCard from "../components/ProductCard";
import Banner from "../components/AdBanner";
import { Product, Category } from "../utils/types";
import { Product } from "../utils/types";
import { Link } from "react-router-dom";
interface HomePageProps {
type HomePageProps = {
products: Product[];
selectedCategory: Category | 'all';
}
export default function HomePage({ products, selectedCategory }: HomePageProps) {
export default function HomePage({ products }: HomePageProps) { //соответствие типов данных в products с указанными типами и свойствами в интерфейсе Product
return(
<section className="home-page">
<Banner />

View File

@@ -2,40 +2,36 @@ import React, { useState } from "react";
import '../PaymentStyle.scss';
export default function PaymentPage() {
let price = 150
const [ccNumber, setCcNumber] = useState(""); //состояние номера кредитной карты
const [valueDate, setValueDate] = useState<number | ''>(''); //состояние даты истечения срока карты
const [valueCode, setValueCode] = useState<number | ''>(''); //состояние кода безопасности карты
const [ccNumber, setCcNumber] = useState("");
const [valueDate, setValueDate] = useState<number | ''>('');
const [valueCode, setValueCode] = useState<number | ''>('');
const formatAndSetCcNumber = (e: React.ChangeEvent<HTMLInputElement>) => {
const inputVal = e.target.value.replace(/ /g, ""); //remove all the empty spaces in the input
let inputNumbersOnly = inputVal.replace(/\D/g, ""); // Get only digits
const formatAndSetCcNumber = (e: React.ChangeEvent<HTMLInputElement>) => { //в ccNumber максимум 16 цифр, разбивка пробелами по 4
const inputVal = e.target.value.replace(/ /g, "");
let inputNumbersOnly = inputVal.replace(/\D/g, "");
if (inputNumbersOnly.length > 16) {
//If entered value has a length greater than 16 then take only the first 16 digits
inputNumbersOnly = inputNumbersOnly.substr(0, 16);
}
// Get nd array of 4 digits per an element EX: ["4242", "4242", ...]
const splits = inputNumbersOnly.match(/.{1,4}/g);
let spacedNumber = "";
if (splits) {
spacedNumber = splits.join(" "); // Join all the splits with an empty space
spacedNumber = splits.join(" ");
}
setCcNumber(spacedNumber); // Set the new CC number
setCcNumber(spacedNumber);
};
const handleChangeDate = (event: React.ChangeEvent<HTMLInputElement>) => {
const handleChangeDate = (event: React.ChangeEvent<HTMLInputElement>) => { //valueDate не более 4-х цифр
const inputValue = event.target.value;
if (inputValue.length <= 4) {
setValueDate(inputValue === '' ? '' : Number(inputValue));
}
};
const handleChangeCode = (event: React.ChangeEvent<HTMLInputElement>) => {
const handleChangeCode = (event: React.ChangeEvent<HTMLInputElement>) => { //valueCode не более 3-х цифр
const inputValue = event.target.value;
if (inputValue.length <= 3) {
setValueCode(inputValue === '' ? '' : Number(inputValue));
@@ -45,7 +41,7 @@ export default function PaymentPage() {
return(
<section className="payment-page">
<h2 className="payment-page__price">
{price}
</h2>
<div className="payment-page__payment-card">
<h3 className="payment-card__heading">

View File

@@ -8,21 +8,29 @@ import ReviewForm from '../components/ReviewForm';
import { useParams } from 'react-router-dom';
export default function ProductPage() {
function trimText(text: string, limit: number) {
function trimText(text: string, limit: number) { //сокращение описания
return text.length > limit ? text.substring(0, limit) + '...' : text;
}
const { id } = useParams();
const [product, setProduct] = useState<Product | null>(null);
const [reviews, setReviews] = useState<Reviews[]>([]);
const [averageRating, setAverageRating] = useState<number>(0);
const [isDataFetched, setIsDataFetched] = useState(false);
const { id } = useParams(); //возвращает id товара из Url
const [product, setProduct] = useState<Product | null>(null); //состояние для данных о товаре
const [reviews, setReviews] = useState<Reviews[]>([]); //состаяние для отзывов
const [averageRating, setAverageRating] = useState<number>(0); //состояние для средней арифметической оценки товара
const [isDataFetched, setIsDataFetched] = useState(false); //состояние для отслеживания кэширования данных из запроса
const totalReviews = reviews.length; //количество отзывов
const countReviewsByRate = (rate: number): number => { //подсчёт отзывов с данной оценкой
return reviews.filter(review => review.rate === rate).length;
};
const percentageOfRate = (rate: number): number => { //расчёт процента отзывов с данной оценкой от количетсва всех отзывов
const count = countReviewsByRate(rate);
return (count / totalReviews) * 100;
};
useEffect(() => {
useEffect(() => { //запрос к api данных о товаре
axios
.get('http://127.0.0.1:8000/api/get/products')
.then(response => {
const productData = response.data.products.find(
const productData = response.data.products.find( //"извлечение" данных о товаре из массива по его id
(item: Product) => item.id.toString() === id
);
setProduct(productData);
@@ -32,15 +40,20 @@ export default function ProductPage() {
});
}, [id]);
useEffect(() => {
if (!isDataFetched) {
useEffect(() => { //запрос к api отзывов у товара
if (!isDataFetched) { //проверка на кэширование данных
axios
.get(`http://127.0.0.1:8000/api/get/reviews/${id}`)
.then(response => {
setReviews(response.data.review);
const totalRating = response.data.review.reduce((acc: number, review: Reviews) => acc + review.rate, 0);
const average = totalRating / response.data.review.length;
setAverageRating(average);
const totalRating = response.data.review.reduce((acc: number, review: Reviews) => acc + review.rate, 0); //общий рейтинг отзывов
const average = totalRating / response.data.review.length; //средннее арифметический рейтинг всех отзывов
if (response.data.review.length > 0) { //проверка на наличие отзывов
setAverageRating(average);
}
else {
setAverageRating(0);
}
setIsDataFetched(true);
})
.catch(error => {
@@ -89,7 +102,7 @@ export default function ProductPage() {
{product.description}
</p>
<ul className="product-page__tags-ul">
{(product.tags.split('|')).map((tag, index) => (
{(product.tags.split('|')).map((tag, index) => ( //разделение тегов
<li key={index} className="product-page__tag-li">
{tag}
</li>
@@ -107,7 +120,7 @@ export default function ProductPage() {
</span>
<div className="rate-block__star-rating">
<div className="star-rating__back-stars">
{'★★★★★'.split('').map((star, i) => (
{'★★★★★'.split('').map((star, i) => ( //пожалуйста, не спрашивайте как это работает
<span key={`back-star-${i}`}>{star}</span>
))}
<div className="star-rating__front-stars" style={{ width: `${(averageRating / 5) * 100}%` }}>
@@ -119,46 +132,16 @@ export default function ProductPage() {
</div>
</div>
<div className='rate-block__progressbars-group'>
<div className='progressbars-group__progressbar-container'>
<span className='rate-progressbar__rate-number'>
5
</span>
<div className='progressbar-container__progressbar'>
<div className='progressbar__active-line'></div>
</div>
{[5, 4, 3, 2, 1].map(rate => (
<div className='progressbars-group__progressbar-container' key={rate}>
<span className='rate-progressbar__rate-number'>
{rate}
</span>
<div className='progressbar-container__progressbar'>
<div className='progressbar__active-line' style={{ width: `${percentageOfRate(rate)}%` }}></div>
</div>
<div className='progressbars-group__progressbar-container'>
<span className='rate-progressbar__rate-number'>
4
</span>
<div className='progressbar-container__progressbar'>
<div className='progressbar__active-line'></div>
</div>
</div>
<div className='progressbars-group__progressbar-container'>
<span className='rate-progressbar__rate-number'>
3
</span>
<div className='progressbar-container__progressbar'>
<div className='progressbar__active-line'></div>
</div>
</div>
<div className='progressbars-group__progressbar-container'>
<span className='rate-progressbar__rate-number'>
2
</span>
<div className='progressbar-container__progressbar'>
<div className='progressbar__active-line'></div>
</div>
</div>
<div className='progressbars-group__progressbar-container'>
<span className='rate-progressbar__rate-number'>
1
</span>
<div className='progressbar-container__progressbar'>
<div className='progressbar__active-line'></div>
</div>
</div>
))}
</div>
</div>
<ReviewForm />

View File

@@ -22,4 +22,11 @@ export interface Reviews {
product_id: number;
rate: number;
user_id: number;
}
export interface DeveloperCard {
avatar: string;
name: string;
info: string;
url: string;
}