Skip to content

Commit

Permalink
feat: 도서관 남은 좌석 UI 로직 (#403)
Browse files Browse the repository at this point in the history
* [추가] 잔여좌석화면 전환용 배너 추가

* [수정] api 쿼리파라미터 수정

* [수정] 상태창 패딩 추가

* [제거] 주석 코드 삭제

* [추가] 뷰모델 추가 및 레포지토리 연결

* [추가] 도서관 앱 이동 로직 추가

* [수정] 도서관 잔여좌석 오류UI 수정

* [수정] 폰트 수정

* [수정] StateFlow 선언 수정

* [수정] indicator 패키지 이름

* [수정] PagingLoadingIndicator 컴포넌트화

* [삭제] 미사용 라이브러리 삭제

* [추가] 패키지 에러 크래시리틱

* [수정] 공백 제거
  • Loading branch information
boiledEgg-s authored Feb 5, 2025
1 parent 40b39a8 commit 1ca09b1
Show file tree
Hide file tree
Showing 21 changed files with 471 additions and 135 deletions.
4 changes: 4 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@
android:name="android.permission.WRITE_EXTERNAL_STORAGE"
android:maxSdkVersion="28" />

<queries>
<package android:name="kr.ac.kku.library" />
</queries>

<application
android:name="com.ku_stacks.ku_ring.KuRingApplication"
android:allowBackup="false"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package com.ku_stacks.ku_ring.designsystem.components

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.Divider
import androidx.compose.material.Text
import androidx.compose.runtime.Composable
Expand All @@ -20,6 +23,7 @@ import androidx.paging.compose.LazyPagingItems
import androidx.paging.compose.itemContentType
import androidx.paging.compose.itemKey
import com.ku_stacks.ku_ring.designsystem.R
import com.ku_stacks.ku_ring.designsystem.components.indicator.PagingLoadingIndicator
import com.ku_stacks.ku_ring.designsystem.kuringtheme.KuringTheme
import com.ku_stacks.ku_ring.designsystem.kuringtheme.values.SfProDisplay
import com.ku_stacks.ku_ring.domain.Notice
Expand Down Expand Up @@ -84,16 +88,6 @@ fun LazyPagingNoticeItemColumn(
}
}

@Composable
private fun PagingLoadingIndicator(modifier: Modifier = Modifier) {
Box(modifier = modifier) {
CircularProgressIndicator(
color = colorResource(id = R.color.kus_green),
modifier = Modifier.align(Alignment.Center),
)
}
}

@Composable
private fun LoadingErrorText(modifier: Modifier = Modifier) {
Box(modifier = modifier) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.ku_stacks.ku_ring.designsystem.components.pager_indicator
package com.ku_stacks.ku_ring.designsystem.components.indicator

import androidx.compose.foundation.ExperimentalFoundationApi
import androidx.compose.foundation.background
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.ku_stacks.ku_ring.designsystem.components.indicator

import androidx.compose.foundation.layout.Box
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.colorResource
import androidx.compose.material.CircularProgressIndicator
import com.ku_stacks.ku_ring.designsystem.R

@Composable
fun PagingLoadingIndicator(modifier: Modifier = Modifier) {
Box(modifier = modifier) {
CircularProgressIndicator(
color = colorResource(id = R.color.kus_green),
modifier = Modifier.align(Alignment.Center),
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.material.Icon
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
Expand All @@ -32,6 +33,7 @@ fun NavigateUpTopBar(
) {
Row(
modifier = modifier
.statusBarsPadding()
.background(KuringTheme.colors.background)
.padding(start = 20.dp, top = 18.dp, bottom = 21.dp),
verticalAlignment = Alignment.CenterVertically,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ class LibraryClient @Inject constructor(private val libraryService: LibraryServi
suspend fun fetchRoomSeatStatus(): LibrarySeatResponse = libraryService.fetchLibrarySeatStatus(
methodCode = LibrarySeatRequest.METHOD_CODE,
roomTypeId = LibrarySeatRequest.ROOM_TYPE_ID,
branchTypeId = LibrarySeatRequest.BRANCH_TYPE_ID,
branchGroupId = LibrarySeatRequest.BRANCH_GROUP_ID,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ interface LibraryService {
suspend fun fetchLibrarySeatStatus(
@Query("smufMethodCode") methodCode: String,
@Query("roomTypeId") roomTypeId: Int,
@Query("branchTypeId") branchTypeId: Int,
@Query("branchGroupId") branchGroupId: Int,
): LibrarySeatResponse
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ package com.ku_stacks.ku_ring.remote.library.request
object LibrarySeatRequest {
const val METHOD_CODE: String = "PC"
const val ROOM_TYPE_ID = 4
const val BRANCH_TYPE_ID: Int = 1
const val BRANCH_GROUP_ID: Int = 1
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class LibraryServiceTest : ApiAbstract<LibraryService>() {
val response = service.fetchLibrarySeatStatus(
methodCode = "PC",
roomTypeId = 4,
branchTypeId = 1,
branchGroupId = 1,
)
mockWebServer.takeRequest()

Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
package com.ku_stacks.ku_ring.library

import android.content.Context
import android.app.Activity
import android.content.ActivityNotFoundException
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.widget.Toast
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
Expand All @@ -11,29 +16,103 @@ import androidx.compose.ui.Modifier
import com.ku_stacks.ku_ring.designsystem.kuringtheme.KuringTheme
import com.ku_stacks.ku_ring.library.compose.LibrarySeatScreen
import dagger.hilt.android.AndroidEntryPoint
import timber.log.Timber

@AndroidEntryPoint
class LibrarySeatActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()

setContent {
KuringTheme {
LibrarySeatScreen(
onBackButtonClick = ::finish,
onReservationButtonClick = {},
onNavigateBack = ::finish,
onLaunchLibraryIntent = ::launchLibrary,
modifier = Modifier.fillMaxSize()
)
}
}
}

override fun finish() {
super.finish()
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
overrideActivityTransition(
OVERRIDE_TRANSITION_CLOSE,
R.anim.anim_slide_left_enter,
R.anim.anim_slide_left_exit
)
} else {
overridePendingTransition(R.anim.anim_slide_left_enter, R.anim.anim_slide_left_exit)
}
}

private fun launchLibrary() {
try {
checkKonkukLibraryInstalled()
launchKonkukLibrary()
} catch (e: PackageManager.NameNotFoundException) {
launchPlayStore()
}
}

private fun checkKonkukLibraryInstalled() {
try {
val packageManager = this.packageManager
packageManager.getPackageInfo(
KU_LIBRARY_PACKAGE_NAME,
PackageManager.MATCH_UNINSTALLED_PACKAGES
)
} catch (e: PackageManager.NameNotFoundException) {
Timber.e("PackageManager could not find $KU_LIBRARY_PACKAGE_NAME: $e")
throw e
}
}

private fun launchKonkukLibrary() {
try {
val intent = Intent().apply {
setClassName(KU_LIBRARY_PACKAGE_NAME, KU_LIBRARY_CLASS_NAME)
}
startActivity(intent)
} catch (e: ActivityNotFoundException) {
Toast.makeText(this, MESSAGE_APP_NOT_FOUND, Toast.LENGTH_SHORT).show()
}
}

private fun launchPlayStore() {
try {
val playStoreIntent = Intent(Intent.ACTION_VIEW).apply {
data = Uri.parse(KU_LIBRARY_STORE_URI)
}
startActivity(playStoreIntent)
} catch (e: ActivityNotFoundException) {
Toast.makeText(this, MESSAGE_APP_NOT_FOUND, Toast.LENGTH_SHORT).show()
}
}


companion object {
fun start(context: Context) {
val intent = Intent(context, LibrarySeatActivity::class.java)
context.startActivity(intent)
fun start(activity: Activity) {
with(activity) {
val intent = Intent(this, LibrarySeatActivity::class.java)
startActivity(intent)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
overrideActivityTransition(
OVERRIDE_TRANSITION_OPEN,
R.anim.anim_slide_right_enter,
R.anim.anim_stay_exit
)
} else {
overridePendingTransition(R.anim.anim_slide_right_enter, R.anim.anim_stay_exit)
}
}
}

private const val KU_LIBRARY_PACKAGE_NAME = "kr.ac.kku.library"
private const val KU_LIBRARY_CLASS_NAME = "kr.ac.kku.library.MainActivity"
private const val KU_LIBRARY_STORE_URI = "market://details?id=$KU_LIBRARY_PACKAGE_NAME"
private const val MESSAGE_APP_NOT_FOUND = "도서관 앱을 찾을 수 없습니다."
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.ku_stacks.ku_ring.library

import com.ku_stacks.ku_ring.domain.LibraryRoom

data class LibrarySeatUiState(
val isLoading: Boolean,
val loadState: SeatLoadState,
){
companion object {
val Empty = LibrarySeatUiState(
isLoading = false,
loadState = SeatLoadState.InitialLoading,
)
}
}

sealed interface SeatLoadState {
data object InitialLoading : SeatLoadState
data object Error : SeatLoadState
data class Success(val rooms: List<LibraryRoom>) : SeatLoadState
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.ku_stacks.ku_ring.library

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.ku_stacks.ku_ring.library.repository.LibraryRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import javax.inject.Inject

@HiltViewModel
class LibrarySeatViewModel @Inject constructor(
private val libraryRepository: LibraryRepository,
) : ViewModel() {

private val _uiState = MutableStateFlow(LibrarySeatUiState.Empty)
val uiState = _uiState.asStateFlow()

fun getLibrarySeatStatus() = viewModelScope.launch {
updateIsLoading(true)

libraryRepository.getRemainingSeats()
.onSuccess { rooms ->
if (rooms.isNotEmpty()) {
updateLoadState(SeatLoadState.Success(rooms))
}
}.onFailure {
updateLoadState(SeatLoadState.Error)
}
}

private fun updateIsLoading(isLoading: Boolean) = _uiState.update { currentState ->
currentState.copy(
isLoading = isLoading
)
}

private fun updateLoadState(loadState: SeatLoadState) {
_uiState.update { currentState ->
currentState.copy(
loadState = loadState,
isLoading = false
)
}
}
}
Loading

0 comments on commit 1ca09b1

Please sign in to comment.