Documentation Index
Fetch the complete documentation index at: https://mintlify.com/ImLukzy/ChefDash/llms.txt
Use this file to discover all available pages before exploring further.
RecipesView is the beating heart of ChefDash — the screen where every round is actually played. Once a level starts, the player stares down a target burger recipe displayed as a row of emoji slots, a ticking arcade timer, and a shuffling grid of ingredient buttons. Their only job is to tap each ingredient in the exact correct order, one by one, before the clock hits zero. Every correct order earns coins and raises the combo multiplier; every mistake costs precious seconds and resets the combo. The round ends the moment the timer expires, at which point the final star rating is calculated and control passes to VictoryView.
How the Round Starts
RecipesView becomes active when ContentView detects gameState.activeTab == "kitchen_round". This value is set immediately after gameState.startNewRound() is called from the pre-game modal on the map screen.
The
CustomTabBar is hidden while activeTab == "kitchen_round". ContentView checks activeTab != "kitchen_round" before rendering the tab bar, keeping the gameplay canvas clean and distraction-free. The same hiding logic applies to "level_complete"..onAppear, RecipesView performs three setup steps:
- Resets
timeRemainingto15.0seconds as the initial baseline. - Reads
gameState.currentLevel.availableIngredientsand stores a shuffled copy inrandomizedIngredients— the local@Statearray that drives the ingredient grid. - Registers the
onRecipeSuccessBonusTimeclosure (see Horno Industrial upgrade).
"oven") upgrade was selected for the round, an additional +5.0 seconds is added to timeRemaining at this point.
Core Gameplay Loop
Generate the next order
gameState.generateNextOrder() is called — either at round start (via startNewRound) or immediately after the previous order is completed. It picks a random recipe from currentLevel.possibleRecipes and writes it to targetRecipeEmojis. It also derives a display name (currentRecipeName) from the recipe’s contents: "Mega Bacon Burger" for recipes containing 🥓, "Fresh Veggie Burger" for 🥬, and "Classic Cheeseburger" otherwise.Player reads the target recipe
The HUD displays
currentRecipeName in the arcade orange accent color, and below it renders each emoji in targetRecipeEmojis as a row of frosted slots — one slot per required ingredient, in order. The player must replicate this sequence exactly.Player taps an ingredient button
The ingredient grid (
LazyVGrid) renders every emoji in randomizedIngredients. Each button tap calls gameState.addIngredient(_ emoji: String) and — regardless of correctness — immediately shuffles the grid via a spring animation, making each press feel snappy and keeping the layout unpredictable.addIngredient validates positionally
GameState.addIngredient appends the tapped emoji to currentBurgerStack, then walks every index so far and compares currentBurgerStack[i] against targetRecipeEmojis[i]. The first mismatch — or a stack that has grown beyond the target length — immediately calls triggerError(). If all positions match and the stack length equals the target, triggerSuccess() is called.On success — coins, combo, bonus time
triggerSuccess() increments ordersCompletedInSession, awards (25 + bonusCoins) * comboMultiplier coins, and bumps comboMultiplier by 1 (capped at 5). It sets showPerfectMessage = true, triggers the onRecipeSuccessBonusTime closure (granting +1.5s to the timer on every successful order), then clears the flag and calls generateNextOrder() after 0.8 seconds.On error — penalty, reset, clear
triggerError() sets showErrorMessage = true and resets comboMultiplier to 1. After 0.8 seconds the flag clears and currentBurgerStack is emptied, giving the player a clean plate to try again on the same order. Note that errors in RecipesView also subtract 3.0 seconds from timeRemaining before calling addIngredient — this deduction happens in the view, not in GameState.Timer Mechanics
RecipesView owns the timer entirely via a Timer.publish(every: 0.1, ...) Combine publisher connected in .onReceive. Each tick decrements timeRemaining by 0.1. When timeRemaining drops to or below 0.1 the publisher is cancelled, the star rating is calculated inline, gameState.finishRound(starsEarned:) is called, and the screen transitions to "level_complete".
timeRemaining <= 5.0, providing a last-seconds visual warning.
The Horno Industrial Upgrade
The Horno Industrial shop item (id: "oven") grants an extra +5.0 seconds at round start. This is the only time-bonus gated by the upgrade:
| Moment | Amount | Condition |
|---|---|---|
Round start (onAppear) | +5.0 s | Only when selectedUpgradesForRound.contains("oven") |
RecipesView always registers an onRecipeSuccessBonusTime closure that adds +1.5 seconds to the timer on every successful order — regardless of whether the Horno Industrial upgrade was active. This closure is set unconditionally in .onAppear:
GameState.triggerSuccess() calls onRecipeSuccessBonusTime?() — it does not mutate timeRemaining directly. This design keeps time management entirely inside RecipesView, where the local @State var timeRemaining lives. Calling the closure from GameState rather than passing a binding avoids threading issues with the Combine timer.Visual Feedback Overlays
Both feedback states are driven by@Published flags on GameState that auto-clear after 0.8 seconds.
✨ Perfect Order
showPerfectMessage = true renders a green capsule overlay reading ”✨ +1.5s ✨” centered over the burger assembly plate. The +1.5s label reflects the bonus time added to timeRemaining on every successful order via the onRecipeSuccessBonusTime closure.💥 Wrong Ingredient
showErrorMessage = true renders a red capsule overlay reading ”💥 -3.0s” over the same plate. The -3.0s penalty is subtracted from timeRemaining in the view at the moment the wrong ingredient is tapped.Combo Multiplier
WhencomboMultiplier > 1, a "🔥 x{N}" badge appears in the header HUD between the exit button and the timer. The multiplier starts at 1 (or 2 with the Cuchillo Afilado upgrade) and increments by 1 on each correct order, capped at 5. Any wrong ingredient resets it to 1.
Clearing the Plate
A “LIMPIAR PLATO” button at the bottom of the ingredient grid clearscurrentBurgerStack directly and reshuffles the ingredient grid. This is a convenience reset that does not trigger triggerError(), so it carries no time penalty and does not break the combo.