-
Notifications
You must be signed in to change notification settings - Fork 0
[feat/#16] Onboarding UI #17
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
WalkthroughIntroduces comprehensive onboarding flow with nine-step UI screens, state management via OnboardingViewModel, and navigation integration into the main app. Adds supporting UI components including HsLinkActionButton and OnboardingProgressBar, updates HsLinkTextField with keyboard configuration options, and provides drawable resources. New navigation structure enables home navigation from onboarding completion. Changes
Sequence DiagramsequenceDiagram
participant User
participant OnboardingRoute
participant OnboardingViewModel
participant Screen as Step Screen
participant NavController
User->>NavController: Navigate to Onboarding
NavController->>OnboardingRoute: Render route
OnboardingRoute->>OnboardingViewModel: Collect state
OnboardingViewModel-->>OnboardingRoute: Emit OnboardingState
rect rgba(100, 150, 255, 0.2)
Note over User,Screen: Step Loop (1-9)
User->>Screen: Interact with current step
Screen->>OnboardingViewModel: updateField(value)
OnboardingViewModel->>OnboardingViewModel: Mutate state
OnboardingViewModel-->>Screen: Emit updated state
Screen-->>User: Re-render with new data
end
User->>Screen: Click Next/Previous
Screen->>OnboardingViewModel: moveToNextStep() / moveToPreviousStep()
OnboardingViewModel->>OnboardingViewModel: Advance currentStep
OnboardingViewModel-->>OnboardingRoute: Emit new step
OnboardingRoute->>Screen: Render next screen
User->>Screen: Complete final step
Screen->>OnboardingViewModel: submitOnboarding()
OnboardingViewModel->>NavController: navigateHome()
NavController-->>User: Navigate to Home
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (4 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
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.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 9
🧹 Nitpick comments (7)
app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/JobSeekingScreen.kt (1)
47-63: Remove redundantisEnabled = trueparameter.Both
HsLinkSelectButtoninstances explicitly passisEnabled = true, which is the default value. This can be omitted for cleaner code.Apply this diff:
HsLinkSelectButton( label = "구직 중이에요", onClick = { onJobSeekingSelect(true) }, size = HsLinkButtonSize.Large, modifier = Modifier.fillMaxWidth(), - isEnabled = true, isSelected = isJobSeeking == true ) HsLinkSelectButton( label = "구직하지 않아요", onClick = { onJobSeekingSelect(false) }, size = HsLinkButtonSize.Large, modifier = Modifier.fillMaxWidth(), - isEnabled = true, isSelected = isJobSeeking == false )app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/OnboardingProgressBar.kt (1)
15-33: Consider clamping the progress value.The
progressparameter is not validated. While Compose'sfillMaxWidthhandles out-of-range values gracefully, explicit validation would make the contract clearer and catch bugs in calling code earlier.Apply this diff:
@Composable fun OnboardingProgressBar( progress: Float, modifier: Modifier = Modifier ) { + val clampedProgress = progress.coerceIn(0f, 1f) + Box( modifier = modifier .fillMaxWidth() .height(4.dp) .clip(RoundedCornerShape(2.dp)) .background(HsLinkTheme.colors.Grey200) ) { Box( modifier = Modifier - .fillMaxWidth(progress) + .fillMaxWidth(clampedProgress) .height(4.dp) .clip(RoundedCornerShape(2.dp)) .background(HsLinkTheme.colors.SkyBlue500) ) } }app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/MentorshipScreen.kt (1)
47-63: Remove redundantisEnabled = trueparameter.Both
HsLinkSelectButtoninstances explicitly passisEnabled = true, which is the default value and can be omitted.Apply this diff:
HsLinkSelectButton( label = "멘토로도 참여할래요", onClick = { onMentorshipSelect(true) }, size = HsLinkButtonSize.Large, modifier = Modifier.fillMaxWidth(), - isEnabled = true, isSelected = wantsMentorship == true ) HsLinkSelectButton( label = "멘티로만 참여할래요", onClick = { onMentorshipSelect(false) }, size = HsLinkButtonSize.Large, modifier = Modifier.fillMaxWidth(), - isEnabled = true, isSelected = wantsMentorship == false )app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/EmploymentStatusScreen.kt (1)
26-26: Remove unnecessary @OptIn annotation.The
@OptIn(ExperimentalLayoutApi::class)annotation is present butFlowRowis not used in this file—only the stableRowAPI is used. This annotation can be removed.Apply this diff:
-@OptIn(ExperimentalLayoutApi::class) @Composable fun EmploymentStatusScreen(app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/AddLinkDialog.kt (1)
58-58: Improve Korean text clarity.The description text is grammatically awkward. Consider revising to "나눔 활동에 참여할 때 기본 정보로 활용됩니다." for better clarity.
Apply this diff:
- text = "나눔에 관련을 할 때 기본 정보로 활용됩니다.", + text = "나눔 활동에 참여할 때 기본 정보로 활용됩니다.",app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/MajorScreen.kt (1)
110-128: Consider using an icon for the clear button.The clear button currently uses the text character "✕" (Line 122). For better semantics and consistency with the design system, consider using a proper icon resource like
R.drawable.ic_closeor similar.app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/JobInfoScreen.kt (1)
185-221: Remove redundant isEnabled parameters.All JobType selection buttons have
isEnabled = trueexplicitly set, which is redundant sincetrueis the default value for theisEnabledparameter inHsLinkSelectButton.Apply this diff to remove the redundant parameters:
HsLinkSelectButton( modifier = Modifier.weight(1f), label = JobType.FULL_TIME.label, onClick = { onJobTypeSelect(JobType.FULL_TIME) }, size = HsLinkButtonSize.Large, - isEnabled = true, isSelected = selectedJobType == JobType.FULL_TIME ) HsLinkSelectButton( modifier = Modifier.weight(1f), label = JobType.CONTRACT.label, onClick = { onJobTypeSelect(JobType.CONTRACT) }, size = HsLinkButtonSize.Large, - isEnabled = true, isSelected = selectedJobType == JobType.CONTRACT )(Apply the same change to INTERN and FREELANCER buttons)
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (22)
app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkActionButton.kt(1 hunks)app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkTextField.kt(3 hunks)app/src/main/java/com/hsLink/hslink/presentation/main/MainNavHost.kt(2 hunks)app/src/main/java/com/hsLink/hslink/presentation/main/MainNavigator.kt(2 hunks)app/src/main/java/com/hsLink/hslink/presentation/onboarding/OnboardingScreen.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/AddLinkDialog.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/OnboardingProgressBar.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/CareerScreen.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/EmploymentStatusScreen.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/JobInfoScreen.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/JobSeekingScreen.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/LinkScreen.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/MajorScreen.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/MentorshipScreen.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/NameScreen.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/StudentIdScreen.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/onboarding/model/MajorData.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/onboarding/model/OnboardingState.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/onboarding/navigation/OnboardingNavigation.kt(1 hunks)app/src/main/java/com/hsLink/hslink/presentation/onboarding/viewmodel/OnboardingViewModel.kt(1 hunks)app/src/main/res/drawable/ic_onboarding_plus.xml(1 hunks)app/src/main/res/drawable/ic_onboarding_search.xml(1 hunks)
🧰 Additional context used
🧬 Code graph analysis (16)
app/src/main/java/com/hsLink/hslink/presentation/onboarding/model/MajorData.kt (1)
app/src/main/java/com/hsLink/hslink/presentation/community/screen/main/CommunityScreen.kt (1)
id(45-50)
app/src/main/res/drawable/ic_onboarding_search.xml (1)
app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkTopBar.kt (1)
Icon(60-66)
app/src/main/java/com/hsLink/hslink/presentation/onboarding/OnboardingScreen.kt (11)
app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/StudentIdScreen.kt (1)
StudentIdScreen(27-80)app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/NameScreen.kt (1)
NameScreen(24-77)app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/MajorScreen.kt (1)
MajorScreen(39-142)app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/EmploymentStatusScreen.kt (1)
EmploymentStatusScreen(26-76)app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/CareerScreen.kt (1)
CareerScreen(30-87)app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/JobInfoScreen.kt (1)
JobInfoScreen(29-228)app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/JobSeekingScreen.kt (1)
JobSeekingScreen(19-66)app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/MentorshipScreen.kt (1)
MentorshipScreen(19-66)app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/LinkScreen.kt (1)
LinksScreen(41-136)app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/OnboardingProgressBar.kt (1)
OnboardingProgressBar(14-34)app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkActionButton.kt (1)
HsLinkActionButton(37-93)
app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/AddLinkDialog.kt (3)
app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkTextField.kt (1)
HsLinkTextField(35-107)app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkSelectButton.kt (1)
HsLinkSelectButton(38-94)app/src/main/java/com/hsLink/hslink/core/designsystem/theme/Theme.kt (1)
HsLinkTheme(37-57)
app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/MajorScreen.kt (1)
app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkTextField.kt (1)
HsLinkTextField(35-107)
app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/EmploymentStatusScreen.kt (2)
app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkSelectButton.kt (1)
HsLinkSelectButton(38-94)app/src/main/java/com/hsLink/hslink/core/designsystem/theme/Theme.kt (1)
HsLinkTheme(37-57)
app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/JobSeekingScreen.kt (2)
app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkSelectButton.kt (1)
HsLinkSelectButton(38-94)app/src/main/java/com/hsLink/hslink/core/designsystem/theme/Theme.kt (1)
HsLinkTheme(37-57)
app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkActionButton.kt (1)
app/src/main/java/com/hsLink/hslink/core/designsystem/theme/Theme.kt (1)
HsLinkTheme(37-57)
app/src/main/java/com/hsLink/hslink/presentation/onboarding/navigation/OnboardingNavigation.kt (2)
app/src/main/java/com/hsLink/hslink/presentation/main/MainNavigator.kt (1)
navigate(37-55)app/src/main/java/com/hsLink/hslink/presentation/onboarding/OnboardingScreen.kt (1)
OnboardingRoute(37-162)
app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/StudentIdScreen.kt (2)
app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkTextField.kt (1)
HsLinkTextField(35-107)app/src/main/java/com/hsLink/hslink/core/designsystem/theme/Theme.kt (1)
HsLinkTheme(37-57)
app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/JobInfoScreen.kt (3)
app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkTextField.kt (1)
HsLinkTextField(35-107)app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkSelectButton.kt (1)
HsLinkSelectButton(38-94)app/src/main/java/com/hsLink/hslink/core/designsystem/theme/Theme.kt (1)
HsLinkTheme(37-57)
app/src/main/java/com/hsLink/hslink/presentation/main/MainNavHost.kt (1)
app/src/main/java/com/hsLink/hslink/presentation/onboarding/navigation/OnboardingNavigation.kt (1)
onboardingNavGraph(18-30)
app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/LinkScreen.kt (2)
app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkSelectButton.kt (1)
HsLinkSelectButton(38-94)app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/AddLinkDialog.kt (1)
AddLinkDialog(32-153)
app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/CareerScreen.kt (1)
app/src/main/java/com/hsLink/hslink/core/designsystem/theme/Theme.kt (1)
HsLinkTheme(37-57)
app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/MentorshipScreen.kt (2)
app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkSelectButton.kt (1)
HsLinkSelectButton(38-94)app/src/main/java/com/hsLink/hslink/core/designsystem/theme/Theme.kt (1)
HsLinkTheme(37-57)
app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/NameScreen.kt (1)
app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkTextField.kt (1)
HsLinkTextField(35-107)
🪛 detekt (1.23.8)
app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/LinkScreen.kt
[warning] 193-193: The caught exception is swallowed. The original exception could be lost.
(detekt.exceptions.SwallowedException)
🔇 Additional comments (11)
app/src/main/res/drawable/ic_onboarding_search.xml (1)
1-9: Vector drawable looks good.Proper XML structure, correct dimensions (24×24dp with matching viewport), valid path syntax, and appropriate color choice for a search icon.
app/src/main/res/drawable/ic_onboarding_plus.xml (1)
1-9: Vector drawable looks good.Proper XML structure, correct dimensions (14×14dp with matching viewport), valid path syntax, and appropriate color choice for an add/action icon.
app/src/main/java/com/hsLink/hslink/presentation/onboarding/model/MajorData.kt (1)
3-21: LGTM!The static major list is cleanly implemented. Consider externalizing this data to a configuration file or database if the list needs frequent updates or localization support in the future.
app/src/main/java/com/hsLink/hslink/presentation/main/MainNavigator.kt (2)
25-25: LGTM! Start destination updated for onboarding flow.The change from
HometoOnboardingaligns with the PR objective. As noted in the PR description, developers can modify thestartDestinationlocally during development if needed.
73-75: LGTM! Navigation method added for onboarding completion.The
navigateToHomemethod correctly delegates to the navigation controller and follows the same pattern as other navigation methods in the class.app/src/main/java/com/hsLink/hslink/presentation/main/MainNavHost.kt (1)
47-51: LGTM! Onboarding navigation graph integrated correctly.The onboarding navigation graph is properly wired with appropriate callbacks, following the same pattern as other navigation graphs in the host.
app/src/main/java/com/hsLink/hslink/core/designsystem/component/HsLinkTextField.kt (2)
44-44: LGTM! Keyboard options parameter enhances flexibility.The addition of
keyboardOptionsparameter with a sensible default and proper merging withimeActionenables callers to configure keyboard behavior while maintaining backward compatibility.Also applies to: 70-70
93-93: Verify this intentional style change aligns with design specs and maintains readability.The change from
body_16Normaltocaption_14Normalfor placeholder text is confirmed to be deliberate (commit feat/#16), affecting all 11HsLinkTextFieldusages across onboarding, community writing, and dialog screens. Confirm:
- Change is approved by design and intentional
- Placeholder text remains readable at the smaller caption size (especially on mobile)
- Visual hierarchy is maintained across all affected screens (StudentIdScreen, NameScreen, MajorScreen, JobInfoScreen, CommunityWritingScreen, etc.)
app/src/main/java/com/hsLink/hslink/presentation/onboarding/navigation/OnboardingNavigation.kt (1)
12-33: LGTM!The navigation setup follows Compose Navigation best practices with type-safe routing using Kotlin serialization. The integration with OnboardingRoute is clean and the callbacks are properly wired.
app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/StudentIdScreen.kt (1)
28-80: LGTM!The implementation correctly handles student ID input with appropriate keyboard configuration (numeric type), proper validation, and clean focus state management. The onDone action properly validates the input before triggering navigation.
app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/NameScreen.kt (1)
25-77: LGTM!The implementation follows the established onboarding screen pattern with proper validation, focus management, and clear user guidance about using real names. The IME action correctly validates before proceeding.
| @@ -0,0 +1,164 @@ | |||
| package com.hsLink.hslink.presentation.onboarding.screen | |||
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.
Fix package name mismatch.
The package declaration is com.hsLink.hslink.presentation.onboarding.screen but the file is located in the component folder. This will cause compilation errors.
Apply this diff:
-package com.hsLink.hslink.presentation.onboarding.screen
+package com.hsLink.hslink.presentation.onboarding.component📝 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.
| package com.hsLink.hslink.presentation.onboarding.screen | |
| package com.hsLink.hslink.presentation.onboarding.component |
🤖 Prompt for AI Agents
In
app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/AddLinkDialog.kt
around line 1, the package declaration is incorrect for the file's folder;
change the package declaration to "package
com.hsLink.hslink.presentation.onboarding.component" (or alternatively move the
file into the "screen" folder to match the current package), then save and
recompile to ensure the package path and filesystem location match.
| CareerSelectButton( | ||
| modifier = Modifier.padding(top = 16.dp), | ||
| onClick = {}, | ||
| label = "커리어 추가하기", | ||
| isEnabled = true | ||
| ) |
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.
Wire up the “커리어 추가하기” CTA
The primary button renders but does nothing because onClick is empty. Users will think the screen is broken. Please route it to onNextClick (or another handler that opens the career form).
- CareerSelectButton(
- modifier = Modifier.padding(top = 16.dp),
- onClick = {},
+ CareerSelectButton(
+ modifier = Modifier.padding(top = 16.dp),
+ onClick = onNextClick,
label = "커리어 추가하기",
isEnabled = true
)📝 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.
| CareerSelectButton( | |
| modifier = Modifier.padding(top = 16.dp), | |
| onClick = {}, | |
| label = "커리어 추가하기", | |
| isEnabled = true | |
| ) | |
| CareerSelectButton( | |
| modifier = Modifier.padding(top = 16.dp), | |
| onClick = onNextClick, | |
| label = "커리어 추가하기", | |
| isEnabled = true | |
| ) |
🤖 Prompt for AI Agents
In
app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/CareerScreen.kt
around lines 78 to 83, the CareerSelectButton's onClick is currently empty so
the "커리어 추가하기" CTA does nothing; replace the empty lambda with the appropriate
handler (e.g. onNextClick or the method that opens the career form) so clicking
the button triggers navigation/opening of the career form and keep the existing
modifier, label, and isEnabled settings.
| } | ||
| }, | ||
| progress = progress, | ||
| subtitle = "자세한 알아주시면 더 맞은 도움을 드릴 수 있어요", |
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.
Fix grammatical error in Korean text.
The subtitle text has grammatical issues. The correct form should be "자세히 알려주시면 더 나은 도움을 드릴 수 있어요" (using "알려주시면" instead of "알아주시면" and "나은" instead of "맞은").
Apply this diff:
- subtitle = "자세한 알아주시면 더 맞은 도움을 드릴 수 있어요",
+ subtitle = "자세히 알려주시면 더 나은 도움을 드릴 수 있어요",📝 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.
| subtitle = "자세한 알아주시면 더 맞은 도움을 드릴 수 있어요", | |
| subtitle = "자세히 알려주시면 더 나은 도움을 드릴 수 있어요", |
🤖 Prompt for AI Agents
In
app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/EmploymentStatusScreen.kt
around line 44, the subtitle string is grammatically incorrect; replace "자세한
알아주시면 더 맞은 도움을 드릴 수 있어요" with the corrected text "자세히 알려주시면 더 나은 도움을 드릴 수 있어요"
(update the string literal only, preserving surrounding code and punctuation).
| Column(verticalArrangement = Arrangement.spacedBy(8.dp)) { | ||
| Text( | ||
| text = buildAnnotatedString { | ||
| append("현재 재직 여부 (형식 : 24.04) ") |
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.
Clarify the field label.
The label "현재 재직 여부 (형식 : 24.04)" translates to "Current employment status (format: 24.04)" but the fields below ask for start and end dates. Consider changing to "재직 기간 (형식 : 24.04)" (Employment period) for better clarity.
Apply this diff:
- append("현재 재직 여부 (형식 : 24.04) ")
+ append("재직 기간 (형식 : 24.04) ")📝 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.
| append("현재 재직 여부 (형식 : 24.04) ") | |
| append("재직 기간 (형식 : 24.04) ") |
🤖 Prompt for AI Agents
In
app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/JobInfoScreen.kt
around line 81, the label currently reads "현재 재직 여부 (형식 : 24.04)" which is
misleading because the inputs collect start and end dates; change the label to
"재직 기간 (형식 : 24.04)" to accurately indicate employment period, replacing the
existing string literal where append(...) is called so the UI displays the
clearer wording.
| private fun String.extractDomain(): String { | ||
| return try { | ||
| val withoutProtocol = this.removePrefix("https://") | ||
| .removePrefix("http://") | ||
| .removePrefix("www.") | ||
|
|
||
| val domain = withoutProtocol.split("/")[0] | ||
|
|
||
| when { | ||
| domain.contains("instagram.com") -> "인스타그램" | ||
| domain.contains("github.com") -> "깃허브" | ||
| domain.contains("linkedin.com") -> "링크드인" | ||
| domain.contains("notion.so") || domain.contains("notion.site") -> "노션" | ||
| else -> domain.take(30) | ||
| } | ||
| } catch (e: Exception) { | ||
| this.take(30) | ||
| } | ||
| } |
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.
Add logging for swallowed exception.
The exception in the extractDomain function is silently swallowed, which can hide parsing errors and make debugging difficult. Consider adding logging to track when domain extraction fails.
Apply this diff:
+import android.util.Log
+
private fun String.extractDomain(): String {
return try {
val withoutProtocol = this.removePrefix("https://")
.removePrefix("http://")
.removePrefix("www.")
val domain = withoutProtocol.split("/")[0]
when {
domain.contains("instagram.com") -> "인스타그램"
domain.contains("github.com") -> "깃허브"
domain.contains("linkedin.com") -> "링크드인"
domain.contains("notion.so") || domain.contains("notion.site") -> "노션"
else -> domain.take(30)
}
} catch (e: Exception) {
+ Log.w("LinkScreen", "Failed to extract domain from URL: $this", e)
this.take(30)
}
}📝 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.
| private fun String.extractDomain(): String { | |
| return try { | |
| val withoutProtocol = this.removePrefix("https://") | |
| .removePrefix("http://") | |
| .removePrefix("www.") | |
| val domain = withoutProtocol.split("/")[0] | |
| when { | |
| domain.contains("instagram.com") -> "인스타그램" | |
| domain.contains("github.com") -> "깃허브" | |
| domain.contains("linkedin.com") -> "링크드인" | |
| domain.contains("notion.so") || domain.contains("notion.site") -> "노션" | |
| else -> domain.take(30) | |
| } | |
| } catch (e: Exception) { | |
| this.take(30) | |
| } | |
| } | |
| import android.util.Log | |
| private fun String.extractDomain(): String { | |
| return try { | |
| val withoutProtocol = this.removePrefix("https://") | |
| .removePrefix("http://") | |
| .removePrefix("www.") | |
| val domain = withoutProtocol.split("/")[0] | |
| when { | |
| domain.contains("instagram.com") -> "인스타그램" | |
| domain.contains("github.com") -> "깃허브" | |
| domain.contains("linkedin.com") -> "링크드인" | |
| domain.contains("notion.so") || domain.contains("notion.site") -> "노션" | |
| else -> domain.take(30) | |
| } | |
| } catch (e: Exception) { | |
| Log.w("LinkScreen", "Failed to extract domain from URL: $this", e) | |
| this.take(30) | |
| } | |
| } |
🧰 Tools
🪛 detekt (1.23.8)
[warning] 193-193: The caught exception is swallowed. The original exception could be lost.
(detekt.exceptions.SwallowedException)
🤖 Prompt for AI Agents
In
app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/LinkScreen.kt
around lines 178 to 196, the extractDomain() function swallows exceptions
silently; update the catch block to log the caught exception (including message
and stack trace) using the project's logging approach (e.g., Timber.e or Android
Log.e or your app logger) before returning this.take(30), ensuring no behavior
change other than adding the log so parsing failures are visible for debugging.
| HsLinkTheme { | ||
| LinksScreen( | ||
| links = listOf( | ||
| ExternalLink(LinkType.GITHUB, "https://instagram.com/username"), |
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.
Fix preview data inconsistency.
The preview data uses LinkType.GITHUB but pairs it with an Instagram URL. This is confusing and should be corrected for clarity.
Apply this diff:
links = listOf(
- ExternalLink(LinkType.GITHUB, "https://instagram.com/username"),
+ ExternalLink(LinkType.INSTAGRAM, "https://instagram.com/username"),
ExternalLink(LinkType.PORTFOLIO, "https://drive.google.com/...")
),📝 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.
| ExternalLink(LinkType.GITHUB, "https://instagram.com/username"), | |
| ExternalLink(LinkType.INSTAGRAM, "https://instagram.com/username"), |
🤖 Prompt for AI Agents
In
app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/LinkScreen.kt
around line 204, the preview entry uses LinkType.GITHUB with an Instagram URL
which is inconsistent; update the LinkType to LinkType.INSTAGRAM (or
alternatively change the URL to a GitHub URL) so the LinkType matches the
provided URL in the preview data.
| append("*") | ||
| } | ||
| }, | ||
| subtitle = "모든 사용자는 멘티로 사작하며, 원할경우 멘토로드 활동에서 초대되니 구독 제공을 받을 수 있어요.", |
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.
Fix typos in user-facing subtitle text.
The subtitle contains several typos that affect readability and meaning:
- "사작하며" → "시작하며" (start)
- "원할경우" → "원할 경우" (spacing)
- "멘토로드" → "멘토로도" (also as mentor)
- "활동에서 초대되니 구독 제공을" → awkward phrasing
Apply this diff:
-subtitle = "모든 사용자는 멘티로 사작하며, 원할경우 멘토로드 활동에서 초대되니 구독 제공을 받을 수 있어요.",
+subtitle = "모든 사용자는 멘티로 시작하며, 원할 경우 멘토로도 활동하여 조언을 제공할 수 있어요.",🤖 Prompt for AI Agents
In
app/src/main/java/com/hsLink/hslink/presentation/onboarding/component/screen/MentorshipScreen.kt
around line 35, the subtitle string contains multiple typos and awkward
phrasing; replace it with a corrected, natural Korean sentence such as: "모든 사용자는
멘티로 시작하며, 원할 경우 멘토로도 활동에 초대되어 구독 혜택을 받을 수 있어요." to fix spelling, spacing,
grammar, and clarity.
| enum class EmploymentStatus(val label: String) { | ||
| WORKING("재학 중"), | ||
| GRADUATED("졸업"), | ||
| EXPECTED_GRADUATION("졸업예정"), | ||
| COMPLETED("수료"), | ||
| LEAVE("휴학") | ||
| } |
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.
Fix semantic mismatch in EmploymentStatus.WORKING.
The enum constant WORKING has the label "재학 중" (currently enrolled/attending school), which doesn't match its name. This semantic mismatch could lead to confusion and incorrect data handling throughout the onboarding flow.
Consider renaming the enum constant to ENROLLED or changing the label to match "WORKING".
Apply this diff to rename to ENROLLED:
enum class EmploymentStatus(val label: String) {
- WORKING("재학 중"),
+ ENROLLED("재학 중"),
GRADUATED("졸업"),
EXPECTED_GRADUATION("졸업예정"),
COMPLETED("수료"),
LEAVE("휴학")
}📝 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.
| enum class EmploymentStatus(val label: String) { | |
| WORKING("재학 중"), | |
| GRADUATED("졸업"), | |
| EXPECTED_GRADUATION("졸업예정"), | |
| COMPLETED("수료"), | |
| LEAVE("휴학") | |
| } | |
| enum class EmploymentStatus(val label: String) { | |
| ENROLLED("재학 중"), | |
| GRADUATED("졸업"), | |
| EXPECTED_GRADUATION("졸업예정"), | |
| COMPLETED("수료"), | |
| LEAVE("휴학") | |
| } |
🤖 Prompt for AI Agents
In
app/src/main/java/com/hsLink/hslink/presentation/onboarding/model/OnboardingState.kt
around lines 39 to 45, the enum constant WORKING has a label "재학 중" which
semantically mismatches; rename the constant to ENROLLED (preserving the label
"재학 중") and update all references/usages across the codebase (tests,
serializers, mappings, switch/case or when blocks, database fields if
applicable) to use EmploymentStatus.ENROLLED to avoid breakage; run a global
search-and-replace for EmploymentStatus.WORKING -> EmploymentStatus.ENROLLED and
adjust any string comparisons or persisted values accordingly.
| fun moveToNextStep() { | ||
| _state.update { | ||
| val nextStep = when (it.currentStep) { | ||
| OnboardingStep.STUDENT_ID -> OnboardingStep.NAME | ||
| OnboardingStep.NAME -> OnboardingStep.MAJOR | ||
| OnboardingStep.MAJOR -> OnboardingStep.EMPLOYMENT_STATUS | ||
| OnboardingStep.EMPLOYMENT_STATUS -> OnboardingStep.CAREER | ||
| OnboardingStep.CAREER -> OnboardingStep.JOB_INFO | ||
| OnboardingStep.JOB_INFO -> OnboardingStep.MENTORSHIP | ||
| OnboardingStep.MENTORSHIP -> OnboardingStep.LINKS | ||
| OnboardingStep.LINKS -> OnboardingStep.JOB_SEEKING | ||
| OnboardingStep.JOB_SEEKING -> OnboardingStep.MENTORSHIP | ||
| } | ||
| it.copy(currentStep = nextStep) | ||
| } | ||
| } | ||
|
|
||
| fun moveToPreviousStep() { | ||
| _state.update { | ||
| val previousStep = when (it.currentStep) { | ||
| OnboardingStep.STUDENT_ID -> OnboardingStep.STUDENT_ID | ||
| OnboardingStep.NAME -> OnboardingStep.STUDENT_ID | ||
| OnboardingStep.MAJOR -> OnboardingStep.NAME | ||
| OnboardingStep.EMPLOYMENT_STATUS -> OnboardingStep.MAJOR | ||
| OnboardingStep.CAREER -> OnboardingStep.EMPLOYMENT_STATUS | ||
| OnboardingStep.JOB_INFO -> OnboardingStep.CAREER | ||
| OnboardingStep.MENTORSHIP -> OnboardingStep.JOB_INFO | ||
| OnboardingStep.LINKS -> OnboardingStep.MENTORSHIP | ||
| OnboardingStep.JOB_SEEKING -> OnboardingStep.LINKS | ||
| } | ||
| it.copy(currentStep = previousStep) | ||
| } |
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.
Fix step progression to include JobSeeking and avoid loops
moveToNextStep jumps from JOB_INFO straight to MENTORSHIP and later loops from LINKS → JOB_SEEKING → MENTORSHIP, so the JobSeeking screen is never reached in order and the flow oscillates. Mirror the UI order (…JOB_INFO → JOB_SEEKING → MENTORSHIP → LINKS) and align the reverse mapping.
val nextStep = when (it.currentStep) {
OnboardingStep.STUDENT_ID -> OnboardingStep.NAME
OnboardingStep.NAME -> OnboardingStep.MAJOR
OnboardingStep.MAJOR -> OnboardingStep.EMPLOYMENT_STATUS
OnboardingStep.EMPLOYMENT_STATUS -> OnboardingStep.CAREER
OnboardingStep.CAREER -> OnboardingStep.JOB_INFO
- OnboardingStep.JOB_INFO -> OnboardingStep.MENTORSHIP
- OnboardingStep.MENTORSHIP -> OnboardingStep.LINKS
- OnboardingStep.LINKS -> OnboardingStep.JOB_SEEKING
- OnboardingStep.JOB_SEEKING -> OnboardingStep.MENTORSHIP
+ OnboardingStep.JOB_INFO -> OnboardingStep.JOB_SEEKING
+ OnboardingStep.JOB_SEEKING -> OnboardingStep.MENTORSHIP
+ OnboardingStep.MENTORSHIP -> OnboardingStep.LINKS
+ OnboardingStep.LINKS -> OnboardingStep.LINKS
} val previousStep = when (it.currentStep) {
OnboardingStep.STUDENT_ID -> OnboardingStep.STUDENT_ID
OnboardingStep.NAME -> OnboardingStep.STUDENT_ID
OnboardingStep.MAJOR -> OnboardingStep.NAME
OnboardingStep.EMPLOYMENT_STATUS -> OnboardingStep.MAJOR
OnboardingStep.CAREER -> OnboardingStep.EMPLOYMENT_STATUS
- OnboardingStep.JOB_INFO -> OnboardingStep.CAREER
- OnboardingStep.MENTORSHIP -> OnboardingStep.JOB_INFO
- OnboardingStep.LINKS -> OnboardingStep.MENTORSHIP
- OnboardingStep.JOB_SEEKING -> OnboardingStep.LINKS
+ OnboardingStep.JOB_INFO -> OnboardingStep.CAREER
+ OnboardingStep.JOB_SEEKING -> OnboardingStep.JOB_INFO
+ OnboardingStep.MENTORSHIP -> OnboardingStep.JOB_SEEKING
+ OnboardingStep.LINKS -> OnboardingStep.MENTORSHIP
}🤖 Prompt for AI Agents
In
app/src/main/java/com/hsLink/hslink/presentation/onboarding/viewmodel/OnboardingViewModel.kt
around lines 90–121, the next/previous step mappings are incorrect causing
JOB_SEEKING to be skipped and a loop LINKS→JOB_SEEKING→MENTORSHIP; update
moveToNextStep to follow the UI order JOB_INFO → JOB_SEEKING → MENTORSHIP →
LINKS (so JOB_INFO maps to JOB_SEEKING, JOB_SEEKING maps to MENTORSHIP,
MENTORSHIP maps to LINKS, and LINKS should remain LINKS or advance to a terminal
state as appropriate), and update moveToPreviousStep to mirror that order in
reverse (so JOB_SEEKING maps back to JOB_INFO, MENTORSHIP back to JOB_SEEKING,
LINKS back to MENTORSHIP), keeping STUDENT_ID as the lower bound; make these
when-branch changes to ensure linear, non-looping progression.
ISSUE
❗ WORK DESCRIPTION
📸 SCREENSHOT
-.Clipchamp.6.mp4