Signed-off-by: Matt Bruce <matt.bruce1@toyota.com>
This commit is contained in:
parent
8cbd85dcce
commit
34455378fc
@ -35,10 +35,8 @@ struct ActionButtonsView: View {
|
|||||||
EmptyView()
|
EmptyView()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.animation(.spring(duration: Design.Animation.quick), value: state.currentPhase)
|
|
||||||
.animation(.easeInOut(duration: Design.Animation.standard), value: state.currentBet > 0)
|
|
||||||
}
|
}
|
||||||
.frame(minHeight: containerHeight)
|
.frame(height: containerHeight)
|
||||||
.padding(.horizontal, Design.Spacing.large)
|
.padding(.horizontal, Design.Spacing.large)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -130,20 +130,22 @@ struct GameTableView: View {
|
|||||||
)
|
)
|
||||||
.frame(maxWidth: maxContentWidth)
|
.frame(maxWidth: maxContentWidth)
|
||||||
|
|
||||||
// Chip selector - only shown during betting phase
|
// Chip selector - only shown during betting phase AND when result banner is NOT showing
|
||||||
if state.currentPhase == .betting {
|
if state.currentPhase == .betting && !state.showResultBanner {
|
||||||
Spacer()
|
|
||||||
.debugBorder(showDebugBorders, color: .yellow, label: "ChipSpacer")
|
|
||||||
|
|
||||||
ChipSelectorView(
|
ChipSelectorView(
|
||||||
selectedChip: $selectedChip,
|
selectedChip: $selectedChip,
|
||||||
balance: state.balance,
|
balance: state.balance,
|
||||||
currentBet: state.minBetForChipSelector, // Use min bet so chips stay enabled if any bet type can accept more
|
currentBet: state.minBetForChipSelector,
|
||||||
maxBet: state.settings.maxBet
|
maxBet: state.settings.maxBet
|
||||||
)
|
)
|
||||||
.frame(maxWidth: maxContentWidth)
|
.frame(maxWidth: maxContentWidth)
|
||||||
.transition(.opacity.combined(with: .move(edge: .bottom)))
|
|
||||||
.debugBorder(showDebugBorders, color: .pink, label: "ChipSelector")
|
.debugBorder(showDebugBorders, color: .pink, label: "ChipSelector")
|
||||||
|
.onAppear {
|
||||||
|
print("🎰 Chip selector APPEARED (banner showing: \(state.showResultBanner))")
|
||||||
|
}
|
||||||
|
.onDisappear {
|
||||||
|
print("🎰 Chip selector DISAPPEARED")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Action buttons - minimal spacing during player turn
|
// Action buttons - minimal spacing during player turn
|
||||||
@ -152,43 +154,78 @@ struct GameTableView: View {
|
|||||||
.padding(.bottom, Design.Spacing.small)
|
.padding(.bottom, Design.Spacing.small)
|
||||||
.debugBorder(showDebugBorders, color: .blue, label: "ActionBtns")
|
.debugBorder(showDebugBorders, color: .blue, label: "ActionBtns")
|
||||||
}
|
}
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity, alignment: .top)
|
||||||
|
.zIndex(1)
|
||||||
|
.onChange(of: state.currentPhase) { oldPhase, newPhase in
|
||||||
|
print("🔄 Phase changed: \(oldPhase) → \(newPhase)")
|
||||||
|
}
|
||||||
|
|
||||||
// Insurance popup overlay (covers entire screen)
|
// Insurance popup overlay (covers entire screen)
|
||||||
if state.currentPhase == .insurance {
|
if state.currentPhase == .insurance {
|
||||||
InsurancePopupView(
|
Color.clear
|
||||||
betAmount: state.currentBet / 2,
|
.overlay(alignment: .center) {
|
||||||
balance: state.balance,
|
InsurancePopupView(
|
||||||
onTake: { Task { await state.takeInsurance() } },
|
betAmount: state.currentBet / 2,
|
||||||
onDecline: { state.declineInsurance() }
|
balance: state.balance,
|
||||||
)
|
onTake: { Task { await state.takeInsurance() } },
|
||||||
.transition(.opacity.combined(with: .scale(scale: 0.9)))
|
onDecline: { state.declineInsurance() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.ignoresSafeArea()
|
||||||
|
.allowsHitTesting(true)
|
||||||
|
.transition(.opacity.combined(with: .scale(scale: 0.9)))
|
||||||
|
.zIndex(100)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Result banner overlay
|
// Result banner overlay
|
||||||
if state.showResultBanner, let result = state.lastRoundResult {
|
if state.showResultBanner, let result = state.lastRoundResult {
|
||||||
ResultBannerView(
|
Color.clear
|
||||||
result: result,
|
.overlay(alignment: .center) {
|
||||||
currentBalance: state.balance,
|
ResultBannerView(
|
||||||
minBet: state.settings.minBet,
|
result: result,
|
||||||
onNewRound: { state.newRound() },
|
currentBalance: state.balance,
|
||||||
onPlayAgain: { state.resetGame() }
|
minBet: state.settings.minBet,
|
||||||
)
|
onNewRound: { state.newRound() },
|
||||||
|
onPlayAgain: { state.resetGame() }
|
||||||
|
)
|
||||||
|
.onAppear {
|
||||||
|
print("🎯 RESULT BANNER APPEARED")
|
||||||
|
}
|
||||||
|
.onDisappear {
|
||||||
|
print("❌ RESULT BANNER DISAPPEARED")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ignoresSafeArea()
|
||||||
|
.allowsHitTesting(true)
|
||||||
|
.zIndex(100)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Confetti for wins (matching Baccarat pattern)
|
// Confetti for wins (matching Baccarat pattern)
|
||||||
if state.showResultBanner && (state.lastRoundResult?.totalWinnings ?? 0) > 0 {
|
if state.showResultBanner && (state.lastRoundResult?.totalWinnings ?? 0) > 0 {
|
||||||
ConfettiView()
|
ConfettiView()
|
||||||
|
.zIndex(101)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Game over
|
// Game over
|
||||||
if state.isGameOver && !state.showResultBanner {
|
if state.isGameOver && !state.showResultBanner {
|
||||||
GameOverView(
|
Color.clear
|
||||||
roundsPlayed: state.roundsPlayed,
|
.overlay(alignment: .center) {
|
||||||
onPlayAgain: { state.resetGame() }
|
GameOverView(
|
||||||
)
|
roundsPlayed: state.roundsPlayed,
|
||||||
|
onPlayAgain: { state.resetGame() }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.ignoresSafeArea()
|
||||||
|
.allowsHitTesting(true)
|
||||||
|
.zIndex(100)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.onChange(of: state.playerHands.count) { oldCount, newCount in
|
||||||
|
print("👥 Player hands count: \(oldCount) → \(newCount)")
|
||||||
|
}
|
||||||
|
.onChange(of: state.balance) { oldBalance, newBalance in
|
||||||
|
print("💰 Balance: \(oldBalance) → \(newBalance)")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -54,7 +54,6 @@ struct ResultBannerView: View {
|
|||||||
ZStack {
|
ZStack {
|
||||||
// Full screen dark background
|
// Full screen dark background
|
||||||
Color.black.opacity(Design.Opacity.strong)
|
Color.black.opacity(Design.Opacity.strong)
|
||||||
.ignoresSafeArea()
|
|
||||||
|
|
||||||
// Content card
|
// Content card
|
||||||
VStack(spacing: Design.Spacing.xLarge) {
|
VStack(spacing: Design.Spacing.xLarge) {
|
||||||
@ -193,18 +192,18 @@ struct ResultBannerView: View {
|
|||||||
.shadow(color: mainResultColor.opacity(Design.Opacity.hint), radius: Design.Shadow.radiusXLarge)
|
.shadow(color: mainResultColor.opacity(Design.Opacity.hint), radius: Design.Shadow.radiusXLarge)
|
||||||
.frame(maxWidth: CasinoDesign.Size.maxModalWidth)
|
.frame(maxWidth: CasinoDesign.Size.maxModalWidth)
|
||||||
.padding(.horizontal, Design.Spacing.large) // Prevent clipping on sides
|
.padding(.horizontal, Design.Spacing.large) // Prevent clipping on sides
|
||||||
.scaleEffect(showContent ? 1.0 : 0.8)
|
.scaleEffect(showContent ? Design.Scale.normal : Design.Scale.slightShrink)
|
||||||
.opacity(showContent ? 1.0 : 0)
|
.opacity(showContent ? 1.0 : 0)
|
||||||
}
|
}
|
||||||
.onAppear {
|
.onAppear {
|
||||||
withAnimation(.spring(duration: Design.Animation.springDuration, bounce: 0.3)) {
|
withAnimation(.spring(duration: Design.Animation.springDuration, bounce: Design.Animation.springBounce)) {
|
||||||
showContent = true
|
showContent = true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Play game over sound if out of chips (after a delay so it doesn't overlap with result sound)
|
// Play game over sound if out of chips (after a delay so it doesn't overlap with result sound)
|
||||||
if isGameOver {
|
if isGameOver {
|
||||||
Task {
|
Task {
|
||||||
try? await Task.sleep(for: .seconds(1))
|
try? await Task.sleep(for: .seconds(Design.Delay.gameOverSound))
|
||||||
SoundManager.shared.play(.gameOver)
|
SoundManager.shared.play(.gameOver)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -222,6 +221,8 @@ struct ResultRow: View {
|
|||||||
let result: HandResult
|
let result: HandResult
|
||||||
var amount: Int? = nil
|
var amount: Int? = nil
|
||||||
|
|
||||||
|
private var showDebugBorders: Bool { Design.showDebugBorders }
|
||||||
|
|
||||||
private var amountText: String? {
|
private var amountText: String? {
|
||||||
guard let amount = amount else { return nil }
|
guard let amount = amount else { return nil }
|
||||||
if amount > 0 {
|
if amount > 0 {
|
||||||
@ -243,24 +244,31 @@ struct ResultRow: View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
HStack {
|
HStack {
|
||||||
Text(label)
|
Text(label)
|
||||||
.font(.system(size: Design.BaseFontSize.body))
|
.font(.system(size: Design.BaseFontSize.medium))
|
||||||
.foregroundStyle(.white.opacity(Design.Opacity.strong))
|
.foregroundStyle(.white.opacity(Design.Opacity.strong))
|
||||||
|
.debugBorder(showDebugBorders, color: .blue, label: "Label")
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
.debugBorder(showDebugBorders, color: .yellow, label: "Spacer")
|
||||||
|
|
||||||
// Show amount if provided
|
// Show amount if provided
|
||||||
if let amountText = amountText {
|
if let amountText = amountText {
|
||||||
Text(amountText)
|
Text(amountText)
|
||||||
.font(.system(size: Design.BaseFontSize.body, weight: .semibold, design: .rounded))
|
.font(.system(size: Design.BaseFontSize.medium, weight: .semibold, design: .rounded))
|
||||||
.foregroundStyle(amountColor)
|
.foregroundStyle(amountColor)
|
||||||
.frame(width: 70, alignment: .trailing)
|
.frame(width: Design.Size.resultRowAmountWidth, alignment: .trailing)
|
||||||
|
.debugBorder(showDebugBorders, color: .green, label: "Amount")
|
||||||
}
|
}
|
||||||
|
|
||||||
Text(result.displayText)
|
Text(result.displayText)
|
||||||
.font(.system(size: Design.BaseFontSize.body, weight: .bold))
|
.font(.system(size: Design.BaseFontSize.large, weight: .bold))
|
||||||
.foregroundStyle(result.color)
|
.foregroundStyle(result.color)
|
||||||
.frame(width: 100, alignment: .trailing)
|
.frame(width: Design.Size.resultRowResultWidth, alignment: .trailing)
|
||||||
|
.lineLimit(1)
|
||||||
|
.minimumScaleFactor(Design.MinScaleFactor.comfortable)
|
||||||
|
.debugBorder(showDebugBorders, color: .red, label: "Result")
|
||||||
}
|
}
|
||||||
|
.debugBorder(showDebugBorders, color: .white, label: "ResultRow")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,6 +280,8 @@ struct SideBetResultRow: View {
|
|||||||
let isWin: Bool
|
let isWin: Bool
|
||||||
let amount: Int
|
let amount: Int
|
||||||
|
|
||||||
|
private var showDebugBorders: Bool { Design.showDebugBorders }
|
||||||
|
|
||||||
private var amountText: String {
|
private var amountText: String {
|
||||||
if amount > 0 {
|
if amount > 0 {
|
||||||
return "+$\(amount)"
|
return "+$\(amount)"
|
||||||
@ -295,23 +305,28 @@ struct SideBetResultRow: View {
|
|||||||
var body: some View {
|
var body: some View {
|
||||||
HStack {
|
HStack {
|
||||||
Text(label)
|
Text(label)
|
||||||
.font(.system(size: Design.BaseFontSize.body))
|
.font(.system(size: Design.BaseFontSize.medium))
|
||||||
.foregroundStyle(.white.opacity(Design.Opacity.strong))
|
.foregroundStyle(.white.opacity(Design.Opacity.strong))
|
||||||
|
.debugBorder(showDebugBorders, color: .blue, label: "Label")
|
||||||
|
|
||||||
Spacer()
|
Spacer()
|
||||||
|
.debugBorder(showDebugBorders, color: .yellow, label: "Spacer")
|
||||||
|
|
||||||
Text(amountText)
|
Text(amountText)
|
||||||
.font(.system(size: Design.BaseFontSize.body, weight: .semibold, design: .rounded))
|
.font(.system(size: Design.BaseFontSize.medium, weight: .semibold, design: .rounded))
|
||||||
.foregroundStyle(amountColor)
|
.foregroundStyle(amountColor)
|
||||||
.frame(width: 70, alignment: .trailing)
|
.frame(width: Design.Size.resultRowAmountWidth, alignment: .trailing)
|
||||||
|
.debugBorder(showDebugBorders, color: .green, label: "Amount")
|
||||||
|
|
||||||
Text(resultText)
|
Text(resultText)
|
||||||
.font(.system(size: Design.BaseFontSize.body, weight: .bold))
|
.font(.system(size: Design.BaseFontSize.large, weight: .bold))
|
||||||
.foregroundStyle(resultColor)
|
.foregroundStyle(resultColor)
|
||||||
.frame(width: 100, alignment: .trailing)
|
.frame(width: Design.Size.resultRowResultWidth, alignment: .trailing)
|
||||||
.lineLimit(1)
|
.lineLimit(1)
|
||||||
.minimumScaleFactor(Design.MinScaleFactor.comfortable)
|
.minimumScaleFactor(Design.MinScaleFactor.comfortable)
|
||||||
|
.debugBorder(showDebugBorders, color: .red, label: "Result")
|
||||||
}
|
}
|
||||||
|
.debugBorder(showDebugBorders, color: .white, label: "SideBetRow")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user