Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/boolti 235 티켓 N매 구현 #261

Merged
merged 23 commits into from
Jul 7, 2024
Merged
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
df24f33
Boolti-235 feat: N매 티켓 새로운 API 연결 및 티켓 목록 UI 변경사항 반영
mangbaam Jun 9, 2024
4319abc
Boolti-235 feat: 인스타그램 인디케이터 작성 (보수 필요)
mangbaam Jun 16, 2024
84e3117
Boolti-235 feat: 티켓 상세에 N매 티켓 반영
mangbaam Jun 16, 2024
776f308
Boolti-235 feat: QR FullScreen 을 TicketDetailScreen 로 이동
mangbaam Jun 21, 2024
8a4795d
Boolti-235 feat: 티켓 목록의 QR 아이콘 수정
mangbaam Jun 21, 2024
7b60ec5
Boolti-235 feat: QR 상세 화면 디자인 변경 (N매 등)
mangbaam Jun 23, 2024
82f4049
Boolti-235 feat: QR 상세 화면에도 티켓 상태에 따른 커버 뷰 추가
mangbaam Jun 23, 2024
390d8e4
Boolti-235 feat: InstagramIndicator dot count 대응
mangbaam Jun 24, 2024
2faebd0
Boolti-235 feat: 티켓 상세, QR 화면 페이지 동기화
mangbaam Jun 24, 2024
dc39fa3
Boolti-235 style: 티켓 상세 티켓 정보 영역 제거 및 디자인 변경 반영
mangbaam Jun 24, 2024
4aa99a3
Boolti-235 style: QR 화면에서 1개 이상일 때만 인디케이터 노출
mangbaam Jun 24, 2024
e89142e
Boolti-235 fix: 인디케이터 시작 페이지 수정
mangbaam Jun 25, 2024
fd1a3fc
Boolti-235 refactor: snapshotFlow 코드 수정
mangbaam Jun 26, 2024
ecb8d1a
Boolti-235 refactor: IndicatorRange 네이밍 변경
mangbaam Jun 26, 2024
b691c9f
Boolti-235 refactor: IndicatorRange contains 제거
mangbaam Jun 26, 2024
d2da962
Merge branch 'refs/heads/develop' into feature/Boolti-235
mangbaam Jun 26, 2024
399abb5
Boolti-235 style: 티켓 탭 디자인 QA 반영
mangbaam Jun 28, 2024
568e7e0
Boolti-235 style: 티켓 상세 디자인 QA 반영
mangbaam Jun 28, 2024
981f03b
디자인 QA 2차 반영
Jul 2, 2024
df68959
문구 수정 (예매 -> 결제), subhead0 fontSize, lineHeight 수정
mangbaam Jul 2, 2024
6500c22
종료된 공연 비활성화 해제
mangbaam Jul 2, 2024
8901b84
Boolti-235 feat: 티켓 상세 - 안내사항 자동 하이라이팅 적용
mangbaam Jul 2, 2024
359d60c
fix : 디자인 추가 QA
HamBP Jul 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,17 @@ package com.nexters.boolti.data.datasource

import com.nexters.boolti.data.network.api.TicketService
import com.nexters.boolti.data.network.response.TicketDetailDto
import com.nexters.boolti.domain.model.Ticket
import com.nexters.boolti.data.network.response.TicketGroupDto
import com.nexters.boolti.domain.model.LegacyTicket
import com.nexters.boolti.domain.model.TicketGroup
import retrofit2.Response
import javax.inject.Inject

internal class TicketDataSource @Inject constructor(
private val apiService: TicketService,
) {
suspend fun getTickets(): List<Ticket> = apiService.getTickets().map { it.toDomain() }
suspend fun getTicket(ticketId: String): Response<TicketDetailDto> = apiService.getTicket(ticketId)
suspend fun legacyGetTickets(): List<LegacyTicket> = apiService.legacyGetTickets().map { it.toDomain() }
suspend fun legacyGetTicket(ticketId: String): Response<TicketDetailDto> = apiService.legacyGetTicket(ticketId)
suspend fun getTickets(): List<TicketGroup> = apiService.getTickets().map { it.toDomain() }
suspend fun getTicket(reservationId: String): Response<TicketGroupDto> = apiService.getTicket(reservationId)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,26 @@ package com.nexters.boolti.data.network.api

import com.nexters.boolti.data.network.response.TicketDetailDto
import com.nexters.boolti.data.network.response.TicketDto
import com.nexters.boolti.data.network.response.TicketGroupDto
import com.nexters.boolti.data.network.response.TicketsDto
import retrofit2.Response
import retrofit2.http.GET
import retrofit2.http.Path

internal interface TicketService {
@GET("/app/api/v1/tickets")
suspend fun getTickets(): List<TicketDto>
suspend fun legacyGetTickets(): List<TicketDto>

@GET("/app/api/v1/ticket/{ticketId}")
suspend fun getTicket(
suspend fun legacyGetTicket(
@Path("ticketId") ticketId: String,
): Response<TicketDetailDto>

@GET("/app/api/v1/reservation/tickets")
suspend fun getTickets(): List<TicketsDto>

@GET("/app/api/v1/ticket/reservation/{reservationId}")
suspend fun getTicket(
@Path("reservationId") reservationId: String,
): Response<TicketGroupDto>
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.nexters.boolti.data.network.response

import com.nexters.boolti.data.util.toLocalDateTime
import com.nexters.boolti.domain.model.Ticket
import com.nexters.boolti.domain.model.LegacyTicket
import kotlinx.serialization.Serializable
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
Expand All @@ -21,7 +21,7 @@ internal data class TicketDto(
val ticketCreatedAt: String,
val csTicketId: String,
) {
fun toDomain(): Ticket = Ticket(
fun toDomain(): LegacyTicket = LegacyTicket(
userId = userId,
ticketId = ticketId,
showName = showName,
Expand Down Expand Up @@ -61,7 +61,7 @@ data class TicketDetailDto(
val csReservationId: String = "",
val csTicketId: String = "",
) {
fun toDomain(): Ticket = Ticket(
fun toDomain(): LegacyTicket = LegacyTicket(
userId = userId,
showId = showId,
ticketId = ticketId,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package com.nexters.boolti.data.network.response


import com.nexters.boolti.data.util.toLocalDateTime
import com.nexters.boolti.domain.model.TicketGroup
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import java.time.LocalDateTime

@Serializable
internal data class TicketsDto(
@SerialName("userId")
val userId: String? = null,
@SerialName("reservationId")
val reservationId: String? = null,
@SerialName("showName")
val showName: String? = null,
@SerialName("placeName")
val placeName: String? = null,
@SerialName("showDate")
val showDate: String? = null,
@SerialName("showImgPath")
val showImgPath: String? = null,
@SerialName("ticketType")
val ticketType: String? = null,
@SerialName("ticketName")
val ticketName: String? = null,
@SerialName("ticketCount")
val ticketCount: Int? = null,
) {
fun toDomain(): TicketGroup = TicketGroup(
userId = userId ?: "",
showId = "",
reservationId = reservationId ?: "",
showName = showName ?: "",
placeName = placeName ?: "",
streetAddress = "",
detailAddress = "",
showDate = showDate?.toLocalDateTime() ?: LocalDateTime.now(),
notice = "",
ticketNotice = "",
poster = showImgPath ?: "",
ticketType = TicketGroup.TicketType.convert(ticketType),
ticketName = ticketName ?: "",
hostName = "",
hostPhoneNumber = "",
tickets = List(ticketCount ?: 0) {
TicketGroup.Ticket(
ticketId = "",
entryCode = "",
usedAt = null,
ticketCreatedAt = LocalDateTime.MIN,
csTicketId = "",
showDate = LocalDateTime.MIN,
)
}
)
}

@Serializable
internal data class TicketGroupDto(
@SerialName("detailAddress")
val detailAddress: String? = null,
@SerialName("hostName")
val hostName: String? = null,
@SerialName("hostPhoneNumber")
val hostPhoneNumber: String? = null,
@SerialName("notice")
val notice: String? = null,
@SerialName("placeName")
val placeName: String? = null,
@SerialName("reservationId")
val reservationId: String? = null,
@SerialName("showDate")
val showDate: String? = null,
@SerialName("showId")
val showId: String? = null,
@SerialName("showImgPath")
val showImgPath: String? = null,
@SerialName("showName")
val showName: String? = null,
@SerialName("streetAddress")
val streetAddress: String? = null,
@SerialName("ticketName")
val ticketName: String? = null,
@SerialName("ticketNotice")
val ticketNotice: String? = null,
@SerialName("ticketType")
val ticketType: String? = null,
@SerialName("tickets")
val tickets: List<TicketDto>? = null,
@SerialName("userId")
val userId: String? = null,
) {
fun toDomain(): TicketGroup = TicketGroup(
userId = userId ?: "",
showId = showId ?: "",
reservationId = reservationId ?: "",
showName = showName ?: "",
placeName = placeName ?: "",
streetAddress = streetAddress ?: "",
detailAddress = detailAddress ?: "",
showDate = showDate?.toLocalDateTime() ?: LocalDateTime.MIN,
notice = notice ?: "",
ticketNotice = ticketNotice ?: "",
poster = showImgPath ?: "",
ticketType = TicketGroup.TicketType.convert(ticketType),
ticketName = ticketName ?: "",
hostName = hostName ?: "",
hostPhoneNumber = hostPhoneNumber ?: "",
tickets = tickets?.map {
it.toDomain(showDate = showDate?.toLocalDateTime() ?: LocalDateTime.MIN)
} ?: emptyList(),
)

@Serializable
data class TicketDto(
@SerialName("csTicketId")
val csTicketId: String? = null,
@SerialName("entryCode")
val entryCode: String? = null,
@SerialName("ticketCreatedAt")
val ticketCreatedAt: String? = null,
@SerialName("ticketId")
val ticketId: String? = null,
@SerialName("usedAt")
val usedAt: String? = null,
) {
fun toDomain(showDate: LocalDateTime): TicketGroup.Ticket = TicketGroup.Ticket(
ticketId = ticketId ?: "",
entryCode = entryCode ?: "",
usedAt = usedAt?.toLocalDateTime(),
ticketCreatedAt = ticketCreatedAt?.toLocalDateTime() ?: LocalDateTime.MIN,
csTicketId = csTicketId ?: "",
showDate = showDate,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ import com.nexters.boolti.domain.exception.ManagerCodeErrorType
import com.nexters.boolti.domain.exception.ManagerCodeException
import com.nexters.boolti.domain.exception.TicketException
import com.nexters.boolti.domain.extension.errorType
import com.nexters.boolti.domain.model.Ticket
import com.nexters.boolti.domain.model.LegacyTicket
import com.nexters.boolti.domain.model.TicketGroup
import com.nexters.boolti.domain.repository.TicketRepository
import com.nexters.boolti.domain.request.ManagerCodeRequest
import kotlinx.coroutines.flow.Flow
Expand All @@ -17,12 +18,27 @@ internal class TicketRepositoryImpl @Inject constructor(
private val dataSource: TicketDataSource,
private val hostDataSource: HostDataSource,
) : TicketRepository {
override suspend fun getTicket(): Flow<List<Ticket>> = flow {
override suspend fun legacyGetTicket(): Flow<List<LegacyTicket>> = flow {
emit(dataSource.legacyGetTickets())
}

override suspend fun legacyGetTicket(ticketId: String): Flow<LegacyTicket> = flow {
val response = dataSource.legacyGetTicket(ticketId)
if (response.isSuccessful) {
response.body()?.toDomain()?.let { emit(it) }
} else {
when (response.code()) {
404 -> throw TicketException.TicketNotFound
}
}
}

override fun getTickets(): Flow<List<TicketGroup>> = flow {
emit(dataSource.getTickets())
}

override suspend fun getTicket(ticketId: String): Flow<Ticket> = flow {
val response = dataSource.getTicket(ticketId)
override fun getTicket(reservationId: String): Flow<TicketGroup> = flow {
val response = dataSource.getTicket(reservationId)
if (response.isSuccessful) {
response.body()?.toDomain()?.let { emit(it) }
} else {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package com.nexters.boolti.domain.model

import java.time.LocalDateTime

/**
* @property userId
* @property showId
* @property ticketId
* @property reservationId
* @property salesTicketTypeId
* @property showName
* @property streetAddress
* @property detailAddress
* @property showDate
* @property poster
* @property isInviteTicket
* @property ticketName
* @property notice 공연 내용 (공연 상세에서 사용)
* @property ticketNotice 안내사항 for 주최자
* @property placeName
* @property entryCode QR 에 담길 정보
* @property usedAt
* @property hostName
* @property hostPhoneNumber
*/
data class LegacyTicket(
val userId: String = "",
val showId: String = "",
val ticketId: String = "",
val reservationId: String = "",
val salesTicketTypeId: String = "",
val showName: String = "",
val streetAddress: String = "",
val detailAddress: String = "",
val showDate: LocalDateTime = LocalDateTime.now(),
val poster: String = "",
val isInviteTicket: Boolean = false,
val ticketName: String = "",
val notice: String = "",
val ticketNotice: String = "",
val placeName: String = "",
val entryCode: String = "",
val usedAt: LocalDateTime? = null,
val hostName: String = "",
val hostPhoneNumber: String = "",
val csReservationId: String = "",
val csTicketId: String = "",
) {
val ticketState: TicketState
get() = run {
val now = LocalDateTime.now()
when {
usedAt != null && now > usedAt -> TicketState.Used
now.toLocalDate() > showDate.toLocalDate() -> TicketState.Finished
else -> TicketState.Ready
}
}
}

enum class TicketState {
Ready, Used, Finished
}
Loading
Loading