From 01a9b55b6a2feec93a5c3f2a86484dc18efdd9be Mon Sep 17 00:00:00 2001 From: Ben Grant Date: Mon, 12 Apr 2021 12:09:10 +1000 Subject: [PATCH 1/5] Dark mode toggle in settings --- .gitignore | 1 + crabfit-frontend/src/App.tsx | 10 ++++++++-- crabfit-frontend/src/components/Settings/Settings.tsx | 9 +++++++++ .../src/components/Settings/settingsStyle.ts | 4 +++- crabfit-frontend/src/stores/index.ts | 2 ++ 5 files changed, 23 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 2e90540..cfc9619 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /graphics +.DS_Store diff --git a/crabfit-frontend/src/App.tsx b/crabfit-frontend/src/App.tsx index e7fd787..9163223 100644 --- a/crabfit-frontend/src/App.tsx +++ b/crabfit-frontend/src/App.tsx @@ -1,4 +1,4 @@ -import { useState, Suspense, lazy } from 'react'; +import { useState, useEffect, Suspense, lazy } from 'react'; import { BrowserRouter, Switch, @@ -8,16 +8,22 @@ import { ThemeProvider, Global } from '@emotion/react'; import { Settings, Loading } from 'components'; +import { useSettingsStore } from 'stores'; import theme from 'theme'; const Home = lazy(() => import('pages/Home/Home')); const Event = lazy(() => import('pages/Event/Event')); const App = () => { + const colortheme = useSettingsStore(state => state.theme); const darkQuery = window.matchMedia('(prefers-color-scheme: dark)'); const [isDark, setIsDark] = useState(darkQuery.matches); - darkQuery.addListener(e => setIsDark(e.matches)); + darkQuery.addListener(e => colortheme === 'System' && setIsDark(e.matches)); + + useEffect(() => { + setIsDark(colortheme === 'System' ? darkQuery.matches : colortheme === 'Dark'); + }, [colortheme]); return ( diff --git a/crabfit-frontend/src/components/Settings/Settings.tsx b/crabfit-frontend/src/components/Settings/Settings.tsx index a2ac8d2..576dd39 100644 --- a/crabfit-frontend/src/components/Settings/Settings.tsx +++ b/crabfit-frontend/src/components/Settings/Settings.tsx @@ -49,6 +49,15 @@ const Settings = () => { value={store.timeFormat} onChange={value => store.setTimeFormat(value)} /> + + store.setTheme(value)} + /> ); diff --git a/crabfit-frontend/src/components/Settings/settingsStyle.ts b/crabfit-frontend/src/components/Settings/settingsStyle.ts index 2c4fe75..af70cfa 100644 --- a/crabfit-frontend/src/components/Settings/settingsStyle.ts +++ b/crabfit-frontend/src/components/Settings/settingsStyle.ts @@ -50,7 +50,9 @@ export const Modal = styled.div` top: 70px; right: 12px; background-color: ${props => props.theme.background}; - border: 1px solid ${props => props.theme.primaryBackground}; + ${props => props.theme.mode === 'dark' && ` + border: 1px solid ${props.theme.primaryBackground}; + `} z-index: 150; padding: 10px 18px; border-radius: 3px; diff --git a/crabfit-frontend/src/stores/index.ts b/crabfit-frontend/src/stores/index.ts index 7eea586..7bcf3ba 100644 --- a/crabfit-frontend/src/stores/index.ts +++ b/crabfit-frontend/src/stores/index.ts @@ -5,9 +5,11 @@ export const useSettingsStore = create(persist( set => ({ weekStart: 0, timeFormat: '12h', + theme: 'System', setWeekStart: weekStart => set({ weekStart }), setTimeFormat: timeFormat => set({ timeFormat }), + setTheme: theme => set({ theme }), }), { name: 'crabfit-settings' }, )); From ad9863f2dea3dfb632ba1bb7e7a7fc4d3b26f0ee Mon Sep 17 00:00:00 2001 From: Ben Grant Date: Mon, 12 Apr 2021 13:06:10 +1000 Subject: [PATCH 2/5] Dev database --- crabfit-backend/index.js | 6 +++++- crabfit-backend/package.json | 2 +- crabfit-backend/routes/createEvent.js | 2 +- crabfit-backend/routes/createPerson.js | 6 +++--- crabfit-backend/routes/getEvent.js | 2 +- crabfit-backend/routes/getPeople.js | 2 +- crabfit-backend/routes/login.js | 2 +- crabfit-backend/routes/stats.js | 4 ++-- crabfit-backend/routes/updatePerson.js | 2 +- crabfit-frontend/package.json | 2 +- 10 files changed, 17 insertions(+), 13 deletions(-) diff --git a/crabfit-backend/index.js b/crabfit-backend/index.js index f79daea..91b2c0b 100644 --- a/crabfit-backend/index.js +++ b/crabfit-backend/index.js @@ -27,6 +27,10 @@ const datastore = new Datastore({ app.use(express.json()); app.use((req, res, next) => { req.datastore = datastore; + req.types = { + event: process.env.NODE_ENV === 'production' ? 'Event' : 'DevEvent', + person: process.env.NODE_ENV === 'production' ? 'Person' : 'DevPerson', + }; next(); }); app.options('*', cors(corsOptions)); @@ -43,5 +47,5 @@ app.post('/event/:eventId/people/:personName', login); app.patch('/event/:eventId/people/:personName', updatePerson); app.listen(port, () => { - console.log(`Crabfit API listening at http://localhost:${port}`) + console.log(`Crabfit API listening at http://localhost:${port} in ${process.env.NODE_ENV === 'production' ? 'prod' : 'dev'} mode`) }); diff --git a/crabfit-backend/package.json b/crabfit-backend/package.json index c87703f..885330d 100644 --- a/crabfit-backend/package.json +++ b/crabfit-backend/package.json @@ -1,6 +1,6 @@ { "name": "crabfit-backend", - "version": "1.0.0", + "version": "1.1.0", "description": "API for Crabfit", "main": "index.js", "author": "Ben Grant", diff --git a/crabfit-backend/routes/createEvent.js b/crabfit-backend/routes/createEvent.js index ef821ff..4e54479 100644 --- a/crabfit-backend/routes/createEvent.js +++ b/crabfit-backend/routes/createEvent.js @@ -24,7 +24,7 @@ module.exports = async (req, res) => { const currentTime = dayjs().unix(); const entity = { - key: req.datastore.key(['Event', eventId]), + key: req.datastore.key([req.types.event, eventId]), data: { name: name, created: currentTime, diff --git a/crabfit-backend/routes/createPerson.js b/crabfit-backend/routes/createPerson.js index b118ac9..81846d3 100644 --- a/crabfit-backend/routes/createPerson.js +++ b/crabfit-backend/routes/createPerson.js @@ -6,8 +6,8 @@ module.exports = async (req, res) => { const { person } = req.body; try { - const event = (await req.datastore.get(req.datastore.key(['Event', eventId])))[0]; - const query = req.datastore.createQuery('Person') + const event = (await req.datastore.get(req.datastore.key([req.types.event, eventId])))[0]; + const query = req.datastore.createQuery(req.types.person) .filter('eventId', eventId) .filter('name', person.name); let personResult = (await req.datastore.runQuery(query))[0][0]; @@ -23,7 +23,7 @@ module.exports = async (req, res) => { } const entity = { - key: req.datastore.key('Person'), + key: req.datastore.key(req.types.person), data: { name: person.name.trim(), password: hash, diff --git a/crabfit-backend/routes/getEvent.js b/crabfit-backend/routes/getEvent.js index 1c98c23..b3a464d 100644 --- a/crabfit-backend/routes/getEvent.js +++ b/crabfit-backend/routes/getEvent.js @@ -2,7 +2,7 @@ module.exports = async (req, res) => { const { eventId } = req.params; try { - const event = (await req.datastore.get(req.datastore.key(['Event', eventId])))[0]; + const event = (await req.datastore.get(req.datastore.key([req.types.event, eventId])))[0]; if (event) { res.send({ diff --git a/crabfit-backend/routes/getPeople.js b/crabfit-backend/routes/getPeople.js index fbc3f72..e157a55 100644 --- a/crabfit-backend/routes/getPeople.js +++ b/crabfit-backend/routes/getPeople.js @@ -2,7 +2,7 @@ module.exports = async (req, res) => { const { eventId } = req.params; try { - const query = req.datastore.createQuery('Person').filter('eventId', eventId); + const query = req.datastore.createQuery(req.types.person).filter('eventId', eventId); let people = (await req.datastore.runQuery(query))[0]; people = people.map(person => ({ name: person.name, diff --git a/crabfit-backend/routes/login.js b/crabfit-backend/routes/login.js index 73a1d4c..d8d15e8 100644 --- a/crabfit-backend/routes/login.js +++ b/crabfit-backend/routes/login.js @@ -5,7 +5,7 @@ module.exports = async (req, res) => { const { person } = req.body; try { - const query = req.datastore.createQuery('Person') + const query = req.datastore.createQuery(req.types.person) .filter('eventId', eventId) .filter('name', personName); let personResult = (await req.datastore.runQuery(query))[0][0]; diff --git a/crabfit-backend/routes/stats.js b/crabfit-backend/routes/stats.js index 921adf6..35d405a 100644 --- a/crabfit-backend/routes/stats.js +++ b/crabfit-backend/routes/stats.js @@ -5,8 +5,8 @@ module.exports = async (req, res) => { let personCount = null; try { - const eventQuery = req.datastore.createQuery(['__Stat_Kind__']).filter('kind_name', 'Event'); - const personQuery = req.datastore.createQuery(['__Stat_Kind__']).filter('kind_name', 'Person'); + const eventQuery = req.datastore.createQuery(['__Stat_Kind__']).filter('kind_name', req.types.event); + const personQuery = req.datastore.createQuery(['__Stat_Kind__']).filter('kind_name', req.types.person); eventCount = (await req.datastore.runQuery(eventQuery))[0][0].count; personCount = (await req.datastore.runQuery(personQuery))[0][0].count; diff --git a/crabfit-backend/routes/updatePerson.js b/crabfit-backend/routes/updatePerson.js index 2d539b4..2a63a92 100644 --- a/crabfit-backend/routes/updatePerson.js +++ b/crabfit-backend/routes/updatePerson.js @@ -5,7 +5,7 @@ module.exports = async (req, res) => { const { person } = req.body; try { - const query = req.datastore.createQuery('Person') + const query = req.datastore.createQuery(req.types.person) .filter('eventId', eventId) .filter('name', personName); let personResult = (await req.datastore.runQuery(query))[0][0]; diff --git a/crabfit-frontend/package.json b/crabfit-frontend/package.json index 15dbfc0..30ab620 100644 --- a/crabfit-frontend/package.json +++ b/crabfit-frontend/package.json @@ -1,6 +1,6 @@ { "name": "crabfit-frontend", - "version": "0.1.0", + "version": "1.0.0", "private": true, "dependencies": { "@emotion/react": "^11.1.5", From 1b40a5919b8e10c9ac08e06051fb83e74d63250b Mon Sep 17 00:00:00 2001 From: Ben Grant Date: Mon, 12 Apr 2021 13:06:18 +1000 Subject: [PATCH 3/5] Click to copy link --- crabfit-frontend/src/App.tsx | 2 +- crabfit-frontend/src/pages/Event/Event.tsx | 13 ++++++++++++- crabfit-frontend/src/pages/Event/eventStyle.ts | 8 ++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/crabfit-frontend/src/App.tsx b/crabfit-frontend/src/App.tsx index 9163223..de2c8b5 100644 --- a/crabfit-frontend/src/App.tsx +++ b/crabfit-frontend/src/App.tsx @@ -23,7 +23,7 @@ const App = () => { useEffect(() => { setIsDark(colortheme === 'System' ? darkQuery.matches : colortheme === 'Dark'); - }, [colortheme]); + }, [colortheme, darkQuery.matches]); return ( diff --git a/crabfit-frontend/src/pages/Event/Event.tsx b/crabfit-frontend/src/pages/Event/Event.tsx index d000fe0..9d629f7 100644 --- a/crabfit-frontend/src/pages/Event/Event.tsx +++ b/crabfit-frontend/src/pages/Event/Event.tsx @@ -65,6 +65,8 @@ const Event = (props) => { const [min, setMin] = useState(0); const [max, setMax] = useState(0); + const [copied, setCopied] = useState(null); + useEffect(() => { const fetchEvent = async () => { try { @@ -272,7 +274,16 @@ const Event = (props) => { {(!!event || isLoading) ? ( <> {event?.name} - https://crab.fit/{id} + navigator.clipboard?.writeText(`https://crab.fit/${id}`) + .then(() => { + setCopied('Copied!'); + setTimeout(() => setCopied(null), 1000); + }) + .catch((e) => console.error('Failed to copy', e)) + } + title={!!navigator.clipboard ? 'Click to copy' : ''} + >{copied ?? `https://crab.fit/${id}`} {!!event?.name && <>Copy the link to this page, or share via email. diff --git a/crabfit-frontend/src/pages/Event/eventStyle.ts b/crabfit-frontend/src/pages/Event/eventStyle.ts index b3da59f..c427909 100644 --- a/crabfit-frontend/src/pages/Event/eventStyle.ts +++ b/crabfit-frontend/src/pages/Event/eventStyle.ts @@ -89,6 +89,14 @@ export const ShareInfo = styled.p` border-radius: 3px; } `} + + ${props => props.onClick && ` + cursor: pointer; + + &:hover { + color: ${props.theme.primaryDark}; + } + `} `; export const Tabs = styled.div` From 003f4e811ac2cb1b196595647b586abf9ab70e5e Mon Sep 17 00:00:00 2001 From: Ben Grant Date: Mon, 12 Apr 2021 13:27:23 +1000 Subject: [PATCH 4/5] Track key events --- crabfit-frontend/src/components/Donate/Donate.tsx | 2 +- crabfit-frontend/src/pages/Event/Event.tsx | 8 +++++++- crabfit-frontend/src/pages/Home/Home.tsx | 3 +++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/crabfit-frontend/src/components/Donate/Donate.tsx b/crabfit-frontend/src/components/Donate/Donate.tsx index a800521..8843abe 100644 --- a/crabfit-frontend/src/components/Donate/Donate.tsx +++ b/crabfit-frontend/src/components/Donate/Donate.tsx @@ -2,7 +2,7 @@ import { Button } from 'components'; const Donate = () => (
- + gtag('event', 'donate', { 'event_category': 'donate' })} href="https://www.paypal.com/donate?business=N89X6YXRT5HKW&item_name=Crab+Fit+Donation¤cy_code=AUD" target="_blank" rel="noreferrer">