Files
service-finder/frontend_admin/.nuxt/dist/server/_nuxt/index-BE0BbUXA.js.map.json
2026-07-01 02:27:38 +00:00

1 line
20 KiB
JSON

{"file":"index-BE0BbUXA.js","mappings":"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","names":["_ssrInterpolate","_unref","_ssrRenderAttr","_ssrIncludeBooleanAttr","_ssrLooseContain","_ssrLooseEqual","_ssrRenderClass","_ssrRenderList","_push","_parent","_createTextVNode","_toDisplayString","_ssrRenderStyle","_createBlock","_createVNode"],"sources":["../../../../pages/providers/index.vue"],"sourcesContent":["<template>\n <div>\n <!-- Page Header -->\n <div class=\"mb-8\">\n <h1 class=\"text-2xl font-bold text-white\">Szolgáltatók</h1>\n <p class=\"text-slate-400 mt-1\">Szolgáltatók listázása, keresése és moderálása</p>\n </div>\n\n <!-- Stats Cards -->\n <div class=\"grid grid-cols-2 md:grid-cols-5 gap-4 mb-8\">\n <div class=\"bg-slate-800 rounded-xl border border-slate-700 p-4\">\n <p class=\"text-xs text-slate-400 uppercase tracking-wider\">Összes</p>\n <p class=\"text-2xl font-bold text-white mt-1\">{{ stats.total }}</p>\n </div>\n <div class=\"bg-slate-800 rounded-xl border border-amber-500/30 p-4\">\n <p class=\"text-xs text-slate-400 uppercase tracking-wider\">Függőben</p>\n <p class=\"text-2xl font-bold text-amber-400 mt-1\">{{ stats.pending }}</p>\n </div>\n <div class=\"bg-slate-800 rounded-xl border border-emerald-500/30 p-4\">\n <p class=\"text-xs text-slate-400 uppercase tracking-wider\">Jóváhagyott</p>\n <p class=\"text-2xl font-bold text-emerald-400 mt-1\">{{ stats.approved }}</p>\n </div>\n <div class=\"bg-slate-800 rounded-xl border border-rose-500/30 p-4\">\n <p class=\"text-xs text-slate-400 uppercase tracking-wider\">Elutasított</p>\n <p class=\"text-2xl font-bold text-rose-400 mt-1\">{{ stats.rejected }}</p>\n </div>\n <div class=\"bg-slate-800 rounded-xl border border-purple-500/30 p-4\">\n <p class=\"text-xs text-slate-400 uppercase tracking-wider\">Megjelölt</p>\n <p class=\"text-2xl font-bold text-purple-400 mt-1\">{{ stats.flagged }}</p>\n </div>\n </div>\n\n <!-- Loading State -->\n <div v-if=\"loading\" class=\"flex items-center justify-center py-20\">\n <div class=\"text-slate-400 flex items-center gap-3\">\n <svg class=\"w-5 h-5 animate-spin\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15\" />\n </svg>\n <span>Szolgáltatók betöltése...</span>\n </div>\n </div>\n\n <!-- Error State -->\n <div v-else-if=\"error\" class=\"bg-rose-500/10 border border-rose-500/30 rounded-xl p-6 mb-8\">\n <p class=\"text-rose-400\">Hiba történt a szolgáltatók betöltése közben.</p>\n <button @click=\"fetchProviders\" class=\"mt-3 text-sm text-rose-300 hover:text-rose-200 underline\">Újrapróbálkozás</button>\n </div>\n\n <template v-else>\n <!-- Filters -->\n <div class=\"bg-slate-800 rounded-xl border border-slate-700 p-4 mb-6\">\n <div class=\"flex flex-wrap items-center gap-4\">\n <!-- Search -->\n <div class=\"flex-1 min-w-[200px]\">\n <input\n v-model=\"filters.search\"\n type=\"text\"\n placeholder=\"Keresés név alapján...\"\n class=\"w-full px-3 py-2 bg-slate-700 border border-slate-600 rounded-lg text-white placeholder-slate-500 focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500 text-sm\"\n @input=\"onSearchInput\"\n />\n </div>\n\n <!-- Status Filter -->\n <select\n v-model=\"filters.status\"\n class=\"px-3 py-2 bg-slate-700 border border-slate-600 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500 text-sm\"\n @change=\"fetchProviders\"\n >\n <option value=\"\">Minden státusz</option>\n <option value=\"pending\">Függőben</option>\n <option value=\"approved\">Jóváhagyott</option>\n <option value=\"rejected\">Elutasított</option>\n <option value=\"flagged\">Megjelölt</option>\n </select>\n\n <!-- Source Filter -->\n <select\n v-model=\"filters.source\"\n class=\"px-3 py-2 bg-slate-700 border border-slate-600 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500 text-sm\"\n @change=\"fetchProviders\"\n >\n <option value=\"\">Minden forrás</option>\n <option value=\"manual\">Kézi</option>\n <option value=\"ocr\">OCR</option>\n <option value=\"import\">Import</option>\n <option value=\"bot\">Bot (Staging)</option>\n <option value=\"verified_org\">Szervezet</option>\n </select>\n\n <!-- Sort -->\n <select\n v-model=\"filters.sort_by\"\n class=\"px-3 py-2 bg-slate-700 border border-slate-600 rounded-lg text-white focus:outline-none focus:ring-2 focus:ring-indigo-500/50 focus:border-indigo-500 text-sm\"\n @change=\"fetchProviders\"\n >\n <option value=\"created_at\">Létrehozás dátuma</option>\n <option value=\"name\">Név</option>\n <option value=\"validation_score\">Validációs pontszám</option>\n </select>\n\n <button\n @click=\"filters.sort_order = filters.sort_order === 'asc' ? 'desc' : 'asc'; fetchProviders()\"\n class=\"px-3 py-2 bg-slate-700 border border-slate-600 rounded-lg text-white hover:bg-slate-600 transition text-sm flex items-center gap-1\"\n >\n <svg class=\"w-4 h-4\" :class=\"filters.sort_order === 'asc' ? 'rotate-180' : ''\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M19 9l-7 7-7-7\" />\n </svg>\n {{ filters.sort_order === 'asc' ? 'Növekvő' : 'Csökkenő' }}\n </button>\n </div>\n </div>\n\n <!-- Providers Table -->\n <div class=\"bg-slate-800 rounded-xl border border-slate-700 overflow-hidden\">\n <table class=\"w-full\">\n <thead>\n <tr class=\"border-b border-slate-700\">\n <th class=\"text-left px-6 py-4 text-xs font-medium text-slate-400 uppercase tracking-wider\">ID</th>\n <th class=\"text-left px-6 py-4 text-xs font-medium text-slate-400 uppercase tracking-wider\">Név</th>\n <th class=\"text-left px-6 py-4 text-xs font-medium text-slate-400 uppercase tracking-wider\">Cím</th>\n <th class=\"text-left px-6 py-4 text-xs font-medium text-slate-400 uppercase tracking-wider\">Státusz</th>\n <th class=\"text-left px-6 py-4 text-xs font-medium text-slate-400 uppercase tracking-wider\">Forrás</th>\n <th class=\"text-left px-6 py-4 text-xs font-medium text-slate-400 uppercase tracking-wider\">Validáció</th>\n <th class=\"text-left px-6 py-4 text-xs font-medium text-slate-400 uppercase tracking-wider\">Létrehozva</th>\n <th class=\"text-right px-6 py-4 text-xs font-medium text-slate-400 uppercase tracking-wider\">Műveletek</th>\n </tr>\n </thead>\n <tbody class=\"divide-y divide-slate-700/50\">\n <tr v-for=\"provider in providers\" :key=\"provider.id\" class=\"hover:bg-slate-700/30 transition\">\n <td class=\"px-6 py-4 text-sm text-slate-400\">{{ provider.id }}</td>\n <td class=\"px-6 py-4\">\n <NuxtLink :to=\"`/providers/${provider.id}`\" class=\"text-sm font-medium text-indigo-400 hover:text-indigo-300 transition\">\n {{ provider.name }}\n </NuxtLink>\n </td>\n <td class=\"px-6 py-4 text-sm text-slate-300 max-w-[200px] truncate\">{{ provider.address || '—' }}</td>\n <td class=\"px-6 py-4\">\n <span class=\"inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium\" :class=\"statusClass(provider.status)\">\n {{ statusLabel(provider.status) }}\n </span>\n </td>\n <td class=\"px-6 py-4\">\n <div class=\"flex items-center gap-1.5\">\n <code class=\"text-xs font-mono text-slate-400 bg-slate-700/50 px-2 py-0.5 rounded\">{{ provider.source }}</code>\n <span v-if=\"provider.source_table\" class=\"text-[10px] font-mono text-slate-500 bg-slate-700/30 px-1.5 py-0.5 rounded\">{{ provider.source_table }}</span>\n </div>\n </td>\n <td class=\"px-6 py-4\">\n <div class=\"flex items-center gap-2\">\n <div class=\"w-16 h-1.5 bg-slate-700 rounded-full overflow-hidden\">\n <div\n class=\"h-full rounded-full transition-all\"\n :class=\"provider.validation_score >= 50 ? 'bg-emerald-500' : provider.validation_score >= 20 ? 'bg-amber-500' : 'bg-slate-500'\"\n :style=\"{ width: Math.min(provider.validation_score, 100) + '%' }\"\n />\n </div>\n <span class=\"text-xs text-slate-400\">{{ provider.validation_score }}</span>\n </div>\n </td>\n <td class=\"px-6 py-4 text-sm text-slate-400\">{{ formatDate(provider.created_at) }}</td>\n <td class=\"px-6 py-4 text-right\">\n <div class=\"flex items-center justify-end gap-2\">\n <NuxtLink\n :to=\"`/providers/${provider.id}`\"\n class=\"p-1.5 rounded-lg text-slate-400 hover:text-white hover:bg-slate-700 transition\"\n title=\"Részletek\"\n >\n <svg class=\"w-4 h-4\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M15 12a3 3 0 11-6 0 3 3 0 016 0z\" />\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z\" />\n </svg>\n </NuxtLink>\n </div>\n </td>\n </tr>\n <tr v-if=\"providers.length === 0\">\n <td colspan=\"8\" class=\"px-6 py-12 text-center text-sm text-slate-500\">\n Nincs megjeleníthető szolgáltató.\n </td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <!-- Pagination -->\n <div class=\"flex items-center justify-between mt-6\">\n <p class=\"text-sm text-slate-400\">\n {{ providers.length }} találat (összesen: {{ stats.total }})\n </p>\n <div class=\"flex items-center gap-2\">\n <button\n :disabled=\"filters.skip <= 0\"\n @click=\"filters.skip = Math.max(0, filters.skip - filters.limit); fetchProviders()\"\n class=\"px-3 py-1.5 bg-slate-700 border border-slate-600 rounded-lg text-white disabled:opacity-50 disabled:cursor-not-allowed hover:bg-slate-600 transition text-sm\"\n >\n Előző\n </button>\n <span class=\"text-sm text-slate-400\">\n {{ Math.floor(filters.skip / filters.limit) + 1 }}. oldal\n </span>\n <button\n :disabled=\"providers.length < filters.limit\"\n @click=\"filters.skip += filters.limit; fetchProviders()\"\n class=\"px-3 py-1.5 bg-slate-700 border border-slate-600 rounded-lg text-white disabled:opacity-50 disabled:cursor-not-allowed hover:bg-slate-600 transition text-sm\"\n >\n Következő\n </button>\n </div>\n </div>\n </template>\n\n <!-- Success Toast -->\n <div v-if=\"toast\" class=\"fixed bottom-6 right-6 z-50 bg-emerald-600 text-white px-4 py-3 rounded-lg shadow-lg text-sm flex items-center gap-2 animate-slide-up\">\n <svg class=\"w-4 h-4 flex-shrink-0\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z\" />\n </svg>\n {{ toast }}\n </div>\n </div>\n</template>\n\n<script setup lang=\"ts\">\ndefinePageMeta({\n middleware: 'auth',\n})\n\nconst { formatDate } = useFormatter()\n\ninterface ProviderListItem {\n id: number\n name: string\n address: string | null\n city: string | null\n category: string | null\n status: string\n source: string\n source_table?: string\n validation_score: number\n added_by_user_id: number | null\n created_at: string | null\n}\n\ninterface ProviderStats {\n total: number\n pending: number\n approved: number\n rejected: number\n flagged: number\n total_validations: number\n staging_pending?: number\n}\n\nconst loading = ref(true)\nconst error = ref(false)\nconst providers = ref<ProviderListItem[]>([])\nconst stats = ref<ProviderStats>({\n total: 0,\n pending: 0,\n approved: 0,\n rejected: 0,\n flagged: 0,\n total_validations: 0,\n staging_pending: 0,\n})\nconst toast = ref('')\nlet searchTimeout: ReturnType<typeof setTimeout> | null = null\n\nconst filters = reactive({\n search: '',\n status: '',\n source: '',\n sort_by: 'created_at',\n sort_order: 'desc',\n skip: 0,\n limit: 50,\n})\n\nfunction getHeaders(): Record<string, string> {\n const tokenCookie = useCookie('access_token')\n const token = tokenCookie.value\n return token ? { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' } : { 'Content-Type': 'application/json' }\n}\n\nfunction showToast(msg: string) {\n toast.value = msg\n setTimeout(() => { toast.value = '' }, 3000)\n}\n\nfunction statusClass(status: string): string {\n const map: Record<string, string> = {\n pending: 'bg-amber-500/10 text-amber-400',\n approved: 'bg-emerald-500/10 text-emerald-400',\n rejected: 'bg-rose-500/10 text-rose-400',\n flagged: 'bg-purple-500/10 text-purple-400',\n }\n return map[status] || 'bg-slate-500/10 text-slate-400'\n}\n\nfunction statusLabel(status: string): string {\n const map: Record<string, string> = {\n pending: 'Függőben',\n approved: 'Jóváhagyott',\n rejected: 'Elutasított',\n flagged: 'Megjelölt',\n }\n return map[status] || status\n}\n\nfunction onSearchInput() {\n if (searchTimeout) clearTimeout(searchTimeout)\n searchTimeout = setTimeout(() => {\n filters.skip = 0\n fetchProviders()\n }, 400)\n}\n\nasync function fetchStats() {\n try {\n const data = await $fetch<ProviderStats>('/api/v1/admin/providers/stats', { headers: getHeaders() })\n stats.value = data\n } catch (e) {\n console.error('Failed to fetch provider stats:', e)\n }\n}\n\nasync function fetchProviders() {\n loading.value = true\n error.value = false\n try {\n const params = new URLSearchParams()\n params.append('skip', String(filters.skip))\n params.append('limit', String(filters.limit))\n params.append('sort_by', filters.sort_by)\n params.append('sort_order', filters.sort_order)\n if (filters.status) params.append('status', filters.status)\n if (filters.source) params.append('source', filters.source)\n if (filters.search) params.append('search', filters.search)\n\n const data = await $fetch<ProviderListItem[]>(`/api/v1/admin/providers?${params.toString()}`, { headers: getHeaders() })\n providers.value = data\n } catch (e) {\n console.error('Failed to fetch providers:', e)\n error.value = true\n } finally {\n loading.value = false\n }\n}\n\nonMounted(() => {\n fetchStats()\n fetchProviders()\n})\n</script>\n\n<style scoped>\n.animate-slide-up {\n animation: slideUp 0.3s ease-out;\n}\n@keyframes slideUp {\n from {\n opacity: 0;\n transform: translateY(1rem);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n</style>\n"],"version":3}