Skip to content

Onboarding 중복 클릭 방지 가드 추가 #43

Merged
devgony merged 2 commits intoprography:mainfrom
devgony:onboarding-guard
Jul 21, 2025
Merged

Onboarding 중복 클릭 방지 가드 추가 #43
devgony merged 2 commits intoprography:mainfrom
devgony:onboarding-guard

Conversation

@devgony
Copy link
Collaborator

@devgony devgony commented Jul 21, 2025

Todo

  • 다음 버튼 API 호출 시 중복 클릭 방지
  • 기간 선택 버튼들 중복 클릭 방지
  • 달력 날짜 선택 중복 클릭 방지
  • 달력 월 네비게이션 중복 클릭 방지 (200ms 딜레이)
  • 제출 중 로딩 상태 표시 ("처리 중...")
  • 에러 발생 시 상태 복구로 재시도 가능

Summary by CodeRabbit

  • New Features

    • Improved UI responsiveness by disabling buttons and controls during form submission and navigation.
    • Added visual feedback and button state changes to prevent duplicate actions and enhance user experience during asynchronous operations.
  • Chores

    • Updated script to ensure environment variables from .env.dev are loaded when running the generator command.

devgony added 2 commits July 21, 2025 10:29
- 다음 버튼 API 호출 시 중복 클릭 방지
- 기간 선택 버튼들 중복 클릭 방지
- 달력 날짜 선택 중복 클릭 방지
- 달력 월 네비게이션 중복 클릭 방지 (200ms 딜레이)
- 제출 중 로딩 상태 표시 ("처리 중...")
- 에러 발생 시 상태 복구로 재시도 가능
@coderabbitai
Copy link

coderabbitai bot commented Jul 21, 2025

Walkthrough

The updates introduce enhanced UI state management to the period selection component, adding safeguards against user actions during asynchronous operations such as form submission and calendar navigation. Additionally, the gen script in package.json now loads environment variables from .env.dev before running the generator script.

Changes

File(s) Change Summary
app/onboarding/_components/PeriodSelectionScreen.tsx Added state variables and handler functions to manage UI interaction states during async operations; disabled controls and added debouncing to prevent rapid actions.
package.json Updated gen script to load environment variables from .env.dev using dotenv before execution.

Poem

A bunny hopped and pressed “Next” with glee,
But now must wait for the form to be free.
With buttons now dimmed, and calendars calm,
No more double clicks—what a soothing balm!
And with dotenv’s aid, in scripts we trust,
Our code hops forward, robust and just!
🐇✨

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

app/onboarding/_components/PeriodSelectionScreen.tsx

(node:29486) ESLintIgnoreWarning: The ".eslintignore" file is no longer supported. Switch to using the "ignores" property in "eslint.config.js": https://eslint.org/docs/latest/use/configure/migration-guide#ignoring-files
(Use node --trace-warnings ... to show where the warning was created)

Oops! Something went wrong! :(

ESLint: 9.31.0

ESLint couldn't find an eslint.config.(js|mjs|cjs) file.

From ESLint v9.0.0, the default configuration file is now eslint.config.js.
If you are using a .eslintrc.* file, please follow the migration guide
to update your configuration file to the new format:

https://eslint.org/docs/latest/use/configure/migration-guide

If you still have problems after following the migration guide, please stop by
https://eslint.org/chat/help to chat with the team.

✨ Finishing Touches
  • 📝 Generate Docstrings

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@devgony devgony requested a review from Hys-Lee July 21, 2025 01:33
@devgony devgony self-assigned this Jul 21, 2025
@devgony devgony added the bug Something isn't working label Jul 21, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (1)
app/onboarding/_components/PeriodSelectionScreen.tsx (1)

262-291: Well-implemented submission protection with room for enhanced error handling.

The submission logic correctly prevents duplicate submissions and manages state appropriately. Consider enhancing the error handling to provide user feedback beyond console logging.

Consider adding user-visible error feedback:

            } catch (error) {
              console.error('Failed to create goal:', error);
+             // Show toast notification or error message to user
+             // Example: showErrorToast('목표 생성에 실패했습니다. 다시 시도해주세요.');
              setIsSubmitting(false);
              // Handle error appropriately (show toast, etc.)
            }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 89992cf and d15d9d3.

📒 Files selected for processing (2)
  • app/onboarding/_components/PeriodSelectionScreen.tsx (10 hunks)
  • package.json (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
package.json (2)
Learnt from: CR
PR: prography/10th-Motimo-FE#0
File: .cursor/rules/global-rule.mdc:0-0
Timestamp: 2025-07-04T14:17:02.454Z
Learning: Applies to components/**/*.stories.{js,jsx,ts,tsx} : If Component is created, add storybook files as well.
Learnt from: CR
PR: prography/10th-Motimo-FE#0
File: .cursor/rules/global-rule.mdc:0-0
Timestamp: 2025-07-04T14:17:02.454Z
Learning: Applies to components/**/*.stories.{js,jsx,ts,tsx} : The first example name of storybook should be `Primary` not `Default`
🔇 Additional comments (14)
package.json (1)

14-14: LGTM! Consistent environment variable handling.

This change follows the existing pattern used by other scripts in the project and ensures environment variables are properly loaded during code generation.

app/onboarding/_components/PeriodSelectionScreen.tsx (13)

32-33: Well-implemented state management for duplicate prevention.

The new state variables clearly separate concerns between form submission and calendar navigation, providing granular control over UI interactions.


59-67: Excellent use of guard clauses for state protection.

The handler functions properly prevent state modifications during submission, ensuring data consistency throughout the async operation lifecycle.


110-111: Proper integration of duplicate click prevention in calendar.

The calendar day buttons correctly use the new handler and disabled state, providing both functional protection and visual feedback.


128-131: Smart debounce implementation for month navigation.

The 200ms debounce effectively prevents rapid consecutive month changes while the guard clause ensures navigation is blocked during form submission.


149-149: Correct integration of submission state in button logic.

The Next button enablement properly incorporates the submission state while preserving existing validation requirements.


171-186: Consistent implementation across period type selection.

The segmented control buttons properly implement the guard pattern with appropriate visual feedback during submission states.


220-231: Comprehensive state checking for navigation buttons.

The calendar navigation buttons properly check both navigation and submission states, ensuring robust protection against duplicate actions.


32-33: LGTM! Well-structured guard states.

The new state variables are properly initialized and follow clear naming conventions for preventing duplicate actions.


59-62: Excellent guard implementation for date selection.

The function properly prevents date changes during submission while maintaining clean, readable code with the early return pattern.


64-67: Consistent guard implementation for period type selection.

The function follows the same reliable pattern as handleDateSelect, ensuring consistent behavior across the component.


110-111: Well-implemented button state management.

The calendar buttons properly combine past date validation with submission guards, providing robust protection against invalid interactions.


220-224: Comprehensive button state management for navigation.

The disabled states properly account for all relevant conditions, ensuring consistent behavior with the navigation guard logic.

Also applies to: 231-231


171-176: Excellent integration of guard logic with visual feedback.

The period selection buttons properly use the centralized handler and provide clear visual feedback during disabled states.

Also applies to: 181-186

Comment on lines 127 to +131
const navigateMonth = (direction: "prev" | "next") => {
if (isNavigating || isSubmitting) return;

setIsNavigating(true);
setTimeout(() => setIsNavigating(false), 200);
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add cleanup for setTimeout to prevent memory leaks.

The navigation guard logic is well-implemented, but the setTimeout could cause issues if the component unmounts before the timeout completes.

+ const timeoutRef = useRef<NodeJS.Timeout | null>(null);
+
+ useEffect(() => {
+   return () => {
+     if (timeoutRef.current) {
+       clearTimeout(timeoutRef.current);
+     }
+   };
+ }, []);

  const navigateMonth = (direction: "prev" | "next") => {
    if (isNavigating || isSubmitting) return;
    
    setIsNavigating(true);
-   setTimeout(() => setIsNavigating(false), 200);
+   timeoutRef.current = setTimeout(() => setIsNavigating(false), 200);

Don't forget to import useRef and useEffect from React.

📝 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
const navigateMonth = (direction: "prev" | "next") => {
if (isNavigating || isSubmitting) return;
setIsNavigating(true);
setTimeout(() => setIsNavigating(false), 200);
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
useEffect(() => {
return () => {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
}
};
}, []);
const navigateMonth = (direction: "prev" | "next") => {
if (isNavigating || isSubmitting) return;
setIsNavigating(true);
timeoutRef.current = setTimeout(() => setIsNavigating(false), 200);
🤖 Prompt for AI Agents
In app/onboarding/_components/PeriodSelectionScreen.tsx around lines 127 to 131,
the setTimeout used to reset isNavigating lacks cleanup, risking memory leaks if
the component unmounts early. Fix this by storing the timeout ID in a useRef,
then use a useEffect hook to clear the timeout on component unmount. Also,
import useRef and useEffect from React at the top of the file.

};

const isNextEnabled = periodType === "months" || targetDate !== null;
const isNextEnabled = (periodType === "months" || targetDate !== null) && !isSubmitting;
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Ensure submission state is reset in all scenarios.

The submission logic has a potential issue where setIsSubmitting(false) is only called on error. If the API call succeeds, the component remains in the submitting state.

            try {
              await goalApi.createGoal({
                title: goal,
                isPeriodByMonth,
                month: isPeriodByMonth ? monthCount : undefined,
                dueDate,
                subGoals: [],
              });
              onNext();
            } catch (error) {
              console.error('Failed to create goal:', error);
-             setIsSubmitting(false);
              // Handle error appropriately (show toast, etc.)
+           } finally {
+             setIsSubmitting(false);
            }

Also, the guard at line 262 is redundant since the button is already disabled when isSubmitting is true. Consider removing it for cleaner code.

Also applies to: 262-265, 285-285, 291-291

🤖 Prompt for AI Agents
In app/onboarding/_components/PeriodSelectionScreen.tsx at line 149 and
surrounding submission logic, ensure that setIsSubmitting(false) is called in
both success and error paths of the API call to reset the submitting state
properly. Also, remove the redundant guard conditions around lines 262-265, 285,
and 291 that check isSubmitting before button actions, since the button is
already disabled when isSubmitting is true, simplifying the code.

Copy link
Collaborator

@Hys-Lee Hys-Lee left a comment

Choose a reason for hiding this comment

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

일단 가시죠

@devgony devgony merged commit e8c66e5 into prography:main Jul 21, 2025
3 of 4 checks passed
devgony added a commit to devgony/10th-Motimo-FE that referenced this pull request Jul 22, 2025
* use .env.dev for gen

* feat: 중복 클릭 방지 가드 추가

- 다음 버튼 API 호출 시 중복 클릭 방지
- 기간 선택 버튼들 중복 클릭 방지
- 달력 날짜 선택 중복 클릭 방지
- 달력 월 네비게이션 중복 클릭 방지 (200ms 딜레이)
- 제출 중 로딩 상태 표시 ("처리 중...")
- 에러 발생 시 상태 복구로 재시도 가능
devgony added a commit that referenced this pull request Jul 24, 2025
* Main page 일단 모킹은 가능하도록 했습니다. (#26)

* feat: TodoBottomSheet 완성

비동기 동작의 책임을 외부에 넘겼습니다.

* feat: 데이터 페칭 이후 타입 변환의 책임을 비동기 훅으로 변경

비동기 훅은 도메인 별로 커스텀 가능한 것이기 때문에 변경했습니다.

* feat: goal 관련 fetching함수 제작

* feat: TodoBottomSheet 동작 수정

초기값 바뀌는 동작 외부에서 key로 제어하지 않고, 내부에서 useEffect로 제어하도록 변경함.
key로 제어하면 remount때문에 애니메이션 이상해서.

* feat: todo, goal, subGoal에 대한 fethcing과 쿼리 훅 생성

데이터 처리를 쿼리 훅 내부에서 하도록 수정.
mutate는 대부분 낙관적 업데이트로 사용하지 않기 때문에 변환 로직으로 덮어쓰지 않았음.

* feat: TodoBottomSheet활성화, 선택된 goal관련 zustand store생성

이들 데이터는 멀리 떨어진 컴포넌트 사이에서 사용되기 때문에 전역 상태 사용함.

* feat: msw모킹 위한 api 및 db 생성

* feat: 메인 페이지 goal관련 데이터 갖는 GoalCard 컴포넌트 생성 (진행중)

* feat: 메인 페이지에 필요한 컴포넌트 생성 및 수정  MainHeader, GoalMenuContainer (임시)

문구 api연결은 아직 안했고, 컴포넌트 구분만 해뒀습니다.
GoalMenuContainer는 선택에 대해 zustand로 전역 상태 처리하도록 수정했습니다.

* feat: 메인 페이지 연결을 위한 자잘한 수정

fetchTemplate는 위치 변경으로 인한 수정.
GoalMenu는 api연결에 필요한 타입 export
TodoItem은 UI가 반응형으로 동작하도록 수정

* feat: TodoList 메인페이지 api연결을 위한 수정

쿼리 훅과 zustand 사용해 동작하도록 수정함. edit버튼 클릭에 대한 동작 추가함. UI반응형으로 동작하도록 w-full로 수정함.

* fix: 바텀 시트 todo추가 동작 수정, 바텀시트 선택된 subgoal 버튼에 보이도록 수정

todo추가 동작 수정에 대해서, 기존 분기처리 잘못해 update를 실행하던 것을 create실행하도록 수정

* fix: TodoBottomSheet 상태 초기화 수정

initTodoInfo를 매번 object 새로 생성해 넘겨줘서 useEffect가 동작했음. 이에 컴폰너트 내부에서 분해해서 사용하도록 수정함.

* feat: GoalCard 모달이 존재하면 바텀시트 닫도록 수정.

이렇지 않으면 dialog가 rule로 지정된 바텀시트에 focus-trap이 걸림.

* feat: useModal 수정

바텀시트 사용할 때 모달의 사용을 알 수 있도록 isOpen을 추가함.

* feat: TodoList에서 ModalAddingSubGoal 동작 관련 연결

subgoal을 추가할 수 있도록 api제작 및 연결

* fix: 자잘한 UI 에러 수정

* feat: 페칭 및 훅 자잘한 수정

use client추가 및 타입 수정

* feat: useTodoList undefined도 가능하도록 수정.

사용하는 입장에서 undefined반환 값으로 처리 분기할 수 있도록.

* feat: cheer, point 관련 fetching 제작

goalFetching에서 불필요 부분 삭제

* feat: 모킹 구조 변경 및 points, cheer 핸들러 추가

관리하기 쉽도록 분리했습니다.

* feat: 불필요 부분 삭제

콘솔 제거 및 element정리

* feat: fetch 동작에서 헤더 설정 수정

get요청에서도 authorization등 적용되도록 수정

* feat: 목표 추가 버튼 제작

모달 클릭 후 페이지 이동은 아직 구현하지 않았습니다.
해당 페이지 구현 마친 후 라우팅 추가하겠습니다.

* feat: GoalCard와 useGoalWithSubGoalTodo대해 타입 및 props명 변경에 따른 수정

* feat: BottomTabBar Link추가로 페이지 이동할 수 있도록 함.

* feat: main페이지에 BottomTabBar추가에 따른 UI수정

(이전 커밋에서 GoalCard에서 pb추가)
TodoBottomSheet는 바텀탭바 존재에 따라 위치 변경 가능하도록 수정.
추가로,
여기서, 기본 subGoal 지정.

* feat: main page에서 bottom tab bar관련 불필요 패딩 제거.

* feat: 로컬 개발 시 msw사용하도록 수정

발표할 때 필요할 것 같아서.

* Main page mock ui관련 수정 사항 반영 (#29)


발표할 때 필요할 것 같아서.

* feat: 시연 전 ui 수정사항 반영

* Main page mock msw 동작하도록 수정 (#30)


* feat: 임시 배포에서도 msw동작하도록 수정

* wip-1

* extract authStore

* feat: fix SSR hydration mismatch using Next.js dynamic imports

- Replace isClient workarounds with Next.js dynamic imports
- Apply { ssr: false } to BottomTabBar and MyPage components
- Remove unnecessary useClientOnly and useAuthState hooks
- Clean up conditional rendering logic in components
- Prevent 'Hydration failed' errors in console
- Maintain clean code without workarounds

* feat: implement groups page with reusable components

- Create GroupEmptyState component for no groups state
- Add PendingGroupCard component for individual group cards
- Build PendingGroupList component for groups collection
- Implement GroupPage main component with AppBar integration
- Add comprehensive Storybook stories for all components
- Create app/group route with BottomTabBar integration
- Download and integrate group empty state image from Figma
- Follow component composition pattern for reusability
- Include proper TypeScript interfaces and props
- Support responsive design with Tailwind CSS

* feat: update group page text styles to match Figma design

- Apply SUIT font family with 700 weight to section titles
- Update font size from 24px (text-2xl) to 20px (text-xl) per Figma spec
- Add line-height 1.2em and letter-spacing -1% for precise typography
- Improve layout with proper padding (px-4, py-4) around sections
- Update GroupPage stories to use GroupData type consistently
- Add WithJoinedGroups story for testing joined groups state
- Ensure text alignment matches design: left-aligned titles

Figma reference: node-id=54330-13373

* remove unused

* generate api

* fix get access token

* implement getJoinedGroups

* refactor: Update fetchTemplate to use auth store instead of localStorage

* generate api

* feat: Add API service wrapper with automatic Bearer token authentication

- Create service.ts as centralized API client wrapper
- Integrate with useAuthStore for automatic token management
- Export individual API groups for convenient usage
- Automatically add Bearer token to all API requests via securityWorker

* refactor: Implement dynamic API/SWR mapping with type safety

- Replace manual hook creation with dynamic useApiQuery function
- Add comprehensive type definitions for API client mapping
- Implement automatic parameter and return type inference
- Add useQuery convenience object for common patterns
- Maintain backward compatibility with legacy hook exports
- Enable future-proof API integration without manual mapping
- Support conditional fetching and custom SWR keys

* refactor: Improve API service SWR integration and debugging

- Optimize SWR fetcher functions to remove unnecessary async/await
- Add debugging capabilities for API response parsing issues
- Test useMyProfile hook implementation in MyPage component
- Investigate and address API response data handling problems
- Update service.ts with better SWR integration patterns

* refactor: Replace legacy SWR hooks with centralized service.ts hooks

- Remove hooks/main/queries folder with custom SWR hooks
- Replace useGoalList with useGoals from service.ts
- Replace useGoalWithSubGoalTodo with useGoalWithSubGoals from service.ts
- Replace useTodoList with useSubGoalTodos from service.ts
- Migrate data conversion logic inline to components
- Maintain backward compatibility with existing component interfaces
- Consolidate all API calls through centralized service layer
- Remove duplicate SWR logic and improve maintainability

* refactor: Restructure API service architecture

- Move service.ts to api/service.ts for better organization
- Separate SWR hooks into api/hooks.ts for modular architecture
- Split core API client from SWR functionality
- Update all import paths from @/service to @/api/hooks
- Maintain clean separation of concerns:
  - api/service.ts: Core API client and types
  - api/hooks.ts: SWR-based React hooks
- All components updated with new import paths
- Build successful with no compilation errors

* refactor: Extract useApiQuery into separate module

- Create dedicated api/useApiQuery.ts for dynamic API query hook
- Remove useApiQuery implementation from api/hooks.ts
- Import and re-export useApiQuery from the new module
- Maintain full backward compatibility with existing imports
- Improve code organization with single responsibility principle
- Clean separation between core hook logic and convenience wrappers
- Build successful with no compilation errors

* feat: Integrate environment variable for API baseUrl

- Update api/service.ts to use SWAGGER_URL from .env file
- Extract base server URL from SWAGGER_URL automatically
- Add getBaseUrl() helper function with URL parsing logic
- Maintain fallback to empty string for proxy scenarios
- Fix import in MyPage.tsx to use separate useApiQuery module
- Environment-driven configuration for better deployment flexibility
- Build successful with no compilation errors

* add env

* fix: Use NEXT_PUBLIC_ prefix for client-side environment variables

- Add NEXT_PUBLIC_API_URL to .env file with proper API base URL
- Update api/service.ts to use NEXT_PUBLIC_API_URL instead of API_URL
- Remove debugging console.log statement
- Fix Next.js client-side environment variable access
- Ensure proper API URL resolution in production builds
- Build successful with correct environment variable usage

* feat: Separate environment configurations for dev and local

- Add dotenv-cli dependency for explicit env file control
- Update package.json scripts:
  - 'npm run dev': uses .env file
  - 'npm run local': uses .env.local file (new)
- Create .env.local with local development overrides
- Add comments to distinguish .env and .env.local usage
- Add .env.local to .gitignore for local-only settings
- Support different API endpoints for dev vs local environments
- Build successful with proper environment variable loading

* feat: Configure local API server for npm run local

- Add USE_LOCAL_API environment variable to control API destination
- Update next.config.ts to dynamically choose between local and remote API
- Configure .env for remote API (motimo.kro.kr:8080) in dev mode
- Configure .env.local for local API (localhost:8080) in local mode
- Set NEXT_PUBLIC_API_URL to empty string in local mode to use Next.js proxy
- Enable seamless switching between local and remote API environments
- Build successful with conditional proxy configuration

* refactor: Complete environment file separation for dev and local

- Rename .env to .env.dev for team development settings
- Update package.json dev script to use .env.dev explicitly
- Add .env.local to .gitignore for local-only settings
- Complete isolation: no cross-contamination between environments
- Dev mode: only .env.dev loaded (remote API)
- Local mode: only .env.local loaded (localhost API)
- Build successful with proper environment separation
- Teams can share .env.dev while keeping .env.local private

* refactor: Replace all templateFetch usage with SWR hooks and direct API calls

- Replace templateFetch-based functions with api/hooks.ts SWR hooks for GET requests:
  - getCheerComment → useCheerPhrase in MainHeader
  - getPoints → usePoints in MainHeader

- Replace templateFetch-based functions with direct API calls for mutations:
  - deleteTodo → todoApi.deleteById in TodoList
  - toggleTodo → todoApi.toggleTodoCompletion in TodoList
  - createNewSubGoalOnGoal → goalApi.addSubGoal in TodoList
  - createNewTodoOnSubGoal → subGoalApi.createTodo in GoalCard
  - updateTodo → todoApi.updateTodo in GoalCard

- Remove unused createNewGoal import from GoalMenuContainer
- Add proper date string conversion for API calls
- Eliminate dependency on lib/main/ templateFetch functions
- Centralize all API calls through api/service.ts
- Build successful with 0 compilation errors

* remove: delete legacy templateFetch files

- Delete lib/common/fetchTemplate.ts
- Delete all lib/main/*Fetching.ts files
- All functionality replaced by new API service architecture

* chore: remove unused

* remove .env.local from gitignore

* tidy up

* refactor: simplify auth store initialization

- Remove redundant getInitialState function
- Let persist middleware handle initial state loading automatically
- Remove manual localStorage reading to prevent conflicts
- Remove skipHydration flag as it's no longer needed
- Improve consistency and prevent potential hydration mismatches

* feat: improve authentication handling and fix hydration issues

- Add NEXT_PUBLIC_FRONTEND_BASE_URL to environment configs
- Refactor app/page.tsx to use AuthGuard component for cleaner auth logic
- Add immediate client-side hydration to useAuthStore
- Create AuthGuard component with dynamic import to avoid SSR issues
- Remove complex authentication logic from main page component

* refactor: update group page to use new API hooks and types

- Replace old useGroupsMe hook with useJoinedGroups from @/api/hooks
- Update GroupPage component to use new API types (GoalNotInGroupRs, JoinedGroupRs)
- Remove unused imports and dependencies (useAuthStore, useState)
- Clean up old hook files and fetching utilities
- Simplify group page logic with new API integration

* refactor: implement generic-based GroupList with type guards

- Convert GroupList to use generics with JoinedGroupRs | GoalNotInGroupRs constraint
- Add type guard function isJoinedGroupRs for runtime type checking
- Implement conditional rendering based on group type
- Update GroupList.stories.tsx to use actual API types instead of mock GroupData
- Remove unused GroupData interface and BaseGroupData interface
- Add proper type-specific property handling:
  - JoinedGroupRs: uses lastActiveDate and isNotificationActive
  - GoalNotInGroupRs: uses undefined for lastActivityDate and false for hasNotification
- Fix missing useRouter import
- Improve type safety and maintainability

* feat: add goal ID routing and error handling for GroupList

- Add goal ID as query parameter when navigating to join-random page
- Implement error handling for missing goal IDs:
  - Log error to console with group title for debugging
  - Show user-friendly alert message
  - Prevent navigation when goal ID is missing
- Improve user experience with proper error feedback

* feat: implement join random group page based on Figma design

- Create /group/join-random page with Figma design implementation
- Add thumbs up illustration with proper positioning and colors
- Implement goal information card showing selected goal and period
- Add API integration:
  - useGoalDetail hook to fetch goal information
  - joinRandomGroup API call for actual group joining
  - Proper error handling and loading states
- Add URL parameter support for goalId from GroupList navigation
- Implement user experience features:
  - Auto-redirect if goalId is missing
  - Loading states with disabled button
  - Success/error alert messages
  - Automatic navigation to group page on success
- Add period calculation from goal due date
- Create storybook file for development and testing
- Follow design tokens and component patterns from existing codebase

* add text-center, remove mt-auto

* add justify-center

* feat: add group detail page and improve group join flow

- Add group/[id] page with Figma design implementation
- Add SystemMessage component for group notifications
- Add UsersGroupIcon for group header
- Update group join flow to redirect to specific group page
- Add Storybook files for new components
- Refactor component exports for consistency

Resolves group detail page requirements from Figma design

* fix: escape quotes in group detail page title

- Fix react/no-unescaped-entities lint error
- Use &quot; HTML entities for quotes in JSX

* fix: resolve type errors and template literal updates

- Fix Next.js 15 params Promise type issue using React.use()
- Remove non-existent GroupData type references
- Update storybook mock data to match actual API types
- Fix JoinedGroupRs and GoalNotInGroupRs type usage
- Update quote handling to use template literals

All TypeScript compilation errors resolved

* fix: wrap useSearchParams in Suspense boundary to fix build error

- Extract main component logic into JoinRandomGroupContent
- Add LoadingPage component for suspense fallback
- Wrap component in Suspense to prevent prerendering error
- Resolves Next.js build error about missing suspense boundary

* feat: Update environment configuration and build scripts

- Rename .env.local to .env.localhost for clarity
- Update package.json local script to use .env.localhost
- Add NODE_ENV=production to build script
- Add .env.production configuration file

* fix: Add Next.js router mocking to Storybook

- Add React import to .storybook/preview.tsx
- Configure nextConfigPath in .storybook/main.ts for proper Next.js integration
- Add mockRouterFunctions with console logging for debugging
- Configure nextRouter parameter with all required router properties
- Resolves 'invariant expected app router to be mounted' error in stories

* feat: Complete Next.js router mocking solution for Storybook

- Create dedicated nextjs-mock.ts file with proper Next.js navigation exports
- Add webpack alias in main.ts to redirect next/navigation imports to mock
- Clean up preview.tsx configuration by removing complex decorators
- Export all Next.js navigation functions (useRouter, useSearchParams, etc.)
- Provides console logging for debugging navigation interactions
- Resolves App Router compatibility issues in Storybook stories

* feat: Add onboarding completion check and redirect

- Add hasCompletedOnboarding check from useAuthStore in onboarding page
- Redirect users to home page if they have already completed onboarding
- Prevents users from accessing onboarding flow after completion

* feat: Implement useOnboardingStore for centralized data management

- Create useOnboardingStore with zustand for onboarding form data
- Refactor GoalInputScreen to use store instead of props
- Refactor PeriodSelectionScreen to use store and call goalApi.createGoal with real data
- Refactor CompletionScreen to use store for display data
- Simplify onboarding page by removing local state management
- Replace hardcoded test data with actual user input in goal creation
- Centralize all onboarding data management in dedicated store

* Add OAuth state and onboarding completion tracking to auth store

* Refactor auth store hydration to use useEffect hook

* Fix due date calculation logic for month-based periods

* Add error handling for goal creation API call in onboarding

* create random group

* revert useEffect

* wip1

* update api

* feat: Update API hooks and fix TypeScript errors

- Update hooks.ts to match latest API specification
- Fix groupChat hook parameters (page/size -> limit/cursor/direction)
- Add missing API hooks (groupDetail, newGroupMessages, notifications)
- Fix getJoinedGroup -> getJoinedGroups method name
- Update GroupDetailPage to use correct API parameters
- Add GetGroupChatParamsDirectionEnum import
- Fix data structure access (messages.content -> groupChat.messages)
- Resolve all TypeScript compilation errors

* feat(group): integrate API data for group details and user profile

- Add useGroupDetail hook to fetch dynamic group name
- Add useMyProfile hook to get user nickname
- Replace hardcoded title with dynamic group name from API
- Update system message to use actual user nickname instead of placeholder

* refactor(group): improve navigation functionality and clean up components

- Remove unused onJoinGroup prop from GroupPage and GroupList
- Rename onJoinClick to onClick in GroupItem for consistency
- Add actual navigation functionality to group items:
  * Joined groups navigate to /group/{groupId}
  * Pending groups navigate to /group/join-random?goalId={id}
- Add hover cursor pointer styling to joined group items
- Simplify pending group click handler by removing unnecessary error handling
- Fix code formatting and indentation

* remove unused

* refactor(GoalCard): simplify boolean conversion

Replace redundant ternary operator with double negation for cleaner code:
- reported: todoInfo.todoResultId ? true : false → reported: git diff --cachedtodoInfo.todoResultId

* feat(api): enhance error handling and add runtime validation in useApiQuery

- Add validation check for API group existence before method access
- Wrap method invocation in try-catch for better error reporting
- Provide more descriptive error messages with context about which API group and method failed
- Improve debugging experience with detailed error information

* remove env.local

* generate api

* sync healthApi

* feat: update API service and hooks to match latest generated API

- Add healthController API export to service
- Fix method names: getGoalWithSubGoalAndTodo → getGoalWithSubGoalAndTodos
- Fix method names: getIncompleteOrTodayTodos → getIncompleteOrTodayTodosWithSlice
- Add pagination support for sub-goal todos hooks
- Add new hooks: completedGoals, health, allSubGoalTodos
- Maintain backward compatibility with legacy hook exports
- Update all API endpoints to match generated API structure

* generate api

* fix: update notification hook to use page parameter instead of offset

- Change notifications hook to use page (default 0) and size parameters
- Align with API specification that expects page/size instead of offset/limit

* feat: format lastActivityDate in GroupItem and fix navigation

- Add date formatting function to display dates in YYYY.MM.DD format
- Change group detail back navigation to use router.push("/group")

* Onboarding 중복 클릭 방지 가드 추가  (#43)

* use .env.dev for gen

* feat: 중복 클릭 방지 가드 추가

- 다음 버튼 API 호출 시 중복 클릭 방지
- 기간 선택 버튼들 중복 클릭 방지
- 달력 날짜 선택 중복 클릭 방지
- 달력 월 네비게이션 중복 클릭 방지 (200ms 딜레이)
- 제출 중 로딩 상태 표시 ("처리 중...")
- 에러 발생 시 상태 복구로 재시도 가능

* Detail page 및 메인 페이지 ui일부 수정 (#40)

* feat: detail page 수정중

다른 브랜치 작업 위한 임시 커밋

* feat: netlify 배포 세팅

* feat: netlify 배포 세팅 초기화

기존 세팅은 정적 방식이었음.
동적 라우팅이 존재하기 때문에 이전 세팅으로는 빌드가 안 됨.

* feat: 배포 404 에러 관련 수정

* feat: 메인페이지 bottom tab bar추가 및 bottom sheet와 함께 모바일 넓이에 맞게 조정

body자체를 scrollbar에 의해 layout shift발생하지 않게 수정하고, bottom sheet에도 적용했습니다.
component/shared 패키지 버전 수정에 따른 lock파일 변경이 추가로 있습니다.
bottom tabbar의 fixed로 인해 modal과의 z-index차이를 조정했습니다.
상단 AppBar관련해서 배너 상단에 공간을 만들어 ui겹침을 제거했습니다.

* feat: 상세-편집 페이지GoalEdit 위치 변경 및 바텀시트와 모달 추가

* feat: 상세-편집 페이지 subGoalEdit 영역 추가

api및 디자인 세부 적용 안됨.

* fix: TodoBottomSheet 버그 수정

엔터로 입력하면 높이 이상해지는 버그 수정했습니다.
focus관련한 버그여서 blur처리로 수정했습니다.

* fix: fetching 반환값 반환하도록 해서 이후 동작 연결되도록 수정

반환값을 보고 결과를 판단하도록 로직을 짰는데, 반환하지 않아서 제대로 작동하지 않았었습니당.

* feat: dev서버 배포 전 프록시 및 msw수정

주소 동적 연결되게 수정 및 msw 주석처리.
이외 자잘한 오류 정리

* feat: api gen 최신화

* feat: fetching 함수들 디렉토리 위치 변경에 따른 수정

페이지에 따라 구분되지 않아서 디렉토리 구조 수정

* feat: 상세-편집 페이지 context를 사용한 상태관리와 api연결

* feat: useGoalWithSubGoalTodo반환 타입 변화에 따른 GoalCard수정

fetch관련 훅이 undefined도 반환할 수 있도록 하여, 이를 사용하는 쪽에서 핸들링 하도록 했습니다.

* feat: shared의 AppBar수정

type button으로 해서 form에 submit안시키도록 함.
event 인자를 받을 수 있도록 변경.
shared빌드해서 처리함.

* feat: 메인 페이지에서 detail 페이지로 이동 기능 추가

* feat: api 재생성 및 Edit_Pencil svg의 stroke 수정

외부에서 색 넣을 수 있도록 currentColor로 변경

* feat: ModalUpdatingSubGoal 생성

* feat: Edit페이지를 EditBody와 EditHeader 생성해 분리

fetch를 통한 서버 상태와 클라이언트 상태 분리 및 관리 용이하도록.

* feat: 세부페이지-편집 EditBody와 EditHeader로 분리함으로 인한 수정

* feat: 모달 동작 및 세부목표 추가 동작 관련 수정

goalId넣어서 fetch동작하도록 함.
ModalUpdatingSubGoal로 변경 및 초기 데이터 추가

* fix: 동작 관련 자잘한 수정

GoalEdit은 form에 영향 안 주도록 함.
나머지는 타입, 값, ui자잘한 수정

* feat: GoalDurationBottomSheet absolute로 중앙정렬 렌더링ㄹ 되도록 수정

* feat: 상세페이지 라우팅 적용

* feat: 빌드 에러 관련 컴포넌트 이름 수정

Body였던 컴포넌트 명을 변경(native element와 빌드 시 혼동 방지)

* feat: 로그인 리다이렉션 주소 환경변수화

배포 환경에서 주소 바꿀 수 있도록 함.

* feat: 메인페이지 수정사항 추가 - GoalMenuContainer

골메뉴 많을 때 가려지도록 overflow hidden추가

* Main page - 로그인 리다이렉션 주소 환경변수화 (#36) (#37)

* feat: 로그인 리다이렉션 주소 환경변수화

배포 환경에서 주소 바꿀 수 있도록 함.

* feat: fetching관련 불필요 제거, 타입 정리, 반환값 처리, 이름 변경.

lib/fetching으로 사용하기로 했는데 머지 과정에서 lib/main이 남아버려서 제거함.

* feat: ModalIncompletingSubGoal 생성

* feat: ListCard 동작 및 fetching 결과 제출 제외 연결

* feat: GoalData 그룹 있을 때 처리 수정

* feat: 목표 상세 컨텐츠 담는 DetailBody생성

* feat: api gen

* feat: 목표 상세 ui구조 변경 및 목표 달성 모달 처리

그룹이동 및 목표완료처리 버튼 밖으로 꺼냄.
컴포넌트 책임상.

* feat: useGoalWithSubGoalTodo 반환 타입 변경으로 인한 수정

undefined 옵셔널 처리에 따른 수정

* feat: GoalData 데이터 주입 완료. UI제외 완성

* feat: TodoResultBottomSheet 동작 완성

* feat: ListCard에 BottomSheet동작 연결

* feat: d-day계산 추출 및 적용

* feat: 목표 상세 api 훅 생성

추가로 fetching 함수 수정

* feat: GoalData 목표 완료 이모지 추가 및 기타 수정

useGoalDetail에서 goalId만 사용하도록 수정
modalIncompletingSubGoal에서 incompleting함수 실행하도록 수정

* feat: svg관련 icon으로 사용하지 않도록 next config수정 및 detail페이지에서 DetailBody사용

* feat: GoalDurationBottomSheet 오버레이 ui 수정

오버레이 배경색 안먹혔던 것을 수정

* feat: 한 컴포넌트에서 BottomSheet여러개 사용되는 경우 대비 수정.

Drawer.Content의 위치 잡아주는 부모요소를 fixed를 통해 위치 고정

* feat: TodoResultBottomSheet 바텀 탭 바 존재할 때 케이스 처리

* feat: 메인 TodoList에서 투구 결과물 제출 관련 바텀시트와 연결

* feat: 상세 페이지에서 바텀 탭바 관련 처리

상세페이지는 필요 없으므로 이에 대해 처리.

* feat: 목표 추가 페이지 제작

상세 목표 편집 페이지랑 유사한 부분이 많았는데, 해당 페이지에서 컴포넌트 분리하기 애매해서 걍 새로 만들었습니다. 추후 리팩토링 할 듯 합니다.

* feat: 메인 페이지에서 목표 생성 페이지 연결 적용

* feat: formData를 post하는 경우 처리

추후 api처리한 PR머지되면 교체 예정

* feat: 목표 상세 페이지 디자인 적용

편집 및 목표 추가 페이지 제외.
close_circle관련 설정 변경으로 인한 TextField에서의 수정(디자인 변화는 없음)

* feat: 상세-편집 페이지 디자인 적용

* feat: 상세-목표 추가 페이지 디자인 적용

* feat: 메인 페이지 골 메뉴 좌우 드래그 처리

좌우 드래그를 통해 골 메뉴들을 확인할 수 있도록 수정했습니다.
휠 처리가 필요한지는 QA후에 결정될 것 같슴다

* feat: 세부목표 순서 변경 처리

* feat: 투구 result emotion처리 수정

백엔드에서 enum값이 바뀌어서 수정

* feat: todoItem에서의 처리 관련 mutate 및 세부 페이지로 이동 처리

* feat: api 훅 수정으로 인한 적용부 수정

타입 변환이 필요한 경우 기존 api 훅 래핑한 커스텀 훅으로 처리

* feat: api gen과 마이너 수정

* feat: subgoal에 대한 todo fetch api의 pagination 기반으로의 변경으로 인한 수정

api gen에서의 fetch반환 타입 정의에 버그가 있어 수동으로 fetch제작.
메인 페이지의 GoalCard, TodoList와 상세 페이지의 ListCard에서 새로 만든 훅을 적용.
또한, 기존에 사용하던 api의 반환 타입 변경으로 인해 연관된 영역에서 수정함.

* feat: 세부 목표 완료 처리

* feat: 메인페이지 무한스크롤 적용 및 기존 무한스크롤 쿼리 훅 offset처리 수정

기존에는 size만큼 offset이 증가하지 않았어서 수정함.

* feat: api gen 및 쓰지 않는 api관련 빌드 에러 수정

찌르기 api가 없어졌고 그룹 api로 통합된 것으로 보임.

* feat: package lock 수정(npm 재설치)

* feat: .env 파일 삭제

production에서 사용되는 듯 해서.

* feat: 배포용 프록시 설정 추가

* feat: 배포 환경 api 프록시 수정

* feat: 상세페이지 목표 제거 api 연결

* feat: GoalDurationBottomSheet 디자인 적용

스타일 적용 안되어있었음

* feat: 상세 페이지 관련 컴포넌트 pr전 스토리북 생성

* feat: 상세 페이지 컴포넌트 스토리 경로 수정

* feat: 목표 완료 시 완료 이미지 뜨도록 수정

이전에는 progress가 100%일 때 뜨도록 했었는데, 목표 완료시 progress가 0이 되는 이슈가 있기도 해서 더 확실한 것으로 수정했습니다.

* fix: 배너 y overflow 처리 추가

* feat: 상세 페이지 바텀 시트 추가

바텀시트에서 활성화 관련 불필요 부분 수정 추가.

* fix: DetailBody에서 목표 완료 이후 목표 완료시키는 버튼 보이지 않도록 수정

* fix: DetailBody 목표 완료 이후에 목표완료모달 역시 뜨지 않도록 수정

* fix: 목표에서 isCompleted 추가 관련 빌드 에러 수정

* fix: resolve TypeScript build errors in group components

- Fix type mismatch in join-random page by accessing goalDetail.dueDate.dueDate
- Update GroupChat stories to use correct GroupMessageContentRs structure
- Fix GroupChat component to access message properties correctly
- Remove invalid onJoinGroup prop from GroupPage stories

* improve: enhance error message construction in useApiQuery for better debugging

- Extract proper error message from Error objects instead of converting entire error to string
- Maintain fallback for non-Error objects using String() conversion
- Improves readability of error messages when API calls fail

* feat: add new message notifications to group items

- Add hasNewMessages prop to BellIcon component
- Show notification dot when either hasNotification or hasNewMessages is true
- Integrate useNewGroupMessages hook in GroupItem to fetch new message status
- Pass groupId prop to GroupItem and GroupList for message checking
- Update GroupList to handle different group types with appropriate IDs

* remove: delete .env.production file

* fix: simplify default goal title in join random group page

* remove: replace all alert() calls with console statements

* feat: add Loading component with Lottie animation

- Install lottie-react dependency
- Add Lottie animation file from LottieFiles
- Create reusable Loading component with size variants
- Add Storybook stories for different use cases
- Export component from shared components index

* fix: update Loading component with proper asset loading and styling

- Use fetch API to dynamically load Lottie animation JSON
- Add fallback CSS spinner while animation loads
- Update text styling to match design specs (16px, label-normal color)
- Increase size variants for better visibility
- Add Loading component usage in join random group page

* refactor: use local import for Lottie animation instead of fetch

- Move animation JSON file to component directory
- Replace async fetch with direct import for better performance
- Remove useState, useEffect, and fallback spinner logic
- Simplify component code and improve load time

* feat: add navigation to member page from group detail

* feat: implement group member page with member list and leave group functionality

* feat: add date formatting utility and implement poke functionality

- Create reusable formatDate utility in lib/date.ts
- Replace hardcoded date with dynamic lastOnlineDate formatting
- Implement poke notification API call in member page
- Refactor GroupItem to use shared date utility

* feat: add toast notification for poke functionality

* feat: implement leave group functionality with confirmation and navigation

* refactor: replace browser confirm with custom Modal for leave group confirmation

* feat: implement notification page with AppBar navigation and Figma design

* refactor: improve BellIcon prop naming for better clarity

* refactor: improve notification page ternary logic

- Always render notification count header instead of duplicating
- Use conditional rendering for "모두 읽음" button based on notification count
- Simplify empty state by removing redundant count display
- Remove unnecessary fragment wrapper in notification list

* feat: update NotificationIcon component with proper bell icon design

Replace eye icon with correct bell notification icon matching Figma specifications

* feat: implement infinite scroll for notification page

Add automatic loading of next page when user scrolls near bottom with loading indicator

* feat: add mock data for testing infinite scroll in notifications

Add mock notification generator with 156 items and debug toggle to test infinite scroll functionality

* refactor: extract NotificationContent component and move mock data to Storybook

- Extract reusable NotificationContent component from notification page
- Clean up notification page to use only real API data
- Add comprehensive Storybook stories for testing infinite scroll with mock data
- Improve component separation and testability

* fix: resolve TypeScript errors in AppBar and notification components

- Remove invalid hasNotification and onNotificationClick props from AppBar usage
- Import and use NotificationItemRsTypeEnum for proper type safety in stories
- Change null to undefined for CustomPageNotificationItemRs compatibility
- Update AppBar stories to remove non-existent prop controls

* fix: improve loading UI for join random group page

- Replace ineffective Suspense with proper Loading component display
- Show Loading component during goal data fetch and group joining
- Remove unused Suspense wrapper and import
- Replace button loading text with full-screen Loading component

* fix: add input validation and error handling to formatDate function

- Add validation for falsy and non-string inputs
- Add invalid date detection using isNaN check
- Return consistent '--.--.--' fallback for invalid inputs
- Add explicit string return type annotation
- Prevent "NaN.NN.NN" display in UI for malformed dates

* refactor: improve type safety and simplify notification content parsing

- Change Notification type property to use strict typing with keyof typeof NOTIFICATION_TYPE_MESSAGES
- Remove fragile regex parsing for nickname extraction
- Consolidate similar notification types into single case handling
- Simplify content rendering to directly use notification content
- Reduce code complexity and potential parsing errors

* fix: improve timeout handling and error management in group member page

- Add useRef to track timeout IDs and prevent memory leaks
- Add useEffect cleanup to clear timeouts on component unmount
- Standardize toast timeout duration to 2000ms for consistency
- Apply proper timeout management to all toast scenarios
- Prevent hanging timeouts after component cleanup

* fix: resolve TypeScript error in useRef timeout declaration

- Add null initial value to useRef<NodeJS.Timeout | null>(null)
- Fix missing required argument error in TypeScript compilation
- Maintain type safety for timeout reference handling

* fix: wrap useSearchParams in Suspense boundary for join-random page

- Add Suspense import back to React imports
- Wrap JoinRandomGroupContent component that uses useSearchParams()
- Add appropriate Loading fallback for page loading state
- Resolve Next.js warning about missing Suspense boundary

* feat: add Primary story to NotificationContent Storybook

- Add Primary story as default example following coding guidelines
- Use 25 notifications for moderate, typical usage demonstration
- Include proper documentation with story description
- Position Primary story before other variants as main example

* fix: improve error handling for poke functionality

- Add toast notification for poke send failures
- Use consistent timeout reference management for error case
- Provide user feedback for failed poke attempts instead of silent failures
- Maintain consistent 2000ms timeout duration across all scenarios

* feat: extract GroupMemberList component and add 7-day poke button logic

- Extract member list functionality from page into reusable GroupMemberList component
- Add conditional poke button visibility based on 7-day inactivity threshold
- Create comprehensive Storybook stories for different member activity scenarios
- Update Storybook config to include app directory stories for better component testing

* refactor: replace custom spinners with shared Loading component in onboarding

- Replace two separate custom spinner divs with consistent Loading component
- Merge duplicate loading conditions into single conditional statement
- Improve code maintainability and UI consistency

* fix: prevent infinite loading when entering onboarding without login

- Split merged loading condition into separate hydration and login checks
- Ensure non-logged-in users see LoginScreen instead of infinite loading
- Improve loading state logic clarity and maintainability

---------

Co-authored-by: SangHyeon Lee <67571350+Hys-Lee@users.noreply.github.com>
@coderabbitai coderabbitai bot mentioned this pull request Aug 20, 2025
13 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants