-
Notifications
You must be signed in to change notification settings - Fork 0
[FEAT] 회원탈퇴 기능 추가 및 마이페이지 디자인 수정사항 반영 #293
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
WalkthroughA user account deletion feature was added to the frontend. This includes a new API call, a button with confirmation modal, mutation hooks, and integration into the MyPage screen. Various style and layout adjustments were made to support the new feature and improve edit mode UI consistency across MyPage components. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant MyPage
participant DeleteAccountButton
participant Modal
participant useDeleteAccountMutation
participant API
User->>MyPage: Navigates to MyPage
MyPage->>DeleteAccountButton: Renders button
User->>DeleteAccountButton: Clicks "회원 탈퇴"
DeleteAccountButton->>Modal: Opens confirmation modal
User->>Modal: Confirms deletion
Modal->>useDeleteAccountMutation: Triggers mutation
useDeleteAccountMutation->>API: Sends DELETE /api/v1/auth/account
API-->>useDeleteAccountMutation: Responds with result
useDeleteAccountMutation->>User: Clears token, redirects to /landing
Assessment against linked issues
Assessment against linked issues: Out-of-scope changesNo out-of-scope changes found. Suggested labels
Poem
✨ 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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed 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)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this 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 (4)
frontend/src/api/deleteAccount.ts (1)
5-9: Add return type annotation and consider error handling documentation.The function lacks a return type annotation, which reduces type safety. Consider adding proper typing and JSDoc documentation.
+/** + * Deletes the current user's account + * @returns Promise containing the deletion result + */ -export const deleteAccount = async () => { +export const deleteAccount = async (): Promise<unknown> => { const result = await fetchClient.delete(API_URL.deleteAccount); return result; };Additionally, consider documenting where error handling occurs (e.g., in the mutation hook) if it's intentionally omitted here.
frontend/src/components/Button/DeleteAccountButton/DeleteAccountButton.styled.ts (1)
3-8: Consider extracting shared button styling to reduce duplication.The styling is identical to
LogoutButtonin terms of font, color, text decoration, and margin. Consider creating a shared base component or utility to avoid code duplication.+// Consider creating a shared base styled component +const BaseActionButton = styled.button` + ${({ theme }) => theme.fonts.label14Med}; + color: ${({ theme }) => theme.colors.gray600}; + text-decoration: underline; + margin-top: 1.6rem; +`; -export const DeleteAccountButton = styled.button` - ${({ theme }) => theme.fonts.label14Med}; - color: ${({ theme }) => theme.colors.gray600}; - text-decoration: underline; - margin-top: 1.6rem; -`; +export const DeleteAccountButton = styled(BaseActionButton)` + /* Additional specific styling if needed */ +`;frontend/src/components/Button/DeleteAccountButton/index.tsx (1)
29-42: Consider adding loading state for better UX.The deletion modal would benefit from showing a loading state while the deletion is in progress to prevent users from clicking multiple times and provide feedback.
Consider adding a loading state:
+ const [isDeleting, setIsDeleting] = useState(false); + const handleConfirmDelete = async () => { + setIsDeleting(true); try { await deleteAccountMutation(); setIsModalOpen(false); } catch (error) { console.error('Account deletion failed:', error); + } finally { + setIsDeleting(false); } };And pass the loading state to the modal:
<HomeModal title="회원 탈퇴" content={[...]} close={handleCloseModal} onConfirm={handleConfirmDelete} confirmText="탈퇴하기" + isLoading={isDeleting} />frontend/src/pages/MyPage/components/MyPageEditableSection/MyPageEditableSection.styled.ts (1)
19-24: Consider reusing existing Divider component to avoid duplication.There's a similar
Dividercomponent infrontend/src/pages/MyPage/MyPage.styled.ts(lines 44-50) with slight differences. The existing one has full width and vertical margin, while this one usesflex: 1and no margin.Consider extracting a shared Divider component or reusing the existing one if the styling differences can be reconciled:
-export const Divider = styled.div` - flex: 1; - height: 0.15rem; - background-color: ${({ theme }) => theme.colors.gray200}; - border-radius: 0.6rem; -`;Import the existing Divider and adjust the container styling if needed.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (15)
frontend/src/api/deleteAccount.ts(1 hunks)frontend/src/components/Button/DeleteAccountButton/DeleteAccountButton.styled.ts(1 hunks)frontend/src/components/Button/DeleteAccountButton/hooks/deleteAccountMutation.ts(1 hunks)frontend/src/components/Button/DeleteAccountButton/index.tsx(1 hunks)frontend/src/components/Button/LogoutButton/hooks/useLogoutMutation.ts(2 hunks)frontend/src/components/Button/LogoutButton/index.tsx(1 hunks)frontend/src/constants/url.ts(1 hunks)frontend/src/pages/MyPage/MyPage.styled.ts(2 hunks)frontend/src/pages/MyPage/components/MyPageEditableSection/MyPageAddress/MyPageAddress.styled.ts(2 hunks)frontend/src/pages/MyPage/components/MyPageEditableSection/MyPageAddress/index.tsx(2 hunks)frontend/src/pages/MyPage/components/MyPageEditableSection/MyPageEditableSection.styled.ts(3 hunks)frontend/src/pages/MyPage/components/MyPageEditableSection/MyPageGoal/MyPageGoal.styled.ts(1 hunks)frontend/src/pages/MyPage/components/MyPageEditableSection/MyPageGoal/index.tsx(2 hunks)frontend/src/pages/MyPage/components/MyPageEditableSection/index.tsx(1 hunks)frontend/src/pages/MyPage/index.tsx(2 hunks)
🧰 Additional context used
🧠 Learnings (1)
frontend/src/pages/MyPage/MyPage.styled.ts (1)
Learnt from: rbgksqkr
PR: softeer5th/Team6-DuBu#37
File: frontend/src/components/Icon/icons/Alert.tsx:16-17
Timestamp: 2025-02-04T05:12:55.556Z
Learning: In React components, SVG attributes should use camelCase (e.g., strokeLinecap instead of stroke-linecap) to prevent console warning messages.
🧬 Code Graph Analysis (7)
frontend/src/components/Button/LogoutButton/index.tsx (1)
frontend/src/components/Button/LogoutButton/LogoutButton.styled.ts (1)
LogoutButton(3-9)
frontend/src/api/deleteAccount.ts (1)
frontend/src/constants/url.ts (1)
API_URL(5-77)
frontend/src/components/Button/DeleteAccountButton/hooks/deleteAccountMutation.ts (1)
frontend/src/api/deleteAccount.ts (1)
deleteAccount(5-9)
frontend/src/components/Button/DeleteAccountButton/index.tsx (1)
frontend/src/components/Button/DeleteAccountButton/DeleteAccountButton.styled.ts (1)
DeleteAccountButton(3-8)
frontend/src/pages/MyPage/components/MyPageEditableSection/MyPageGoal/index.tsx (1)
frontend/src/types/filter.ts (1)
CategoryType(2-2)
frontend/src/pages/MyPage/components/MyPageEditableSection/MyPageEditableSection.styled.ts (1)
frontend/src/pages/MyPage/MyPage.styled.ts (1)
Divider(44-50)
frontend/src/pages/MyPage/index.tsx (1)
frontend/src/components/Button/DeleteAccountButton/DeleteAccountButton.styled.ts (1)
DeleteAccountButton(3-8)
🔇 Additional comments (22)
frontend/src/constants/url.ts (1)
30-32: LGTM! Well-structured API endpoint addition.The new
deleteAccountendpoint follows the existing URL structure and is appropriately categorized under the authentication section.frontend/src/components/Button/LogoutButton/index.tsx (2)
1-1: Good naming consistency improvement.The hook rename from
useLogouttouseLogoutMutationimproves consistency with other mutation hooks in the codebase.
5-5: Hook usage updated correctly.The hook invocation properly reflects the renamed import while maintaining the same functionality.
frontend/src/components/Button/LogoutButton/hooks/useLogoutMutation.ts (2)
6-6: Consistent hook naming improves code organization.The rename from
useLogouttouseLogoutMutationfollows mutation hook naming conventions and improves consistency across the codebase.
20-20: Export updated correctly.The default export properly reflects the renamed hook function.
frontend/src/pages/MyPage/MyPage.styled.ts (2)
6-7: Layout improvements look good.The gap reduction and addition of vertical scrolling improve the page layout and user experience. The overflow-y: scroll ensures proper scrolling behavior when content exceeds the container height.
49-49: Proper divider spacing added.The margin addition provides consistent spacing around the divider element, which aligns with the updated layout structure.
frontend/src/components/Button/DeleteAccountButton/hooks/deleteAccountMutation.ts (1)
12-13: Token cleanup and navigation logic is appropriate.The localStorage token removal and navigation to the landing page correctly handles the post-deletion state, ensuring the user is logged out and redirected appropriately.
frontend/src/pages/MyPage/index.tsx (2)
10-10: Clean integration of the DeleteAccountButton component.The import and placement of the DeleteAccountButton component is well-positioned and follows the existing component structure.
43-44: Appropriate placement of destructive action.The divider and DeleteAccountButton placement at the bottom of the page with visual separation is a good UX pattern for destructive actions like account deletion.
frontend/src/pages/MyPage/components/MyPageEditableSection/MyPageAddress/index.tsx (3)
8-8: Theme import is necessary for dynamic color logic.The theme import enables the getLabelColor function to access color values for conditional styling based on edit mode.
51-53: Clean helper function for conditional styling.The getLabelColor function centralizes the color logic and provides consistent visual feedback for edit mode across the address section.
62-72: Proper integration of edit mode styling.The $editMode prop is correctly passed to styled components, and the conditional styling provides clear visual feedback when users can interact with address items.
frontend/src/pages/MyPage/components/MyPageEditableSection/MyPageAddress/MyPageAddress.styled.ts (3)
22-22: Consistent color update for message text.The color change from green700 to green600 aligns with the overall color scheme and provides consistent visual feedback.
31-36: Effective conditional border styling for edit mode.The $editMode prop enables dynamic border colors that clearly indicate when address items are interactive (green600) versus read-only (gray200).
41-46: Proper conditional text color for edit mode feedback.The conditional text color based on $editMode provides clear visual feedback to users about the interactive state of address labels.
frontend/src/pages/MyPage/components/MyPageEditableSection/MyPageGoal/index.tsx (2)
43-50: Excellent refactoring of icon color logic.The new
getIconColorhelper function centralizes the color determination logic, making it more maintainable and testable. The function clearly handles the three states (not selected, selected in edit mode, selected in view mode) with appropriate color values.
63-68: Good prop passing for consistent edit mode behavior.The
editModeprop is properly passed to bothS.GoalItemandS.GoalItemTextstyled components, ensuring consistent styling behavior across the goal selection interface.frontend/src/pages/MyPage/components/MyPageEditableSection/index.tsx (1)
43-66: Excellent UI restructuring for better user experience.The separation of edit controls (
EditButtonContainer) from editable content (EditContentContainer) creates a cleaner interface with better visual hierarchy. The conditional rendering logic is now more intuitive - edit button appears in view mode, and cancel/save buttons appear in edit mode.frontend/src/pages/MyPage/components/MyPageEditableSection/MyPageEditableSection.styled.ts (1)
35-40: Improved button styling with consistent theme usage.The font styling change to
theme.fonts.label13and the addition offlex-shrink: 0andpadding-right: 0create better visual consistency and prevent layout issues.frontend/src/pages/MyPage/components/MyPageEditableSection/MyPageGoal/MyPageGoal.styled.ts (2)
32-50: Excellent conditional styling implementation for edit mode.The
GoalItemstyled component now provides clear visual feedback for different states:
- Unselected: gray background with gray border
- Selected in edit mode: white background with green border
- Selected in view mode: white background with gray border
This creates intuitive visual cues for users to understand the current state and available actions.
52-60: Consistent text color scheme across all states.The
GoalItemTextcolor logic properly matches the visual hierarchy:
- Gray for unselected items
- Green for selected items in edit mode
- Gray for selected items in view mode
This ensures readability and visual consistency throughout the interface.
| const { mutate: deleteAccountMutation } = useMutation({ | ||
| mutationFn: deleteAccount, | ||
| onSuccess: () => { | ||
| localStorage.removeItem('accessToken'); | ||
| navigate('/landing'); | ||
| }, | ||
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Consider adding error handling to the mutation.
The current implementation handles the success case well, but there's no error handling for failed deletion attempts. Consider adding an onError callback to handle network failures or server errors gracefully.
const { mutate: deleteAccountMutation } = useMutation({
mutationFn: deleteAccount,
onSuccess: () => {
localStorage.removeItem('accessToken');
navigate('/landing');
},
+ onError: (error) => {
+ // Handle deletion failure - show user feedback
+ console.error('Account deletion failed:', error);
+ },
});📝 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.
| const { mutate: deleteAccountMutation } = useMutation({ | |
| mutationFn: deleteAccount, | |
| onSuccess: () => { | |
| localStorage.removeItem('accessToken'); | |
| navigate('/landing'); | |
| }, | |
| }); | |
| const { mutate: deleteAccountMutation } = useMutation({ | |
| mutationFn: deleteAccount, | |
| onSuccess: () => { | |
| localStorage.removeItem('accessToken'); | |
| navigate('/landing'); | |
| }, | |
| onError: (error) => { | |
| // Handle deletion failure - show user feedback | |
| console.error('Account deletion failed:', error); | |
| }, | |
| }); |
🤖 Prompt for AI Agents
In
frontend/src/components/Button/DeleteAccountButton/hooks/deleteAccountMutation.ts
around lines 9 to 15, the useMutation call lacks error handling for failed
deletion attempts. Add an onError callback to the mutation options to handle
network or server errors gracefully, such as showing an error message or logging
the failure, ensuring the user is informed if the deletion does not succeed.
| const handleConfirmDelete = () => { | ||
| deleteAccountMutation(); | ||
| setIsModalOpen(false); | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Handle deletion errors and avoid race conditions.
The current implementation has a potential race condition where the modal closes immediately after calling the mutation, regardless of whether the deletion succeeds or fails. This could lead to poor user experience if the deletion fails silently.
Consider waiting for the mutation to complete before closing the modal:
- const handleConfirmDelete = () => {
- deleteAccountMutation();
- setIsModalOpen(false);
- };
+ const handleConfirmDelete = async () => {
+ try {
+ await deleteAccountMutation();
+ setIsModalOpen(false);
+ } catch (error) {
+ // Handle error (show error message, keep modal open, etc.)
+ console.error('Account deletion failed:', error);
+ }
+ };📝 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.
| const handleConfirmDelete = () => { | |
| deleteAccountMutation(); | |
| setIsModalOpen(false); | |
| }; | |
| const handleConfirmDelete = async () => { | |
| try { | |
| await deleteAccountMutation(); | |
| setIsModalOpen(false); | |
| } catch (error) { | |
| // Handle error (show error message, keep modal open, etc.) | |
| console.error('Account deletion failed:', error); | |
| } | |
| }; |
🤖 Prompt for AI Agents
In frontend/src/components/Button/DeleteAccountButton/index.tsx around lines 16
to 19, the modal closes immediately after calling deleteAccountMutation without
waiting for the mutation to complete, which can cause race conditions and poor
UX if deletion fails. Modify handleConfirmDelete to await the completion of
deleteAccountMutation, then close the modal only if the mutation succeeds. Also,
handle any errors from the mutation to provide feedback or keep the modal open
if deletion fails.
Issue Number
close #292
As-Is
To-Be
Check List
Test Screenshot
(Optional) Additional Description
Summary by CodeRabbit