Merge branch 'GRA0007:main' into feat/ClipboardCopy

This commit is contained in:
Midas 2023-06-20 12:26:29 +01:00 committed by GitHub
commit 99fce5e395
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
11 changed files with 83 additions and 72 deletions

View file

@ -12,6 +12,7 @@ jobs:
build-and-push: build-and-push:
name: Deploy to Fly.io name: Deploy to Fly.io
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.repository == 'GRA0007/crab.fit'
defaults: defaults:
run: run:

View file

@ -16,6 +16,7 @@ jobs:
deploy: deploy:
name: Deploy to Vercel name: Deploy to Vercel
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.repository == 'GRA0007/crab.fit'
defaults: defaults:
run: run:

View file

@ -10,7 +10,16 @@
"react-hooks/exhaustive-deps": "off", "react-hooks/exhaustive-deps": "off",
"space-infix-ops": "warn", "space-infix-ops": "warn",
"comma-spacing": "warn", "comma-spacing": "warn",
"react-hooks/rules-of-hooks": "off" "react-hooks/rules-of-hooks": "off",
"eqeqeq": "error",
"no-return-await": "warn",
"no-var": "error",
"prefer-const": "warn",
"eol-last": ["warn", "always"],
"indent": ["warn", 2],
"semi": ["error", "never"],
"arrow-parens": ["error", "as-needed"],
"jsx-quotes": ["warn", "prefer-double"]
}, },
"overrides": [ "overrides": [
{ {

View file

@ -41,20 +41,20 @@ const Page = async ({ params }: PageProps) => {
<div className={styles.info}><span className={styles.bone} style={{ width: '20em' }} /></div> <div className={styles.info}><span className={styles.bone} style={{ width: '20em' }} /></div>
</Content>} </Content>}
> >
<Content> <Content>
<h1 className={styles.name}>{event.name}</h1> <h1 className={styles.name}>{event.name}</h1>
<span <span
className={styles.date} className={styles.date}
title={Temporal.Instant.fromEpochSeconds(event.created_at).toLocaleString(i18n.language, { dateStyle: 'long' })} title={Temporal.Instant.fromEpochSeconds(event.created_at).toLocaleString(i18n.language, { dateStyle: 'long' })}
>{t('common:created', { date: relativeTimeFormat(Temporal.Instant.fromEpochSeconds(event.created_at), i18n.language) })}</span> >{t('common:created', { date: relativeTimeFormat(Temporal.Instant.fromEpochSeconds(event.created_at), i18n.language) })}</span>
<Copyable className={styles.info}> <Copyable className={styles.info}>
{`https://crab.fit/${event.id}`} {`https://crab.fit/${event.id}`}
</Copyable> </Copyable>
<p className={makeClass(styles.info, styles.noPrint)}> <p className={makeClass(styles.info, styles.noPrint)}>
<Trans i18nKey="event:nav.shareinfo" t={t} i18n={i18n}>_<a href={`mailto:?subject=${encodeURIComponent(t('event:nav.email_subject', { event_name: event.name }))}&body=${encodeURIComponent(`${t('event:nav.email_body')} https://crab.fit/${event.id}`)}`}>_</a>_</Trans> <Trans i18nKey="event:nav.shareinfo" t={t} i18n={i18n}>_<a href={`mailto:?subject=${encodeURIComponent(t('event:nav.email_subject', { event_name: event.name }))}&body=${encodeURIComponent(`${t('event:nav.email_body')} https://crab.fit/${event.id}`)}`}>_</a>_</Trans>
</p> </p>
</Content> </Content>
</Suspense> </Suspense>
<EventAvailabilities event={event} /> <EventAvailabilities event={event} />

View file

@ -22,12 +22,10 @@ const RecentEvents = ({ eventId, times, onImport }: RecentEventsProps) => {
const { t, i18n } = useTranslation('event') const { t, i18n } = useTranslation('event')
const allRecents = useStore(useRecentsStore, state => state.recents) const allRecents = useStore(useRecentsStore, state => state.recents)
const recents = useMemo(() => const recents = useMemo(() => allRecents
allRecents ?.filter(hasAvailability)
?.filter(hasAvailability) .filter(e => e.id !== eventId && e.user.availability.some(a => times.includes(a))) ?? [],
.filter(e => e.id !== eventId && e.user.availability.some(a => times.includes(a))) ?? [], [allRecents])
[allRecents]
)
const [isOpen, setIsOpen] = useState(false) const [isOpen, setIsOpen] = useState(false)
const [selected, setSelected] = useState<string>() const [selected, setSelected] = useState<string>()

View file

@ -121,7 +121,7 @@ const Month = ({ value, onChange }: MonthProps) => {
</div> </div>
{hasPastDates && <div className={styles.warningLabel}> {hasPastDates && <div className={styles.warningLabel}>
<AlertTriangle size='1.2em' /> <AlertTriangle size="1.2em" />
<span>{t('form.dates.warnings.date_in_past')}</span> <span>{t('form.dates.warnings.date_in_past')}</span>
</div>} </div>}
</> </>

View file

@ -17,19 +17,19 @@ const Footer = async ({ isSmall }: FooterProps) => {
return isRunningInApp return isRunningInApp
? null // Cannot show external donation link in an Android app ? null // Cannot show external donation link in an Android app
: <footer : <footer
id="donate" // Required to allow scrolling directly to the footer id="donate" // Required to allow scrolling directly to the footer
className={makeClass(styles.footer, isSmall && styles.small)} className={makeClass(styles.footer, isSmall && styles.small)}
> >
<span>{t('donate.info')}</span> <span>{t('donate.info')}</span>
<Button <Button
isSmall isSmall
title={t('donate.title')} title={t('donate.title')}
href="https://ko-fi.com/A06841WZ" href="https://ko-fi.com/A06841WZ"
target="_blank" target="_blank"
rel="noreferrer noopener payment" rel="noreferrer noopener payment"
style={{ whiteSpace: 'nowrap' }} style={{ whiteSpace: 'nowrap' }}
>{t('donate.button')}</Button> >{t('donate.button')}</Button>
</footer> </footer>
} }
export default Footer export default Footer

View file

@ -21,28 +21,28 @@ const ToggleField = <TValue extends string>({
value, value,
onChange, onChange,
}: ToggleFieldProps<TValue>) => <Wrapper style={{ marginBlock: '10px' }}> }: ToggleFieldProps<TValue>) => <Wrapper style={{ marginBlock: '10px' }}>
{/* TODO: Better description viewer */} {/* TODO: Better description viewer */}
{label && <Label style={{ fontSize: '.9em' }} title={description as string}> {label && <Label style={{ fontSize: '.9em' }} title={description as string}>
{label} {description && <Info size="1em" style={{ verticalAlign: 'middle' }} />} {label} {description && <Info size="1em" style={{ verticalAlign: 'middle' }} />}
</Label>} </Label>}
<div className={styles.toggleContainer}> <div className={styles.toggleContainer}>
{Object.entries(options).map(([key, label]) => {Object.entries(options).map(([key, label]) =>
<div className={styles.option} key={key}> <div className={styles.option} key={key}>
<input <input
className={styles.hiddenInput} className={styles.hiddenInput}
type="radio" type="radio"
name={name} name={name}
value={key} value={key}
id={`${name}-${key}`} id={`${name}-${key}`}
checked={value === key} checked={value === key}
onChange={() => onChange(key as TValue)} onChange={() => onChange(key as TValue)}
onClick={() => onChange(key as TValue)} onClick={() => onChange(key as TValue)}
/> />
<label className={styles.button} htmlFor={`${name}-${key}`}>{label as React.ReactNode}</label> <label className={styles.button} htmlFor={`${name}-${key}`}>{label as React.ReactNode}</label>
</div> </div>
)} )}
</div> </div>
</Wrapper> </Wrapper>
export default ToggleField export default ToggleField

View file

@ -63,6 +63,7 @@
"select_all": "Select all", "select_all": "Select all",
"select_none": "Select none", "select_none": "Select none",
"select_invert": "Invert selection", "select_invert": "Invert selection",
"google_cal": "Sync with Google Calendar", "google_cal": "Sync with Google Calendar",
"outlook_cal": "Sync with Outlook Calendar", "outlook_cal": "Sync with Outlook Calendar",
"integration": { "integration": {

View file

@ -1,20 +1,20 @@
const OutlookIcon = (props: React.ComponentProps<'svg'>) => const OutlookIcon = (props: React.ComponentProps<'svg'>) =>
<svg version="1.1" width="103.17322" height="104.31332" viewBox="0 0 103.17322 104.31332" {...props}> <svg version="1.1" width="103.17322" height="104.31332" viewBox="0 0 103.17322 104.31332" {...props}>
<path <path
d="m 64.566509,22.116383 v 20.404273 l 7.130526,4.489881 c 0.188058,0.05485 0.595516,0.05877 0.783574,0 L 103.16929,26.320259 c 0,-2.44867 -2.28412,-4.203876 -3.573094,-4.203876 H 64.566509 z" d="m 64.566509,22.116383 v 20.404273 l 7.130526,4.489881 c 0.188058,0.05485 0.595516,0.05877 0.783574,0 L 103.16929,26.320259 c 0,-2.44867 -2.28412,-4.203876 -3.573094,-4.203876 H 64.566509 z"
fill="currentColor" /> fill="currentColor" />
<path <path
d="m 64.566509,50.13308 6.507584,4.470291 c 0.916782,0.673874 2.021622,0 2.021622,0 -1.100922,0.673874 30.077495,-20.035993 30.077495,-20.035993 v 37.501863 c 0,4.082422 -2.61322,5.794531 -5.551621,5.794531 H 64.562591 V 50.13308 z" d="m 64.566509,50.13308 6.507584,4.470291 c 0.916782,0.673874 2.021622,0 2.021622,0 -1.100922,0.673874 30.077495,-20.035993 30.077495,-20.035993 v 37.501863 c 0,4.082422 -2.61322,5.794531 -5.551621,5.794531 H 64.562591 V 50.13308 z"
fill="currentColor" /> fill="currentColor" />
<g transform="matrix(3.9178712,0,0,3.9178712,-13.481403,-41.384473)"> <g transform="matrix(3.9178712,0,0,3.9178712,-13.481403,-41.384473)">
<path <path
d="m 11.321,20.958 c -0.566,0 -1.017,0.266 -1.35,0.797 -0.333,0.531 -0.5,1.234 -0.5,2.109 0,0.888 0.167,1.59 0.5,2.106 0.333,0.517 0.77,0.774 1.31,0.774 0.557,0 0.999,-0.251 1.325,-0.753 0.326,-0.502 0.49,-1.199 0.49,-2.09 0,-0.929 -0.158,-1.652 -0.475,-2.169 -0.317,-0.516 -0.75,-0.774 -1.3,-0.774 z" d="m 11.321,20.958 c -0.566,0 -1.017,0.266 -1.35,0.797 -0.333,0.531 -0.5,1.234 -0.5,2.109 0,0.888 0.167,1.59 0.5,2.106 0.333,0.517 0.77,0.774 1.31,0.774 0.557,0 0.999,-0.251 1.325,-0.753 0.326,-0.502 0.49,-1.199 0.49,-2.09 0,-0.929 -0.158,-1.652 -0.475,-2.169 -0.317,-0.516 -0.75,-0.774 -1.3,-0.774 z"
fill="currentColor" /> fill="currentColor" />
<path <path
d="m 3.441,13.563 v 20.375 l 15.5,3.25 V 10.563 l -15.5,3 z m 10.372,13.632 c -0.655,0.862 -1.509,1.294 -2.563,1.294 -1.027,0 -1.863,-0.418 -2.51,-1.253 C 8.094,26.4 7.77,25.312 7.77,23.97 c 0,-1.417 0.328,-2.563 0.985,-3.438 0.657,-0.875 1.527,-1.313 2.61,-1.313 1.023,0 1.851,0.418 2.482,1.256 0.632,0.838 0.948,1.942 0.948,3.313 10e-4,1.409 -0.327,2.545 -0.982,3.407 z" d="m 3.441,13.563 v 20.375 l 15.5,3.25 V 10.563 l -15.5,3 z m 10.372,13.632 c -0.655,0.862 -1.509,1.294 -2.563,1.294 -1.027,0 -1.863,-0.418 -2.51,-1.253 C 8.094,26.4 7.77,25.312 7.77,23.97 c 0,-1.417 0.328,-2.563 0.985,-3.438 0.657,-0.875 1.527,-1.313 2.61,-1.313 1.023,0 1.851,0.418 2.482,1.256 0.632,0.838 0.948,1.942 0.948,3.313 10e-4,1.409 -0.327,2.545 -0.982,3.407 z"
fill="currentColor" /> fill="currentColor" />
</g> </g>
</svg> </svg>
export default OutlookIcon export default OutlookIcon

View file

@ -20,6 +20,7 @@ export const detectBrowser = () => {
const isChrome = !!window.chrome const isChrome = !!window.chrome
// Edge (based on chromium) detection // Edge (based on chromium) detection
// eslint-disable-next-line eqeqeq
const isEdgeChromium = isChrome && (navigator.userAgent.indexOf("Edg") != -1) const isEdgeChromium = isChrome && (navigator.userAgent.indexOf("Edg") != -1)
if (isEdgeChromium) return 'edge_chromium' if (isEdgeChromium) return 'edge_chromium'