import { GetNodesDocument, GetHubCountriesDocument } from '~/composables/graphql/public/geo-generated' const PAGE_SIZE = 24 // Shared state across list and map views const items = ref([]) const total = ref(0) const selectedFilter = ref('all') const selectedCountry = ref('all') const countries = ref([]) const isLoading = ref(false) const isLoadingMore = ref(false) const isInitialized = ref(false) export function useCatalogHubs() { const { t } = useI18n() const { execute } = useGraphQL() const filters = computed(() => [ { id: 'all', label: t('catalogHubsSection.filters.all') }, { id: 'auto', label: t('catalogHubsSection.filters.auto') }, { id: 'rail', label: t('catalogHubsSection.filters.rail') }, { id: 'sea', label: t('catalogHubsSection.filters.sea') }, { id: 'air', label: t('catalogHubsSection.filters.air') } ]) const countryFilters = computed(() => [ { id: 'all', label: t('catalogHubsSection.filters.all_countries') }, ...countries.value.map(c => ({ id: c, label: c })) ]) const itemsWithCoords = computed(() => items.value.filter(h => h.latitude && h.longitude) ) const itemsByCountry = computed(() => { const grouped = new Map() items.value.forEach(hub => { const country = hub.country || t('catalogMap.labels.country_unknown') if (!grouped.has(country)) grouped.set(country, []) grouped.get(country)!.push(hub) }) return Array.from(grouped.entries()) .map(([name, hubsList]) => ({ name, hubs: hubsList })) .sort((a, b) => a.name.localeCompare(b.name)) }) const canLoadMore = computed(() => items.value.length < total.value) const fetchPage = async (offset: number, replace = false) => { if (replace) isLoading.value = true try { const transportType = selectedFilter.value === 'all' ? null : selectedFilter.value const country = selectedCountry.value === 'all' ? null : selectedCountry.value const data = await execute( GetNodesDocument, { limit: PAGE_SIZE, offset, transportType, country }, 'public', 'geo' ) const next = data?.nodes || [] items.value = replace ? next : items.value.concat(next) total.value = data?.nodesCount ?? total.value isInitialized.value = true } finally { isLoading.value = false } } const loadCountries = async () => { try { const data = await execute(GetHubCountriesDocument, {}, 'public', 'geo') countries.value = data?.hubCountries || [] } catch (e) { console.error('Failed to load hub countries', e) } } const loadMore = async () => { if (isLoadingMore.value) return isLoadingMore.value = true try { await fetchPage(items.value.length) } finally { isLoadingMore.value = false } } // При смене фильтра - перезагрузка watch([selectedFilter, selectedCountry], () => { if (isInitialized.value) { fetchPage(0, true) } }) // Initialize data if not already loaded const init = async () => { if (!isInitialized.value && items.value.length === 0) { await Promise.all([ fetchPage(0, true), loadCountries() ]) } } return { items, total, selectedFilter, selectedCountry, filters, countryFilters, isLoading, isLoadingMore, itemsWithCoords, itemsByCountry, canLoadMore, fetchPage, loadMore, init } }