diff --git a/.prettierrc.js b/.prettierrc.js index 65e18f5ff..97139a108 100644 --- a/.prettierrc.js +++ b/.prettierrc.js @@ -7,4 +7,5 @@ module.exports = { bracketSpacing: true, arrowParens: "avoid", htmlWhitespaceSensitivity: "ignore", + endOfLine: 'auto' }; diff --git a/README.md b/README.md index 9b90842c4..2c442bea5 100644 --- a/README.md +++ b/README.md @@ -44,3 +44,10 @@ https://skypro-web-developer.github.io/react-memo/ Запускает eslint проверку кода, эта же команда запускается перед каждым коммитом. Если не получается закоммитить, попробуйте запустить эту команду и исправить все ошибки и предупреждения. + +### Оценочное время выполнения + +20 часов + +### Фактическое время выполнения +13ч \ No newline at end of file diff --git a/public/assets/fonts/Poppins-Regular.woff2 b/public/assets/fonts/Poppins-Regular.woff2 new file mode 100644 index 000000000..4aae28cf1 Binary files /dev/null and b/public/assets/fonts/Poppins-Regular.woff2 differ diff --git a/public/assets/fonts/Roboto-Regular.woff2 b/public/assets/fonts/Roboto-Regular.woff2 new file mode 100644 index 000000000..30370cf27 Binary files /dev/null and b/public/assets/fonts/Roboto-Regular.woff2 differ diff --git a/src/api.js b/src/api.js new file mode 100644 index 000000000..606a7f53c --- /dev/null +++ b/src/api.js @@ -0,0 +1,27 @@ +const URL = "https://wedev-api.sky.pro/api/leaderboard"; + +export async function getLeaders() { + const response = await fetch(URL); + + if (response.status !== 200) { + throw new Error("Ошибка"); + } + const data = await response.json(); + return data.leaders; +} + +export async function postLeader(data) { + try { + const response = await fetch("https://wedev-api.sky.pro/api/leaderboard", { + method: "POST", + body: JSON.stringify(data), + }); + if (!response.ok) { + throw new Error(`Ошибка: ${response.status}`); + } + return await response.json(); + } catch (error) { + console.error("Ошибка при отправке данных:", error); + throw error; + } +} diff --git a/src/components/Cards/Cards.jsx b/src/components/Cards/Cards.jsx index 7526a56c8..464596c40 100644 --- a/src/components/Cards/Cards.jsx +++ b/src/components/Cards/Cards.jsx @@ -1,10 +1,12 @@ import { shuffle } from "lodash"; -import { useEffect, useState } from "react"; +import { useContext, useEffect, useState } from "react"; import { generateDeck } from "../../utils/cards"; import styles from "./Cards.module.css"; import { EndGameModal } from "../../components/EndGameModal/EndGameModal"; import { Button } from "../../components/Button/Button"; import { Card } from "../../components/Card/Card"; +import { LightContext } from "../../context/easyMode"; +// import { useNavigate } from "react-router-dom"; // Игра закончилась const STATUS_LOST = "STATUS_LOST"; @@ -41,8 +43,12 @@ function getTimerValue(startDate, endDate) { * previewSeconds - сколько секунд пользователь будет видеть все карты открытыми до начала игры */ export function Cards({ pairsCount = 3, previewSeconds = 5 }) { + const { isLight, tries, setTries } = useContext(LightContext); // В cards лежит игровое поле - массив карт и их состояние открыта\закрыта const [cards, setCards] = useState([]); + + const [playerLost, setPlayerLost] = useState(false); + // Текущий статус игры const [status, setStatus] = useState(STATUS_PREVIEW); @@ -68,7 +74,12 @@ export function Cards({ pairsCount = 3, previewSeconds = 5 }) { setTimer(getTimerValue(startDate, null)); setStatus(STATUS_IN_PROGRESS); } + // const navigate = useNavigate(); + function resetGame() { + // navigate("/"); + setTries(isLight ? 3 : 1); + setPlayerLost(false); setGameStartDate(null); setGameEndDate(null); setTimer(getTimerValue(null, null)); @@ -77,16 +88,26 @@ export function Cards({ pairsCount = 3, previewSeconds = 5 }) { /** * Обработка основного действия в игре - открытие карты. - * После открытия карты игра может пепереходит в следующие состояния + * После открытия карты игра может переходить в следующие состояния * - "Игрок выиграл", если на поле открыты все карты * - "Игрок проиграл", если на поле есть две открытые карты без пары * - "Игра продолжается", если не случилось первых двух условий */ + + useEffect(() => { + if (tries === 0) setPlayerLost(true); + }, [tries, playerLost]); + + useEffect(() => { + if (playerLost) finishGame(STATUS_LOST); + }, [playerLost]); + const openCard = clickedCard => { // Если карта уже открыта, то ничего не делаем if (clickedCard.open) { return; } + // Игровое поле после открытия кликнутой карты const nextCards = cards.map(card => { if (card.id !== clickedCard.id) { @@ -123,13 +144,37 @@ export function Cards({ pairsCount = 3, previewSeconds = 5 }) { return false; }); - const playerLost = openCardsWithoutPair.length >= 2; + function tryLost() { + if (openCardsWithoutPair.length === 2) { + setTries(tries - 1); + setTimeout(() => { + setCards( + cards.reduce((acc, card) => { + if (card.id === clickedCard.id) { + return [...acc, { ...card, open: false }]; + } + return [...acc, card]; + }, []), + ); + setCards( + cards.reduce((acc, card) => { + const previousCard = openCardsWithoutPair.find(item => item.id !== clickedCard.id); + if (card.id === previousCard.id) { + return [...acc, { ...card, open: false }]; + } + return [...acc, card]; + }, []), + ); + }, 1000); + } + } + tryLost(); // "Игрок проиграл", т.к на поле есть две открытые карты без пары - if (playerLost) { - finishGame(STATUS_LOST); - return; - } + // if (lost) { + // finishGame(STATUS_LOST); + // return; + // } // ... игра продолжается }; @@ -195,9 +240,13 @@ export function Cards({ pairsCount = 3, previewSeconds = 5 }) { > )} - {status === STATUS_IN_PROGRESS ? : null} + {status === STATUS_IN_PROGRESS ? ( +
Осталось попыток: {tries}
} +Затраченное время:
-Загрузка...
; + } + + if (error) { + return{error}
; + } + + return ( +Лидерборд
+ + + +Позиция
+Пользователь
+Время
+#{index + 1}
+{leader.name}
+{formatTime(leader.time)}
{} +