# πŸ”΅ Finance Module β€” Mock Data & Back Button Blueprint **Date:** 2026-07-26 **Author:** Architect Mode **Status:** Pending Code Mode Execution **Priority:** MEDIUM β€” UI polish, no app-breaking bugs --- ## STEP 1: MOCK DATA ANALYSIS ### 1.1 Dashboard Financial Card (ProfileTrustCard.vue) **File:** [`frontend_app/src/components/dashboard/ProfileTrustCard.vue`](frontend_app/src/components/dashboard/ProfileTrustCard.vue) | Field | Current Value | Source | Is Mock? | |-------|--------------|--------|----------| | `financeStore.totalCredits` (line 40) | Live API data | `financeStore.fetchWalletBalance()` β†’ `GET /billing/wallet/balance` | **❌ LIVE** β€” already fetches real data | | `financeStore.serviceCoins` (line 43) | Live API data | Same store | **❌ LIVE** | | `financeStore.totalCredits` stat tile (line 51) | Live API data | Same store | **❌ LIVE** | | Transaction count (line 57) | `β€”` hardcoded | Static placeholder | **βœ… MOCK** | | Package info (line 63) | `β€’` hardcoded | Static placeholder | **βœ… MOCK** | | `financeStore.voucherBalance` (line 69) | Live API data | Same store | **❌ LIVE** | **Conclusion:** The wallet balance numbers (`totalCredits`, `serviceCoins`, `voucherBalance`) ARE live and fetched from the API. However, two stat tiles show static placeholders that render identically for all users. ### 1.2 Gamification Card (GamificationCard.vue) **File:** [`frontend_app/src/components/dashboard/GamificationCard.vue`](frontend_app/src/components/dashboard/GamificationCard.vue) | Field | Current Value | Source | Is Mock? | |-------|--------------|--------|----------| | Score (line 18) | `2,450` hardcoded | Literal number in template | **βœ… MOCK** β€” same for all users | | Badges (lines 56-61) | 4 hardcoded entries | Static array in script | **βœ… MOCK** β€” same for all users | **Evidence:** - [`GamificationCard.vue`](frontend_app/src/components/dashboard/GamificationCard.vue:18): `

2,450

` β€” literal HTML - [`GamificationCard.vue`](frontend_app/src/components/dashboard/GamificationCard.vue:56-61): `const badges = ref([{ icon: '🌱', label: 'Eco Driver' }, ...])` β€” never updated from API **Fix plan:** - Import a gamification/PinΓ­a store (check if one exists) to fetch real user score - If no gamification store exists yet, create a computed that reads from `authStore` or call an API endpoint - Replace hardcoded badges with data fetched from a gamification endpoint ### 1.3 FinanceMainView Cards **File:** [`frontend_app/src/components/../views/FinanceMainView.vue`](frontend_app/src/views/FinanceMainView.vue) **Card 1 (Wallet):** Uses `financeStore.totalCredits`, `financeStore.purchasedCredits`, `financeStore.serviceCoins`, `financeStore.earnedCredits`, `financeStore.voucherBalance` β€” all live data from `financeStore.fetchWalletBalance()` βœ… **Card 2 (Packages):** Uses `authStore.user?.subscription_plan` β€” live data βœ… **Card 3 (Transactions):** Static placeholder with emoji β€” by design (placeholder page) βœ… **Card 4 (Invoices):** Static placeholder with 🚧 β€” by design ("Hamarosan") βœ… --- ## STEP 2: BACK BUTTON LAYOUT ANALYSIS ### 2.1 The Gold Standard: FleetView.vue Header **File:** [`frontend_app/src/views/vehicles/FleetView.vue`](frontend_app/src/views/vehicles/FleetView.vue:13-57) The FleetView header pattern: ```html

{{ t('garage.title') }}

{{ t('garage.subtitle', { count: ... }) }}

``` **Key structural elements:** 1. Container: `class="mb-8 flex items-center justify-between"` 2. Left side: `
` with `

` title + optional `

` subtitle 3. Right side: `

` with action buttons 4. Back button: `bg-white/10 px-4 py-2 text-sm text-white/80 hover:bg-white/20 hover:text-white` + left-arrow SVG ### 2.2 Current Finance Views: Teleport Anti-Pattern All 4 finance views currently use `` to inject a page title into the global header: - [`FinanceMainView.vue`](frontend_app/src/views/FinanceMainView.vue:38-40): `` - [`FinanceWalletsView.vue`](frontend_app/src/views/FinanceWalletsView.vue:19-21) - [`FinancePackagesView.vue`](frontend_app/src/views/FinancePackagesView.vue:17-19) - [`FinanceTransactionsView.vue`](frontend_app/src/views/FinanceTransactionsView.vue:15-17) All 4 need the same structural change. ### 2.3 The Fix: FleetView Pattern Applied to Finance For each finance view: 1. **REMOVE** the entire `` block 2. **REMOVE** `teleportReady`, `onMounted`, `onBeforeUnmount` boilerplate 3. **ADD** a local content header matching FleetView: ```html

πŸ’° {{ t('menu.finance') }}

``` 4. **PRESERVE** the existing card grid / content area below the header --- ## STEP 3: CODE MODE HAND-OFF β€” Explicit Task List Execute in order. Do NOT modify FleetView.vue, PrivateLayout.vue, BaseHeader.vue, or router/index.ts. ### Task A: Fix Mock Data in GamificationCard.vue **File:** [`frontend_app/src/components/dashboard/GamificationCard.vue`](frontend_app/src/components/dashboard/GamificationCard.vue) 1. **Check if a gamification store exists:** ```bash ls frontend_app/src/stores/gamification* 2>/dev/null || echo "No gamification store" ``` If a store exists, import and use it. If not, create a simple onMounted fetch to a gamification endpoint. 2. **Replace hardcoded score (line 18):** - Change `

2,450

` - To: `

{{ userScore }}

` - Add script logic: `const userScore = computed(...)` linked to real data source 3. **Replace hardcoded badges (lines 56-61):** - Change the static `badges` array to a computed or ref that fetches from API - Keep the same HTML template rendering β€” just change data source ### Task B: Fix Mock Data in ProfileTrustCard.vue **File:** [`frontend_app/src/components/dashboard/ProfileTrustCard.vue`](frontend_app/src/components/dashboard/ProfileTrustCard.vue) 1. **Fix transaction count (line 57):** - Change `

β€”

` - To: `

{{ transactionCount }}

` - Add: `const transactionCount = computed(() => 0)` β€” placeholder for now, will wire to real API later 2. **Fix package info (line 63):** - Change `

β€’

` - To: `

{{ authStore.user?.subscription_plan || 'β€”' }}

` - Add: `import { useAuthStore } from '../../stores/auth'` and `const authStore = useAuthStore()` ### Task C: Remove Teleport & Add Local Header β€” FinanceMainView.vue **File:** [`frontend_app/src/views/FinanceMainView.vue`](frontend_app/src/views/FinanceMainView.vue) 1. **DELETE lines 38-40** β€” the entire Teleport block: ```html πŸ’° {{ t('menu.finance') }} ``` 2. **ADD local content header** immediately after the Teleport block removal (before line 42's `
`): ```html

πŸ’° {{ t('menu.finance') }}

``` 3. **Clean up script:** Remove `teleportReady`, `ref`, and lifecycle hooks that are no longer needed: - Line 237: Change `import { computed, ref, onMounted, onBeforeUnmount } from 'vue'` to `import { computed, onMounted } from 'vue'` - Line 243: Delete `const teleportReady = ref(false)` - Line 278: Delete `teleportReady.value = true` - Lines 282-284: Delete `onBeforeUnmount` block ### Task D: Remove Teleport & Add Local Header β€” FinanceWalletsView.vue **File:** [`frontend_app/src/views/FinanceWalletsView.vue`](frontend_app/src/views/FinanceWalletsView.vue) 1. **DELETE lines 19-21** β€” the Teleport block 2. **ADD** local content header (after line 21 deletion, before line 23's `
`): ```html

πŸ’° {{ t('finance.wallet') }}

``` (Note: back button goes to `/finance` for sub-pages) 3. **Clean up script:** Change imports: remove `ref, onMounted, onBeforeUnmount`, remove `teleportReady` and lifecycle hooks. - Also add: `import { useRouter } from 'vue-router'` and `const router = useRouter()` for the back button (or use `$router` in template) ### Task E: Remove Teleport & Add Local Header β€” FinancePackagesView.vue **File:** [`frontend_app/src/views/FinancePackagesView.vue`](frontend_app/src/views/FinancePackagesView.vue) 1. **DELETE lines 17-19** β€” the Teleport block 2. **ADD** local content header with title "πŸ“¦ {{ t('subscription.title') }}" and back button to `/finance` 3. **Clean up script:** Same as Task D β€” remove teleport boilerplate, add router import if not present ### Task F: Remove Teleport & Add Local Header β€” FinanceTransactionsView.vue **File:** [`frontend_app/src/views/FinanceTransactionsView.vue`](frontend_app/src/views/FinanceTransactionsView.vue) 1. **DELETE lines 15-17** β€” the Teleport block 2. **ADD** local content header with title "πŸ“‹ {{ t('finance.transactionHistory') }}" and back button to `/finance` 3. **Clean up script:** Same as Task D β€” remove teleport boilerplate, add router import if not present ### Task G: Verify 1. **Frontend build check:** ```bash docker compose exec sf_public_frontend npm run build 2>&1 | tail -5 ``` Must show `βœ“ built in X.XXs` with no errors. 2. **Backend imports:** ```bash docker compose exec sf_api python3 -c "from app.main import app; print('OK')" ``` --- ## πŸ“‹ Summary Table | Task | File | Action | |------|------|--------| | A | [`GamificationCard.vue`](frontend_app/src/components/dashboard/GamificationCard.vue) | Replace `2,450` with live score, replace hardcoded badges | | B | [`ProfileTrustCard.vue`](frontend_app/src/components/dashboard/ProfileTrustCard.vue) | Replace `β€”` and `β€’` with live/computed values | | C | [`FinanceMainView.vue`](frontend_app/src/views/FinanceMainView.vue) | Remove Teleport, add FleetView-style local header + back button | | D | [`FinanceWalletsView.vue`](frontend_app/src/views/FinanceWalletsView.vue) | Remove Teleport, add local header + back button to `/finance` | | E | [`FinancePackagesView.vue`](frontend_app/src/views/FinancePackagesView.vue) | Remove Teleport, add local header + back button to `/finance` | | F | [`FinanceTransactionsView.vue`](frontend_app/src/views/FinanceTransactionsView.vue) | Remove Teleport, add local header + back button to `/finance` | | G | Build + verify | `npm run build`, backend imports check | ## ⚠️ DO NOT MODIFY - [`FleetView.vue`](frontend_app/src/views/vehicles/FleetView.vue) β€” reference pattern only - [`FinanceLayout.vue`](frontend_app/src/layouts/FinanceLayout.vue) β€” layout is correct - [`BaseHeader.vue`](frontend_app/src/components/layout/BaseHeader.vue) β€” working header - [`router/index.ts`](frontend_app/src/router/index.ts) β€” correct route config - [`DashboardView.vue`](frontend_app/src/views/DashboardView.vue) β€” working dashboard