@ozdao/martyrs 0.2.561 → 0.2.563
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{abac-DC2x92Pa.js → abac-DYoheWuc.js} +2 -1
- package/dist/{core.logger-VRHh-WUW.js → core.cache-DALYFDdy.js} +10 -59
- package/dist/core.logger-C3q8A9dl.js +51 -0
- package/dist/core.server.js +1 -1
- package/dist/{crud-DFFgLl09.js → crud-C7FSTUes.js} +2 -1
- package/dist/inventory.server.js +4 -3
- package/dist/{main-DQtUY5ma.js → main-CmjWiDVF.js} +2837 -2548
- package/dist/marketplace.server.js +389 -0
- package/dist/martyrs/src/components/Button/{Button.vue.js → Button.vue2.js} +3 -3
- package/dist/martyrs/src/components/Button/Button.vue2.js.map +1 -0
- package/dist/martyrs/src/components/Checkbox/Checkbox.vue.js +1 -1
- package/dist/martyrs/src/components/Checkbox/Checkbox.vue.js.map +1 -1
- package/dist/martyrs/src/components/FieldBig/FieldBig.vue.js +1 -1
- package/dist/martyrs/src/components/Menu/{Menu.vue2.js → Menu.vue.js} +2 -2
- package/dist/martyrs/src/components/Menu/Menu.vue.js.map +1 -0
- package/dist/martyrs/src/components/Select/{Select.vue2.js → Select.vue.js} +2 -2
- package/dist/martyrs/src/components/Select/Select.vue.js.map +1 -0
- package/dist/martyrs/src/components/Spoiler/{Spoiler.vue.js → Spoiler.vue2.js} +2 -2
- package/dist/martyrs/src/components/Spoiler/Spoiler.vue2.js.map +1 -0
- package/dist/martyrs/src/modules/auth/views/components/pages/EnterPassword.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/Invite.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/Profile.vue.js +2 -2
- package/dist/martyrs/src/modules/auth/views/components/pages/ProfileEditAccount.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/ProfileEditProfile.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/ResetPassword.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/SignIn.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/SignUp.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/sections/ProfileEditCredentials.vue.js +1 -1
- package/dist/martyrs/src/modules/community/components/layouts/Community.vue.js +1 -1
- package/dist/martyrs/src/modules/community/components/pages/BlogPost.vue.js +1 -1
- package/dist/martyrs/src/modules/community/components/pages/CreateBlogPost.vue.js +1 -1
- package/dist/martyrs/src/modules/core/views/components/blocks/CardHeader.vue.js +1 -1
- package/dist/martyrs/src/modules/core/views/components/blocks/PopupAuth.vue.js +1 -1
- package/dist/martyrs/src/modules/core/views/components/blocks/PopupDateSelector.vue.js +1 -1
- package/dist/martyrs/src/modules/core/views/components/layouts/Client.vue.js +3 -6
- package/dist/martyrs/src/modules/core/views/components/layouts/Client.vue.js.map +1 -1
- package/dist/martyrs/src/modules/core/views/components/partials/Header.vue.js +3 -3
- package/dist/martyrs/src/modules/core/views/components/partials/Header.vue.js.map +1 -1
- package/dist/martyrs/src/modules/core/views/components/partials/Navigation.vue.js +1 -1
- package/dist/martyrs/src/modules/core/views/components/partials/NavigationBar.vue.js +1 -1
- package/dist/martyrs/src/modules/core/views/components/sections/Filters.vue.js +59 -171
- package/dist/martyrs/src/modules/core/views/components/sections/Filters.vue.js.map +1 -1
- package/dist/martyrs/src/modules/core/views/components/sections/filters/FilterCheckbox.vue2.js +64 -0
- package/dist/martyrs/src/modules/core/views/components/sections/filters/FilterCheckbox.vue2.js.map +1 -0
- package/dist/martyrs/src/modules/core/views/components/sections/filters/FilterDateRange.vue2.js +160 -0
- package/dist/martyrs/src/modules/core/views/components/sections/filters/FilterDateRange.vue2.js.map +1 -0
- package/dist/martyrs/src/modules/core/views/components/sections/filters/FilterOptions.vue.js +46 -0
- package/dist/martyrs/src/modules/core/views/components/sections/filters/FilterOptions.vue.js.map +1 -0
- package/dist/martyrs/src/modules/core/views/components/sections/filters/FilterRange.vue.js +105 -0
- package/dist/martyrs/src/modules/core/views/components/sections/filters/FilterRange.vue.js.map +1 -0
- package/dist/martyrs/src/modules/core/views/components/sections/filters/FiltersGroup.vue.js +166 -0
- package/dist/martyrs/src/modules/core/views/components/sections/filters/FiltersGroup.vue.js.map +1 -0
- package/dist/martyrs/src/modules/core/views/utils/vue-app-renderer.js +4 -0
- package/dist/martyrs/src/modules/core/views/utils/vue-app-renderer.js.map +1 -1
- package/dist/martyrs/src/modules/events/components/elements/ButtonCheck.vue.js +1 -1
- package/dist/martyrs/src/modules/events/components/elements/ButtonJoin.vue.js +1 -1
- package/dist/martyrs/src/modules/events/components/pages/EditEvent.vue.js +1 -1
- package/dist/martyrs/src/modules/events/components/pages/EditEventTickets.vue.js +1 -1
- package/dist/martyrs/src/modules/events/components/pages/Event.vue.js +2 -0
- package/dist/martyrs/src/modules/events/components/pages/Event.vue.js.map +1 -1
- package/dist/martyrs/src/modules/events/components/sections/EditTickets.vue.js +1 -1
- package/dist/martyrs/src/modules/gallery/components/sections/BackofficeGallery.vue.js +2 -2
- package/dist/martyrs/src/modules/inventory/components/forms/AdjustmentForm.vue.js +2 -2
- package/dist/martyrs/src/modules/inventory/components/forms/ColumnSettingsMenu.vue.js +1 -1
- package/dist/martyrs/src/modules/inventory/components/forms/HistoryView.vue.js +1 -1
- package/dist/martyrs/src/modules/inventory/components/forms/StockAlertsForm.vue.js +2 -2
- package/dist/martyrs/src/modules/inventory/components/pages/InventoryEdit.vue.js +2 -2
- package/dist/martyrs/src/modules/landing/components/sections/SectionFeatures.vue.js +1 -1
- package/dist/martyrs/src/modules/landing/components/sections/SectionFeatures.vue.js.map +1 -1
- package/dist/martyrs/src/modules/landing/components/sections/SectionGuide.vue.js +1 -1
- package/dist/martyrs/src/modules/marketplace/marketplace.client.js +5 -9
- package/dist/martyrs/src/modules/marketplace/marketplace.client.js.map +1 -1
- package/dist/martyrs/src/modules/marketplace/views/components/pages/Marketplace.vue.js +242 -0
- package/dist/martyrs/src/modules/marketplace/views/components/pages/Marketplace.vue.js.map +1 -0
- package/dist/martyrs/src/modules/marketplace/views/router/marketplace.router.js +39 -0
- package/dist/martyrs/src/modules/marketplace/views/router/marketplace.router.js.map +1 -0
- package/dist/martyrs/src/modules/marketplace/views/store/marketplace.js +65 -2
- package/dist/martyrs/src/modules/marketplace/views/store/marketplace.js.map +1 -1
- package/dist/martyrs/src/modules/music/components/cards/AlbumCard.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/cards/ArtistCardSmall.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/cards/PlaylistCard.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/cards/TrackListCard.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/forms/AlbumForm.vue.js +2 -2
- package/dist/martyrs/src/modules/music/components/forms/ArtistForm.vue.js +2 -2
- package/dist/martyrs/src/modules/music/components/forms/PlaylistForm.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/forms/SearchForm.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/forms/TrackForm.vue.js +2 -2
- package/dist/martyrs/src/modules/music/components/pages/Album.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/pages/Artist.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/pages/MusicLibrary.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/pages/Playlist.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/pages/SearchResults.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/pages/Track.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/pages/TrackCreate.vue.js +1 -1
- package/dist/martyrs/src/modules/music/components/player/MusicPlayer.vue.js +1 -1
- package/dist/martyrs/src/modules/orders/components/forms/FormApplicationDetails.vue.js +2 -2
- package/dist/martyrs/src/modules/orders/components/forms/FormCustomerDetails.vue.js +2 -2
- package/dist/martyrs/src/modules/orders/components/forms/FormSelectCustomer.vue.js +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/OrderBackoffice.vue.js +2 -2
- package/dist/martyrs/src/modules/orders/components/pages/OrderCreate.vue.js +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/OrderCreateBackoffice.vue.js +1 -1
- package/dist/martyrs/src/modules/orders/components/sections/ApplicationDetails.vue.js +1 -1
- package/dist/martyrs/src/modules/orders/components/sections/CustomerDetails.vue.js +1 -1
- package/dist/martyrs/src/modules/orders/components/sections/FormDelivery.vue.js +2 -0
- package/dist/martyrs/src/modules/orders/components/sections/FormDelivery.vue.js.map +1 -1
- package/dist/martyrs/src/modules/orders/components/sections/FormPayment.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/blocks/CardDepartment.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/blocks/CardOrganization.vue.js +4 -4
- package/dist/martyrs/src/modules/organizations/components/blocks/CardOrganization.vue.js.map +1 -1
- package/dist/martyrs/src/modules/organizations/components/elements/ButtonToggleMembership.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/forms/AddExistingMembersForm.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/forms/DepartmentForm.vue.js +2 -2
- package/dist/martyrs/src/modules/organizations/components/forms/InviteForm.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/Department.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/Organization.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/OrganizationBackoffice.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/OrganizationEdit.vue.js +2 -2
- package/dist/martyrs/src/modules/organizations/components/sections/Documents.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/sections/MembersAdd.vue.js +2 -2
- package/dist/martyrs/src/modules/organizations/components/sections/Organizations.vue.js +1 -1
- package/dist/martyrs/src/modules/pages/views/components/blocks/CardPage.vue.js +1 -1
- package/dist/martyrs/src/modules/pages/views/components/pages/PageEdit.vue.js +1 -1
- package/dist/martyrs/src/modules/pages/views/components/partials/SidebarPages.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Categories.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.js +4 -2
- package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.js.map +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Product.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.js +2 -2
- package/dist/martyrs/src/modules/products/components/pages/Products.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/sections/EditAttributes.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/sections/EditDiscounts.vue.js +2 -2
- package/dist/martyrs/src/modules/products/components/sections/EditVariants.vue.js +2 -2
- package/dist/martyrs/src/modules/products/components/sections/FilterProducts.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/sections/ProductConfigurator.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/sections/ProductsRecommended.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/sections/SectionProduct.vue.js +1 -1
- package/dist/martyrs/src/modules/rents/views/components/pages/Gant/GanttToolbar.vue.js +1 -1
- package/dist/martyrs/src/modules/reports/components/sections/FormReport.vue.js +2 -2
- package/dist/martyrs/src/modules/spots/components/blocks/SpotMemberModify.vue.js +1 -1
- package/dist/martyrs/src/modules/spots/components/layouts/Spots.vue.js +1 -1
- package/dist/martyrs/src/modules/spots/components/pages/Map.vue.js +1 -1
- package/dist/martyrs/src/modules/spots/components/pages/Spot.vue.js +1 -1
- package/dist/martyrs/src/modules/spots/components/pages/SpotEdit.vue.js +2 -2
- package/dist/martyrs/src/modules/spots/components/sections/WorktimeEdit.vue.js +2 -2
- package/dist/martyrs/src/modules/wallet/views/components/blocks/CryptoDeposit.vue.js +1 -1
- package/dist/martyrs/src/modules/wallet/views/components/pages/Wallet.vue.js +2 -2
- package/dist/martyrs.css +1 -1
- package/dist/martyrs.es.js +1 -1
- package/dist/music.server.js +4 -3
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/core/utils.js +1 -1
- package/dist/node_modules/.pnpm/qrcode@1.5.4/node_modules/qrcode/lib/renderer/utils.js +1 -1
- package/dist/orders.server.js +2 -2
- package/dist/organizations.server.js +10 -215
- package/dist/products.server.js +4 -3
- package/dist/queryProcessorOrganizations-BB11WFpc.js +221 -0
- package/dist/rents.server.js +2 -1
- package/dist/style.css +10 -1
- package/dist/{web-Cyc6i_pv.js → web-cNKIl_cL.js} +1 -1
- package/package.json +1 -1
- package/src/components/Button/Button.vue +1 -1
- package/src/components/Checkbox/Checkbox.vue +1 -1
- package/src/modules/core/views/components/layouts/Client.vue +7 -11
- package/src/modules/core/views/components/partials/Header.vue +1 -1
- package/src/modules/core/views/components/sections/Filters.vue +47 -161
- package/src/modules/core/views/components/sections/filters/FilterCheckbox.vue +12 -31
- package/src/modules/core/views/components/sections/filters/FilterDateRange.vue +15 -15
- package/src/modules/core/views/components/sections/filters/FilterOptions.vue +12 -43
- package/src/modules/core/views/components/sections/filters/FilterRange.vue +59 -36
- package/src/modules/core/views/components/sections/filters/FiltersGroup.vue +177 -0
- package/src/modules/core/views/utils/vue-app-renderer.js +12 -0
- package/src/modules/landing/components/sections/SectionFeatures.vue +1 -1
- package/src/modules/marketplace/controllers/marketplace.controller.js +123 -0
- package/src/modules/marketplace/controllers/utils/lookupConfigs.js +130 -0
- package/src/modules/marketplace/controllers/utils/queryProcessorMarketplace.js +211 -0
- package/src/modules/marketplace/marketplace.client.js +3 -10
- package/src/modules/marketplace/marketplace.server.js +22 -0
- package/src/modules/marketplace/routes/marketplace.routes.js +34 -0
- package/src/modules/marketplace/views/components/pages/Marketplace.vue +273 -0
- package/src/modules/marketplace/views/router/marketplace.router.js +37 -30
- package/src/modules/marketplace/views/store/marketplace.js +74 -3
- package/src/modules/organizations/components/blocks/CardOrganization.vue +8 -8
- package/src/modules/organizations/controllers/organizations.controller.js +1 -1
- package/src/modules/organizations/controllers/utils/queryProcessorOrganizations.js +8 -1
- package/dist/martyrs/src/components/Button/Button.vue.js.map +0 -1
- package/dist/martyrs/src/components/Menu/Menu.vue2.js.map +0 -1
- package/dist/martyrs/src/components/Select/Select.vue2.js.map +0 -1
- package/dist/martyrs/src/components/Spoiler/Spoiler.vue.js.map +0 -1
- package/dist/martyrs/src/modules/marketplace/marketplace.router.js +0 -63
- package/dist/martyrs/src/modules/marketplace/marketplace.router.js.map +0 -1
- package/dist/martyrs/src/modules/marketplace/views/components/layouts/Marketplace.vue.js +0 -326
- package/dist/martyrs/src/modules/marketplace/views/components/layouts/Marketplace.vue.js.map +0 -1
- package/dist/martyrs/src/modules/marketplace/views/components/pages/Catalog.vue.js +0 -74
- package/dist/martyrs/src/modules/marketplace/views/components/pages/Catalog.vue.js.map +0 -1
- package/src/modules/core/views/components/sections/filters/FilterPrice.vue +0 -81
- package/src/modules/marketplace/marketplace.router.js +0 -66
- package/src/modules/marketplace/views/components/layouts/Marketplace.vue +0 -363
- package/src/modules/marketplace/views/components/pages/Catalog.vue +0 -73
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div>
|
|
3
|
+
<div v-if="showHeader" class="flex-v-center flex-nowrap flex mn-b-medium">
|
|
4
|
+
<h3 class="flex-child-full">Filters</h3>
|
|
5
|
+
</div>
|
|
6
|
+
|
|
7
|
+
<div class="filters-content">
|
|
8
|
+
<div
|
|
9
|
+
v-for="filter in filters"
|
|
10
|
+
:key="filter.value"
|
|
11
|
+
class="mn-b-medium"
|
|
12
|
+
>
|
|
13
|
+
<h4 class="mn-b-small">{{ filter.title }}</h4>
|
|
14
|
+
|
|
15
|
+
<!-- Checkbox Filter -->
|
|
16
|
+
<FilterCheckbox
|
|
17
|
+
v-if="filter.type === 'checkbox'"
|
|
18
|
+
v-model="workingValues[filter.value]"
|
|
19
|
+
:options="filter.options"
|
|
20
|
+
@apply="handleApply(filter.value)"
|
|
21
|
+
/>
|
|
22
|
+
|
|
23
|
+
<!-- Range Filter -->
|
|
24
|
+
<FilterRange
|
|
25
|
+
v-else-if="filter.type === 'range'"
|
|
26
|
+
v-model="workingValues[filter.value]"
|
|
27
|
+
:minPlaceholder="filter.minPlaceholder || 'Min'"
|
|
28
|
+
:maxPlaceholder="filter.maxPlaceholder || 'Max'"
|
|
29
|
+
:label="filter.label"
|
|
30
|
+
@apply="handleApply(filter.value)"
|
|
31
|
+
/>
|
|
32
|
+
|
|
33
|
+
<!-- Date Filter -->
|
|
34
|
+
<FilterDateRange
|
|
35
|
+
v-else-if="filter.type === 'date'"
|
|
36
|
+
v-model="workingValues[filter.value]"
|
|
37
|
+
@apply="handleApply(filter.value)"
|
|
38
|
+
/>
|
|
39
|
+
|
|
40
|
+
<!-- Radio/Options Filter -->
|
|
41
|
+
<FilterOptions
|
|
42
|
+
v-else-if="filter.type === 'radio'"
|
|
43
|
+
v-model="workingValues[filter.value]"
|
|
44
|
+
:options="filter.options"
|
|
45
|
+
/>
|
|
46
|
+
</div>
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
<div class="flex gap-thin mn-t-medium">
|
|
50
|
+
<button
|
|
51
|
+
v-if="showApplyButton"
|
|
52
|
+
@click="applyFilters"
|
|
53
|
+
class="button bg-main flex-child-full"
|
|
54
|
+
>
|
|
55
|
+
Apply
|
|
56
|
+
</button>
|
|
57
|
+
<button
|
|
58
|
+
v-if="showResetButton"
|
|
59
|
+
@click="resetFilters"
|
|
60
|
+
class="button bg-light"
|
|
61
|
+
:class="{ 'flex-child-full': !showApplyButton }"
|
|
62
|
+
>
|
|
63
|
+
Reset Filters
|
|
64
|
+
</button>
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
</template>
|
|
68
|
+
|
|
69
|
+
<script setup>
|
|
70
|
+
import { ref, reactive, watch } from 'vue'
|
|
71
|
+
import { useGlobalMixins } from '@martyrs/src/modules/core/views/mixins/mixins.js'
|
|
72
|
+
import FilterCheckbox from './FilterCheckbox.vue'
|
|
73
|
+
import FilterRange from './FilterRange.vue'
|
|
74
|
+
import FilterDateRange from './FilterDateRange.vue'
|
|
75
|
+
import FilterOptions from './FilterOptions.vue'
|
|
76
|
+
|
|
77
|
+
const props = defineProps({
|
|
78
|
+
filters: {
|
|
79
|
+
type: Array,
|
|
80
|
+
required: true
|
|
81
|
+
},
|
|
82
|
+
immediate: {
|
|
83
|
+
type: Boolean,
|
|
84
|
+
default: false
|
|
85
|
+
},
|
|
86
|
+
showHeader: {
|
|
87
|
+
type: Boolean,
|
|
88
|
+
default: true
|
|
89
|
+
},
|
|
90
|
+
showApplyButton: {
|
|
91
|
+
type: Boolean,
|
|
92
|
+
default: false
|
|
93
|
+
},
|
|
94
|
+
showResetButton: {
|
|
95
|
+
type: Boolean,
|
|
96
|
+
default: true
|
|
97
|
+
}
|
|
98
|
+
})
|
|
99
|
+
|
|
100
|
+
const selected = defineModel('selected', {
|
|
101
|
+
type: Object,
|
|
102
|
+
default: () => ({})
|
|
103
|
+
})
|
|
104
|
+
|
|
105
|
+
const { returnCurrency } = useGlobalMixins()
|
|
106
|
+
|
|
107
|
+
const workingValues = reactive({})
|
|
108
|
+
|
|
109
|
+
// Initialize working values
|
|
110
|
+
watch(() => props.filters, (newFilters) => {
|
|
111
|
+
newFilters.forEach(filter => {
|
|
112
|
+
if (!workingValues[filter.value]) {
|
|
113
|
+
if (filter.type === 'checkbox') {
|
|
114
|
+
workingValues[filter.value] = [...(selected.value[filter.value] || [])]
|
|
115
|
+
} else if (filter.type === 'range') {
|
|
116
|
+
workingValues[filter.value] = { ...(selected.value[filter.value] || { min: '', max: '' }) }
|
|
117
|
+
} else if (filter.type === 'date') {
|
|
118
|
+
workingValues[filter.value] = selected.value[filter.value] || null
|
|
119
|
+
} else {
|
|
120
|
+
workingValues[filter.value] = selected.value[filter.value] || null
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
})
|
|
124
|
+
}, { immediate: true, deep: true })
|
|
125
|
+
|
|
126
|
+
// Sync selected to workingValues
|
|
127
|
+
watch(selected, (newValue) => {
|
|
128
|
+
Object.keys(newValue).forEach(key => {
|
|
129
|
+
const filter = props.filters.find(f => f.value === key)
|
|
130
|
+
if (filter) {
|
|
131
|
+
if (filter.type === 'checkbox') {
|
|
132
|
+
workingValues[key] = [...(newValue[key] || [])]
|
|
133
|
+
} else if (filter.type === 'range') {
|
|
134
|
+
workingValues[key] = { ...(newValue[key] || { min: '', max: '' }) }
|
|
135
|
+
} else {
|
|
136
|
+
workingValues[key] = newValue[key]
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
})
|
|
140
|
+
}, { deep: true })
|
|
141
|
+
|
|
142
|
+
const handleApply = (filterValue) => {
|
|
143
|
+
if (props.immediate) {
|
|
144
|
+
const updated = { ...selected.value }
|
|
145
|
+
updated[filterValue] = workingValues[filterValue]
|
|
146
|
+
selected.value = updated
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const applyFilters = () => {
|
|
151
|
+
const updated = {}
|
|
152
|
+
Object.keys(workingValues).forEach(key => {
|
|
153
|
+
updated[key] = workingValues[key]
|
|
154
|
+
})
|
|
155
|
+
selected.value = updated
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
const resetFilters = () => {
|
|
159
|
+
props.filters.forEach(filter => {
|
|
160
|
+
if (filter.type === 'checkbox') {
|
|
161
|
+
workingValues[filter.value] = []
|
|
162
|
+
} else if (filter.type === 'range') {
|
|
163
|
+
workingValues[filter.value] = { min: '', max: '' }
|
|
164
|
+
} else if (filter.type === 'date') {
|
|
165
|
+
workingValues[filter.value] = null
|
|
166
|
+
} else {
|
|
167
|
+
workingValues[filter.value] = null
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Удаляем ключ из selected
|
|
171
|
+
delete selected.value[filter.value]
|
|
172
|
+
})
|
|
173
|
+
}
|
|
174
|
+
</script>
|
|
175
|
+
|
|
176
|
+
<style scoped>
|
|
177
|
+
</style>
|
|
@@ -79,6 +79,8 @@ export function renderAndMountApp({ createApp, hooks = {} }) {
|
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
|
|
82
|
+
|
|
83
|
+
|
|
82
84
|
if (initialState) {
|
|
83
85
|
console.log('[AUTH COOKIE DEBUG] Browser initialState.auth:', initialState.auth);
|
|
84
86
|
console.log('[AUTH COOKIE DEBUG] Has token?', !!initialState?.auth?.access?.token);
|
|
@@ -89,6 +91,7 @@ export function renderAndMountApp({ createApp, hooks = {} }) {
|
|
|
89
91
|
|
|
90
92
|
if (initialState?.auth?.access?.token) {
|
|
91
93
|
console.log('[AUTH COOKIE DEBUG] Setting auth token from initialState');
|
|
94
|
+
|
|
92
95
|
setAuthToken(initialState.auth.access.token);
|
|
93
96
|
} else if (initialState?.auth && !initialState.auth.access?.status) {
|
|
94
97
|
// Если SSR сбросил auth (из-за ошибки), удаляем куку в браузере
|
|
@@ -106,6 +109,12 @@ export function renderAndMountApp({ createApp, hooks = {} }) {
|
|
|
106
109
|
}
|
|
107
110
|
}
|
|
108
111
|
|
|
112
|
+
const savedPosition = localStorage.getItem('position');
|
|
113
|
+
|
|
114
|
+
if (savedPosition) {
|
|
115
|
+
store.core.state.position = JSON.parse(savedPosition);
|
|
116
|
+
}
|
|
117
|
+
|
|
109
118
|
// app.config.globalProperties.$i18n.locale = router.currentRoute.value.params.locale
|
|
110
119
|
// app.config.globalProperties.$i18n.locale = router.currentRoute.value.params.locale
|
|
111
120
|
// If user browser locae supported then change locale
|
|
@@ -171,6 +180,9 @@ export async function render({ url, cookies, ssrContext, createApp}) {
|
|
|
171
180
|
}
|
|
172
181
|
}
|
|
173
182
|
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
|
|
174
186
|
if (user) {
|
|
175
187
|
// [LOADING 27] SSR auth initialization
|
|
176
188
|
performance.mark('loading-27-start');
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import Cache from '@martyrs/src/modules/core/controllers/classes/core.cache.js';
|
|
2
|
+
import queryProcessorCore from '@martyrs/src/modules/core/controllers/utils/queryProcessor.js';
|
|
3
|
+
import { getLookupStages } from '@martyrs/src/modules/organizations/controllers/utils/queryProcessorOrganizations.js';
|
|
4
|
+
import lookupConfigs from './utils/lookupConfigs.js';
|
|
5
|
+
import {
|
|
6
|
+
getBasicMatchConditions,
|
|
7
|
+
getPriceConditions,
|
|
8
|
+
getCategoryConditions,
|
|
9
|
+
getContainConditions,
|
|
10
|
+
getSpotsLocationStages,
|
|
11
|
+
} from './utils/queryProcessorMarketplace.js';
|
|
12
|
+
|
|
13
|
+
const controllerFactory = db => {
|
|
14
|
+
const Spot = db.spot;
|
|
15
|
+
|
|
16
|
+
const cache = new Cache({ ttlSeconds: 60 * 5 });
|
|
17
|
+
|
|
18
|
+
const readCatalog = async (req, res) => {
|
|
19
|
+
console.log('marketplace catalog query', req.query);
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
const cacheKey = JSON.stringify(req.query);
|
|
23
|
+
|
|
24
|
+
let cachedResult = await cache.get(cacheKey);
|
|
25
|
+
if (cachedResult) {
|
|
26
|
+
return res.status(200).send(cachedResult);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const matchConditions = getBasicMatchConditions(req.query);
|
|
30
|
+
|
|
31
|
+
const stages = [
|
|
32
|
+
// Базовые фильтры spots (delivery, payment)
|
|
33
|
+
...(matchConditions.length > 0 ? [{ $match: { $and: matchConditions } }] : []),
|
|
34
|
+
|
|
35
|
+
// Геопоиск ПЕРВЫМ (если есть location)
|
|
36
|
+
...(req.query.location || req.query.city || req.query.state || req.query.country
|
|
37
|
+
? (await getSpotsLocationStages(req.query)).stages
|
|
38
|
+
: [{ $addFields: { distance: null } }]),
|
|
39
|
+
|
|
40
|
+
// Lookups (без availability пока)
|
|
41
|
+
...getLookupStages(['products', 'organizations'], lookupConfigs),
|
|
42
|
+
|
|
43
|
+
// Фильтр по наличию products
|
|
44
|
+
...getContainConditions(['products', 'organizations']),
|
|
45
|
+
|
|
46
|
+
// Фильтр по ценам
|
|
47
|
+
...getPriceConditions(req.query.priceMin, req.query.priceMax),
|
|
48
|
+
|
|
49
|
+
// Фильтр по категориям
|
|
50
|
+
...getCategoryConditions(req.query.categories),
|
|
51
|
+
|
|
52
|
+
// Group по organization
|
|
53
|
+
{
|
|
54
|
+
$group: {
|
|
55
|
+
_id: { $arrayElemAt: ['$organizations._id', 0] },
|
|
56
|
+
profile: { $first: { $arrayElemAt: ['$organizations.profile', 0] } },
|
|
57
|
+
rating: { $first: { $arrayElemAt: ['$organizations.rating', 0] } },
|
|
58
|
+
official: { $first: { $arrayElemAt: ['$organizations.official', 0] } },
|
|
59
|
+
views: { $first: { $arrayElemAt: ['$organizations.views', 0] } },
|
|
60
|
+
spots: {
|
|
61
|
+
$push: {
|
|
62
|
+
_id: '$_id',
|
|
63
|
+
name: '$profile.name',
|
|
64
|
+
address: '$address',
|
|
65
|
+
location: '$location',
|
|
66
|
+
distance: '$distance',
|
|
67
|
+
delivery: '$delivery',
|
|
68
|
+
payment: '$payment',
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
products: { $first: '$products' },
|
|
72
|
+
distance: { $min: '$distance' },
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
|
|
76
|
+
// Добавляем numberOfProducts
|
|
77
|
+
{
|
|
78
|
+
$addFields: {
|
|
79
|
+
numberOfProducts: { $size: { $ifNull: ['$products', []] } },
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
|
|
83
|
+
// Финальная структура
|
|
84
|
+
{
|
|
85
|
+
$project: {
|
|
86
|
+
_id: 1,
|
|
87
|
+
profile: 1,
|
|
88
|
+
rating: 1,
|
|
89
|
+
official: 1,
|
|
90
|
+
views: 1,
|
|
91
|
+
spots: 1,
|
|
92
|
+
products: 1,
|
|
93
|
+
distance: 1,
|
|
94
|
+
numberOfProducts: 1,
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
// Сортировка
|
|
99
|
+
...queryProcessorCore.getSortingOptions(req.query.sortParam || 'distance', req.query.sortOrder),
|
|
100
|
+
|
|
101
|
+
// Пагинация
|
|
102
|
+
...queryProcessorCore.getPaginationOptions(req.query.skip, req.query.limit),
|
|
103
|
+
].filter(Boolean);
|
|
104
|
+
|
|
105
|
+
console.log('Marketplace pipeline:', JSON.stringify(stages, null, 2));
|
|
106
|
+
|
|
107
|
+
const catalog = await Spot.aggregate(stages);
|
|
108
|
+
|
|
109
|
+
await cache.setWithTags(cacheKey, catalog, ['marketplace_catalog']);
|
|
110
|
+
|
|
111
|
+
res.status(200).send(catalog);
|
|
112
|
+
} catch (err) {
|
|
113
|
+
console.error('Marketplace catalog error:', err);
|
|
114
|
+
res.status(500).send({ message: err.message });
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
readCatalog,
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export default controllerFactory;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
const lookupConfigs = {
|
|
2
|
+
availability: {
|
|
3
|
+
lookup: {
|
|
4
|
+
from: 'stockavailabilities',
|
|
5
|
+
localField: '_id',
|
|
6
|
+
foreignField: 'storage',
|
|
7
|
+
pipeline: [
|
|
8
|
+
{
|
|
9
|
+
$match: {
|
|
10
|
+
$expr: { $gt: ['$available', 0] },
|
|
11
|
+
},
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
$project: {
|
|
15
|
+
_id: 1,
|
|
16
|
+
product: 1,
|
|
17
|
+
variant: 1,
|
|
18
|
+
available: 1,
|
|
19
|
+
quantity: 1,
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
as: 'availability',
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
variants: {
|
|
27
|
+
lookup: {
|
|
28
|
+
from: 'variants',
|
|
29
|
+
let: { variantIds: '$availability.variant' },
|
|
30
|
+
pipeline: [
|
|
31
|
+
{
|
|
32
|
+
$match: {
|
|
33
|
+
$expr: {
|
|
34
|
+
$in: ['$_id', '$$variantIds'],
|
|
35
|
+
},
|
|
36
|
+
status: 'published',
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
$project: {
|
|
41
|
+
_id: 1,
|
|
42
|
+
product: 1,
|
|
43
|
+
name: 1,
|
|
44
|
+
price: 1,
|
|
45
|
+
unit: 1,
|
|
46
|
+
images: 1,
|
|
47
|
+
sku: 1,
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
],
|
|
51
|
+
as: 'variants',
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
products: {
|
|
55
|
+
lookup: {
|
|
56
|
+
from: 'products',
|
|
57
|
+
localField: 'organization',
|
|
58
|
+
foreignField: 'owner.target',
|
|
59
|
+
pipeline: [
|
|
60
|
+
{
|
|
61
|
+
$match: {
|
|
62
|
+
status: 'published',
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
$lookup: {
|
|
67
|
+
from: 'variants',
|
|
68
|
+
localField: '_id',
|
|
69
|
+
foreignField: 'product',
|
|
70
|
+
pipeline: [
|
|
71
|
+
{
|
|
72
|
+
$project: {
|
|
73
|
+
_id: 1,
|
|
74
|
+
name: 1,
|
|
75
|
+
price: 1,
|
|
76
|
+
unit: 1,
|
|
77
|
+
images: 1,
|
|
78
|
+
sku: 1,
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
],
|
|
82
|
+
as: 'variants',
|
|
83
|
+
},
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
$project: {
|
|
87
|
+
_id: 1,
|
|
88
|
+
name: 1,
|
|
89
|
+
description: 1,
|
|
90
|
+
images: 1,
|
|
91
|
+
category: 1,
|
|
92
|
+
'owner.target': 1,
|
|
93
|
+
'owner.type': 1,
|
|
94
|
+
variants: 1,
|
|
95
|
+
},
|
|
96
|
+
},
|
|
97
|
+
],
|
|
98
|
+
as: 'products',
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
organizations: {
|
|
102
|
+
lookup: {
|
|
103
|
+
from: 'organizations',
|
|
104
|
+
let: { orgIds: '$products.owner.target' },
|
|
105
|
+
pipeline: [
|
|
106
|
+
{
|
|
107
|
+
$match: {
|
|
108
|
+
$expr: {
|
|
109
|
+
$in: ['$_id', '$$orgIds'],
|
|
110
|
+
},
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
$project: {
|
|
115
|
+
_id: 1,
|
|
116
|
+
'profile.name': 1,
|
|
117
|
+
'profile.photo': 1,
|
|
118
|
+
'profile.description': 1,
|
|
119
|
+
'profile.tags': 1,
|
|
120
|
+
rating: 1,
|
|
121
|
+
official: 1,
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
as: 'organizations',
|
|
126
|
+
},
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
export default lookupConfigs;
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { Types } from 'mongoose';
|
|
2
|
+
import * as googleMapsServicesJs from '@googlemaps/google-maps-services-js';
|
|
3
|
+
|
|
4
|
+
const ObjectId = Types.ObjectId;
|
|
5
|
+
const { Client } = googleMapsServicesJs;
|
|
6
|
+
const client = new Client({});
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Get basic match conditions for spots (delivery, payment)
|
|
10
|
+
*/
|
|
11
|
+
const getBasicMatchConditions = query => {
|
|
12
|
+
const conditions = [];
|
|
13
|
+
|
|
14
|
+
if (query.delivery) {
|
|
15
|
+
// Нормализуем в массив и фильтруем пустые значения
|
|
16
|
+
let deliveryMethods = Array.isArray(query.delivery)
|
|
17
|
+
? query.delivery
|
|
18
|
+
: typeof query.delivery === 'string'
|
|
19
|
+
? query.delivery.split(',')
|
|
20
|
+
: [];
|
|
21
|
+
|
|
22
|
+
deliveryMethods = deliveryMethods.filter(Boolean).map(m => m.trim());
|
|
23
|
+
|
|
24
|
+
if (deliveryMethods.length > 0) {
|
|
25
|
+
// $in = spots которые поддерживают ХОТЯ БЫ ОДИН метод
|
|
26
|
+
conditions.push({ delivery: { $in: deliveryMethods } });
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (query.payment) {
|
|
31
|
+
// Нормализуем в массив и фильтруем пустые значения
|
|
32
|
+
let paymentMethods = Array.isArray(query.payment)
|
|
33
|
+
? query.payment
|
|
34
|
+
: typeof query.payment === 'string'
|
|
35
|
+
? query.payment.split(',')
|
|
36
|
+
: [];
|
|
37
|
+
|
|
38
|
+
paymentMethods = paymentMethods.filter(Boolean).map(m => m.trim());
|
|
39
|
+
|
|
40
|
+
if (paymentMethods.length > 0) {
|
|
41
|
+
// $in = spots которые поддерживают ХОТЯ БЫ ОДИН метод
|
|
42
|
+
conditions.push({ payment: { $in: paymentMethods } });
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return conditions;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Get price filter conditions for variants
|
|
51
|
+
*/
|
|
52
|
+
const getPriceConditions = (priceMin, priceMax) => {
|
|
53
|
+
if (!priceMin && !priceMax) return [];
|
|
54
|
+
|
|
55
|
+
const conditions = {};
|
|
56
|
+
|
|
57
|
+
if (priceMin !== undefined && priceMin !== null && priceMin !== '') {
|
|
58
|
+
conditions['products.variants.price'] = { $gte: parseFloat(priceMin) };
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (priceMax !== undefined && priceMax !== null && priceMax !== '') {
|
|
62
|
+
if (conditions['products.variants.price']) {
|
|
63
|
+
conditions['products.variants.price'].$lte = parseFloat(priceMax);
|
|
64
|
+
} else {
|
|
65
|
+
conditions['products.variants.price'] = { $lte: parseFloat(priceMax) };
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return Object.keys(conditions).length > 0 ? [{ $match: conditions }] : [];
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Get category filter conditions for products
|
|
74
|
+
*/
|
|
75
|
+
const getCategoryConditions = categories => {
|
|
76
|
+
if (!categories || categories.length === 0) return [];
|
|
77
|
+
|
|
78
|
+
const categoriesArray = Array.isArray(categories) ? categories : categories.split(',');
|
|
79
|
+
|
|
80
|
+
return [
|
|
81
|
+
{
|
|
82
|
+
$match: {
|
|
83
|
+
'products.category': { $in: categoriesArray.map(id => new ObjectId(id)) },
|
|
84
|
+
},
|
|
85
|
+
},
|
|
86
|
+
];
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Get contain conditions (spots must have availability, products, etc)
|
|
91
|
+
*/
|
|
92
|
+
const getContainConditions = contain => {
|
|
93
|
+
if (!contain) return [];
|
|
94
|
+
|
|
95
|
+
const conditions = contain.map(property => ({
|
|
96
|
+
[property]: { $exists: true, $not: { $size: 0 } },
|
|
97
|
+
}));
|
|
98
|
+
|
|
99
|
+
return conditions.length > 0 ? [{ $match: { $and: conditions } }] : [];
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Геофильтрация для Spots (адаптировано из organizations)
|
|
104
|
+
*/
|
|
105
|
+
const hasLocationParams = query => query.location || query.address || query.city || query.state || query.country;
|
|
106
|
+
|
|
107
|
+
const resolveLocation = async query => {
|
|
108
|
+
if (query.location) {
|
|
109
|
+
const parsedLocation = typeof query.location === 'string' ? JSON.parse(query.location) : query.location;
|
|
110
|
+
const coordinates = parsedLocation.lng ? [parsedLocation.lng, parsedLocation.lat] : parsedLocation.coordinates;
|
|
111
|
+
return { coordinates: coordinates.map(coord => parseFloat(coord)) };
|
|
112
|
+
}
|
|
113
|
+
const searchString = [query.address, query.city, query.state, query.country].filter(Boolean).join(', ');
|
|
114
|
+
try {
|
|
115
|
+
const geoResponse = await client.geocode({
|
|
116
|
+
params: {
|
|
117
|
+
address: searchString,
|
|
118
|
+
key: process.env.GOOGLE_MAPS_API_KEY,
|
|
119
|
+
},
|
|
120
|
+
});
|
|
121
|
+
if (!geoResponse.data.results?.length) {
|
|
122
|
+
throw new Error('Unable to geocode the provided location.');
|
|
123
|
+
}
|
|
124
|
+
const { lng, lat } = geoResponse.data.results[0].geometry.location;
|
|
125
|
+
return { coordinates: [lng, lat] };
|
|
126
|
+
} catch (err) {
|
|
127
|
+
throw new Error('Error occurred while geocoding.');
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
const getRadius = query => {
|
|
132
|
+
if (query.locationRadius) return parseFloat(query.locationRadius) / 6378.1;
|
|
133
|
+
if (query.city) return 25 / 6378.1;
|
|
134
|
+
if (query.state) return 50 / 6378.1;
|
|
135
|
+
return null;
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const getDistanceStages = location => [
|
|
139
|
+
{
|
|
140
|
+
$addFields: {
|
|
141
|
+
distance: {
|
|
142
|
+
$function: {
|
|
143
|
+
body: `function(spotCoords, userCoords, isMiles) {
|
|
144
|
+
function toRad(x) {
|
|
145
|
+
return x * Math.PI / 180;
|
|
146
|
+
}
|
|
147
|
+
var lon1 = spotCoords[0];
|
|
148
|
+
var lat1 = spotCoords[1];
|
|
149
|
+
var lon2 = userCoords[0];
|
|
150
|
+
var lat2 = userCoords[1];
|
|
151
|
+
var R = 6371;
|
|
152
|
+
if (isMiles) R = 3959;
|
|
153
|
+
var x1 = lat2 - lat1;
|
|
154
|
+
var dLat = toRad(x1);
|
|
155
|
+
var x2 = lon2 - lon1;
|
|
156
|
+
var dLon = toRad(x2);
|
|
157
|
+
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
|
158
|
+
Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) *
|
|
159
|
+
Math.sin(dLon / 2) * Math.sin(dLon / 2);
|
|
160
|
+
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
161
|
+
var d = R * c;
|
|
162
|
+
return d;
|
|
163
|
+
}`,
|
|
164
|
+
args: ['$location.coordinates', location.coordinates, false],
|
|
165
|
+
lang: 'js',
|
|
166
|
+
},
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
},
|
|
170
|
+
];
|
|
171
|
+
|
|
172
|
+
const getSpotsLocationStages = async query => {
|
|
173
|
+
if (!hasLocationParams(query)) {
|
|
174
|
+
return { stages: [], userLocation: null };
|
|
175
|
+
}
|
|
176
|
+
const location = await resolveLocation(query);
|
|
177
|
+
const radius = getRadius(query);
|
|
178
|
+
const geoStages = radius
|
|
179
|
+
? [
|
|
180
|
+
{
|
|
181
|
+
$match: {
|
|
182
|
+
'location.coordinates': {
|
|
183
|
+
$geoWithin: {
|
|
184
|
+
$centerSphere: [[location.coordinates[0], location.coordinates[1]], radius],
|
|
185
|
+
},
|
|
186
|
+
},
|
|
187
|
+
},
|
|
188
|
+
},
|
|
189
|
+
]
|
|
190
|
+
: [];
|
|
191
|
+
return {
|
|
192
|
+
stages: [...geoStages, ...getDistanceStages(location)],
|
|
193
|
+
userLocation: location,
|
|
194
|
+
};
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
export {
|
|
198
|
+
getBasicMatchConditions,
|
|
199
|
+
getPriceConditions,
|
|
200
|
+
getCategoryConditions,
|
|
201
|
+
getContainConditions,
|
|
202
|
+
getSpotsLocationStages,
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
export default {
|
|
206
|
+
getBasicMatchConditions,
|
|
207
|
+
getPriceConditions,
|
|
208
|
+
getCategoryConditions,
|
|
209
|
+
getContainConditions,
|
|
210
|
+
getSpotsLocationStages,
|
|
211
|
+
};
|