From 7bb41cccb78b23bb9389cb8b4a7ac86d1619d749 Mon Sep 17 00:00:00 2001 From: Jason Date: Wed, 5 Jun 2024 15:45:54 +0100 Subject: [PATCH 1/2] ACD-17356: making rentokil heatmap more generic --- package-lock.json | 118 +++++++++++++++++ package.json | 1 + src/App.css | 14 +- src/App.module.scss | 19 +++ src/App.tsx | 46 ++++++- src/assets/ancoris-logo.svg | 123 ++++++++++++++++++ src/assets/menu.svg | 1 + src/components/Avatar/Avatar.module.scss | 38 ++++++ src/components/Avatar/Avatar.tsx | 38 ++++++ src/components/Button/Button.tsx | 53 ++++++++ src/components/Button/ButtonTypes.ts | 5 + .../DateSlider/DateSlider.module.css | 5 + src/components/DateSlider/index.tsx | 2 +- src/components/Header/Header.module.scss | 42 ++++++ src/components/Header/Header.tsx | 27 ++++ src/components/List/List.module.scss | 15 +++ src/components/List/List.tsx | 25 ++++ src/components/ListItem/ListItem.module.scss | 37 ++++++ src/components/ListItem/ListItem.tsx | 37 ++++++ src/components/Map/Map.module.css | 2 +- src/context/ThemeContext.tsx | 53 ++++++++ src/context/ThemeTypes.ts | 6 + src/main.tsx | 6 +- src/themes/_colours.scss | 39 ++++++ src/themes/_mixins.scss | 55 ++++++++ src/themes/dark.scss | 33 +++++ src/themes/default.scss | 76 +++++++++++ 27 files changed, 896 insertions(+), 20 deletions(-) create mode 100644 src/App.module.scss create mode 100644 src/assets/ancoris-logo.svg create mode 100644 src/assets/menu.svg create mode 100644 src/components/Avatar/Avatar.module.scss create mode 100644 src/components/Avatar/Avatar.tsx create mode 100644 src/components/Button/Button.tsx create mode 100644 src/components/Button/ButtonTypes.ts create mode 100644 src/components/Header/Header.module.scss create mode 100644 src/components/Header/Header.tsx create mode 100644 src/components/List/List.module.scss create mode 100644 src/components/List/List.tsx create mode 100644 src/components/ListItem/ListItem.module.scss create mode 100644 src/components/ListItem/ListItem.tsx create mode 100644 src/context/ThemeContext.tsx create mode 100644 src/context/ThemeTypes.ts create mode 100644 src/themes/_colours.scss create mode 100644 src/themes/_mixins.scss create mode 100644 src/themes/dark.scss create mode 100644 src/themes/default.scss diff --git a/package-lock.json b/package-lock.json index 7f8e4048fd..1e07b5ef87 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "eslint": "^8.57.0", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.6", + "sass": "^1.77.4", "typescript": "^5.2.2", "vite": "^5.2.0" } @@ -1927,6 +1928,19 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -1948,6 +1962,18 @@ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -1994,6 +2020,42 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/cliui": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", @@ -2674,6 +2736,12 @@ "node": ">= 4" } }, + "node_modules/immutable": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.6.tgz", + "integrity": "sha512-Ju0+lEMyzMVZarkTn/gqRpdqd5dOPaz1mCZ0SH3JV6iFw81PldE/PEB1hWVEA288HPt4WXW8O7AWxB10M+03QQ==", + "dev": true + }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", @@ -2715,6 +2783,18 @@ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -2974,6 +3054,15 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", @@ -3208,6 +3297,18 @@ "react": "^18.3.1" } }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -3327,6 +3428,23 @@ } ] }, + "node_modules/sass": { + "version": "1.77.4", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.77.4.tgz", + "integrity": "sha512-vcF3Ckow6g939GMA4PeU7b2K/9FALXk2KF9J87txdHzXbUF9XRQRwSxcAs/fGaTnJeBFd7UoV22j3lzMLdM0Pw==", + "dev": true, + "dependencies": { + "chokidar": ">=3.0.0 <4.0.0", + "immutable": "^4.0.0", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/scheduler": { "version": "0.23.2", "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", diff --git a/package.json b/package.json index 04cd50e474..65c17fe438 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "eslint": "^8.57.0", "eslint-plugin-react-hooks": "^4.6.0", "eslint-plugin-react-refresh": "^0.4.6", + "sass": "^1.77.4", "typescript": "^5.2.2", "vite": "^5.2.0" } diff --git a/src/App.css b/src/App.css index 4eaa5115ed..f026502d04 100644 --- a/src/App.css +++ b/src/App.css @@ -5,16 +5,4 @@ display: flex; flex-direction: column; overflow: hidden; -} - -div.wrapper { - height: 100%; -} - -div.areaCalc { - font-size: 18px; - font-weight: 900; - padding: 0px 20px 20px 20px; - margin-top: -20px; - border-bottom: 1px solid #e0e0e0; -} +} \ No newline at end of file diff --git a/src/App.module.scss b/src/App.module.scss new file mode 100644 index 0000000000..59572840f1 --- /dev/null +++ b/src/App.module.scss @@ -0,0 +1,19 @@ +@import "./themes/default.scss"; +@import "./themes/dark.scss"; +@import "./themes/mixins"; + +.wrapper { + height: 100%; +} + +.areaCalc { + font-size: 18px; + font-weight: 900; + padding: 0px 20px 20px 20px; + margin-top: -20px; + border-bottom: 1px solid #e0e0e0; +} + +.top { + background: var(--background-default); +} \ No newline at end of file diff --git a/src/App.tsx b/src/App.tsx index db14efebf3..39db3c3680 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,7 +1,7 @@ -import { useEffect, useState } from "react"; +import { useEffect, useState, useContext } from "react"; import "./App.css"; +import styles from "./App.module.scss"; import { Map } from "./components/Map"; -import { PrimaryNavigation } from "./components/PrimaryNavigation"; import { initializeApp } from "firebase/app"; import { getAnalytics } from "firebase/analytics"; import Sidebar from "./components/Sidebar/Sidebar"; @@ -9,6 +9,13 @@ import { PolygonEditor } from "./components/PolygonEditor"; import { GeoJsonArea } from "./components/GeoJsonArea"; import { SiteInfo } from "./components/SiteInfo/SiteInfo"; import { AtRiskList } from "./components/AtRiskList/AtRiskList"; +import { Header } from "./components/Header/Header"; +import { Avatar } from "./components/Avatar/Avatar"; +import { ListItem } from "./components/ListItem/ListItem"; +import { ThemeContext } from "./context/ThemeContext"; +import ThemeType from "./context/ThemeTypes"; +import Menu from "./assets/menu.svg"; +import Logo from "../src/assets/ancoris-logo.svg" assert { type: "png" }; const enum InfoType { siteInfo = "siteInfo", @@ -20,6 +27,7 @@ function App() { string[] >([]); const [map, setMap] = useState(null); + const { setTheme } = useContext(ThemeContext); const app = initializeApp({ apiKey: "AIzaSyBWjMNpB8OfCyVhcARQUMBh9bDzrcxBOpc", @@ -54,7 +62,7 @@ function App() { const siteDetails = () => { return ( <> -
+
{ + setTheme(ThemeType.Light); + console.log(ThemeType.Light); + }} + />, + { + setTheme(ThemeType.Dark); + console.log(ThemeType.Dark); + }} + />, + ]; + const handleAtRiskBuildingClick = ( featureId: string, coord: google.maps.LatLng, @@ -79,7 +106,18 @@ function App() { return ( <> - +
+
+ } + title="Rentokil Heatmap" + avatar={} + /> +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/assets/menu.svg b/src/assets/menu.svg new file mode 100644 index 0000000000..a60b7abccc --- /dev/null +++ b/src/assets/menu.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/components/Avatar/Avatar.module.scss b/src/components/Avatar/Avatar.module.scss new file mode 100644 index 0000000000..104ca51ff7 --- /dev/null +++ b/src/components/Avatar/Avatar.module.scss @@ -0,0 +1,38 @@ +.avatarImage { + width: 40px; + height: 40px; +} + +.avatarBorder { + border: 1px solid var(--grey-300); + border-radius: 24px; +} + +.avatarDropdown { + position: relative; + display: inline-block; + line-height: 0px; +} + +.avatarDropdownContent { + display: block; + position: absolute; + width: fit-content; + z-index: 5; + left: auto; + right: 0; + margin-right: -10px; + padding-block-start: var(--space-x1); +} + +.avatarDropdownContentInner { + background: var(--grey-300); + width: fit-content; + border-radius: 10px; + box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2); + overflow: hidden; +} + +.avatarDropdown:hover .avatarDropdownContent { + display: block; +} diff --git a/src/components/Avatar/Avatar.tsx b/src/components/Avatar/Avatar.tsx new file mode 100644 index 0000000000..7649849416 --- /dev/null +++ b/src/components/Avatar/Avatar.tsx @@ -0,0 +1,38 @@ +import { ReactNode, useState, FunctionComponent } from "react"; +import styles from "./Avatar.module.scss"; +import { List } from "../List/List"; + +interface AvatarProps { + image: string; + options?: ReactNode[]; +} + +export const Avatar: FunctionComponent = ({ + image, + options = [], +}: AvatarProps) => { + const [showMenu, setShowMenu] = useState(false); + + const handleMenu = () => { + console.log("clicked") + setShowMenu(!showMenu); + }; + + return ( +
+ Avatar + {showMenu && ( +
+
+ +
+
+ )} +
+ ); +}; diff --git a/src/components/Button/Button.tsx b/src/components/Button/Button.tsx new file mode 100644 index 0000000000..732d6eac71 --- /dev/null +++ b/src/components/Button/Button.tsx @@ -0,0 +1,53 @@ +import { ReactNode, FunctionComponent } from "react"; +import styles from "./Button.module.scss"; +import { ButtonType } from "./ButtonTypes"; + +interface ButtonProps { + type?: ButtonType; + label?: string; + icon?: ReactNode; + hideLabel?: boolean; + hideIcon?: boolean; + onClick: () => void; +} + +export const Button: FunctionComponent = ({ + type = ButtonType.Action, + label, + icon, + hideLabel = false, + hideIcon = true, + onClick, +}: ButtonProps) => { + let buttonClass; + switch (type) { + case ButtonType.Action: + buttonClass = styles.actionOuter; + break; + case ButtonType.Send: + buttonClass = styles.sendOuter; + break; + case ButtonType.Suggestion: + buttonClass = styles.suggestionOuter; + break; + } + + return ( + + ); +}; diff --git a/src/components/Button/ButtonTypes.ts b/src/components/Button/ButtonTypes.ts new file mode 100644 index 0000000000..6206cdd469 --- /dev/null +++ b/src/components/Button/ButtonTypes.ts @@ -0,0 +1,5 @@ +export enum ButtonType { + Action, + Send, + Suggestion, +} diff --git a/src/components/DateSlider/DateSlider.module.css b/src/components/DateSlider/DateSlider.module.css index 415ba4d7a4..f0fb779cf3 100644 --- a/src/components/DateSlider/DateSlider.module.css +++ b/src/components/DateSlider/DateSlider.module.css @@ -67,6 +67,10 @@ div.timeSliderContainer { } } + .date { + color: var(--text-primary) + } + .labels { position: absolute; bottom: 0; @@ -74,6 +78,7 @@ div.timeSliderContainer { } .labels span { + color: var(--text-primary); position: absolute; left: calc( var(--i) * (var(--slider-width) - (2 * var(--label-margins))) / diff --git a/src/components/DateSlider/index.tsx b/src/components/DateSlider/index.tsx index d19bc981fb..eb7e3de9ba 100644 --- a/src/components/DateSlider/index.tsx +++ b/src/components/DateSlider/index.tsx @@ -121,7 +121,7 @@ export const DateSlider: FunctionComponent = ({ /> {daysAgo(0)}