[SwiftUI] ChildView -> RootView로의 이벤트 전달

Hyunndy·2024년 6월 4일
0

iOS-SwiftUI

목록 보기
1/1

import SwiftUI
import CoreData
import SDWebImage
import SDWebImageSwiftUI

struct ItemAction {
    var didTapHeartItem: KartGoodsInfo? = nil
}

struct RootView: View {
    
    @ObservedObject var model: HomeListModel
    @State var action = ItemAction()
    
    var body: some View {
        ScrollView(.vertical, showsIndicators: true, content: {
            ForEach(model.sections, id: \.section.id, content: { section in
                SectionView(section: section, action: $action)
            })
        })
        .onChange(of: action.didTapHeartItem, perform: { item in
            if let _item = item  {
                model.updateFavoriteStatus(for: _item)
                action.didTapHeartItem = nil
            }
        })
    }
}

struct SectionView: View {
    
    var section: HomeListSection
    @Binding var action: ItemAction
    
    var body: some View {
        VStack(alignment: .leading) {
            Button(action: {
                print("으아악")
            },
                   label: {
                HStack {
                    Text(section.section.title)
                        .font(.title)
                    Image(systemName: "chevron.right")
                        .frame(width: 20, height: 20)
                }
                .foregroundColor(.black)
            })
            
            GeometryReader(content: { geometry in
                ScrollView(.horizontal) {
                    HStack {
                        ForEach(section.items, id: \.self, content: { item in
                            ItemView(item: item, action: $action)
                                .frame(width: geometry.size.width - 40)
                                .background(.white)
                                .overlay(
                                    RoundedRectangle(cornerRadius: 10)
                                        .stroke(Color.gray, lineWidth: 1)
                                )
                                .onTapGesture {
                                    print("안녕하세요")
                                }
                            //                            .onTapGesture {
                            //
                            //                            }
                            //                            .sheet(item: $selectedItem) { item in
                            //                                DetailView(item: item)
                            //                            }
                        })
                    }
                }
                
            })
            .frame(height: 200)
        }
    }
}

struct ItemView: View {
    let item: HomeListSectionItem
    @Binding var action: ItemAction
    
    var body: some View {
        switch(item) {
        case let .recentGoodsList(kartGoodsInfo):
            RecentGoodsInfoView(item: kartGoodsInfo, action: $action)
        }
    }
}

struct RecentGoodsInfoView: View {
    var item: KartGoodsInfo
    @Binding var action: ItemAction
    
    var body: some View {
        HStack() {
            ImageContainerView(item: item, action: $action)
                .padding(10)
            TextContainerView(item: item)
                .padding(10)
            Spacer()
        }
    }
}

struct ImageContainerView: View {
    
    let item: KartGoodsInfo
    @Binding var action: ItemAction
    
    var body: some View {
        ZStack(alignment: .bottomTrailing) {
            WebImage(url: URL(string: item.imageUrl)!,
                     content: { image in
                image
            },
                     placeholder: {
                Image(systemName: "face.smiling")
            })
            .resizable()
            .frame(width: 120, height: 120)
            .cornerRadius(25)
            .clipped()
            Button(action: {
                action.didTapHeartItem = item
            }, label: {
                if item.isFavorite {
                    Image(systemName: "heart.fill")
                        .resizable()
                        .scaledToFit()
                        .frame(width: 20, height: 20)
                        .foregroundColor(.red)
                } else {
                    Image(systemName: "heart")
                        .resizable()
                        .scaledToFit()
                        .frame(width: 20, height: 20)
                        .foregroundColor(.gray)
                }
            })
            .offset(x: -10, y: -10)
        }
    }
}

struct TextContainerView: View {
    
    var item: KartGoodsInfo
    
    var body: some View {
        VStack(alignment: .leading, spacing: 10) {
            Text(item.brandName)
                .foregroundColor(.gray)
            + Text(item.name)
            Text(item.price)
                .bold()
            HStack {
                Text("5% 캐시백")
                    .bold()
                    .font(.system(size: 10, weight: .bold))
                    .foregroundColor(.white)
                    .padding(5)
                    .background(.red)
                    .cornerRadius(5)
                    .clipped()
                Text("한정 이벤트")
                    .bold()
                    .font(.system(size: 10, weight: .bold))
                    .foregroundColor(.black)
                    .padding(5)
                    .background(.yellow)
                    .cornerRadius(5)
                    .clipped()
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        RootView(model: getRandomMockData())
    }
}

// Mock Data 및 KartGoodsInfo의 copy 메서드를 추가해야 합니다.
extension KartGoodsInfo {
    func copy() -> KartGoodsInfo {
        return KartGoodsInfo(id: self.id, brandName: self.brandName, name: self.name, price: self.price, imageUrl: self.imageUrl, isFavorite: self.isFavorite)
    }
}
profile
https://hyunndyblog.tistory.com/163 티스토리에서 이사 중

0개의 댓글