I'm trying to create a swipeable shopping app prototype and came across a problem that I simply can't figure out.
My goal is to make each card clickable, so that when a user taps on one of them, it shows them another view with more product details
I've already made the cards swipeable, and i've already made each card clickable.
I am unable to figure out how to update the information in product view so that it matches with the clicked card
The problem lies in
I can't use
Any help/suggestions would be greatly appreciated, as I have tried literally everything I could think of over the past 3 days to solve this.
P.S- i can provide more code if needed. apologies for the long pasted code
My goal is to make each card clickable, so that when a user taps on one of them, it shows them another view with more product details
I've already made the cards swipeable, and i've already made each card clickable.
I am unable to figure out how to update the information in product view so that it matches with the clicked card
Code Block language struct ContentView: View { // MARK: - PROPERTIES @EnvironmentObject var shop: Shop @State var showLiked: Bool = false @State var showBag: Bool = false @GestureState private var dragState = DragState.inactive private let dragAreaThreshold: CGFloat = 65.0 @State private var lastCardIndex: Int = 1 @State private var cardRemovalTransition = AnyTransition.trailingBotton // MARK: - CARD VIEWS @State var cardViews: [CardView] = { var views = [CardView]() for index in 0..<2 { views.append(CardView(zoope: zoopeData[index])) } return views }() // MARK: - MOVE THE CARD private func moveCards() { cardViews.removeFirst() self.lastCardIndex += 1 let zoope = zoopeData[lastCardIndex % zoopeData.count] let newCardView = CardView(zoope: zoope) cardViews.append(newCardView) } // MARK: - TOP CARD private func isTopCard(cardView: CardView) -> Bool { guard let index = cardViews.firstIndex(where: { $0.id == cardView.id }) else { return false } return index == 0 } // MARK: - DRAG STATE enum DragState { case inactive case pressing case dragging(translation: CGSize) var translation: CGSize { switch self { case .inactive, .pressing: return .zero case .dragging(let translation): return translation } } var isDragging: Bool { switch self { case .dragging: return true case .pressing, .inactive: return false } } var isPressing: Bool { switch self { case .pressing, .dragging: return true case .inactive: return false } } } var body: some View { VStack { if shop.showingProduct == false && shop.selectedProduct == nil { ZStack { Color("ColorBackground") .ignoresSafeArea(edges: .all) VStack { // MARK: - HEADER HeaderView() Spacer() // MARK: - CARDS ZStack { ForEach(cardViews) { cardView in cardView .zIndex(self.isTopCard(cardView: cardView) ? 1 : 0) .onTapGesture { shop.selectedProduct = sampleClothes shop.showingProduct = true } .overlay( ZStack { // X-MARK SYMBOL Image(systemName: "x.circle") .modifier(SymbolModifier()) .opacity(self.dragState.translation.width < -self.dragAreaThreshold && self.isTopCard(cardView: cardView) ? 1.0 : 0.0) // HEART SYMBOL Image(systemName: "heart.circle") .modifier(SymbolModifier()) .opacity(self.dragState.translation.width > self.dragAreaThreshold && self.isTopCard(cardView: cardView) ? 1.0 : 0.0) } ) .offset(x: self.isTopCard(cardView: cardView) ? self.dragState.translation.width : 0, y: self.isTopCard(cardView: cardView) ? self.dragState.translation.height : 0) .scaleEffect(self.dragState.isDragging && self.isTopCard(cardView: cardView) ? 0.85 : 1.0) .rotationEffect(Angle(degrees: self.isTopCard(cardView: cardView) ? Double(self.dragState.translation.width / 12) : 0)) .animation(.interpolatingSpring(stiffness: 120, damping: 120)) .gesture(LongPressGesture(minimumDuration: 0.01) .sequenced(before: DragGesture()) .updating(self.$dragState, body: { (value, state, transaction) in switch value { case .first(true): state = .pressing case .second(true, let drag): state = .dragging(translation: drag?.translation ?? .zero) default: break } }) .onChanged({ (value) in guard case .second(true ,let drag?) = value else { return } if drag.translation.width < -self.dragAreaThreshold { self.cardRemovalTransition = .leadingBottom } if drag.translation.width > self.dragAreaThreshold { self.cardRemovalTransition = .trailingBotton } }) .onEnded({ (value) in guard case .second(true, let drag?) = value else { return } if drag.translation.width < -self.dragAreaThreshold || drag.translation.width > self.dragAreaThreshold { self.moveCards() } }) ).transition(self.cardRemovalTransition) } } .padding() Spacer() // MARK: - FOOTER FooterView(showLikedView: $showLiked, showBagView: $showBag) .opacity(dragState.isDragging ? 0.0 : 1.0) .animation(.default) } } } else { ProductDetailView() } } } }
The problem lies in
Code Block shop.selectedProduct = sampleClothes
I can't use
Code Block cardView
as they are different data typesAny help/suggestions would be greatly appreciated, as I have tried literally everything I could think of over the past 3 days to solve this.
P.S- i can provide more code if needed. apologies for the long pasted code