Skip to content

[Feat] : 출석체크 모달 상태 부모 관리 및 첫 접속 시 자동 오픈 (#182)#183

Merged
GulSam00 merged 2 commits into
developfrom
feat/182-checkInModalAutoOpen
Apr 10, 2026
Merged

[Feat] : 출석체크 모달 상태 부모 관리 및 첫 접속 시 자동 오픈 (#182)#183
GulSam00 merged 2 commits into
developfrom
feat/182-checkInModalAutoOpen

Conversation

@GulSam00
Copy link
Copy Markdown
Owner

@GulSam00 GulSam00 commented Apr 8, 2026

User description

📌 PR 제목

[Feat] : 출석체크 모달 상태 부모 관리 및 첫 접속 시 자동 오픈

📌 변경 사항

  • 출석 여부 판단 로직(parseLastCheckIn >= today)을 CheckInModal에서 Header(부모)로 이동하여 isCheckedIn prop으로 전달
  • CheckInModal에서 date-fns import 및 내부 날짜 비교 변수(today, parseLastCheckIn) 제거
  • 로그인 상태이고 미출석 시 첫 접속에서 출석체크 모달 자동 오픈하는 useEffect 추가
  • FallingIcons 배경색 bg-amber-50border로 스타일 변경
  • 포맷 정리 및 sitemap 갱신

💬 추가 참고 사항


PR Type

Enhancement


Description

  • Move check-in logic from modal to parent Header component

  • Auto-open check-in modal on first visit when not checked in

  • Pass isCheckedIn prop to CheckInModal for state management

  • Remove date-fns dependency from CheckInModal component

  • Update FallingIcons styling and format documentation


Diagram Walkthrough

flowchart LR
  Header["Header Component"]
  Logic["Check-in Logic<br/>date comparison"]
  Modal["CheckInModal<br/>receives isCheckedIn prop"]
  AutoOpen["Auto-open on<br/>first visit"]
  
  Header -- "calculates isCheckedIn" --> Logic
  Logic -- "passes isCheckedIn prop" --> Modal
  Header -- "useEffect triggers" --> AutoOpen
  AutoOpen -- "setOpen true" --> Modal
Loading

File Walkthrough

Relevant files
Enhancement
Header.tsx
Move check-in logic to Header and add auto-open                   

apps/web/src/Header.tsx

  • Import format from date-fns for date comparison
  • Calculate today and isCheckedIn state in Header component
  • Add useEffect hook to auto-open modal when user is logged in and not
    checked in
  • Pass isCheckedIn prop to CheckInModal component
+10/-0   
CheckInModal.tsx
Remove date logic and accept isCheckedIn prop                       

apps/web/src/components/CheckInModal.tsx

  • Remove date-fns import and date comparison logic
  • Add isCheckedIn boolean prop to component interface
  • Replace local date comparison with isCheckedIn prop usage
  • Simplify component by delegating state management to parent
+3/-6     
FallingIcons.tsx
Update FallingIcons background styling                                     

apps/web/src/components/FallingIcons.tsx

  • Change background styling from bg-amber-50 to border
+1/-1     
Formatting
getSongTag.ts
Reorder imports for consistency                                                   

packages/crawling/src/utils/getSongTag.ts

  • Reorder imports: move dotenv before OpenAI
+1/-1     
Configuration changes
sitemap-0.xml
Update sitemap timestamp                                                                 

apps/web/public/sitemap-0.xml

  • Update lastmod timestamp to current date
+1/-1     
Documentation
CLAUDE.md
Fix documentation table formatting                                             

packages/crawling/CLAUDE.md

  • Fix table formatting and alignment in GitHub Actions workflow
    documentation
+6/-6     

@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented Apr 8, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
singcode Ready Ready Preview, Comment Apr 8, 2026 1:12pm

@qodo-code-review
Copy link
Copy Markdown

Review Summary by Qodo

Move check-in modal state to parent and auto-open on first login

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Move check-in logic from CheckInModal to Header parent component
• Add isCheckedIn prop to CheckInModal for cleaner state management
• Auto-open check-in modal on first login if not checked in
• Update FallingIcons styling from background to border
• Format and sitemap updates
Diagram
flowchart LR
  Header["Header Component"]
  Logic["Date Comparison Logic"]
  CheckInModal["CheckInModal Component"]
  AutoOpen["Auto-open on First Login"]
  
  Header -- "calculates isCheckedIn" --> Logic
  Logic -- "passes isCheckedIn prop" --> CheckInModal
  Header -- "useEffect checks user state" --> AutoOpen
  AutoOpen -- "setOpen true" --> CheckInModal
Loading

Grey Divider

File Changes

1. apps/web/src/Header.tsx ✨ Enhancement +10/-0

Move check-in logic to Header parent component

• Import format from date-fns for date formatting
• Calculate today and isCheckedIn in Header component
• Add useEffect to auto-open modal when user is logged in but not checked in
• Pass isCheckedIn prop to CheckInModal component

apps/web/src/Header.tsx


2. apps/web/src/components/CheckInModal.tsx ✨ Enhancement +3/-6

Receive check-in status via prop instead of calculating

• Remove date-fns import and date calculation logic
• Add isCheckedIn prop to component interface
• Replace local date comparison with isCheckedIn prop
• Simplify component by removing date formatting logic

apps/web/src/components/CheckInModal.tsx


3. apps/web/src/components/FallingIcons.tsx Formatting +1/-1

Update FallingIcons container styling

• Change background styling from bg-amber-50 to border

apps/web/src/components/FallingIcons.tsx


View more (3)
4. packages/crawling/src/utils/getSongTag.ts Formatting +1/-1

Reorder import statements

• Reorder imports to place dotenv before openai

packages/crawling/src/utils/getSongTag.ts


5. apps/web/public/sitemap-0.xml ⚙️ Configuration changes +1/-1

Regenerate sitemap with updated timestamp

• Update lastmod timestamp to current build time

apps/web/public/sitemap-0.xml


6. packages/crawling/CLAUDE.md Formatting +6/-6

Format markdown table alignment

• Adjust table column alignment and spacing for consistency

packages/crawling/CLAUDE.md


Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review Bot commented Apr 8, 2026

Code Review by Qodo

Grey Divider

New Review Started

This review has been superseded by a new analysis

Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@GulSam00
Copy link
Copy Markdown
Owner Author

GulSam00 commented Apr 8, 2026

/describe

@GulSam00
Copy link
Copy Markdown
Owner Author

GulSam00 commented Apr 8, 2026

/review

@GulSam00
Copy link
Copy Markdown
Owner Author

GulSam00 commented Apr 8, 2026

/improve

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review Bot commented Apr 8, 2026

Code Review by Qodo

Grey Divider

New Review Started

This review has been superseded by a new analysis

Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown

qodo-code-review Bot commented Apr 8, 2026

Code Review by Qodo

🐞 Bugs (2)   📘 Rule violations (0)   📎 Requirement gaps (0)   🎨 UX Issues (0)
🐞\ ≡ Correctness (1) ☼ Reliability (1)

Grey Divider


Action required

1. Null check-in treated done 🐞
Description
Header에서 last_check_in이 null인 경우 lastCheckIn을 new Date()로 대체해 isCheckedIn이 true가 되어, 실제로는 미출석인데도 자동
오픈이 되지 않고 모달이 DONE 상태로 초기화됩니다. last_check_in이 null 가능한 타입 정의와 충돌해 신규/초기 사용자에서 출석 기능이 비활성화될 수 있습니다.
Code

apps/web/src/Header.tsx[R61-63]

  const lastCheckIn = user?.last_check_in ?? new Date();
+  const today = format(new Date(), 'yyyy-MM-dd');
+  const isCheckedIn = format(new Date(lastCheckIn), 'yyyy-MM-dd') >= today;
Evidence
User 타입에서 last_check_in은 null 가능인데, Header에서 null을 new Date()로 치환하여(=오늘 날짜) isCheckedIn 비교 결과가 항상
true가 됩니다. 이 값이 CheckInModal의 initalStatus로 전달되어 미출석 사용자도 DONE으로 시작할 수 있습니다.

apps/web/src/types/user.ts[1-7]
apps/web/src/Header.tsx[59-64]
apps/web/src/components/CheckInModal.tsx[16-56]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`last_check_in`이 `null`일 수 있는데도 `?? new Date()`로 오늘 날짜로 치환해버려, 미출석 사용자가 `isCheckedIn=true`로 판정됩니다.

### Issue Context
- `User.last_check_in` 타입은 `Date | null` 입니다.
- 현재 로직은 `null`을 '오늘 출석함'으로 간주합니다.

### Fix Focus Areas
- apps/web/src/Header.tsx[59-64]
- apps/web/src/components/CheckInModal.tsx[16-33]

### Suggested fix direction
- `lastCheckIn`을 `Date | null`로 유지하고, `isCheckedIn` 계산 시 `lastCheckIn`이 없으면 `false`로 처리하세요.
 - 예: `const lastCheckIn = user?.last_check_in ?? null;`
 - 예: `const isCheckedIn = lastCheckIn ? format(new Date(lastCheckIn), 'yyyy-MM-dd') >= today : false;`
- `CheckInModalProps.lastCheckIn`도 `Date | null`로 바꾸고(`useCheckInTimer`는 이미 `Date | null` 허용), 내부 사용처를 이에 맞게 조정하세요.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Auto-open reopens after refetch 🐞
Description
Header의 자동 오픈 useEffect는 '첫 접속 1회'를 보장하는 가드가 없고, user 쿼리 갱신으로 user 참조가 바뀔 때마다 미출석이면 setOpen(true)를
다시 실행할 수 있습니다. 예를 들어 미출석 상태에서 사용자가 모달을 닫은 뒤 포인트 사용(ThumbUpModal) 등으로 userCheckIn 쿼리가
invalidate/refetch 되면 출석 모달이 다시 강제로 열릴 수 있습니다.
Code

apps/web/src/Header.tsx[R84-88]

+  useEffect(() => {
+    if (!isLoading && !!user && !isCheckedIn) {
+      setOpen(true);
+    }
+  }, [isLoading, user, isCheckedIn]);
Evidence
Header는 (!isLoading && user && !isCheckedIn)이면 무조건 setOpen(true)를 수행하며, 의존성 배열에 user 객체 자체가
포함되어 있어 쿼리 데이터가 갱신될 때마다 effect가 재평가됩니다. 또한 usePatchSetPointMutation 등에서 동일한 ['userCheckIn'] 키를
invalidate하여 refetch를 유발할 수 있고, ThumbUpModal에서 해당 mutation을 실제로 사용합니다.

apps/web/src/Header.tsx[84-88]
apps/web/src/queries/userQuery.ts[5-18]
apps/web/src/queries/userQuery.ts[35-46]
apps/web/src/components/ThumbUpModal.tsx[40-52]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
미출석 상태에서 `userCheckIn` 쿼리가 invalidate/refetch 될 때마다 자동 오픈 effect가 다시 실행되어, 사용자가 모달을 닫아도 출석 모달이 재오픈될 수 있습니다.

### Issue Context
- Header effect는 `user` 객체 참조 변화에 민감합니다.
- `usePatchSetPointMutation`/`usePatchUserCheckInMutation`가 `['userCheckIn']`을 invalidate 합니다.
- ThumbUpModal에서 포인트 차감 mutation이 실행됩니다.

### Fix Focus Areas
- apps/web/src/Header.tsx[84-88]
- apps/web/src/queries/userQuery.ts[21-46]
- apps/web/src/components/ThumbUpModal.tsx[40-52]

### Suggested fix direction
- '첫 접속 1회'를 보장하는 플래그를 추가하세요.
 - 예: `const didAutoOpenRef = useRef(false);` 후 `if (!didAutoOpenRef.current && ...) { setOpen(true); didAutoOpenRef.current = true; }`
 - 또는 사용자가 닫았으면 같은 세션/같은 날짜에는 다시 자동 오픈하지 않도록 `sessionStorage/localStorage`에 기록
- 의존성에서 `user` 객체 전체 대신 `user?.id` 및 `isCheckedIn` 등 안정적인 스칼라 값만 사용해 불필요한 재실행을 줄이세요.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@qodo-code-review
Copy link
Copy Markdown

PR Description updated to latest commit (2628da5)

Comment thread apps/web/src/Header.tsx
Comment on lines 61 to +63
const lastCheckIn = user?.last_check_in ?? new Date();
const today = format(new Date(), 'yyyy-MM-dd');
const isCheckedIn = format(new Date(lastCheckIn), 'yyyy-MM-dd') >= today;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Action required

1. Null check-in treated done 🐞 Bug ≡ Correctness

Header에서 last_check_in이 null인 경우 lastCheckIn을 new Date()로 대체해 isCheckedIn이 true가 되어, 실제로는 미출석인데도 자동
오픈이 되지 않고 모달이 DONE 상태로 초기화됩니다. last_check_in이 null 가능한 타입 정의와 충돌해 신규/초기 사용자에서 출석 기능이 비활성화될 수 있습니다.
Agent Prompt
### Issue description
`last_check_in`이 `null`일 수 있는데도 `?? new Date()`로 오늘 날짜로 치환해버려, 미출석 사용자가 `isCheckedIn=true`로 판정됩니다.

### Issue Context
- `User.last_check_in` 타입은 `Date | null` 입니다.
- 현재 로직은 `null`을 '오늘 출석함'으로 간주합니다.

### Fix Focus Areas
- apps/web/src/Header.tsx[59-64]
- apps/web/src/components/CheckInModal.tsx[16-33]

### Suggested fix direction
- `lastCheckIn`을 `Date | null`로 유지하고, `isCheckedIn` 계산 시 `lastCheckIn`이 없으면 `false`로 처리하세요.
  - 예: `const lastCheckIn = user?.last_check_in ?? null;`
  - 예: `const isCheckedIn = lastCheckIn ? format(new Date(lastCheckIn), 'yyyy-MM-dd') >= today : false;`
- `CheckInModalProps.lastCheckIn`도 `Date | null`로 바꾸고(`useCheckInTimer`는 이미 `Date | null` 허용), 내부 사용처를 이에 맞게 조정하세요.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

그럼 >=가 아니라 =로 처리하면 되는 거 아니야?

@GulSam00 GulSam00 merged commit 9a99a73 into develop Apr 10, 2026
2 checks passed
@GulSam00 GulSam00 deleted the feat/182-checkInModalAutoOpen branch April 12, 2026 14:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

출석체크 모달 상태 부모 관리 및 첫 접속 시 자동 오픈

1 participant