# Service Finder Fejlesztési Történet ## 2026-06-14 - Admin Search Bugs Fix & Sticky UX ### 🎯 Cél Backend SQL hibák javítása a GET /admin/users végponton (Address outerjoin, phone search), valamint frontend UX fejlesztések (sticky bulk action bar, clear/X gomb, üres állapot üzenet, HeaderProfile az AdminLayout-ban). ### 🔧 Változtatások **1. BACKEND - [`admin.py`](backend/app/api/v1/endpoints/admin.py:502):** - `GET /admin/users` SQL javítás: `Address` outerjoin-ra változtatva (`isouter=True`), hogy a cím nélküli userek is visszajöjjenek - Telefonszám keresés: `phone` mező hozzáadva a `or_()` feltételhez **2. FRONTEND - [`AdminLayout.vue`](frontend/src/layouts/AdminLayout.vue:1):** - `HeaderProfile` komponens beillesztve a jobb felső sarokba (belépett user avatar + név) - A `SidebarToggle` gomb fixálva a sidebar szélén **3. FRONTEND - [`AdminUsersView.vue`](frontend/src/views/AdminUsersView.vue:1):** - **Sticky Bulk Action Bar:** A tömeges műveletek sáv (`BulkActionBar`) `sticky` pozícionálást kapott, hogy görgetéskor is látszódjon - **Clear/X gomb:** A keresőmezőbe egy `X` gomb került, ami egy kattintással törli a keresési feltételt ## 2026-06-16 - Fix 404 API Router & Redesign Dashboard Launcher Card ### 🎯 Cél A Dashboard Service Finder kártya (Card 3) átalakítása elegáns, kétgombos indítópulttá (Launcher), valamint a providers API 404 hiba kivizsgálása és javítása. ### 🔧 Változtatások **1. BACKEND AUDIT - [`api.py`](backend/app/api/v1/api.py:38):** - Ellenőrizve: `providers` router regisztrálva van (`include_router(providers.router, prefix="/providers")`) - Ellenőrizve: providers végpontokon NINCS trailing slash (`/categories`, `/search`, `/quick-add`) - **Route-ok élőben is ellenőrizve:** `GET /api/v1/providers/categories`, `GET /api/v1/providers/search`, `POST /api/v1/providers/quick-add` mind aktívak **2. FRONTEND - [`ProviderQuickAddModal.vue`](frontend/src/components/provider/ProviderQuickAddModal.vue:223):** - `fetchCategories()` már rendelkezik try/catch blokkal, 11 hardcoded fallback kategóriával - Nincs szükség módosításra **3. FRONTEND - [`DashboardView.vue`](frontend/src/views/DashboardView.vue:187):** - **Card 3 teljes átalakítása:** A 3-lépéses kontextuális kereső űrlap (input, 2 dropdown, keresés gomb) ELTÁVOLÍTVA - **Launcher dizájn:** Két nagy gomb, szépen formázva: - `🔍 Szervizek Keresése` — nagy, zöld gradient gomb, `isSearchModalOpen` modalt nyit - `➕ Új Szolgáltató Rögzítése` — szekunder, dashed border gomb, `isSfQuickAddOpen` modalt nyit (meglévő ProviderQuickAddModal) - **Search Modal (Placeholder):** Teleportált modál, benne: `🔍` ikon, "Részletes kereső térképpel hamarosan..." szöveg, fejlesztés alatt státusz - Régi `sfSearchLocation`, `sfSearchCategory`, `sfSearchVehicleId`, `sfCategories`, `fetchSfCategories()`, `onSfSearch()` eltávolítva ## 2026-06-17 - P0 Bugfix: Provider Data Persistence & Schema Alignment ### 🎯 Cél Kritikus adatperzisztencia hiba javítása a Service Finder Provider rendszerében. A frontend edit modal nem hívott backend API-t, így a szerkesztett adatok elvesztek. Emellett a contact mezők (phone, email, website, tags) nem kerültek perzisztálásra a quick-add során, és a search nem adta vissza ezeket. ### 🔧 Változtatások **1. BACKEND - [`provider.py`](backend/app/schemas/provider.py:1) (NEW):** - `ProviderQuickAddIn`: `contact_phone`, `contact_email`, `website`, `tags` mezők hozzáadva - `ProviderSearchResult`: `address_zip`, `contact_phone`, `contact_email`, `website`, `tags` mezők hozzáadva - `ProviderUpdateIn` (NEW): name, city, address_zip, street, contact_phone, contact_email, website, tags - `ProviderUpdateResponse` (NEW): id, name, status, message **2. BACKEND - [`provider_service.py`](backend/app/services/provider_service.py:486):** - `quick_add_provider()`: contact mezők mentése ServiceProfile-ba - `search_providers()`: LEFT JOIN ServiceProfile, contact mezők visszaadása - `update_provider()` (NEW): Organization + ServiceProfile atomi frissítése **3. BACKEND - [`providers.py`](backend/app/api/v1/endpoints/providers.py:134):** - `PUT /providers/{id}` végpont hozzáadva (authentikált, hibakezeléssel) **4. FRONTEND - [`ProviderEditModal.vue`](frontend/src/components/provider/ProviderEditModal.vue:191):** - **CRITICAL FIX**: `handleSave()` most `api.put()`-et hív, nem csak eventet emitál - `@save` → `@saved` (past tense, API call után) - `address_zip`, `contact_phone`, `contact_email`, `website`, `tags` mezők támogatása - `source` kivéve a payload-ból (backend-only) **5. FRONTEND - [`ProviderQuickAddModal.vue`](frontend/src/components/provider/ProviderQuickAddModal.vue:253):** - Telefon, email, weboldal, címkék mezők hozzáadva a formhoz - Tag management (vessző/pontosvessző parsing, remove gomb) - Payload bővítése contact mezőkkel **6. FRONTEND - [`ServiceFinderView.vue`](frontend/src/views/ServiceFinderView.vue:375):** - `@save` → `@saved` event binding - `handleEditSaved()`: mentés után automatikus keresés újrafuttatás ### ✅ Verifikáció - `sync_engine` lefuttatva: **1061 elem OK, 0 javítás, 0 shadow data** - rendszer tökéletesen szinkronban ## 2026-06-17 - P1 Critical Align: Atomizált címmezők a Provider sémákban ### 🎯 Cél A `street: Optional[str]` mező eltávolítása és helyette atomizált címmezők (`address_street_name`, `address_street_type`, `address_house_number`) bevezetése a Pydantic sémákban, backend service-ben és frontend űrlapokon. A kapcsolatfelvételi adatok (contact_phone, contact_email, website, tags) a ServiceProfile-ba kerülnek. ### 🔧 Változtatások **1. BACKEND - [`provider.py`](backend/app/schemas/provider.py):** - `street` mező ELTÁVOLÍTVA a `ProviderQuickAddIn` és `ProviderUpdateIn` sémákból - `address_street_name`, `address_street_type`, `address_house_number` mezők HOZZÁADVA mindkét sémához - `ProviderSearchResult` bővítve az atomizált címmezőkkel **2. BACKEND - [`provider_service.py`](backend/app/services/provider_service.py):** - `quick_add_provider()`: `data.street` → `data.address_street_name`, `data.address_street_type`, `data.address_house_number` az Organization és Branch táblákban - `update_provider()`: ugyanez az atomizált címkezelés - `search_providers()`: az org SELECT most már tartalmazza az `address_street_name`, `address_street_type`, `address_house_number` mezőket - A Branch létrehozásánál a `street_name`, `street_type`, `house_number` mezők külön-külön töltődnek **3. FRONTEND - [`ProviderQuickAddModal.vue`](frontend/src/components/provider/ProviderQuickAddModal.vue):** - A régi egyesített "Cím (Utca, házszám)" mező helyett 3 külön mező: Utca neve (text), Közterület jellege (select/dropdown 15 opcióval), Házszám (text) - Payload az új atomizált kulcsokkal megy a backend felé **4. FRONTEND - [`ProviderEditModal.vue`](frontend/src/components/provider/ProviderEditModal.vue):** - Ugyanaz a 3 mezős szétbontás, a form populate az atomizált mezőkből történik - Payload atomizált kulcsokkal **5. FRONTEND - [`ProviderDetailModal.vue`](frontend/src/components/provider/ProviderDetailModal.vue):** - Az intelligens címösszefűzés (`formattedAddress` computed) a `provider.address_street_name + ' ' + provider.address_street_type + ' ' + provider.address_house_number` alapján történik - `hasAddress` computed ellenőrzi az atomizált mezők meglétét ### ✅ Verifikáció - `sync_engine` lefuttatva: **1061 elem OK, 0 javítás, 0 shadow data** - rendszer tökéletesen szinkronban - Python syntax check: minden fájl szintaktikailag helyes ## 2026-06-17 - Provider Update & Search Fix Csomag (#264) ### 🎯 Cél Két kritikus hiba javítása a provider endpointokban: 1. **PUT /providers/{id} → 404**: A konténer nem volt újraindítva a providers modul kódváltoztatásai után 2. **GET /providers/search → 500**: `.astext` hiba JSONB subscripten + UNION oszlopszám mismatch 3. **Multi-source update**: Az `update_provider` csak Organization-ben keresett, de a search 3 forrást használ ### 🔧 Változtatások **1. BACKEND - [`provider_service.py:207`](backend/app/services/provider_service.py:207):** - `.astext` → `cast()` javítás: `Organization.external_integration_config["source"].astext` → `cast(Organization.external_integration_config["source"], String)` - **Root cause**: JSON oszlop subscript-je `BinaryExpression`-t ad vissza, amelyen nincs `.astext` **2. BACKEND - [`provider_service.py:232-274`](backend/app/services/provider_service.py:232):** - UNION oszlopszám mismatch javítva: staging és crowd SELECT-ekhez hozzáadva a hiányzó `contact_phone`, `contact_email`, `website`, `specialization_tags` mezők (14 oszlopra egységesítve) **3. BACKEND - [`provider_service.py:477-622`](backend/app/services/provider_service.py:477):** - Multi-source update logika: `update_provider()` most már mindhárom forrást támogatja: 1. `fleet.organizations` (verified orgs) - közvetlen frissítés 2. `marketplace.service_staging` (robot adatok) - migrálás Organization-be 3. `marketplace.service_providers` (crowdsourced) - migrálás Organization-be **4. INFRA - [`pre_start.sh`](backend/app/scripts/pre_start.sh):** - Dokumentálva: a `uvicorn` `--reload` nélkül fut, kódváltoztatás után `docker compose restart sf_api` szükséges **5. BACKEND - [`provider_service.py:578-596`](backend/app/services/provider_service.py:578):** - **Adatvédelmi javítás (2026-06-17):** A címmezők (`address_city`, `address_zip`, `address_street_name`, `address_street_type`, `address_house_number`) most már **csak akkor íródnak felül**, ha a frontend explicit nem-`null` értéket küld. Ez megakadályozza, hogy a meglévő címadatok véletlenül `null`-ra állítódjanak, amikor a felhasználó csak más mezőket szerkeszt. - **Trigger:** A Gitea kártya visszautasításra került (`denied` státusz) a felhasználó által: *"az adatok tárolása minden esetben bontottan történjen meg és ha hiányzik valamelyik az alap cím tárolási adatból akkor vissza kell tenni."* ### ✅ Verifikáció - **PUT /providers/58**: 200 OK ✅ - **PUT /providers/58 (partial update - csak zip)**: 200 OK ✅ (többi mező nem nullázódik) - **GET /providers/search?q=Dunakeszi**: 200 OK ✅ (2 provider) - **GET /providers/categories**: 200 OK ✅ (11 categories) - **Login**: 200 OK ✅ ## 2026-06-17 - i18n: Hiányzó provider címmező fordítások hozzáadása ### 🎯 Cél A ProviderEditModal.vue 6 darab `provider.*` i18n kulcsa hiányzott mindkét nyelvi modulból (`hu.ts`, `en.ts`), így a felhasználói felületen a kulcsnevek (pl. `provider.streetNameLabel`) jelentek meg a lefordított szöveg helyett. ### 🔧 Változtatások **1. FRONTEND - [`hu.ts`](frontend/src/i18n/hu.ts:1300):** - `provider.streetNameLabel`: `'Utca neve'` - `provider.streetNamePlaceholder`: `'Pl. Egressy'` - `provider.streetTypeLabel`: `'Közterület jellege'` - `provider.streetTypePlaceholder`: `'Válassz típust...'` - `provider.houseNumberLabel`: `'Házszám'` - `provider.houseNumberPlaceholder`: `'Pl. 4'` **2. FRONTEND - [`en.ts`](frontend/src/i18n/en.ts:1300):** - `provider.streetNameLabel`: `'Street Name'` - `provider.streetNamePlaceholder`: `'e.g. Egressy'` - `provider.streetTypeLabel`: `'Street Type'` - `provider.streetTypePlaceholder`: `'Select type...'` - `provider.houseNumberLabel`: `'House Number'` - `provider.houseNumberPlaceholder`: `'e.g. 4'` ### ✅ Verifikáció - Mindkét i18n fájl szintaktikailag helyes (Node.js require sikeres) - A ProviderEditModal.vue összes `t('provider.*')` hívása le van fedve ## 2026-06-17 - "Dunakeszi, Dunakeszi" duplikáció javítása + irányítószám megjelenítés ### 🎯 Cél A szervizkereső oldalon a kártyán "Dunakeszi, Dunakeszi" duplikált városnév jelent meg, mert a backend `address` mezője megegyezett a `city` mezővel. A részletes nézetből hiányzott az irányítószám. ### 🔧 Változtatások **1. BACKEND - [`provider_service.py`](backend/app/services/provider_service.py:198):** - Az `address` mezőt `Organization.address_city.label("address")`-ről `func.concat(...)`-re változtattuk, ami az összes atomizált címmezőt (irányítószám, város, utca, közterület, házszám) fűzi össze. - Példa eredmény: `"2120 Dunakeszi, Egressy utca 4"` a korábbi `"Dunakeszi"` helyett. **2. FRONTEND - [`ServiceFinderView.vue`](frontend/src/views/ServiceFinderView.vue:543):** - Új `formatCardAddress(provider)` metódus, ami a kártyán az atomizált címmezőkből építi fel a címet. - Fallback: ha nincs atomizált adat, a backend által összefűzött `address` mezőt használja. **3. FRONTEND - [`ProviderDetailModal.vue`](frontend/src/components/provider/ProviderDetailModal.vue:237):** - A `formattedAddress` computed property most már tartalmazza az `address_zip` mezőt is. - Formátum: `"2120 Dunakeszi, Egressy utca 4"` ### ✅ Verifikáció - Backend API: `GET /api/v1/providers/search?city=Dunakeszi` → `address` = `"2120 Dunakeszi, Egressy utca 4"` ✅ - Backend API: Autónyíri Kft. (id=58) → `address_zip=2120`, `address_street_name=Egressy`, `address_street_type=utca`, `address_house_number=4` ✅ - Frontend build: `npm run build` sikeres, 0 hiba ✅ - Backend konténer újraindítva: `docker compose restart sf_api` ✅ ## 2026-06-17 - Kártya fő szolgáltatás (category) mindig megjelenítése ### 🎯 Cél A szervizkereső kártyákon a fő szolgáltatás (category) mindig látszódjon. Ha van, akkor a kategória neve, ha nincs, akkor egy szaggatott vonalú placeholder. ### 🔧 Változtatások **1. FRONTEND - [`ServiceFinderView.vue:263`](frontend/src/views/ServiceFinderView.vue:263):** - A category badge `v-if="provider.category"` helyett `v-if`/`v-else` szerkezet: - Ha van category: `bg-sf-accent/10` háttér, `text-sf-accent` szín - Ha nincs: szaggatott vonalú (`border-dashed`) placeholder "Nincs kategória" / "No category" **2. FRONTEND - [`hu.ts:1237`](frontend/src/i18n/hu.ts:1237):** - `serviceFinder.noCategory`: `'Nincs kategória'` **3. FRONTEND - [`en.ts:1237`](frontend/src/i18n/en.ts:1237):** - `serviceFinder.noCategory`: `'No category'` ### ✅ Verifikáció - Frontend build: `npm run build` sikeres, 0 hiba ✅