124 lines
4.9 KiB
Vue
124 lines
4.9 KiB
Vue
<template>
|
|
<div>
|
|
<!-- Empty state -->
|
|
<div v-if="!data || isEmpty(data)" class="text-center py-8">
|
|
<svg class="w-10 h-10 mx-auto mb-3 text-slate-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M20 7l-8-4-8 4m16 0l-8 4m8-4v10l-8 4m0-10L4 7m8 4v10M4 7v10l8 4" />
|
|
</svg>
|
|
<p class="text-sm text-slate-500">Nincs nyers adat</p>
|
|
</div>
|
|
|
|
<!-- JSON tree view -->
|
|
<div v-else class="space-y-1 font-mono text-xs">
|
|
<div
|
|
v-for="(value, key) in data"
|
|
:key="key"
|
|
class="border-b border-slate-700/50 last:border-0"
|
|
>
|
|
<div class="flex items-start gap-3 py-2">
|
|
<!-- Key -->
|
|
<span class="text-indigo-400 font-semibold whitespace-nowrap min-w-[140px] flex-shrink-0">
|
|
{{ key }}
|
|
</span>
|
|
|
|
<!-- Value -->
|
|
<div class="flex-1 min-w-0">
|
|
<!-- Null -->
|
|
<span v-if="value === null || value === undefined" class="text-slate-500 italic">null</span>
|
|
|
|
<!-- String -->
|
|
<span v-else-if="typeof value === 'string'" class="text-emerald-300 break-words">
|
|
"{{ value }}"
|
|
</span>
|
|
|
|
<!-- Number / Boolean -->
|
|
<span v-else-if="typeof value === 'number' || typeof value === 'boolean'" class="text-amber-300">
|
|
{{ value }}
|
|
</span>
|
|
|
|
<!-- Array -->
|
|
<div v-else-if="Array.isArray(value)">
|
|
<template v-if="value.length === 0">
|
|
<span class="text-slate-500 italic">[]</span>
|
|
</template>
|
|
<template v-else>
|
|
<details class="group">
|
|
<summary class="cursor-pointer text-slate-400 hover:text-slate-300 list-none flex items-center gap-1.5">
|
|
<svg class="w-3 h-3 transition-transform group-open:rotate-90" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
|
|
</svg>
|
|
<span class="text-slate-400">Array [{{ value.length }}]</span>
|
|
</summary>
|
|
<div class="ml-4 mt-1 space-y-1 border-l border-slate-700 pl-3">
|
|
<div v-for="(item, idx) in value" :key="idx" class="py-1">
|
|
<span class="text-slate-500 mr-2">[{{ idx }}]</span>
|
|
<span v-if="typeof item === 'object' && item !== null" class="text-slate-400">
|
|
<RawDataViewer :data="item" />
|
|
</span>
|
|
<span v-else-if="typeof item === 'string'" class="text-emerald-300">"{{ item }}"</span>
|
|
<span v-else class="text-amber-300">{{ item }}</span>
|
|
</div>
|
|
</div>
|
|
</details>
|
|
</template>
|
|
</div>
|
|
|
|
<!-- Object (nested JSON) -->
|
|
<div v-else-if="typeof value === 'object'">
|
|
<details class="group">
|
|
<summary class="cursor-pointer text-slate-400 hover:text-slate-300 list-none flex items-center gap-1.5">
|
|
<svg class="w-3 h-3 transition-transform group-open:rotate-90" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
|
|
</svg>
|
|
<span class="text-slate-400">Object {{ objectKeys(value) }}</span>
|
|
</summary>
|
|
<div class="ml-4 mt-1 border-l border-slate-700 pl-3">
|
|
<RawDataViewer :data="value" />
|
|
</div>
|
|
</details>
|
|
</div>
|
|
|
|
<!-- Fallback -->
|
|
<span v-else class="text-slate-400">{{ String(value) }}</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
/**
|
|
* RawDataViewer.vue
|
|
*
|
|
* Egy Vue 3 komponens, amely egy JSON/objektum adatot jelenít meg
|
|
* strukturált, fa-szerű nézetben. Támogatja a beágyazott objektumokat
|
|
* és tömböket összecsukható (details/summary) elemekkel.
|
|
*
|
|
* Props:
|
|
* data - Object | null - A megjelenítendő nyers adat (JSON)
|
|
*/
|
|
defineProps<{
|
|
data: Record<string, any> | null
|
|
}>()
|
|
|
|
/**
|
|
* Ellenőrzi, hogy egy objektum üres-e (nincs saját enumerable tulajdonsága).
|
|
*/
|
|
function isEmpty(obj: Record<string, any>): boolean {
|
|
if (!obj || typeof obj !== 'object') return true
|
|
return Object.keys(obj).length === 0
|
|
}
|
|
|
|
/**
|
|
* Visszaadja az objektum kulcsainak számát szöveges formában,
|
|
* pl. "{ 3 kulcs }" vagy "{ üres }"
|
|
*/
|
|
function objectKeys(obj: Record<string, any>): string {
|
|
if (!obj || typeof obj !== 'object') return '{ }'
|
|
const keys = Object.keys(obj)
|
|
if (keys.length === 0) return '{ üres }'
|
|
return `{ ${keys.length} kulcs }`
|
|
}
|
|
</script>
|