Skip to content

Commit

Permalink
[AN/USER] feat: 축제 상세 페이지 구현(#750) (#763)
Browse files Browse the repository at this point in the history
* feat(FestivalDetailFragment): 축제 상세 화면 생성 및 프레그먼트 기본 세팅

* feat(FestivalViewModel): FestivalDetailViewModel 생성

* refactor(FestivalItemUiState): rename StageUiState

* refactor(ArtistRepository): 가수의 축제들을 불러온다

* refactor(Stages): 복수 공연 객체 제거

* feat(FestivalDetail): 축제 상세 객체 정의

* feat(Stage): 공연 객체 생성

* feat(FestivalDetailUiState): FestivalDetailUiState 정의

* feat(StageResponse): 공연 response 객체 정의

* feat(FestivalDetailResponse): 축제 상세 Response 객체 정의

* feat(FestivalRepository): 축제 상세 조희 메서드 정의

* feat(FestivalRetrofitService): 축제 상세 조회 API 에 파라미터로 id 를 전달한다.

* feat(FestivalDetailViewModel): 축제 상세 뷰모델 작성

* feat(FestivalDetail): 축제 상세 프레그먼트 화면 작성

* feat(FestivalDetail): 축제 상세 공연 가수 화면 정의

* feat(FestivalDetail): 축제 상세 공연 화면 정의

* feat(ArtistItemUiState): 가수 uiState 정의

* feat(adapter/artist): Artist 리사이클러뷰 어댑터 및 뷰홀더 정의

* feat(adapter/stage): 공연 목록 어댑터 및 뷰홀더 정의

* refactor: 사용하지 않는 import 제거

* feat(FestivalDetailViewModel): 가수 uiState 변환 로직 추가

* feat(FestivalDetailFragment): 축제 상세 Fragment 정의

* feat(FestivalDetailFragment): Media 에 이름이 포함된다.

* feat(FestivalListEvent): 축제 목록에서 축제 상세를 보여주는 이벤트 정의

* feat(FestivalDetail): 축제 상세 디자인 수정

* feat(FestivalList): 축제 선택 시 SingleClick 으로 축제 상세를 불러온다.

* feat(FestivalDetail): 축제 이름 스타일 수정

* refactor(FestivalDetail): 가짜 축제 저장소에서 가짜 축제 상세를 분리한다

* feat(FestivalDetail): 타이틀에는 축제이름만 보인다

* feat(FakeFestival): 부경대 축제 이름 추가

* feat(item_media): 소셜 미디어 이름을 보여주지 않는다

* feat: 축제 이름 말줄임 표시 처리

* fix: 상태바 색깔 역전

* feat(FestivalDetail): 축제 상세에서 아티스트를 선택하면 아티스트 상세를 보여준다

* feat(FestivalDetail): 축제 상세의 DDay 를 보여준다

* feat(FestivalDetail): 스크롤 시 기준 선 밑으로 아이템이 사라진다

* fix(fragment): clickable true 로 클릭 중복 현상 해결

* feat(FestivalDetail): 축제 상세 dday 디자인 변경 반영
  • Loading branch information
SeongHoonC authored Mar 6, 2024
1 parent ee2cfc9 commit 8897f89
Show file tree
Hide file tree
Showing 46 changed files with 1,138 additions and 58 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.festago.festago.data.dto.festival

import com.festago.festago.data.dto.school.SchoolResponse
import com.festago.festago.data.dto.school.SocialMediaResponse
import com.festago.festago.data.dto.stage.StageResponse
import com.festago.festago.domain.model.festival.FestivalDetail
import kotlinx.serialization.Serializable
import java.time.LocalDate

@Serializable
data class FestivalDetailResponse(
val id: Long,
val name: String,
val startDate: String,
val endDate: String,
val posterImageUrl: String,
val school: SchoolResponse,
val socialMedias: List<SocialMediaResponse>,
val stages: List<StageResponse>,
) {
fun toDomain() = FestivalDetail(
id,
name,
LocalDate.parse(startDate),
LocalDate.parse(endDate),
posterImageUrl,
school.toDomain(),
socialMedias.map { it.toDomain() },
stages.map { it.toDomain() },
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package com.festago.festago.data.dto.stage

import com.festago.festago.data.dto.artist.ArtistResponse
import com.festago.festago.domain.model.stage.Stage
import kotlinx.serialization.Serializable
import java.time.LocalDateTime

@Serializable
data class StageResponse(
val id: Long,
val startDateTime: String,
val artists: List<ArtistResponse>,
) {
fun toDomain() = Stage(
id = id,
startDateTime = LocalDateTime.parse(startDateTime),
artists = artists.map { it.toDomain() },
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ package com.festago.festago.data.repository
import com.festago.festago.domain.model.artist.Artist
import com.festago.festago.domain.model.artist.ArtistDetail
import com.festago.festago.domain.model.artist.ArtistMedia
import com.festago.festago.domain.model.artist.Stages
import com.festago.festago.domain.model.festival.Festival
import com.festago.festago.domain.model.festival.FestivalsPage
import com.festago.festago.domain.model.school.School
import com.festago.festago.domain.repository.ArtistRepository
import java.time.LocalDate
Expand Down Expand Up @@ -37,11 +37,11 @@ class FakeArtistRepository @Inject constructor() : ArtistRepository {
),
)

override suspend fun loadArtistStages(id: Long, size: Int): Result<Stages> =
override suspend fun loadArtistFestivals(id: Long, size: Int): Result<FestivalsPage> =
Result.success(
Stages(
false,
(0..10).flatMap {
FestivalsPage(
isLastPage = false,
festivals = (0..10).flatMap {
listOf(
Festival(
1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package com.festago.festago.data.repository

import com.festago.festago.domain.model.artist.Artist
import com.festago.festago.domain.model.festival.Festival
import com.festago.festago.domain.model.festival.FestivalDetail
import com.festago.festago.domain.model.festival.FestivalFilter
import com.festago.festago.domain.model.festival.FestivalsPage
import com.festago.festago.domain.model.festival.PopularFestivals
Expand Down Expand Up @@ -69,11 +70,35 @@ class FakeFestivalRepository @Inject constructor() : FestivalRepository {
name = "뉴진스",
imageUrl = "https://cdn.mediatoday.co.kr/news/photo/202311/313885_438531_4716.jpg",
),
Artist(
id = 1L,
name = "BTS",
imageUrl = "https://i.namu.wiki/i/gpgJvt_C2vKJS4VA4K_Vm57Y5WoS83ofshxhJlQaT4P9Tu0N96vZ2OcdeAN7ZtRAM26UyyQs3sualkKk6i_SrRMvwVKrU015XJqzJ7wKRbOub_oUAxPSFre_8D5De3oy-fCxL0uZ-HGvsWxIX57yrw.webp",
),
Artist(
id = 2L,
name = "싸이",
imageUrl = "https://i.namu.wiki/i/VH58lI8f-y8QSoxFH9IAjjCobySN0lflZ4rMy6Un7qawUwAyi9UfeseZWCzxH-lQeZk7q_eUyTHGlZBAPqSLWliIKWYDLaAgomVtOyAQg60aCpF3oNTBOgUe_hig3rbHW-YAgoj95Fww3MCToyM6MA.webp",
),
Artist(
id = 10L,
name = "마마무",
imageUrl = "https://i.namu.wiki/i/Mre8tXnE40mB9_UwXIwASMEAUSVhHvyjJxXq-lQo40C3bLWYfxXBeai8t6TugyomPjFgxL3VfDA2zn65HlzqPXgTKlvdRl1gJ6PGZLxYYk8Uhk8L6va7zm_etSK5UzVLE56fUATqUCq-6tRQXigmYQ.webp",
),
Artist(
id = 11L,
name = "블랙핑크",
imageUrl = "https://i.namu.wiki/i/VZxRYO8_CXa2QbOSZgttDq5ue5QEu_Fbk1Lwo3qpasLAfS802YExcnmVmDhCq3ONF0ExzhACz_YkZbxOGmIfjuPDZnFo7i0pWaT05NluHRHGfp9NqsAT6WBNb0k5KecOyDvakXk0VH2fUo4ojSwC6g.webp",
),
),
)
}
}

override suspend fun loadFestivalDetail(id: Long): Result<FestivalDetail> {
return Result.success(FakeFestivals.festivalDetail)
}

companion object {
private const val LAST_ITEM_ID = 27L
private const val DEFAULT_SIZE = 10
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,155 @@ package com.festago.festago.data.repository

import com.festago.festago.domain.model.artist.Artist
import com.festago.festago.domain.model.festival.Festival
import com.festago.festago.domain.model.festival.FestivalDetail
import com.festago.festago.domain.model.school.School
import com.festago.festago.domain.model.social.SocialMedia
import com.festago.festago.domain.model.stage.Stage
import java.time.LocalDate
import java.time.LocalDateTime

object FakeFestivals {

val festivalDetail = FestivalDetail(
id = 1L,
name = "부경대 대동제",
startDate = LocalDate.now().plusDays(7L),
endDate = LocalDate.now().plusDays(10L),
posterImageUrl = "https://mblogthumb-phinf.pstatic.net/MjAyMzA1MjNfMTMx/MDAxNjg0ODIwNzY5NzQ5.MuYItN1HCOQUcADB6B7ua0SO9Au_QNNk01-6yZkcTH0g.wxSjluY-Glq20JIojs7OuScLQWh6c_sQsoW5xXqiM7Ag.JPEG.chummilmil99/SE-126908ba-0f82-4903-91c5-695db78a98e9.jpg?type=w800",
school = School(id = 2L, name = "부경대학교", imageUrl = ""),
socialMedias = listOf(
SocialMedia(
type = "INSTAGRAM",
name = "총학생회 인스타그램",
logoUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e7/Instagram_logo_2016.svg/2048px-Instagram_logo_2016.svg.png",
url = "https://www.instagram.com/25th_solution/",
),
SocialMedia(
type = "FACEBOOK",
name = "총학생회 페이스북",
logoUrl = "https://upload.wikimedia.org/wikipedia/commons/thumb/5/51/Facebook_f_logo_%282019%29.svg/1200px-Facebook_f_logo_%282019%29.svg.png",
url = "https://www.facebook.com/23rdemotion/",
),
),
stages = listOf(
Stage(
id = 1L,
startDateTime = LocalDateTime.now().plusDays(0L),
artists = listOf(
Artist(
id = 1L,
name = "BTS",
imageUrl = "https://i.namu.wiki/i/gpgJvt_C2vKJS4VA4K_Vm57Y5WoS83ofshxhJlQaT4P9Tu0N96vZ2OcdeAN7ZtRAM26UyyQs3sualkKk6i_SrRMvwVKrU015XJqzJ7wKRbOub_oUAxPSFre_8D5De3oy-fCxL0uZ-HGvsWxIX57yrw.webp",
),
Artist(
id = 2L,
name = "싸이",
imageUrl = "https://i.namu.wiki/i/VH58lI8f-y8QSoxFH9IAjjCobySN0lflZ4rMy6Un7qawUwAyi9UfeseZWCzxH-lQeZk7q_eUyTHGlZBAPqSLWliIKWYDLaAgomVtOyAQg60aCpF3oNTBOgUe_hig3rbHW-YAgoj95Fww3MCToyM6MA.webp",
),
Artist(
id = 10L,
name = "마마무",
imageUrl = "https://i.namu.wiki/i/Mre8tXnE40mB9_UwXIwASMEAUSVhHvyjJxXq-lQo40C3bLWYfxXBeai8t6TugyomPjFgxL3VfDA2zn65HlzqPXgTKlvdRl1gJ6PGZLxYYk8Uhk8L6va7zm_etSK5UzVLE56fUATqUCq-6tRQXigmYQ.webp",
),
Artist(
id = 11L,
name = "블랙핑크",
imageUrl = "https://i.namu.wiki/i/VZxRYO8_CXa2QbOSZgttDq5ue5QEu_Fbk1Lwo3qpasLAfS802YExcnmVmDhCq3ONF0ExzhACz_YkZbxOGmIfjuPDZnFo7i0pWaT05NluHRHGfp9NqsAT6WBNb0k5KecOyDvakXk0VH2fUo4ojSwC6g.webp",
),
Artist(
id = 4L,
name = "AKMU",
imageUrl = "https://i.namu.wiki/i/7yRF8Yrk9kdQxzETNO8TQp9jJpQENVUGbj-4YwB-xdVmJWoTAY7MgVA6G72Z-xmunPG0Zd3WTN_EsTwsx7oNFIO-yl0nHmaIU-ZRCpyhzVE5L9y8Sb9gkAKVt_jZBtgvVrOjw1UQq32gQsYaoS1jsg.webp",
),
),
),
Stage(
id = 2L,
startDateTime = LocalDateTime.now().plusDays(1L),
artists = listOf(
Artist(
id = 3L,
name = "아이유",
imageUrl = "https://i.namu.wiki/i/-GuxB5nI9Q-a5W_nAJEapwdUzCLyFShWJfmUfZk04cW_fFC485TRD6UlzGQCBnFpJegXBaa4WO-PThNom_7wlosOiXgb-k3-wgUr3PkyX89PU3RCschmgQ0FmS1ClOK3ph4ztAd55YWWlhk7Gm114w.webp",
),
Artist(
id = 5L,
name = "뉴진스",
imageUrl = "https://i.namu.wiki/i/GdMUzQlsrAXyF5zlgqRR0lYvAGnFghBbLxqTZK_mzLvV0LYPNQdaak1ezYtKqSNBA7UaINkrMNqncRkxThI8j2IEk2qcXJ3bLqIllRexenai641g-uvxCxFcDa9doCy0kTnMLEp5gad8Ze2fLDDBvg.webp",
),
Artist(
id = 6L,
name = "비비",
imageUrl = "https://i.namu.wiki/i/JlXBTAah7fOILgmvAQf5bW4yWbS082qw6XtV36g4a-2g5TrwTRaUf95r1YnEYi6dt_rf3o9YuRN2qVl0pdgIW5d6-DeYg67KwaSrqu3_MkUwQItlsrSLqDjm1G0jW-Z5mzQ2aOTU4ZvyE1hpSokIOA.webp",
),
),
),
Stage(
id = 3L,
startDateTime = LocalDateTime.now().plusDays(2L),
artists = listOf(
Artist(
id = 7L,
name = "TWS",
imageUrl = "https://i.namu.wiki/i/rVwKhMepUc-b-hRa2Nc6mIJRO0eTfgxyAEwVS5XfADNRhQhYJdSg8ke3o6VZd3rLyNasMlGjuXJWqHDoD_Z24o3dBzkaf7gqhCc89XoCKOiII4P-eilx46XHOOTfd2eaonCVNQevsAVl0l5WIWaI5Q.webp",
),
Artist(
id = 8L,
name = "소녀시대",
imageUrl = "https://i.namu.wiki/i/snftu-N6Op26hU4HITlraWW6Q_WiSXqhRX2NOhQadzI81RPC7054_mi-evsqRTdRe9nKcBEF-Ugji4vtWunmtiEY1v319tHhIVestCkcSJ0MZF6KbKOScoDjOypW7WPa58goYA-vX5D8baIa2UYFZg.webp",
),
Artist(
id = 9L,
name = "르세라핌",
imageUrl = "https://i.namu.wiki/i/Zbm1DseL0fjSd9H2uLrfL9SpBLPYQe7j4S9BPI2wdTw9G_Gykifyw-Nil8yVZglxxW-CRQt15b-tMdrvfuUiSW9mm2ZEBf8sQQQgp9wZmZhe8neg_5A6ehJ6hYLATAqvnOw157aODDq4qU1J-kv-bA.webp",
),
),
),
Stage(
id = 4L,
startDateTime = LocalDateTime.now().plusDays(3L),
artists = listOf(
Artist(
id = 7L,
name = "TWS",
imageUrl = "https://i.namu.wiki/i/rVwKhMepUc-b-hRa2Nc6mIJRO0eTfgxyAEwVS5XfADNRhQhYJdSg8ke3o6VZd3rLyNasMlGjuXJWqHDoD_Z24o3dBzkaf7gqhCc89XoCKOiII4P-eilx46XHOOTfd2eaonCVNQevsAVl0l5WIWaI5Q.webp",
),
Artist(
id = 8L,
name = "소녀시대",
imageUrl = "https://i.namu.wiki/i/snftu-N6Op26hU4HITlraWW6Q_WiSXqhRX2NOhQadzI81RPC7054_mi-evsqRTdRe9nKcBEF-Ugji4vtWunmtiEY1v319tHhIVestCkcSJ0MZF6KbKOScoDjOypW7WPa58goYA-vX5D8baIa2UYFZg.webp",
),
Artist(
id = 9L,
name = "르세라핌",
imageUrl = "https://i.namu.wiki/i/Zbm1DseL0fjSd9H2uLrfL9SpBLPYQe7j4S9BPI2wdTw9G_Gykifyw-Nil8yVZglxxW-CRQt15b-tMdrvfuUiSW9mm2ZEBf8sQQQgp9wZmZhe8neg_5A6ehJ6hYLATAqvnOw157aODDq4qU1J-kv-bA.webp",
),
),
),
Stage(
id = 5L,
startDateTime = LocalDateTime.now().plusDays(4L),
artists = listOf(
Artist(
id = 7L,
name = "TWS",
imageUrl = "https://i.namu.wiki/i/rVwKhMepUc-b-hRa2Nc6mIJRO0eTfgxyAEwVS5XfADNRhQhYJdSg8ke3o6VZd3rLyNasMlGjuXJWqHDoD_Z24o3dBzkaf7gqhCc89XoCKOiII4P-eilx46XHOOTfd2eaonCVNQevsAVl0l5WIWaI5Q.webp",
),
Artist(
id = 8L,
name = "소녀시대",
imageUrl = "https://i.namu.wiki/i/snftu-N6Op26hU4HITlraWW6Q_WiSXqhRX2NOhQadzI81RPC7054_mi-evsqRTdRe9nKcBEF-Ugji4vtWunmtiEY1v319tHhIVestCkcSJ0MZF6KbKOScoDjOypW7WPa58goYA-vX5D8baIa2UYFZg.webp",
),
Artist(
id = 9L,
name = "르세라핌",
imageUrl = "https://i.namu.wiki/i/Zbm1DseL0fjSd9H2uLrfL9SpBLPYQe7j4S9BPI2wdTw9G_Gykifyw-Nil8yVZglxxW-CRQt15b-tMdrvfuUiSW9mm2ZEBf8sQQQgp9wZmZhe8neg_5A6ehJ6hYLATAqvnOw157aODDq4qU1J-kv-bA.webp",
),
),
),
),
)

val progressFestivals = listOf(
Festival(
id = 1,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.festago.festago.data.repository
import com.festago.festago.data.service.FestivalRetrofitService
import com.festago.festago.data.util.onSuccessOrCatch
import com.festago.festago.data.util.runCatchingResponse
import com.festago.festago.domain.model.festival.FestivalDetail
import com.festago.festago.domain.model.festival.FestivalFilter
import com.festago.festago.domain.model.festival.FestivalsPage
import com.festago.festago.domain.model.festival.PopularFestivals
Expand Down Expand Up @@ -38,4 +39,10 @@ class FestivalDefaultRepository @Inject constructor(
)
}.onSuccessOrCatch { it.toDomain() }
}

override suspend fun loadFestivalDetail(id: Long): Result<FestivalDetail> {
return runCatchingResponse {
festivalRetrofitService.getFestivalDetail(id)
}.onSuccessOrCatch { it.toDomain() }
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package com.festago.festago.data.service

import com.festago.festago.data.dto.festival.FestivalDetailResponse
import com.festago.festago.data.dto.festival.FestivalsResponse
import com.festago.festago.data.dto.festival.PopularFestivalsResponse
import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.Path
import retrofit2.http.Query
import java.time.LocalDate

Expand All @@ -19,4 +21,9 @@ interface FestivalRetrofitService {
@Query("lastStartDate") lastStartDate: LocalDate?,
@Query("size") size: Int?,
): Response<FestivalsResponse>

@GET("api/v1/festivals/{festivalId}")
suspend fun getFestivalDetail(
@Path("festivalId") festivalId: Long,
): Response<FestivalDetailResponse>
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package com.festago.festago.domain.model.festival

import com.festago.festago.domain.model.school.School
import com.festago.festago.domain.model.social.SocialMedia
import com.festago.festago.domain.model.stage.Stage
import java.time.LocalDate

data class FestivalDetail(
val id: Long,
val name: String,
val startDate: LocalDate,
val endDate: LocalDate,
val posterImageUrl: String,
val school: School,
val socialMedias: List<SocialMedia>,
val stages: List<Stage>,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package com.festago.festago.domain.model.stage

import com.festago.festago.domain.model.artist.Artist
import java.time.LocalDateTime

class Stage(
val id: Long,
val startDateTime: LocalDateTime,
val artists: List<Artist>,
)
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
package com.festago.festago.domain.repository

import com.festago.festago.domain.model.artist.ArtistDetail
import com.festago.festago.domain.model.artist.Stages
import com.festago.festago.domain.model.festival.FestivalsPage

interface ArtistRepository {
suspend fun loadArtistDetail(id: Long): Result<ArtistDetail>

suspend fun loadArtistStages(id: Long, size: Int): Result<Stages>
suspend fun loadArtistFestivals(id: Long, size: Int): Result<FestivalsPage>
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.festago.festago.domain.repository

import com.festago.festago.domain.model.festival.FestivalDetail
import com.festago.festago.domain.model.festival.FestivalFilter
import com.festago.festago.domain.model.festival.FestivalsPage
import com.festago.festago.domain.model.festival.PopularFestivals
Expand All @@ -15,4 +16,6 @@ interface FestivalRepository {
lastStartDate: LocalDate? = null,
size: Int? = null,
): Result<FestivalsPage>

suspend fun loadFestivalDetail(id: Long): Result<FestivalDetail>
}
Loading

0 comments on commit 8897f89

Please sign in to comment.