diff --git a/android/2023-emmsale/app/src/main/AndroidManifest.xml b/android/2023-emmsale/app/src/main/AndroidManifest.xml
index ce1c2c0e9..8b4736320 100644
--- a/android/2023-emmsale/app/src/main/AndroidManifest.xml
+++ b/android/2023-emmsale/app/src/main/AndroidManifest.xml
@@ -33,7 +33,7 @@
android:name=".presentation.ui.onboarding.OnboardingActivity"
android:exported="true" />
,
- val imageUrl: String?,
+ val postImageUrl: String?,
val remainingDays: Int,
val type: String,
)
diff --git a/android/2023-emmsale/app/src/main/java/com/emmsale/data/eventdetail/EventDetailRepository.kt b/android/2023-emmsale/app/src/main/java/com/emmsale/data/eventdetail/EventDetailRepository.kt
index ecef11dd1..90cece3ec 100644
--- a/android/2023-emmsale/app/src/main/java/com/emmsale/data/eventdetail/EventDetailRepository.kt
+++ b/android/2023-emmsale/app/src/main/java/com/emmsale/data/eventdetail/EventDetailRepository.kt
@@ -3,5 +3,5 @@ package com.emmsale.data.eventdetail
import com.emmsale.data.common.ApiResult
interface EventDetailRepository {
- suspend fun fetchEventDetail(eventId: Long): ApiResult
+ suspend fun getEventDetail(eventId: Long): ApiResult
}
diff --git a/android/2023-emmsale/app/src/main/java/com/emmsale/data/eventdetail/EventDetailRepositoryImpl.kt b/android/2023-emmsale/app/src/main/java/com/emmsale/data/eventdetail/EventDetailRepositoryImpl.kt
index bda92aa37..ecf0202a9 100644
--- a/android/2023-emmsale/app/src/main/java/com/emmsale/data/eventdetail/EventDetailRepositoryImpl.kt
+++ b/android/2023-emmsale/app/src/main/java/com/emmsale/data/eventdetail/EventDetailRepositoryImpl.kt
@@ -3,14 +3,15 @@ package com.emmsale.data.eventdetail
import com.emmsale.data.common.ApiResult
import com.emmsale.data.common.handleApi
import com.emmsale.data.eventdetail.dto.EventDetailApiModel
+import com.emmsale.data.eventdetail.mapper.toData
class EventDetailRepositoryImpl(
private val eventDetailService: EventDetailService,
) : EventDetailRepository {
- override suspend fun fetchEventDetail(eventId: Long): ApiResult {
+ override suspend fun getEventDetail(eventId: Long): ApiResult {
return handleApi(
- execute = { eventDetailService.fetchEventDetail(eventId) },
+ execute = { eventDetailService.getEventDetail(eventId) },
mapToDomain = EventDetailApiModel::toData,
)
}
diff --git a/android/2023-emmsale/app/src/main/java/com/emmsale/data/eventdetail/EventDetailService.kt b/android/2023-emmsale/app/src/main/java/com/emmsale/data/eventdetail/EventDetailService.kt
index 4bbb2cc74..8cc535c06 100644
--- a/android/2023-emmsale/app/src/main/java/com/emmsale/data/eventdetail/EventDetailService.kt
+++ b/android/2023-emmsale/app/src/main/java/com/emmsale/data/eventdetail/EventDetailService.kt
@@ -7,7 +7,7 @@ import retrofit2.http.Path
interface EventDetailService {
@GET("events/{eventId}")
- suspend fun fetchEventDetail(
+ suspend fun getEventDetail(
@Path("eventId") eventId: Long,
): Response
}
diff --git a/android/2023-emmsale/app/src/main/java/com/emmsale/data/eventdetail/dto/EventDetailApiModel.kt b/android/2023-emmsale/app/src/main/java/com/emmsale/data/eventdetail/dto/EventDetailApiModel.kt
index 7f4445883..9e05a2909 100644
--- a/android/2023-emmsale/app/src/main/java/com/emmsale/data/eventdetail/dto/EventDetailApiModel.kt
+++ b/android/2023-emmsale/app/src/main/java/com/emmsale/data/eventdetail/dto/EventDetailApiModel.kt
@@ -1,6 +1,5 @@
package com.emmsale.data.eventdetail.dto
-import com.emmsale.data.eventdetail.EventDetail
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@@ -10,36 +9,30 @@ data class EventDetailApiModel(
val id: Long,
@SerialName("name")
val name: String,
- @SerialName("status")
- val status: String,
- @SerialName("location")
- val location: String,
+ @SerialName("informationUrl")
+ val informationUrl: String,
@SerialName("startDate")
val startDate: String,
@SerialName("endDate")
val endDate: String,
- @SerialName("informationUrl")
- val informationUrl: String,
+ @SerialName("applyStartDate")
+ val applyStartDate: String,
+ @SerialName("applyEndDate")
+ val applyEndDate: String,
+ @SerialName("location")
+ val location: String,
+ @SerialName("status")
+ val status: String,
+ @SerialName("applyStatus")
+ val applyStatus: String,
@SerialName("tags")
val tags: List,
@SerialName("imageUrl")
val imageUrl: String?,
@SerialName("remainingDays")
val remainingDays: Int,
+ @SerialName("applyRemainingDays")
+ val applyRemainingDays: Int,
@SerialName("type")
val type: String,
-) {
- fun toData(): EventDetail = EventDetail(
- id = id,
- name = name,
- status = status,
- location = location,
- startDate = startDate,
- endDate = endDate,
- informationUrl = informationUrl,
- tags = tags,
- imageUrl = imageUrl,
- remainingDays = remainingDays,
- type = type,
- )
-}
+)
diff --git a/android/2023-emmsale/app/src/main/java/com/emmsale/data/eventdetail/mapper/EventDetailMapper.kt b/android/2023-emmsale/app/src/main/java/com/emmsale/data/eventdetail/mapper/EventDetailMapper.kt
new file mode 100644
index 000000000..515a54a1b
--- /dev/null
+++ b/android/2023-emmsale/app/src/main/java/com/emmsale/data/eventdetail/mapper/EventDetailMapper.kt
@@ -0,0 +1,25 @@
+package com.emmsale.data.eventdetail.mapper
+
+import com.emmsale.data.eventdetail.EventDetail
+import com.emmsale.data.eventdetail.dto.EventDetailApiModel
+import java.time.LocalDateTime
+import java.time.format.DateTimeFormatter
+
+fun EventDetailApiModel.toData(): EventDetail = EventDetail(
+ id = id,
+ name = name,
+ status = status,
+ location = location,
+ startDate = startDate.toLocalDateTime(),
+ endDate = endDate.toLocalDateTime(),
+ informationUrl = informationUrl,
+ tags = tags,
+ postImageUrl = imageUrl,
+ remainingDays = remainingDays,
+ type = type,
+)
+
+private fun String.toLocalDateTime(): LocalDateTime {
+ val format = DateTimeFormatter.ofPattern("yyyy:MM:dd:HH:mm:ss")
+ return LocalDateTime.parse(this, format)
+}
diff --git a/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/ui/eventdetail/EventDetailActivity.kt b/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/ui/eventdetail/EventDetailActivity.kt
index e1f1d7652..1555b1299 100644
--- a/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/ui/eventdetail/EventDetailActivity.kt
+++ b/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/ui/eventdetail/EventDetailActivity.kt
@@ -1,51 +1,45 @@
-package com.emmsale.presentation.eventdetail
+package com.emmsale.presentation.ui.eventdetail
import android.content.Context
import android.content.Intent
import android.os.Bundle
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
+import com.emmsale.R
import com.emmsale.databinding.ActivityEventDetailBinding
import com.emmsale.presentation.common.extension.showToast
-import com.emmsale.presentation.ui.eventdetail.EventDetailFragmentStateAdpater
-import com.emmsale.presentation.ui.eventdetail.EventDetailViewModel
-import com.emmsale.presentation.ui.eventdetail.EventTag
-import com.emmsale.presentation.ui.eventdetail.uistate.EventDetailUiState
import com.google.android.material.tabs.TabLayoutMediator
class EventDetailActivity : AppCompatActivity() {
private lateinit var binding: ActivityEventDetailBinding
- private val viewModel: EventDetailViewModel by viewModels { EventDetailViewModel.factory }
private val eventId: Long by lazy {
intent.getLongExtra(EVENT_ID_KEY, DEFAULT_EVENT_ID)
}
-
+ private val viewModel: EventDetailViewModel by viewModels { EventDetailViewModel.factory(eventId) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setUpBinding()
setUpEventDetail()
- setBackPress()
- viewModel.fetchEventDetail(eventId)
+ initBackPressButtonClickListener()
}
private fun setUpBinding() {
binding = ActivityEventDetailBinding.inflate(layoutInflater)
setContentView(binding.root)
+ binding.lifecycleOwner = this
+ binding.vm = viewModel
}
private fun setUpEventDetail() {
viewModel.eventDetail.observe(this) { eventDetailUiState ->
- when (eventDetailUiState) {
- is EventDetailUiState.Success -> {
- binding.eventDetail = eventDetailUiState
- addTag(eventDetailUiState.tags)
- initFragmentStateAdapter(
- eventDetailUiState.informationUrl,
- eventDetailUiState.imageUrl,
- )
- }
-
- else -> showToast("행사 받아오기 실패")
+ if (eventDetailUiState.isError) {
+ showToast(getString(R.string.eventdetail_fetch_eventdetail_error_message))
+ } else {
+ addEventTag(eventDetailUiState.tags)
+ initFragmentStateAdapter(
+ eventDetailUiState.informationUrl,
+ eventDetailUiState.imageUrl,
+ )
}
}
}
@@ -53,25 +47,26 @@ class EventDetailActivity : AppCompatActivity() {
private fun initFragmentStateAdapter(informationUrl: String, imageUrl: String?) {
binding.vpEventdetail.adapter =
EventDetailFragmentStateAdpater(this, eventId, informationUrl, imageUrl)
- TabLayoutMediator(binding.tablayoutEventdetail, binding.vpEventdetail) { tab, position ->
- when (position) {
- INFORMATION_TAB_POSITION -> tab.text = "상세 정보"
- COMMENT_TAB_POSITION -> tab.text = "댓글"
- RECRUITMENT_TAB_POSITION -> tab.text = "같이가요"
- }
+ val tabNames = listOf(
+ getString(R.string.eventdetail_tab_infromation),
+ getString(R.string.eventdetail_tab_comment),
+ getString(R.string.eventdetail_tab_recruitment),
+ )
+ TabLayoutMediator(binding.tablayoutEventdetail, binding.vpEventdetail) { _, _ ->
+ tabNames
}.attach()
binding.vpEventdetail.isUserInputEnabled = false
}
- private fun addTag(tags: List) {
- tags.forEach { binding.chipgroupEvendetailTags.addView(createTag(it)) }
+ private fun addEventTag(tags: List) {
+ tags.forEach { binding.chipgroupEvendetailTags.addView(createEventTag(it)) }
}
- private fun createTag(tag: String) = EventTag(this).apply {
+ private fun createEventTag(tag: String) = EventTag(this).apply {
text = tag
}
- private fun setBackPress() {
+ private fun initBackPressButtonClickListener() {
binding.ivEventdetailBackpress.setOnClickListener {
finish()
}
@@ -80,10 +75,6 @@ class EventDetailActivity : AppCompatActivity() {
companion object {
private const val EVENT_ID_KEY = "EVENT_ID_KEY"
private const val DEFAULT_EVENT_ID = 1L
- private const val INFORMATION_TAB_POSITION = 0
- private const val COMMENT_TAB_POSITION = 1
- private const val RECRUITMENT_TAB_POSITION = 2
-
fun startActivity(context: Context, eventId: Long) {
val intent = Intent(context, EventDetailActivity::class.java)
intent.putExtra(EVENT_ID_KEY, eventId)
diff --git a/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/ui/eventdetail/EventDetailViewModel.kt b/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/ui/eventdetail/EventDetailViewModel.kt
index 88bbb14d7..22cacdd47 100644
--- a/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/ui/eventdetail/EventDetailViewModel.kt
+++ b/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/ui/eventdetail/EventDetailViewModel.kt
@@ -1,47 +1,63 @@
package com.emmsale.presentation.ui.eventdetail
-import androidx.lifecycle.LiveData
-import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.emmsale.data.common.ApiError
import com.emmsale.data.common.ApiException
import com.emmsale.data.common.ApiSuccess
+import com.emmsale.data.eventdetail.EventDetail
import com.emmsale.data.eventdetail.EventDetailRepository
-import com.emmsale.data.member.MemberRepository
import com.emmsale.presentation.KerdyApplication
import com.emmsale.presentation.common.ViewModelFactory
+import com.emmsale.presentation.common.livedata.NotNullLiveData
+import com.emmsale.presentation.common.livedata.NotNullMutableLiveData
import com.emmsale.presentation.ui.eventdetail.uistate.EventDetailUiState
import kotlinx.coroutines.launch
class EventDetailViewModel(
+ private val eventId: Long,
private val eventDetailRepository: EventDetailRepository,
- private val memberRepository: MemberRepository,
) : ViewModel() {
- private val _eventDetail: MutableLiveData =
- MutableLiveData()
- val eventDetail: LiveData
- get() = _eventDetail
+ private val _eventDetail: NotNullMutableLiveData =
+ NotNullMutableLiveData(EventDetailUiState())
+ val eventDetail: NotNullLiveData = _eventDetail
- fun fetchEventDetail(id: Long) {
- viewModelScope.launch {
- when (val result = eventDetailRepository.fetchEventDetail(id)) {
- is ApiSuccess -> _eventDetail.postValue(
- EventDetailUiState.from(result.data),
- )
+ init {
+ fetchEventDetail(eventId)
+ }
- is ApiError -> _eventDetail.postValue(EventDetailUiState.Error)
- is ApiException -> _eventDetail.postValue(EventDetailUiState.Error)
+ private fun fetchEventDetail(id: Long) {
+ setLoadingState(true)
+ viewModelScope.launch {
+ when (val result = eventDetailRepository.getEventDetail(id)) {
+ is ApiSuccess -> fetchSuccessEventDetail(result.data)
+ is ApiError -> changeToErrorState()
+ is ApiException -> changeToErrorState()
}
}
}
+ private fun setLoadingState(state: Boolean) {
+ _eventDetail.value = _eventDetail.value.copy(isLoading = state)
+ }
+
+ private fun fetchSuccessEventDetail(eventDetail: EventDetail) {
+ _eventDetail.value = EventDetailUiState.from(eventDetail)
+ }
+
+ private fun changeToErrorState() {
+ _eventDetail.value = _eventDetail.value.copy(
+ isError = true,
+ isLoading = false,
+ )
+ }
+
companion object {
- val factory = ViewModelFactory {
+ fun factory(eventId: Long) = ViewModelFactory {
EventDetailViewModel(
+ eventId,
eventDetailRepository = KerdyApplication.repositoryContainer.eventDetailRepository,
- memberRepository = KerdyApplication.repositoryContainer.memberRepository,
)
}
}
diff --git a/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/ui/eventdetail/uistate/EventDetailUiState.kt b/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/ui/eventdetail/uistate/EventDetailUiState.kt
index eeb3490e0..3ed84ed43 100644
--- a/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/ui/eventdetail/uistate/EventDetailUiState.kt
+++ b/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/ui/eventdetail/uistate/EventDetailUiState.kt
@@ -1,30 +1,28 @@
package com.emmsale.presentation.ui.eventdetail.uistate
import com.emmsale.data.eventdetail.EventDetail
-import java.time.LocalDate
import java.time.LocalDateTime
-import java.time.LocalTime
import java.time.format.DateTimeFormatter
-sealed class EventDetailUiState {
- data class Success(
- val id: Long,
- val name: String,
- val status: String,
- val location: String,
- val startDate: String,
- val endDate: String,
- val informationUrl: String,
- val tags: List,
- val imageUrl: String?,
- ) : EventDetailUiState()
-
- object Error : EventDetailUiState()
+data class EventDetailUiState(
+ val id: Long = DEFAULT_ID,
+ val name: String = "",
+ val status: String = "",
+ val location: String = "",
+ val startDate: String = "",
+ val endDate: String = "",
+ val informationUrl: String = "",
+ val tags: List = listOf(),
+ val imageUrl: String = "",
+ val isError: Boolean = false,
+ val isLoading: Boolean = false,
+) {
companion object {
- fun from(eventDetail: EventDetail): Success {
+ private const val DEFAULT_ID = -1L
+ fun from(eventDetail: EventDetail): EventDetailUiState {
return with(eventDetail) {
- Success(
+ EventDetailUiState(
id = id,
name = name,
status = status,
@@ -33,21 +31,16 @@ sealed class EventDetailUiState {
endDate = getGeneralDateFormat(endDate),
informationUrl = informationUrl,
tags = tags,
- imageUrl = imageUrl,
+ imageUrl = postImageUrl ?: "",
+ isError = false,
+ isLoading = false,
)
}
}
- private fun getGeneralDateFormat(dateString: String): String {
- val formatter = DateTimeFormatter.ofPattern("yyyy:MM:dd:HH:mm:ss")
- val dateTime = LocalDateTime.parse(dateString, formatter)
-
- val targetDate = LocalDate.of(dateTime.year, dateTime.month, dateTime.dayOfMonth)
- val targetTime = LocalTime.of(dateTime.hour, dateTime.minute)
- val targetDateTime = LocalDateTime.of(targetDate, targetTime)
-
+ private fun getGeneralDateFormat(dateTime: LocalDateTime): String {
val resultFormatter = DateTimeFormatter.ofPattern("yyyy.M.d HH:mm")
- return targetDateTime.format(resultFormatter)
+ return dateTime.format(resultFormatter)
}
}
}
diff --git a/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/ui/main/event/conference/ConferenceFragment.kt b/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/ui/main/event/conference/ConferenceFragment.kt
index 6ba6990fb..677ebad06 100644
--- a/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/ui/main/event/conference/ConferenceFragment.kt
+++ b/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/ui/main/event/conference/ConferenceFragment.kt
@@ -12,7 +12,7 @@ import com.emmsale.presentation.common.extension.getSerializableExtraCompat
import com.emmsale.presentation.common.extension.showToast
import com.emmsale.presentation.common.views.FilterTag
import com.emmsale.presentation.common.views.filterChipOf
-import com.emmsale.presentation.eventdetail.EventDetailActivity
+import com.emmsale.presentation.ui.eventdetail.EventDetailActivity
import com.emmsale.presentation.ui.main.event.conference.recyclerview.ConferenceRecyclerViewAdapter
import com.emmsale.presentation.ui.main.event.conference.recyclerview.ConferenceRecyclerViewDivider
import com.emmsale.presentation.ui.main.event.conference.uistate.ConferenceItemUiState
diff --git a/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/ui/notificationBox/NotificationBoxViewModel.kt b/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/ui/notificationBox/NotificationBoxViewModel.kt
index 479f9f0e2..fe6f128db 100644
--- a/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/ui/notificationBox/NotificationBoxViewModel.kt
+++ b/android/2023-emmsale/app/src/main/java/com/emmsale/presentation/ui/notificationBox/NotificationBoxViewModel.kt
@@ -89,7 +89,7 @@ class NotificationBoxViewModel(
private suspend fun getConferenceNameAsync(conferenceId: Long): Deferred =
viewModelScope.async {
- when (val conference = eventDetailRepository.fetchEventDetail(conferenceId)) {
+ when (val conference = eventDetailRepository.getEventDetail(conferenceId)) {
is ApiSuccess -> conference.data.name
is ApiException, is ApiError -> null
}
diff --git a/android/2023-emmsale/app/src/main/res/layout/activity_event_detail.xml b/android/2023-emmsale/app/src/main/res/layout/activity_event_detail.xml
index bb8b79a85..4061ea1cd 100644
--- a/android/2023-emmsale/app/src/main/res/layout/activity_event_detail.xml
+++ b/android/2023-emmsale/app/src/main/res/layout/activity_event_detail.xml
@@ -4,10 +4,7 @@
xmlns:tools="http://schemas.android.com/tools">
-
-
+
+ tools:context=".presentation.ui.eventdetail.EventDetailActivity">
+ app:layout_constraintTop_toBottomOf="@id/tv_eventdetail_eventname" />
+
+
diff --git a/android/2023-emmsale/app/src/main/res/values/strings.xml b/android/2023-emmsale/app/src/main/res/values/strings.xml
index 1b0af8991..7737a3feb 100644
--- a/android/2023-emmsale/app/src/main/res/values/strings.xml
+++ b/android/2023-emmsale/app/src/main/res/values/strings.xml
@@ -131,4 +131,9 @@
화면을 팽창 시킵니다.
0
+
+ 이벤트를 불러올 수 없어요
+ 상세 정보
+ 댓글
+ 같이가요