Skip to content

Commit 9d69940

Browse files
committed
Merge branch 'feature/755-기숙사-봉사-신청-기능구현' into develop
2 parents 3a7243e + 16b2458 commit 9d69940

File tree

13 files changed

+235
-4
lines changed

13 files changed

+235
-4
lines changed

app/src/main/java/team/aliens/dms/android/app/DmsApp.kt

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ import team.aliens.dms.android.feature.resetpassword.navigation.ResetPasswordNav
2626
import team.aliens.dms.android.feature.signup.SignUpViewModel
2727
import team.aliens.dms.android.feature.signup.TermsUrl
2828
import team.aliens.dms.android.feature.signup.navigation.SignUpNavGraph
29-
import team.aliens.dms.android.feature.voting.VotingViewModel
30-
import team.aliens.dms.android.feature.voting.navigation.VotingNavGraph
3129
import team.aliens.dms.android.network.BuildConfig
3230

3331
@Composable
@@ -77,6 +75,13 @@ fun DmsApp(
7775
hiltViewModel<ResetPasswordViewModel>(parentEntry)
7876
}
7977

78+
dependency(VolunteersNavGraph) {
79+
val parentEntry = remember(navBackStackEntry) {
80+
navController.getBackStackEntry(VolunteersNavGraph.route)
81+
}
82+
hiltViewModel<VolunteersViewModel>(parentEntry)
83+
}
84+
8085
dependency(VotingNavGraph) {
8186
val parentEntry = remember(navBackStackEntry) {
8287
navController.getBackStackEntry(VotingNavGraph.route)

app/src/main/java/team/aliens/dms/android/app/navigation/DmsNavigator.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import team.aliens.dms.android.feature.outing.navigation.OutingNavGraph
4545
import team.aliens.dms.android.feature.resetpassword.navigation.ResetPasswordNavGraph
4646
import team.aliens.dms.android.feature.signup.navigation.SignUpNavGraph
4747
import team.aliens.dms.android.feature.voting.navigation.VotingNavGraph
48+
import team.aliens.dms.android.feature.volunteers.navigation.VolunteersNavGraph
4849
import java.util.UUID
4950

5051
class DmsNavigator(
@@ -100,6 +101,10 @@ class DmsNavigator(
100101
}
101102
}
102103

104+
override fun openVolunteer() {
105+
navController.navigateSingleTop(VolunteersNavGraph)
106+
}
107+
103108
override fun openEditPasswordSetPassword(currentPassword: String) {
104109
navController.navigateSingleTop(EditPasswordSetPasswordScreenDestination within EditPasswordNavGraph)
105110
}

app/src/main/java/team/aliens/dms/android/app/navigation/authorized/AuthorizedNavGraph.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@ import team.aliens.dms.android.feature.destinations.VotingApprovalScreenDestinat
1818
import team.aliens.dms.android.feature.destinations.VotingModelStudentScreenDestination
1919
import team.aliens.dms.android.feature.destinations.VotingSelectedScreenDestination
2020
import team.aliens.dms.android.feature.destinations.VotingStudentScreenDestination
21+
import team.aliens.dms.android.feature.destinations.VolunteersScreenDestination
2122
import team.aliens.dms.android.feature.editpassword.navigation.EditPasswordNavGraph
2223
import team.aliens.dms.android.feature.outing.navigation.OutingNavGraph
2324
import team.aliens.dms.android.feature.studyroom.navigation.StudyRoomNavGraph
2425
import team.aliens.dms.android.feature.voting.navigation.VotingNavGraph
26+
import team.aliens.dms.android.feature.volunteers.navigation.VolunteersNavGraph
2527

2628
object AuthorizedNavGraph : NavGraphSpec {
2729
override val route: String = "authorized"
@@ -32,6 +34,7 @@ object AuthorizedNavGraph : NavGraphSpec {
3234
StudyRoomNavGraph,
3335
OutingNavGraph,
3436
VotingNavGraph,
37+
VolunteersNavGraph,
3538
)
3639

3740
override val destinationsByRoute: Map<String, DestinationSpec<*>> =
@@ -50,6 +53,7 @@ object AuthorizedNavGraph : NavGraphSpec {
5053
VotingStudentScreenDestination,
5154
VotingSelectedScreenDestination,
5255
VotingApprovalScreenDestination,
56+
VolunteersScreenDestination,
5357
)
5458
.routedIn(navGraphSpec = this)
5559
.associateBy { it.route }

app/src/main/java/team/aliens/dms/android/app/navigation/authorized/AuthorizedNavigator.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import team.aliens.dms.android.feature.point.navigation.PointHistoryNavigator
1111
import team.aliens.dms.android.feature.remains.navigator.RemainsNavigator
1212
import team.aliens.dms.android.feature.studyroom.navigation.StudyRoomNavigator
1313
import team.aliens.dms.android.feature.voting.navigation.VotingNavigator
14+
import team.aliens.dms.android.feature.volunteers.navigation.VolunteersNavigator
1415

1516
interface AuthorizedNavigator :
1617
MainNavigator,
@@ -22,5 +23,4 @@ interface AuthorizedNavigator :
2223
PointHistoryNavigator,
2324
RemainsNavigator,
2425
StudyRoomNavigator,
25-
OutingNavigator,
26-
VotingNavigator
26+
OutingNavigator

feature/build.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ android {
3232

3333
buildFeatures {
3434
compose = true
35+
buildConfig = true
3536
}
3637

3738
composeOptions {
@@ -59,7 +60,9 @@ dependencies {
5960
implementation(project(ProjectPaths.Core.DESIGN_SYSTEM))
6061
implementation(project(ProjectPaths.Core.FILE))
6162
implementation(project(ProjectPaths.Core.NOTIFICATION))
63+
implementation(project(ProjectPaths.Core.JWT))
6264

65+
implementation(project(ProjectPaths.NETWORK))
6366
implementation(project(ProjectPaths.DATA))
6467

6568
implementation(libs.androidx.core)

feature/src/main/java/team/aliens/dms/android/feature/main/Main.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ internal fun Main(
124124
ApplicationScreen(
125125
onNavigateToRemains = mainNavigator::openRemainsApplication,
126126
onNavigateToOuting = mainNavigator::openOutingNav,
127+
onNavigateToVolunteers = mainNavigator::openVolunteer,
127128
onNavigateToModelStudent = mainNavigator::openVotingModelStudent,
128129
onNavigateToApprovalVote = mainNavigator::openVotingApproval,
129130
onNavigateToStudentVote = mainNavigator::openVotingStudent,

feature/src/main/java/team/aliens/dms/android/feature/main/application/ApplicationScreen.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ internal fun ApplicationScreen(
6666
modifier: Modifier = Modifier,
6767
onNavigateToRemains: () -> Unit,
6868
onNavigateToOuting: () -> Unit,
69+
onNavigateToVolunteers: () -> Unit,
6970
onNavigateToModelStudent: (voteOptionId: UUID, voteTopicTitle: String) -> Unit,
7071
onNavigateToApprovalVote: (voteOptionId: UUID, voteTopicTitle: String) -> Unit,
7172
onNavigateToStudentVote: (voteOptionId: UUID, voteTopicTitle: String) -> Unit,
@@ -314,6 +315,15 @@ private fun ApplicationCard(
314315
) {
315316
Text(text = buttonText)
316317
}
318+
ApplicationCard(
319+
modifier = Modifier
320+
.fillMaxWidth()
321+
.topPadding(),
322+
title = stringResource(id = R.string.volunteers_application),
323+
description = stringResource(id = R.string.volunteers_description),
324+
buttonText = stringResource(id = R.string.volunteers_do_description),
325+
onButtonClick = onNavigateToVolunteers,
326+
)
317327
}
318328
}
319329
}

feature/src/main/java/team/aliens/dms/android/feature/main/navigation/MainNavigator.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package team.aliens.dms.android.feature.main.navigation
22

3+
import team.aliens.dms.android.core.jwt.Tokens
34
import team.aliens.dms.android.data.point.model.PointType
45
import java.util.UUID
56

@@ -32,4 +33,6 @@ interface MainNavigator {
3233
fun openVotingSelected(voteOptionId: UUID, voteTopicTitle: String)
3334

3435
fun openVotingStudent(voteOptionId: UUID, voteTopicTitle: String)
36+
37+
fun openVolunteer()
3538
}
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
package team.aliens.dms.android.feature.volunteers
2+
3+
import android.annotation.SuppressLint
4+
import android.view.ViewGroup
5+
import android.webkit.WebView
6+
import android.webkit.WebViewClient
7+
import androidx.compose.foundation.background
8+
import androidx.compose.foundation.isSystemInDarkTheme
9+
import androidx.compose.foundation.layout.Column
10+
import androidx.compose.foundation.layout.fillMaxSize
11+
import androidx.compose.foundation.layout.imePadding
12+
import androidx.compose.foundation.layout.padding
13+
import androidx.compose.material3.ExperimentalMaterial3Api
14+
import androidx.compose.material3.Icon
15+
import androidx.compose.material3.IconButton
16+
import androidx.compose.material3.Text
17+
import androidx.compose.runtime.Composable
18+
import androidx.compose.runtime.getValue
19+
import androidx.compose.ui.Modifier
20+
import androidx.compose.ui.res.painterResource
21+
import androidx.compose.ui.res.stringResource
22+
import androidx.compose.ui.viewinterop.AndroidView
23+
import androidx.hilt.navigation.compose.hiltViewModel
24+
import androidx.lifecycle.compose.collectAsStateWithLifecycle
25+
import com.ramcosta.composedestinations.annotation.Destination
26+
import team.aliens.dms.android.core.designsystem.DmsTheme
27+
import team.aliens.dms.android.core.designsystem.DmsTopAppBar
28+
import team.aliens.dms.android.core.designsystem.Scaffold
29+
import team.aliens.dms.android.feature.R
30+
import team.aliens.dms.android.feature.volunteers.navigation.VolunteersNavigator
31+
import team.aliens.dms.android.network.BuildConfig
32+
33+
@SuppressLint("SetJavaScriptEnabled")
34+
@OptIn(ExperimentalMaterial3Api::class)
35+
@Destination
36+
@Composable
37+
fun VolunteersScreen(
38+
modifier: Modifier = Modifier,
39+
navigator: VolunteersNavigator,
40+
viewModel: VolunteersViewModel = hiltViewModel(),
41+
) {
42+
val uiState by viewModel.stateFlow.collectAsStateWithLifecycle()
43+
val theme = if (isSystemInDarkTheme()) "dark" else "light"
44+
var isTokenSet = false
45+
46+
Scaffold(
47+
modifier = modifier.background(color = DmsTheme.colorScheme.background),
48+
topBar = {
49+
DmsTopAppBar(
50+
title = {
51+
Text(text = stringResource(id = R.string.volunteers))
52+
},
53+
navigationIcon = {
54+
IconButton(onClick = navigator::navigateUp) {
55+
Icon(
56+
painter = painterResource(id = R.drawable.ic_baseline_arrow_back_24),
57+
contentDescription = stringResource(id = R.string.top_bar_back_button),
58+
)
59+
}
60+
},
61+
)
62+
},
63+
) { padValues ->
64+
Column(
65+
modifier = Modifier
66+
.fillMaxSize()
67+
.padding(padValues)
68+
.imePadding(),
69+
) {
70+
AndroidView(
71+
modifier = Modifier.weight(1f),
72+
factory = {
73+
WebView(it).apply {
74+
layoutParams = ViewGroup.LayoutParams(
75+
ViewGroup.LayoutParams.MATCH_PARENT,
76+
ViewGroup.LayoutParams.MATCH_PARENT,
77+
)
78+
settings.javaScriptEnabled = true
79+
webViewClient = object : WebViewClient() {
80+
private val redirectedUrls = mutableSetOf<String>()
81+
82+
override fun onPageFinished(
83+
view: WebView?,
84+
url: String?,
85+
) {
86+
if (!isTokenSet) {
87+
view?.evaluateJavascript(
88+
"window.setAuthToken('${uiState.accessToken}', '${uiState.refreshToken}')",
89+
null,
90+
)
91+
isTokenSet = true
92+
}
93+
}
94+
95+
override fun doUpdateVisitedHistory(
96+
view: WebView?,
97+
url: String?,
98+
isReload: Boolean,
99+
) {
100+
super.doUpdateVisitedHistory(view, url, isReload)
101+
102+
if (url == null || isReload || redirectedUrls.contains(url)) return
103+
104+
if (url.contains("theme=")) {
105+
return
106+
}
107+
108+
if (url.contains("/volunteer")) {
109+
val separator = if (url.contains("?")) "&" else "?"
110+
val urlWithTheme = "$url${separator}theme=$theme"
111+
112+
redirectedUrls.add(urlWithTheme)
113+
view?.loadUrl(urlWithTheme)
114+
}
115+
}
116+
}
117+
loadUrl("${BuildConfig.TERMS_URL}volunteer/application?theme=$theme")
118+
}
119+
},
120+
)
121+
}
122+
}
123+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package team.aliens.dms.android.feature.volunteers
2+
3+
import androidx.compose.runtime.Immutable
4+
import dagger.hilt.android.lifecycle.HiltViewModel
5+
import team.aliens.dms.android.core.jwt.AccessToken
6+
import team.aliens.dms.android.core.jwt.RefreshToken
7+
import team.aliens.dms.android.core.jwt.datastore.JwtDataStoreDataSource
8+
import team.aliens.dms.android.core.ui.mvi.BaseMviViewModel
9+
import team.aliens.dms.android.core.ui.mvi.Intent
10+
import team.aliens.dms.android.core.ui.mvi.SideEffect
11+
import team.aliens.dms.android.core.ui.mvi.UiState
12+
import javax.inject.Inject
13+
14+
@HiltViewModel
15+
class VolunteersViewModel @Inject constructor(
16+
private val jwtDataStoreDataSource: JwtDataStoreDataSource,
17+
) : BaseMviViewModel<VolunteersState, VolunteersIntent, VolunteersSideEffect>(
18+
initialState = VolunteersState.initial(),
19+
) {
20+
init {
21+
loadToken()
22+
}
23+
24+
private fun loadToken() {
25+
reduce(
26+
newState = stateFlow.value.copy(
27+
accessToken = jwtDataStoreDataSource.loadTokens().accessToken,
28+
refreshToken = jwtDataStoreDataSource.loadTokens().refreshToken,
29+
),
30+
)
31+
}
32+
}
33+
34+
@Immutable
35+
data class VolunteersState(
36+
val accessToken: AccessToken?,
37+
val refreshToken: RefreshToken?,
38+
) : UiState() {
39+
companion object {
40+
fun initial() = VolunteersState(
41+
accessToken = null,
42+
refreshToken = null,
43+
)
44+
}
45+
}
46+
47+
sealed class VolunteersIntent : Intent()
48+
49+
sealed class VolunteersSideEffect : SideEffect()

0 commit comments

Comments
 (0)