Files
service-finder/plans/finance_mock_data_and_back_button_blueprint_2026-07-26.md
2026-07-27 08:39:18 +00:00

14 KiB

🔵 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

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

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: <p class="text-3xl font-extrabold text-emerald-600">2,450</p> — literal HTML
  • GamificationCard.vue: 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

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

The FleetView header pattern:

<!-- Page header -->
<div class="mb-8 flex items-center justify-between">
  <div>
    <h1 class="text-3xl font-bold text-white">{{ t('garage.title') }}</h1>
    <p class="mt-1 text-sm text-white/60">{{ t('garage.subtitle', { count: ... }) }}</p>
  </div>
  <div class="flex items-center gap-3">
    <!-- Action buttons on the right -->
    <button ...>Add Vehicle</button>
    <button @click="router.push('/dashboard')" class="...bg-white/10...">
      <svg>...</svg>
      {{ t('garage.backToDashboard') }}
    </button>
  </div>
</div>

Key structural elements:

  1. Container: class="mb-8 flex items-center justify-between"
  2. Left side: <div> with <h1> title + optional <p> subtitle
  3. Right side: <div class="flex items-center gap-3"> 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 <Teleport to="#header-teleport-target"> to inject a page title into the global header:

All 4 need the same structural change.

2.3 The Fix: FleetView Pattern Applied to Finance

For each finance view:

  1. REMOVE the entire <Teleport ...> block

  2. REMOVE teleportReady, onMounted, onBeforeUnmount boilerplate

  3. ADD a local content header matching FleetView:

    <!-- Page header -->
    <div class="mb-8 flex items-center justify-between">
      <div>
        <h1 class="text-3xl font-bold text-white">💰 {{ t('menu.finance') }}</h1>
      </div>
      <div class="flex items-center gap-3">
        <button
          @click="router.push('/dashboard')"
          class="flex items-center gap-2 rounded-xl bg-white/10 px-4 py-2 text-sm text-white/80 transition-all duration-200 hover:bg-white/20 hover:text-white"
        >
          <svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18" />
          </svg>
          {{ t('garage.backToDashboard') }}
        </button>
      </div>
    </div>
    
  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

  1. Check if a gamification store exists:

    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 <p class="text-3xl font-extrabold text-emerald-600">2,450</p>
    • To: <p class="text-3xl font-extrabold text-emerald-600">{{ userScore }}</p>
    • 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

  1. Fix transaction count (line 57):

    • Change <p class="text-lg font-bold text-slate-800">—</p>
    • To: <p class="text-lg font-bold text-slate-800">{{ transactionCount }}</p>
    • Add: const transactionCount = computed(() => 0) — placeholder for now, will wire to real API later
  2. Fix package info (line 63):

    • Change <p class="text-lg font-bold text-slate-800">•</p>
    • To: <p class="text-lg font-bold text-slate-800">{{ authStore.user?.subscription_plan || '—' }}</p>
    • 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

  1. DELETE lines 38-40 — the entire Teleport block:

    <Teleport v-if="teleportReady" to="#header-teleport-target">
      <span class="text-white font-bold text-sm tracking-wide">💰 {{ t('menu.finance') }}</span>
    </Teleport>
    
  2. ADD local content header immediately after the Teleport block removal (before line 42's <div class="flex flex-col...">):

      <!-- ── Page header (FleetView.vue pattern) ── -->
      <div class="mb-8 flex items-center justify-between">
        <div>
          <h1 class="text-3xl font-bold text-white">💰 {{ t('menu.finance') }}</h1>
        </div>
        <div class="flex items-center gap-3">
          <button
            @click="router.push('/dashboard')"
            class="flex items-center gap-2 rounded-xl bg-white/10 px-4 py-2 text-sm text-white/80 transition-all duration-200 hover:bg-white/20 hover:text-white"
          >
            <svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18" />
            </svg>
            {{ t('garage.backToDashboard') }}
          </button>
        </div>
      </div>
    
  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

  1. DELETE lines 19-21 — the Teleport block

  2. ADD local content header (after line 21 deletion, before line 23's <div class="flex flex-col...">):

      <!-- ── Page header (FleetView.vue pattern) ── -->
      <div class="mb-8 flex items-center justify-between">
        <div>
          <h1 class="text-3xl font-bold text-white">💰 {{ t('finance.wallet') }}</h1>
        </div>
        <div class="flex items-center gap-3">
          <button
            @click="$router.push('/finance')"
            class="flex items-center gap-2 rounded-xl bg-white/10 px-4 py-2 text-sm text-white/80 transition-all duration-200 hover:bg-white/20 hover:text-white"
          >
            <svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
              <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18" />
            </svg>
            {{ t('common.back') }}
          </button>
        </div>
      </div>
    

    (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

  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

  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:

    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:

    docker compose exec sf_api python3 -c "from app.main import app; print('OK')"
    

📋 Summary Table

Task File Action
A GamificationCard.vue Replace 2,450 with live score, replace hardcoded badges
B ProfileTrustCard.vue Replace and with live/computed values
C FinanceMainView.vue Remove Teleport, add FleetView-style local header + back button
D FinanceWalletsView.vue Remove Teleport, add local header + back button to /finance
E FinancePackagesView.vue Remove Teleport, add local header + back button to /finance
F FinanceTransactionsView.vue Remove Teleport, add local header + back button to /finance
G Build + verify npm run build, backend imports check

⚠️ DO NOT MODIFY