frontend költség beállítások
This commit is contained in:
275
plans/p0_vehicle_card_fix_plan.md
Normal file
275
plans/p0_vehicle_card_fix_plan.md
Normal file
@@ -0,0 +1,275 @@
|
||||
# P0 Végrehajtási Terv: Vehicle Components & Modal Javítások
|
||||
|
||||
**Státusz:** Tervezés alatt
|
||||
**Dátum:** 2026-06-21
|
||||
**Architect:** Rendszer-Architect
|
||||
|
||||
---
|
||||
|
||||
## 1. Áttekintés
|
||||
|
||||
A P0 feladat a meglévő jármű komponensek 4 problémás területének javítása az Architect modul elemzése alapján. A terv 3 fájl módosítását írja elő, új komponensek létrehozása NÉLKÜL.
|
||||
|
||||
### Érintett fájlok:
|
||||
| # | Fájl | Művelet | Hatás |
|
||||
|---|------|---------|-------|
|
||||
| 1 | `frontend/src/types/vehicle.ts` | `image_url` mező hozzáadása a `VehicleData` interfészhez | Type safety |
|
||||
| 2 | `frontend/src/components/vehicle/VehicleCardStandard.vue` | 5 adatkötés javítás | UI adatok helyes megjelenítése |
|
||||
| 3 | `frontend/src/components/vehicle/VehicleDetailModal.vue` | 5. tab (TechData) integráció + Pénzügyek tab bővítés | Teljes TCO láthatóság |
|
||||
|
||||
---
|
||||
|
||||
## 2. Részletes Módosítási Terv
|
||||
|
||||
### 2.1 `VehicleData` típus bővítése
|
||||
|
||||
**Fájl:** [`frontend/src/types/vehicle.ts`](frontend/src/types/vehicle.ts:10)
|
||||
|
||||
```typescript
|
||||
export interface VehicleData {
|
||||
// ... existing fields ...
|
||||
image_url?: string | null; // ÚJ mező a kép URL tárolására
|
||||
}
|
||||
```
|
||||
|
||||
**Indoklás:** A `VehicleCardStandard.vue` `:src="vehicle.image_url"`-t használna, de a `VehicleData` interfészből hiányzik ez a mező. A backend már visszaadhat `image_url`-t az `AssetResponse`-ben (lásd [`assets.py:386`](backend/app/api/v1/endpoints/assets.py:386)).
|
||||
|
||||
---
|
||||
|
||||
### 2.2 `VehicleCardStandard.vue` - 5 adatkötés javítás
|
||||
|
||||
**Fájl:** [`frontend/src/components/vehicle/VehicleCardStandard.vue`](frontend/src/components/vehicle/VehicleCardStandard.vue)
|
||||
|
||||
| # | Probléma | Javítás | Sor |
|
||||
|---|----------|---------|-----|
|
||||
| 1 | `is_primary` csillag gomb (megvan, de nincs szöveges badge) | **Nem változtatunk** - a meglévő star toggle működik, a feladat csak a data bindings-okról szól | 119-131 |
|
||||
| 2 | `color` mező: `vehicle.individual_equipment?.color \|\| vehicle.color \|\| '—'` | Lecserélés erre: `vehicle.individual_equipment?.color \|\| 'N/A'` | 103 |
|
||||
| 3 | `engine` mező: `vehicle.engine \|\| vehicle.fuel_type \|\| '—'` | Lecserélés erre: `` `${vehicle.power_kw || '?'} kW / ${vehicle.engine_capacity || '?'} cm³` `` | 95 |
|
||||
| 4 | `country_code` mező: `vehicle.countryCode \|\| vehicle.country_code` | **Hozzáadás** `registration_country` használatával | 62 |
|
||||
| 5 | `image` mező: `vehicle.image` | Lecserélés `vehicle.image_url`-re, fallback SVG placeholder | 9-10 |
|
||||
|
||||
**Részletes módosítások:**
|
||||
|
||||
**2.2.a - Image (9-10. sor):**
|
||||
```html
|
||||
<img v-if="vehicle.image_url" :src="vehicle.image_url" alt="" class="..." />
|
||||
<template v-else>
|
||||
<svg ... ></svg> <!-- Meglévő placeholder SVG változatlan -->
|
||||
</template>
|
||||
```
|
||||
|
||||
**2.2.b - Country (62. sor):**
|
||||
```html
|
||||
<span class="...">{{ vehicle.registration_country || vehicle.countryCode || vehicle.country_code || '—' }}</span>
|
||||
```
|
||||
|
||||
**2.2.c - Engine (95. sor):**
|
||||
```html
|
||||
<span class="...">{{ vehicle.power_kw ? vehicle.power_kw + ' kW' : '?' }} / {{ vehicle.engine_capacity ? vehicle.engine_capacity + ' cm³' : '?' }}</span>
|
||||
```
|
||||
|
||||
**2.2.d - Color (103. sor):**
|
||||
```html
|
||||
<span class="...">{{ vehicle.individual_equipment?.color || 'N/A' }}</span>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2.3 `VehicleDetailModal.vue` - TechData Tab integráció
|
||||
|
||||
**Fájl:** [`frontend/src/components/vehicle/VehicleDetailModal.vue`](frontend/src/components/vehicle/VehicleDetailModal.vue)
|
||||
|
||||
#### Háttér
|
||||
A [`TechDataTab.vue`](frontend/src/components/vehicles/tabs/TechDataTab.vue) LÉTEZIK (279 sor), de **NINCS integrálva** a modálba. Jelenleg 4 tab van (`basics`, `finance`, `alerts`, `servicebook`).
|
||||
|
||||
#### Megoldás: 5. tab hozzáadása
|
||||
|
||||
**a) Tab gomb hozzáadása (a meglévő tab gombok után, ~866-873. sor):**
|
||||
```html
|
||||
<button @click="activeTab = 'techdata'" :class="activeTab === 'techdata' ? '...' : '...'">
|
||||
{{ $t('vehicle.techData') || 'Műszaki adatok' }}
|
||||
</button>
|
||||
```
|
||||
|
||||
**b) Tab content blokk hozzáadása (a servicebook tab után, ~736. sor után):**
|
||||
```html
|
||||
<div v-if="activeTab === 'techdata'" class="space-y-5">
|
||||
<TechDataTab />
|
||||
</div>
|
||||
```
|
||||
|
||||
**c) Import hozzáadása (script section):**
|
||||
```typescript
|
||||
import TechDataTab from '@/components/vehicles/tabs/TechDataTab.vue';
|
||||
```
|
||||
|
||||
**d) `provide/inject` kompatibilitás biztosítása:**
|
||||
A [`TechDataTab.vue`](frontend/src/components/vehicles/tabs/TechDataTab.vue:107) `inject<computed<Vehicle | null>>('vehicle')`-t használ. A `VehicleDetailModal.vue`-ban a `vehicle` computed property már létezik. A provide-ot a modal szülőjének (vagy a modal-nak magának) kell biztosítania.
|
||||
|
||||
**Megvizsgálandó:** A `VehicleDetailModal.vue` jelenleg `props`-on keresztül kapja a vehicle adatokat. Ha a `TechDataTab.vue` `inject('vehicle')`-t vár, akkor vagy:
|
||||
- Biztosítani kell a `provide('vehicle', computed(...))`-t a modalban, VAGY
|
||||
- Át kell alakítani a TechDataTab-et, hogy elfogadjon egy prop-ot is.
|
||||
|
||||
**Ajánlás:** Mivel a [`OverviewTab.vue`](frontend/src/components/vehicles/tabs/OverviewTab.vue) is ugyanezt az `inject`-es mintát használja, a legegyszerűbb megoldás a `provide` hozzáadása a `VehicleDetailModal.vue`-hoz:
|
||||
|
||||
```typescript
|
||||
// A script setup blokkban
|
||||
import { provide, computed } from 'vue';
|
||||
|
||||
const vehicle = computed(() => props.vehicle || null);
|
||||
provide('vehicle', vehicle);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2.4 `VehicleDetailModal.vue` - Pénzügyek Tab bővítés
|
||||
|
||||
#### Jelenlegi állapot
|
||||
A `finance` tab (282-436. sor) csak `GET /assets/{id}/costs`-t hív (944-957. sor) és két részből áll: non-premium esetén egyszerű lista, premium esetén chart.
|
||||
|
||||
#### Bővítés: 3 új API hívás párhuzamosan
|
||||
|
||||
**Backend endpointok (már léteznek, VERIFIKÁLVA):**
|
||||
| Endpoint | Visszatérési típus | Helye |
|
||||
|----------|-------------------|-------|
|
||||
| `GET /api/v1/assets/vehicles/{id}/financials` | `AssetFinancialsResponse` | [`assets.py:1245`](backend/app/api/v1/endpoints/assets.py:1245) |
|
||||
| `GET /api/v1/assets/vehicles/{id}/insurance` | `List[VehicleInsurancePolicyResponse]` | [`assets.py:1314`](backend/app/api/v1/endpoints/assets.py:1314) |
|
||||
| `GET /api/v1/assets/vehicles/{id}/tax` | `List[VehicleTaxObligationResponse]` | [`assets.py:1376`](backend/app/api/v1/endpoints/assets.py:1376) |
|
||||
|
||||
**Store metódusok (már léteznek, VERIFIKÁLVA):**
|
||||
| Metódus | Param | Visszatérés |
|
||||
|---------|-------|-------------|
|
||||
| `fetchAssetFinancials(assetId)` | `string` | `Promise<AssetFinancials \| null>` | [`vehicle.ts:318`](frontend/src/stores/vehicle.ts:318) |
|
||||
| `fetchInsurancePolicies(assetId)` | `string` | `Promise<VehicleInsurancePolicy[]>` | [`vehicle.ts:346`](frontend/src/stores/vehicle.ts:346) |
|
||||
| `fetchTaxObligations(assetId)` | `string` | `Promise<VehicleTaxObligation[]>` | [`vehicle.ts:388`](frontend/src/stores/vehicle.ts:388) |
|
||||
|
||||
#### Tervezett módosítások a `VehicleDetailModal.vue`-ban:
|
||||
|
||||
**a) Új state változók (script setup):**
|
||||
```typescript
|
||||
const assetFinancials = ref<AssetFinancials | null>(null);
|
||||
const insurancePolicies = ref<VehicleInsurancePolicy[]>([]);
|
||||
const taxObligations = ref<VehicleTaxObligation[]>([]);
|
||||
const financeLoading = ref(false);
|
||||
```
|
||||
|
||||
**b) Párhuzamos API hívás a `loadFinanceData` függvényben (~944. sor környékén):**
|
||||
```typescript
|
||||
async function loadFinanceData() {
|
||||
financeLoading.value = true;
|
||||
try {
|
||||
const vehicleId = props.vehicle?.id?.toString();
|
||||
if (!vehicleId) return;
|
||||
|
||||
// Promise.all a 3 új híváshoz
|
||||
const [financials, policies, taxes] = await Promise.all([
|
||||
vehicleStore.fetchAssetFinancials(vehicleId),
|
||||
vehicleStore.fetchInsurancePolicies(vehicleId),
|
||||
vehicleStore.fetchTaxObligations(vehicleId),
|
||||
]);
|
||||
|
||||
assetFinancials.value = financials;
|
||||
insurancePolicies.value = policies;
|
||||
taxObligations.value = taxes;
|
||||
|
||||
// Meglévő costs betöltés változatlan
|
||||
await loadCosts();
|
||||
} catch (err) {
|
||||
console.error('Failed to load finance data:', err);
|
||||
} finally {
|
||||
financeLoading.value = false;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**c) Template bővítés - új szekciók a meglévő "Költségek" szekció ELÉ:**
|
||||
|
||||
```html
|
||||
<div v-if="activeTab === 'finance'" class="space-y-5">
|
||||
|
||||
<!-- 1. ÚJ: Beszerzés & Lízing szekció -->
|
||||
<div v-if="assetFinancials" class="...">
|
||||
<h3>{{ $t('vehicle.financials.title') }}</h3>
|
||||
<div class="grid grid-cols-2 gap-3">
|
||||
<div>...purchase_price...</div>
|
||||
<div>...leasing...residual_value...</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 2. ÚJ: Biztosítások szekció -->
|
||||
<div v-if="insurancePolicies.length" class="...">
|
||||
<h3>{{ $t('vehicle.insurance.title') }}</h3>
|
||||
<div v-for="policy in insurancePolicies" :key="policy.id">
|
||||
{{ policy.insurance_type }} - {{ policy.premium_amount }} - {{ policy.expiry_date }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 3. ÚJ: Adók szekció -->
|
||||
<div v-if="taxObligations.length" class="...">
|
||||
<h3>{{ $t('vehicle.tax.title') }}</h3>
|
||||
<div v-for="tax in taxObligations" :key="tax.id">
|
||||
{{ tax.tax_type }} - {{ tax.amount }} - {{ tax.payment_status }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 4. MEGLÉVŐ: Költségek szekció (változatlan) -->
|
||||
<div v-if="!costsLoading">
|
||||
<!-- ... existing costs content ... -->
|
||||
</div>
|
||||
</div>
|
||||
```
|
||||
|
||||
**d) Importok hozzáadása:**
|
||||
```typescript
|
||||
import type { AssetFinancials, VehicleInsurancePolicy, VehicleTaxObligation } from '@/types/vehicle';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Függőségi Térkép
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[vehicle.ts - VehicleData] -->|image_url mező| B[VehicleCardStandard.vue]
|
||||
A -->|Vehicle típus| C[VehicleDetailModal.vue]
|
||||
C -->|provide vehicle| D[TechDataTab.vue]
|
||||
C -->|Promise.all| E[vehicleStore: fetchAssetFinancials]
|
||||
C -->|Promise.all| F[vehicleStore: fetchInsurancePolicies]
|
||||
C -->|Promise.all| G[vehicleStore: fetchTaxObligations]
|
||||
E --> H[assets.py: GET /vehicles/{id}/financials]
|
||||
F --> I[assets.py: GET /vehicles/{id}/insurance]
|
||||
G --> J[assets.py: GET /vehicles/{id}/tax]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Végrehajtási Sorrend
|
||||
|
||||
| Lépés | Fájl | Művelet | Függőség |
|
||||
|-------|------|---------|----------|
|
||||
| 1 | `types/vehicle.ts` | `image_url` hozzáadása | Nincs |
|
||||
| 2 | `VehicleCardStandard.vue` | 5 data binding javítás | 1. lépés (`image_url`) |
|
||||
| 3 | `VehicleDetailModal.vue` | TechData tab + provide hozzáadás | Nincs |
|
||||
| 4 | `VehicleDetailModal.vue` | Finance tab bővítés (Promise.all) | Nincs |
|
||||
| 5 | - | Vite build futtatás | 1-4. lépés |
|
||||
|
||||
---
|
||||
|
||||
## 5. Kockázatok és Megjegyzések
|
||||
|
||||
1. **TechDataTab inject függőség:** Ha a `provide` nem működik a modalban (pl. scope issue), alternatív megoldás a `TechDataTab.vue` átírása prop-alapúra. Ez azonban többletkockázat, ezért először a `provide`-os megoldást próbáljuk.
|
||||
|
||||
2. **`FinancialsTab.vue` átvételének elvetése:** A `FinancialsTab.vue` (709 sor) már tartalmazza a 3 API hívást, de sötét témát (bg-slate-900) használ, ami nem kompatibilis a modal világos témájával. A kód lemásolása helyett a logikát közvetlenül a `VehicleDetailModal.vue`-ba építjük be.
|
||||
|
||||
3. **Nincs Compact variáns:** A keresés nem talált Compact változatot, így csak a Standard kártyát kell javítani.
|
||||
|
||||
4. **i18n kulcsok:** A `hu.ts` és `en.ts` fájlokba új fordítási kulcsokat kell felvenni (pl. `vehicle.financials.title`, `vehicle.insurance.title`, `vehicle.tax.title`, `vehicle.techData`).
|
||||
|
||||
---
|
||||
|
||||
## 6. Jóváhagyás
|
||||
|
||||
**Architect:** ✅ Terv elkészítve
|
||||
**Fejlesztő:** ⏳ Jóváhagyásra vár
|
||||
|
||||
A terv végrehajtásához **Code módba** kell váltani.
|
||||
Reference in New Issue
Block a user