Skip to content

๐Ÿ”€ :: (#960) ์ƒˆ๋ฒฝ ์ž์Šต ์‹ ์ฒญ ๊ธฐ๋Šฅ ๊ตฌํ˜„#926

Open
ashxom wants to merge 148 commits intodevelopfrom
feature/890-์ƒˆ๋ฒฝ-์ž์Šต-์‹ ์ฒญ-๊ธฐ๋Šฅ-๊ตฌํ˜„

Hidden character warning

The head ref may contain hidden characters: "feature/890-\uc0c8\ubcbd-\uc790\uc2b5-\uc2e0\uccad-\uae30\ub2a5-\uad6c\ud604"
Open

๐Ÿ”€ :: (#960) ์ƒˆ๋ฒฝ ์ž์Šต ์‹ ์ฒญ ๊ธฐ๋Šฅ ๊ตฌํ˜„#926
ashxom wants to merge 148 commits intodevelopfrom
feature/890-์ƒˆ๋ฒฝ-์ž์Šต-์‹ ์ฒญ-๊ธฐ๋Šฅ-๊ตฌํ˜„

Conversation

@ashxom
Copy link
Copy Markdown
Member

@ashxom ashxom commented Apr 30, 2026

๊ฐœ์š”

์ƒˆ๋ฒฝ ์ž์Šต ์‹ ์ฒญ ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ–ˆ์Šต๋‹ˆ๋‹ค.

image

์ž‘์—…์‚ฌํ•ญ

์ถ”๊ฐ€ ๋กœ ํ•  ๋ง

Summary by CodeRabbit

  • New Features

    • Late Study application: new screen to choose study type, teacher, date range, and reason; client-side validation, inline teacher suggestions, and highlighted matches.
    • In-app calendar for selecting start/end dates and submission flow; submission result is recorded and reflected in Applications.
  • Style

    • Application cards show status-aware chips for late-study applications.
  • Bug Fixes

    • Minor end-of-file newline/formatting fix.

ashxom added 30 commits April 10, 2026 09:08
@ashxom ashxom self-assigned this Apr 30, 2026
@ashxom ashxom added the feat ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ ํ•  ๊ฒฝ์šฐ label Apr 30, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 30, 2026

No actionable comments were generated in the recent review. ๐ŸŽ‰

โ„น๏ธ Recent review info
โš™๏ธ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: e6121296-69bb-4638-9daa-b164225a7731

๐Ÿ“ฅ Commits

Reviewing files that changed from the base of the PR and between ed51c5b and e84380a.

๐Ÿ“’ Files selected for processing (1)
  • core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/card/DmsApplicationCard.kt
โœ… Files skipped from review due to trivial changes (1)
  • core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/card/DmsApplicationCard.kt

๐Ÿ“ Walkthrough

Walkthrough

Adds a complete "Late Study" feature: API, network datasource, repository + DI, domain models and mappers, ViewModel, Compose UI (screen + components + calendar), navigation key/route wiring, application-screen integration, and a design-system chip style.

Changes

Late Study Feature

Layer / File(s) Summary
Data Shape / Models
network/src/.../latestudy/model/FetchStudyTypesResponse.kt, network/src/.../latestudy/model/TeacherResponse.kt, network/src/.../latestudy/model/StudyApplicationStatusResponse.kt, network/src/.../latestudy/model/SubmitLateStudyRequest.kt, data/src/.../latestudy/model/StudyType.kt
Adds network DTOs and domain StudyType, plus SubmitLateStudyRequest for submission payload.
Network API
network/src/.../latestudy/apiservice/LateStudyApiService.kt
New Retrofit interface declaring endpoints to fetch study types, teachers, current user application status, and to submit a late-study request.
Network Datasource
network/src/.../latestudy/datasource/NetworkLateStudyDataSource.kt, network/src/.../latestudy/datasource/NetworkLateStudyDataSourceImpl.kt
Introduces datasource interface and implementation delegating calls to LateStudyApiService.
Network DI
network/src/.../latestudy/di/LateStudyApiServiceModule.kt, network/src/.../latestudy/di/LateStudyDataSourceModule.kt
Hilt modules: provide LateStudyApiService via Retrofit and bind NetworkLateStudyDataSourceImpl to the datasource interface.
Repository Layer
data/src/.../latestudy/repository/LateStudyRepository.kt, data/src/.../latestudy/repository/LateStudyRepositoryImpl.kt, data/src/.../latestudy/mapper/StudyTypeMapper.kt, data/src/.../latestudy/di/LateStudyRepositoryModule.kt
Adds LateStudyRepository interface and implementation, mapper from response to domain model, and Hilt binding module for the repository.
Feature ViewModel
feature/src/.../latestudy/viewmodel/LateStudyViewModel.kt
Hilt ViewModel exposing Compose state (studyTypes, selectedTypeId, teachers), fetches data on init, supports selecting a study type and submitting late-study requests.
Feature Navigation & Route
feature/src/.../latestudy/navigation/LateStudyRoute.kt, app/src/.../navigation/DmsNavKeys.kt, app/src/.../ui/DmsApp.kt, feature/src/.../main/application/navigation/ApplicationRoute.kt
Adds LateStudyNav key, LateStudyRoute composable entry wired into app navigation; ApplicationRoute and DmsApp wired to navigate to and render the new route.
UI Screen & Components
feature/src/.../latestudy/ui/LateStudyScreen.kt, feature/src/.../latestudy/ui/component/LateStudySectionCard.kt, .../LateStudyTeacherSection.kt, .../LateStudyTypeItem.kt, .../LateStudyCalendarSection.kt, .../LateStudyReasonSection.kt
New LateStudyScreen with teacher search/dropdown, selectable study types, a calendar with range selection and range visuals, reason input with 200-char limit, submit flow, plus reusable UI components.
Application Integration
feature/src/.../main/application/ui/ApplicationScreen.kt, .../ApplicationContent.kt, .../viewmodel/ApplicationViewModel.kt
Threads navigation callback into Application UI, consumes a local result store key for submission result, fetches remote late-study status in ApplicationViewModel, adds lateStudyApplicationTitle and lateStudyStatusUi state and setLateStudyApplication to persist/update status.
Design System Update
core/design-system/src/main/java/.../card/ApplicationChipStyle.kt, core/design-system/src/main/java/.../card/DmsApplicationCard.kt
Adds ApplicationChipStyle enum (DEFAULT/APPROVED/REJECTED/PENDING); DmsApplicationCard gains chipStyle, computes chip display/text/colors from style, and suppresses chip when style is DEFAULT and no explicit title.
DI Wiring
network/.../di/*, data/.../latestudy/di/*
Hilt modules added to provide API, data source, and repository bindings into the app's singleton component.

Sequence Diagram

sequenceDiagram
    actor User
    participant UI as LateStudyScreen
    participant VM as LateStudyViewModel
    participant Repo as LateStudyRepository
    participant ND as NetworkLateStudyDataSource
    participant API as LateStudyApiService
    participant AppVM as ApplicationViewModel
    participant Store as LocalResultStore

    User->>UI: Open Late Study Screen
    UI->>VM: init -> fetchStudyTypes, fetchTeachers
    VM->>Repo: fetchStudyTypes()
    Repo->>ND: fetchStudyTypes()
    ND->>API: GET /study-types
    API-->>ND: FetchStudyTypesResponse
    ND-->>Repo: Response
    Repo-->>VM: List<StudyType>

    VM->>Repo: fetchTeachers()
    Repo->>ND: fetchTeachers()
    ND->>API: GET /teachers
    API-->>ND: FetchTeachersResponse
    ND-->>Repo: Response
    Repo-->>VM: List<TeacherResponse>

    User->>UI: Select teacher/type/dates/reason
    User->>UI: Tap Submit
    UI->>VM: submitLateStudy(...)
    VM->>Repo: submitLateStudy(SubmitLateStudyRequest)
    Repo->>ND: submitLateStudy(request)
    ND->>API: POST /submit
    API-->>ND: Success
    ND-->>Repo: Return
    Repo-->>VM: Return
    UI->>Store: set("late_study_application_result","์‹ ์ฒญ ์ค‘")
    UI->>AppVM: onNavigateLateStudyApplication callback
    AppVM->>Repo: fetchMyStudyApplicationStatus()
    Repo->>ND: fetchMyStudyApplicationStatus()
    ND->>API: GET /application-status
    API-->>ND: StudyApplicationStatusResponse
    ND-->>Repo: Response
    Repo-->>AppVM: Response
    AppVM->>AppVM: derive UI status & persist title
Loading

Estimated code review effort

๐ŸŽฏ 4 (Complex) | โฑ๏ธ ~60 minutes

Possibly related PRs

Poem

๐Ÿฐ
I hopped at dawn to spin a brand new screen,
Chips and calendars in a pastel sheen,
APIs I chewed, DI tunnels I made,
Now students file requests in the glade!

๐Ÿšฅ Pre-merge checks | โœ… 4 | โŒ 1

โŒ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage โš ๏ธ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
โœ… Passed checks (4 passed)
Check name Status Explanation
Description Check โœ… Passed Check skipped - CodeRabbitโ€™s high-level summary is enabled.
Title check โœ… Passed The title '๐Ÿ”€ :: (#960) ์ƒˆ๋ฒฝ ์ž์Šต ์‹ ์ฒญ ๊ธฐ๋Šฅ ๊ตฌํ˜„' clearly describes the main feature added: implementing the early morning self-study application functionality, which is accurately reflected across all changed files.
Linked Issues check โœ… Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check โœ… Passed Check skipped because no linked issues were found for this pull request.

โœ๏ธ Tip: You can configure your own custom pre-merge checks in the settings.

โœจ Finishing Touches
๐Ÿ“ Generate docstrings
  • Create stacked PR
  • Commit on current branch
๐Ÿงช Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/890-์ƒˆ๋ฒฝ-์ž์Šต-์‹ ์ฒญ-๊ธฐ๋Šฅ-๊ตฌํ˜„

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
Review rate limit: 0/1 reviews remaining, refill in 60 minutes.

Comment @coderabbitai help to get the list of available commands and usage tips.

)
}
if (title == null) {
sharedPreferences.edit().remove(KEY_APPLIED_LATE_STUDY_TITLE).apply()
if (title == null) {
sharedPreferences.edit().remove(KEY_APPLIED_LATE_STUDY_TITLE).apply()
} else {
sharedPreferences.edit().putString(KEY_APPLIED_LATE_STUDY_TITLE, title).apply()
}

internal fun setLateStudyApplication(title: String) {
sharedPreferences.edit().putString(KEY_APPLIED_LATE_STUDY_TITLE, title).apply()
Copy link
Copy Markdown

@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: 6

๐Ÿงน Nitpick comments (3)
feature/src/main/kotlin/team/aliens/dms/android/feature/latestudy/ui/component/LateStudyReasonSection.kt (1)

44-45: โšก Quick win

Use REASON_MAX_LENGTH consistently instead of hardcoded 200.

Line 44 and Line 65 duplicate the max-length literal even though a constant already exists. This can drift later.

Proposed change
-            Text(
-                text = "${value.length}/200",
+            Text(
+                text = "${value.length}/$REASON_MAX_LENGTH",
                 color = DmsTheme.colorScheme.inverseSurface,
                 style = DmsTheme.typography.labelM,
                 modifier = Modifier.padding(top = 4.dp, end = 10.dp)
             )
@@
-                onValueChange = { newValue ->
-                    if (newValue.length <= 200) {
+                onValueChange = { newValue ->
+                    if (newValue.length <= REASON_MAX_LENGTH) {
                         onValueChange(newValue)
                     }
                 },

Also applies to: 65-66

๐Ÿค– Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@feature/src/main/kotlin/team/aliens/dms/android/feature/latestudy/ui/component/LateStudyReasonSection.kt`
around lines 44 - 45, Replace the hardcoded max-length literal 200 with the
existing REASON_MAX_LENGTH constant in the LateStudyReasonSection composable:
update the text display that currently uses "${value.length}/200" and any other
occurrences (e.g., maxLength parameters or checks around value in
LateStudyReasonSection) to reference REASON_MAX_LENGTH instead (ensure the
constant is in scope or import it if needed) so both places use the single
source of truth.
feature/src/main/kotlin/team/aliens/dms/android/feature/main/application/ui/component/ApplicationContent.kt (1)

37-59: โšก Quick win

Decouple business mapping from display strings.

Behavior is keyed off localized title text (when (title)), which is brittle. A text/resource change can break appliedTitle and chipStyle mapping without compile-time signal.

Use a stable card type (enum/sealed class) and map title/chip/appliedTitle off that type.

๐Ÿค– Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@feature/src/main/kotlin/team/aliens/dms/android/feature/main/application/ui/component/ApplicationContent.kt`
around lines 37 - 59, The UI currently switches behavior using localized title
strings (the Triple list and the when(title) blocks in ApplicationContent.kt)
which is brittle; replace that by introducing a stable card identifier (e.g., an
enum or sealed class like ApplicationCardType) and build a list of card models
(data class with type: ApplicationCardType, titleRes/iconRes/onClick) instead of
Triples; then update DmsApplicationCard usages to derive appliedTitle and
chipStyle by switching on the card.type (use ApplicationCardType.REMAIN,
LATE_STUDY, OUTING, VOLUNTEER) rather than the title string so UI text can
change without breaking logic (adjust any references to appliedTitle and
chipStyle to use the new type-based when branches).
data/src/main/kotlin/team/aliens/dms/android/data/latestudy/repository/LateStudyRepository.kt (1)

4-16: ๐Ÿ—๏ธ Heavy lift

Avoid exposing network DTOs in repository contracts.

LateStudyRepository is a data-layer boundary, but it currently imports and exposes network models directly. This couples feature/data code to transport schema changes and makes future API changes ripple farther than needed.

Please introduce repository-facing models/commands (or domain models) and map in LateStudyRepositoryImpl.

๐Ÿค– Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@data/src/main/kotlin/team/aliens/dms/android/data/latestudy/repository/LateStudyRepository.kt`
around lines 4 - 16, LateStudyRepository currently exposes network DTOs
(StudyApplicationStatusResponse, TeacherResponse, SubmitLateStudyRequest) in its
public API; change the interface to use repository/domain models (e.g.,
StudyType (if already domain), Teacher, StudyApplicationStatus,
SubmitLateStudyCommand) instead of the network types for the methods
fetchTeachers(), fetchMyStudyApplicationStatus(), and submitLateStudy(); then
implement mapping in LateStudyRepositoryImpl to convert network DTOs to these
domain models on fetch and convert the repository command/model to
SubmitLateStudyRequest when sending to the network. Ensure all references to
StudyApplicationStatusResponse, TeacherResponse, and SubmitLateStudyRequest are
removed from the interface and only appear inside LateStudyRepositoryImpl
mapping code.
๐Ÿค– Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@feature/src/main/kotlin/team/aliens/dms/android/feature/latestudy/ui/component/LateStudyCalendarSection.kt`:
- Around line 68-73: The Icon usages in LateStudyCalendarSection (the left and
right month controls) use Modifier.clickable which yields a 24ร—24 dp tap area;
replace those Icons with IconButton wrappers (one for the previous-month control
tied to onPrevMonthClick and one for the next-month control tied to
onNextMonthClick) so the touch target is at least 48ร—48 dp and the control is
announced as a button; preserve the existing contentDescription and tint, move
any modifier (padding/size) to the IconButton as appropriate, and remove the
.clickable from the inner Icon.

In
`@feature/src/main/kotlin/team/aliens/dms/android/feature/latestudy/ui/component/LateStudyTypeItem.kt`:
- Around line 34-45: The Row currently uses .clickable(onClick = onClick) which
doesn't expose role/selected state to accessibility services; update the
modifier chain in LateStudyTypeItem's Row to use .selectable(selected =
selected, onClick = onClick, role = Role.RadioButton) instead of .clickable so
assistive tech can announce selection, and add the necessary import for
androidx.compose.foundation.selection.selectable and
androidx.compose.ui.semantics.Role if missing.

In
`@feature/src/main/kotlin/team/aliens/dms/android/feature/latestudy/ui/LateStudyScreen.kt`:
- Around line 302-320: The click handler currently re-checks endDate and rejects
one-day submissions; update the onClick validation to match the button enabled
logic by removing the endDate != null condition so it only requires
selectedTeacherId, selectedTypeId, startDate, and non-blank reason before
calling viewModel.submitLateStudy; keep the existing fallback endDate ?:
startDate usage and pass teacherId = selectedTeacherId!!, typeId =
selectedTypeId!!, reason, startDate.toString(), and (endDate ?:
startDate).toString() as before.

In
`@feature/src/main/kotlin/team/aliens/dms/android/feature/latestudy/viewmodel/LateStudyViewModel.kt`:
- Around line 59-80: The submitLateStudy function currently fire-and-forgets and
swallows exceptions; change its API so callers can observe success/failure: make
TeamAliensDMS.android.feature.latestudy.viewmodel.LateStudyViewModel.submitLateStudy
a suspend function (or return a Result<Boolean>/Deferred/Flow) that directly
calls lateStudyRepository.submitLateStudy and returns success or throws the
repository exception instead of catching it; remove the internal
viewModelScope.launch and e.printStackTrace(), or alternatively keep the launch
but post the outcome to a LiveData/StateFlow (e.g., lateStudyApplicationResult)
so the screen can react to success/failure; ensure to reference submitLateStudy
and lateStudyRepository.submitLateStudy when updating callers.

In
`@feature/src/main/kotlin/team/aliens/dms/android/feature/main/application/ui/ApplicationScreen.kt`:
- Around line 57-66: The current LaunchedEffect uses snapshotFlow over
resultStore.resultStateMap[...] which is a plain mutableMap and not
snapshot-aware, so snapshotFlow may never re-emit when keys are later added;
change the store to expose snapshot-aware state (e.g., make resultStateMap a
SnapshotStateMap or expose a State/MutableState for each result key) and then
collect from snapshotFlow (or directly observe the State) instead of reading a
plain Map; specifically update the resultStore/resultStateMap implementation so
setResult(...) inserts into a SnapshotStateMap (or exposes an observable
getResultState(key): State<String?>) and then in ApplicationScreen's
LaunchedEffect use that snapshot-aware State to call
viewModel.setLateStudyApplication(result) and resultStore.removeResult(resultKey
= "late_study_application_result").

In
`@feature/src/main/kotlin/team/aliens/dms/android/feature/main/application/viewmodel/ApplicationViewModel.kt`:
- Around line 78-88: The ViewModel preserves in-memory late-study fields when
the API returns null, causing a stale chip; update the setState call in
ApplicationViewModel (the lambda passed to setState) to assign the nullable
values directly (e.g., lateStudyApplicationTitle = title and lateStudyStatusUi =
statusUi) instead of falling back to current.* so that when title or statusUi
are null the in-memory state is cleared; keep the sharedPreferences
removal/putString logic with KEY_APPLIED_LATE_STUDY_TITLE as-is to remain
consistent with persisted state.

---

Nitpick comments:
In
`@data/src/main/kotlin/team/aliens/dms/android/data/latestudy/repository/LateStudyRepository.kt`:
- Around line 4-16: LateStudyRepository currently exposes network DTOs
(StudyApplicationStatusResponse, TeacherResponse, SubmitLateStudyRequest) in its
public API; change the interface to use repository/domain models (e.g.,
StudyType (if already domain), Teacher, StudyApplicationStatus,
SubmitLateStudyCommand) instead of the network types for the methods
fetchTeachers(), fetchMyStudyApplicationStatus(), and submitLateStudy(); then
implement mapping in LateStudyRepositoryImpl to convert network DTOs to these
domain models on fetch and convert the repository command/model to
SubmitLateStudyRequest when sending to the network. Ensure all references to
StudyApplicationStatusResponse, TeacherResponse, and SubmitLateStudyRequest are
removed from the interface and only appear inside LateStudyRepositoryImpl
mapping code.

In
`@feature/src/main/kotlin/team/aliens/dms/android/feature/latestudy/ui/component/LateStudyReasonSection.kt`:
- Around line 44-45: Replace the hardcoded max-length literal 200 with the
existing REASON_MAX_LENGTH constant in the LateStudyReasonSection composable:
update the text display that currently uses "${value.length}/200" and any other
occurrences (e.g., maxLength parameters or checks around value in
LateStudyReasonSection) to reference REASON_MAX_LENGTH instead (ensure the
constant is in scope or import it if needed) so both places use the single
source of truth.

In
`@feature/src/main/kotlin/team/aliens/dms/android/feature/main/application/ui/component/ApplicationContent.kt`:
- Around line 37-59: The UI currently switches behavior using localized title
strings (the Triple list and the when(title) blocks in ApplicationContent.kt)
which is brittle; replace that by introducing a stable card identifier (e.g., an
enum or sealed class like ApplicationCardType) and build a list of card models
(data class with type: ApplicationCardType, titleRes/iconRes/onClick) instead of
Triples; then update DmsApplicationCard usages to derive appliedTitle and
chipStyle by switching on the card.type (use ApplicationCardType.REMAIN,
LATE_STUDY, OUTING, VOLUNTEER) rather than the title string so UI text can
change without breaking logic (adjust any references to appliedTitle and
chipStyle to use the new type-based when branches).
๐Ÿช„ Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

โ„น๏ธ Review info
โš™๏ธ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: b791a9af-5511-492b-8b89-435b4c17f2c6

๐Ÿ“ฅ Commits

Reviewing files that changed from the base of the PR and between fcde610 and 17c268e.

โ›” Files ignored due to path filters (1)
  • core/design-system/src/main/res/drawable/img_3d_dawn.png is excluded by !**/*.png
๐Ÿ“’ Files selected for processing (29)
  • app/src/main/kotlin/team/aliens/dms/android/app/navigation/DmsNavKeys.kt
  • app/src/main/kotlin/team/aliens/dms/android/app/ui/DmsApp.kt
  • core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/card/DmsApplicationCard.kt
  • data/src/main/kotlin/team/aliens/dms/android/data/latestudy/di/LateStudyRepositoryModule.kt
  • data/src/main/kotlin/team/aliens/dms/android/data/latestudy/mapper/StudyTypeMapper.kt
  • data/src/main/kotlin/team/aliens/dms/android/data/latestudy/model/StudyType.kt
  • data/src/main/kotlin/team/aliens/dms/android/data/latestudy/repository/LateStudyRepository.kt
  • data/src/main/kotlin/team/aliens/dms/android/data/latestudy/repository/LateStudyRepositoryImpl.kt
  • feature/src/main/kotlin/team/aliens/dms/android/feature/latestudy/navigation/LateStudyRoute.kt
  • feature/src/main/kotlin/team/aliens/dms/android/feature/latestudy/ui/LateStudyScreen.kt
  • feature/src/main/kotlin/team/aliens/dms/android/feature/latestudy/ui/component/LateStudyCalendarSection.kt
  • feature/src/main/kotlin/team/aliens/dms/android/feature/latestudy/ui/component/LateStudyReasonSection.kt
  • feature/src/main/kotlin/team/aliens/dms/android/feature/latestudy/ui/component/LateStudySectionCard.kt
  • feature/src/main/kotlin/team/aliens/dms/android/feature/latestudy/ui/component/LateStudyTeacherSection.kt
  • feature/src/main/kotlin/team/aliens/dms/android/feature/latestudy/ui/component/LateStudyTypeItem.kt
  • feature/src/main/kotlin/team/aliens/dms/android/feature/latestudy/viewmodel/LateStudyViewModel.kt
  • feature/src/main/kotlin/team/aliens/dms/android/feature/main/application/navigation/ApplicationRoute.kt
  • feature/src/main/kotlin/team/aliens/dms/android/feature/main/application/ui/ApplicationScreen.kt
  • feature/src/main/kotlin/team/aliens/dms/android/feature/main/application/ui/component/ApplicationContent.kt
  • feature/src/main/kotlin/team/aliens/dms/android/feature/main/application/viewmodel/ApplicationViewModel.kt
  • network/src/main/kotlin/team/aliens/dms/android/network/latestudy/apiservice/LateStudyApiService.kt
  • network/src/main/kotlin/team/aliens/dms/android/network/latestudy/datasource/NetworkLateStudyDataSource.kt
  • network/src/main/kotlin/team/aliens/dms/android/network/latestudy/datasource/NetworkLateStudyDataSourceImpl.kt
  • network/src/main/kotlin/team/aliens/dms/android/network/latestudy/di/LateStudyApiServiceModule.kt
  • network/src/main/kotlin/team/aliens/dms/android/network/latestudy/di/LateStudyDataSourceModule.kt
  • network/src/main/kotlin/team/aliens/dms/android/network/latestudy/model/FetchStudyTypesResponse.kt
  • network/src/main/kotlin/team/aliens/dms/android/network/latestudy/model/StudyApplicationStatusResponse.kt
  • network/src/main/kotlin/team/aliens/dms/android/network/latestudy/model/SubmitLateStudyRequest.kt
  • network/src/main/kotlin/team/aliens/dms/android/network/latestudy/model/TeacherResponse.kt

Comment on lines +59 to +80
fun submitLateStudy(
teacherId: String,
typeId: String,
reason: String,
startDate: String,
endDate: String,
) {
viewModelScope.launch {
try {
lateStudyRepository.submitLateStudy(
SubmitLateStudyRequest(
teacher_id = teacherId,
type_id = typeId,
reason = reason,
start_date = startDate,
end_date = endDate,
),
)
} catch (e: Exception) {
e.printStackTrace()
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

โš ๏ธ Potential issue | ๐ŸŸ  Major | ๐Ÿ—๏ธ Heavy lift

Return submission success to the caller instead of fire-and-forget.

submitLateStudy() launches internally and swallows failures, so the caller cannot know whether the request actually succeeded. The current screen flow updates late_study_application_result and pops immediately after invoking this method, which means a network failure still looks like a submitted application to the user.

๐Ÿค– Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@feature/src/main/kotlin/team/aliens/dms/android/feature/latestudy/viewmodel/LateStudyViewModel.kt`
around lines 59 - 80, The submitLateStudy function currently fire-and-forgets
and swallows exceptions; change its API so callers can observe success/failure:
make
TeamAliensDMS.android.feature.latestudy.viewmodel.LateStudyViewModel.submitLateStudy
a suspend function (or return a Result<Boolean>/Deferred/Flow) that directly
calls lateStudyRepository.submitLateStudy and returns success or throws the
repository exception instead of catching it; remove the internal
viewModelScope.launch and e.printStackTrace(), or alternatively keep the launch
but post the outcome to a LiveData/StateFlow (e.g., lateStudyApplicationResult)
so the screen can react to success/failure; ensure to reference submitLateStudy
and lateStudyRepository.submitLateStudy when updating callers.

Comment on lines +57 to +66
LaunchedEffect(Unit) {
snapshotFlow {
resultStore.resultStateMap["late_study_application_result"]?.value as? String?
}.collect { result ->
if (result != null) {
viewModel.setLateStudyApplication(result)
resultStore.removeResult<String?>(resultKey = "late_study_application_result")
}
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

โš ๏ธ Potential issue | ๐ŸŸ  Major

๐Ÿงฉ Analysis chain

๐ŸŒ Web query:

In Jetpack Compose, does snapshotFlow { map[key]?.value }re-emit whenmapis a plainmutableMapOf() and the key is inserted later, or does it only track snapshot-aware state reads?

๐Ÿ’ก Result:

No, snapshotFlow { map[key]?.value } does not re-emit when map is a plain mutableMapOf and the key is inserted later. It only tracks snapshot-aware state reads.

Citations:


๐Ÿ Script executed:

# Find and read the ResultStore implementation
fd -e kt -e java ResultStore | head -5

Repository: team-aliens/DMS-Android

Length of output: 147


๐Ÿ Script executed:

cat -n core/ui/src/main/java/team/aliens/dms/android/core/ui/navigation/ResultStore.kt

Repository: team-aliens/DMS-Android

Length of output: 2148


๐Ÿ Script executed:

# Now let's check the ApplicationScreen usage context
head -70 feature/src/main/kotlin/team/aliens/dms/android/feature/main/application/ui/ApplicationScreen.kt | tail -20

Repository: team-aliens/DMS-Android

Length of output: 779


๐Ÿ Script executed:

# Let's check if there are other similar patterns with resultStore in the codebase
rg "snapshotFlow" feature/src/main/kotlin/team/aliens/dms/android/feature --context 3 -A 5

Repository: team-aliens/DMS-Android

Length of output: 5940


๐Ÿ Script executed:

# Check if late_study_application_result is ever pre-initialized anywhere
rg "late_study_application_result" feature/ --context 2

Repository: team-aliens/DMS-Android

Length of output: 1941


Use a snapshot-aware container for the result store.

snapshotFlow only re-emits when the lambda reads snapshot state. resultStateMap is a plain mutableMapOf(), so if the key is missing on first composition, the flow never subscribes to that key's state. When the key is later inserted via setResult() (e.g., after the user returns from LateStudyScreen), snapshotFlow will not re-emit, and the UI update will be missed entirely.

This pattern affects multiple screens: ApplicationScreen (both remain and late-study results), VoteScreen, and NoticeDetailScreen. Consider wrapping result state in a snapshot-aware data structure like SnapshotStateMap or restructuring to observe the store itself rather than nested map accesses.

๐Ÿค– Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@feature/src/main/kotlin/team/aliens/dms/android/feature/main/application/ui/ApplicationScreen.kt`
around lines 57 - 66, The current LaunchedEffect uses snapshotFlow over
resultStore.resultStateMap[...] which is a plain mutableMap and not
snapshot-aware, so snapshotFlow may never re-emit when keys are later added;
change the store to expose snapshot-aware state (e.g., make resultStateMap a
SnapshotStateMap or expose a State/MutableState for each result key) and then
collect from snapshotFlow (or directly observe the State) instead of reading a
plain Map; specifically update the resultStore/resultStateMap implementation so
setResult(...) inserts into a SnapshotStateMap (or exposes an observable
getResultState(key): State<String?>) and then in ApplicationScreen's
LaunchedEffect use that snapshot-aware State to call
viewModel.setLateStudyApplication(result) and resultStore.removeResult(resultKey
= "late_study_application_result").

Comment on lines +78 to +88
setState { current ->
current.copy(
lateStudyApplicationTitle = title ?: current.lateStudyApplicationTitle,
lateStudyStatusUi = statusUi ?: current.lateStudyStatusUi,
)
}
if (title == null) {
sharedPreferences.edit().remove(KEY_APPLIED_LATE_STUDY_TITLE).apply()
} else {
sharedPreferences.edit().putString(KEY_APPLIED_LATE_STUDY_TITLE, title).apply()
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

โš ๏ธ Potential issue | ๐ŸŸ  Major | โšก Quick win

Clear the in-memory late-study state when the API returns no active item.

Lines 80-81 preserve the previous title/status when toAppliedTitle() or toUiStatus() return null, but Lines 84-87 still delete the stored preference. That leaves a stale late-study chip on screen until this ViewModel is recreated.

Suggested fix
                 setState { current ->
                     current.copy(
-                        lateStudyApplicationTitle = title ?: current.lateStudyApplicationTitle,
-                        lateStudyStatusUi = statusUi ?: current.lateStudyStatusUi,
+                        lateStudyApplicationTitle = title,
+                        lateStudyStatusUi = statusUi,
                     )
                 }
๐Ÿค– Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@feature/src/main/kotlin/team/aliens/dms/android/feature/main/application/viewmodel/ApplicationViewModel.kt`
around lines 78 - 88, The ViewModel preserves in-memory late-study fields when
the API returns null, causing a stale chip; update the setState call in
ApplicationViewModel (the lambda passed to setState) to assign the nullable
values directly (e.g., lateStudyApplicationTitle = title and lateStudyStatusUi =
statusUi) instead of falling back to current.* so that when title or statusUi
are null the in-memory state is cleared; keep the sharedPreferences
removal/putString logic with KEY_APPLIED_LATE_STUDY_TITLE as-is to remain
consistent with persisted state.

Copy link
Copy Markdown

@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)
feature/src/main/kotlin/team/aliens/dms/android/feature/latestudy/viewmodel/LateStudyViewModel.kt (1)

25-26: โšก Quick win

selectedTypeId state and selectStudyType() are dead code.

LateStudyScreen maintains its own local selectedTypeId via remember { mutableStateOf(null) } and never calls viewModel.selectStudyType(). The ViewModel's selectedTypeId is always null. These can be removed; submitLateStudy already receives typeId as a parameter.

โ™ป๏ธ Proposed fix
-    var selectedTypeId by mutableStateOf<String?>(null)
-        private set
-
     var teachers by mutableStateOf<List<TeacherResponse>>(emptyList())
         private set

-    fun selectStudyType(typeId: String) {
-        selectedTypeId = typeId
-    }
-
     fun submitLateStudy(

Also applies to: 56-58

๐Ÿค– Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@feature/src/main/kotlin/team/aliens/dms/android/feature/latestudy/viewmodel/LateStudyViewModel.kt`
around lines 25 - 26, Remove the dead ViewModel state and method: delete the
nullable mutableState property selectedTypeId and the selectStudyType() function
from LateStudyViewModel since LateStudyScreen holds its own selectedTypeId and
never invokes selectStudyType(); ensure submitLateStudy still accepts a typeId
parameter and leave it unchanged (so callers pass the screen-local typeId
directly). Also remove any references/usages of selectedTypeId within
LateStudyViewModel (and any related private setter) to avoid unused
declarations.
๐Ÿค– Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@feature/src/main/kotlin/team/aliens/dms/android/feature/latestudy/ui/LateStudyScreen.kt`:
- Around line 192-194: The IconButton's touch target was reduced by using
Modifier.size(24.dp); remove the Modifier.size(24.dp) from the IconButton (the
call where IconButton(onClick = onBack, modifier = Modifier.size(24.dp))) so it
keeps Material3's default 48 dp interactive area; if you intended the visible
icon to be 24 dp, move Modifier.size(24.dp) to the Icon composable inside the
IconButton instead.

In
`@feature/src/main/kotlin/team/aliens/dms/android/feature/latestudy/viewmodel/LateStudyViewModel.kt`:
- Around line 69-77: The SubmitLateStudyRequest is being constructed with
snake_case parameter names causing compilation errors; update the call in
LateStudyViewModel (where lateStudyRepository.submitLateStudy(...) is invoked)
to use the Kotlin constructor parameter names: teacherId, typeId, reason,
startDate and endDate (camelCase matching the SubmitLateStudyRequest primary
constructor) so the request compiles and Gson `@SerializedName` can still map to
JSON.

---

Nitpick comments:
In
`@feature/src/main/kotlin/team/aliens/dms/android/feature/latestudy/viewmodel/LateStudyViewModel.kt`:
- Around line 25-26: Remove the dead ViewModel state and method: delete the
nullable mutableState property selectedTypeId and the selectStudyType() function
from LateStudyViewModel since LateStudyScreen holds its own selectedTypeId and
never invokes selectStudyType(); ensure submitLateStudy still accepts a typeId
parameter and leave it unchanged (so callers pass the screen-local typeId
directly). Also remove any references/usages of selectedTypeId within
LateStudyViewModel (and any related private setter) to avoid unused
declarations.
๐Ÿช„ Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

โ„น๏ธ Review info
โš™๏ธ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4b47b2d9-9e8d-4e95-962d-fe5261d89185

๐Ÿ“ฅ Commits

Reviewing files that changed from the base of the PR and between 17c268e and db69d81.

๐Ÿ“’ Files selected for processing (8)
  • core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/card/ApplicationChipStyle.kt
  • core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/card/DmsApplicationCard.kt
  • feature/src/main/kotlin/team/aliens/dms/android/feature/latestudy/ui/LateStudyScreen.kt
  • feature/src/main/kotlin/team/aliens/dms/android/feature/latestudy/ui/component/LateStudyCalendarSection.kt
  • feature/src/main/kotlin/team/aliens/dms/android/feature/latestudy/ui/component/LateStudyReasonSection.kt
  • feature/src/main/kotlin/team/aliens/dms/android/feature/latestudy/ui/component/LateStudyTypeItem.kt
  • feature/src/main/kotlin/team/aliens/dms/android/feature/latestudy/viewmodel/LateStudyViewModel.kt
  • network/src/main/kotlin/team/aliens/dms/android/network/latestudy/model/SubmitLateStudyRequest.kt
โœ… Files skipped from review due to trivial changes (1)
  • network/src/main/kotlin/team/aliens/dms/android/network/latestudy/model/SubmitLateStudyRequest.kt
๐Ÿšง Files skipped from review as they are similar to previous changes (2)
  • core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/card/DmsApplicationCard.kt
  • feature/src/main/kotlin/team/aliens/dms/android/feature/latestudy/ui/component/LateStudyTypeItem.kt

@ashxom ashxom requested review from uson1004 May 4, 2026 15:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat ์ƒˆ๋กœ์šด ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ ํ•  ๊ฒฝ์šฐ

Projects

None yet

Development

Successfully merging this pull request may close these issues.

์ƒˆ๋ฒฝ ์ž์Šต ์‹ ์ฒญ ๊ธฐ๋Šฅ ๊ตฌํ˜„

2 participants