시리즈 상세 - 번역 데이터가 있으면 번역 데이터를 표시하도록 수정
This commit is contained in:
@@ -17,6 +17,7 @@ struct GetSeriesDetailResponse: Decodable {
|
|||||||
let writer: String?
|
let writer: String?
|
||||||
let studio: String?
|
let studio: String?
|
||||||
let publishedDate: String
|
let publishedDate: String
|
||||||
|
let publishedDateUtc: String
|
||||||
let creator: GetSeriesDetailCreator
|
let creator: GetSeriesDetailCreator
|
||||||
let rentalMinPrice: Int
|
let rentalMinPrice: Int
|
||||||
let rentalMaxPrice: Int
|
let rentalMaxPrice: Int
|
||||||
@@ -27,6 +28,8 @@ struct GetSeriesDetailResponse: Decodable {
|
|||||||
let publishedDaysOfWeek: String
|
let publishedDaysOfWeek: String
|
||||||
let contentList: [GetSeriesContentListItem]
|
let contentList: [GetSeriesContentListItem]
|
||||||
let contentCount: Int
|
let contentCount: Int
|
||||||
|
let translated: TranslatedSeries?
|
||||||
|
let translatedGenre: String?
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GetSeriesDetailCreator: Decodable {
|
struct GetSeriesDetailCreator: Decodable {
|
||||||
@@ -36,3 +39,51 @@ struct GetSeriesDetailCreator: Decodable {
|
|||||||
let isFollow: Bool
|
let isFollow: Bool
|
||||||
let isNotify: Bool
|
let isNotify: Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct TranslatedSeries: Decodable {
|
||||||
|
let title: String
|
||||||
|
let introduction: String
|
||||||
|
let keywords: [String]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 표시용 계산 프로퍼티: 번역 데이터가 있으면 번역을 우선 사용
|
||||||
|
extension GetSeriesDetailResponse {
|
||||||
|
// 번역된 제목 우선
|
||||||
|
var displayTitle: String { translated?.title ?? title }
|
||||||
|
// 번역된 소개 우선
|
||||||
|
var displayIntroduction: String { translated?.introduction ?? introduction }
|
||||||
|
// 번역된 키워드 우선
|
||||||
|
var displayKeywords: [String] { translated?.keywords ?? keywordList }
|
||||||
|
// 번역된 장르 우선
|
||||||
|
var displayGenre: String { translatedGenre ?? genre }
|
||||||
|
// ISO8601 UTC를 현재 타임존 기준 yyyy.MM.dd 포맷으로 변환
|
||||||
|
var displayPublishedDate: String {
|
||||||
|
// publishedDateUtc 예: ISO8601 문자열
|
||||||
|
let iso = ISO8601DateFormatter()
|
||||||
|
// .withInternetDateTime가 기본이지만, fractional seconds 등 다양한 포맷 대응
|
||||||
|
iso.formatOptions = [.withInternetDateTime, .withFractionalSeconds]
|
||||||
|
|
||||||
|
func format(_ date: Date) -> String {
|
||||||
|
let formatter = DateFormatter()
|
||||||
|
formatter.calendar = Calendar(identifier: .gregorian)
|
||||||
|
formatter.timeZone = .current
|
||||||
|
formatter.locale = Locale(identifier: Locale.current.identifier)
|
||||||
|
formatter.dateFormat = "yyyy.MM.dd"
|
||||||
|
return formatter.string(from: date)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let date = iso.date(from: publishedDateUtc) {
|
||||||
|
return format(date)
|
||||||
|
} else {
|
||||||
|
// fractional seconds 미포함 대응
|
||||||
|
let isoNoFrac = ISO8601DateFormatter()
|
||||||
|
isoNoFrac.formatOptions = [.withInternetDateTime]
|
||||||
|
if let date = isoNoFrac.date(from: publishedDateUtc) {
|
||||||
|
return format(date)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 파싱 실패 시 기존 표시값 폴백
|
||||||
|
return publishedDate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ struct SeriesDetailIntroductionView: View {
|
|||||||
.padding(.top, 16)
|
.padding(.top, 16)
|
||||||
.padding(.horizontal, 13.3)
|
.padding(.horizontal, 13.3)
|
||||||
|
|
||||||
FlowLayout(mode: .scrollable, items: seriesDetail.keywordList, itemSpacing: 5.3) {
|
FlowLayout(mode: .scrollable, items: seriesDetail.displayKeywords, itemSpacing: 5.3) {
|
||||||
SeriesKeywordChipView(keyword: $0)
|
SeriesKeywordChipView(keyword: $0)
|
||||||
}
|
}
|
||||||
.padding(.horizontal, 13.3)
|
.padding(.horizontal, 13.3)
|
||||||
@@ -35,7 +35,7 @@ struct SeriesDetailIntroductionView: View {
|
|||||||
.font(.custom(Font.bold.rawValue, size: 14.7))
|
.font(.custom(Font.bold.rawValue, size: 14.7))
|
||||||
.foregroundColor(Color.grayee)
|
.foregroundColor(Color.grayee)
|
||||||
|
|
||||||
Text(seriesDetail.introduction)
|
Text(seriesDetail.displayIntroduction)
|
||||||
.font(.custom(Font.medium.rawValue, size: 14.7))
|
.font(.custom(Font.medium.rawValue, size: 14.7))
|
||||||
.foregroundColor(Color.gray77)
|
.foregroundColor(Color.gray77)
|
||||||
.lineSpacing(4)
|
.lineSpacing(4)
|
||||||
@@ -83,7 +83,7 @@ struct SeriesDetailIntroductionView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
VStack(alignment: .leading, spacing: 13.3) {
|
VStack(alignment: .leading, spacing: 13.3) {
|
||||||
Text(seriesDetail.genre)
|
Text(seriesDetail.displayGenre)
|
||||||
.font(.custom(Font.medium.rawValue, size: 14.7))
|
.font(.custom(Font.medium.rawValue, size: 14.7))
|
||||||
.foregroundColor(Color.white)
|
.foregroundColor(Color.white)
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ struct SeriesDetailIntroductionView: View {
|
|||||||
.font(.custom(Font.medium.rawValue, size: 14.7))
|
.font(.custom(Font.medium.rawValue, size: 14.7))
|
||||||
.foregroundColor(Color.white)
|
.foregroundColor(Color.white)
|
||||||
|
|
||||||
Text(seriesDetail.publishedDate)
|
Text(seriesDetail.displayPublishedDate)
|
||||||
.font(.custom(Font.medium.rawValue, size: 14.7))
|
.font(.custom(Font.medium.rawValue, size: 14.7))
|
||||||
.foregroundColor(Color.white)
|
.foregroundColor(Color.white)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -76,14 +76,14 @@ struct SeriesDetailView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
VStack(alignment: .leading, spacing: 0) {
|
VStack(alignment: .leading, spacing: 0) {
|
||||||
Text(seriesDetail.title)
|
Text(seriesDetail.displayTitle)
|
||||||
.font(.custom(Font.bold.rawValue, size: 18.3))
|
.font(.custom(Font.bold.rawValue, size: 18.3))
|
||||||
.foregroundColor(Color.grayee)
|
.foregroundColor(Color.grayee)
|
||||||
.padding(.horizontal, 13.3)
|
.padding(.horizontal, 13.3)
|
||||||
.padding(.top, 24)
|
.padding(.top, 24)
|
||||||
|
|
||||||
HStack(spacing: 5.3) {
|
HStack(spacing: 5.3) {
|
||||||
Text(seriesDetail.genre)
|
Text(seriesDetail.displayGenre)
|
||||||
.font(.custom(Font.medium.rawValue, size: 12))
|
.font(.custom(Font.medium.rawValue, size: 12))
|
||||||
.foregroundColor(Color(hex: "3bac6a"))
|
.foregroundColor(Color(hex: "3bac6a"))
|
||||||
.padding(.horizontal, 5.3)
|
.padding(.horizontal, 5.3)
|
||||||
@@ -118,8 +118,8 @@ struct SeriesDetailView: View {
|
|||||||
|
|
||||||
ScrollView(.horizontal, showsIndicators: false) {
|
ScrollView(.horizontal, showsIndicators: false) {
|
||||||
HStack(spacing: 5.3) {
|
HStack(spacing: 5.3) {
|
||||||
ForEach(0..<seriesDetail.keywordList.count, id: \.self) {
|
ForEach(0..<seriesDetail.displayKeywords.count, id: \.self) {
|
||||||
SeriesKeywordChipView(keyword: seriesDetail.keywordList[$0])
|
SeriesKeywordChipView(keyword: seriesDetail.displayKeywords[$0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -209,7 +209,7 @@ struct SeriesDetailView: View {
|
|||||||
|
|
||||||
default:
|
default:
|
||||||
SeriesDetailHomeView(
|
SeriesDetailHomeView(
|
||||||
title: seriesDetail.title,
|
title: seriesDetail.displayTitle,
|
||||||
seriesId: seriesDetail.seriesId,
|
seriesId: seriesDetail.seriesId,
|
||||||
contentCount: seriesDetail.contentCount,
|
contentCount: seriesDetail.contentCount,
|
||||||
contentList: seriesDetail.contentList
|
contentList: seriesDetail.contentList
|
||||||
|
|||||||
Reference in New Issue
Block a user