-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathPromoBar.tsx
More file actions
87 lines (76 loc) · 2.99 KB
/
PromoBar.tsx
File metadata and controls
87 lines (76 loc) · 2.99 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import { CSSProperties, FC, useContext, useEffect, useState } from 'react';
import { Alert, CloseButton } from 'react-bootstrap';
import { normalizeText, TableCellText } from 'mobx-lark';
import { Activity, ActivityModel } from '../../models/Activity';
import { I18nContext } from '../../models/Translation';
import styles from './PromoBar.module.less';
export const PromoBar: FC = () => {
const { t } = useContext(I18nContext);
const [isVisible, setIsVisible] = useState(true);
const [barStyle, setBarStyle] = useState<CSSProperties>();
const [activity, setActivity] = useState<Activity>();
useEffect(() => {
const navbar = document.querySelector('nav');
const syncTopBarOffset = () => {
const navbarHeight = navbar?.getBoundingClientRect().height || 56;
setBarStyle({
'--promo-bar-gap': `${Math.max(navbarHeight - 56, 0)}px`,
'--promo-bar-offset': `${navbarHeight}px`,
} as CSSProperties);
};
const observer =
typeof ResizeObserver === 'undefined' || !navbar
? undefined
: new ResizeObserver(syncTopBarOffset);
syncTopBarOffset();
if (navbar) observer?.observe(navbar);
window.addEventListener('resize', syncTopBarOffset);
return () => {
observer?.disconnect();
window.removeEventListener('resize', syncTopBarOffset);
};
}, []);
useEffect(() => {
(async () => {
try {
const model = new ActivityModel();
const data = await model.getOne('Labor-AI-hackathon-2026');
setActivity(data);
} catch (err) {
console.error('Failed to load activity:', err);
}
})();
}, []);
const closeBar = () => setIsVisible(false);
if (!isVisible) return null;
return (
<Alert
role="banner"
className={`${styles.promoBar} d-flex flex-column w-100 text-white mb-0 p-0 border-0 rounded-0`}
aria-label={t('home_hackathon_top_bar_aria_label')}
style={barStyle}
>
<div className={`${styles.promoBarInner} d-flex align-items-center mx-auto px-3`}>
<Alert.Link
className={`${styles.promoBarContent} d-flex justify-content-center align-items-center text-decoration-none`}
href={activity ? ActivityModel.getLink(activity) : '/hackathon/Labor-AI-hackathon-2026'}
>
<span className={`${styles.promoBarText} d-flex align-items-baseline`}>
<strong>{t('home_hackathon_top_bar_title')}</strong>
<span>{t('home_hackathon_top_bar_description')}</span>
</span>
<span className={styles.promoBarEventName}>
{activity ? normalizeText(activity.name as TableCellText) : 'Labor AI Hackathon 2026'}
</span>
<span className={styles.promoBarAction}>{t('home_hackathon_top_bar_action')}</span>
</Alert.Link>
<CloseButton
className={`${styles.promoBarClose} p-0 rounded`}
variant="white"
aria-label={t('home_hackathon_top_bar_close')}
onClick={closeBar}
/>
</div>
</Alert>
);
};