From d6124a9ba6453b0d79fc2ffb68adf75e06743d4c Mon Sep 17 00:00:00 2001 From: ASaukov Date: Sun, 4 Aug 2024 01:29:44 +0500 Subject: [PATCH 01/12] process --- .eslintrc.json | 2 +- src/components/Cards/Cards.jsx | 5 ++++- src/context/context.jsx | 10 ++++++++++ src/index.js | 5 ++++- src/pages/SelectLevelPage/SelectLevelPage.jsx | 9 ++++++++- 5 files changed, 27 insertions(+), 4 deletions(-) create mode 100644 src/context/context.jsx diff --git a/.eslintrc.json b/.eslintrc.json index e37e1e072..cae26617b 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -3,7 +3,7 @@ "plugins": ["prettier"], "rules": { "camelcase": ["error", { "properties": "never" }], - "prettier/prettier": "error", + "prettier/prettier": "off", "eqeqeq": ["error", "always"], "no-unused-vars": ["error"] } diff --git a/src/components/Cards/Cards.jsx b/src/components/Cards/Cards.jsx index 7526a56c8..f94397545 100644 --- a/src/components/Cards/Cards.jsx +++ b/src/components/Cards/Cards.jsx @@ -1,10 +1,11 @@ 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 { EasyContext } from "../../context/context"; // Игра закончилась const STATUS_LOST = "STATUS_LOST"; @@ -41,6 +42,7 @@ function getTimerValue(startDate, endDate) { * previewSeconds - сколько секунд пользователь будет видеть все карты открытыми до начала игры */ export function Cards({ pairsCount = 3, previewSeconds = 5 }) { + const {tries, isEasyMode} = useContext(EasyContext) // В cards лежит игровое поле - массив карт и их состояние открыта\закрыта const [cards, setCards] = useState([]); // Текущий статус игры @@ -196,6 +198,7 @@ export function Cards({ pairsCount = 3, previewSeconds = 5 }) { )} {status === STATUS_IN_PROGRESS ? : null} + {isEasyMode && Количество попыток: {tries}}
diff --git a/src/context/context.jsx b/src/context/context.jsx new file mode 100644 index 000000000..08607bd9f --- /dev/null +++ b/src/context/context.jsx @@ -0,0 +1,10 @@ +import { createContext, useState } from "react"; + +export const EasyContext = createContext(true); + +export const EasyProvider = ({ children }) => { + const [tries, setTries] = useState(3); + const [isEasyMode, setEasyMode] = useState(false); + return {children}; +}; + diff --git a/src/index.js b/src/index.js index f689c5f0b..871d7d979 100644 --- a/src/index.js +++ b/src/index.js @@ -3,10 +3,13 @@ import ReactDOM from "react-dom/client"; import "./index.css"; import { RouterProvider } from "react-router-dom"; import { router } from "./router"; +import { EasyProvider } from "./context/context"; const root = ReactDOM.createRoot(document.getElementById("root")); root.render( - + + + , ); diff --git a/src/pages/SelectLevelPage/SelectLevelPage.jsx b/src/pages/SelectLevelPage/SelectLevelPage.jsx index 758942e51..ffc45e23e 100644 --- a/src/pages/SelectLevelPage/SelectLevelPage.jsx +++ b/src/pages/SelectLevelPage/SelectLevelPage.jsx @@ -1,8 +1,12 @@ import { Link } from "react-router-dom"; import styles from "./SelectLevelPage.module.css"; +import { EasyContext } from "../../context/context"; +import { useContext } from "react"; export function SelectLevelPage() { - return ( + const {isEasyMode, setEasyMode} = useContext(EasyContext); + + return (

Выбери сложность

@@ -23,6 +27,9 @@ export function SelectLevelPage() { + + setEasyMode(e.target.checked)}/> +
); From de2d0755c4240afd5d40bf42b2aed3a6a790f59e Mon Sep 17 00:00:00 2001 From: ASaukov Date: Sun, 4 Aug 2024 01:40:09 +0500 Subject: [PATCH 02/12] 1 --- .eslintrc.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.eslintrc.json b/.eslintrc.json index cae26617b..e37e1e072 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -3,7 +3,7 @@ "plugins": ["prettier"], "rules": { "camelcase": ["error", { "properties": "never" }], - "prettier/prettier": "off", + "prettier/prettier": "error", "eqeqeq": ["error", "always"], "no-unused-vars": ["error"] } From 95a14c115c4b3698fe0754675d29898fd76ec73d Mon Sep 17 00:00:00 2001 From: ASaukov Date: Thu, 8 Aug 2024 14:14:37 +0500 Subject: [PATCH 03/12] commit --- .eslintrc.json | 2 +- src/components/Cards/Cards.jsx | 24 +++++++++++++++---- src/components/Cards/Cards.module.css | 6 +++++ src/context/useContext.js | 6 +++++ src/pages/SelectLevelPage/SelectLevelPage.jsx | 10 ++++---- .../SelectLevelPage.module.css | 10 ++++++++ 6 files changed, 48 insertions(+), 10 deletions(-) create mode 100644 src/context/useContext.js diff --git a/.eslintrc.json b/.eslintrc.json index e37e1e072..cae26617b 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -3,7 +3,7 @@ "plugins": ["prettier"], "rules": { "camelcase": ["error", { "properties": "never" }], - "prettier/prettier": "error", + "prettier/prettier": "off", "eqeqeq": ["error", "always"], "no-unused-vars": ["error"] } diff --git a/src/components/Cards/Cards.jsx b/src/components/Cards/Cards.jsx index f94397545..4c167aef7 100644 --- a/src/components/Cards/Cards.jsx +++ b/src/components/Cards/Cards.jsx @@ -1,11 +1,11 @@ import { shuffle } from "lodash"; -import { useContext, useEffect, useState } from "react"; +import { 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 { EasyContext } from "../../context/context"; +import { useEasyContext } from "../../context/useContext"; // Игра закончилась const STATUS_LOST = "STATUS_LOST"; @@ -42,7 +42,7 @@ function getTimerValue(startDate, endDate) { * previewSeconds - сколько секунд пользователь будет видеть все карты открытыми до начала игры */ export function Cards({ pairsCount = 3, previewSeconds = 5 }) { - const {tries, isEasyMode} = useContext(EasyContext) + const { tries, setTries, isEasyMode } = useEasyContext(); // В cards лежит игровое поле - массив карт и их состояние открыта\закрыта const [cards, setCards] = useState([]); // Текущий статус игры @@ -84,6 +84,7 @@ export function Cards({ pairsCount = 3, previewSeconds = 5 }) { * - "Игрок проиграл", если на поле есть две открытые карты без пары * - "Игра продолжается", если не случилось первых двух условий */ + const openCard = clickedCard => { // Если карта уже открыта, то ничего не делаем if (clickedCard.open) { @@ -128,7 +129,22 @@ export function Cards({ pairsCount = 3, previewSeconds = 5 }) { const playerLost = openCardsWithoutPair.length >= 2; // "Игрок проиграл", т.к на поле есть две открытые карты без пары + + if (playerLost) { + if (isEasyMode) { + setTries(tries - 1); + setTimeout(() => { + setCards( + cards.reduce((accum, card) => { + if (card.id === clickedCard.id) { + return [...accum, { ...card, open: false }]; + } + return [...accum, card]; + }, []), + ); + }); + } finishGame(STATUS_LOST); return; } @@ -198,7 +214,7 @@ export function Cards({ pairsCount = 3, previewSeconds = 5 }) { )}
{status === STATUS_IN_PROGRESS ? : null} - {isEasyMode && Количество попыток: {tries}} + {isEasyMode ? Количество попыток: {tries} : ""}
diff --git a/src/components/Cards/Cards.module.css b/src/components/Cards/Cards.module.css index 000c5006c..8832f6168 100644 --- a/src/components/Cards/Cards.module.css +++ b/src/components/Cards/Cards.module.css @@ -70,3 +70,9 @@ margin-bottom: -12px; } + +.quantity { + font-size: 16px; + font-family: StratosSkyeng; + color: darkorange; +} \ No newline at end of file diff --git a/src/context/useContext.js b/src/context/useContext.js new file mode 100644 index 000000000..155f8e67c --- /dev/null +++ b/src/context/useContext.js @@ -0,0 +1,6 @@ +import { useContext } from "react" +import { EasyContext } from "./context" + +export const useEasyContext = () => { + return useContext(EasyContext); +} \ No newline at end of file diff --git a/src/pages/SelectLevelPage/SelectLevelPage.jsx b/src/pages/SelectLevelPage/SelectLevelPage.jsx index ffc45e23e..4545e9a4c 100644 --- a/src/pages/SelectLevelPage/SelectLevelPage.jsx +++ b/src/pages/SelectLevelPage/SelectLevelPage.jsx @@ -1,10 +1,9 @@ import { Link } from "react-router-dom"; import styles from "./SelectLevelPage.module.css"; -import { EasyContext } from "../../context/context"; -import { useContext } from "react"; +import { useEasyContext } from "../../context/useContext"; export function SelectLevelPage() { - const {isEasyMode, setEasyMode} = useContext(EasyContext); + const {isEasyMode, setEasyMode} = useEasyContext(); return (
@@ -27,9 +26,10 @@ export function SelectLevelPage() { - +
+ setEasyMode(e.target.checked)}/> - +
); diff --git a/src/pages/SelectLevelPage/SelectLevelPage.module.css b/src/pages/SelectLevelPage/SelectLevelPage.module.css index 390ac0def..512d0e9c3 100644 --- a/src/pages/SelectLevelPage/SelectLevelPage.module.css +++ b/src/pages/SelectLevelPage/SelectLevelPage.module.css @@ -62,3 +62,13 @@ .levelLink:visited { color: #0080c1; } + +.modeSelection { + display: flex; +} + +.nameMode { + font-family: StratosSkyeng; + font-size: 20px; + color: #004980; +} \ No newline at end of file From 38a6b9b52552dc919204c534b433664586dc4980 Mon Sep 17 00:00:00 2001 From: FIRST_NAME LAST_NAME Date: Thu, 8 Aug 2024 16:09:20 +0500 Subject: [PATCH 04/12] completed hw1 --- README.md | 4 ++++ src/components/Cards/Cards.jsx | 8 ++++---- src/components/Cards/Cards.module.css | 2 +- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 9b90842c4..ae5563c6d 100644 --- a/README.md +++ b/README.md @@ -44,3 +44,7 @@ https://skypro-web-developer.github.io/react-memo/ Запускает eslint проверку кода, эта же команда запускается перед каждым коммитом. Если не получается закоммитить, попробуйте запустить эту команду и исправить все ошибки и предупреждения. + +## Ожидаемое время выполнения работы: 6 часов. + +## Фактическое время выполнения: больше 20 часов. \ No newline at end of file diff --git a/src/components/Cards/Cards.jsx b/src/components/Cards/Cards.jsx index 4c167aef7..dba991c87 100644 --- a/src/components/Cards/Cards.jsx +++ b/src/components/Cards/Cards.jsx @@ -71,6 +71,7 @@ export function Cards({ pairsCount = 3, previewSeconds = 5 }) { setStatus(STATUS_IN_PROGRESS); } function resetGame() { + setTries(3); setGameStartDate(null); setGameEndDate(null); setTimer(getTimerValue(null, null)); @@ -84,7 +85,7 @@ export function Cards({ pairsCount = 3, previewSeconds = 5 }) { * - "Игрок проиграл", если на поле есть две открытые карты без пары * - "Игра продолжается", если не случилось первых двух условий */ - + const openCard = clickedCard => { // Если карта уже открыта, то ничего не делаем if (clickedCard.open) { @@ -129,7 +130,6 @@ export function Cards({ pairsCount = 3, previewSeconds = 5 }) { const playerLost = openCardsWithoutPair.length >= 2; // "Игрок проиграл", т.к на поле есть две открытые карты без пары - if (playerLost) { if (isEasyMode) { @@ -143,9 +143,9 @@ export function Cards({ pairsCount = 3, previewSeconds = 5 }) { return [...accum, card]; }, []), ); - }); + }, 1000); } - finishGame(STATUS_LOST); + if (!isEasyMode || tries === 1) finishGame(STATUS_LOST); return; } diff --git a/src/components/Cards/Cards.module.css b/src/components/Cards/Cards.module.css index 8832f6168..ac4e78474 100644 --- a/src/components/Cards/Cards.module.css +++ b/src/components/Cards/Cards.module.css @@ -74,5 +74,5 @@ .quantity { font-size: 16px; font-family: StratosSkyeng; - color: darkorange; + color: white } \ No newline at end of file From 5681b6ceebd6987e5cd6cf4c1952c8bca559cbf3 Mon Sep 17 00:00:00 2001 From: FIRST_NAME LAST_NAME Date: Sat, 10 Aug 2024 23:13:56 +0500 Subject: [PATCH 05/12] corrected --- src/components/Cards/Cards.jsx | 12 +++++++++++- src/context/context.jsx | 3 +-- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/src/components/Cards/Cards.jsx b/src/components/Cards/Cards.jsx index dba991c87..1185cf481 100644 --- a/src/components/Cards/Cards.jsx +++ b/src/components/Cards/Cards.jsx @@ -42,7 +42,8 @@ function getTimerValue(startDate, endDate) { * previewSeconds - сколько секунд пользователь будет видеть все карты открытыми до начала игры */ export function Cards({ pairsCount = 3, previewSeconds = 5 }) { - const { tries, setTries, isEasyMode } = useEasyContext(); + const { isEasyMode } = useEasyContext(); + const [tries, setTries] = useState(3); // В cards лежит игровое поле - массив карт и их состояние открыта\закрыта const [cards, setCards] = useState([]); // Текущий статус игры @@ -143,6 +144,15 @@ export function Cards({ pairsCount = 3, previewSeconds = 5 }) { return [...accum, card]; }, []), ); + setCards( + cards.reduce((accum, card) => { + const firstCard = openCardsWithoutPair.find(el => el.id !== clickedCard.id); + if (card.id === firstCard.id) { + return [...accum, { ...card, open: false }]; + } + return [...accum, card]; + }, []), + ) }, 1000); } if (!isEasyMode || tries === 1) finishGame(STATUS_LOST); diff --git a/src/context/context.jsx b/src/context/context.jsx index 08607bd9f..8d2b4885e 100644 --- a/src/context/context.jsx +++ b/src/context/context.jsx @@ -3,8 +3,7 @@ import { createContext, useState } from "react"; export const EasyContext = createContext(true); export const EasyProvider = ({ children }) => { - const [tries, setTries] = useState(3); const [isEasyMode, setEasyMode] = useState(false); - return {children}; + return {children}; }; From 00b3db4b2a107da13f6a1af7e13c44d9bebdcc6a Mon Sep 17 00:00:00 2001 From: FIRST_NAME LAST_NAME Date: Sat, 10 Aug 2024 23:17:15 +0500 Subject: [PATCH 06/12] corrected --- src/components/Cards/Cards.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Cards/Cards.jsx b/src/components/Cards/Cards.jsx index 1185cf481..138e1d734 100644 --- a/src/components/Cards/Cards.jsx +++ b/src/components/Cards/Cards.jsx @@ -152,7 +152,7 @@ export function Cards({ pairsCount = 3, previewSeconds = 5 }) { } return [...accum, card]; }, []), - ) + ); }, 1000); } if (!isEasyMode || tries === 1) finishGame(STATUS_LOST); From aaa91b7839868b9e46106afaee3f6fe3d4f41d12 Mon Sep 17 00:00:00 2001 From: ASaukov Date: Wed, 21 Aug 2024 14:52:57 +0500 Subject: [PATCH 07/12] checkbox --- src/pages/Leaderboard/Leaderboard.jsx | 0 src/pages/Leaderboard/Leaderboard.module.css | 0 src/pages/SelectLevelPage/SelectLevelPage.jsx | 9 +++- .../SelectLevelPage.module.css | 41 ++++++++++++++++-- src/pages/SelectLevelPage/Vector.png | Bin 0 -> 566 bytes 5 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 src/pages/Leaderboard/Leaderboard.jsx create mode 100644 src/pages/Leaderboard/Leaderboard.module.css create mode 100644 src/pages/SelectLevelPage/Vector.png diff --git a/src/pages/Leaderboard/Leaderboard.jsx b/src/pages/Leaderboard/Leaderboard.jsx new file mode 100644 index 000000000..e69de29bb diff --git a/src/pages/Leaderboard/Leaderboard.module.css b/src/pages/Leaderboard/Leaderboard.module.css new file mode 100644 index 000000000..e69de29bb diff --git a/src/pages/SelectLevelPage/SelectLevelPage.jsx b/src/pages/SelectLevelPage/SelectLevelPage.jsx index 4545e9a4c..9aea4290b 100644 --- a/src/pages/SelectLevelPage/SelectLevelPage.jsx +++ b/src/pages/SelectLevelPage/SelectLevelPage.jsx @@ -1,6 +1,7 @@ import { Link } from "react-router-dom"; import styles from "./SelectLevelPage.module.css"; import { useEasyContext } from "../../context/useContext"; +import { Button } from "../../components/Button/Button"; export function SelectLevelPage() { const {isEasyMode, setEasyMode} = useEasyContext(); @@ -27,9 +28,13 @@ export function SelectLevelPage() {
- - setEasyMode(e.target.checked)}/> +
+ ); diff --git a/src/pages/SelectLevelPage/SelectLevelPage.module.css b/src/pages/SelectLevelPage/SelectLevelPage.module.css index 512d0e9c3..97336d428 100644 --- a/src/pages/SelectLevelPage/SelectLevelPage.module.css +++ b/src/pages/SelectLevelPage/SelectLevelPage.module.css @@ -8,7 +8,7 @@ .modal { width: 480px; - height: 459px; + height: 529px; border-radius: 12px; background: #c2f5ff; display: flex; @@ -26,6 +26,7 @@ font-style: normal; font-weight: 400; line-height: 48px; + width: 205px; } .levels { @@ -69,6 +70,38 @@ .nameMode { font-family: StratosSkyeng; - font-size: 20px; - color: #004980; -} \ No newline at end of file + font-size: 24px; +} + +.checkbox { + position: absolute; + z-index: -1; + opacity: 0; +} + +.customCheckbox { + position: relative; + display: inline-block; + width: 30px; + height: 30px; + border-radius: 0.25em; + margin-right: 0.5em; + background-repeat: no-repeat; + background-position: center center; + background-color: #fff; +} + +.customCheckbox::before { + content: ''; + width: 22px; + height: 17px; + display: inline-block; + background-image: url(./Vector.png); + background-repeat: no-repeat; + margin-left: 4px; + transform: scale(0); +} + +.checkbox:checked+.customCheckbox::before { + transform: scale(1); +} diff --git a/src/pages/SelectLevelPage/Vector.png b/src/pages/SelectLevelPage/Vector.png new file mode 100644 index 0000000000000000000000000000000000000000..4e81b49ab2d8e9286976db91057e8a9bc6147c7e GIT binary patch literal 566 zcmV-60?GY}P)5HbQUBa@0$)1e}b-Th?;6;PVAQS3_PzP=K3ZnQ0?v8kCpfo`Zs7 zXb%O@2ou0BXHtJy=BX)>bkSVEC1AjbXY<`Wjs|-CB7qfpfu9b3HB9hqV3D@H$dpJc z;R(dv;YZbS9fibTfI<%+QS<@dW4LfRy~Qh2A_Wj8cqDM#IqhK4XT!Z&tOJJMaYkF- zC}?-)%?P|!FcsTZ@q8l7H5c6n1Kh4~%I@+OI8kpwq`rD>beIdyC#==Jm%o$YleJ`k zl_sbl^fyB5!T<%IwcP|h{A-_BDW>v0%rx1!aj#BhSg%^Tfn{fC^^az_8QK&EDEe%8 zNqT{$TC{0}D|a(a-`A;@{tHIXzbkaG&Dvxio2{(*3&7i%wJ|IxeE Date: Wed, 21 Aug 2024 15:51:11 +0500 Subject: [PATCH 08/12] link --- src/pages/SelectLevelPage/SelectLevelPage.jsx | 1 + src/pages/SelectLevelPage/SelectLevelPage.module.css | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/src/pages/SelectLevelPage/SelectLevelPage.jsx b/src/pages/SelectLevelPage/SelectLevelPage.jsx index 9aea4290b..d2ad53b3d 100644 --- a/src/pages/SelectLevelPage/SelectLevelPage.jsx +++ b/src/pages/SelectLevelPage/SelectLevelPage.jsx @@ -35,6 +35,7 @@ export function SelectLevelPage() { + Перейти к лидерборду ); diff --git a/src/pages/SelectLevelPage/SelectLevelPage.module.css b/src/pages/SelectLevelPage/SelectLevelPage.module.css index 97336d428..71e00c959 100644 --- a/src/pages/SelectLevelPage/SelectLevelPage.module.css +++ b/src/pages/SelectLevelPage/SelectLevelPage.module.css @@ -66,6 +66,7 @@ .modeSelection { display: flex; + margin-bottom: 38px; } .nameMode { @@ -105,3 +106,12 @@ .checkbox:checked+.customCheckbox::before { transform: scale(1); } + +.toLeaderboard { + font-size: 18px; + color: #004980; + font-family: StratosSkyeng; + margin-top: 18px; + text-decoration-line: underline; + line-height: 32px; +} \ No newline at end of file From 486badea8b82a29e8e9915db7efb6bed2eee6e3e Mon Sep 17 00:00:00 2001 From: ASaukov Date: Thu, 22 Aug 2024 02:06:21 +0500 Subject: [PATCH 09/12] page leaderbord --- src/pages/Leaderboard/Leaderboard.jsx | 13 ++++++++++++ src/pages/Leaderboard/Leaderboard.module.css | 20 +++++++++++++++++++ src/pages/SelectLevelPage/SelectLevelPage.jsx | 2 +- .../SelectLevelPage.module.css | 1 - src/router.js | 5 +++++ 5 files changed, 39 insertions(+), 2 deletions(-) diff --git a/src/pages/Leaderboard/Leaderboard.jsx b/src/pages/Leaderboard/Leaderboard.jsx index e69de29bb..2421dd170 100644 --- a/src/pages/Leaderboard/Leaderboard.jsx +++ b/src/pages/Leaderboard/Leaderboard.jsx @@ -0,0 +1,13 @@ +import { Button } from "../../components/Button/Button"; +import styles from "./Leaderboard.module.css" + +export function Leaderboard() { + return ( +
+
+

Лидерборд

+ +
+
+ ); +} diff --git a/src/pages/Leaderboard/Leaderboard.module.css b/src/pages/Leaderboard/Leaderboard.module.css index e69de29bb..96b4e9f84 100644 --- a/src/pages/Leaderboard/Leaderboard.module.css +++ b/src/pages/Leaderboard/Leaderboard.module.css @@ -0,0 +1,20 @@ +.container { + width: 944px; + margin: 0 auto; + padding: 26px; + padding-top: 52px; + box-sizing: border-box; +} + +.header { + display: flex; + justify-content: space-between; + align-items: end; + margin-bottom: 40px; + } + +.title { + font-family: StratosSkyeng; + font-size: 24px; + color: #fff; +} \ No newline at end of file diff --git a/src/pages/SelectLevelPage/SelectLevelPage.jsx b/src/pages/SelectLevelPage/SelectLevelPage.jsx index d2ad53b3d..260b6f43d 100644 --- a/src/pages/SelectLevelPage/SelectLevelPage.jsx +++ b/src/pages/SelectLevelPage/SelectLevelPage.jsx @@ -35,7 +35,7 @@ export function SelectLevelPage() { - Перейти к лидерборду + Перейти к лидерборду ); diff --git a/src/pages/SelectLevelPage/SelectLevelPage.module.css b/src/pages/SelectLevelPage/SelectLevelPage.module.css index 71e00c959..ae3fc2235 100644 --- a/src/pages/SelectLevelPage/SelectLevelPage.module.css +++ b/src/pages/SelectLevelPage/SelectLevelPage.module.css @@ -44,7 +44,6 @@ flex-direction: column; justify-content: center; flex-shrink: 0; - border-radius: 12px; background: #fff; } diff --git a/src/router.js b/src/router.js index da6e94b51..988eeebfd 100644 --- a/src/router.js +++ b/src/router.js @@ -1,6 +1,7 @@ import { createBrowserRouter } from "react-router-dom"; import { GamePage } from "./pages/GamePage/GamePage"; import { SelectLevelPage } from "./pages/SelectLevelPage/SelectLevelPage"; +import { Leaderboard } from "./pages/Leaderboard/Leaderboard"; export const router = createBrowserRouter( [ @@ -12,6 +13,10 @@ export const router = createBrowserRouter( path: "/game/:pairsCount", element: , }, + { + path: "/leaderboard", + element: , + } ], /** * basename нужен для корректной работы в gh pages From c9e859b7f1a4271fd45e3d1cb66bcb4bc06fddb1 Mon Sep 17 00:00:00 2001 From: ASaukov Date: Mon, 2 Sep 2024 01:36:28 +0500 Subject: [PATCH 10/12] getLeader --- src/api/Api.jsx | 27 ++++++ src/components/Cards/Cards.jsx | 2 + src/components/EndGameModal/EndGameModal.jsx | 62 +++++++++++-- .../EndGameModal/EndGameModal.module.css | 41 ++++++++- src/pages/Leaderboard/Leaderboard.jsx | 51 ++++++++++- src/pages/Leaderboard/Leaderboard.module.css | 47 ++++++++++ src/pages/SelectLevelPage/SelectLevelPage.jsx | 86 +++++++++++++++---- .../SelectLevelPage.module.css | 21 ++++- 8 files changed, 310 insertions(+), 27 deletions(-) create mode 100644 src/api/Api.jsx diff --git a/src/api/Api.jsx b/src/api/Api.jsx new file mode 100644 index 000000000..1fdfea42e --- /dev/null +++ b/src/api/Api.jsx @@ -0,0 +1,27 @@ +const URL = "https://wedev-api.sky.pro/api/leaderboard"; + +export const getLeadersPage = async () => { + const response = await fetch(URL, { + method: "GET", + }); + if (!response.ok) { + throw new Error("Не удалось получить данные"); + } + const data = await response.json() + return data.leaders; +}; + +export const getLeader = async (name, time) => { + const response = await fetch(URL, { + method: "POST", + body: JSON.stringify ({ + name, + time, + }) + }) + if (response.status === 400) { + throw new Error ("Не удалось загрузить данные") + } + const data = await response.json() + return data.leaders; +} \ No newline at end of file diff --git a/src/components/Cards/Cards.jsx b/src/components/Cards/Cards.jsx index 138e1d734..5a747e94b 100644 --- a/src/components/Cards/Cards.jsx +++ b/src/components/Cards/Cards.jsx @@ -42,6 +42,7 @@ function getTimerValue(startDate, endDate) { * previewSeconds - сколько секунд пользователь будет видеть все карты открытыми до начала игры */ export function Cards({ pairsCount = 3, previewSeconds = 5 }) { + const isHardMode = pairsCount === 3; const { isEasyMode } = useEasyContext(); const [tries, setTries] = useState(3); // В cards лежит игровое поле - массив карт и их состояние открыта\закрыта @@ -243,6 +244,7 @@ export function Cards({ pairsCount = 3, previewSeconds = 5 }) {
{imgAlt} -

{title}

+ {!isLeader &&

{title}

} + + {isLeader && ( +
+

Вы попали на Лидерборд!

+ +
+ )} +

{error}

+

Затраченное время:

{gameDurationMinutes.toString().padStart("2", "0")}.{gameDurationSeconds.toString().padStart("2", "0")}
- - + + {isLeader && ( + + Перейти к лидерборду + + )}
); } diff --git a/src/components/EndGameModal/EndGameModal.module.css b/src/components/EndGameModal/EndGameModal.module.css index 9368cb8b5..d9874626d 100644 --- a/src/components/EndGameModal/EndGameModal.module.css +++ b/src/components/EndGameModal/EndGameModal.module.css @@ -1,12 +1,14 @@ .modal { width: 480px; - height: 459px; + max-height: 634px; border-radius: 12px; background: #c2f5ff; display: flex; flex-direction: column; justify-content: center; align-items: center; + padding-bottom: 48px; + padding-top: 40px; } .image { @@ -27,6 +29,27 @@ margin-bottom: 28px; } +.leaderText { + text-align: center +} + +.placeholder { + border-radius: 10px; + border: none; + background: rgb(255, 255, 255); + width: 276px; + height: 45px; + left: 374px; + top: 334px; + margin-bottom: 28px; + color: black; + font-size: 24px; + font-weight: 400; + line-height: 32px; + letter-spacing: 0%; + text-align: center; +} + .description { color: #000; font-variant-numeric: lining-nums proportional-nums; @@ -49,3 +72,19 @@ margin-bottom: 40px; } + +.toLeaderboard { + font-size: 18px; + color: #565EEF; + font-family: StratosSkyeng; + margin-top: 18px; + text-decoration-line: underline; + line-height: 32px; +} + +.error { + margin-bottom: 20px; + font-size: 18px; + color: red; + font-family: StratosSkyeng; +} \ No newline at end of file diff --git a/src/pages/Leaderboard/Leaderboard.jsx b/src/pages/Leaderboard/Leaderboard.jsx index 2421dd170..aed3d7d55 100644 --- a/src/pages/Leaderboard/Leaderboard.jsx +++ b/src/pages/Leaderboard/Leaderboard.jsx @@ -1,12 +1,59 @@ +import { useState } from "react"; +import { getLeadersPage } from "../../api/Api"; import { Button } from "../../components/Button/Button"; -import styles from "./Leaderboard.module.css" +import styles from "./Leaderboard.module.css"; +import { useEffect } from "react"; +import { useNavigate } from "react-router-dom"; + + + export function Leaderboard() { + const [leaderArr, setLeaderArr] = useState([]); + const [error, setError] = useState(null); + const navigate = useNavigate(); + + function StartGame() { +navigate("/game/9") + } + + useEffect(() => { + const fetchData = async () => { + try { + const data = await getLeadersPage(); + const filterData = data + .sort((a, b) => a.time - b.time) + .slice(0, 10); + setLeaderArr(filterData); + } catch (error) { + setError("Не удалось загрузить данные"); + } + } + fetchData(); + }, []); + return (

Лидерборд

- + +
+
+
+

Позиция

+

Пользователь

+

+

Время

+
+ {leaderArr.map((leader, index) => ( +
+

# {index + 1}

+

{leader.name}

+

+

{`${Math.floor(leader.time / 60).toString().padStart(2, 0)}:${(leader.time % 60).toString().padStart(2, 0)}`}

+
+ ))} + {error}
); diff --git a/src/pages/Leaderboard/Leaderboard.module.css b/src/pages/Leaderboard/Leaderboard.module.css index 96b4e9f84..ec0e95140 100644 --- a/src/pages/Leaderboard/Leaderboard.module.css +++ b/src/pages/Leaderboard/Leaderboard.module.css @@ -17,4 +17,51 @@ font-family: StratosSkyeng; font-size: 24px; color: #fff; +} + +.table { + display: flex; + flex-direction: column; + gap: 15px; +} + +.contentLeaders, +.contentTitle { + display: flex; + justify-content: space-between; + gap: 66px; + align-items: center; + border: 3px solid none; + background-color: #fff; + border-radius: 12px; + height: 64px; + font-size: 24px; + font-family: StratosSkyeng; + padding-left: 20px; + padding-right: 20px; + color: #999; +} + +.contentLeaders { + color: black; +} + +.positionTitle { +width: 178px; +/* color: #999; */ +} + +.nameTitle { + width: 324px; + /* color: #999; */ +} + +.reserveTitle { + width: 102px; + /* color: #999; */ +} + +.timeTitle { + width: 102px; + /* color: #999; */ } \ No newline at end of file diff --git a/src/pages/SelectLevelPage/SelectLevelPage.jsx b/src/pages/SelectLevelPage/SelectLevelPage.jsx index 260b6f43d..8563bea26 100644 --- a/src/pages/SelectLevelPage/SelectLevelPage.jsx +++ b/src/pages/SelectLevelPage/SelectLevelPage.jsx @@ -1,41 +1,93 @@ -import { Link } from "react-router-dom"; +import { Link, useNavigate } from "react-router-dom"; import styles from "./SelectLevelPage.module.css"; import { useEasyContext } from "../../context/useContext"; import { Button } from "../../components/Button/Button"; +import { useState } from "react"; export function SelectLevelPage() { - const {isEasyMode, setEasyMode} = useEasyContext(); - - return ( + const navigate = useNavigate(); + const [error, setError] = useState(null); + const { isEasyMode, setEasyMode } = useEasyContext(); + + const [level, setLevel] = useState(null); + + function ChengeLevel(e) { + setLevel(e.target.value); + } + + function StartGame() { + if (!level) { + setError("Выбери уровень сложности"); + return; + } + navigate(level); + } + + return (

Выбери сложность

  • - + +
  • - + +
  • - + +
- +
- - Перейти к лидерборду +

{error}

+ + + Перейти к лидерборду +
); diff --git a/src/pages/SelectLevelPage/SelectLevelPage.module.css b/src/pages/SelectLevelPage/SelectLevelPage.module.css index ae3fc2235..98214521f 100644 --- a/src/pages/SelectLevelPage/SelectLevelPage.module.css +++ b/src/pages/SelectLevelPage/SelectLevelPage.module.css @@ -108,9 +108,28 @@ .toLeaderboard { font-size: 18px; - color: #004980; + color: #565EEF; font-family: StratosSkyeng; margin-top: 18px; text-decoration-line: underline; line-height: 32px; +} + +.levelButton { + display: none; + + &[type="radio"]:checked + label { + text-shadow: 5px 5px 5px gray; + position: relative; + bottom: 3px; + right: 3px; + + } +} + +.error { + margin-bottom: 20px; + font-size: 18px; + color: red; + font-family: StratosSkyeng; } \ No newline at end of file From 42575b3450f9c70357aa2298225b7e45f92c5af6 Mon Sep 17 00:00:00 2001 From: ASaukov Date: Mon, 2 Sep 2024 02:52:21 +0500 Subject: [PATCH 11/12] completed --- src/components/Cards/Cards.jsx | 2 +- src/components/EndGameModal/EndGameModal.jsx | 33 +++++++++---------- .../EndGameModal/EndGameModal.module.css | 2 +- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/components/Cards/Cards.jsx b/src/components/Cards/Cards.jsx index 5a747e94b..c97b0d2da 100644 --- a/src/components/Cards/Cards.jsx +++ b/src/components/Cards/Cards.jsx @@ -42,7 +42,7 @@ function getTimerValue(startDate, endDate) { * previewSeconds - сколько секунд пользователь будет видеть все карты открытыми до начала игры */ export function Cards({ pairsCount = 3, previewSeconds = 5 }) { - const isHardMode = pairsCount === 3; + const isHardMode = pairsCount === 9; const { isEasyMode } = useEasyContext(); const [tries, setTries] = useState(3); // В cards лежит игровое поле - массив карт и их состояние открыта\закрыта diff --git a/src/components/EndGameModal/EndGameModal.jsx b/src/components/EndGameModal/EndGameModal.jsx index 840e2ddeb..dfbb85b1c 100644 --- a/src/components/EndGameModal/EndGameModal.jsx +++ b/src/components/EndGameModal/EndGameModal.jsx @@ -13,27 +13,24 @@ export function EndGameModal({ isWon, isHardMode, gameDurationSeconds, gameDurat const timeLeader = gameDurationMinutes * 60 + gameDurationSeconds; const [error, setError] = useState(null); - const [leaderData, setLeaderData] = useState({ - name: "", - time: timeLeader, - }); + const [leaderName, setLeaderName] = useState(""); function handleInputChange(e) { - const { name, value } = e.target; - - setLeaderData({ - ...leaderData, - [name]: value, - }); + setLeaderName(e.target.value); } - async function HandleNewLeader(e) { - e.preventDefault(); - if (leaderData.name.trim() === "") { + async function HandleNewLeader() { + if (leaderName.trim() === "") { setError("Введите имя"); return; } - await getLeader({leaderData}); + await getLeader(leaderName, timeLeader); + } + + function onKeyDown (e) { + if (e.key === "Enter") { + HandleNewLeader(); + } } const title = isWon ? "Вы победили!" : "Вы проиграли!"; @@ -53,15 +50,17 @@ export function EndGameModal({ isWon, isHardMode, gameDurationSeconds, gameDurat )} -

{error}

- + {error &&

{error}

} + + {/* */}

Затраченное время:

{gameDurationMinutes.toString().padStart("2", "0")}.{gameDurationSeconds.toString().padStart("2", "0")} diff --git a/src/components/EndGameModal/EndGameModal.module.css b/src/components/EndGameModal/EndGameModal.module.css index d9874626d..eb73ba011 100644 --- a/src/components/EndGameModal/EndGameModal.module.css +++ b/src/components/EndGameModal/EndGameModal.module.css @@ -87,4 +87,4 @@ font-size: 18px; color: red; font-family: StratosSkyeng; -} \ No newline at end of file +} From a21c16cff81a4a67ab1e5344a535d7db2eb81ac3 Mon Sep 17 00:00:00 2001 From: ASaukov Date: Mon, 23 Sep 2024 23:44:42 +0500 Subject: [PATCH 12/12] improvement --- src/api/{Api.jsx => Api.js} | 2 +- src/components/Cards/Cards.jsx | 2 +- src/components/EndGameModal/EndGameModal.jsx | 16 +++++++++--- .../EndGameModal/EndGameModal.module.css | 25 +++++++++++++++++-- 4 files changed, 37 insertions(+), 8 deletions(-) rename src/api/{Api.jsx => Api.js} (92%) diff --git a/src/api/Api.jsx b/src/api/Api.js similarity index 92% rename from src/api/Api.jsx rename to src/api/Api.js index 1fdfea42e..8daa31f1f 100644 --- a/src/api/Api.jsx +++ b/src/api/Api.js @@ -11,7 +11,7 @@ export const getLeadersPage = async () => { return data.leaders; }; -export const getLeader = async (name, time) => { +export const createLeader = async (name, time) => { const response = await fetch(URL, { method: "POST", body: JSON.stringify ({ diff --git a/src/components/Cards/Cards.jsx b/src/components/Cards/Cards.jsx index c97b0d2da..5a747e94b 100644 --- a/src/components/Cards/Cards.jsx +++ b/src/components/Cards/Cards.jsx @@ -42,7 +42,7 @@ function getTimerValue(startDate, endDate) { * previewSeconds - сколько секунд пользователь будет видеть все карты открытыми до начала игры */ export function Cards({ pairsCount = 3, previewSeconds = 5 }) { - const isHardMode = pairsCount === 9; + const isHardMode = pairsCount === 3; const { isEasyMode } = useEasyContext(); const [tries, setTries] = useState(3); // В cards лежит игровое поле - массив карт и их состояние открыта\закрыта diff --git a/src/components/EndGameModal/EndGameModal.jsx b/src/components/EndGameModal/EndGameModal.jsx index dfbb85b1c..b1cff6450 100644 --- a/src/components/EndGameModal/EndGameModal.jsx +++ b/src/components/EndGameModal/EndGameModal.jsx @@ -5,7 +5,7 @@ import celebrationImageUrl from "./images/celebration.png"; import { Link } from "react-router-dom"; import { useEasyContext } from "../../context/useContext"; import { useState } from "react"; -import { getLeader } from "../../api/Api"; +import { createLeader } from "../../api/Api"; export function EndGameModal({ isWon, isHardMode, gameDurationSeconds, gameDurationMinutes, onClick }) { const { isEasyMode } = useEasyContext(); @@ -14,6 +14,11 @@ export function EndGameModal({ isWon, isHardMode, gameDurationSeconds, gameDurat const [error, setError] = useState(null); const [leaderName, setLeaderName] = useState(""); + const [isDisabled, setIsDisabled] = useState(false); + + function changeDisable() { + setIsDisabled(!isDisabled); + } function handleInputChange(e) { setLeaderName(e.target.value); @@ -24,10 +29,11 @@ export function EndGameModal({ isWon, isHardMode, gameDurationSeconds, gameDurat setError("Введите имя"); return; } - await getLeader(leaderName, timeLeader); + await createLeader(leaderName, timeLeader); + changeDisable(); } - function onKeyDown (e) { + function onKeyDown(e) { if (e.key === "Enter") { HandleNewLeader(); } @@ -60,7 +66,9 @@ export function EndGameModal({ isWon, isHardMode, gameDurationSeconds, gameDurat )} {error &&

{error}

} - {/* */} +

Затраченное время:

{gameDurationMinutes.toString().padStart("2", "0")}.{gameDurationSeconds.toString().padStart("2", "0")} diff --git a/src/components/EndGameModal/EndGameModal.module.css b/src/components/EndGameModal/EndGameModal.module.css index eb73ba011..bb2c4c7a2 100644 --- a/src/components/EndGameModal/EndGameModal.module.css +++ b/src/components/EndGameModal/EndGameModal.module.css @@ -41,7 +41,7 @@ height: 45px; left: 374px; top: 334px; - margin-bottom: 28px; + /* margin-bottom: 28px; */ color: black; font-size: 24px; font-weight: 400; @@ -58,7 +58,7 @@ font-style: normal; font-weight: 400; line-height: 32px; - + margin-top: 28px; margin-bottom: 10px; } @@ -88,3 +88,24 @@ color: red; font-family: StratosSkyeng; } + +.buttonLeader { + border-radius: 8px; + margin-top: 10px; + border: none; + width: 150px; + height: 30px; + font-family: StratosSkyeng; + font-size: 18px; + background: rgb(255, 255, 255); + color: rgba(80, 75, 75, 0.675); +} + +.buttonLeader:hover { + color: #000; + cursor: pointer; +} + +.buttonLeader:disabled { + color: lightgrey; +} \ No newline at end of file