diff --git a/src/assets/Shadow Down.svg b/src/assets/Shadow Down.svg new file mode 100644 index 0000000..d16eb2d --- /dev/null +++ b/src/assets/Shadow Down.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/src/assets/backgrounds/BG-1.png b/src/assets/backgrounds/BG-1.png new file mode 100644 index 0000000..3b80d13 Binary files /dev/null and b/src/assets/backgrounds/BG-1.png differ diff --git a/src/assets/backgrounds/BG-2.png b/src/assets/backgrounds/BG-2.png new file mode 100644 index 0000000..4771fed Binary files /dev/null and b/src/assets/backgrounds/BG-2.png differ diff --git a/src/assets/backgrounds/BG-3.png b/src/assets/backgrounds/BG-3.png new file mode 100644 index 0000000..230353f Binary files /dev/null and b/src/assets/backgrounds/BG-3.png differ diff --git a/src/assets/scrum_expressions/Scrum-1.png b/src/assets/scrum_expressions/Scrum-1.png new file mode 100644 index 0000000..9b9067f Binary files /dev/null and b/src/assets/scrum_expressions/Scrum-1.png differ diff --git a/src/assets/scrum_expressions/Scrum-2.png b/src/assets/scrum_expressions/Scrum-2.png new file mode 100644 index 0000000..b768e54 Binary files /dev/null and b/src/assets/scrum_expressions/Scrum-2.png differ diff --git a/src/assets/scrum_expressions/Scrum-3.png b/src/assets/scrum_expressions/Scrum-3.png new file mode 100644 index 0000000..cc99e87 Binary files /dev/null and b/src/assets/scrum_expressions/Scrum-3.png differ diff --git a/src/assets/scrum_expressions/Scrum-4.png b/src/assets/scrum_expressions/Scrum-4.png new file mode 100644 index 0000000..f0ffd92 Binary files /dev/null and b/src/assets/scrum_expressions/Scrum-4.png differ diff --git a/src/components/History/DialogueBox.jsx b/src/components/History/DialogueBox.jsx new file mode 100644 index 0000000..669adbb --- /dev/null +++ b/src/components/History/DialogueBox.jsx @@ -0,0 +1,23 @@ +import React from "react"; + +import styles from "./style.module.css"; + +function DialogueBox({text}) { + return ( +
+
+

{text}

+
+
+
+

Scrum Master

+
+
+ +
+
+
+ ); +} + +export default DialogueBox; diff --git a/src/components/History/HistoryWrapper.jsx b/src/components/History/HistoryWrapper.jsx new file mode 100644 index 0000000..b012f90 --- /dev/null +++ b/src/components/History/HistoryWrapper.jsx @@ -0,0 +1,41 @@ +import {useState} from "react"; +import {useNavigate, Link} from "react-router-dom"; +import CountDown from "@components/common/CountDown"; +import styles from "./style.module.css"; +import DialogueBox from "./DialogueBox"; +import ScrumMaster from "./ScrumMaster"; +import ModularBackGround from "./ModularBackGround"; + +function HistoryWrapper({dialogue, url}) { + const navigate = useNavigate(); + const [currentIndex, setCurrentIndex] = useState(0); + const [finishedHistory, setFinishedHistory] = useState(false); + + const handleClick = () => { + setCurrentIndex((prev) => { + const nextIndex = prev + 1; + + if (nextIndex === dialogue.length) { + setFinishedHistory(true); + return prev; + } + + return nextIndex; + }); + }; + + const {scrumExpr, text, backGround} = dialogue[currentIndex]; + + return ( +
+
+ +
+ + + {finishedHistory && navigate(url)} />} +
+ ); +} + +export default HistoryWrapper; diff --git a/src/components/History/ModularBackGround.jsx b/src/components/History/ModularBackGround.jsx new file mode 100644 index 0000000..2d9456b --- /dev/null +++ b/src/components/History/ModularBackGround.jsx @@ -0,0 +1,17 @@ +import {useEffect, useState} from "react"; +import styles from "./style.module.css"; + +function ModularBackGround({backGround}) { + if (backGround === 0) return null; + + return ( + Imagem de fundo + ); +} + +export default ModularBackGround; diff --git a/src/components/History/ScrumMaster.jsx b/src/components/History/ScrumMaster.jsx new file mode 100644 index 0000000..c7aa261 --- /dev/null +++ b/src/components/History/ScrumMaster.jsx @@ -0,0 +1,17 @@ +import {useEffect, useState} from "react"; +import styles from "./style.module.css"; + +function ScrumMaster({scrumExpr, pos}) { + if (scrumExpr === 0) return null; + + return ( + scrum-master + ); +} + +export default ScrumMaster; diff --git a/src/components/History/style.module.css b/src/components/History/style.module.css new file mode 100644 index 0000000..d596746 --- /dev/null +++ b/src/components/History/style.module.css @@ -0,0 +1,117 @@ +.dialogueWrapper { + width: 90%; + position: relative; + z-index: 1; + opacity: 0; + animation: fadeIn 0.1s ease-in forwards; +} + +.dialogueBox { + width: 100%; + background-color: var(--soft-white); + padding: 5% 5% 10% 5%; + outline: 3px solid var(--expert-vision); + border-radius: 5px; + position: relative; + min-height: 4em; + box-sizing: border-box; +} + +.dialogueLabelWrapper { + position: relative; + justify-content: flex-start; + align-items: center; + border-radius: 0 5px 5px 5px; + width: 100%; + display: flex; + transform: translateY(-40%); +} + +.dialogueClickable { + display: flex; + width: 100%; + height: max-content; + justify-content: center; + align-items: center; +} + +.dialogueLabel { + background-color: var(--expert-horizon); + display: flex; + justify-content: center; + align-items: center; + border-radius: 0 5px 5px 5px; + outline: 3px solid var(--expert-vision); + padding: 0.5rem 1rem; + width: 55%; +} + +.dialogueLabelShadow { + position: absolute; + bottom: 0; + height: 60%; + width: 55%; + background-color: rgba(0, 0, 0, 0.171); + clip-path: polygon(0 0%, 100% 15%, 100% 100%, 0% 100%); +} + +.dialogueText { + color: var(--expert-vision); + display: block; + width: 100%; +} + +.dialogueLabelText { + color: var(--soft-white); +} + +.scrumMaster { + z-index: 1; + width: 90%; + transform: translateY(6%); + animation: jump 0.5s ease; +} + +.backGround { + z-index: 0; + top: 0; + width: 100%; + height: 100%; + position: absolute; + object-fit: cover; + opacity: 0; + animation: fadeIn 0.1s ease-in forwards; +} + + +.historyWrapper { + padding: 5dvh 0 0 0; + display: flex; + height: -webkit-fill-available; + height: -moz-available; + height: 100%; + width: 100%; + justify-content: space-between; + flex-direction: column; + align-items: center; + overflow: hidden; +} + + +@keyframes jump { + 0% { + transform: translateY(calc(5% + 0px)); + } + 30% { + transform: translateY(calc(5% - 20px)); + } + 60%, 100% { + transform: translateY(calc(5% + 0px)); + } +} + +@keyframes fadeIn { + to { + opacity: 1; + } +} diff --git a/src/components/Map/Column.jsx b/src/components/Map/Column.jsx index cff130c..4ab9101 100644 --- a/src/components/Map/Column.jsx +++ b/src/components/Map/Column.jsx @@ -1,14 +1,25 @@ -import React from "react"; +import React, {useEffect, useRef} from "react"; import styles from "./style.module.css"; function Column({title, children, length}) { + const listRef = useRef(null); + + useEffect(() => { + const el = listRef.current; + if (el && title == "To-do") { + el.scrollTop = el.scrollHeight; + } + }, []); + return (
{length} {title} -
{children}
+
+ {children} +
); } diff --git a/src/components/Map/style.module.css b/src/components/Map/style.module.css index 80defe2..a498f0d 100644 --- a/src/components/Map/style.module.css +++ b/src/components/Map/style.module.css @@ -15,8 +15,10 @@ .cards { display: flex; flex-direction: column; - gap: 5vh; + gap: 3vh; width: 100%; + overflow-y: scroll; + padding: 1vh 0; } .easy { @@ -116,9 +118,9 @@ } .player-profile { - position: fixed; - z-index: 10; - top: 126px; + position: relative; + z-index: 10; + top: 4dvh; } .name-tickets { @@ -147,6 +149,7 @@ .column { display: flex; width: 100%; + max-height: 33%; } .column .title { diff --git a/src/components/common/CountDown/index.jsx b/src/components/common/CountDown/index.jsx new file mode 100644 index 0000000..880d5c9 --- /dev/null +++ b/src/components/common/CountDown/index.jsx @@ -0,0 +1,34 @@ +import { useEffect, useState } from "react"; +import styles from "./style.module.css"; + +function CountDown({ onComplete }) { + const [count, setCount] = useState(3); + + useEffect(() => { + if (count === 0) { + const timeout = setTimeout(() => { + onComplete(); + }, 1000); + return () => clearTimeout(timeout); + } + + const timer = setTimeout(() => { + setCount((prev) => prev - 1); + }, 1000); + + return () => clearTimeout(timer); + }, [count, onComplete]); + + return ( +
+ background +
{count === 0 ? "GO!" : count}
+
+ ); +} + +export default CountDown; diff --git a/src/components/common/CountDown/style.module.css b/src/components/common/CountDown/style.module.css new file mode 100644 index 0000000..91255ea --- /dev/null +++ b/src/components/common/CountDown/style.module.css @@ -0,0 +1,55 @@ +.overlay { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + display: flex; + justify-content: center; + align-items: center; + z-index: 9999; + overflow: hidden; +} + +.backgroundImage { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + object-fit: cover; + z-index: -1; + opacity: 0; + animation: fadeIn 1s ease forwards; +} +.number { + color: var(--soft-white); + font-size: 9dvw; + animation: pop 1s ease; + text-shadow: 4px 4px 10px rgba(0, 0, 0, 0.7); + font-weight: bold; +} + +@keyframes pop { + 0% { + transform: scale(0.2); + opacity: 0; + } + 50% { + transform: scale(1.2); + opacity: 1; + } + 100% { + transform: scale(1); + opacity: 1; + } +} + +@keyframes fadeIn { + from { + opacity: 0; + } + to { + opacity: 1; + } +} diff --git a/src/global.css b/src/global.css index 904ce0e..cbff9f5 100644 --- a/src/global.css +++ b/src/global.css @@ -47,7 +47,7 @@ body::-webkit-scrollbar { } body::-webkit-scrollbar-track { - background: #f1f1f1; + background: transparent; border-radius: 10px; } @@ -60,9 +60,15 @@ body::-webkit-scrollbar-thumb:hover { background: #555; } +body::-webkit-scrollbar-button { + display: none; + height: 0; + width: 0; +} + body { scrollbar-width: thin; - scrollbar-color: #888 #f1f1f1; + scrollbar-color: #888 transparent; } button { diff --git a/src/helpers/Routes.jsx b/src/helpers/Routes.jsx index 8bbc8be..dfa7d45 100644 --- a/src/helpers/Routes.jsx +++ b/src/helpers/Routes.jsx @@ -1,8 +1,8 @@ -import { createBrowserRouter } from "react-router-dom"; +import {createBrowserRouter} from "react-router-dom"; import Frame from "@components/common/Frame"; import ProtectedRoute from "./ProtectedRoute"; -import {Home, Map, Wordle, Register, ConfirmPhone, Login, Phrase, Quiz, Memory} from "../pages"; +import {Home, Map, Wordle, Register, ConfirmPhone, Login, Phrase, Quiz, Memory, History} from "../pages"; const routes = createBrowserRouter([ { @@ -11,20 +11,21 @@ const routes = createBrowserRouter([ children: [ {path: "/", element: }, {path: "/register", element: }, - { path: "/login", element: }, + {path: "/login", element: }, {path: "/confirm-phone", element: }, { element: , children: [ {path: "/map", element: }, {path: "/wordle", element: }, - { path: "/memory", element: }, + {path: "/memory", element: }, {path: "/phrase", element: }, - {path: "/quiz", element: } + {path: "/quiz", element: }, + {path: "/history", element: } ] } ] } ]); -export default routes; +export default routes; \ No newline at end of file diff --git a/src/pages/History/index.jsx b/src/pages/History/index.jsx new file mode 100644 index 0000000..ed6d7c4 --- /dev/null +++ b/src/pages/History/index.jsx @@ -0,0 +1,71 @@ +import React, {useState} from "react"; +import {useNavigate} from "react-router-dom"; + +import styles from "./style.module.css"; +import HistoryWrapper from "@components/History/HistoryWrapper"; + +const dialogueOptions = [ + { + id: 0, + dialogue: [ + { text: "Fala, SEUNOME! Bem-vindo ao SoftExpert! Eu sou o Scrum Master, seu novo guia na jornada dos códigos.", scrumExpr: 1, backGround: 1 }, + { text: "Temos um projetinho top para alguém recém-chegado como você! Vem cá que vou te mostrar…", scrumExpr: 1, backGround: 1 }, + { text: "... Chegamos!", scrumExpr: 0, backGround: 0 }, + { text: "Um Problema clássico de qualquer software: BUGS! Eles aparecem do nada...", scrumExpr: 0, backGround: 2 }, + { text: "Decidimos criar a solução definitiva para acabar com todos os bugs do mundo!", scrumExpr: 0, backGround: 3 }, + { text: "E adivinha? Você vai entrar bem na reta final dessa missão épica! Boa sorte!", scrumExpr: 1, backGround: 0 } + ], + url: "/map" + }, + { + id: 1, + dialogue: [ + { text: "Ei jovem, como sua primeira tarefa preciso que você responda umas questões.", scrumExpr: 1, backGround: 1 }, + { text: "Preparado?", scrumExpr: 1, backGround: 1 } + ], + url: "/quiz" + }, + { + id: 2, + dialogue: [ + { text: "Tudo bom? Estava arrumando o nosso quadro do projeto, só que os emblemas das linguagens estão todos embaralhados...", scrumExpr: 3, backGround: 1 }, + { text: "Você consegue organizar eles pra mim? Temos 1 par de cada, preciso que ache e agrupe os pares de mesma imagem", scrumExpr: 2, backGround: 1 }, + { text: "Preparado?", scrumExpr: 1, backGround: 1 } + ], + url: "/memory" + }, + { + id: 3, + dialogue: [ + { text: "Ah cara... estou escrevendo a documentação para a nossa solução contra os bugs, mas me deu um branco pra lembrar uma palavra aqui... pode me ajudar?", scrumExpr: 3, backGround: 1 }, + { text: "Preparado?", scrumExpr: 1, backGround: 1 } + ], + url: "/wordle" + }, + { + id: 4, + dialogue: [ + { text: "Parabéns! você finalizou seu treinamento. olha só, se tornou um grande profissional, eles crescem tão rápido...", scrumExpr: 2, backGround: 1 }, + { text: "Agora para ir em busca de novos horizontes, visite nosso estande e bata um papo com o pessoal. Você terá uma recepção calorosa!", scrumExpr: 4, backGround: 1 }, + { text: "Ah, quase me esqueci. Fique de olho na frase da vez, que fica à mostra lá no estande. Você também pode ganhar cupons ao enviar ela por aqui. Se cuida!", scrumExpr: 1, backGround: 1 }, + { text: "Preparado?", scrumExpr: 1, backGround: 1 } + ], + url: "/phrase" + } +]; + +// DEPOIS FAZER COM A STORE DO JOGADOR +const level = 0 + +function History() { + + const currentDialogue = dialogueOptions.find(item => item.id === level) + + return ( +
+ +
+ ); +} + +export default History; diff --git a/src/pages/History/style.module.css b/src/pages/History/style.module.css new file mode 100644 index 0000000..916a111 --- /dev/null +++ b/src/pages/History/style.module.css @@ -0,0 +1,10 @@ +.content { + display: flex; + height: -webkit-fill-available; + height: -moz-available; + height: 100%; + justify-content: space-between; + flex-direction: column; + align-items: center; + overflow: hidden; +} diff --git a/src/pages/Home/index.jsx b/src/pages/Home/index.jsx index 96079a7..fe8c465 100644 --- a/src/pages/Home/index.jsx +++ b/src/pages/Home/index.jsx @@ -18,6 +18,12 @@ function Home() { const [isPrizesModalOpen, setIsPrizesModalOpen] = useState(false); const getToken = useAuthStore((state) => state.token); + const handleNavigation = () => { + if (getToken === null) return navigate("/register"); // se o user não estiver loggado: Vai pro registro + if (level === 0) return navigate("/history"); // se o jogador não jogou nenhum jogo, vai pra historia inicial + return navigate("/map"); + }; + return (
Logo da SoftExpert @@ -33,7 +39,7 @@ function Home() { type="primary" size="large" icon="bx-play" - onClick={() => (getToken === null ? navigate("/register") : navigate("/map"))} + onClick={handleNavigation} />