244 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			Swift
		
	
	
	
	
	
			
		
		
	
	
			244 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			Swift
		
	
	
	
	
	
//
 | 
						|
//  SearchUnifiedView.swift
 | 
						|
//  SodaLive
 | 
						|
//
 | 
						|
//  Created by klaus on 3/27/25.
 | 
						|
//
 | 
						|
 | 
						|
import SwiftUI
 | 
						|
import Kingfisher
 | 
						|
 | 
						|
struct SearchUnifiedView: View {
 | 
						|
    
 | 
						|
    let creatorList: [SearchResponseItem]
 | 
						|
    let contentList: [SearchResponseItem]
 | 
						|
    let searchList: [SearchResponseItem]
 | 
						|
    
 | 
						|
    let onTapMoreCreator: () -> Void
 | 
						|
    let onTapMoreContent: () -> Void
 | 
						|
    let onTapMoreSeries: () -> Void
 | 
						|
    
 | 
						|
    var body: some View {
 | 
						|
        ScrollView(.vertical, showsIndicators: false) {
 | 
						|
            VStack(spacing: 30) {
 | 
						|
                if !creatorList.isEmpty {
 | 
						|
                    SearchUnifiedItemView(
 | 
						|
                        title: "채널",
 | 
						|
                        itemList: creatorList,
 | 
						|
                        onTapMore: onTapMoreCreator
 | 
						|
                    )
 | 
						|
                    .frame(maxWidth: .infinity)
 | 
						|
                    .padding(.horizontal, 13.3)
 | 
						|
                }
 | 
						|
                
 | 
						|
                if !contentList.isEmpty {
 | 
						|
                    SearchUnifiedItemView(
 | 
						|
                        title: "콘텐츠",
 | 
						|
                        itemList: contentList,
 | 
						|
                        onTapMore: onTapMoreContent
 | 
						|
                    )
 | 
						|
                    .frame(maxWidth: .infinity)
 | 
						|
                    .padding(.horizontal, 13.3)
 | 
						|
                }
 | 
						|
                
 | 
						|
                if !searchList.isEmpty {
 | 
						|
                    SearchUnifiedItemView(
 | 
						|
                        title: "시리즈",
 | 
						|
                        itemList: searchList,
 | 
						|
                        onTapMore: onTapMoreSeries
 | 
						|
                    )
 | 
						|
                    .frame(maxWidth: .infinity)
 | 
						|
                    .padding(.horizontal, 13.3)
 | 
						|
                }
 | 
						|
            }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
struct SearchUnifiedItemView: View {
 | 
						|
    let title: String
 | 
						|
    let itemList: [SearchResponseItem]
 | 
						|
    let onTapMore: () -> Void
 | 
						|
    
 | 
						|
    var body: some View {
 | 
						|
        VStack(alignment: .leading, spacing: 13.3) {
 | 
						|
            Text(title)
 | 
						|
                .font(.custom(Font.bold.rawValue, size: 16))
 | 
						|
                .foregroundColor(.grayee)
 | 
						|
            
 | 
						|
            ForEach(0..<itemList.count, id: \.self) {
 | 
						|
                let item = itemList[$0]
 | 
						|
                
 | 
						|
                switch item.type {
 | 
						|
                case .CREATOR:
 | 
						|
                    SearchCreatorItemView(item: item)
 | 
						|
                    
 | 
						|
                case .CONTENT:
 | 
						|
                    SearchContentItemView(item: item)
 | 
						|
                    
 | 
						|
                case .SERIES:
 | 
						|
                    SearchSeriesItemView(item: item)
 | 
						|
                }
 | 
						|
            }
 | 
						|
            
 | 
						|
            Text("더보기 >")
 | 
						|
                .font(.custom(Font.medium.rawValue, size: 13.3))
 | 
						|
                .foregroundColor(.grayee)
 | 
						|
                .padding(.vertical, 10)
 | 
						|
                .frame(maxWidth: .infinity)
 | 
						|
                .background(Color.gray33.opacity(0.7))
 | 
						|
                .onTapGesture { onTapMore() }
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
struct SearchCreatorItemView: View {
 | 
						|
    let item: SearchResponseItem
 | 
						|
    
 | 
						|
    var body: some View {
 | 
						|
        NavigationLink {
 | 
						|
            UserProfileView(userId: item.id)
 | 
						|
        } label: {
 | 
						|
            HStack(spacing: 13.3) {
 | 
						|
                KFImage(URL(string: item.imageUrl))
 | 
						|
                    .cancelOnDisappear(true)
 | 
						|
                    .downsampling(size: CGSize(width: 60, height: 60))
 | 
						|
                    .resizable()
 | 
						|
                    .frame(width: 60, height: 60)
 | 
						|
                    .clipShape(Circle())
 | 
						|
                
 | 
						|
                Text(item.nickname)
 | 
						|
                    .font(.custom(Font.medium.rawValue, size: 13.3))
 | 
						|
                    .foregroundColor(Color.grayee)
 | 
						|
                
 | 
						|
                Spacer()
 | 
						|
            }
 | 
						|
            .frame(maxWidth: .infinity)
 | 
						|
            .contentShape(Rectangle())
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
struct SearchContentItemView: View {
 | 
						|
    let item: SearchResponseItem
 | 
						|
    
 | 
						|
    var body: some View {
 | 
						|
        NavigationLink {
 | 
						|
            ContentDetailView(contentId: item.id)
 | 
						|
        } label: {
 | 
						|
            HStack(spacing: 13.3) {
 | 
						|
                KFImage(URL(string: item.imageUrl))
 | 
						|
                    .cancelOnDisappear(true)
 | 
						|
                    .downsampling(size: CGSize(width: 60, height: 60))
 | 
						|
                    .resizable()
 | 
						|
                    .frame(width: 60, height: 60)
 | 
						|
                    .cornerRadius(5.3)
 | 
						|
                
 | 
						|
                VStack(alignment: .leading, spacing: 6.7) {
 | 
						|
                    Text(item.title)
 | 
						|
                        .font(.custom(Font.medium.rawValue, size: 13.3))
 | 
						|
                        .foregroundColor(Color.grayee)
 | 
						|
                        .multilineTextAlignment(.leading)
 | 
						|
                        .lineLimit(2)
 | 
						|
                    
 | 
						|
                    Text(item.nickname)
 | 
						|
                        .font(.custom(Font.medium.rawValue, size: 10))
 | 
						|
                        .foregroundColor(Color.gray77)
 | 
						|
                }
 | 
						|
                
 | 
						|
                Spacer()
 | 
						|
            }
 | 
						|
            .frame(maxWidth: .infinity)
 | 
						|
            .contentShape(Rectangle())
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
struct SearchSeriesItemView: View {
 | 
						|
    let item: SearchResponseItem
 | 
						|
    
 | 
						|
    var body: some View {
 | 
						|
        NavigationLink {
 | 
						|
            SeriesDetailView(seriesId: item.id)
 | 
						|
        } label: {
 | 
						|
            HStack(spacing: 13.3) {
 | 
						|
                KFImage(URL(string: item.imageUrl))
 | 
						|
                    .cancelOnDisappear(true)
 | 
						|
                    .downsampling(size: CGSize(width: 60, height: 85))
 | 
						|
                    .resizable()
 | 
						|
                    .scaledToFill()
 | 
						|
                    .frame(width: 60, height: 85)
 | 
						|
                    .clipped()
 | 
						|
                    .cornerRadius(5.3)
 | 
						|
                
 | 
						|
                VStack(alignment: .leading, spacing: 6.7) {
 | 
						|
                    Text(item.title)
 | 
						|
                        .font(.custom(Font.medium.rawValue, size: 13.3))
 | 
						|
                        .foregroundColor(Color.grayee)
 | 
						|
                        .multilineTextAlignment(.leading)
 | 
						|
                        .lineLimit(2)
 | 
						|
                    
 | 
						|
                    Text(item.nickname)
 | 
						|
                        .font(.custom(Font.medium.rawValue, size: 10))
 | 
						|
                        .foregroundColor(Color.gray77)
 | 
						|
                }
 | 
						|
                
 | 
						|
                Spacer()
 | 
						|
            }
 | 
						|
            .frame(maxWidth: .infinity)
 | 
						|
            .contentShape(Rectangle())
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#Preview {
 | 
						|
    SearchUnifiedView(
 | 
						|
        creatorList: [
 | 
						|
            SearchResponseItem(
 | 
						|
                id: 1,
 | 
						|
                imageUrl: "https://test-cf.sodalive.net/profile/default-profile.png",
 | 
						|
                title: "Tester",
 | 
						|
                nickname: "Tester",
 | 
						|
                type: .CREATOR
 | 
						|
            )
 | 
						|
        ],
 | 
						|
        contentList: [
 | 
						|
            SearchResponseItem(
 | 
						|
                id: 1,
 | 
						|
                imageUrl: "https://test-cf.sodalive.net/profile/default-profile.png",
 | 
						|
                title: "Title1",
 | 
						|
                nickname: "Tester",
 | 
						|
                type: .CONTENT
 | 
						|
            ),
 | 
						|
            
 | 
						|
            SearchResponseItem(
 | 
						|
                id: 2,
 | 
						|
                imageUrl: "https://test-cf.sodalive.net/profile/default-profile.png",
 | 
						|
                title: "Title2",
 | 
						|
                nickname: "Tester2",
 | 
						|
                type: .CONTENT
 | 
						|
            )
 | 
						|
        ],
 | 
						|
        searchList: [
 | 
						|
            SearchResponseItem(
 | 
						|
                id: 1,
 | 
						|
                imageUrl: "https://test-cf.sodalive.net/profile/default-profile.png",
 | 
						|
                title: "Title1",
 | 
						|
                nickname: "Tester",
 | 
						|
                type: .SERIES
 | 
						|
            ),
 | 
						|
            
 | 
						|
            SearchResponseItem(
 | 
						|
                id: 2,
 | 
						|
                imageUrl: "https://test-cf.sodalive.net/profile/default-profile.png",
 | 
						|
                title: "Title2",
 | 
						|
                nickname: "Tester2",
 | 
						|
                type: .SERIES
 | 
						|
            )],
 | 
						|
        onTapMoreCreator: {},
 | 
						|
        onTapMoreContent: {},
 | 
						|
        onTapMoreSeries: {}
 | 
						|
    )
 | 
						|
}
 |