Files
webapp/app/components/catalog/ExplorePanel.vue
Ruslan Bakiev 2dbe600d8a
All checks were successful
Build Docker Image / build (push) Successful in 4m3s
refactor: remove all any types, add strict GraphQL scalar typing
- Add strictScalars: true to codegen.ts with proper scalar mappings
  (Date, Decimal, JSONString, JSON, UUID, BigInt → string/Record)
- Replace all ref<any[]> with proper GraphQL-derived types
- Add type guards for null filtering in arrays
- Fix bugs exposed by typing (locationLatitude vs latitude, etc.)
- Add interfaces for external components (MapboxSearchBox)

This enables end-to-end type safety from GraphQL schema to frontend.
2026-01-27 11:34:12 +07:00

81 lines
2.4 KiB
Vue

<template>
<div class="flex flex-col gap-4">
<!-- View toggle -->
<div class="join join-horizontal">
<button
class="btn btn-sm join-item"
:class="{ 'btn-active': mapViewMode === 'offers' }"
@click="setMapViewMode('offers')"
>
<Icon name="lucide:shopping-bag" size="16" />
<span class="hidden sm:inline">{{ $t('catalog.views.offers') }}</span>
</button>
<button
class="btn btn-sm join-item"
:class="{ 'btn-active': mapViewMode === 'hubs' }"
@click="setMapViewMode('hubs')"
>
<Icon name="lucide:warehouse" size="16" />
<span class="hidden sm:inline">{{ $t('catalog.views.hubs') }}</span>
</button>
<button
class="btn btn-sm join-item"
:class="{ 'btn-active': mapViewMode === 'suppliers' }"
@click="setMapViewMode('suppliers')"
>
<Icon name="lucide:factory" size="16" />
<span class="hidden sm:inline">{{ $t('catalog.views.suppliers') }}</span>
</button>
</div>
<!-- Selected item info -->
<div v-if="selectedItem" class="card bg-base-100 shadow-lg">
<div class="card-body p-4">
<div class="flex items-start justify-between gap-2">
<div>
<h3 class="card-title text-base">{{ selectedItem.name }}</h3>
<p v-if="selectedItem.country" class="text-sm text-base-content/70">
{{ selectedItem.country }}
</p>
</div>
<button class="btn btn-ghost btn-sm btn-circle" @click="emit('close-selected')">
<Icon name="lucide:x" size="16" />
</button>
</div>
<div class="card-actions justify-end mt-2">
<button class="btn btn-primary btn-sm" @click="emit('view-details', selectedItem)">
{{ $t('common.viewDetails') }}
</button>
</div>
</div>
</div>
<!-- Hint when nothing selected -->
<div v-else class="text-sm text-base-content/60">
<p>{{ $t('catalog.explore.subtitle') }}</p>
</div>
</div>
</template>
<script setup lang="ts">
interface SelectedItem {
uuid: string
name?: string | null
country?: string | null
latitude?: number | null
longitude?: number | null
}
defineProps<{
selectedItem?: SelectedItem | null
}>()
const emit = defineEmits<{
'close-selected': []
'view-details': [item: SelectedItem]
}>()
const { mapViewMode, setMapViewMode } = useCatalogSearch()
</script>