Skip to content

Commit

Permalink
feat: challenge status banner (#1319)
Browse files Browse the repository at this point in the history
#1266

---------

Co-authored-by: Kira Evans <contact@kne42.me>
  • Loading branch information
codemonkey800 and kne42 authored Nov 6, 2024
1 parent 7ceff67 commit 1bd0bff
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ import { ReactNode } from 'react'

import { SurveyBanner } from 'app/components/SurveyBanner'

import { MLChallengeBanner } from '../MLChallenge'
import { Footer } from './Footer'
import { TopNavigation } from './TopNavigation'

export function Layout({ children }: { children: ReactNode }) {
return (
<main className="flex flex-col flex-auto">
<MLChallengeBanner />
<TopNavigation />
<div className="flex flex-col flex-[1_0_auto]">{children}</div>
<Footer />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import { Banner } from '@czi-sds/components'
import { useLocalStorageValue } from '@react-hookz/web'
import { useLocation } from '@remix-run/react'
import dayjs from 'dayjs'
import { useState } from 'react'
import { match, P } from 'ts-pattern'

import { I18n } from 'app/components/I18n'
import { LocalStorageKeys } from 'app/constants/localStorage'
import { useEffectOnce } from 'app/hooks/useEffectOnce'
import { I18nKeys } from 'app/types/i18n'

const BANNER_ALLOWLIST = [/^\/$/, /^\/browse-data\/.*$/]
const ML_CHALLENGE_END_DATE = dayjs('February 6, 2025')

// TODO(jeremy) check with team to see what the correct interval is
const ML_CHALLENGE_END_INTERVAL = 10

const ML_CHALLENGE_END_NOTIFY_DATE = ML_CHALLENGE_END_DATE.subtract(
ML_CHALLENGE_END_INTERVAL,
'days',
)

export function MLChallengeBanner() {
const {
value: lastDismissedBannerMessage,
set: setLastDismissedBannerMessage,
} = useLocalStorageValue<string | null>(
LocalStorageKeys.CompetitionBannerDismissed,
{ defaultValue: null },
)
const [open, setOpen] = useState(false)
const location = useLocation()

const now = dayjs()

const bannerI18nKey = match(now)
.with(
P.when((d) => d.isAfter(ML_CHALLENGE_END_DATE)),
() => 'mlCompetitionEnded' as I18nKeys,
)
.with(
P.when((d) => d.isAfter(ML_CHALLENGE_END_NOTIFY_DATE)),
() => 'mlCompetitionEnding' as I18nKeys,
)
.otherwise(() => 'mlCompetitionHasBegun' as I18nKeys)

// open banner on client side to prevent flash of content since local storage
// is not available when server-side rendering.
useEffectOnce(() => setOpen(bannerI18nKey !== lastDismissedBannerMessage))

return (
<Banner
dismissed={
!open ||
BANNER_ALLOWLIST.every((regex) => !regex.test(location.pathname))
}
dismissible
sdsType="primary"
onClose={() => {
setOpen(false)
setLastDismissedBannerMessage(bannerI18nKey)
}}
>
<div className="[&_a]:text-white [&_a]:border-b [&_a]:border-dashed [&_a]:border-white">
<I18n
i18nKey={bannerI18nKey}
values={{
// round to 1 day on the last day when there's less than 24 hours before the challenge ends
days: Math.max(ML_CHALLENGE_END_DATE.diff(now, 'days'), 1),
}}
/>
</div>
</Banner>
)
}
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './MLChallenge'
export * from './MLChallengeBanner'
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Banner, Icon } from '@czi-sds/components'
import { useLocalStorageValue } from '@react-hookz/web'
import { useLocation } from '@remix-run/react'
import dayjs, { OpUnitType } from 'dayjs'
import { useState } from 'react'

Expand All @@ -13,6 +14,12 @@ import styles from './SurveyBanner.module.css'
const DURATION_BEFORE_SHOW_SURVEY = 2
const DURATION_UNIT_BEFORE_SHOW_SURVEY: OpUnitType = 'weeks'

const BANNER_ALLOWLIST = [
/^\/datasets\/.*$/,
/^\/runs\/.*$/,
/^\/depositions\/.*$/,
]

export function SurveyBanner() {
const { value: lastDismissed, set: setLastDismissed } = useLocalStorageValue<
string | null
Expand All @@ -33,11 +40,16 @@ export function SurveyBanner() {
),
)

const location = useLocation()

return (
<div
className={cns(
'hidden screen-716:block sticky bottom-0 w-full',
styles.banner,

BANNER_ALLOWLIST.every((regex) => !regex.test(location.pathname)) &&
'screen-716:hidden',
)}
>
<Banner
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export enum LocalStorageKeys {
CompetitionBannerDismissed = 'competition-banner-dismissed',
SurveyBannerDismissed = 'survey-banner-dismissed',
TableRenderErrorPageReloadCount = 'table-render-error-page-reload-count',
}
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,10 @@
"microscopeModel": "Microscope model",
"mlChallengeStartDate": "November 6, 2024",
"mlChallengeEndDate": "February 5, 2025",
"mlCompetitionLearnMore": "<url to='/competition'>Learn More</url>",
"mlCompetitionHasBegun": "ML Competition has begun. Enter for cash prizes. $t(mlCompetitionLearnMore)",
"mlCompetitionEnding": "ML Competition is ending in {{days}} days. Compete for cash prizes. $t(mlCompetitionLearnMore)",
"mlCompetitionEnded": "Congratulations to the ML Competition winners! $t(mlCompetitionLearnMore) about the winning models.",
"modelWeights": "Model Weights",
"moderate": "Moderate",
"moreInfo": "More Info",
Expand Down

0 comments on commit 1bd0bff

Please sign in to comment.