Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 70 additions & 1 deletion pages/index.tsx
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

某方面专用的功能放到独立组件中实现,再在页面中引用,不要在一个页面里堆砌大量不同功能的代码,样式那边也要跟随组件一同迁移为独立 CSS modules 文件。

Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { observer } from 'mobx-react';
import { FC, useContext } from 'react';
import { CSSProperties, FC, useContext, useEffect, useState } from 'react';
import { Card, Col, Row } from 'react-bootstrap';
import { renderToStaticMarkup } from 'react-dom/server';
import ReactTyped from 'react-typed-component';
Expand All @@ -8,13 +8,82 @@ import { PageHead } from '../components/Layout/PageHead';
import { I18nContext } from '../models/Translation';
import styles from '../styles/Home.module.less';

// Temporarily disable localStorage persistence so the bar returns after refresh.
// const HackathonTopBarStorageKey = 'labor-ai-hackathon-2026-top-bar-dismissed';
const HackathonTopBarLink = '/hackathon/Labor-AI-hackathon-2026';

const HomePage: FC = observer(() => {
const { t } = useContext(I18nContext);
const [isHackathonTopBarVisible, setIsHackathonTopBarVisible] = useState(true);
const [hackathonTopBarStyle, setHackathonTopBarStyle] = useState<CSSProperties>();

// useEffect(() => {
// setIsHackathonTopBarVisible(localStorage.getItem(HackathonTopBarStorageKey) !== 'true');
// }, []);
useEffect(() => {
const navbar = document.querySelector('nav');
const syncTopBarOffset = () => {
const navbarHeight = navbar?.getBoundingClientRect().height || 56;

setHackathonTopBarStyle({
'--hackathon-top-bar-gap': `${Math.max(navbarHeight - 56, 0)}px`,
'--hackathon-top-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);
};
}, []);

const closeHackathonTopBar = () => {
setIsHackathonTopBarVisible(false);
// localStorage.setItem(HackathonTopBarStorageKey, 'true');
};

return (
<>
<PageHead />

{isHackathonTopBarVisible && (
<aside
className={styles.hackathonTopBar}
aria-label={t('home_hackathon_top_bar_aria_label')}
style={hackathonTopBarStyle}
>
<div className={styles.hackathonTopBarInner}>
<a className={styles.hackathonTopBarContent} href={HackathonTopBarLink}>
<span className={styles.hackathonTopBarText}>
<strong>{t('home_hackathon_top_bar_title')}</strong>
<span>{t('home_hackathon_top_bar_description')}</span>
</span>
<span className={styles.hackathonTopBarEventName}>Labor AI Hackathon 2026</span>
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

把活动名称也接入 i18n。

当前横幅里的 Labor AI Hackathon 2026 还是硬编码,和“所有用户可见文案都必须走 t()”的约束不一致。建议补一个翻译 key,再替换成 t(...)

As per coding guidelines: All user-facing text MUST use the i18n t() function (no hardcoded strings).

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pages/index.tsx` at line 69, Replace the hardcoded event name inside the span
(className styles.hackathonTopBarEventName) with a call to the i18n t() function
and add a corresponding translation key (e.g. "hackathon.eventName") to your
locale files; update pages/index.tsx to use t('hackathon.eventName') (or the
chosen key) so the visible text is localized and ensure the new key exists in
all supported locales.

<span className={styles.hackathonTopBarAction}>
{t('home_hackathon_top_bar_action')}
</span>
</a>
<button
className={styles.hackathonTopBarClose}
type="button"
aria-label={t('home_hackathon_top_bar_close')}
title={t('home_hackathon_top_bar_close')}
onClick={closeHackathonTopBar}
>
×
</button>
</div>
</aside>
Comment on lines +57 to +84
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# 只做只读检索:查找 pages/components 中已有的 React Bootstrap 横幅/通知条模式。
rg -n --type tsx '(<Alert|<Button|<Stack|<Badge|<CloseButton|<Card)' pages components

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 119


🏁 Script executed:

#!/bin/bash
# Search for React Bootstrap component usage with correct approach
rg -n --type ts '<(Alert|Button|Stack|Badge|CloseButton|Card|Container|Row|Col)' pages/ components/

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 13658


🏁 Script executed:

#!/bin/bash
# Also search by file content for Bootstrap imports to understand usage patterns
rg -n "from.*react-bootstrap" pages/ components/

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 4001


🏁 Script executed:

#!/bin/bash
# Examine the full pages/index.tsx file to understand context
wc -l pages/index.tsx

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 111


🏁 Script executed:

#!/bin/bash
# Look at the specific lines mentioned in the review (57-84) plus surrounding context
sed -n '50,90p' pages/index.tsx

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 1618


🏁 Script executed:

#!/bin/bash
# Check if there are any CloseButton or dismissible banner patterns in existing code
rg -n "CloseButton|Alert.*dismissible" pages/ components/ -A 2

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 73


🏁 Script executed:

#!/bin/bash
# Look at how Alert is used in pages/recipe/index.tsx to understand the pattern
sed -n '40,60p' pages/recipe/index.tsx

Repository: Open-Source-Bazaar/Open-Source-Bazaar.github.io

Length of output: 700


将活动横幅改为 React Bootstrap 组件,并将硬编码的事件名提取为 i18n 文本。

根据编码约束 {pages,components}/**/*.tsx,此页面必须统一使用 React Bootstrap 组件(不用原生 HTML 元素),且所有用户文本必须使用 t() 国际化函数。

当前代码的两个问题:

  1. 使用了原生 HTML 元素<aside><div><a><button><span>),应改为 React Bootstrap 的 Alert、Button、CloseButton 等组件。参考项目中已有的 Alert 用法(pages/recipe/index.tsx:45)。

  2. 硬编码事件名称:"Labor AI Hackathon 2026" 是用户可见的文本,应移至 i18n 配置文件并使用 t('home_hackathon_top_bar_event_name') 调用,与其他文本保持一致。

建议用 <Alert><Card> 加上 Bootstrap utility classes 重构此横幅,用 <Button> 替代 <button>,并补充缺失的 i18n 键。

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pages/index.tsx` around lines 57 - 84, The top-banner uses raw HTML elements
and a hard-coded event name; replace the <aside>/<div>/<a>/<button>/<span> usage
with React Bootstrap components (e.g., Alert, Card, Button/CloseButton) while
preserving behavior tied to isHackathonTopBarVisible, hackathonTopBarStyle,
HackathonTopBarLink and the closeHackathonTopBar handler, and move the literal
"Labor AI Hackathon 2026" into i18n as home_hackathon_top_bar_event_name,
rendering it via t('home_hackathon_top_bar_event_name') alongside the existing
t('home_hackathon_top_bar_title'), t('home_hackathon_top_bar_description') and
t('home_hackathon_top_bar_action'); ensure aria-label/title still use
t('home_hackathon_top_bar_aria_label') and t('home_hackathon_top_bar_close').

)}

<section
className={`flex-fill d-flex flex-column justify-content-center align-items-center bg-secondary bg-gradient text-dark bg-opacity-10 ${styles.main}`}
>
Expand Down
Loading
Loading