feat(creator): 시리즈 탭을 추가한다
This commit is contained in:
@@ -0,0 +1,137 @@
|
||||
import SwiftUI
|
||||
|
||||
struct CreatorChannelSeriesListItem: View {
|
||||
let series: CreatorChannelSeriesResponse
|
||||
let showsOwnershipProgress: Bool
|
||||
let action: () -> Void
|
||||
|
||||
init(
|
||||
series: CreatorChannelSeriesResponse,
|
||||
showsOwnershipProgress: Bool,
|
||||
action: @escaping () -> Void = {}
|
||||
) {
|
||||
self.series = series
|
||||
self.showsOwnershipProgress = showsOwnershipProgress
|
||||
self.action = action
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
Button {
|
||||
action()
|
||||
} label: {
|
||||
HStack(alignment: .center, spacing: SodaSpacing.s14) {
|
||||
thumbnail
|
||||
|
||||
VStack(alignment: .leading, spacing: 0) {
|
||||
titleArea
|
||||
|
||||
Spacer(minLength: SodaSpacing.s8)
|
||||
|
||||
if showsOwnershipProgress,
|
||||
let purchasedContentCount = series.purchasedContentCount,
|
||||
let paidContentCount = series.paidContentCount,
|
||||
let purchasedPaidContentRate = series.purchasedPaidContentRate {
|
||||
CreatorChannelSeriesOwnershipRateView(
|
||||
purchasedContentCount: purchasedContentCount,
|
||||
paidContentCount: paidContentCount,
|
||||
purchasedPaidContentRate: purchasedPaidContentRate
|
||||
)
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
|
||||
}
|
||||
.padding(.horizontal, SodaSpacing.s20)
|
||||
.padding(.vertical, SodaSpacing.s8)
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.contentShape(Rectangle())
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
}
|
||||
|
||||
private var thumbnail: some View {
|
||||
ZStack(alignment: .topLeading) {
|
||||
DownsampledKFImage(
|
||||
url: series.coverImageUrl.flatMap(URL.init(string:)),
|
||||
size: CGSize(width: 122, height: 172)
|
||||
)
|
||||
.background(Color.gray800)
|
||||
|
||||
if series.isOriginal {
|
||||
originalTag
|
||||
}
|
||||
|
||||
HStack(spacing: 0) {
|
||||
Spacer()
|
||||
|
||||
if series.isAdult {
|
||||
CreatorChannelAudioAdultTag()
|
||||
.padding(.top, 6)
|
||||
.padding(.trailing, 6)
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(width: 122, height: 172)
|
||||
.clipShape(RoundedRectangle(cornerRadius: SodaSpacing.s14, style: .continuous))
|
||||
}
|
||||
|
||||
private var originalTag: some View {
|
||||
HStack(spacing: 4) {
|
||||
Image("ic_series_original")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 14, height: 14)
|
||||
|
||||
Image("img_new_only")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(height: 14)
|
||||
}
|
||||
.padding(.horizontal, 8)
|
||||
.padding(.vertical, 5)
|
||||
.background(Color.gray900)
|
||||
}
|
||||
|
||||
private var titleArea: some View {
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text(series.title)
|
||||
.appFont(size: 16, weight: .bold)
|
||||
.foregroundColor(.white)
|
||||
.lineLimit(1)
|
||||
.truncationMode(.tail)
|
||||
|
||||
Text(subtitle)
|
||||
.appFont(size: 14, weight: .medium)
|
||||
.foregroundColor(Color.gray500)
|
||||
.lineLimit(1)
|
||||
.truncationMode(.tail)
|
||||
}
|
||||
}
|
||||
|
||||
private var subtitle: String {
|
||||
let status = series.isProceeding ? I18n.CreatorChannelSeries.proceeding : I18n.CreatorChannelSeries.completed
|
||||
return "\(series.publishedDaysOfWeek) • \(I18n.CreatorChannelSeries.totalContentCount(series.contentCount)) • \(status)"
|
||||
}
|
||||
}
|
||||
|
||||
struct CreatorChannelSeriesListItem_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
CreatorChannelSeriesListItem(
|
||||
series: CreatorChannelSeriesResponse(
|
||||
seriesId: 1,
|
||||
title: "시리즈 이름",
|
||||
coverImageUrl: "https://picsum.photos/300/420",
|
||||
publishedDaysOfWeek: "매주 월",
|
||||
isOriginal: true,
|
||||
isAdult: true,
|
||||
isProceeding: false,
|
||||
contentCount: 45,
|
||||
purchasedContentCount: 12,
|
||||
paidContentCount: 45,
|
||||
purchasedPaidContentRate: 40
|
||||
),
|
||||
showsOwnershipProgress: true
|
||||
)
|
||||
.background(Color.black)
|
||||
.previewLayout(.sizeThatFits)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
import SwiftUI
|
||||
|
||||
struct CreatorChannelSeriesOwnershipRateView: View {
|
||||
let purchasedContentCount: Int
|
||||
let paidContentCount: Int
|
||||
let purchasedPaidContentRate: Int
|
||||
|
||||
private var progress: Double {
|
||||
max(0, min(Double(purchasedPaidContentRate) / 100, 1))
|
||||
}
|
||||
|
||||
init(
|
||||
purchasedContentCount: Int,
|
||||
paidContentCount: Int,
|
||||
purchasedPaidContentRate: Int
|
||||
) {
|
||||
self.purchasedContentCount = purchasedContentCount
|
||||
self.paidContentCount = paidContentCount
|
||||
self.purchasedPaidContentRate = purchasedPaidContentRate
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: SodaSpacing.s4) {
|
||||
HStack(alignment: .center, spacing: SodaSpacing.s8) {
|
||||
(
|
||||
Text(purchasedContentCount.comma())
|
||||
.foregroundColor(.white)
|
||||
+ Text("/\(paidContentCount.comma())\(I18n.CreatorChannelSeries.contentCountUnit)")
|
||||
.foregroundColor(Color.gray500)
|
||||
)
|
||||
.appFont(size: 14, weight: .medium)
|
||||
.lineLimit(1)
|
||||
|
||||
Spacer(minLength: SodaSpacing.s8)
|
||||
|
||||
Text("\(purchasedPaidContentRate)%")
|
||||
.appFont(size: 14, weight: .medium)
|
||||
.foregroundColor(Color.soda400)
|
||||
.lineLimit(1)
|
||||
}
|
||||
|
||||
ProgressView(value: progress)
|
||||
.progressViewStyle(.linear)
|
||||
.tint(Color.soda400)
|
||||
.frame(height: 4)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct CreatorChannelSeriesOwnershipRateView_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
CreatorChannelSeriesOwnershipRateView(
|
||||
purchasedContentCount: 12,
|
||||
paidContentCount: 45,
|
||||
purchasedPaidContentRate: 40
|
||||
)
|
||||
.background(Color.black)
|
||||
.previewLayout(.sizeThatFits)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user