Skip to content
Merged
63 changes: 63 additions & 0 deletions components/Activity/Hackathon/AgendaCountdown.module.less
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
@import './theme.less';

.wrap {
display: grid;
gap: 0.75rem;
max-width: 520px;
}

.label {
margin: 0;
color: @muted;
font-size: 0.72rem;
font-family: @heading;
letter-spacing: 0.1em;
text-transform: uppercase;
}

.grid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 0.8rem;

li {
gap: 0.7rem;
box-shadow:
inset 0 0 0 1px rgba(255, 255, 255, 0.03),
0 0 26px rgba(44, 232, 255, 0.08);
border: 1px solid rgba(44, 232, 255, 0.26);
border-radius: 18px;
background: linear-gradient(180deg, rgba(44, 232, 255, 0.08), rgba(44, 232, 255, 0.03));
min-height: 120px;

strong {
color: #fff;
font-size: clamp(2.3rem, 4vw, 3.8rem);
line-height: 1;
font-family: @heading;
letter-spacing: 0.08em;
}

span {
color: rgba(255, 255, 255, 0.72);
font-size: 0.82rem;
font-family: @heading;
letter-spacing: 0.2em;
text-transform: uppercase;
}
}
}

@media (max-width: 767px) {
.grid {
grid-template-columns: repeat(2, minmax(0, 1fr));

li {
min-height: 96px;

strong {
font-size: 2rem;
}
}
}
}
48 changes: 48 additions & 0 deletions components/Activity/Hackathon/AgendaCountdown.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { TableCellValue } from 'mobx-lark';
import { observer } from 'mobx-react';
import { FC, useContext, useState } from 'react';

import { Agenda } from '../../../models/Hackathon';
import { I18nContext } from '../../../models/Translation';
import { Countdown, TimeUnit } from '../../Base/Countdown';
import styles from './AgendaCountdown.module.less';
import { agendaTypeLabelOf, resolveCountdownState } from './utility';

export interface AgendaCountdownProps {
agendaItems: Agenda[];
endTime?: TableCellValue;
startTime?: TableCellValue;
units: TimeUnit[];
}

export const AgendaCountdown: FC<AgendaCountdownProps> = observer(
({ agendaItems, endTime, startTime, units }) => {
const { t } = useContext(I18nContext);
const [referenceTime, setReferenceTime] = useState(Date.now());
const { nextItem: nextAgendaItem, countdownTo } = resolveCountdownState(
agendaItems,
referenceTime,
startTime,
endTime,
);

if (!countdownTo) return null;

const countdownLabel = nextAgendaItem
? agendaTypeLabelOf(nextAgendaItem.type, t, t('agenda'))
: t('event_duration');

return (
<div className={styles.wrap}>
{countdownLabel && <p className={styles.label}>{countdownLabel}</p>}

<Countdown
className={styles.grid}
endTime={countdownTo}
onEnd={() => setReferenceTime(Date.now())}
units={units}
/>
</div>
);
},
);
65 changes: 6 additions & 59 deletions components/Activity/Hackathon/Hero.module.less
Original file line number Diff line number Diff line change
Expand Up @@ -179,54 +179,10 @@
}
}

.countdownWrap {
display: grid;
gap: 0.75rem;
max-width: 520px;
}

.countdownLabel {
color: @muted;
font-size: 0.72rem;
font-family: @heading;
letter-spacing: 0.1em;
text-transform: uppercase;
}

.countdownGrid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 0.8rem;
}

.countdownCell {
gap: 0.7rem;
box-shadow:
inset 0 0 0 1px rgba(255, 255, 255, 0.03),
0 0 26px rgba(44, 232, 255, 0.08);
border: 1px solid rgba(44, 232, 255, 0.26);
border-radius: 18px;
background: linear-gradient(180deg, rgba(44, 232, 255, 0.08), rgba(44, 232, 255, 0.03));
min-height: 120px;

strong {
color: #fff;
font-size: clamp(2.3rem, 4vw, 3.8rem);
line-height: 1;
font-family: @heading;
letter-spacing: 0.08em;
}

span {
color: rgba(255, 255, 255, 0.72);
font-size: 0.82rem;
font-family: @heading;
letter-spacing: 0.2em;
text-transform: uppercase;
}
}

.actionButton {
// prettier-ignore
.button-primary();

box-shadow: 0 0 28px rgba(44, 232, 255, 0.14);
border-color: rgba(44, 232, 255, 0.48);
background: rgba(44, 232, 255, 0.08);
Expand All @@ -240,6 +196,9 @@
}

.actionButtonGhost {
// prettier-ignore
.button-ghost();

border-color: rgba(255, 255, 255, 0.16);
background: rgba(255, 255, 255, 0.03);
color: rgba(255, 255, 255, 0.82);
Expand Down Expand Up @@ -442,16 +401,4 @@
.heroBadge {
font-size: 0.72rem;
}

.countdownGrid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}

.countdownCell {
min-height: 96px;

strong {
font-size: 2rem;
}
}
}
77 changes: 18 additions & 59 deletions components/Activity/Hackathon/Hero.tsx
Comment thread
TechQuery marked this conversation as resolved.
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { TableCellValue } from 'mobx-lark';
import { FC, useEffect, useMemo, useState } from 'react';
import { FC } from 'react';
import { Container } from 'react-bootstrap';

import { Agenda } from '../../../models/Hackathon';
import { LarkImage } from '../../LarkImage';
import { AgendaCountdown } from './AgendaCountdown';
import { TimeUnit } from '../../Base/Countdown';
import styles from './Hero.module.less';

export type HackathonHeroNavItem = Record<'label' | 'href', string>;
Expand All @@ -22,13 +25,14 @@ export interface HackathonHeroProps extends Record<
| 'imageFallback',
string
> {
agendaItems: Agenda[];
badges: string[];
bottomCard?: HackathonHeroCard;
chips?: string[];
countdownLabel?: string;
countdownUnitLabels: string[];
countdownTo?: string;
countdownUnits: TimeUnit[];
endTime?: TableCellValue;
image?: TableCellValue;
startTime?: TableCellValue;
navigation: HackathonHeroNavItem[];
primaryAction: HackathonHeroAction;
secondaryAction: HackathonHeroAction;
Expand Down Expand Up @@ -74,38 +78,6 @@ const FloatingCard: FC<{
</div>
);

const useCountdown = (countdownTo?: string) => {
const target = useMemo(() => {
const value = countdownTo ? new Date(countdownTo).getTime() : NaN;

return Number.isFinite(value) ? value : NaN;
}, [countdownTo]);
const [now, setNow] = useState<number | null>(null);

useEffect(() => {
if (!Number.isFinite(target)) return;

setNow(Date.now());

const timer = window.setInterval(() => setNow(Date.now()), 1000);

return () => window.clearInterval(timer);
}, [target]);

return useMemo(() => {
if (!Number.isFinite(target) || now === null) return ['--', '--', '--', '--'];

const rest = Math.max(0, target - now);
const totalSeconds = Math.floor(rest / 1000);
const days = Math.floor(totalSeconds / 86400);
const hours = Math.floor((totalSeconds % 86400) / 3600);
const minutes = Math.floor((totalSeconds % 3600) / 60);
const seconds = totalSeconds % 60;

return [days, hours, minutes, seconds].map(value => String(value).padStart(2, '0'));
}, [now, target]);
};

const splitHeroTitle = (name: string, subtitle: string) => {
const segments = name.split(/\s+/).filter(Boolean);

Expand All @@ -122,28 +94,28 @@ const splitHeroTitle = (name: string, subtitle: string) => {
};

export const HackathonHero: FC<HackathonHeroProps> = ({
agendaItems,
badges,
bottomCard,
chips,
countdownLabel,
countdownUnitLabels,
countdownTo,
countdownUnits,
description,
endTime,
image,
imageFallback,
locationText,
name,
navigation,
primaryAction,
secondaryAction,
startTime,
subtitle,
topCard,
visualChip,
visualCopy,
visualKicker,
visualTitle,
}) => {
const countdown = useCountdown(countdownTo);
const title = splitHeroTitle(name, subtitle);

return (
Expand Down Expand Up @@ -192,25 +164,12 @@ export const HackathonHero: FC<HackathonHeroProps> = ({

<p className={styles.description}>{description}</p>

{countdownTo && (
<div className={styles.countdownWrap}>
{countdownLabel && (
<p className={`${styles.countdownLabel} m-0`}>{countdownLabel}</p>
)}

<ol className={`list-unstyled ${styles.countdownGrid} m-0`}>
{countdown.map((value, index) => (
<li
key={`${index}-${countdownUnitLabels[index]}`}
className={`${styles.countdownCell} d-flex flex-column justify-content-center align-items-center`}
>
<strong>{value}</strong>
<span>{countdownUnitLabels[index]}</span>
</li>
))}
</ol>
</div>
)}
<AgendaCountdown
agendaItems={agendaItems}
endTime={endTime}
startTime={startTime}
units={countdownUnits}
/>

<nav className="d-flex flex-wrap gap-2 gap-md-3" aria-label={subtitle}>
<HeroLink action={primaryAction} variant="primary" />
Expand Down
7 changes: 0 additions & 7 deletions components/Activity/Hackathon/constant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,13 +91,6 @@ export const heroNavigation = ({ t }: typeof i18n) => [
{ href: '#faq', label: t('common_questions') },
];

export const buildCountdownUnitLabels = ({ t }: typeof i18n) => [
t('countdown_days'),
t('countdown_hours'),
t('countdown_minutes'),
t('countdown_seconds'),
];

export const buildHighlightCards = (
{ t }: typeof i18n,
{
Expand Down
44 changes: 0 additions & 44 deletions components/Activity/Hackathon/useLiveCountdownState.ts

This file was deleted.

Loading
Loading