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:
|
||||
name: Deploy to Fly.io
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'GRA0007/crab.fit'
|
||||
|
||||
defaults:
|
||||
run:
|
||||
|
|
|
|||
1
.github/workflows/deploy_frontend.yml
vendored
1
.github/workflows/deploy_frontend.yml
vendored
|
|
@ -16,6 +16,7 @@ jobs:
|
|||
deploy:
|
||||
name: Deploy to Vercel
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'GRA0007/crab.fit'
|
||||
|
||||
defaults:
|
||||
run:
|
||||
|
|
|
|||
|
|
@ -10,7 +10,16 @@
|
|||
"react-hooks/exhaustive-deps": "off",
|
||||
"space-infix-ops": "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": [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -41,20 +41,20 @@ const Page = async ({ params }: PageProps) => {
|
|||
<div className={styles.info}><span className={styles.bone} style={{ width: '20em' }} /></div>
|
||||
</Content>}
|
||||
>
|
||||
<Content>
|
||||
<h1 className={styles.name}>{event.name}</h1>
|
||||
<span
|
||||
className={styles.date}
|
||||
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>
|
||||
<Content>
|
||||
<h1 className={styles.name}>{event.name}</h1>
|
||||
<span
|
||||
className={styles.date}
|
||||
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>
|
||||
|
||||
<Copyable className={styles.info}>
|
||||
{`https://crab.fit/${event.id}`}
|
||||
</Copyable>
|
||||
<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>
|
||||
</p>
|
||||
</Content>
|
||||
<Copyable className={styles.info}>
|
||||
{`https://crab.fit/${event.id}`}
|
||||
</Copyable>
|
||||
<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>
|
||||
</p>
|
||||
</Content>
|
||||
</Suspense>
|
||||
|
||||
<EventAvailabilities event={event} />
|
||||
|
|
|
|||
|
|
@ -22,12 +22,10 @@ const RecentEvents = ({ eventId, times, onImport }: RecentEventsProps) => {
|
|||
const { t, i18n } = useTranslation('event')
|
||||
|
||||
const allRecents = useStore(useRecentsStore, state => state.recents)
|
||||
const recents = useMemo(() =>
|
||||
allRecents
|
||||
?.filter(hasAvailability)
|
||||
.filter(e => e.id !== eventId && e.user.availability.some(a => times.includes(a))) ?? [],
|
||||
[allRecents]
|
||||
)
|
||||
const recents = useMemo(() => allRecents
|
||||
?.filter(hasAvailability)
|
||||
.filter(e => e.id !== eventId && e.user.availability.some(a => times.includes(a))) ?? [],
|
||||
[allRecents])
|
||||
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
const [selected, setSelected] = useState<string>()
|
||||
|
|
|
|||
|
|
@ -121,7 +121,7 @@ const Month = ({ value, onChange }: MonthProps) => {
|
|||
</div>
|
||||
|
||||
{hasPastDates && <div className={styles.warningLabel}>
|
||||
<AlertTriangle size='1.2em' />
|
||||
<AlertTriangle size="1.2em" />
|
||||
<span>{t('form.dates.warnings.date_in_past')}</span>
|
||||
</div>}
|
||||
</>
|
||||
|
|
|
|||
|
|
@ -17,19 +17,19 @@ const Footer = async ({ isSmall }: FooterProps) => {
|
|||
return isRunningInApp
|
||||
? null // Cannot show external donation link in an Android app
|
||||
: <footer
|
||||
id="donate" // Required to allow scrolling directly to the footer
|
||||
className={makeClass(styles.footer, isSmall && styles.small)}
|
||||
>
|
||||
<span>{t('donate.info')}</span>
|
||||
<Button
|
||||
isSmall
|
||||
title={t('donate.title')}
|
||||
href="https://ko-fi.com/A06841WZ"
|
||||
target="_blank"
|
||||
rel="noreferrer noopener payment"
|
||||
style={{ whiteSpace: 'nowrap' }}
|
||||
>{t('donate.button')}</Button>
|
||||
</footer>
|
||||
id="donate" // Required to allow scrolling directly to the footer
|
||||
className={makeClass(styles.footer, isSmall && styles.small)}
|
||||
>
|
||||
<span>{t('donate.info')}</span>
|
||||
<Button
|
||||
isSmall
|
||||
title={t('donate.title')}
|
||||
href="https://ko-fi.com/A06841WZ"
|
||||
target="_blank"
|
||||
rel="noreferrer noopener payment"
|
||||
style={{ whiteSpace: 'nowrap' }}
|
||||
>{t('donate.button')}</Button>
|
||||
</footer>
|
||||
}
|
||||
|
||||
export default Footer
|
||||
|
|
|
|||
|
|
@ -21,28 +21,28 @@ const ToggleField = <TValue extends string>({
|
|||
value,
|
||||
onChange,
|
||||
}: ToggleFieldProps<TValue>) => <Wrapper style={{ marginBlock: '10px' }}>
|
||||
{/* TODO: Better description viewer */}
|
||||
{label && <Label style={{ fontSize: '.9em' }} title={description as string}>
|
||||
{label} {description && <Info size="1em" style={{ verticalAlign: 'middle' }} />}
|
||||
</Label>}
|
||||
{/* TODO: Better description viewer */}
|
||||
{label && <Label style={{ fontSize: '.9em' }} title={description as string}>
|
||||
{label} {description && <Info size="1em" style={{ verticalAlign: 'middle' }} />}
|
||||
</Label>}
|
||||
|
||||
<div className={styles.toggleContainer}>
|
||||
{Object.entries(options).map(([key, label]) =>
|
||||
<div className={styles.option} key={key}>
|
||||
<input
|
||||
className={styles.hiddenInput}
|
||||
type="radio"
|
||||
name={name}
|
||||
value={key}
|
||||
id={`${name}-${key}`}
|
||||
checked={value === key}
|
||||
onChange={() => onChange(key as TValue)}
|
||||
onClick={() => onChange(key as TValue)}
|
||||
/>
|
||||
<label className={styles.button} htmlFor={`${name}-${key}`}>{label as React.ReactNode}</label>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Wrapper>
|
||||
<div className={styles.toggleContainer}>
|
||||
{Object.entries(options).map(([key, label]) =>
|
||||
<div className={styles.option} key={key}>
|
||||
<input
|
||||
className={styles.hiddenInput}
|
||||
type="radio"
|
||||
name={name}
|
||||
value={key}
|
||||
id={`${name}-${key}`}
|
||||
checked={value === key}
|
||||
onChange={() => onChange(key as TValue)}
|
||||
onClick={() => onChange(key as TValue)}
|
||||
/>
|
||||
<label className={styles.button} htmlFor={`${name}-${key}`}>{label as React.ReactNode}</label>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Wrapper>
|
||||
|
||||
export default ToggleField
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@
|
|||
"select_all": "Select all",
|
||||
"select_none": "Select none",
|
||||
"select_invert": "Invert selection",
|
||||
|
||||
"google_cal": "Sync with Google Calendar",
|
||||
"outlook_cal": "Sync with Outlook Calendar",
|
||||
"integration": {
|
||||
|
|
|
|||
|
|
@ -1,20 +1,20 @@
|
|||
const OutlookIcon = (props: React.ComponentProps<'svg'>) =>
|
||||
<svg version="1.1" width="103.17322" height="104.31332" viewBox="0 0 103.17322 104.31332" {...props}>
|
||||
<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"
|
||||
fill="currentColor" />
|
||||
<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"
|
||||
fill="currentColor" />
|
||||
<svg version="1.1" width="103.17322" height="104.31332" viewBox="0 0 103.17322 104.31332" {...props}>
|
||||
<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"
|
||||
fill="currentColor" />
|
||||
<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"
|
||||
fill="currentColor" />
|
||||
|
||||
<g transform="matrix(3.9178712,0,0,3.9178712,-13.481403,-41.384473)">
|
||||
<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"
|
||||
fill="currentColor" />
|
||||
<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"
|
||||
fill="currentColor" />
|
||||
</g>
|
||||
</svg>
|
||||
<g transform="matrix(3.9178712,0,0,3.9178712,-13.481403,-41.384473)">
|
||||
<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"
|
||||
fill="currentColor" />
|
||||
<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"
|
||||
fill="currentColor" />
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
export default OutlookIcon
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ export const detectBrowser = () => {
|
|||
const isChrome = !!window.chrome
|
||||
|
||||
// Edge (based on chromium) detection
|
||||
// eslint-disable-next-line eqeqeq
|
||||
const isEdgeChromium = isChrome && (navigator.userAgent.indexOf("Edg") != -1)
|
||||
|
||||
if (isEdgeChromium) return 'edge_chromium'
|
||||
|
|
|
|||
Loading…
Reference in a new issue