feat: 메인 홈

- 주간 차트, 무료 콘텐츠 UI 추가
This commit is contained in:
Yu Sung
2025-07-12 02:50:24 +09:00
parent 6a9854bdd7
commit 07c73366e9
3 changed files with 232 additions and 32 deletions

View File

@@ -132,24 +132,8 @@ struct HomeTabView: View {
viewModel.getDayOfWeekSeriesList(dayOfWeek: $0) viewModel.getDayOfWeekSeriesList(dayOfWeek: $0)
} }
VStack(alignment: .leading, spacing: 16) { if !viewModel.contentRanking.isEmpty {
HStack(spacing: 0) { HomeWeeklyChartView(contentList: viewModel.contentRanking)
Text("보온")
.font(.custom(Font.preBold.rawValue, size: 26))
.foregroundColor(.button)
Text(" 주간 차트")
.font(.custom(Font.preBold.rawValue, size: 26))
.foregroundColor(.white)
}
.padding(.horizontal, 24)
ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 16) {
}
.padding(.horizontal, 24)
}
} }
VStack(alignment: .leading, spacing: 16) { VStack(alignment: .leading, spacing: 16) {
@@ -172,6 +156,7 @@ struct HomeTabView: View {
} }
} }
if !viewModel.freeContentList.isEmpty {
VStack(alignment: .leading, spacing: 16) { VStack(alignment: .leading, spacing: 16) {
HStack(spacing: 0) { HStack(spacing: 0) {
Text("무료") Text("무료")
@@ -186,11 +171,14 @@ struct HomeTabView: View {
ScrollView(.horizontal, showsIndicators: false) { ScrollView(.horizontal, showsIndicators: false) {
HStack(spacing: 16) { HStack(spacing: 16) {
ForEach(0..<viewModel.freeContentList.count, id: \.self) { index in
ContentItemView(item: viewModel.freeContentList[index])
}
} }
.padding(.horizontal, 24) .padding(.horizontal, 24)
} }
} }
}
Text(""" Text("""
- 회사명 : 주식회사 소다라이브 - 회사명 : 주식회사 소다라이브

View File

@@ -0,0 +1,63 @@
//
// HomeWeeklyChartItemView.swift
// SodaLive
//
// Created by klaus on 7/12/25.
//
import SwiftUI
import Kingfisher
struct HomeWeeklyChartItemView: View {
let rank: Int
let content: GetAudioContentRankingItem
let onClickItem: (Int) -> Void
var body: some View {
HStack(spacing: 16) {
Text("\(rank)")
.font(.custom(Font.preBold.rawValue, size: 16.7))
.foregroundColor(Color(hex: "B5E7FA"))
KFImage(URL(string: content.coverImageUrl))
.cancelOnDisappear(true)
.resizable()
.frame(width: 60, height: 60)
.cornerRadius(12)
VStack(alignment: .leading, spacing: 6) {
Text(content.title)
.lineLimit(1)
.font(.custom(Font.preRegular.rawValue, size: 18))
.foregroundColor(.white)
Text(content.creatorNickname)
.font(.custom(Font.preRegular.rawValue, size: 14))
.foregroundColor(Color(hex: "78909C"))
}
}
.frame(width: 242, alignment: .leading)
.contentShape(Rectangle())
.onTapGesture { onClickItem(content.contentId) }
}
}
#Preview {
HomeWeeklyChartItemView(
rank: 1,
content: GetAudioContentRankingItem(
contentId: 1,
title: "안녕하세요 오늘은 커버곡을 들려드릴께요....안녕하세요 오늘은 커버곡을 들려드릴께요....",
coverImageUrl: "https://test-cf.sodalive.net/profile/default-profile.png",
themeStr: "커버곡",
price: 100,
duration: "00:30:20",
creatorId: 1,
creatorNickname: "유저1",
isPointAvailable: false,
creatorProfileImageUrl: "https://test-cf.sodalive.net/profile/default-profile.png"
),
onClickItem: { _ in }
)
}

View File

@@ -0,0 +1,149 @@
//
// HomeWeeklyChartView.swift
// SodaLive
//
// Created by klaus on 7/12/25.
//
import SwiftUI
struct HomeWeeklyChartView: View {
@AppStorage("token") private var token: String = UserDefaults.string(forKey: UserDefaultsKey.token)
let rows = [
GridItem(.fixed(60), alignment: .leading),
GridItem(.fixed(60), alignment: .leading),
GridItem(.fixed(60), alignment: .leading),
GridItem(.fixed(60), alignment: .leading)
]
let contentList: [GetAudioContentRankingItem]
var body: some View {
VStack(spacing: 16) {
HStack(spacing: 0) {
Text("보온")
.font(.custom(Font.preBold.rawValue, size: 26))
.foregroundColor(.button)
Text(" 주간 차트")
.font(.custom(Font.preBold.rawValue, size: 26))
.foregroundColor(.white)
Spacer()
}
.padding(.horizontal, 24)
ScrollView(.horizontal, showsIndicators: false) {
LazyHGrid(rows: rows, spacing: 13.3) {
ForEach(0..<contentList.count, id: \.self) { index in
HomeWeeklyChartItemView(
rank: index + 1,
content: contentList[index]
) {
if !token.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty {
AppState.shared
.setAppStep(step: .contentDetail(contentId: $0))
} else {
AppState.shared
.setAppStep(step: .login)
}
}
}
}
.padding(.horizontal, 24)
}
}
}
}
#Preview {
HomeWeeklyChartView(
contentList: [
GetAudioContentRankingItem(
contentId: 1,
title: "안녕하세요 오늘은 커버곡을 들려드릴께요....안녕하세요 오늘은 커버곡을 들려드릴께요....",
coverImageUrl: "https://test-cf.sodalive.net/profile/default-profile.png",
themeStr: "커버곡",
price: 100,
duration: "00:30:20",
creatorId: 1,
creatorNickname: "유저1",
isPointAvailable: false,
creatorProfileImageUrl: "https://test-cf.sodalive.net/profile/default-profile.png"
),
GetAudioContentRankingItem(
contentId: 2,
title: "안녕하세요 오늘은 커버곡을 들려드릴께요....",
coverImageUrl: "https://test-cf.sodalive.net/profile/default-profile.png",
themeStr: "커버곡",
price: 0,
duration: "00:30:20",
creatorId: 2,
creatorNickname: "유저2",
isPointAvailable: false,
creatorProfileImageUrl: "https://test-cf.sodalive.net/profile/default-profile.png"
),
GetAudioContentRankingItem(
contentId: 3,
title: "안녕하세요 오늘은 커버곡을 들려드릴께요....안녕하세요 오늘은 커버곡을 들려드릴께요....",
coverImageUrl: "https://test-cf.sodalive.net/profile/default-profile.png",
themeStr: "커버곡",
price: 50,
duration: "00:30:20",
creatorId: 3,
creatorNickname: "유저3",
isPointAvailable: true,
creatorProfileImageUrl: "https://test-cf.sodalive.net/profile/default-profile.png"
),
GetAudioContentRankingItem(
contentId: 3,
title: "안녕하세요 오늘은 커버곡을 들려드릴께요....안녕하세요 오늘은 커버곡을 들려드릴께요....",
coverImageUrl: "https://test-cf.sodalive.net/profile/default-profile.png",
themeStr: "커버곡",
price: 50,
duration: "00:30:20",
creatorId: 3,
creatorNickname: "유저3",
isPointAvailable: true,
creatorProfileImageUrl: "https://test-cf.sodalive.net/profile/default-profile.png"
),
GetAudioContentRankingItem(
contentId: 3,
title: "안녕하세요 오늘은 커버곡을 들려드릴께요....안녕하세요 오늘은 커버곡을 들려드릴께요....",
coverImageUrl: "https://test-cf.sodalive.net/profile/default-profile.png",
themeStr: "커버곡",
price: 50,
duration: "00:30:20",
creatorId: 3,
creatorNickname: "유저3",
isPointAvailable: true,
creatorProfileImageUrl: "https://test-cf.sodalive.net/profile/default-profile.png"
),
GetAudioContentRankingItem(
contentId: 3,
title: "안녕하세요 오늘은 커버곡을 들려드릴께요....안녕하세요 오늘은 커버곡을 들려드릴께요....",
coverImageUrl: "https://test-cf.sodalive.net/profile/default-profile.png",
themeStr: "커버곡",
price: 50,
duration: "00:30:20",
creatorId: 3,
creatorNickname: "유저3",
isPointAvailable: true,
creatorProfileImageUrl: "https://test-cf.sodalive.net/profile/default-profile.png"
),
GetAudioContentRankingItem(
contentId: 3,
title: "안녕하세요 오늘은 커버곡을 들려드릴께요....안녕하세요 오늘은 커버곡을 들려드릴께요....",
coverImageUrl: "https://test-cf.sodalive.net/profile/default-profile.png",
themeStr: "커버곡",
price: 50,
duration: "00:30:20",
creatorId: 3,
creatorNickname: "유저3",
isPointAvailable: true,
creatorProfileImageUrl: "https://test-cf.sodalive.net/profile/default-profile.png"
)
]
)
}