fix(checkin): prevent visual flicker when loading check-in component - #2566
Conversation
- Add initialLoaded state to track first data load completion - Set isCollapsed to null initially, determined after data loads - Show loading state on button and description text before data arrives - Remove auto-collapse effect that caused visual flicker - Add i18n translations for loading states (en/fr/ja/ru/vi/zh) Fixes issue where component would collapse/expand after data loads, causing visual flicker when navigating to personal settings page.
WalkthroughIntroduces an explicit Changes
Sequence Diagram(s)(omitted — change is localized to a single component's internal loading/collapse behavior and does not introduce multi-component sequential flows) Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (3)
web/src/i18n/locales/ja.json (1)
2143-2144: Avoid duplicate加载中...key; keep a single entryThere is already a
"加载中..."→"読み込み中..."entry earlier in this file, so this new one is redundant. JSON will keep only the last value, but duplicate keys make the locale harder to maintain. You can keep the existing global key and only add the new, specific"正在加载签到状态..."entry here.Proposed minimal cleanup
- "加载中...": "読み込み中...", - "正在加载签到状态...": "チェックイン状態を読み込み中...", + "正在加载签到状态...": "チェックイン状態を読み込み中...",web/src/i18n/locales/ru.json (1)
2254-2255: Deduplicate Russian"加载中..."translationAs in
ja.json,"加载中..."is defined twice here with the same Russian text"Загрузка...". Only the last one is effective, so this is redundant and may surprise future editors. Recommend keeping one"加载中..."entry and just adding the new"正在加载签到状态..."key for the check‑in UI.Proposed minimal cleanup
- "加载中...": "Загрузка...", - "正在加载签到状态...": "Загрузка статуса регистрации...", + "正在加载签到状态...": "Загрузка статуса регистрации...",web/src/components/settings/personal/cards/CheckinCalendar.jsx (1)
56-59: Align tri‑state collapse logic and avoid first‑click no‑op while loadingUsing
null/true/falseforisCollapsedis reasonable, but the current combination of:
onClick={() => setIsCollapsed(!isCollapsed)},- chevron selection via
isCollapsed ? <ChevronDown> : <ChevronUp>, andCollapsible isOpen={isCollapsed === false}leads to inconsistent behavior before the first load:
- Initial
isCollapsed === null→ panel is closed (isOpenis false) but the arrow shows as if open (Up).- First header click sets
isCollapsedtotrue, which still keeps the panel closed (true === falseis false), so the first click effectively does nothing from the user’s perspective.!isCollapsedwith a tri-state is also fragile for very fast repeated clicks.You can keep the “only
falsemeans open” contract and make everything consistent by:
- Using a functional updater that treats any non‑
falseas collapsed, and- Driving the icon off the same
=== falsecheck you use forCollapsible.Proposed collapse toggle & icon refactor
- <div - className='flex items-center flex-1 cursor-pointer' - onClick={() => setIsCollapsed(!isCollapsed)} - > + <div + className='flex items-center flex-1 cursor-pointer' + onClick={() => + setIsCollapsed((prev) => (prev === false ? true : false)) + } + > @@ - {isCollapsed ? ( - <ChevronDown size={16} className='text-gray-400' /> - ) : ( - <ChevronUp size={16} className='text-gray-400' /> - )} + {isCollapsed === false ? ( + <ChevronUp size={16} className='text-gray-400' /> + ) : ( + <ChevronDown size={16} className='text-gray-400' /> + )} @@ - <Collapsible isOpen={isCollapsed === false} keepDOM> + <Collapsible isOpen={isCollapsed === false} keepDOM>(Last line is unchanged, shown only to highlight the shared
=== falsecontract.)Also applies to: 193-207, 238-238
📜 Review details
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (7)
web/src/components/settings/personal/cards/CheckinCalendar.jsxweb/src/i18n/locales/en.jsonweb/src/i18n/locales/fr.jsonweb/src/i18n/locales/ja.jsonweb/src/i18n/locales/ru.jsonweb/src/i18n/locales/vi.jsonweb/src/i18n/locales/zh.json
🧰 Additional context used
🧬 Code graph analysis (1)
web/src/components/settings/personal/cards/CheckinCalendar.jsx (2)
web/src/helpers/secureApiCall.js (1)
data(55-55)web/src/helpers/utils.jsx (1)
showError(122-151)
🔇 Additional comments (2)
web/src/components/settings/personal/cards/CheckinCalendar.jsx (2)
82-107: First-load handling & error paths look correct
isFirstLoadderived frominitialLoaded, plus settingisCollapsedandinitialLoadedonly on that first load (including both non‑success and error branches), cleanly separates initial behavior from later month changes and should eliminate the original flicker.
210-216: Loading/status copy and button gating match the new UXThe header text and button state correctly:
- Show a dedicated “正在加载签到状态...” message until the first status fetch completes.
- Disable and show “加载中...” on the button until
initialLoadedis true.- Then switch to “今日已签到…” vs “每日签到可获得随机额度奖励” / “立即签到” based on
checked_in_today, while preventing repeat check‑ins.This matches the described UX changes and should prevent the incorrect “未签到” state during initial load.
Also applies to: 225-233
PR 类型
PR 是否包含破坏性更新?
PR 描述
问题描述
在签到功能中,当用户从其他页面切换到个人设置页面时,如果用户当天已签到,签到组件会出现视觉闪烁问题:
此外,在数据加载完成前,按钮和描述文本会显示"未签到"状态,容易造成误解。
解决方案
添加初始加载状态追踪:引入
initialLoaded状态变量,用于标记首次数据是否加载完成延迟确定折叠状态:将
isCollapsed初始值设为null(未确定),仅在首次数据加载完成后根据checked_in_today设置最终状态改进加载状态展示:
isCollapsed === false时展开(null 时保持关闭)删除自动折叠效果:移除根据
checked_in_today自动设置折叠状态的useEffect,避免数据刷新时改变用户手动设置的折叠状态国际化支持:在 6 种语言文件中添加"加载中..."和"正在加载签到状态..."的翻译
技术细节
fetchCheckinStatus中使用闭包捕获isFirstLoad状态,确保在异步操作完成时正确判断是否为首次加载isCollapsed === false替代!isCollapsed,明确区分null、true和false三种状态测试场景
Summary by CodeRabbit
Bug Fixes
New Features
Localization
✏️ Tip: You can customize this high-level summary in your review settings.