Skip to content

Add [Open Library] & Library Work Flow#20

Open
dethan3 wants to merge 10 commits into
Open-Source-Bazaar:mainfrom
dethan3:main
Open

Add [Open Library] & Library Work Flow#20
dethan3 wants to merge 10 commits into
Open-Source-Bazaar:mainfrom
dethan3:main

Conversation

@dethan3

@dethan3 dethan3 commented Feb 24, 2025

Copy link
Copy Markdown
Member

PR-20 PR-20 PR-20 Powered by Pull Request Badge

Checklist(清单):

  • Labels
  • Assignees
  • Reviewers
  1. Add [Open Library],
  2. Use the documentation to quickly start operating Open Library.

Closes #15

Summary by CodeRabbit

版本发布说明

  • 新功能

    • 新增"Open Library"模块,包含图书浏览、详情展示、借阅指南等功能
    • 支持图书目录查看、状态标记(可借/已借出)和借阅信息展示
    • 新增顶部导航菜单项,可直接访问"Open Library"
  • 样式优化

    • 调整多个组件中的样式声明格式
    • 优化样式混合函数的组织方式
  • 其他改进

    • 修复代码结构和类型声明的格式问题

@TechQuery TechQuery added the feature New feature or request label Jul 8, 2025
@TechQuery TechQuery self-requested a review July 8, 2025 18:20

@TechQuery TechQuery left a comment

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.

  1. 很多问题在不同文件都有,不一一列举,但都要改
  2. 软件开发要一个一个模块来,代码量太大对开发者、reviewer、AI 都有巨大上下文负担,很容易跑偏、卡死
  3. 以后要在看板上多拆几个 issue,不要闷头搞很久后发一个差不多做完整个项目的巨大 PR……

Comment thread .husky/pre-commit
Comment thread components/Navigator/MainNavigator.tsx
Comment thread package.json
Comment thread translation/zh-CN.ts
donate_books: '捐赠书籍',
how_it_works: '运作方式',
how_it_works_description: '三个简单步骤借阅社区书籍',
step_1_find_book: '1. 寻找书籍',

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.

数字序号放在 HTML 结构中用 <ol /> 实现。

Comment thread translation/zh-CN.ts
available: '可借阅',
borrowed: '已借出',
reset_filters: '重置筛选',
showing_books: '显示 {0} 本书,共 {1} 本',

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.

</Col>
<Col md={9}>
<h1>{book.title}</h1>
<h5 className="text-muted mb-3">by {book.author}</h5>

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.

作者信息不是标题,一般用 <cite />https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/cite

Comment on lines +307 to +324
<Row className="mt-4">
<Col sm={6} md={3} className="mb-3">
<div className="text-muted small">ISBN</div>
<div>{book.isbn || 'N/A'}</div>
</Col>
<Col sm={6} md={3} className="mb-3">
<div className="text-muted small">Publisher</div>
<div>{book.publisher || 'N/A'}</div>
</Col>
<Col sm={6} md={3} className="mb-3">
<div className="text-muted small">Published</div>
<div>{book.publishYear || 'N/A'}</div>
</Col>
<Col sm={6} md={3} className="mb-3">
<div className="text-muted small">Pages</div>
<div>{book.pageCount || 'N/A'}</div>
</Col>
</Row>

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.

Suggested change
<Row className="mt-4">
<Col sm={6} md={3} className="mb-3">
<div className="text-muted small">ISBN</div>
<div>{book.isbn || 'N/A'}</div>
</Col>
<Col sm={6} md={3} className="mb-3">
<div className="text-muted small">Publisher</div>
<div>{book.publisher || 'N/A'}</div>
</Col>
<Col sm={6} md={3} className="mb-3">
<div className="text-muted small">Published</div>
<div>{book.publishYear || 'N/A'}</div>
</Col>
<Col sm={6} md={3} className="mb-3">
<div className="text-muted small">Pages</div>
<div>{book.pageCount || 'N/A'}</div>
</Col>
</Row>
<Row as="ul" className="list-unstyled mt-4 g-3" sm={2} md={4}>
<Col as="li">
<div className="text-muted small">ISBN</div>
<div>{book.isbn || 'N/A'}</div>
</Col>
<Col as="li">
<div className="text-muted small">Publisher</div>
<div>{book.publisher || 'N/A'}</div>
</Col>
<Col as="li">
<div className="text-muted small">Published</div>
<div>{book.publishYear || 'N/A'}</div>
</Col>
<Col as="li">
<div className="text-muted small">Pages</div>
<div>{book.pageCount || 'N/A'}</div>
</Col>
</Row>

Comment on lines +351 to +352
{book.reviews && book.reviews.length > 0 ? (
<div>

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.

Suggested change
{book.reviews && book.reviews.length > 0 ? (
<div>
{book.reviews?.[0] ? (
<>

Comment on lines +404 to +405
<div className="table-responsive">
<table className="table table-hover">

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.

Comment on lines +419 to +421
{new Date(
history.borrowDate,
).toLocaleDateString()}

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.

Suggested change
{new Date(
history.borrowDate,
).toLocaleDateString()}
{formatDate(history.borrowDate, 'YYYY-MM-DD')}
  1. 服务端地区设置和用户浏览器通常不同,toLocaleXXX() 的结果也会不同,会出现 SSR 报错
  2. https://web-cell.dev/web-utility/functions/formatDate.html

@TechQuery TechQuery added the enhancement Some improvements label Jul 9, 2025
# Conflicts:
#	.husky/pre-commit
#	.husky/pre-push
#	package.json
#	pages/_app.tsx
#	translation/en-US.ts
#	translation/zh-CN.ts
#	translation/zh-TW.ts
@coderabbitai

coderabbitai Bot commented Jun 19, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

新增完整的 Open Library 微站,包含独立导航、共享布局、书卡组件、首页、书目录页、书详情页与借阅说明页,并将其集成进 _app.tsx 路由(跳过主站导航与页脚)。同时对 Hackathon、CardPage、Navigator 等现有文件做格式化与少量类型收窄。

Changes

Open Library 微站

Layer / File(s) Summary
布局基础设施
components/open-library/useOpenLibraryLayout.ts, components/open-library/Layout.tsx, components/open-library/Navbar.tsx, components/open-library/Footer.tsx, pages/_app.tsx
新增 useOpenLibraryLayout Hook(操作 body/htmlopen-library 类),ContentContainerLayout 共享布局(含 Head/LibraryNavbar/FooterComponent),以及 LibraryNavbarisMounted 防水合、动态加载 LanguageMenu);_app.tsx 导入 open-library.css 并通过 isOpenLibraryPath 旁路主站导航与页脚渲染。
共享 UI 组件
components/open-library/BookCard.tsx, components/open-library/FeaturedBooks.tsx, components/open-library/HeroSection.tsx, components/open-library/HowItWorks.tsx
新增 Book 数据接口与 BookCardvariant/showStatus/i18n 按钮);FeaturedBooks(前 8 本书栅格 + 查看全部入口);HeroSection(双列布局 + 外链/内链 CTA);HowItWorks(四步流程卡片含连接线与条件 CTA)。
Open Library 首页
pages/open-library/index.tsx
新增 OpenLibraryHomepage:组合 HeroSection、关于我们信息卡、FeaturedBooksHowItWorks、支持区与 FooterComponent;所有文案通过 I18nContext t() 读取并提供中文回退;内置 featuredBooksworkflowSteps 示例数据。
书目录页
pages/open-library/books/index.tsx
新增 BookCatalog 页面:定义局部 Book 接口,内置示例数据,用 Row/Col/Card 渲染书卡网格,根据 status 切换角标文案,提供跳转详情页按钮链接。
书详情页
pages/open-library/book/[id].tsx
新增 BookDetail 动态路由页面:从 booksDatabase 按数字 id 查找书目,维护 book/loading 状态;渲染加载中、404、详情三种视图;详情含封面、状态徽标、基础信息网格、借阅按钮,以及 Reviews 与 Borrow History 两个 Tab。
借阅说明页
pages/open-library/how-to-borrow.tsx
新增 HowToBorrowPage:渲染借阅流程步骤卡片、借阅规则侧边栏、FAQ 网格与页尾行动号召;站内链接用 Link legacyBehavior,外链附 noopener noreferrer
主站导航集成
components/Navigator/MainNavigator.tsx
topNavBarMenu 新增 /open-library 菜单项(t('open_library'));当 pathname/open-library 开头时提前 return null,避免主站导航渲染于 Open Library 页面。

现有代码格式化与类型修复

Layer / File(s) Summary
TypeScript 接口排版与类型收窄
components/Activity/Hackathon/Hero.tsx, components/Activity/Hackathon/Resources.tsx, components/Activity/Hackathon/Schedule.tsx, components/Layout/CardPage.tsx, components/License/helper.ts, components/Map/ChinaMap.tsx, components/Navigator/SearchBar.tsx, components/Organization/Card.tsx
Hackathon 接口 extends Record<> 排版调整(无语义变化);CardPageProps.Cardany 收窄为 Record<string, unknown>SearchBarPropsOrganizationCardProps 接口单行化;licenseTips 箭头函数闭合符号修复;ChinaMap JSX 精简为单行。
Hackathon theme.less mixin 结构变更
components/Activity/Hackathon/theme.less
section-frame() 子选择器移除对 .section-shell()/.section-header()/.section-title()/.section-subtitle()/.accent-line() 的调用(替换为空语句块);button-primary()/button-ghost() 移除对 .button-base() 的调用;多个 mixin 内属性声明顺序重排。

Sequence Diagram(s)

sequenceDiagram
  participant Browser as 浏览器
  participant _app as _app.tsx
  participant Layout as Layout
  participant LibraryNavbar as LibraryNavbar
  participant Page as Open Library 页面
  participant FooterComponent as FooterComponent

  Browser->>"_app": 访问 /open-library/*
  "_app"->>"_app": isOpenLibraryPath = true
  "_app"->>Layout: 渲染(跳过主站 MainNavigator 与主站 Footer)
  Layout->>LibraryNavbar: 渲染独立导航(isMounted 防水合)
  Layout->>Page: 渲染 children(首页/书目录/书详情/借阅说明)
  Layout->>FooterComponent: 渲染 Open Library 专属页脚
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

📚 书库初开,代码扬帆起航,
Hero 展翼,BookCard 整装待发,
Layout 为舟,Navbar 引路灯亮,
t() 织文案,类型收窄无虑忧,
Open Library,源源不断共分享! 🚀

🚥 Pre-merge checks | ✅ 2 | ❌ 3

❌ Failed checks (2 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning 检测到不相关的格式调整变更:components/Activity/Hackathon/ 与 components/Layout/CardPage.tsx 等多个文件的类型定义排版、Less 样式属性顺序调整,与 Open Library 功能无关。 建议将无关的格式调整(Hackathon 文件、theme.less、CardPage.tsx、SearchBar.tsx、Organization/Card.tsx 等)分离到独立的 PR 中,保持此 PR 专注于 Open Library 功能实现。
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive 标题 'Add [Open Library] & Library Work Flow' 表述不够清晰,'Library Work Flow' 含义模糊。 建议调整为更具体的标题,例如 'feat: Implement Open Library feature with navigation and layout components',以更清楚地说明主要变更。
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Pull request 完整实现了 Issue #15 的需求:添加 Open Library 功能及完整的工作流、导航、布局组件。

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 15

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
components/Activity/Hackathon/theme.less (2)

132-143: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

.button-ghost() 同样缺失 .button-base() 调用

.button-primary() 相同的问题,Line 133 的空语句导致 ghost 按钮丢失所有基础样式(flex 布局、padding、border-radius、字体、hover 动效等)。

🐛 建议恢复 mixin 调用
 .button-ghost() {
-  ;
+  .button-base();
   border-color: rgba(255, 255, 255, 0.14);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@components/Activity/Hackathon/theme.less` around lines 132 - 143, The
`.button-ghost()` mixin in the theme.less file contains an empty statement (a
standalone semicolon) on the first line inside the mixin definition. Replace
this empty statement with a call to the `.button-base()` mixin to ensure ghost
buttons inherit all the foundational styles including flex layout, padding,
border-radius, fonts, and transition effects. This will restore the missing base
styling that ghost buttons currently lack.

118-130: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

.button-primary() 缺失 .button-base() 调用,按钮将丢失基础样式

.button-base() 提供了按钮的核心样式:display: inline-flexjustify-contentalign-itemsgaptransitionborder-radiuspaddingfont 系列属性以及 &:hovertransform 效果。

当前 Line 119 的 ; 是空语句,导致 Hero.module.lessActionHub.module.less 中调用 .button-primary() 的按钮将缺失这些基础布局与交互样式。

🐛 建议恢复 mixin 调用
 .button-primary() {
-  ;
+  .button-base();
   box-shadow: 0 0 24px rgba(44, 232, 255, 0.18);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@components/Activity/Hackathon/theme.less` around lines 118 - 130, The
.button-primary() mixin in theme.less is missing a required call to the
.button-base() mixin. Currently, there is only an empty semicolon on line 119,
which means buttons using .button-primary() are losing essential base styles
like display, flexbox properties, transitions, border-radius, padding, and hover
transform effects. Replace the empty semicolon in the .button-primary() mixin
body with a call to .button-base() to restore these foundational styles that are
needed by buttons in Hero.module.less and ActionHub.module.less.
♻️ Duplicate comments (1)
pages/open-library/index.tsx (1)

210-224: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

“支持我们”区块请改为 React Bootstrap 按钮组件而非原生 a/span 伪按钮。

Line 210-224 当前实现破坏了 UI 组件一致性,也影响可维护性与可访问性语义。

As per coding guidelines, “ALWAYS use React Bootstrap components instead of custom HTML elements in UI code”.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pages/open-library/index.tsx` around lines 210 - 224, The "支持我们" (Support Us)
section uses native HTML elements (the `a` tag for GitHub Sponsors and the
`span` within `Link` for book sharing) styled as buttons with className
attributes, which violates the React Bootstrap component guideline. Replace the
`a` element containing "GitHub Sponsors" with a React Bootstrap Button component
using appropriate props for href, variant, and size instead of className.
Similarly, replace the `Link` wrapper and `span` element containing "分享你的图书"
with a React Bootstrap Button component, ensuring the Link functionality is
preserved if needed. Import Button from react-bootstrap at the top of the file
and apply consistent button variants (such as light and outline-light) using the
variant prop instead of className.

Source: Coding guidelines

🧹 Nitpick comments (1)
pages/open-library/index.tsx (1)

104-113: ⚡ Quick win

建议复用 components/open-library/Layout.tsx,避免页面级重复装配导航/页脚/样式 Hook。

当前首页手动拼装 LibraryNavbar + useOpenLibraryLayout + FooterComponent,与共享 Layout 的职责重复,后续容易出现页间不一致。

As per coding guidelines, “Use minimal exports and avoid unnecessary custom implementations”.

Also applies to: 231-231

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pages/open-library/index.tsx` around lines 104 - 113, The page is manually
assembling LibraryNavbar, useOpenLibraryLayout hook, and FooterComponent instead
of using the shared Layout component from components/open-library/Layout.tsx.
Remove the individual LibraryNavbar, useOpenLibraryLayout hook usage, and
FooterComponent composition from the page, and instead wrap the page content
with the Layout component to eliminate duplication and ensure consistency across
pages. Apply this same refactoring to all locations where this manual assembly
occurs, including the location at line 231.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@components/Activity/Hackathon/theme.less`:
- Around line 31-51: The `.section-frame()` mixin is missing its internal mixin
calls and only contains empty statements. Replace the empty semicolons in the
nested selectors `.section`, `.sectionHeader`, `.sectionTitle`,
`.sectionSubtitle`, and `.accentLine` with their corresponding mixin calls
(e.g., `.section()` for the `.section` selector, `.sectionHeader()` for the
`.sectionHeader` selector, and so on). This will restore the style generation
for these elements that downstream files like `Overview.module.less` depend on
when calling `.section-frame()`.

In `@components/Layout/CardPage.tsx`:
- Around line 6-10: Replace the overly broad `Record<string, unknown>` type for
the Card property in CardPageProps with a precise union type that accurately
reflects the actual prop signatures of ActivityCard, ProjectCard, and
OrganizationCard. Alternatively, update each card component to properly accept
and handle the className and linkOf props that CardPage.tsx is passing on line
24, rather than ignoring them. Choose the approach that best aligns with your
component design intent: either define Card as a union of the three specific
card component types with their actual prop interfaces, or extend each card
component's prop interface to include className and linkOf parameters.

In `@components/Navigator/MainNavigator.tsx`:
- Around line 84-87: The menu item object for the open-library navigation route
uses the incorrect field name `name` when the MenuItem interface contract
requires the field to be named `title`. Change the property name from `name` to
`title` in the navigation item object that contains href set to '/open-library'.
This will align with the MenuItem type definition and ensure the navigation
title is properly rendered.

In `@components/open-library/BookCard.tsx`:
- Line 47: The hardcoded Chinese strings on line 47 (the conditional rendering
of '可借阅' and '已借出' based on book.status) and the alt text on line 57 are not
using the i18n t() function as required by the coding guidelines. Replace these
hardcoded user-facing strings by wrapping them with the t() function and
providing appropriate i18n keys for each string. This applies to the status
display conditional in the book.status ternary operator and any image alt text
attributes, ensuring all user-visible and accessibility-related text goes
through the translation function to avoid hardcoding and enable proper
localization.

In `@components/open-library/FeaturedBooks.tsx`:
- Around line 19-24: The FeaturedBooks component has hardcoded Chinese strings
as default values for title, subtitle, and viewAllText parameters, which
bypasses internationalization. Replace these hardcoded strings with i18n
translations by either accepting already-translated strings as parameters from
the calling component, or by integrating the I18nContext within the
FeaturedBooks component to call the t() function directly for these default
values. Ensure all user-facing text in the component uses the i18n t() function
to comply with the coding guidelines.

In `@components/open-library/Footer.tsx`:
- Around line 26-29: The Footer component contains multiple hardcoded
user-facing text strings that violate the i18n requirement. Replace all
hardcoded text with t() function calls using appropriate i18n keys: the social
media platform names (GitHub, Twitter, Feishu) around the mentioned lines, the
contact information section (联系信息) in the range specified, and
copyright/placeholder text. Ensure each hardcoded string is replaced with a
corresponding t() call and that i18n keys follow the existing naming convention
used in the component for consistency.
- Around line 31-51: The social media links in the Footer component use
placeholder href values (`#github`, `#twitter`, `#feishu`) that do not navigate to
actual external URLs. Replace the href attributes in the GitHub link, Twitter
link, and Feishu link with the real external URLs to their respective platforms,
or conditionally hide these link elements if the actual URLs are not yet
available in the application configuration.

In `@components/open-library/HeroSection.tsx`:
- Around line 16-22: The HeroSection component contains hardcoded user-facing
text strings that violate the i18n requirement. Replace all hardcoded Chinese
strings with i18n t() function calls: the default parameter values for title,
subtitle, ctaText, and heroImageAlt in the component function signature need to
use t() instead of literal Chinese strings, and the "浏览图书" text on line 59 also
needs to be wrapped with t(). Ensure all user-visible text strings are
internationalized consistently throughout the HeroSection component.

In `@components/open-library/HowItWorks.tsx`:
- Around line 23-57: The HowItWorks component has hardcoded Chinese text strings
that violate the i18n requirement. Replace all hardcoded strings in the
defaultSteps array (the title and description fields for each step object), the
default values for the title and subtitle parameters in the HowItWorksProps
destructuring, and the button text (mentioned as being on line 151) with
appropriate i18n keys wrapped in the t() function. Import and use the i18n
translation function to wrap these hardcoded strings with their corresponding
translation keys for proper internationalization support.

In `@components/open-library/Layout.tsx`:
- Around line 21-33: The default page title in the Layout component is hardcoded
as a string instead of using internationalization. Replace the hardcoded default
title value in the title parameter (currently set to 'Open Library - Open Source
Bazaar') with a call to the i18n t() function, using an appropriate translation
key like t('open_library_page_title'). This will ensure the page title changes
dynamically based on the user's language preference and complies with the coding
guideline that all user-facing text must use the i18n t() function.

In `@components/open-library/Navbar.tsx`:
- Line 31: The ternary expression in Navbar.tsx contains a hardcoded fallback
string 'Open Library' that violates the i18n constraint requiring all
user-facing text to use the t() function. Replace the hardcoded string 'Open
Library' in the false branch of the ternary operator with t('open_library') so
that both branches consistently use the translation function, ensuring proper
hydration-safe i18n handling throughout the component.

In `@pages/open-library/book/`[id].tsx:
- Around line 217-224: All user-facing text strings in the book details page
component must use the i18n t() function instead of being hardcoded. Replace all
hardcoded strings (including "Loading...", "Book Not Found", "Back", "Reviews",
"Borrow History", "Returned/Active" and others at the specified line ranges:
217-224, 234-244, 260, 282-283, 288, 294, 309-323, 335, 339, 350, 382, 389, 397,
402, 408-412, 432, 435, 446) with t() function calls using appropriate i18n
keys. First define all the necessary translation keys in your i18n
configuration, then systematically update each hardcoded string reference to use
t(keyName) instead.

In `@pages/open-library/books/index.tsx`:
- Around line 118-121: Replace all hardcoded Chinese text strings in the book
directory page with i18n t() function calls to enable proper language switching.
Locate the hardcoded strings in the h1 element containing "图书目录", the p element
containing "浏览我们的社区共享图书馆,发现有趣的书籍", and also check lines 143, 164, and 172 for
additional hardcoded text (titles, status messages, hints, or button labels).
For each hardcoded string, wrap it with the t() function using an appropriate
translation key that describes the content, ensuring all user-facing text
follows the i18n guidelines and the page properly reflects language changes when
users switch locales.

In `@pages/open-library/how-to-borrow.tsx`:
- Around line 9-13: The page contains hardcoded user-facing text like "如何借阅"
that should be internationalized. Replace all hardcoded strings throughout the
component (including the h1 title and all content in the mentioned line ranges)
with the t() function calls from the i18n library. Create corresponding
translation keys in the language resource files and ensure each hardcoded string
(titles, descriptions, process steps, rules, FAQs, and CTAs) is replaced with
t('keyName') calls, maintaining consistency with the project's i18n
implementation used in other pages.

In `@pages/open-library/index.tsx`:
- Around line 124-129: Replace all hardcoded Chinese text strings in the
component with the i18n `t()` function to comply with internationalization
standards. In the affected sections (lines 124-129, 135-156, 170-173, 202-208,
and 222-223), wrap every user-facing text string including titles like "📚
关于我们", descriptions like "freeCodeCamp 成都社区「Open Library」开放共享图书馆", list items,
and button labels with the `t()` function. Ensure each string has a
corresponding key defined in your i18n translation files.

---

Outside diff comments:
In `@components/Activity/Hackathon/theme.less`:
- Around line 132-143: The `.button-ghost()` mixin in the theme.less file
contains an empty statement (a standalone semicolon) on the first line inside
the mixin definition. Replace this empty statement with a call to the
`.button-base()` mixin to ensure ghost buttons inherit all the foundational
styles including flex layout, padding, border-radius, fonts, and transition
effects. This will restore the missing base styling that ghost buttons currently
lack.
- Around line 118-130: The .button-primary() mixin in theme.less is missing a
required call to the .button-base() mixin. Currently, there is only an empty
semicolon on line 119, which means buttons using .button-primary() are losing
essential base styles like display, flexbox properties, transitions,
border-radius, padding, and hover transform effects. Replace the empty semicolon
in the .button-primary() mixin body with a call to .button-base() to restore
these foundational styles that are needed by buttons in Hero.module.less and
ActionHub.module.less.

---

Duplicate comments:
In `@pages/open-library/index.tsx`:
- Around line 210-224: The "支持我们" (Support Us) section uses native HTML elements
(the `a` tag for GitHub Sponsors and the `span` within `Link` for book sharing)
styled as buttons with className attributes, which violates the React Bootstrap
component guideline. Replace the `a` element containing "GitHub Sponsors" with a
React Bootstrap Button component using appropriate props for href, variant, and
size instead of className. Similarly, replace the `Link` wrapper and `span`
element containing "分享你的图书" with a React Bootstrap Button component, ensuring
the Link functionality is preserved if needed. Import Button from
react-bootstrap at the top of the file and apply consistent button variants
(such as light and outline-light) using the variant prop instead of className.

---

Nitpick comments:
In `@pages/open-library/index.tsx`:
- Around line 104-113: The page is manually assembling LibraryNavbar,
useOpenLibraryLayout hook, and FooterComponent instead of using the shared
Layout component from components/open-library/Layout.tsx. Remove the individual
LibraryNavbar, useOpenLibraryLayout hook usage, and FooterComponent composition
from the page, and instead wrap the page content with the Layout component to
eliminate duplication and ensure consistency across pages. Apply this same
refactoring to all locations where this manual assembly occurs, including the
location at line 231.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0b924692-11c8-4d01-b037-fb6acd2a8a56

📥 Commits

Reviewing files that changed from the base of the PR and between 96f3b06 and 5ccc58c.

⛔ Files ignored due to path filters (10)
  • .github/scripts/transform-message.ts is excluded by none and included by none
  • .github/workflows/self-scan.yml is excluded by none and included by none
  • .husky/pre-commit is excluded by none and included by none
  • .husky/pre-push is excluded by none and included by none
  • package.json is excluded by none and included by none
  • pages/open-library/readme.md is excluded by !**/*.md and included by pages/**
  • styles/open-library.css is excluded by none and included by none
  • translation/en-US.ts is excluded by none and included by none
  • translation/zh-CN.ts is excluded by none and included by none
  • translation/zh-TW.ts is excluded by none and included by none
📒 Files selected for processing (23)
  • components/Activity/Hackathon/Hero.tsx
  • components/Activity/Hackathon/Resources.tsx
  • components/Activity/Hackathon/Schedule.tsx
  • components/Activity/Hackathon/theme.less
  • components/Layout/CardPage.tsx
  • components/License/helper.ts
  • components/Map/ChinaMap.tsx
  • components/Navigator/MainNavigator.tsx
  • components/Navigator/SearchBar.tsx
  • components/Organization/Card.tsx
  • components/open-library/BookCard.tsx
  • components/open-library/FeaturedBooks.tsx
  • components/open-library/Footer.tsx
  • components/open-library/HeroSection.tsx
  • components/open-library/HowItWorks.tsx
  • components/open-library/Layout.tsx
  • components/open-library/Navbar.tsx
  • components/open-library/useOpenLibraryLayout.ts
  • pages/_app.tsx
  • pages/open-library/book/[id].tsx
  • pages/open-library/books/index.tsx
  • pages/open-library/how-to-borrow.tsx
  • pages/open-library/index.tsx

Comment on lines 31 to 51
.section-frame() {
.section {
.section-shell();
;
}

.sectionHeader {
.section-header();
;
}

.sectionTitle {
.section-title();
;
}

.sectionSubtitle {
.section-subtitle();
;
}

.accentLine {
.accent-line();
;
}
}

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 | 🔴 Critical | ⚡ Quick win

.section-frame() mixin 内部调用被清空,将导致下游样式完全丢失

此 mixin 内的所有嵌套选择器(.section.sectionHeader.sectionTitle.sectionSubtitle.accentLine)原本应调用对应的子 mixin 以生成样式,现在全部被替换为空语句 ;

根据 Overview.module.less 等下游文件直接调用 .section-frame(),这意味着这些选择器将编译为空规则集,导致 Hackathon 页面的 section 布局、标题、副标题、装饰线样式全部丢失。

🐛 建议恢复 mixin 调用
 .section-frame() {
   .section {
-    ;
+    .section-shell();
   }

   .sectionHeader {
-    ;
+    .section-header();
   }

   .sectionTitle {
-    ;
+    .section-title();
   }

   .sectionSubtitle {
-    ;
+    .section-subtitle();
   }

   .accentLine {
-    ;
+    .accent-line();
   }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.section-frame() {
.section {
.section-shell();
;
}
.sectionHeader {
.section-header();
;
}
.sectionTitle {
.section-title();
;
}
.sectionSubtitle {
.section-subtitle();
;
}
.accentLine {
.accent-line();
;
}
}
.section-frame() {
.section {
.section-shell();
}
.sectionHeader {
.section-header();
}
.sectionTitle {
.section-title();
}
.sectionSubtitle {
.section-subtitle();
}
.accentLine {
.accent-line();
}
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@components/Activity/Hackathon/theme.less` around lines 31 - 51, The
`.section-frame()` mixin is missing its internal mixin calls and only contains
empty statements. Replace the empty semicolons in the nested selectors
`.section`, `.sectionHeader`, `.sectionTitle`, `.sectionSubtitle`, and
`.accentLine` with their corresponding mixin calls (e.g., `.section()` for the
`.section` selector, `.sectionHeader()` for the `.sectionHeader` selector, and
so on). This will restore the style generation for these elements that
downstream files like `Overview.module.less` depend on when calling
`.section-frame()`.

Comment on lines 6 to 10
export interface CardPageProps extends SearchPageMeta {
Card: ComponentClass<any> | FC<any>;
Card: ComponentClass<Record<string, unknown>> | FC<Record<string, unknown>>;
cardLinkOf?: (id: string) => string;
pageLinkOf: (page: number) => string;
}

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 | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# 检查 ActivityCard、ProjectCard、OrganizationCard 的 props 接口定义
rg -n -A 8 'export.*ActivityCard|export.*ProjectCard' --type=tsx | head -50
rg -n -A 10 'export interface.*CardProps|type.*CardProps' --type=tsx | grep -E '(Activity|Project|Organization)Card'

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

Length of output: 147


🏁 Script executed:

#!/bin/bash
# Find card component files
fd -e tsx -e ts | grep -i 'card' | head -20

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

Length of output: 397


🏁 Script executed:

#!/bin/bash
# Search for ActivityCard, ProjectCard, OrganizationCard definitions
rg -n "export.*ActivityCard\|export.*ProjectCard\|export.*OrganizationCard" | head -30

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

Length of output: 73


🏁 Script executed:

#!/bin/bash
# Check CardPage.tsx to see how Card is used
cat -n components/Layout/CardPage.tsx

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

Length of output: 1420


🏁 Script executed:

#!/bin/bash
# Check Activity Card props
head -30 components/Activity/Card.tsx

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

Length of output: 907


🏁 Script executed:

#!/bin/bash
# Check Project Card props
head -30 components/Project/Card.tsx

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

Length of output: 528


🏁 Script executed:

#!/bin/bash
# Check Organization Card props
head -30 components/Organization/Card.tsx

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

Length of output: 1106


CardPageProps.Card 类型收窄存在兼容性问题。

Card 类型收窄为 ComponentClass<Record<string, unknown>> | FC<Record<string, unknown>> 无法安全匹配现有卡片组件的实际签名:

  • ActivityCardFC<ActivityCardProps extends Activity>):接受 className,但 linkOf 被忽略
  • ProjectCardFC<Project>):不接受 className,不接受 linkOf,两者都被忽略
  • OrganizationCardFC<OrganizationCardProps>):接受 className,但 linkOf 被忽略

CardPage.tsx 第 24 行实际传递了 className="h-100"linkOf={cardLinkOf},但 ProjectCard 会忽略 className,三个卡片组件都不使用 linkOf。这表明 Record<string, unknown> 的类型声明宣称的灵活性与实现不符。应改为更精确的联合类型或为各卡片组件补充缺失的 props 定义。

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@components/Layout/CardPage.tsx` around lines 6 - 10, Replace the overly broad
`Record<string, unknown>` type for the Card property in CardPageProps with a
precise union type that accurately reflects the actual prop signatures of
ActivityCard, ProjectCard, and OrganizationCard. Alternatively, update each card
component to properly accept and handle the className and linkOf props that
CardPage.tsx is passing on line 24, rather than ignoring them. Choose the
approach that best aligns with your component design intent: either define Card
as a union of the three specific card component types with their actual prop
interfaces, or extend each card component's prop interface to include className
and linkOf parameters.

Comment on lines +84 to +87
{
href: '/open-library',
name: t('open_library'),
},

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 | 🔴 Critical | ⚡ Quick win

新菜单项字段名写错,破坏 MenuItem 契约。

Line 86 使用了 name,但 MenuItem 定义要求的是 title。这会触发类型错误,并导致导航渲染读取不到标题字段。

建议修复
   {
     href: '/open-library',
-    name: t('open_library'),
+    title: t('open_library'),
   },
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
{
href: '/open-library',
name: t('open_library'),
},
{
href: '/open-library',
title: t('open_library'),
},
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@components/Navigator/MainNavigator.tsx` around lines 84 - 87, The menu item
object for the open-library navigation route uses the incorrect field name
`name` when the MenuItem interface contract requires the field to be named
`title`. Change the property name from `name` to `title` in the navigation item
object that contains href set to '/open-library'. This will align with the
MenuItem type definition and ensure the navigation title is properly rendered.

: 'bg-warning text-dark'
}`}
>
{book.status === 'available' ? '可借阅' : '已借出'}

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 | ⚡ Quick win

状态与图片替代文本仍有硬编码,需统一走 t()

Line 47 与 Line 57 都是用户可见文本(含可访问性文本),应改为 i18n key,避免中英混杂和后续翻译遗漏。

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

Also applies to: 57-57

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@components/open-library/BookCard.tsx` at line 47, The hardcoded Chinese
strings on line 47 (the conditional rendering of '可借阅' and '已借出' based on
book.status) and the alt text on line 57 are not using the i18n t() function as
required by the coding guidelines. Replace these hardcoded user-facing strings
by wrapping them with the t() function and providing appropriate i18n keys for
each string. This applies to the status display conditional in the book.status
ternary operator and any image alt text attributes, ensuring all user-visible
and accessibility-related text goes through the translation function to avoid
hardcoding and enable proper localization.

Source: Coding guidelines

Comment on lines +19 to +24
title = '精选图书',
subtitle = '社区成员推荐的优质读物,涵盖技术、设计、创业等多个领域',
showViewAll = true,
viewAllLink = '/open-library/books',
viewAllText = '查看全部图书',
}) => (

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 | ⚡ Quick win

组件默认文案为硬编码,导致未传参场景无法国际化。

title/subtitle/viewAllText 默认值是直接中文字符串;一旦调用方未覆盖,会直接绕过 i18n。请改为 t() 驱动(可由上层传入已翻译文案,或组件内接入 I18nContext)。

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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@components/open-library/FeaturedBooks.tsx` around lines 19 - 24, The
FeaturedBooks component has hardcoded Chinese strings as default values for
title, subtitle, and viewAllText parameters, which bypasses
internationalization. Replace these hardcoded strings with i18n translations by
either accepting already-translated strings as parameters from the calling
component, or by integrating the I18nContext within the FeaturedBooks component
to call the t() function directly for these default values. Ensure all
user-facing text in the component uses the i18n t() function to comply with the
coding guidelines.

Source: Coding guidelines

className="d-flex align-items-center"
>
{/* Use a static placeholder during SSR and replace it with translated content after hydration */}
{isMounted ? t('open_library') : 'Open Library'}

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 | ⚡ Quick win

将品牌占位文案改为 i18n key,避免硬编码文本。

Line 31 当前回退为 'Open Library',这是用户可见文本,违反本仓库 i18n 约束。建议使用 t() 的可回退 key(例如 t('open_library') + 统一的 hydration-safe 方案),不要直接写死英文。

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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@components/open-library/Navbar.tsx` at line 31, The ternary expression in
Navbar.tsx contains a hardcoded fallback string 'Open Library' that violates the
i18n constraint requiring all user-facing text to use the t() function. Replace
the hardcoded string 'Open Library' in the false branch of the ternary operator
with t('open_library') so that both branches consistently use the translation
function, ensuring proper hydration-safe i18n handling throughout the component.

Source: Coding guidelines

Comment on lines +217 to +224
<Layout title="Loading... - Open Library">
<ContentContainer>
<div
className="d-flex justify-content-center align-items-center"
style={{ height: '50vh' }}
>
<div className="spinner-border text-primary" role="status">
<span className="visually-hidden">Loading...</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 | 🟠 Major | 🏗️ Heavy lift

详情页大量用户文案仍为硬编码。

从 Line 217 起到历史记录区(如 Loading、Book Not Found、Back、Reviews、Borrow History、Returned/Active 等)均未走 t();建议集中抽取 i18n key,统一由翻译层驱动。

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

Also applies to: 234-244, 260-260, 282-283, 288-288, 294-294, 309-323, 335-335, 339-339, 350-350, 382-382, 389-389, 397-397, 402-402, 408-412, 432-432, 435-435, 446-446

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pages/open-library/book/`[id].tsx around lines 217 - 224, All user-facing
text strings in the book details page component must use the i18n t() function
instead of being hardcoded. Replace all hardcoded strings (including
"Loading...", "Book Not Found", "Back", "Reviews", "Borrow History",
"Returned/Active" and others at the specified line ranges: 217-224, 234-244,
260, 282-283, 288, 294, 309-323, 335, 339, 350, 382, 389, 397, 402, 408-412,
432, 435, 446) with t() function calls using appropriate i18n keys. First define
all the necessary translation keys in your i18n configuration, then
systematically update each hardcoded string reference to use t(keyName) instead.

Source: Coding guidelines

Comment on lines +118 to +121
<h1 className="display-4 fw-bold text-primary mb-3">图书目录</h1>
<p className="lead text-muted">
浏览我们的社区共享图书馆,发现有趣的书籍
</p>

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 | ⚡ Quick win

目录页关键 UI 文案未国际化。

Line 118-121、143、164、172 的标题/状态/提示/按钮文案为硬编码,建议全部替换为 t() key,避免语言切换后该页仍固定中文。

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

Also applies to: 143-144, 164-164, 172-172

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pages/open-library/books/index.tsx` around lines 118 - 121, Replace all
hardcoded Chinese text strings in the book directory page with i18n t() function
calls to enable proper language switching. Locate the hardcoded strings in the
h1 element containing "图书目录", the p element containing "浏览我们的社区共享图书馆,发现有趣的书籍",
and also check lines 143, 164, and 172 for additional hardcoded text (titles,
status messages, hints, or button labels). For each hardcoded string, wrap it
with the t() function using an appropriate translation key that describes the
content, ensuring all user-facing text follows the i18n guidelines and the page
properly reflects language changes when users switch locales.

Source: Coding guidelines

Comment on lines +9 to +13
<Layout title="How to Borrow - Open Library">
<ContentContainer>
<div className="mb-5">
<h1 className="display-4 mb-4">如何借阅</h1>

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 | 🏗️ Heavy lift

“如何借阅”页面未按项目 i18n 规范实现。

该页主体内容几乎全部为硬编码文案(标题、流程、规则、FAQ、CTA),建议整体改为 t() + 语言资源文件,保持与站点其余页面一致。

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

Also applies to: 16-23, 31-32, 54-157, 167-188, 195-223, 232-273, 279-290

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pages/open-library/how-to-borrow.tsx` around lines 9 - 13, The page contains
hardcoded user-facing text like "如何借阅" that should be internationalized. Replace
all hardcoded strings throughout the component (including the h1 title and all
content in the mentioned line ranges) with the t() function calls from the i18n
library. Create corresponding translation keys in the language resource files
and ensure each hardcoded string (titles, descriptions, process steps, rules,
FAQs, and CTAs) is replaced with t('keyName') calls, maintaining consistency
with the project's i18n implementation used in other pages.

Source: Coding guidelines

Comment on lines +124 to +129
📚 关于我们
</h2>
<p className="lead text-muted">
freeCodeCamp 成都社区「Open Library」开放共享图书馆
</p>
</div>

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 | ⚡ Quick win

首页仍有大量硬编码文案,需统一接入 t()

上述区段包含标题、描述、列表项与按钮文案等用户可见文本,当前直接写死字符串,和项目 i18n 规则冲突。

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

Also applies to: 135-156, 170-173, 202-208, 222-223

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pages/open-library/index.tsx` around lines 124 - 129, Replace all hardcoded
Chinese text strings in the component with the i18n `t()` function to comply
with internationalization standards. In the affected sections (lines 124-129,
135-156, 170-173, 202-208, and 222-223), wrap every user-facing text string
including titles like "📚 关于我们", descriptions like "freeCodeCamp 成都社区「Open
Library」开放共享图书馆", list items, and button labels with the `t()` function. Ensure
each string has a corresponding key defined in your i18n translation files.

Source: Coding guidelines

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Some improvements feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[feat] Open Library

2 participants