diff --git a/crabfit-frontend/src/App.tsx b/crabfit-frontend/src/App.tsx index 652c942..10331af 100644 --- a/crabfit-frontend/src/App.tsx +++ b/crabfit-frontend/src/App.tsx @@ -32,7 +32,7 @@ const App = () => { backgroundColor: theme.background, color: theme.text, fontFamily: `'Karla', sans-serif`, - fontWeight: 600, + fontWeight: theme.mode === 'dark' ? 500 : 600, margin: 0, }, a: { diff --git a/crabfit-frontend/src/components/AvailabilityViewer/AvailabilityViewer.tsx b/crabfit-frontend/src/components/AvailabilityViewer/AvailabilityViewer.tsx new file mode 100644 index 0000000..31a6e9b --- /dev/null +++ b/crabfit-frontend/src/components/AvailabilityViewer/AvailabilityViewer.tsx @@ -0,0 +1,91 @@ +import { useState } from 'react'; +import dayjs from 'dayjs'; +import localeData from 'dayjs/plugin/localeData'; +import customParseFormat from 'dayjs/plugin/customParseFormat'; + +import { + Wrapper, + Container, + Date, + DateLabel, + DayLabel, + Time, + Spacer, + Tooltip, + TooltipTitle, + TooltipDate, + TooltipContent, +} from './availabilityViewerStyle'; + +dayjs.extend(localeData); +dayjs.extend(customParseFormat); + +const AvailabilityViewer = ({ + dates, + times, + people = [], + ...props +}) => { + const [tooltip, setTooltip] = useState(null); + + return ( + + + {dates.map((date, i) => { + const parsedDate = dayjs(date, 'DDMMYYYY'); + const last = dates.length === i+1 || dayjs(dates[i+1], 'DDMMYYYY').diff(parsedDate, 'day') > 1; + return ( + <> + + {parsedDate.format('MMM D')} + {parsedDate.format('ddd')} + + {times.map((time, i) => { + const peopleHere = people.filter(person => person.availability.includes(`${time}-${date}`)).map(person => person.name); + return ( + + {last && dates.length !== i+1 && ( + + )} + + ); + })} + + {tooltip && ( + + {tooltip.available} + {tooltip.date} + {tooltip.people} + + )} + + ); +}; + +export default AvailabilityViewer; diff --git a/crabfit-frontend/src/components/AvailabilityViewer/availabilityViewerStyle.ts b/crabfit-frontend/src/components/AvailabilityViewer/availabilityViewerStyle.ts new file mode 100644 index 0000000..da02c15 --- /dev/null +++ b/crabfit-frontend/src/components/AvailabilityViewer/availabilityViewerStyle.ts @@ -0,0 +1,91 @@ +import styled from '@emotion/styled'; + +export const Wrapper = styled.div` + overflow-x: auto; + margin: 20px 0; +`; + +export const Container = styled.div` + display: inline-flex; + box-sizing: border-box; + min-width: 100%; + align-items: flex-start; + padding: 0 calc(calc(100% - 600px) / 2); +`; + +export const Date = styled.div` + flex-shrink: 0; + display: flex; + flex-direction: column; + width: 60px; + min-width: 60px; + + & .time:last-of-type { + border-bottom: 1px solid ${props => props.theme.primaryDark}; + } + &.last > .time { + border-right: 1px solid ${props => props.theme.primaryDark}; + } +`; + +export const DateLabel = styled.label` + display: block; + font-size: 12px; + text-align: center; + user-select: none; +`; + +export const DayLabel = styled.label` + display: block; + font-size: 15px; + text-align: center; + user-select: none; +`; + +export const Time = styled.div` + height: 10px; + border-left: 1px solid ${props => props.theme.primaryDark}; + + ${props => props.time.slice(-2) === '00' && ` + border-top: 1px solid ${props.theme.primaryDark}; + `} + ${props => props.time.slice(-2) === '30' && ` + border-top: 1px dotted ${props.theme.primaryDark}; + `} + + background-color: ${props => `${props.theme.primary}${Math.round((props.people.length/(props.totalPeople))*255).toString(16)}`}; +`; + +export const Spacer = styled.div` + width: 12px; + flex-shrink: 0; +`; + +export const Tooltip = styled.div` + position: fixed; + top: ${props => props.y+6}px; + left: ${props => props.x+6}px; + border: 1px solid ${props => props.theme.text}; + border-radius: 3px; + padding: 4px 8px; + background-color: ${props => props.theme.background}; + max-width: 200px; +`; + +export const TooltipTitle = styled.span` + font-size: 15px; + display: block; + font-weight: 700; +`; + +export const TooltipDate = styled.span` + font-size: 13px; + display: block; + opacity: .7; + font-weight: 700; +`; + +export const TooltipContent = styled.span` + font-size: 13px; + display: block; +`; diff --git a/crabfit-frontend/src/components/CalendarField/CalendarField.tsx b/crabfit-frontend/src/components/CalendarField/CalendarField.tsx index e8cbe8c..3f79424 100644 --- a/crabfit-frontend/src/components/CalendarField/CalendarField.tsx +++ b/crabfit-frontend/src/components/CalendarField/CalendarField.tsx @@ -1,6 +1,7 @@ import { useState, useEffect, useRef } from 'react'; import dayjs from 'dayjs'; import isToday from 'dayjs/plugin/isToday'; +import localeData from 'dayjs/plugin/localeData'; import { Button } from 'components'; import { @@ -15,31 +16,7 @@ import { } from './calendarFieldStyle'; dayjs.extend(isToday); - -const days = [ - 'Sun', - 'Mon', - 'Tue', - 'Wed', - 'Thu', - 'Fri', - 'Sat', -]; - -const months = [ - 'January', - 'February', - 'March', - 'April', - 'May', - 'June', - 'July', - 'August', - 'September', - 'October', - 'November', - 'December', -]; +dayjs.extend(localeData); const calculateMonth = (month, year) => { const date = dayjs().month(month).year(year); @@ -123,7 +100,7 @@ const CalendarField = ({ } }} >< - {months[month]} {year} + {dayjs.months()[month]} {year} + + These details are only for this event. Use a password to prevent others from changing your availability. + + + + + + + + { + e.preventDefault(); + if (false) { + setTab('you'); + } + }} + selected={tab === 'you'} + disabled={true} + title={true ? 'Login to set your availability' : ''} + >Your availability + { + e.preventDefault(); + setTab('group'); + }} + selected={tab === 'group'} + >Group availability + + + + {tab === 'group' ? ( +
+ + +
Hover and click the calendar below to see who is available
+
+ +
+ ) : ( +
+ +
Click and drag the calendar below to set your availabilities
+
+
+ )} + + + ); }; diff --git a/crabfit-frontend/src/pages/Event/eventStyle.ts b/crabfit-frontend/src/pages/Event/eventStyle.ts new file mode 100644 index 0000000..0723f4f --- /dev/null +++ b/crabfit-frontend/src/pages/Event/eventStyle.ts @@ -0,0 +1,100 @@ +import styled from '@emotion/styled'; + +export const StyledMain = styled.div` + width: 600px; + margin: 20px auto; + max-width: calc(100% - 60px); +`; + +export const Footer = styled.footer` + width: 600px; + margin: 20px auto; + max-width: calc(100% - 60px); + display: flex; + align-items: center; + justify-content: space-between; +`; + +export const Logo = styled.img` + width: 2.5rem; + margin-right: 16px; +`; + +export const Title = styled.span` + display: block; + font-size: 2rem; + color: ${props => props.theme.primary}; + font-family: 'Molot'; + font-weight: 400; + text-shadow: 0 2px 0 ${props => props.theme.primaryDark}; + line-height: 1em; +`; + +export const EventName = styled.h1` + text-align: center; + font-weight: 800; + margin: 20px 0 14px; +`; + +export const LoginForm = styled.form` + display: grid; + grid-template-columns: 1fr 1fr 100px; + align-items: flex-end; + grid-gap: 18px; + + @media (max-width: 500px) { + grid-template-columns: 1fr 1fr; + } + @media (max-width: 400px) { + grid-template-columns: 1fr; + } +`; + +export const LoginSection = styled.section` + background-color: ${props => props.theme.primaryBackground}; + padding: 10px 0; +`; + +export const Info = styled.p` + margin: 18px 0; + opacity: .6; + font-size: 12px; +`; + +export const ShareInfo = styled.p` + margin: 6px 0; + text-align: center; + font-size: 15px; +`; + +export const Tabs = styled.div` + display: flex; + align-items: center; + justify-content: center; + margin: 30px 0 20px; +`; + +export const Tab = styled.a` + user-select: none; + text-decoration: none; + display: block; + color: ${props => props.theme.text}; + padding: 8px 18px; + background-color: ${props => props.theme.primaryBackground}; + border: 1px solid ${props => props.theme.primaryLight}; + border-bottom: 0; + margin: 0 4px; + border-top-left-radius: 5px; + border-top-right-radius: 5px; + + ${props => props.selected && ` + color: #FFF; + background-color: ${props.theme.primary}; + border-color: ${props.theme.primary}; + `} + + ${props => props.disabled && ` + opacity: .5; + cursor: not-allowed; + `} +`; diff --git a/crabfit-frontend/src/pages/Home/Home.tsx b/crabfit-frontend/src/pages/Home/Home.tsx index ea9cf0a..cc061d6 100644 --- a/crabfit-frontend/src/pages/Home/Home.tsx +++ b/crabfit-frontend/src/pages/Home/Home.tsx @@ -61,6 +61,7 @@ const Home = () => { subLabel="Click and drag to select" name="dates" id="dates" + required register={register} /> @@ -69,6 +70,7 @@ const Home = () => { subLabel="Click and drag to select a time range" name="times" id="times" + required register={register} />