diff --git a/crabfit-backend/routes/getPeople.js b/crabfit-backend/routes/getPeople.js
index e157a55..716f446 100644
--- a/crabfit-backend/routes/getPeople.js
+++ b/crabfit-backend/routes/getPeople.js
@@ -7,6 +7,7 @@ module.exports = async (req, res) => {
people = people.map(person => ({
name: person.name,
availability: person.availability,
+ created: person.created,
}));
res.send({
diff --git a/crabfit-backend/routes/login.js b/crabfit-backend/routes/login.js
index d8d15e8..4b6dd29 100644
--- a/crabfit-backend/routes/login.js
+++ b/crabfit-backend/routes/login.js
@@ -21,6 +21,7 @@ module.exports = async (req, res) => {
res.send({
name: personName,
availability: personResult.availability,
+ created: personResult.created,
});
} else {
res.sendStatus(404);
diff --git a/crabfit-backend/swagger.yaml b/crabfit-backend/swagger.yaml
index f9656a6..e64c0c9 100644
--- a/crabfit-backend/swagger.yaml
+++ b/crabfit-backend/swagger.yaml
@@ -36,6 +36,8 @@ definitions:
type: "array"
items:
type: "string"
+ created:
+ type: "integer"
paths:
"/stats":
get:
diff --git a/crabfit-frontend/src/components/AvailabilityViewer/AvailabilityViewer.tsx b/crabfit-frontend/src/components/AvailabilityViewer/AvailabilityViewer.tsx
index fad5a09..1d7cbf4 100644
--- a/crabfit-frontend/src/components/AvailabilityViewer/AvailabilityViewer.tsx
+++ b/crabfit-frontend/src/components/AvailabilityViewer/AvailabilityViewer.tsx
@@ -1,13 +1,15 @@
-import { useState, useEffect, Fragment } from 'react';
+import { useState, useEffect, useRef, Fragment } from 'react';
import dayjs from 'dayjs';
import localeData from 'dayjs/plugin/localeData';
import customParseFormat from 'dayjs/plugin/customParseFormat';
+import relativeTime from 'dayjs/plugin/relativeTime';
import { useSettingsStore } from 'stores';
import { Legend, Center } from 'components';
import {
Wrapper,
+ ScrollWrapper,
Container,
Date,
Times,
@@ -19,6 +21,7 @@ import {
TooltipTitle,
TooltipDate,
TooltipContent,
+ TooltipPerson,
TimeLabels,
TimeLabel,
TimeSpace,
@@ -29,6 +32,7 @@ import {
dayjs.extend(localeData);
dayjs.extend(customParseFormat);
+dayjs.extend(relativeTime);
const AvailabilityViewer = ({
times,
@@ -47,6 +51,8 @@ const AvailabilityViewer = ({
const [tempFocus, setTempFocus] = useState(null);
const [focusCount, setFocusCount] = useState(null);
+ const wrapper = useRef();
+
useEffect(() => {
setFilteredPeople(people.map(p => p.name));
setTouched(people.length <= 1);
@@ -85,6 +91,7 @@ const AvailabilityViewer = ({
}}
onMouseOver={() => setTempFocus(person.name)}
onMouseOut={() => setTempFocus(null)}
+ title={person.created && dayjs.unix(person.created).fromNow()}
>{person.name}
)}
@@ -92,82 +99,94 @@ const AvailabilityViewer = ({
)}
-
-
-
- {!!timeLabels.length && timeLabels.map((label, i) =>
-
- {label.label?.length !== '' && {label.label}}
-
- )}
-
- {dates.map((date, i) => {
- const parsedDate = isSpecificDates ? dayjs(date, 'DDMMYYYY') : dayjs().day(date);
- const last = dates.length === i+1 || (isSpecificDates ? dayjs(dates[i+1], 'DDMMYYYY') : dayjs().day(dates[i+1])).diff(parsedDate, 'day') > 1;
- return (
-
-
- {isSpecificDates && {parsedDate.format('MMM D')}}
- {parsedDate.format('ddd')}
+
+
+
+
+ {!!timeLabels.length && timeLabels.map((label, i) =>
+
+ {label.label?.length !== '' && {label.label}}
+
+ )}
+
+ {dates.map((date, i) => {
+ const parsedDate = isSpecificDates ? dayjs(date, 'DDMMYYYY') : dayjs().day(date);
+ const last = dates.length === i+1 || (isSpecificDates ? dayjs(dates[i+1], 'DDMMYYYY') : dayjs().day(dates[i+1])).diff(parsedDate, 'day') > 1;
+ return (
+
+
+ {isSpecificDates && {parsedDate.format('MMM D')}}
+ {parsedDate.format('ddd')}
-
- {timeLabels.map((timeLabel, i) => {
- if (!timeLabel.time) return null;
- if (!times.includes(`${timeLabel.time}-${date}`)) {
- return (
-
- );
- }
- const time = `${timeLabel.time}-${date}`;
- const peopleHere = tempFocus !== null
- ? people.filter(person => person.availability.includes(time) && tempFocus === person.name).map(person => person.name)
- : people.filter(person => person.availability.includes(time) && filteredPeople.includes(person.name)).map(person => person.name);
+
+ {timeLabels.map((timeLabel, i) => {
+ if (!timeLabel.time) return null;
+ if (!times.includes(`${timeLabel.time}-${date}`)) {
+ return (
+
+ );
+ }
+ const time = `${timeLabel.time}-${date}`;
+ const peopleHere = tempFocus !== null
+ ? people.filter(person => person.availability.includes(time) && tempFocus === person.name).map(person => person.name)
+ : people.filter(person => person.availability.includes(time) && filteredPeople.includes(person.name)).map(person => person.name);
- return (
-
-
- {last && dates.length !== i+1 && (
-
- )}
-
- );
- })}
-
- {tooltip && (
-
- {tooltip.available}
- {tooltip.date}
- {tooltip.people}
-
- )}
+ return (
+
+ {last && dates.length !== i+1 && (
+
+ )}
+
+ );
+ })}
+
+ {tooltip && (
+
+ {tooltip.available}
+ {tooltip.date}
+ {!!filteredPeople.length && (
+
+ {tooltip.people.map(person =>
+ {person}
+ )}
+ {filteredPeople.filter(p => !tooltip.people.includes(p)).map(person =>
+ {person}
+ )}
+
+ )}
+
+ )}
+
>
);
diff --git a/crabfit-frontend/src/components/AvailabilityViewer/availabilityViewerStyle.ts b/crabfit-frontend/src/components/AvailabilityViewer/availabilityViewerStyle.ts
index 707488f..31d5155 100644
--- a/crabfit-frontend/src/components/AvailabilityViewer/availabilityViewerStyle.ts
+++ b/crabfit-frontend/src/components/AvailabilityViewer/availabilityViewerStyle.ts
@@ -1,8 +1,13 @@
import styled from '@emotion/styled';
export const Wrapper = styled.div`
- overflow-x: auto;
+ overflow-y: visible;
margin: 20px 0;
+ position: relative;
+`;
+
+export const ScrollWrapper = styled.div`
+ overflow-x: auto;
`;
export const Container = styled.div`
@@ -62,8 +67,8 @@ export const Time = styled.div`
`}
background-image: linear-gradient(
- ${props => `${props.theme.primary}${Math.round(((props.peopleCount-props.minPeople)/(props.maxPeople-props.minPeople))*255).toString(16)}`},
- ${props => `${props.theme.primary}${Math.round(((props.peopleCount-props.minPeople)/(props.maxPeople-props.minPeople))*255).toString(16)}`}
+ ${props => `${props.theme.primary}${Math.round((props.peopleCount/props.maxPeople)*255).toString(16)}`},
+ ${props => `${props.theme.primary}${Math.round((props.peopleCount/props.maxPeople)*255).toString(16)}`}
);
`;
@@ -73,16 +78,17 @@ export const Spacer = styled.div`
`;
export const Tooltip = styled.div`
- position: fixed;
+ position: absolute;
top: ${props => props.y}px;
left: ${props => props.x}px;
transform: translateX(-50%);
border: 1px solid ${props => props.theme.text};
border-radius: 3px;
padding: 4px 8px;
- background-color: ${props => props.theme.background}DD;
+ background-color: ${props => props.theme.background}${props => props.theme.mode === 'light' ? 'EE' : 'DD'};
max-width: 200px;
pointer-events: none;
+ z-index: 100;
`;
export const TooltipTitle = styled.span`
@@ -94,13 +100,26 @@ export const TooltipTitle = styled.span`
export const TooltipDate = styled.span`
font-size: 13px;
display: block;
- opacity: .7;
- font-weight: 700;
+ opacity: .8;
+ font-weight: 600;
`;
-export const TooltipContent = styled.span`
+export const TooltipContent = styled.div`
font-size: 13px;
- display: block;
+ padding: 4px 0;
+`;
+
+export const TooltipPerson = styled.span`
+ display: inline-block;
+ margin: 2px;
+ padding: 1px 4px;
+ border: 1px solid ${props => props.theme.primary};
+ border-radius: 3px;
+
+ ${props => props.disabled && `
+ opacity: .5;
+ border-color: ${props.theme.text}
+ `}
`;
export const TimeLabels = styled.div`
diff --git a/crabfit-frontend/src/components/Legend/Legend.tsx b/crabfit-frontend/src/components/Legend/Legend.tsx
index 16a51e3..978d317 100644
--- a/crabfit-frontend/src/components/Legend/Legend.tsx
+++ b/crabfit-frontend/src/components/Legend/Legend.tsx
@@ -21,11 +21,11 @@ const Legend = ({
onSegmentFocus(null)}>
- {[...Array(max-min+1).keys()].map(i =>
+ {[...Array(max+1-min).keys()].map(i => i+min).map(i =>
onSegmentFocus(i+min)}
+ color={`${theme.primary}${Math.round((i/(max))*255).toString(16)}`}
+ onMouseOver={() => onSegmentFocus(i)}
/>
)}
diff --git a/crabfit-frontend/src/pages/Event/Event.tsx b/crabfit-frontend/src/pages/Event/Event.tsx
index 52ea2f1..3184ab8 100644
--- a/crabfit-frontend/src/pages/Event/Event.tsx
+++ b/crabfit-frontend/src/pages/Event/Event.tsx
@@ -286,7 +286,7 @@ const Event = (props) => {
{(!!event || isLoading) ? (
<>
{event?.name}
- {event?.created && `Created ${dayjs.unix(event?.created).fromNow()}`}
+ {event?.created && `Created ${dayjs.unix(event?.created).fromNow()}`}
navigator.clipboard?.writeText(`https://crab.fit/${id}`)
.then(() => {