diff --git a/crabfit-frontend/src/App.jsx b/crabfit-frontend/src/App.jsx
index 7f0c73a..8a1a401 100644
--- a/crabfit-frontend/src/App.jsx
+++ b/crabfit-frontend/src/App.jsx
@@ -66,8 +66,8 @@ const App = () => {
} />
} />
} />
- {/* } />
- } /> */}
+ } />
+ } />
diff --git a/crabfit-frontend/src/pages/Create/Create.tsx b/crabfit-frontend/src/pages/Create/Create.jsx
similarity index 66%
rename from crabfit-frontend/src/pages/Create/Create.tsx
rename to crabfit-frontend/src/pages/Create/Create.jsx
index f63213f..87350c4 100644
--- a/crabfit-frontend/src/pages/Create/Create.tsx
+++ b/crabfit-frontend/src/pages/Create/Create.jsx
@@ -1,12 +1,12 @@
-import { useEffect, useState } from 'react';
-import { useHistory } from 'react-router-dom';
-import { useForm } from 'react-hook-form';
-import { useTranslation, Trans } from 'react-i18next';
+import { useEffect, useState } from 'react'
+import { useNavigate } from 'react-router-dom'
+import { useForm } from 'react-hook-form'
+import { useTranslation, Trans } from 'react-i18next'
-import dayjs from 'dayjs';
-import utc from 'dayjs/plugin/utc';
-import timezone from 'dayjs/plugin/timezone';
-import customParseFormat from 'dayjs/plugin/customParseFormat';
+import dayjs from 'dayjs'
+import utc from 'dayjs/plugin/utc'
+import timezone from 'dayjs/plugin/timezone'
+import customParseFormat from 'dayjs/plugin/customParseFormat'
import {
TextField,
@@ -17,7 +17,7 @@ import {
Error,
Recents,
Footer,
-} from 'components';
+} from '/src/components'
import {
StyledMain,
@@ -27,80 +27,80 @@ import {
P,
OfflineMessage,
ShareInfo,
-} from './createStyle';
+} from './Create.styles'
-import api from 'services';
-import { useRecentsStore } from 'stores';
+import api from '/src/services'
+import { useRecentsStore } from '/src/stores'
-import timezones from 'res/timezones.json';
+import timezones from '/src/res/timezones.json'
-dayjs.extend(utc);
-dayjs.extend(timezone);
-dayjs.extend(customParseFormat);
+dayjs.extend(utc)
+dayjs.extend(timezone)
+dayjs.extend(customParseFormat)
const Create = ({ offline }) => {
const { register, handleSubmit, setValue } = useForm({
defaultValues: {
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
},
- });
- const [isLoading, setIsLoading] = useState(false);
- const [error, setError] = useState(null);
- const [createdEvent, setCreatedEvent] = useState(null);
- const [copied, setCopied] = useState(null);
- const [showFooter, setShowFooter] = useState(true);
+ })
+ const [isLoading, setIsLoading] = useState(false)
+ const [error, setError] = useState(null)
+ const [createdEvent, setCreatedEvent] = useState(null)
+ const [copied, setCopied] = useState(null)
+ const [showFooter, setShowFooter] = useState(true)
- const { push } = useHistory();
- const { t } = useTranslation(['common', 'home', 'event']);
+ const navigate = useNavigate()
+ const { t } = useTranslation(['common', 'home', 'event'])
- const addRecent = useRecentsStore(state => state.addRecent);
+ const addRecent = useRecentsStore(state => state.addRecent)
useEffect(() => {
if (window.self === window.top) {
- push('/');
+ navigate('/')
}
- document.title = 'Create a Crab Fit';
+ document.title = 'Create a Crab Fit'
if (window.parent) {
- window.parent.postMessage('crabfit-create', '*');
+ window.parent.postMessage('crabfit-create', '*')
window.addEventListener('message', e => {
if (e.data === 'safari-extension') {
- setShowFooter(false);
+ setShowFooter(false)
}
}, {
once: true
- });
+ })
}
- }, [push]);
+ }, [navigate])
const onSubmit = async data => {
- setIsLoading(true);
- setError(null);
+ setIsLoading(true)
+ setError(null)
try {
- const { start, end } = JSON.parse(data.times);
- const dates = JSON.parse(data.dates);
+ const { start, end } = JSON.parse(data.times)
+ const dates = JSON.parse(data.dates)
if (dates.length === 0) {
- return setError(t('home:form.errors.no_dates'));
+ return setError(t('home:form.errors.no_dates'))
}
- const isSpecificDates = typeof dates[0] === 'string' && dates[0].length === 8;
+ const isSpecificDates = typeof dates[0] === 'string' && dates[0].length === 8
if (start === end) {
- return setError(t('home:form.errors.same_times'));
+ return setError(t('home:form.errors.same_times'))
}
- let times = dates.reduce((times, date) => {
- let day = [];
+ const times = dates.reduce((times, date) => {
+ const day = []
for (let i = start; i < (start > end ? 24 : end); i++) {
if (isSpecificDates) {
day.push(
dayjs.tz(date, 'DDMMYYYY', data.timezone)
- .hour(i).minute(0).utc().format('HHmm-DDMMYYYY')
- );
+ .hour(i).minute(0).utc().format('HHmm-DDMMYYYY')
+ )
} else {
day.push(
dayjs().tz(data.timezone)
- .day(date).hour(i).minute(0).utc().format('HHmm-d')
- );
+ .day(date).hour(i).minute(0).utc().format('HHmm-d')
+ )
}
}
if (start > end) {
@@ -108,21 +108,21 @@ const Create = ({ offline }) => {
if (isSpecificDates) {
day.push(
dayjs.tz(date, 'DDMMYYYY', data.timezone)
- .hour(i).minute(0).utc().format('HHmm-DDMMYYYY')
- );
+ .hour(i).minute(0).utc().format('HHmm-DDMMYYYY')
+ )
} else {
day.push(
dayjs().tz(data.timezone)
- .day(date).hour(i).minute(0).utc().format('HHmm-d')
- );
+ .day(date).hour(i).minute(0).utc().format('HHmm-d')
+ )
}
}
}
- return [...times, ...day];
- }, []);
+ return [...times, ...day]
+ }, [])
if (times.length === 0) {
- return setError(t('home:form.errors.no_time'));
+ return setError(t('home:form.errors.no_time'))
}
const response = await api.post('/event', {
@@ -131,23 +131,23 @@ const Create = ({ offline }) => {
times: times,
timezone: data.timezone,
},
- });
- setCreatedEvent(response.data);
+ })
+ setCreatedEvent(response.data)
addRecent({
id: response.data.id,
created: response.data.created,
name: response.data.name,
- });
+ })
gtag('event', 'create_event', {
'event_category': 'create',
- });
+ })
} catch (e) {
- setError(t('home:form.errors.unknown'));
- console.error(e);
+ setError(t('home:form.errors.unknown'))
+ console.error(e)
} finally {
- setIsLoading(false);
+ setIsLoading(false)
}
- };
+ }
return (
<>
@@ -162,16 +162,16 @@ const Create = ({ offline }) => {
{createdEvent?.name}
navigator.clipboard?.writeText(`https://crab.fit/${createdEvent.id}`)
- .then(() => {
- setCopied(t('event:nav.copied'));
- setTimeout(() => setCopied(null), 1000);
- gtag('event', 'copy_link', {
- 'event_category': 'event',
- });
+ .then(() => {
+ setCopied(t('event:nav.copied'))
+ setTimeout(() => setCopied(null), 1000)
+ gtag('event', 'copy_link', {
+ 'event_category': 'event',
})
- .catch((e) => console.error('Failed to copy', e))
+ })
+ .catch(e => console.error('Failed to copy', e))
}
- title={!!navigator.clipboard ? t('event:nav.title') : ''}
+ title={navigator.clipboard ? t('event:nav.title') : ''}
>{copied ?? `https://crab.fit/${createdEvent?.id}`}
{/* eslint-disable-next-line */}
@@ -236,7 +236,7 @@ const Create = ({ offline }) => {
>
)}
>
- );
-};
+ )
+}
-export default Create;
+export default Create
diff --git a/crabfit-frontend/src/pages/Create/createStyle.ts b/crabfit-frontend/src/pages/Create/Create.styles.js
similarity index 57%
rename from crabfit-frontend/src/pages/Create/createStyle.ts
rename to crabfit-frontend/src/pages/Create/Create.styles.js
index 6b3d021..1da9a0a 100644
--- a/crabfit-frontend/src/pages/Create/createStyle.ts
+++ b/crabfit-frontend/src/pages/Create/Create.styles.js
@@ -1,50 +1,50 @@
-import styled from '@emotion/styled';
+import { styled } from 'goober'
-export const StyledMain = styled.div`
+export const StyledMain = styled('div')`
width: 600px;
margin: 10px auto;
max-width: calc(100% - 30px);
-`;
+`
-export const CreateForm = styled.form`
+export const CreateForm = styled('form')`
margin: 0 0 30px;
-`;
+`
-export const TitleSmall = styled.span`
+export const TitleSmall = styled('span')`
display: block;
margin: 0;
font-size: 2rem;
text-align: center;
font-family: 'Samurai Bob', sans-serif;
font-weight: 400;
- color: ${props => props.theme.primaryDark};
+ color: var(--secondary);
line-height: 1em;
text-transform: uppercase;
-`;
+`
-export const TitleLarge = styled.h1`
+export const TitleLarge = styled('h1')`
margin: 0;
font-size: 2rem;
text-align: center;
- color: ${props => props.theme.primary};
+ color: var(--primary);
font-family: 'Molot', sans-serif;
font-weight: 400;
- text-shadow: 0 3px 0 ${props => props.theme.primaryDark};
+ text-shadow: 0 3px 0 var(--secondary);
line-height: 1em;
text-transform: uppercase;
-`;
+`
-export const P = styled.p`
+export const P = styled('p')`
font-weight: 500;
line-height: 1.6em;
-`;
+`
-export const OfflineMessage = styled.div`
+export const OfflineMessage = styled('div')`
text-align: center;
margin: 50px 0 20px;
-`;
+`
-export const ShareInfo = styled.p`
+export const ShareInfo = styled('p')`
margin: 6px 0;
text-align: center;
font-size: 15px;
@@ -54,7 +54,7 @@ export const ShareInfo = styled.p`
cursor: pointer;
&:hover {
- color: ${props.theme.primaryDark};
+ color: var(--secondary);
}
`}
-`;
+`
diff --git a/crabfit-frontend/src/pages/Event/Event.tsx b/crabfit-frontend/src/pages/Event/Event.jsx
similarity index 60%
rename from crabfit-frontend/src/pages/Event/Event.tsx
rename to crabfit-frontend/src/pages/Event/Event.jsx
index 1a63e58..4d74464 100644
--- a/crabfit-frontend/src/pages/Event/Event.tsx
+++ b/crabfit-frontend/src/pages/Event/Event.jsx
@@ -1,12 +1,13 @@
-import { useForm } from 'react-hook-form';
-import { useState, useEffect } from 'react';
-import { useTranslation, Trans } from 'react-i18next';
+import { useForm } from 'react-hook-form'
+import { useState, useEffect } from 'react'
+import { useTranslation, Trans } from 'react-i18next'
+import { useParams } from 'react-router-dom'
-import dayjs from 'dayjs';
-import utc from 'dayjs/plugin/utc';
-import timezone from 'dayjs/plugin/timezone';
-import customParseFormat from 'dayjs/plugin/customParseFormat';
-import relativeTime from 'dayjs/plugin/relativeTime';
+import dayjs from 'dayjs'
+import utc from 'dayjs/plugin/utc'
+import timezone from 'dayjs/plugin/timezone'
+import customParseFormat from 'dayjs/plugin/customParseFormat'
+import relativeTime from 'dayjs/plugin/relativeTime'
import {
Footer,
@@ -17,9 +18,9 @@ import {
AvailabilityEditor,
Error,
Logo,
-} from 'components';
+} from '/src/components'
-import { StyledMain } from '../Home/homeStyle';
+import { StyledMain } from '../Home/Home.styles'
import {
EventName,
@@ -30,232 +31,227 @@ import {
ShareInfo,
Tabs,
Tab,
-} from './eventStyle';
+} from './Event.styles'
-import api from 'services';
-import { useSettingsStore, useRecentsStore, useLocaleUpdateStore } from 'stores';
+import api from '/src/services'
+import { useSettingsStore, useRecentsStore, useLocaleUpdateStore } from '/src/stores'
-import timezones from 'res/timezones.json';
+import timezones from '/src/res/timezones.json'
-dayjs.extend(utc);
-dayjs.extend(timezone);
-dayjs.extend(customParseFormat);
-dayjs.extend(relativeTime);
+dayjs.extend(utc)
+dayjs.extend(timezone)
+dayjs.extend(customParseFormat)
+dayjs.extend(relativeTime)
-const Event = (props) => {
- const timeFormat = useSettingsStore(state => state.timeFormat);
- const weekStart = useSettingsStore(state => state.weekStart);
+const Event = () => {
+ const timeFormat = useSettingsStore(state => state.timeFormat)
+ const weekStart = useSettingsStore(state => state.weekStart)
- const addRecent = useRecentsStore(state => state.addRecent);
- const removeRecent = useRecentsStore(state => state.removeRecent);
- const locale = useLocaleUpdateStore(state => state.locale);
+ const addRecent = useRecentsStore(state => state.addRecent)
+ const removeRecent = useRecentsStore(state => state.removeRecent)
+ const locale = useLocaleUpdateStore(state => state.locale)
- const { t } = useTranslation(['common', 'event']);
+ const { t } = useTranslation(['common', 'event'])
- const { register, handleSubmit, setFocus, reset } = useForm();
- const { id } = props.match.params;
- const { offline } = props;
- const [timezone, setTimezone] = useState(Intl.DateTimeFormat().resolvedOptions().timeZone);
- const [user, setUser] = useState(null);
- const [password, setPassword] = useState(null);
- const [tab, setTab] = useState(user ? 'you' : 'group');
- const [isLoading, setIsLoading] = useState(true);
- const [isLoginLoading, setIsLoginLoading] = useState(false);
- const [error, setError] = useState(null);
- const [event, setEvent] = useState(null);
- const [people, setPeople] = useState([]);
+ const { register, handleSubmit, setFocus, reset } = useForm()
+ const { id } = useParams()
+ const [timezone, setTimezone] = useState(Intl.DateTimeFormat().resolvedOptions().timeZone)
+ const [user, setUser] = useState(null)
+ const [password, setPassword] = useState(null)
+ const [tab, setTab] = useState(user ? 'you' : 'group')
+ const [isLoading, setIsLoading] = useState(true)
+ const [isLoginLoading, setIsLoginLoading] = useState(false)
+ const [error, setError] = useState(null)
+ const [event, setEvent] = useState(null)
+ const [people, setPeople] = useState([])
- const [times, setTimes] = useState([]);
- const [timeLabels, setTimeLabels] = useState([]);
- const [dates, setDates] = useState([]);
- const [min, setMin] = useState(0);
- const [max, setMax] = useState(0);
+ const [times, setTimes] = useState([])
+ const [timeLabels, setTimeLabels] = useState([])
+ const [dates, setDates] = useState([])
+ const [min, setMin] = useState(0)
+ const [max, setMax] = useState(0)
- const [copied, setCopied] = useState(null);
+ const [copied, setCopied] = useState(null)
useEffect(() => {
const fetchEvent = async () => {
try {
- const response = await api.get(`/event/${id}`);
+ const response = await api.get(`/event/${id}`)
- setEvent(response.data);
+ setEvent(response.data)
addRecent({
id: response.data.id,
created: response.data.created,
name: response.data.name,
- });
- document.title = `${response.data.name} | Crab Fit`;
+ })
+ document.title = `${response.data.name} | Crab Fit`
} catch (e) {
- console.error(e);
+ console.error(e)
if (e.status === 404) {
- removeRecent(id);
+ removeRecent(id)
}
} finally {
- setIsLoading(false);
+ setIsLoading(false)
}
- };
+ }
- fetchEvent();
- }, [id, addRecent, removeRecent]);
+ fetchEvent()
+ }, [id, addRecent, removeRecent])
useEffect(() => {
const fetchPeople = async () => {
try {
- const response = await api.get(`/event/${id}/people`);
+ const response = await api.get(`/event/${id}/people`)
const adjustedPeople = response.data.people.map(person => ({
...person,
availability: (!!person.availability.length && person.availability[0].length === 13)
? person.availability.map(date => dayjs(date, 'HHmm-DDMMYYYY').utc(true).tz(timezone).format('HHmm-DDMMYYYY'))
: person.availability.map(date => dayjs(date, 'HHmm').day(date.substring(5)).utc(true).tz(timezone).format('HHmm-d')),
- }));
- setPeople(adjustedPeople);
+ }))
+ setPeople(adjustedPeople)
} catch (e) {
- console.error(e);
+ console.error(e)
}
}
if (tab === 'group') {
- fetchPeople();
+ fetchPeople()
}
- }, [tab, id, timezone]);
+ }, [tab, id, timezone])
// Convert to timezone and expand minute segments
useEffect(() => {
if (event) {
- const isSpecificDates = event.times[0].length === 13;
+ const isSpecificDates = event.times[0].length === 13
setTimes(event.times.reduce(
(allTimes, time) => {
const date = isSpecificDates ?
dayjs(time, 'HHmm-DDMMYYYY').utc(true).tz(timezone)
- : dayjs(time, 'HHmm').day(time.substring(5)).utc(true).tz(timezone);
- const format = isSpecificDates ? 'HHmm-DDMMYYYY' : 'HHmm-d';
+ : dayjs(time, 'HHmm').day(time.substring(5)).utc(true).tz(timezone)
+ const format = isSpecificDates ? 'HHmm-DDMMYYYY' : 'HHmm-d'
return [
...allTimes,
date.minute(0).format(format),
date.minute(15).format(format),
date.minute(30).format(format),
date.minute(45).format(format),
- ];
+ ]
},
[]
).sort((a, b) => {
if (isSpecificDates) {
- return dayjs(a, 'HHmm-DDMMYYYY').diff(dayjs(b, 'HHmm-DDMMYYYY'));
+ return dayjs(a, 'HHmm-DDMMYYYY').diff(dayjs(b, 'HHmm-DDMMYYYY'))
} else {
return dayjs(a, 'HHmm').day((parseInt(a.substring(5))-weekStart % 7 + 7) % 7)
- .diff(dayjs(b, 'HHmm').day((parseInt(b.substring(5))-weekStart % 7 + 7) % 7));
+ .diff(dayjs(b, 'HHmm').day((parseInt(b.substring(5))-weekStart % 7 + 7) % 7))
}
- }));
+ }))
}
- }, [event, timezone, weekStart]);
+ }, [event, timezone, weekStart])
useEffect(() => {
if (!!times.length && !!people.length) {
setMin(times.reduce((min, time) => {
- let total = people.reduce(
- (total, person) => person.availability.includes(time) ? total+1 : total,
- 0
- );
- return total < min ? total : min;
- },
- Infinity
- ));
+ const total = people.reduce(
+ (total, person) => person.availability.includes(time) ? total+1 : total,
+ 0
+ )
+ return total < min ? total : min
+ }, Infinity))
setMax(times.reduce((max, time) => {
- let total = people.reduce(
- (total, person) => person.availability.includes(time) ? total+1 : total,
- 0
- );
- return total > max ? total : max;
- },
- -Infinity
- ));
+ const total = people.reduce(
+ (total, person) => person.availability.includes(time) ? total+1 : total,
+ 0
+ )
+ return total > max ? total : max
+ }, -Infinity))
}
- }, [times, people]);
+ }, [times, people])
useEffect(() => {
- if (!!times.length) {
+ if (times.length) {
setTimeLabels(times.reduce((labels, datetime) => {
- const time = datetime.substring(0, 4);
- if (labels.includes(time)) return labels;
- return [...labels, time];
+ const time = datetime.substring(0, 4)
+ if (labels.includes(time)) return labels
+ return [...labels, time]
}, [])
- .sort((a, b) => parseInt(a) - parseInt(b))
- .reduce((labels, time, i, allTimes) => {
- if (time.substring(2) === '30') return [...labels, { label: '', time }];
- if (allTimes.length - 1 === i) return [
- ...labels,
- { label: '', time },
- { label: dayjs(time, 'HHmm').add(1, 'hour').format(timeFormat === '12h' ? 'h A' : 'HH'), time: null }
- ];
- if (allTimes.length - 1 > i && parseInt(allTimes[i+1].substring(0, 2))-1 > parseInt(time.substring(0, 2))) return [
- ...labels,
- { label: '', time },
- { label: dayjs(time, 'HHmm').add(1, 'hour').format(timeFormat === '12h' ? 'h A' : 'HH'), time: 'space' },
- { label: '', time: 'space' },
- { label: '', time: 'space' },
- ];
- if (time.substring(2) !== '00') return [...labels, { label: '', time }];
- return [...labels, { label: dayjs(time, 'HHmm').format(timeFormat === '12h' ? 'h A' : 'HH'), time }];
- }, []));
+ .sort((a, b) => parseInt(a) - parseInt(b))
+ .reduce((labels, time, i, allTimes) => {
+ if (time.substring(2) === '30') return [...labels, { label: '', time }]
+ if (allTimes.length - 1 === i) return [
+ ...labels,
+ { label: '', time },
+ { label: dayjs(time, 'HHmm').add(1, 'hour').format(timeFormat === '12h' ? 'h A' : 'HH'), time: null }
+ ]
+ if (allTimes.length - 1 > i && parseInt(allTimes[i+1].substring(0, 2))-1 > parseInt(time.substring(0, 2))) return [
+ ...labels,
+ { label: '', time },
+ { label: dayjs(time, 'HHmm').add(1, 'hour').format(timeFormat === '12h' ? 'h A' : 'HH'), time: 'space' },
+ { label: '', time: 'space' },
+ { label: '', time: 'space' },
+ ]
+ if (time.substring(2) !== '00') return [...labels, { label: '', time }]
+ return [...labels, { label: dayjs(time, 'HHmm').format(timeFormat === '12h' ? 'h A' : 'HH'), time }]
+ }, []))
setDates(times.reduce((allDates, time) => {
- if (time.substring(2, 4) !== '00') return allDates;
- const date = time.substring(5);
- if (allDates.includes(date)) return allDates;
- return [...allDates, date];
- }, []));
+ if (time.substring(2, 4) !== '00') return allDates
+ const date = time.substring(5)
+ if (allDates.includes(date)) return allDates
+ return [...allDates, date]
+ }, []))
}
- }, [times, timeFormat, locale]);
+ }, [times, timeFormat, locale])
useEffect(() => {
const fetchUser = async () => {
try {
- const response = await api.post(`/event/${id}/people/${user.name}`, { person: { password } });
+ const response = await api.post(`/event/${id}/people/${user.name}`, { person: { password } })
const adjustedUser = {
...response.data,
availability: (!!response.data.availability.length && response.data.availability[0].length === 13)
? response.data.availability.map(date => dayjs(date, 'HHmm-DDMMYYYY').utc(true).tz(timezone).format('HHmm-DDMMYYYY'))
: response.data.availability.map(date => dayjs(date, 'HHmm').day(date.substring(5)).utc(true).tz(timezone).format('HHmm-d')),
- };
- setUser(adjustedUser);
+ }
+ setUser(adjustedUser)
} catch (e) {
- console.log(e);
+ console.log(e)
}
- };
+ }
if (user) {
- fetchUser();
+ fetchUser()
}
// eslint-disable-next-line
}, [timezone]);
const onSubmit = async data => {
if (!data.name || data.name.length === 0) {
- setFocus('name');
- return setError(t('event:form.errors.name_required'));
+ setFocus('name')
+ return setError(t('event:form.errors.name_required'))
}
- setIsLoginLoading(true);
- setError(null);
+ setIsLoginLoading(true)
+ setError(null)
try {
const response = await api.post(`/event/${id}/people/${data.name}`, {
person: {
password: data.password,
},
- });
- setPassword(data.password);
+ })
+ setPassword(data.password)
const adjustedUser = {
...response.data,
availability: (!!response.data.availability.length && response.data.availability[0].length === 13)
? response.data.availability.map(date => dayjs(date, 'HHmm-DDMMYYYY').utc(true).tz(timezone).format('HHmm-DDMMYYYY'))
: response.data.availability.map(date => dayjs(date, 'HHmm').day(date.substring(5)).utc(true).tz(timezone).format('HHmm-d')),
- };
- setUser(adjustedUser);
- setTab('you');
+ }
+ setUser(adjustedUser)
+ setTab('you')
} catch (e) {
if (e.status === 401) {
- setError(t('event:form.errors.password_incorrect'));
+ setError(t('event:form.errors.password_incorrect'))
} else if (e.status === 404) {
// Create user
try {
@@ -264,25 +260,25 @@ const Event = (props) => {
name: data.name,
password: data.password,
},
- });
- setPassword(data.password);
+ })
+ setPassword(data.password)
setUser({
name: data.name,
availability: [],
- });
- setTab('you');
+ })
+ setTab('you')
} catch (e) {
- setError(t('event:form.errors.unknown'));
+ setError(t('event:form.errors.unknown'))
}
}
} finally {
- setIsLoginLoading(false);
+ setIsLoginLoading(false)
gtag('event', 'login', {
'event_category': 'event',
- });
- reset();
+ })
+ reset()
}
- };
+ }
return (
<>
@@ -291,39 +287,32 @@ const Event = (props) => {
{(!!event || isLoading) ? (
<>
- {event?.name}
- {event?.created && t('common:created', { date: dayjs.unix(event?.created).fromNow() })}
+ {event?.name}
+ {event?.created && t('common:created', { date: dayjs.unix(event?.created).fromNow() })}
navigator.clipboard?.writeText(`https://crab.fit/${id}`)
- .then(() => {
- setCopied(t('event:nav.copied'));
- setTimeout(() => setCopied(null), 1000);
- gtag('event', 'copy_link', {
- 'event_category': 'event',
- });
+ .then(() => {
+ setCopied(t('event:nav.copied'))
+ setTimeout(() => setCopied(null), 1000)
+ gtag('event', 'copy_link', {
+ 'event_category': 'event',
})
- .catch((e) => console.error('Failed to copy', e))
+ })
+ .catch(e => console.error('Failed to copy', e))
}
- title={!!navigator.clipboard ? t('event:nav.title') : ''}
+ title={navigator.clipboard ? t('event:nav.title') : ''}
>{copied ?? `https://crab.fit/${id}`}
-
+
{!!event?.name &&
Copy the link to this page, or share via gtag('event', 'send_email', { 'event_category': 'event' })} href={`mailto:?subject=${encodeURIComponent(t('event:nav.email_subject', { event_name: event?.name }))}&body=${encodeURIComponent(`${t('event:nav.email_body')} https://crab.fit/${id}`)}`}>email.
}
>
) : (
- offline ? (
-
- {t('event:offline.title')}
-
-
- ) : (
-
- {t('event:error.title')}
- {t('event:error.body')}
-
- )
+
+ {t('event:error.title')}
+ {t('event:error.body')}
+
)}
@@ -335,9 +324,9 @@ const Event = (props) => {
{t('event:form.signed_in', { name: user.name })}
) : (
@@ -363,7 +352,7 @@ const Event = (props) => {
@@ -383,8 +372,8 @@ const Event = (props) => {
/>
{/* eslint-disable-next-line */}
{event?.timezone && event.timezone !== timezone && This event was created in the timezone {{timezone: event.timezone}}. {
- e.preventDefault();
- setTimezone(event.timezone);
+ e.preventDefault()
+ setTimezone(event.timezone)
}}>Click here to use it.
}
{((
Intl.DateTimeFormat().resolvedOptions().timeZone !== timezone
@@ -395,8 +384,8 @@ const Event = (props) => {
)) && (
/* eslint-disable-next-line */
Your local timezone is detected to be {{timezone: Intl.DateTimeFormat().resolvedOptions().timeZone}}. {
- e.preventDefault();
- setTimezone(Intl.DateTimeFormat().resolvedOptions().timeZone);
+ e.preventDefault()
+ setTimezone(Intl.DateTimeFormat().resolvedOptions().timeZone)
}}>Click here to use it.
)}
@@ -407,11 +396,11 @@ const Event = (props) => {
{
- e.preventDefault();
+ e.preventDefault()
if (user) {
- setTab('you');
+ setTab('you')
} else {
- setFocus('name');
+ setFocus('name')
}
}}
selected={tab === 'you'}
@@ -421,8 +410,8 @@ const Event = (props) => {
{
- e.preventDefault();
- setTab('group');
+ e.preventDefault()
+ setTab('group')
}}
selected={tab === 'group'}
>{t('event:tabs.group')}
@@ -451,21 +440,21 @@ const Event = (props) => {
isSpecificDates={!!dates.length && dates[0].length === 8}
value={user.availability}
onChange={async availability => {
- const oldAvailability = [...user.availability];
+ const oldAvailability = [...user.availability]
const utcAvailability = (!!availability.length && availability[0].length === 13)
? availability.map(date => dayjs.tz(date, 'HHmm-DDMMYYYY', timezone).utc().format('HHmm-DDMMYYYY'))
- : availability.map(date => dayjs.tz(date, 'HHmm', timezone).day(date.substring(5)).utc().format('HHmm-d'));
- setUser({ ...user, availability });
+ : availability.map(date => dayjs.tz(date, 'HHmm', timezone).day(date.substring(5)).utc().format('HHmm-d'))
+ setUser({ ...user, availability })
try {
await api.patch(`/event/${id}/people/${user.name}`, {
person: {
password,
availability: utcAvailability,
},
- });
+ })
} catch (e) {
- console.log(e);
- setUser({ ...user, oldAvailability });
+ console.log(e)
+ setUser({ ...user, oldAvailability })
}
}}
/>
@@ -476,7 +465,7 @@ const Event = (props) => {
>
- );
-};
+ )
+}
-export default Event;
+export default Event
diff --git a/crabfit-frontend/src/pages/Event/eventStyle.ts b/crabfit-frontend/src/pages/Event/Event.styles.js
similarity index 63%
rename from crabfit-frontend/src/pages/Event/eventStyle.ts
rename to crabfit-frontend/src/pages/Event/Event.styles.js
index c554204..2cd9d64 100644
--- a/crabfit-frontend/src/pages/Event/eventStyle.ts
+++ b/crabfit-frontend/src/pages/Event/Event.styles.js
@@ -1,24 +1,24 @@
-import styled from '@emotion/styled';
+import { styled } from 'goober'
-export const EventName = styled.h1`
+export const EventName = styled('h1')`
text-align: center;
font-weight: 800;
margin: 20px 0 5px;
- ${props => props.isLoading && `
+ ${props => props.$isLoading && `
&:after {
content: '';
display: inline-block;
height: 1em;
width: 400px;
max-width: 100%;
- background-color: ${props.theme.loading};
+ background-color: var(--loading);
border-radius: 3px;
}
`}
-`;
+`
-export const EventDate = styled.span`
+export const EventDate = styled('span')`
display: block;
text-align: center;
font-size: 14px;
@@ -27,14 +27,14 @@ export const EventDate = styled.span`
font-weight: 500;
letter-spacing: .01em;
- ${props => props.isLoading && `
+ ${props => props.$isLoading && `
&:after {
content: '';
display: inline-block;
height: 1em;
width: 200px;
max-width: 100%;
- background-color: ${props.theme.loading};
+ background-color: var(--loading);
border-radius: 3px;
}
`}
@@ -44,9 +44,9 @@ export const EventDate = styled.span`
content: ' - ' attr(title);
}
}
-`;
+`
-export const LoginForm = styled.form`
+export const LoginForm = styled('form')`
display: grid;
grid-template-columns: 1fr 1fr auto;
align-items: flex-end;
@@ -62,36 +62,36 @@ export const LoginForm = styled.form`
--btn-width: 100%;
}
}
-`;
+`
-export const LoginSection = styled.section`
- background-color: ${props => props.theme.primaryBackground};
+export const LoginSection = styled('section')`
+ background-color: var(--surface);
padding: 10px 0;
@media print {
display: none;
}
-`;
+`
-export const Info = styled.p`
+export const Info = styled('p')`
margin: 18px 0;
opacity: .6;
font-size: 12px;
-`;
+`
-export const ShareInfo = styled.p`
+export const ShareInfo = styled('p')`
margin: 6px 0;
text-align: center;
font-size: 15px;
- ${props => props.isLoading && `
+ ${props => props.$isLoading && `
&:after {
content: '';
display: inline-block;
height: 1em;
width: 300px;
max-width: 100%;
- background-color: ${props.theme.loading};
+ background-color: var(--loading);
border-radius: 3px;
}
`}
@@ -100,7 +100,7 @@ export const ShareInfo = styled.p`
cursor: pointer;
&:hover {
- color: ${props.theme.mode === 'light' ? props.theme.primaryDark : props.theme.primaryLight};
+ color: var(--secondary);
}
`}
@@ -109,40 +109,40 @@ export const ShareInfo = styled.p`
display: none;
}
}
-`;
+`
-export const Tabs = styled.div`
+export const Tabs = styled('div')`
display: flex;
align-items: center;
justify-content: center;
margin: 30px 0 20px;
-
+
@media print {
display: none;
}
-`;
+`
-export const Tab = styled.a`
+export const Tab = styled('a')`
user-select: none;
text-decoration: none;
display: block;
- color: ${props => props.theme.text};
+ color: var(--text);
padding: 8px 18px;
- background-color: ${props => props.theme.primaryBackground};
- border: 1px solid ${props => props.theme.primary};
+ background-color: var(--surface);
+ border: 1px solid var(--primary);
border-bottom: 0;
margin: 0 4px;
border-top-left-radius: 5px;
border-top-right-radius: 5px;
- ${props => props.selected && `
+ ${props => props.$selected && `
color: #FFF;
- background-color: ${props.theme.primary};
- border-color: ${props.theme.primary};
+ background-color: var(--primary);
+ border-color: var(--primary);
`}
${props => props.disabled && `
opacity: .5;
cursor: not-allowed;
`}
-`;
+`
diff --git a/crabfit-frontend/src/pages/index.js b/crabfit-frontend/src/pages/index.js
index 8946c0d..8e5bbde 100644
--- a/crabfit-frontend/src/pages/index.js
+++ b/crabfit-frontend/src/pages/index.js
@@ -1,7 +1,7 @@
import { lazy } from 'react'
export const Home = lazy(() => import('./Home/Home'))
-//export const Event = lazy(() => import('./Event/Event'))
-//export const Create = lazy(() => import('./Create/Create'))
+export const Event = lazy(() => import('./Event/Event'))
+export const Create = lazy(() => import('./Create/Create'))
export const Help = lazy(() => import('./Help/Help'))
export const Privacy = lazy(() => import('./Privacy/Privacy'))
diff --git a/crabfit-frontend/src/sw.js b/crabfit-frontend/src/sw.js
index 22517fe..198d965 100644
--- a/crabfit-frontend/src/sw.js
+++ b/crabfit-frontend/src/sw.js
@@ -1,38 +1,38 @@
/* eslint-disable no-restricted-globals */
-import { clientsClaim, skipWaiting } from 'workbox-core';
-import { ExpirationPlugin } from 'workbox-expiration';
-import { precacheAndRoute, createHandlerBoundToURL } from 'workbox-precaching';
-import { registerRoute } from 'workbox-routing';
-import { StaleWhileRevalidate, NetworkFirst } from 'workbox-strategies';
+import { clientsClaim, skipWaiting } from 'workbox-core'
+import { ExpirationPlugin } from 'workbox-expiration'
+import { precacheAndRoute, createHandlerBoundToURL } from 'workbox-precaching'
+import { registerRoute } from 'workbox-routing'
+import { StaleWhileRevalidate, NetworkFirst } from 'workbox-strategies'
-skipWaiting();
-clientsClaim();
+skipWaiting()
+clientsClaim()
// Injection point
-precacheAndRoute(self.__WB_MANIFEST);
+precacheAndRoute(self.__WB_MANIFEST)
-const fileExtensionRegexp = new RegExp('/[^/?]+\\.[^/]+$');
+const fileExtensionRegexp = new RegExp('/[^/?]+\\.[^/]+$')
registerRoute(
// Return false to exempt requests from being fulfilled by index.html.
({ request, url }) => {
// If this isn't a navigation, skip.
if (request.mode !== 'navigate') {
- return false;
+ return false
} // If this is a URL that starts with /_, skip.
if (url.pathname.startsWith('/_')) {
- return false;
+ return false
} // If this looks like a URL for a resource, because it contains // a file extension, skip.
if (url.pathname.match(fileExtensionRegexp)) {
- return false;
+ return false
} // Return true to signal that we want to use the handler.
- return true;
+ return true
},
createHandlerBoundToURL(process.env.PUBLIC_URL + '/index.html')
-);
+)
registerRoute(
// Add in any other file extensions or routing criteria as needed.
@@ -54,7 +54,7 @@ registerRoute(
new ExpirationPlugin({ maxEntries: 50 }),
],
})
-);
+)
registerRoute(
// Add in any other file extensions or routing criteria as needed.
@@ -62,4 +62,4 @@ registerRoute(
new NetworkFirst({
cacheName: 'i18n',
})
-);
+)