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
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
shop.selectedProduct = sampleClothes
I can't use cardViewas they are different data types
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
Selecting any option will automatically load the page