From 9d4b2ffbb50dcd2ca1280b7623eb94025ee860ce Mon Sep 17 00:00:00 2001 From: Ben Grant Date: Thu, 15 Apr 2021 18:04:28 +1000 Subject: [PATCH] Chrome and Firefox extension --- crabfit-browser-extension/manifest.json | 25 ++ crabfit-browser-extension/popup.html | 22 ++ crabfit-browser-extension/res/icon128.png | Bin 0 -> 4459 bytes crabfit-browser-extension/res/icon16.png | Bin 0 -> 620 bytes crabfit-browser-extension/res/icon32.png | Bin 0 -> 1192 bytes crabfit-browser-extension/res/icon48.png | Bin 0 -> 1827 bytes crabfit-frontend/src/App.tsx | 6 + .../ToggleField/toggleFieldStyle.ts | 3 +- crabfit-frontend/src/pages/Create/Create.tsx | 248 ++++++++++++++++++ .../src/pages/Create/createStyle.ts | 106 ++++++++ crabfit-frontend/src/pages/Home/Home.tsx | 2 +- crabfit-frontend/src/pages/Home/homeStyle.ts | 10 +- crabfit-frontend/src/pages/index.ts | 1 + 13 files changed, 419 insertions(+), 4 deletions(-) create mode 100644 crabfit-browser-extension/manifest.json create mode 100644 crabfit-browser-extension/popup.html create mode 100644 crabfit-browser-extension/res/icon128.png create mode 100644 crabfit-browser-extension/res/icon16.png create mode 100644 crabfit-browser-extension/res/icon32.png create mode 100644 crabfit-browser-extension/res/icon48.png create mode 100644 crabfit-frontend/src/pages/Create/Create.tsx create mode 100644 crabfit-frontend/src/pages/Create/createStyle.ts diff --git a/crabfit-browser-extension/manifest.json b/crabfit-browser-extension/manifest.json new file mode 100644 index 0000000..6bcae9b --- /dev/null +++ b/crabfit-browser-extension/manifest.json @@ -0,0 +1,25 @@ +{ + "name": "Crab Fit", + "description": "Enter your availability to find a time that works for everyone!", + "version": "1.0", + "manifest_version": 2, + + "author": "Ben Grant", + "homepage_url": "https://crab.fit", + + "browser_action": { + "default_popup": "popup.html", + "default_icon": { + "16": "res/icon16.png", + "32": "res/icon32.png", + "48": "res/icon48.png", + "128": "res/icon128.png" + } + }, + "icons": { + "16": "res/icon16.png", + "32": "res/icon32.png", + "48": "res/icon48.png", + "128": "res/icon128.png" + } +} diff --git a/crabfit-browser-extension/popup.html b/crabfit-browser-extension/popup.html new file mode 100644 index 0000000..d922600 --- /dev/null +++ b/crabfit-browser-extension/popup.html @@ -0,0 +1,22 @@ + + + + + + + + + + diff --git a/crabfit-browser-extension/res/icon128.png b/crabfit-browser-extension/res/icon128.png new file mode 100644 index 0000000000000000000000000000000000000000..6b9643dc544a24d9d1795a2b7a44fc1f446f6c86 GIT binary patch literal 4459 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 import('pages/Home/Home')); const Event = lazy(() => import('pages/Event/Event')); +const Create = lazy(() => import('pages/Create/Create')); const App = () => { const colortheme = useSettingsStore(state => state.theme); @@ -113,6 +114,11 @@ const App = () => { }> + )} /> + ( + }> + + )} /> ( }> diff --git a/crabfit-frontend/src/components/ToggleField/toggleFieldStyle.ts b/crabfit-frontend/src/components/ToggleField/toggleFieldStyle.ts index c33601c..6bfde63 100644 --- a/crabfit-frontend/src/components/ToggleField/toggleFieldStyle.ts +++ b/crabfit-frontend/src/components/ToggleField/toggleFieldStyle.ts @@ -25,7 +25,8 @@ export const HiddenInput = styled.input` height: 0; width: 0; position: absolute; - right: -1000px; + left: -1000px; + opacity: 0; &:checked + label { color: ${props => props.theme.background}; diff --git a/crabfit-frontend/src/pages/Create/Create.tsx b/crabfit-frontend/src/pages/Create/Create.tsx new file mode 100644 index 0000000..083c8c3 --- /dev/null +++ b/crabfit-frontend/src/pages/Create/Create.tsx @@ -0,0 +1,248 @@ +import { useEffect, useState } from 'react'; +import { useHistory } from 'react-router-dom'; +import { useForm } from 'react-hook-form'; + +import dayjs from 'dayjs'; +import utc from 'dayjs/plugin/utc'; +import timezone from 'dayjs/plugin/timezone'; +import customParseFormat from 'dayjs/plugin/customParseFormat'; + +import { + TextField, + CalendarField, + TimeRangeField, + SelectField, + Button, + Donate, + Error, +} from 'components'; + +import { + StyledMain, + CreateForm, + TitleSmall, + TitleLarge, + P, + OfflineMessage, + ShareInfo, + Footer, + AboutSection, + Recent, +} from './createStyle'; + +import api from 'services'; +import { useRecentsStore } from 'stores'; + +import timezones from 'res/timezones.json'; + +dayjs.extend(utc); +dayjs.extend(timezone); +dayjs.extend(customParseFormat); + +const Create = ({ offline }) => { + const { register, handleSubmit } = 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 { push } = useHistory(); + + const recentsStore = useRecentsStore(); + + useEffect(() => { + if (window.self === window.top) { + push('/'); + } + document.title = 'Create a Crab Fit'; + }, [push]); + + const onSubmit = async data => { + setIsLoading(true); + setError(null); + try { + const { start, end } = JSON.parse(data.times); + const dates = JSON.parse(data.dates); + + if (dates.length === 0) { + return setError(`You haven't selected any dates!`); + } + const isSpecificDates = typeof dates[0] === 'string' && dates[0].length === 8; + if (start === end) { + return setError(`The start and end times can't be the same`); + } + + let times = dates.reduce((times, date) => { + let 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') + ); + } else { + day.push( + dayjs().tz(data.timezone) + .day(date).hour(i).minute(0).utc().format('HHmm-d') + ); + } + } + if (start > end) { + for (let i = 0; i < end; i++) { + if (isSpecificDates) { + day.push( + dayjs.tz(date, 'DDMMYYYY', data.timezone) + .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') + ); + } + } + } + return [...times, ...day]; + }, []); + + if (times.length === 0) { + return setError(`You don't have any time selected`); + } + + const response = await api.post('/event', { + event: { + name: data.name, + times: times, + }, + }); + setCreatedEvent(response.data); + recentsStore.addRecent({ + id: response.data.id, + created: response.data.created, + name: response.data.name, + }); + gtag('event', 'create_event', { + 'event_category': 'home', + }); + } catch (e) { + setError('An error ocurred while creating the event. Please try again later.'); + console.error(e); + } finally { + setIsLoading(false); + } + }; + + return ( + <> + + CREATE A + CRAB FIT + + + {createdEvent ? ( + + +

Created {createdEvent.name}

+ navigator.clipboard?.writeText(`https://crab.fit/${createdEvent.id}`) + .then(() => { + setCopied('Copied!'); + setTimeout(() => setCopied(null), 1000); + gtag('event', 'copy_link', { + 'event_category': 'event', + }); + }) + .catch((e) => console.error('Failed to copy', e)) + } + title={!!navigator.clipboard ? 'Click to copy' : ''} + >{copied ?? `https://crab.fit/${createdEvent.id}`} + + {/* eslint-disable-next-line */} + Click the link above to copy it to your clipboard, or share via gtag('event', 'send_email', { 'event_category': 'event' })} href={`mailto:?subject=${encodeURIComponent(`Scheduling ${createdEvent.name}`)}&body=${encodeURIComponent(`Visit this link to enter your availabilities: https://crab.fit/${createdEvent.id}`)}`} target="_blank">email. + +
+ Thank you for using Crab Fit. If you like it, consider donating. + +
+
+
+ ) : ( + <> + {!!recentsStore.recents.length && ( + + +

Recently visited

+ {recentsStore.recents.map(event => ( + + {event.name} + Created {dayjs.unix(event.created).format('D MMMM, YYYY')} + + ))} +
+
+ )} + + + {offline ? ( + +

🦀📵

+

You can't create a Crab Fit when you don't have an internet connection. Please make sure you're connected.

+
+ ) : ( + + + + + + + + + + {error && ( + setError(null)}>{error} + )} + + + + )} +
+ + )} + + ); +}; + +export default Create; diff --git a/crabfit-frontend/src/pages/Create/createStyle.ts b/crabfit-frontend/src/pages/Create/createStyle.ts new file mode 100644 index 0000000..d6b37b3 --- /dev/null +++ b/crabfit-frontend/src/pages/Create/createStyle.ts @@ -0,0 +1,106 @@ +import styled from '@emotion/styled'; + +export const StyledMain = styled.div` + width: 600px; + margin: 10px auto; + max-width: calc(100% - 30px); +`; + +export const CreateForm = styled.form` + margin: 0 0 30px; +`; + +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}; + line-height: 1em; +`; + +export const TitleLarge = styled.h1` + margin: 0; + font-size: 2rem; + text-align: center; + color: ${props => props.theme.primary}; + font-family: 'Molot', sans-serif; + font-weight: 400; + text-shadow: 0 4px 0 ${props => props.theme.primaryDark}; + line-height: 1em; +`; + +export const P = styled.p` + font-weight: 500; + line-height: 1.6em; +`; + +export const Footer = styled.footer` + margin: 60px auto 0; + width: 250px; + + & span { + display: block; + margin-bottom: 20px; + } +`; + +export const OfflineMessage = styled.div` + text-align: center; + margin: 50px 0 20px; +`; + +export const ShareInfo = styled.p` + margin: 6px 0; + text-align: center; + font-size: 15px; + padding: 10px 0; + + ${props => props.onClick && ` + cursor: pointer; + + &:hover { + color: ${props.theme.primaryDark}; + } + `} +`; + +export const AboutSection = styled.section` + margin: 30px 0 0; + background-color: ${props => props.theme.primaryBackground}; + padding: 10px 0; + + & h2 { + margin: 0 0 10px; + font-size: 1.2rem; + } +`; + +export const Recent = styled.a` + text-decoration: none; + color: inherit; + display: flex; + align-items: center; + justify-content: space-between; + padding: 5px 0; + flex-wrap: wrap; + + & .name { + font-weight: 700; + color: ${props => props.theme.primaryDark}; + } + & .date { + font-weight: 400; + font-size: .9em; + opacity: .8; + text-align: right; + flex: 1; + white-space: nowrap; + } + + &:hover .name { + text-decoration: underline; + } +`; diff --git a/crabfit-frontend/src/pages/Home/Home.tsx b/crabfit-frontend/src/pages/Home/Home.tsx index 7a4e3ab..59c1510 100644 --- a/crabfit-frontend/src/pages/Home/Home.tsx +++ b/crabfit-frontend/src/pages/Home/Home.tsx @@ -164,7 +164,7 @@ const Home = ({ offline }) => {

Recently visited

{recentsStore.recents.map(event => ( - + {event.name} Created {dayjs.unix(event.created).format('D MMMM, YYYY')} diff --git a/crabfit-frontend/src/pages/Home/homeStyle.ts b/crabfit-frontend/src/pages/Home/homeStyle.ts index f37f112..1e9797f 100644 --- a/crabfit-frontend/src/pages/Home/homeStyle.ts +++ b/crabfit-frontend/src/pages/Home/homeStyle.ts @@ -101,14 +101,20 @@ export const Recent = styled.a` display: flex; align-items: center; justify-content: space-between; - margin: 10px 0; + padding: 5px 0; + flex-wrap: wrap; & .name { - font-weight: 800; + font-weight: 700; font-size: 1.1em; + color: ${props => props.theme.primaryDark}; } & .date { font-weight: 400; + opacity: .8; + text-align: right; + flex: 1; + white-space: nowrap; } &:hover .name { diff --git a/crabfit-frontend/src/pages/index.ts b/crabfit-frontend/src/pages/index.ts index a8cf604..a4f9c82 100644 --- a/crabfit-frontend/src/pages/index.ts +++ b/crabfit-frontend/src/pages/index.ts @@ -1,2 +1,3 @@ export { default as Home } from './Home/Home'; export { default as Event } from './Event/Event'; +export { default as Create } from './Create/Create';