feat(main-home): 추천 홈 공용 컴포넌트를 추가한다
This commit is contained in:
@@ -0,0 +1,70 @@
|
||||
import SwiftUI
|
||||
|
||||
struct CreatorProfileGridItem: Identifiable, Hashable {
|
||||
let id: String
|
||||
let imageUrl: String?
|
||||
let name: String
|
||||
let subtitle: String?
|
||||
|
||||
init(
|
||||
id: String,
|
||||
imageUrl: String?,
|
||||
name: String,
|
||||
subtitle: String? = nil
|
||||
) {
|
||||
self.id = id
|
||||
self.imageUrl = imageUrl
|
||||
self.name = name
|
||||
self.subtitle = subtitle
|
||||
}
|
||||
}
|
||||
|
||||
struct CreatorProfileGrid: View {
|
||||
let items: [CreatorProfileGridItem]
|
||||
let columns: Int
|
||||
let spacing: CGFloat
|
||||
let action: (CreatorProfileGridItem) -> Void
|
||||
|
||||
init(
|
||||
items: [CreatorProfileGridItem],
|
||||
columns: Int = 3,
|
||||
spacing: CGFloat = SodaSpacing.s16,
|
||||
action: @escaping (CreatorProfileGridItem) -> Void = { _ in }
|
||||
) {
|
||||
self.items = items
|
||||
self.columns = columns
|
||||
self.spacing = spacing
|
||||
self.action = action
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
LazyVGrid(columns: gridColumns, alignment: .center, spacing: spacing) {
|
||||
ForEach(items) { item in
|
||||
CreatorProfileItem(
|
||||
imageUrl: item.imageUrl,
|
||||
name: item.name,
|
||||
subtitle: item.subtitle
|
||||
) {
|
||||
action(item)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private var gridColumns: [GridItem] {
|
||||
Array(repeating: GridItem(.flexible(), spacing: spacing), count: columns)
|
||||
}
|
||||
}
|
||||
|
||||
struct CreatorProfileGrid_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
CreatorProfileGrid(items: [
|
||||
CreatorProfileGridItem(id: "1", imageUrl: nil, name: "크리에이터 1"),
|
||||
CreatorProfileGridItem(id: "2", imageUrl: nil, name: "크리에이터 2"),
|
||||
CreatorProfileGridItem(id: "3", imageUrl: nil, name: "크리에이터 3")
|
||||
])
|
||||
.padding(SodaSpacing.s20)
|
||||
.background(Color.black)
|
||||
.previewLayout(.sizeThatFits)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
import SwiftUI
|
||||
|
||||
struct CreatorProfileItem: View {
|
||||
let imageUrl: String?
|
||||
let name: String
|
||||
let subtitle: String?
|
||||
let action: (() -> Void)?
|
||||
|
||||
init(
|
||||
imageUrl: String?,
|
||||
name: String,
|
||||
subtitle: String? = nil,
|
||||
action: (() -> Void)? = nil
|
||||
) {
|
||||
self.imageUrl = imageUrl
|
||||
self.name = name
|
||||
self.subtitle = subtitle
|
||||
self.action = action
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
Button {
|
||||
action?()
|
||||
} label: {
|
||||
VStack(alignment: .center, spacing: SodaSpacing.s8) {
|
||||
profileImage
|
||||
|
||||
VStack(alignment: .center, spacing: 2) {
|
||||
Text(name)
|
||||
.appFont(.body4)
|
||||
.foregroundColor(.white)
|
||||
.lineLimit(1)
|
||||
.truncationMode(.tail)
|
||||
|
||||
if let subtitle, !subtitle.isEmpty {
|
||||
Text(subtitle)
|
||||
.appFont(.caption2)
|
||||
.foregroundColor(Color.gray500)
|
||||
.lineLimit(1)
|
||||
.truncationMode(.tail)
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.disabled(action == nil)
|
||||
}
|
||||
|
||||
private var profileImage: some View {
|
||||
DownsampledKFImage(url: URL(string: imageUrl ?? ""), size: CGSize(width: 72, height: 72))
|
||||
.background(Color.gray800)
|
||||
.clipShape(Circle())
|
||||
}
|
||||
}
|
||||
|
||||
struct CreatorProfileItem_Previews: PreviewProvider {
|
||||
static var previews: some View {
|
||||
CreatorProfileItem(imageUrl: nil, name: "크리에이터", subtitle: "방금 활동")
|
||||
.frame(width: 96)
|
||||
.padding(SodaSpacing.s20)
|
||||
.background(Color.black)
|
||||
.previewLayout(.sizeThatFits)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user