UI improvements: filters, map layout, search bar
Some checks failed
Build Docker Image / build (push) Failing after 1m29s
Some checks failed
Build Docker Image / build (push) Failing after 1m29s
- Add hubCountries query and country filter for hubs page - Add getAvailableProducts query for offers (only products with active offers) - Add sourceLatitude/sourceLongitude to orders GraphQL - Fix ListMapLayout with position fixed for proper map height - GlobalSearchBar: make fields wider, remove unit selector - Remove status/isVerified filters from suppliers/offers (backend handles this)
This commit is contained in:
@@ -1,14 +1,15 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="flex flex-col flex-1 min-h-0">
|
<div class="flex flex-col flex-1 min-h-0">
|
||||||
<!-- Desktop: side-by-side layout -->
|
<!-- Desktop: side-by-side layout -->
|
||||||
<div class="hidden lg:flex flex-1 gap-4 min-h-0 overflow-hidden">
|
<div class="hidden lg:flex flex-1 gap-4 min-h-0">
|
||||||
<!-- Left side: List (scrollable) -->
|
<!-- Left side: List (scrollable) -->
|
||||||
<div class="w-2/5 overflow-y-auto pr-2">
|
<div class="w-2/5 overflow-y-auto pr-2">
|
||||||
<slot name="list" />
|
<slot name="list" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Right side: Map (sticky, full height from SubNav to bottom) -->
|
<!-- Right side: Map (fixed position, full height) -->
|
||||||
<div class="w-3/5 h-full rounded-lg overflow-hidden sticky top-0 self-start">
|
<div class="w-3/5 relative">
|
||||||
|
<div class="fixed top-28 right-6 w-[calc(60%-3rem)] h-[calc(100vh-8rem)] rounded-lg overflow-hidden">
|
||||||
<ClientOnly>
|
<ClientOnly>
|
||||||
<CatalogMap
|
<CatalogMap
|
||||||
ref="mapRef"
|
ref="mapRef"
|
||||||
@@ -20,6 +21,7 @@
|
|||||||
</ClientOnly>
|
</ClientOnly>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Mobile: toggle between list and map -->
|
<!-- Mobile: toggle between list and map -->
|
||||||
<div class="lg:hidden flex-1 flex flex-col min-h-0">
|
<div class="lg:hidden flex-1 flex flex-col min-h-0">
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
>
|
>
|
||||||
<!-- Product field (clickable, navigates to /goods) -->
|
<!-- Product field (clickable, navigates to /goods) -->
|
||||||
<div
|
<div
|
||||||
class="flex flex-col px-4 py-2 min-w-32 pl-6 rounded-l-full hover:bg-base-200/50 border-r border-base-300 cursor-pointer"
|
class="flex flex-col px-4 py-2 min-w-48 pl-6 rounded-l-full hover:bg-base-200/50 border-r border-base-300 cursor-pointer"
|
||||||
@click="goToProductSelection"
|
@click="goToProductSelection"
|
||||||
>
|
>
|
||||||
<label class="text-xs font-semibold text-base-content/60 mb-0.5">
|
<label class="text-xs font-semibold text-base-content/60 mb-0.5">
|
||||||
@@ -19,29 +19,23 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Quantity field (editable) -->
|
<!-- Quantity field (editable) -->
|
||||||
<div class="flex flex-col px-4 py-2 min-w-32 hover:bg-base-200/50 border-r border-base-300">
|
<div class="flex flex-col px-4 py-2 min-w-48 hover:bg-base-200/50 border-r border-base-300">
|
||||||
<label class="text-xs font-semibold text-base-content/60 mb-0.5">
|
<label class="text-xs font-semibold text-base-content/60 mb-0.5">
|
||||||
{{ $t('search.quantity') }}
|
{{ $t('search.quantity') }}
|
||||||
</label>
|
</label>
|
||||||
<div class="flex items-center gap-1">
|
|
||||||
<input
|
<input
|
||||||
v-model="quantity"
|
v-model="quantity"
|
||||||
type="number"
|
type="number"
|
||||||
min="1"
|
min="1"
|
||||||
:placeholder="$t('search.quantity_placeholder')"
|
:placeholder="$t('search.quantity_placeholder')"
|
||||||
class="w-16 bg-transparent outline-none text-sm"
|
class="w-full bg-transparent outline-none text-sm"
|
||||||
@change="syncQuantityToStore"
|
@change="syncQuantityToStore"
|
||||||
/>
|
/>
|
||||||
<select v-model="unit" class="bg-transparent outline-none text-sm text-base-content/70" @change="syncQuantityToStore">
|
|
||||||
<option value="t">{{ $t('units.t') }}</option>
|
|
||||||
<option value="kg">{{ $t('units.kg') }}</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Destination field (clickable, navigates to /select-location) -->
|
<!-- Destination field (clickable, navigates to /select-location) -->
|
||||||
<div
|
<div
|
||||||
class="flex flex-col px-4 py-2 min-w-32 hover:bg-base-200/50 cursor-pointer"
|
class="flex flex-col px-4 py-2 min-w-48 hover:bg-base-200/50 cursor-pointer"
|
||||||
@click="goToLocationSelection"
|
@click="goToLocationSelection"
|
||||||
>
|
>
|
||||||
<label class="text-xs font-semibold text-base-content/60 mb-0.5">
|
<label class="text-xs font-semibold text-base-content/60 mb-0.5">
|
||||||
@@ -67,7 +61,7 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
const emit = defineEmits<{
|
const emit = defineEmits<{
|
||||||
search: [params: { productUuid?: string; quantity?: number; unit?: string; locationUuid?: string }]
|
search: [params: { productUuid?: string; quantity?: number; locationUuid?: string }]
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const router = useRouter()
|
const router = useRouter()
|
||||||
@@ -84,13 +78,11 @@ const locationUuid = computed(() => searchStore.searchForm.locationUuid || '')
|
|||||||
const quantity = ref<number | undefined>(
|
const quantity = ref<number | undefined>(
|
||||||
searchStore.searchForm.quantity ? Number(searchStore.searchForm.quantity) : undefined
|
searchStore.searchForm.quantity ? Number(searchStore.searchForm.quantity) : undefined
|
||||||
)
|
)
|
||||||
const unit = ref(searchStore.searchForm.unit || 't')
|
|
||||||
|
|
||||||
const syncQuantityToStore = () => {
|
const syncQuantityToStore = () => {
|
||||||
if (quantity.value) {
|
if (quantity.value) {
|
||||||
searchStore.setQuantity(String(quantity.value))
|
searchStore.setQuantity(String(quantity.value))
|
||||||
}
|
}
|
||||||
searchStore.setUnit(unit.value)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Navigation to selection pages
|
// Navigation to selection pages
|
||||||
@@ -135,7 +127,6 @@ const handleSearch = () => {
|
|||||||
emit('search', {
|
emit('search', {
|
||||||
productUuid: productUuid.value,
|
productUuid: productUuid.value,
|
||||||
quantity: quantity.value,
|
quantity: quantity.value,
|
||||||
unit: unit.value,
|
|
||||||
locationUuid: locationUuid.value
|
locationUuid: locationUuid.value
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -146,10 +137,4 @@ watch(() => searchStore.searchForm.quantity, (val) => {
|
|||||||
quantity.value = Number(val)
|
quantity.value = Number(val)
|
||||||
}
|
}
|
||||||
}, { immediate: true })
|
}, { immediate: true })
|
||||||
|
|
||||||
watch(() => searchStore.searchForm.unit, (val) => {
|
|
||||||
if (val) {
|
|
||||||
unit.value = val
|
|
||||||
}
|
|
||||||
}, { immediate: true })
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { GetNodesDocument } from '~/composables/graphql/public/geo-generated'
|
import { GetNodesDocument, GetHubCountriesDocument } from '~/composables/graphql/public/geo-generated'
|
||||||
|
|
||||||
const PAGE_SIZE = 24
|
const PAGE_SIZE = 24
|
||||||
|
|
||||||
@@ -6,6 +6,8 @@ const PAGE_SIZE = 24
|
|||||||
const items = ref<any[]>([])
|
const items = ref<any[]>([])
|
||||||
const total = ref(0)
|
const total = ref(0)
|
||||||
const selectedFilter = ref('all')
|
const selectedFilter = ref('all')
|
||||||
|
const selectedCountry = ref('all')
|
||||||
|
const countries = ref<string[]>([])
|
||||||
const isLoading = ref(false)
|
const isLoading = ref(false)
|
||||||
const isLoadingMore = ref(false)
|
const isLoadingMore = ref(false)
|
||||||
const isInitialized = ref(false)
|
const isInitialized = ref(false)
|
||||||
@@ -22,6 +24,11 @@ export function useCatalogHubs() {
|
|||||||
{ id: 'air', label: t('catalogHubsSection.filters.air') }
|
{ 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(() =>
|
const itemsWithCoords = computed(() =>
|
||||||
items.value.filter(h => h.latitude && h.longitude)
|
items.value.filter(h => h.latitude && h.longitude)
|
||||||
)
|
)
|
||||||
@@ -44,9 +51,10 @@ export function useCatalogHubs() {
|
|||||||
if (replace) isLoading.value = true
|
if (replace) isLoading.value = true
|
||||||
try {
|
try {
|
||||||
const transportType = selectedFilter.value === 'all' ? null : selectedFilter.value
|
const transportType = selectedFilter.value === 'all' ? null : selectedFilter.value
|
||||||
|
const country = selectedCountry.value === 'all' ? null : selectedCountry.value
|
||||||
const data = await execute(
|
const data = await execute(
|
||||||
GetNodesDocument,
|
GetNodesDocument,
|
||||||
{ limit: PAGE_SIZE, offset, transportType },
|
{ limit: PAGE_SIZE, offset, transportType, country },
|
||||||
'public',
|
'public',
|
||||||
'geo'
|
'geo'
|
||||||
)
|
)
|
||||||
@@ -59,6 +67,15 @@ export function useCatalogHubs() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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 () => {
|
const loadMore = async () => {
|
||||||
if (isLoadingMore.value) return
|
if (isLoadingMore.value) return
|
||||||
isLoadingMore.value = true
|
isLoadingMore.value = true
|
||||||
@@ -70,7 +87,7 @@ export function useCatalogHubs() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// При смене фильтра - перезагрузка
|
// При смене фильтра - перезагрузка
|
||||||
watch(selectedFilter, () => {
|
watch([selectedFilter, selectedCountry], () => {
|
||||||
if (isInitialized.value) {
|
if (isInitialized.value) {
|
||||||
fetchPage(0, true)
|
fetchPage(0, true)
|
||||||
}
|
}
|
||||||
@@ -79,7 +96,10 @@ export function useCatalogHubs() {
|
|||||||
// Initialize data if not already loaded
|
// Initialize data if not already loaded
|
||||||
const init = async () => {
|
const init = async () => {
|
||||||
if (!isInitialized.value && items.value.length === 0) {
|
if (!isInitialized.value && items.value.length === 0) {
|
||||||
await fetchPage(0, true)
|
await Promise.all([
|
||||||
|
fetchPage(0, true),
|
||||||
|
loadCountries()
|
||||||
|
])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +107,9 @@ export function useCatalogHubs() {
|
|||||||
items,
|
items,
|
||||||
total,
|
total,
|
||||||
selectedFilter,
|
selectedFilter,
|
||||||
|
selectedCountry,
|
||||||
filters,
|
filters,
|
||||||
|
countryFilters,
|
||||||
isLoading,
|
isLoading,
|
||||||
isLoadingMore,
|
isLoadingMore,
|
||||||
itemsWithCoords,
|
itemsWithCoords,
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ export function useCatalogOffers() {
|
|||||||
{
|
{
|
||||||
limit: PAGE_SIZE,
|
limit: PAGE_SIZE,
|
||||||
offset,
|
offset,
|
||||||
status: 'active',
|
|
||||||
productUuid: selectedProductUuid.value
|
productUuid: selectedProductUuid.value
|
||||||
},
|
},
|
||||||
'public',
|
'public',
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { GetProductsDocument } from '~/composables/graphql/public/exchange-generated'
|
import { GetAvailableProductsDocument } from '~/composables/graphql/public/exchange-generated'
|
||||||
|
|
||||||
// Shared state
|
// Shared state
|
||||||
const items = ref<any[]>([])
|
const items = ref<any[]>([])
|
||||||
@@ -13,12 +13,12 @@ export function useCatalogProducts() {
|
|||||||
isLoading.value = true
|
isLoading.value = true
|
||||||
try {
|
try {
|
||||||
const data = await execute(
|
const data = await execute(
|
||||||
GetProductsDocument,
|
GetAvailableProductsDocument,
|
||||||
{},
|
{},
|
||||||
'public',
|
'public',
|
||||||
'exchange'
|
'exchange'
|
||||||
)
|
)
|
||||||
items.value = data?.getProducts || []
|
items.value = data?.getAvailableProducts || []
|
||||||
isInitialized.value = true
|
isInitialized.value = true
|
||||||
} finally {
|
} finally {
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
|
|||||||
@@ -5,20 +5,13 @@ const PAGE_SIZE = 24
|
|||||||
// Shared state across list and map views
|
// Shared state across list and map views
|
||||||
const items = ref<any[]>([])
|
const items = ref<any[]>([])
|
||||||
const total = ref(0)
|
const total = ref(0)
|
||||||
const selectedFilter = ref('all')
|
|
||||||
const isLoading = ref(false)
|
const isLoading = ref(false)
|
||||||
const isLoadingMore = ref(false)
|
const isLoadingMore = ref(false)
|
||||||
const isInitialized = ref(false)
|
const isInitialized = ref(false)
|
||||||
|
|
||||||
export function useCatalogSuppliers() {
|
export function useCatalogSuppliers() {
|
||||||
const { t } = useI18n()
|
|
||||||
const { execute } = useGraphQL()
|
const { execute } = useGraphQL()
|
||||||
|
|
||||||
const filters = computed(() => [
|
|
||||||
{ id: 'all', label: t('catalogSuppliersSection.filters.all') },
|
|
||||||
{ id: 'verified', label: t('catalogSuppliersSection.filters.verified') }
|
|
||||||
])
|
|
||||||
|
|
||||||
const itemsWithCoords = computed(() =>
|
const itemsWithCoords = computed(() =>
|
||||||
items.value.filter(s => s.latitude && s.longitude)
|
items.value.filter(s => s.latitude && s.longitude)
|
||||||
)
|
)
|
||||||
@@ -28,10 +21,9 @@ export function useCatalogSuppliers() {
|
|||||||
const fetchPage = async (offset: number, replace = false) => {
|
const fetchPage = async (offset: number, replace = false) => {
|
||||||
if (replace) isLoading.value = true
|
if (replace) isLoading.value = true
|
||||||
try {
|
try {
|
||||||
const isVerified = selectedFilter.value === 'verified' ? true : null
|
|
||||||
const data = await execute(
|
const data = await execute(
|
||||||
GetSupplierProfilesDocument,
|
GetSupplierProfilesDocument,
|
||||||
{ limit: PAGE_SIZE, offset, isVerified },
|
{ limit: PAGE_SIZE, offset },
|
||||||
'public',
|
'public',
|
||||||
'exchange'
|
'exchange'
|
||||||
)
|
)
|
||||||
@@ -54,13 +46,6 @@ export function useCatalogSuppliers() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// При смене фильтра - перезагрузка
|
|
||||||
watch(selectedFilter, () => {
|
|
||||||
if (isInitialized.value) {
|
|
||||||
fetchPage(0, true)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// Initialize data if not already loaded
|
// Initialize data if not already loaded
|
||||||
const init = async () => {
|
const init = async () => {
|
||||||
if (!isInitialized.value && items.value.length === 0) {
|
if (!isInitialized.value && items.value.length === 0) {
|
||||||
@@ -71,8 +56,6 @@ export function useCatalogSuppliers() {
|
|||||||
return {
|
return {
|
||||||
items,
|
items,
|
||||||
total,
|
total,
|
||||||
selectedFilter,
|
|
||||||
filters,
|
|
||||||
isLoading,
|
isLoading,
|
||||||
isLoadingMore,
|
isLoadingMore,
|
||||||
itemsWithCoords,
|
itemsWithCoords,
|
||||||
|
|||||||
@@ -8,7 +8,10 @@
|
|||||||
@select="onSelectHub"
|
@select="onSelectHub"
|
||||||
>
|
>
|
||||||
<template #filters>
|
<template #filters>
|
||||||
|
<div class="flex gap-2">
|
||||||
<CatalogFilterSelect :filters="filters" v-model="selectedFilter" />
|
<CatalogFilterSelect :filters="filters" v-model="selectedFilter" />
|
||||||
|
<CatalogFilterSelect :filters="countryFilters" v-model="selectedCountry" />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template #card="{ item }">
|
<template #card="{ item }">
|
||||||
@@ -45,7 +48,9 @@ const {
|
|||||||
items,
|
items,
|
||||||
total,
|
total,
|
||||||
selectedFilter,
|
selectedFilter,
|
||||||
|
selectedCountry,
|
||||||
filters,
|
filters,
|
||||||
|
countryFilters,
|
||||||
isLoading,
|
isLoading,
|
||||||
isLoadingMore,
|
isLoadingMore,
|
||||||
itemsByCountry,
|
itemsByCountry,
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
query GetAvailableProducts {
|
||||||
|
getAvailableProducts {
|
||||||
|
uuid
|
||||||
|
name
|
||||||
|
categoryId
|
||||||
|
categoryName
|
||||||
|
terminusSchemaId
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
query GetOffers($status: String, $productUuid: String, $locationUuid: String, $categoryName: String, $teamUuid: String, $limit: Int, $offset: Int) {
|
query GetOffers($productUuid: String, $locationUuid: String, $categoryName: String, $teamUuid: String, $limit: Int, $offset: Int) {
|
||||||
getOffers(status: $status, productUuid: $productUuid, locationUuid: $locationUuid, categoryName: $categoryName, teamUuid: $teamUuid, limit: $limit, offset: $offset) {
|
getOffers(productUuid: $productUuid, locationUuid: $locationUuid, categoryName: $categoryName, teamUuid: $teamUuid, limit: $limit, offset: $offset) {
|
||||||
uuid
|
uuid
|
||||||
teamUuid
|
teamUuid
|
||||||
status
|
|
||||||
# Location
|
# Location
|
||||||
locationUuid
|
locationUuid
|
||||||
locationName
|
locationName
|
||||||
@@ -25,5 +24,5 @@ query GetOffers($status: String, $productUuid: String, $locationUuid: String, $c
|
|||||||
createdAt
|
createdAt
|
||||||
updatedAt
|
updatedAt
|
||||||
}
|
}
|
||||||
getOffersCount(status: $status, productUuid: $productUuid, locationUuid: $locationUuid, categoryName: $categoryName, teamUuid: $teamUuid)
|
getOffersCount(productUuid: $productUuid, locationUuid: $locationUuid, categoryName: $categoryName, teamUuid: $teamUuid)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
query GetSupplierProfiles($country: String, $isVerified: Boolean, $limit: Int, $offset: Int) {
|
query GetSupplierProfiles($country: String, $limit: Int, $offset: Int) {
|
||||||
getSupplierProfiles(country: $country, isVerified: $isVerified, limit: $limit, offset: $offset) {
|
getSupplierProfiles(country: $country, limit: $limit, offset: $offset) {
|
||||||
uuid
|
uuid
|
||||||
teamUuid
|
teamUuid
|
||||||
name
|
name
|
||||||
@@ -7,11 +7,9 @@ query GetSupplierProfiles($country: String, $isVerified: Boolean, $limit: Int, $
|
|||||||
country
|
country
|
||||||
countryCode
|
countryCode
|
||||||
logoUrl
|
logoUrl
|
||||||
isVerified
|
|
||||||
isActive
|
|
||||||
offersCount
|
offersCount
|
||||||
latitude
|
latitude
|
||||||
longitude
|
longitude
|
||||||
}
|
}
|
||||||
getSupplierProfilesCount(country: $country, isVerified: $isVerified)
|
getSupplierProfilesCount(country: $country)
|
||||||
}
|
}
|
||||||
|
|||||||
3
graphql/operations/public/geo/GetHubCountries.graphql
Normal file
3
graphql/operations/public/geo/GetHubCountries.graphql
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
query GetHubCountries {
|
||||||
|
hubCountries
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
query GetNodes($limit: Int, $offset: Int, $transportType: String) {
|
query GetNodes($limit: Int, $offset: Int, $transportType: String, $country: String) {
|
||||||
nodes(limit: $limit, offset: $offset, transportType: $transportType) {
|
nodes(limit: $limit, offset: $offset, transportType: $transportType, country: $country) {
|
||||||
uuid
|
uuid
|
||||||
name
|
name
|
||||||
latitude
|
latitude
|
||||||
@@ -9,5 +9,5 @@ query GetNodes($limit: Int, $offset: Int, $transportType: String) {
|
|||||||
syncedAt
|
syncedAt
|
||||||
transportTypes
|
transportTypes
|
||||||
}
|
}
|
||||||
nodesCount(transportType: $transportType)
|
nodesCount(transportType: $transportType, country: $country)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ query GetTeamOrders {
|
|||||||
totalAmount
|
totalAmount
|
||||||
currency
|
currency
|
||||||
sourceLocationName
|
sourceLocationName
|
||||||
|
sourceLatitude
|
||||||
|
sourceLongitude
|
||||||
destinationLocationName
|
destinationLocationName
|
||||||
createdAt
|
createdAt
|
||||||
orderLines {
|
orderLines {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
},
|
},
|
||||||
"filters": {
|
"filters": {
|
||||||
"all": "All",
|
"all": "All",
|
||||||
|
"all_countries": "All countries",
|
||||||
"auto": "Auto",
|
"auto": "Auto",
|
||||||
"rail": "Rail",
|
"rail": "Rail",
|
||||||
"sea": "Sea",
|
"sea": "Sea",
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
},
|
},
|
||||||
"filters": {
|
"filters": {
|
||||||
"all": "Все",
|
"all": "Все",
|
||||||
|
"all_countries": "Все страны",
|
||||||
"auto": "Авто",
|
"auto": "Авто",
|
||||||
"rail": "Ж/д",
|
"rail": "Ж/д",
|
||||||
"sea": "Море",
|
"sea": "Море",
|
||||||
|
|||||||
Reference in New Issue
Block a user