From 98fc75b54b124ab921d80b1d06abd69ce5fc4c90 Mon Sep 17 00:00:00 2001 From: Heather Logan <118981273+heatherlogan-scottlogic@users.noreply.github.com> Date: Thu, 12 Oct 2023 15:14:08 +0100 Subject: [PATCH] 334 move info message to handbook (#345) This work unifies the overlay for the three main popups: welcome message, mission info, handbook. --- frontend/package.json | 2 +- frontend/src/App.tsx | 33 +++++----- frontend/src/Levels.ts | 8 +-- frontend/src/Theme.css | 1 + .../HandbookOverlay/HandbookOverlay.css | 54 +--------------- .../HandbookOverlay/HandbookOverlay.tsx | 53 ++++++++-------- .../HandbookOverlay/HandbookOverlayTabs.css | 57 +++++++++++++++++ .../HandbookOverlay/HandbookOverlayTabs.tsx | 46 ++++++++++++++ .../components/Overlay/MissionInformation.css | 3 + .../components/Overlay/MissionInformation.tsx | 17 +++++ frontend/src/components/Overlay/Overlay.css | 62 +++++++++++++++++++ frontend/src/components/Overlay/Overlay.tsx | 45 ++++++++++++++ .../OverlayWelcome.css} | 8 ++- .../OverlayWelcome.tsx} | 8 +-- frontend/src/models/handbook.ts | 13 ++++ frontend/src/models/level.ts | 2 +- frontend/src/models/overlay.ts | 1 + 17 files changed, 308 insertions(+), 105 deletions(-) create mode 100644 frontend/src/components/HandbookOverlay/HandbookOverlayTabs.css create mode 100644 frontend/src/components/HandbookOverlay/HandbookOverlayTabs.tsx create mode 100644 frontend/src/components/Overlay/MissionInformation.css create mode 100644 frontend/src/components/Overlay/MissionInformation.tsx create mode 100644 frontend/src/components/Overlay/Overlay.css create mode 100644 frontend/src/components/Overlay/Overlay.tsx rename frontend/src/components/{HandbookOverlay/HandbookWelcome.css => Overlay/OverlayWelcome.css} (58%) rename frontend/src/components/{HandbookOverlay/HandbookWelcome.tsx => Overlay/OverlayWelcome.tsx} (66%) create mode 100644 frontend/src/models/handbook.ts diff --git a/frontend/package.json b/frontend/package.json index ea141b065..ec4f409d4 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -27,8 +27,8 @@ "@typescript-eslint/parser": "^6.0.0", "@vitejs/plugin-react": "^4.0.3", "eslint": "^8.50.0", - "eslint-plugin-react": "^7.33.2", "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.3", "prettier": "2.8.8", diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 49036bc1d..63687d28b 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -22,8 +22,7 @@ import { import { DEFENCE_DETAILS_ALL, DEFENCE_DETAILS_LEVEL } from "./Defences"; import { DEFENCE_TYPES, DefenceConfig, DefenceInfo } from "./models/defence"; import { getCompletedLevels } from "./service/levelService"; -import { LEVELS } from "./Levels"; -import HandbookOverlay from "./components/HandbookOverlay/HandbookOverlay"; +import Overlay from "./components/Overlay/Overlay"; import { OVERLAY_TYPE } from "./models/overlay"; function App({ isNewUser }: { isNewUser: boolean }) { @@ -75,7 +74,12 @@ function App({ isNewUser }: { isNewUser: boolean }) { }, [currentLevel]); function closeOverlay() { - setShowOverlay(false); + // open the mission info after welcome page for a new user + if (overlayType === OVERLAY_TYPE.WELCOME) { + openInformationOverlay(); + } else { + setShowOverlay(false); + } } function openHandbook() { @@ -83,6 +87,11 @@ function App({ isNewUser }: { isNewUser: boolean }) { setShowOverlay(true); } + function openInformationOverlay() { + setOverlayType(OVERLAY_TYPE.INFORMATION); + setShowOverlay(true); + } + // methods to modify messages function addChatMessage(message: ChatMessage) { setMessages((messages: ChatMessage[]) => [...messages, message]); @@ -94,11 +103,6 @@ function App({ isNewUser }: { isNewUser: boolean }) { await clearChat(currentLevel); setMessages([]); - // add preamble to start of chat - addChatMessage({ - message: LEVELS[currentLevel].preamble, - type: CHAT_MESSAGE_TYPE.LEVEL_INFO, - }); await clearEmails(currentLevel); setEmails([]); @@ -119,6 +123,11 @@ function App({ isNewUser }: { isNewUser: boolean }) { // for going switching level without clearing progress async function setNewLevel(newLevel: LEVEL_NAMES) { console.log(`changing level from ${currentLevel} to ${newLevel}`); + + if (currentLevel !== newLevel) { + openInformationOverlay(); + } + setMessages([]); setCurrentLevel(newLevel); @@ -128,11 +137,7 @@ function App({ isNewUser }: { isNewUser: boolean }) { // get chat history for new level from the backend const levelChatHistory = await getChatHistory(newLevel); - // add the preamble to the start of the chat history - levelChatHistory.unshift({ - message: LEVELS[newLevel].preamble, - type: CHAT_MESSAGE_TYPE.LEVEL_INFO, - }); + setMessages(levelChatHistory); const defences = @@ -224,7 +229,7 @@ function App({ isNewUser }: { isNewUser: boolean }) { return (
{showOverlay && ( - .close-button { - position: absolute; - right: 16px; - top: 16px; - max-width: 2rem; - max-height: 2rem; - min-height: 1.6rem; - padding: 5px; - - color: inherit; - font-size: 1.5rem; - font-weight: bold; -} - -.handbook-overlay > .close-button:hover { - color: var(--main-button-hover-text-colour); - text-decoration: none; - cursor: pointer; -} - -.handbook-overlay-content { +#handbook-overlay-content { height: 100%; - padding: 0 5%; text-align: center; overflow-y: auto; diff --git a/frontend/src/components/HandbookOverlay/HandbookOverlay.tsx b/frontend/src/components/HandbookOverlay/HandbookOverlay.tsx index eb87b9844..19c656ee6 100644 --- a/frontend/src/components/HandbookOverlay/HandbookOverlay.tsx +++ b/frontend/src/components/HandbookOverlay/HandbookOverlay.tsx @@ -1,39 +1,40 @@ +import { useState } from "react"; import { LEVEL_NAMES } from "../../models/level"; -import { OVERLAY_TYPE } from "../../models/overlay"; +import MissionInformation from "../Overlay/MissionInformation"; import HandbookAttacks from "./HandbookAttacks"; +import HandbookOverlayTabs from "./HandbookOverlayTabs"; +import { HANDBOOK_PAGES } from "../../models/handbook"; import "./HandbookOverlay.css"; -import HandbookWelcome from "./HandbookWelcome"; -function HandbookOverlay({ - currentLevel, - overlayType, - closeOverlay, -}: { - currentLevel: LEVEL_NAMES; - overlayType: OVERLAY_TYPE; - closeOverlay: () => void; -}) { - function showOverlayByType() { - switch (overlayType) { - case OVERLAY_TYPE.HANDBOOK: +function HandbookOverlay({ currentLevel }: { currentLevel: LEVEL_NAMES }) { + const [selectedPage, setSelectedPage] = useState( + HANDBOOK_PAGES.MISSION_INFO + ); + + function setPageContent(handbookPage: HANDBOOK_PAGES) { + switch (handbookPage) { + case HANDBOOK_PAGES.ATTACKS: return ; - case OVERLAY_TYPE.WELCOME: + case HANDBOOK_PAGES.TOOLS: + return ( +
+

Placeholder

+
+ ); + case HANDBOOK_PAGES.MISSION_INFO: default: - return ; + return ; } } return ( -
-
- -
{showOverlayByType()}
+
+ +
+ {setPageContent(selectedPage)}
); diff --git a/frontend/src/components/HandbookOverlay/HandbookOverlayTabs.css b/frontend/src/components/HandbookOverlay/HandbookOverlayTabs.css new file mode 100644 index 000000000..348b0a203 --- /dev/null +++ b/frontend/src/components/HandbookOverlay/HandbookOverlayTabs.css @@ -0,0 +1,57 @@ +.handbook-tabs { + display: flex; + flex-wrap: wrap; + width: 100%; + position: absolute; + top: -50px; /* position above overlay */ + left: 2rem; + z-index: -1; +} + +.handbook-tabs label { + display: flex; + align-items: center; + justify-content: center; + padding: 1rem 2rem; + margin-right: 0.0625rem; + cursor: pointer; + background-color: var(--overlay-closed-tab-colour); + font-weight: 700; + transition: ease 0.1s; + border-radius: 10px 10px 0 0; +} + +.handbook-tabs label:not(:first-child):not(:last-child) { + border-right: 2px solid #000; +} + +.handbook-tabs [type="radio"] { + display: none; +} + +.handbook-tabs [type="radio"]:checked + label { + background-color: var(--overlay-background-colour); +} + +.handbook-tabs [type="radio"]:checked + label + .tab { + display: block; +} + +@media (min-width: 768px) { + body { + font-size: 1.125rem; + } + + .handbook-tabs-container { + padding: 4rem 4rem; + } + + .handbook-tabs label { + order: 1; + width: auto; + } + + .handbook-tabs .tab { + order: 9; + } +} diff --git a/frontend/src/components/HandbookOverlay/HandbookOverlayTabs.tsx b/frontend/src/components/HandbookOverlay/HandbookOverlayTabs.tsx new file mode 100644 index 000000000..5a1cc416b --- /dev/null +++ b/frontend/src/components/HandbookOverlay/HandbookOverlayTabs.tsx @@ -0,0 +1,46 @@ +import { HANDBOOK_PAGES, handbookPageNames } from "../../models/handbook"; +import { LEVEL_NAMES } from "../../models/level"; +import "./HandbookOverlayTabs.css"; + +function HandbookOverlayTabs({ + currentLevel, + setSelectedPage, +}: { + currentLevel: LEVEL_NAMES; + setSelectedPage: (page: HANDBOOK_PAGES) => void; +}) { + // the tabs that are shown depend on the current level + function getLevelTabs(currentLevel: LEVEL_NAMES) { + switch (currentLevel) { + case LEVEL_NAMES.LEVEL_1: + return [HANDBOOK_PAGES.MISSION_INFO]; + default: + return [ + HANDBOOK_PAGES.MISSION_INFO, + HANDBOOK_PAGES.ATTACKS, + HANDBOOK_PAGES.TOOLS, + ]; + } + } + + return ( +
+ {getLevelTabs(currentLevel).map((tab) => ( +
+ { + setSelectedPage(tab); + }} + /> + +
+ ))} +
+ ); +} + +export default HandbookOverlayTabs; diff --git a/frontend/src/components/Overlay/MissionInformation.css b/frontend/src/components/Overlay/MissionInformation.css new file mode 100644 index 000000000..e44107ed3 --- /dev/null +++ b/frontend/src/components/Overlay/MissionInformation.css @@ -0,0 +1,3 @@ +#mission-info p { + font-size: 1.5rem; +} diff --git a/frontend/src/components/Overlay/MissionInformation.tsx b/frontend/src/components/Overlay/MissionInformation.tsx new file mode 100644 index 000000000..b38709c6e --- /dev/null +++ b/frontend/src/components/Overlay/MissionInformation.tsx @@ -0,0 +1,17 @@ +import { LEVEL_NAMES } from "../../models/level"; +import { LEVELS } from "../../Levels"; + +import "./MissionInformation.css"; + +function MissionInformation({ currentLevel }: { currentLevel: LEVEL_NAMES }) { + return ( +
+

Mission Information

+
+

{LEVELS[currentLevel].missionInfo}

+
+
+ ); +} + +export default MissionInformation; diff --git a/frontend/src/components/Overlay/Overlay.css b/frontend/src/components/Overlay/Overlay.css new file mode 100644 index 000000000..1363769ff --- /dev/null +++ b/frontend/src/components/Overlay/Overlay.css @@ -0,0 +1,62 @@ +.overlay-screen { + background-color: var(--overlay-hidden-colour); + + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 100; + + display: flex; + justify-content: center; + align-items: center; +} + +.overlay { + position: relative; + + background-color: var(--overlay-background-colour); + color: var(--overlay-text-colour); + + display: flex; + justify-content: center; + align-items: center; + overflow: visible; + + width: 50%; + height: 50%; + border-radius: 10px; +} + +.overlay .handbook-overlay { + border-radius: 0; +} + +.overlay > .close-button { + position: absolute; + right: 16px; + top: 16px; + max-width: 2rem; + max-height: 2rem; + min-height: 1.6rem; + padding: 5px; + + color: inherit; + font-size: 1.5rem; + font-weight: bold; +} + +.overlay > .close-button:hover { + color: var(--main-button-hover-text-colour); + text-decoration: none; + cursor: pointer; +} + +.overlay-content { + height: 100%; + padding: 0 5%; + + text-align: center; + overflow-y: auto; +} diff --git a/frontend/src/components/Overlay/Overlay.tsx b/frontend/src/components/Overlay/Overlay.tsx new file mode 100644 index 000000000..37f64770e --- /dev/null +++ b/frontend/src/components/Overlay/Overlay.tsx @@ -0,0 +1,45 @@ +import { LEVEL_NAMES } from "../../models/level"; +import { OVERLAY_TYPE } from "../../models/overlay"; +import "./Overlay.css"; +import HandbookWelcome from "./OverlayWelcome"; +import HandbookOverlay from "../HandbookOverlay/HandbookOverlay"; +import MissionInformation from "../Overlay/MissionInformation"; + +function Overlay({ + currentLevel, + overlayType, + closeOverlay, +}: { + currentLevel: LEVEL_NAMES; + overlayType: OVERLAY_TYPE; + closeOverlay: () => void; +}) { + function showOverlayByType() { + switch (overlayType) { + case OVERLAY_TYPE.HANDBOOK: + return ; + case OVERLAY_TYPE.INFORMATION: + return ; + case OVERLAY_TYPE.WELCOME: + default: + return ; + } + } + + return ( +
+
+ +
{showOverlayByType()}
+
+
+ ); +} + +export default Overlay; diff --git a/frontend/src/components/HandbookOverlay/HandbookWelcome.css b/frontend/src/components/Overlay/OverlayWelcome.css similarity index 58% rename from frontend/src/components/HandbookOverlay/HandbookWelcome.css rename to frontend/src/components/Overlay/OverlayWelcome.css index 1e7796083..f734ca3e3 100644 --- a/frontend/src/components/HandbookOverlay/HandbookWelcome.css +++ b/frontend/src/components/Overlay/OverlayWelcome.css @@ -1,9 +1,13 @@ -#handbook-welcome h1 { +#welcome { + padding: 0 5%; +} + +#welcome h1 { font-weight: 700; font-size: 3rem; } -#handbook-welcome p { +#welcome p { font-weight: 500; font-size: 2rem; } diff --git a/frontend/src/components/HandbookOverlay/HandbookWelcome.tsx b/frontend/src/components/Overlay/OverlayWelcome.tsx similarity index 66% rename from frontend/src/components/HandbookOverlay/HandbookWelcome.tsx rename to frontend/src/components/Overlay/OverlayWelcome.tsx index cbd993b48..2c2d89033 100644 --- a/frontend/src/components/HandbookOverlay/HandbookWelcome.tsx +++ b/frontend/src/components/Overlay/OverlayWelcome.tsx @@ -1,8 +1,8 @@ -import "./HandbookWelcome.css"; +import "./OverlayWelcome.css"; -function HandbookWelcome() { +function OverlayWelcome() { return ( -
+

Welcome!

Your mission, should you choose to accept it, is to go undercover and @@ -13,4 +13,4 @@ function HandbookWelcome() { ); } -export default HandbookWelcome; +export default OverlayWelcome; diff --git a/frontend/src/models/handbook.ts b/frontend/src/models/handbook.ts new file mode 100644 index 000000000..da0dc0ad7 --- /dev/null +++ b/frontend/src/models/handbook.ts @@ -0,0 +1,13 @@ +enum HANDBOOK_PAGES { + MISSION_INFO, + ATTACKS, + TOOLS, +} + +const handbookPageNames: { [key in HANDBOOK_PAGES]: string } = { + [HANDBOOK_PAGES.MISSION_INFO]: "Mission Info", + [HANDBOOK_PAGES.ATTACKS]: "Attacks", + [HANDBOOK_PAGES.TOOLS]: "Tools", +}; + +export { HANDBOOK_PAGES, handbookPageNames }; diff --git a/frontend/src/models/level.ts b/frontend/src/models/level.ts index 07951e62a..8186384d4 100644 --- a/frontend/src/models/level.ts +++ b/frontend/src/models/level.ts @@ -8,7 +8,7 @@ enum LEVEL_NAMES { interface Level { id: LEVEL_NAMES; name: string; - preamble: string; + missionInfo: string; } export { LEVEL_NAMES }; diff --git a/frontend/src/models/overlay.ts b/frontend/src/models/overlay.ts index 0b3873f7e..f31415bb0 100644 --- a/frontend/src/models/overlay.ts +++ b/frontend/src/models/overlay.ts @@ -1,6 +1,7 @@ enum OVERLAY_TYPE { WELCOME, HANDBOOK, + INFORMATION, } export { OVERLAY_TYPE };