Merge pull request #283 from GRA0007/chore/eslint
Specify additional ESlint rules
This commit is contained in:
commit
d9e0094856
1
.github/workflows/deploy_api.yml
vendored
1
.github/workflows/deploy_api.yml
vendored
|
|
@ -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:
|
||||||
|
|
|
||||||
1
.github/workflows/deploy_frontend.yml
vendored
1
.github/workflows/deploy_frontend.yml
vendored
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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": [
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -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} />
|
||||||
|
|
|
||||||
|
|
@ -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>()
|
||||||
|
|
|
||||||
|
|
@ -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>}
|
||||||
</>
|
</>
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,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": {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue