diff --git a/forgettable-frontend/package.json b/forgettable-frontend/package.json index a396b79a..47113dff 100644 --- a/forgettable-frontend/package.json +++ b/forgettable-frontend/package.json @@ -15,6 +15,7 @@ "firebase": "^9.6.8", "image-to-base64": "^2.2.0", "react": "^17.0.2", + "react-calendar-heatmap": "^1.8.1", "react-dom": "^17.0.2", "react-firebase-hooks": "^5.0.3", "react-google-autocomplete": "^2.6.1", @@ -23,6 +24,7 @@ "react-scripts": "^5.0.0", "react-test-renderer": "^17.0.2", "react-toastify": "^8.2.0", + "react-tooltip": "^4.2.21", "typescript": "^4.6.2", "web-vitals": "^2.1.4" }, diff --git a/forgettable-frontend/src/components/Streaks/Streaks.js b/forgettable-frontend/src/components/Streaks/Streaks.js new file mode 100644 index 00000000..1b2cedb6 --- /dev/null +++ b/forgettable-frontend/src/components/Streaks/Streaks.js @@ -0,0 +1,105 @@ + +import React, {useState, useEffect} from 'react'; +import CalendarHeatmap from 'react-calendar-heatmap'; +import ReactTooltip from 'react-tooltip'; +import classes from './Streaks.module.css'; +import './react-calendar-heatmap/dist/styles.css'; +import {getLongDateStringWithSlashes} from '../../functions/dateFormatter'; +import {getAllEncounters} from '../../services'; +import {unmarshalEncounters} from '../../functions/dataUnmarshaller'; +import {Avatar, Card} from '@mui/material'; + +const today = new Date(); + +function Streaks(encounter) { + const [dates, setDates]=useState([]); + async function getDate() { + const encountersResult = await getAllEncounters(); + + const unmarshalledEncounters = encountersResult.map((encounter) => + unmarshalEncounters(encounter), + ); + setDates(unmarshalledEncounters.map((a) =>a.date)); + } + useEffect(()=>{ + try { + getDate(); + } catch (err) { + console.log(err); + } + }, [encounter]); + // count the occurrences of the date + const occurrences = dates.reduce(function(acc, curr) { + return acc[curr] ? ++acc[curr] : acc[curr] = 1, acc; + }, {}); + // set useful Array + const resultDate = Object.keys(occurrences); + const resultCount = Object.values(occurrences); + // use for the values props of the CalendarHeatmap + const data = getRange(resultCount.length).map((d) => ( + { + date: resultDate[d], + count: resultCount[d], + })); + return ( +
+
+

Streaks

+
+
Encounter for last 5 months
+
+
+
Low
+
+
+
+
+
+
+
High
+
+
+
+
+
+ + { + if (!value) { + return 'color-streaks-0'; + } + return `${value.count}` <= 10 ? + `color-streaks-${value.count}` : + `color-streaks-10`; + }} + tooltipDataAttrs={(value) => { + if (!value.date) { + return {'data-tip': + `None encounter at this date`}; + } + return { + 'data-tip': `${getLongDateStringWithSlashes(value.date)} + has count: + ${value.count }`, + }; + } + } + showWeekdayLabels={true} + /> +
+
+ ); +} +// use for the startDate props of the CalendarHeatmap +function shiftDate(date, numDays) { + const newDate = new Date(date); + newDate.setDate(newDate.getDate() + numDays); + return newDate; +} +function getRange(count) { + return Array.from({length: count}, (_, i) => i); +} +export default Streaks; diff --git a/forgettable-frontend/src/components/Streaks/Streaks.module.css b/forgettable-frontend/src/components/Streaks/Streaks.module.css new file mode 100644 index 00000000..e52b76f8 --- /dev/null +++ b/forgettable-frontend/src/components/Streaks/Streaks.module.css @@ -0,0 +1,69 @@ +.scales { + display: flex; + margin-left: auto; + margin-right: 0; + } + .description { + width: 915px; + margin-left: 29px; + color: #313131; + display: flex; + justify-content: space-between; +} + +.descriptionScales { + display: flex; +} + +.streaks0 { + background: #eeeeee; + fill: #eeeeee; + width: 14px; + height: 14px; + margin: 5px; + border-radius: 50%; +} + +.streaks1 { + background:#F3D58A ; + fill: #F3D58A; + width: 14px; + height: 14px; + margin: 5px; + border-radius: 50%; +} + +.streaks2 { + width: 14px; + height: 14px; + margin: 5px; + border-radius: 50%; + fill: #ecc769; + background: #ecc769; +} + +.streaks3 { + width: 14px; + height: 14px; + margin: 5px; + border-radius: 50%; + fill: #ebb429; + background: #ebb429; +} + +.streaks4 { + width: 14px; + height: 14px; + margin: 5px; + border-radius: 50%; + fill: #d89d07; + background: #d89d07; +} +.streaks5 { + width: 14px; + height: 14px; + margin: 5px; + border-radius: 50%; + fill: #d80707; + background:#d80707; +} diff --git a/forgettable-frontend/src/components/Streaks/react-calendar-heatmap/dist/styles.css b/forgettable-frontend/src/components/Streaks/react-calendar-heatmap/dist/styles.css new file mode 100644 index 00000000..1fe99ca8 --- /dev/null +++ b/forgettable-frontend/src/components/Streaks/react-calendar-heatmap/dist/styles.css @@ -0,0 +1,59 @@ +/* + * react-calendar-heatmap styles + * + * All of the styles in this file are optional and configurable! + * The github and gitlab color scales are provided for reference. + */ + + .react-calendar-heatmap text { + font-size: 5px; + fill: #aaa; + } + + .react-calendar-heatmap .react-calendar-heatmap-small-text { + font-size: 5px; + } + + .react-calendar-heatmap rect:hover { + stroke: #555; + stroke-width: 1px; + } + + + .color-streaks-0 { + fill: #eeeeee; + } + + .color-streaks-1 { + fill: #F3D58A; + } + + .color-streaks-2 { + fill: #ecc769; + } + + .color-streaks-3 { + fill: #ebb429; + } + + .color-streaks-4 { + fill: #e9a804; + } + .color-streaks-5 { + fill: #d89d07; + } + .color-streaks-6 { + fill: #8f6804; + } + .color-streaks-7 { + fill: #7b5902; + } + .color-streaks-8 { + fill: #4b3600; + } + .color-streaks-9 { + fill: #463200; + } + .color-streaks-10 { + fill: #d80707; + } \ No newline at end of file diff --git a/forgettable-frontend/src/pages/home/Home.js b/forgettable-frontend/src/pages/home/Home.js index 2ee10724..5aab23ea 100644 --- a/forgettable-frontend/src/pages/home/Home.js +++ b/forgettable-frontend/src/pages/home/Home.js @@ -19,6 +19,7 @@ import { useNavigate } from 'react-router-dom'; import { unmarshalPerson, unmarshalEncounters } from '../../functions/dataUnmarshaller'; import UpcomingBirthdaySummary from '../../components/UpcomingBirthdaySummary/UpcomingBirthdaySummary'; import SearchFilterModal from '../../components/SearchFilterModal/SearchFilterModal'; +import Streaks from '../../components/Streaks/Streaks'; function Home() { const [isHover, setIsHover] = useState(false); @@ -162,6 +163,9 @@ function Home() {
+
+ +
Recently Updated
diff --git a/forgettable-frontend/src/pages/home/Home.module.css b/forgettable-frontend/src/pages/home/Home.module.css index 50287596..e25a7975 100644 --- a/forgettable-frontend/src/pages/home/Home.module.css +++ b/forgettable-frontend/src/pages/home/Home.module.css @@ -13,7 +13,16 @@ font-size: var(--text-xxlarge); font-weight: var(--font-semibold); } - +.streaks_container { + display: flex; + flex-direction: column; + margin-left: 35px; + margin-top: flex; + margin-bottom: 20px; + margin-right: 490px; /* accounts for summary panel + margin */ + min-width: 805px; + max-width: 1565px; +} .home_searchArea { width: 100%; display: flex;