@ozdao/martyrs 0.2.562 → 0.2.564
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-TV4u6Jux.js → main-CmjWiDVF.js} +402 -402
- package/dist/marketplace.server.js +389 -0
- package/dist/martyrs/src/modules/core/views/components/sections/filters/FiltersGroup.vue.js +1 -3
- package/dist/martyrs/src/modules/core/views/components/sections/filters/FiltersGroup.vue.js.map +1 -1
- 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/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/{layouts → pages}/Marketplace.vue.js +14 -18
- 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 +0 -16
- package/dist/martyrs/src/modules/marketplace/views/store/marketplace.js.map +1 -1
- package/dist/martyrs.es.js +1 -1
- package/dist/music.server.js +4 -3
- package/dist/orders.server.js +2 -2
- package/dist/organizations.server.js +9 -219
- package/dist/products.server.js +4 -3
- package/dist/queryProcessorOrganizations-BB11WFpc.js +221 -0
- package/dist/rents.server.js +2 -1
- package/dist/{web-Cq5tyhkl.js → web-cNKIl_cL.js} +1 -1
- package/package.json +1 -1
- package/src/modules/core/views/components/sections/filters/FiltersGroup.vue +3 -4
- package/src/modules/landing/components/sections/SectionFeatures.vue +1 -1
- package/src/modules/marketplace/marketplace.client.js +3 -10
- package/src/modules/marketplace/views/components/{layouts → pages}/Marketplace.vue +7 -16
- package/src/modules/marketplace/views/router/marketplace.router.js +37 -45
- package/src/modules/marketplace/views/store/marketplace.js +0 -16
- 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.map +0 -1
- package/dist/martyrs/src/modules/marketplace/views/components/pages/Catalog.vue.js +0 -73
- package/dist/martyrs/src/modules/marketplace/views/components/pages/Catalog.vue.js.map +0 -1
- package/src/modules/marketplace/marketplace.router.js +0 -66
- package/src/modules/marketplace/views/components/pages/Catalog.vue +0 -74
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
import { m as middlewareIndexFactory } from "./index-_Edcmck_.js";
|
|
2
|
+
import { C as CacheNamespaced } from "./core.cache-DALYFDdy.js";
|
|
3
|
+
import { q as queryProcessorCore } from "./queryProcessor-CBQgZycY.js";
|
|
4
|
+
import { b as getLookupStages } from "./queryProcessorOrganizations-BB11WFpc.js";
|
|
5
|
+
import { Types } from "mongoose";
|
|
6
|
+
import * as googleMapsServicesJs from "@googlemaps/google-maps-services-js";
|
|
7
|
+
const lookupConfigs = {
|
|
8
|
+
availability: {
|
|
9
|
+
lookup: {
|
|
10
|
+
from: "stockavailabilities",
|
|
11
|
+
localField: "_id",
|
|
12
|
+
foreignField: "storage",
|
|
13
|
+
pipeline: [
|
|
14
|
+
{
|
|
15
|
+
$match: {
|
|
16
|
+
$expr: { $gt: ["$available", 0] }
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
$project: {
|
|
21
|
+
_id: 1,
|
|
22
|
+
product: 1,
|
|
23
|
+
variant: 1,
|
|
24
|
+
available: 1,
|
|
25
|
+
quantity: 1
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
],
|
|
29
|
+
as: "availability"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
variants: {
|
|
33
|
+
lookup: {
|
|
34
|
+
from: "variants",
|
|
35
|
+
let: { variantIds: "$availability.variant" },
|
|
36
|
+
pipeline: [
|
|
37
|
+
{
|
|
38
|
+
$match: {
|
|
39
|
+
$expr: {
|
|
40
|
+
$in: ["$_id", "$$variantIds"]
|
|
41
|
+
},
|
|
42
|
+
status: "published"
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
$project: {
|
|
47
|
+
_id: 1,
|
|
48
|
+
product: 1,
|
|
49
|
+
name: 1,
|
|
50
|
+
price: 1,
|
|
51
|
+
unit: 1,
|
|
52
|
+
images: 1,
|
|
53
|
+
sku: 1
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
],
|
|
57
|
+
as: "variants"
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
products: {
|
|
61
|
+
lookup: {
|
|
62
|
+
from: "products",
|
|
63
|
+
localField: "organization",
|
|
64
|
+
foreignField: "owner.target",
|
|
65
|
+
pipeline: [
|
|
66
|
+
{
|
|
67
|
+
$match: {
|
|
68
|
+
status: "published"
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
$lookup: {
|
|
73
|
+
from: "variants",
|
|
74
|
+
localField: "_id",
|
|
75
|
+
foreignField: "product",
|
|
76
|
+
pipeline: [
|
|
77
|
+
{
|
|
78
|
+
$project: {
|
|
79
|
+
_id: 1,
|
|
80
|
+
name: 1,
|
|
81
|
+
price: 1,
|
|
82
|
+
unit: 1,
|
|
83
|
+
images: 1,
|
|
84
|
+
sku: 1
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
],
|
|
88
|
+
as: "variants"
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
$project: {
|
|
93
|
+
_id: 1,
|
|
94
|
+
name: 1,
|
|
95
|
+
description: 1,
|
|
96
|
+
images: 1,
|
|
97
|
+
category: 1,
|
|
98
|
+
"owner.target": 1,
|
|
99
|
+
"owner.type": 1,
|
|
100
|
+
variants: 1
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
],
|
|
104
|
+
as: "products"
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
organizations: {
|
|
108
|
+
lookup: {
|
|
109
|
+
from: "organizations",
|
|
110
|
+
let: { orgIds: "$products.owner.target" },
|
|
111
|
+
pipeline: [
|
|
112
|
+
{
|
|
113
|
+
$match: {
|
|
114
|
+
$expr: {
|
|
115
|
+
$in: ["$_id", "$$orgIds"]
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
$project: {
|
|
121
|
+
_id: 1,
|
|
122
|
+
"profile.name": 1,
|
|
123
|
+
"profile.photo": 1,
|
|
124
|
+
"profile.description": 1,
|
|
125
|
+
"profile.tags": 1,
|
|
126
|
+
rating: 1,
|
|
127
|
+
official: 1
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
],
|
|
131
|
+
as: "organizations"
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
const ObjectId = Types.ObjectId;
|
|
136
|
+
const { Client } = googleMapsServicesJs;
|
|
137
|
+
const client = new Client({});
|
|
138
|
+
const getBasicMatchConditions = (query) => {
|
|
139
|
+
const conditions = [];
|
|
140
|
+
if (query.delivery) {
|
|
141
|
+
let deliveryMethods = Array.isArray(query.delivery) ? query.delivery : typeof query.delivery === "string" ? query.delivery.split(",") : [];
|
|
142
|
+
deliveryMethods = deliveryMethods.filter(Boolean).map((m) => m.trim());
|
|
143
|
+
if (deliveryMethods.length > 0) {
|
|
144
|
+
conditions.push({ delivery: { $in: deliveryMethods } });
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (query.payment) {
|
|
148
|
+
let paymentMethods = Array.isArray(query.payment) ? query.payment : typeof query.payment === "string" ? query.payment.split(",") : [];
|
|
149
|
+
paymentMethods = paymentMethods.filter(Boolean).map((m) => m.trim());
|
|
150
|
+
if (paymentMethods.length > 0) {
|
|
151
|
+
conditions.push({ payment: { $in: paymentMethods } });
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return conditions;
|
|
155
|
+
};
|
|
156
|
+
const getPriceConditions = (priceMin, priceMax) => {
|
|
157
|
+
if (!priceMin && !priceMax) return [];
|
|
158
|
+
const conditions = {};
|
|
159
|
+
if (priceMin !== void 0 && priceMin !== null && priceMin !== "") {
|
|
160
|
+
conditions["products.variants.price"] = { $gte: parseFloat(priceMin) };
|
|
161
|
+
}
|
|
162
|
+
if (priceMax !== void 0 && priceMax !== null && priceMax !== "") {
|
|
163
|
+
if (conditions["products.variants.price"]) {
|
|
164
|
+
conditions["products.variants.price"].$lte = parseFloat(priceMax);
|
|
165
|
+
} else {
|
|
166
|
+
conditions["products.variants.price"] = { $lte: parseFloat(priceMax) };
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return Object.keys(conditions).length > 0 ? [{ $match: conditions }] : [];
|
|
170
|
+
};
|
|
171
|
+
const getCategoryConditions = (categories) => {
|
|
172
|
+
if (!categories || categories.length === 0) return [];
|
|
173
|
+
const categoriesArray = Array.isArray(categories) ? categories : categories.split(",");
|
|
174
|
+
return [
|
|
175
|
+
{
|
|
176
|
+
$match: {
|
|
177
|
+
"products.category": { $in: categoriesArray.map((id) => new ObjectId(id)) }
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
];
|
|
181
|
+
};
|
|
182
|
+
const getContainConditions = (contain) => {
|
|
183
|
+
if (!contain) return [];
|
|
184
|
+
const conditions = contain.map((property) => ({
|
|
185
|
+
[property]: { $exists: true, $not: { $size: 0 } }
|
|
186
|
+
}));
|
|
187
|
+
return conditions.length > 0 ? [{ $match: { $and: conditions } }] : [];
|
|
188
|
+
};
|
|
189
|
+
const hasLocationParams = (query) => query.location || query.address || query.city || query.state || query.country;
|
|
190
|
+
const resolveLocation = async (query) => {
|
|
191
|
+
if (query.location) {
|
|
192
|
+
const parsedLocation = typeof query.location === "string" ? JSON.parse(query.location) : query.location;
|
|
193
|
+
const coordinates = parsedLocation.lng ? [parsedLocation.lng, parsedLocation.lat] : parsedLocation.coordinates;
|
|
194
|
+
return { coordinates: coordinates.map((coord) => parseFloat(coord)) };
|
|
195
|
+
}
|
|
196
|
+
const searchString = [query.address, query.city, query.state, query.country].filter(Boolean).join(", ");
|
|
197
|
+
try {
|
|
198
|
+
const geoResponse = await client.geocode({
|
|
199
|
+
params: {
|
|
200
|
+
address: searchString,
|
|
201
|
+
key: process.env.GOOGLE_MAPS_API_KEY
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
if (!geoResponse.data.results?.length) {
|
|
205
|
+
throw new Error("Unable to geocode the provided location.");
|
|
206
|
+
}
|
|
207
|
+
const { lng, lat } = geoResponse.data.results[0].geometry.location;
|
|
208
|
+
return { coordinates: [lng, lat] };
|
|
209
|
+
} catch (err) {
|
|
210
|
+
throw new Error("Error occurred while geocoding.");
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
const getRadius = (query) => {
|
|
214
|
+
if (query.locationRadius) return parseFloat(query.locationRadius) / 6378.1;
|
|
215
|
+
if (query.city) return 25 / 6378.1;
|
|
216
|
+
if (query.state) return 50 / 6378.1;
|
|
217
|
+
return null;
|
|
218
|
+
};
|
|
219
|
+
const getDistanceStages = (location) => [
|
|
220
|
+
{
|
|
221
|
+
$addFields: {
|
|
222
|
+
distance: {
|
|
223
|
+
$function: {
|
|
224
|
+
body: `function(spotCoords, userCoords, isMiles) {
|
|
225
|
+
function toRad(x) {
|
|
226
|
+
return x * Math.PI / 180;
|
|
227
|
+
}
|
|
228
|
+
var lon1 = spotCoords[0];
|
|
229
|
+
var lat1 = spotCoords[1];
|
|
230
|
+
var lon2 = userCoords[0];
|
|
231
|
+
var lat2 = userCoords[1];
|
|
232
|
+
var R = 6371;
|
|
233
|
+
if (isMiles) R = 3959;
|
|
234
|
+
var x1 = lat2 - lat1;
|
|
235
|
+
var dLat = toRad(x1);
|
|
236
|
+
var x2 = lon2 - lon1;
|
|
237
|
+
var dLon = toRad(x2);
|
|
238
|
+
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
|
|
239
|
+
Math.cos(toRad(lat1)) * Math.cos(toRad(lat2)) *
|
|
240
|
+
Math.sin(dLon / 2) * Math.sin(dLon / 2);
|
|
241
|
+
var c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
242
|
+
var d = R * c;
|
|
243
|
+
return d;
|
|
244
|
+
}`,
|
|
245
|
+
args: ["$location.coordinates", location.coordinates, false],
|
|
246
|
+
lang: "js"
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
];
|
|
252
|
+
const getSpotsLocationStages = async (query) => {
|
|
253
|
+
if (!hasLocationParams(query)) {
|
|
254
|
+
return { stages: [], userLocation: null };
|
|
255
|
+
}
|
|
256
|
+
const location = await resolveLocation(query);
|
|
257
|
+
const radius = getRadius(query);
|
|
258
|
+
const geoStages = radius ? [
|
|
259
|
+
{
|
|
260
|
+
$match: {
|
|
261
|
+
"location.coordinates": {
|
|
262
|
+
$geoWithin: {
|
|
263
|
+
$centerSphere: [[location.coordinates[0], location.coordinates[1]], radius]
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
] : [];
|
|
269
|
+
return {
|
|
270
|
+
stages: [...geoStages, ...getDistanceStages(location)],
|
|
271
|
+
userLocation: location
|
|
272
|
+
};
|
|
273
|
+
};
|
|
274
|
+
const controllerFactory = (db) => {
|
|
275
|
+
const Spot = db.spot;
|
|
276
|
+
const cache = new CacheNamespaced({ ttlSeconds: 60 * 5 });
|
|
277
|
+
const readCatalog = async (req, res) => {
|
|
278
|
+
console.log("marketplace catalog query", req.query);
|
|
279
|
+
try {
|
|
280
|
+
const cacheKey = JSON.stringify(req.query);
|
|
281
|
+
let cachedResult = await cache.get(cacheKey);
|
|
282
|
+
if (cachedResult) {
|
|
283
|
+
return res.status(200).send(cachedResult);
|
|
284
|
+
}
|
|
285
|
+
const matchConditions = getBasicMatchConditions(req.query);
|
|
286
|
+
const stages = [
|
|
287
|
+
// Базовые фильтры spots (delivery, payment)
|
|
288
|
+
...matchConditions.length > 0 ? [{ $match: { $and: matchConditions } }] : [],
|
|
289
|
+
// Геопоиск ПЕРВЫМ (если есть location)
|
|
290
|
+
...req.query.location || req.query.city || req.query.state || req.query.country ? (await getSpotsLocationStages(req.query)).stages : [{ $addFields: { distance: null } }],
|
|
291
|
+
// Lookups (без availability пока)
|
|
292
|
+
...getLookupStages(["products", "organizations"], lookupConfigs),
|
|
293
|
+
// Фильтр по наличию products
|
|
294
|
+
...getContainConditions(["products", "organizations"]),
|
|
295
|
+
// Фильтр по ценам
|
|
296
|
+
...getPriceConditions(req.query.priceMin, req.query.priceMax),
|
|
297
|
+
// Фильтр по категориям
|
|
298
|
+
...getCategoryConditions(req.query.categories),
|
|
299
|
+
// Group по organization
|
|
300
|
+
{
|
|
301
|
+
$group: {
|
|
302
|
+
_id: { $arrayElemAt: ["$organizations._id", 0] },
|
|
303
|
+
profile: { $first: { $arrayElemAt: ["$organizations.profile", 0] } },
|
|
304
|
+
rating: { $first: { $arrayElemAt: ["$organizations.rating", 0] } },
|
|
305
|
+
official: { $first: { $arrayElemAt: ["$organizations.official", 0] } },
|
|
306
|
+
views: { $first: { $arrayElemAt: ["$organizations.views", 0] } },
|
|
307
|
+
spots: {
|
|
308
|
+
$push: {
|
|
309
|
+
_id: "$_id",
|
|
310
|
+
name: "$profile.name",
|
|
311
|
+
address: "$address",
|
|
312
|
+
location: "$location",
|
|
313
|
+
distance: "$distance",
|
|
314
|
+
delivery: "$delivery",
|
|
315
|
+
payment: "$payment"
|
|
316
|
+
}
|
|
317
|
+
},
|
|
318
|
+
products: { $first: "$products" },
|
|
319
|
+
distance: { $min: "$distance" }
|
|
320
|
+
}
|
|
321
|
+
},
|
|
322
|
+
// Добавляем numberOfProducts
|
|
323
|
+
{
|
|
324
|
+
$addFields: {
|
|
325
|
+
numberOfProducts: { $size: { $ifNull: ["$products", []] } }
|
|
326
|
+
}
|
|
327
|
+
},
|
|
328
|
+
// Финальная структура
|
|
329
|
+
{
|
|
330
|
+
$project: {
|
|
331
|
+
_id: 1,
|
|
332
|
+
profile: 1,
|
|
333
|
+
rating: 1,
|
|
334
|
+
official: 1,
|
|
335
|
+
views: 1,
|
|
336
|
+
spots: 1,
|
|
337
|
+
products: 1,
|
|
338
|
+
distance: 1,
|
|
339
|
+
numberOfProducts: 1
|
|
340
|
+
}
|
|
341
|
+
},
|
|
342
|
+
// Сортировка
|
|
343
|
+
...queryProcessorCore.getSortingOptions(req.query.sortParam || "distance", req.query.sortOrder),
|
|
344
|
+
// Пагинация
|
|
345
|
+
...queryProcessorCore.getPaginationOptions(req.query.skip, req.query.limit)
|
|
346
|
+
].filter(Boolean);
|
|
347
|
+
console.log("Marketplace pipeline:", JSON.stringify(stages, null, 2));
|
|
348
|
+
const catalog = await Spot.aggregate(stages);
|
|
349
|
+
await cache.setWithTags(cacheKey, catalog, ["marketplace_catalog"]);
|
|
350
|
+
res.status(200).send(catalog);
|
|
351
|
+
} catch (err) {
|
|
352
|
+
console.error("Marketplace catalog error:", err);
|
|
353
|
+
res.status(500).send({ message: err.message });
|
|
354
|
+
}
|
|
355
|
+
};
|
|
356
|
+
return {
|
|
357
|
+
readCatalog
|
|
358
|
+
};
|
|
359
|
+
};
|
|
360
|
+
const marketplaceRoutes = (function(app, db) {
|
|
361
|
+
const controller = controllerFactory(db);
|
|
362
|
+
const { authJwt } = middlewareIndexFactory(db);
|
|
363
|
+
app.get(
|
|
364
|
+
"/api/marketplace/catalog",
|
|
365
|
+
[
|
|
366
|
+
authJwt.verifyToken(true)
|
|
367
|
+
// Optional authentication
|
|
368
|
+
],
|
|
369
|
+
controller.readCatalog
|
|
370
|
+
);
|
|
371
|
+
});
|
|
372
|
+
function initializeMarketplace(app, db, origins, publicPath) {
|
|
373
|
+
if (app) {
|
|
374
|
+
marketplaceRoutes(app, db);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
const routes = {
|
|
378
|
+
marketplaceRoutes
|
|
379
|
+
};
|
|
380
|
+
const initialize = initializeMarketplace;
|
|
381
|
+
const marketplace_server = {
|
|
382
|
+
initialize: initializeMarketplace,
|
|
383
|
+
routes
|
|
384
|
+
};
|
|
385
|
+
export {
|
|
386
|
+
marketplace_server as default,
|
|
387
|
+
initialize,
|
|
388
|
+
routes
|
|
389
|
+
};
|
|
@@ -101,10 +101,8 @@ const _sfc_main = {
|
|
|
101
101
|
} else {
|
|
102
102
|
workingValues[filter.value] = null;
|
|
103
103
|
}
|
|
104
|
+
delete selected.value[filter.value];
|
|
104
105
|
});
|
|
105
|
-
if (props.immediate) {
|
|
106
|
-
applyFilters();
|
|
107
|
-
}
|
|
108
106
|
};
|
|
109
107
|
return (_ctx, _cache) => {
|
|
110
108
|
return openBlock(), createElementBlock("div", null, [
|
package/dist/martyrs/src/modules/core/views/components/sections/filters/FiltersGroup.vue.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FiltersGroup.vue.js","sources":["../../../../../../../../../src/modules/core/views/components/sections/filters/FiltersGroup.vue"],"sourcesContent":["<template>\n <div>\n <div v-if=\"showHeader\" class=\"flex-v-center flex-nowrap flex mn-b-medium\">\n <h3 class=\"flex-child-full\">Filters</h3>\n </div>\n\n <div class=\"filters-content\">\n <div\n v-for=\"filter in filters\"\n :key=\"filter.value\"\n class=\"mn-b-medium\"\n >\n <h4 class=\"mn-b-small\">{{ filter.title }}</h4>\n\n <!-- Checkbox Filter -->\n <FilterCheckbox\n v-if=\"filter.type === 'checkbox'\"\n v-model=\"workingValues[filter.value]\"\n :options=\"filter.options\"\n @apply=\"handleApply(filter.value)\"\n />\n\n <!-- Range Filter -->\n <FilterRange\n v-else-if=\"filter.type === 'range'\"\n v-model=\"workingValues[filter.value]\"\n :minPlaceholder=\"filter.minPlaceholder || 'Min'\"\n :maxPlaceholder=\"filter.maxPlaceholder || 'Max'\"\n :label=\"filter.label\"\n @apply=\"handleApply(filter.value)\"\n />\n\n <!-- Date Filter -->\n <FilterDateRange\n v-else-if=\"filter.type === 'date'\"\n v-model=\"workingValues[filter.value]\"\n @apply=\"handleApply(filter.value)\"\n />\n\n <!-- Radio/Options Filter -->\n <FilterOptions\n v-else-if=\"filter.type === 'radio'\"\n v-model=\"workingValues[filter.value]\"\n :options=\"filter.options\"\n />\n </div>\n </div>\n\n <div class=\"flex gap-thin mn-t-medium\">\n <button\n v-if=\"showApplyButton\"\n @click=\"applyFilters\"\n class=\"button bg-main flex-child-full\"\n >\n Apply\n </button>\n <button\n v-if=\"showResetButton\"\n @click=\"resetFilters\"\n class=\"button bg-light\"\n :class=\"{ 'flex-child-full': !showApplyButton }\"\n >\n Reset Filters\n </button>\n </div>\n </div>\n</template>\n\n<script setup>\nimport { ref, reactive, watch } from 'vue'\nimport { useGlobalMixins } from '@martyrs/src/modules/core/views/mixins/mixins.js'\nimport FilterCheckbox from './FilterCheckbox.vue'\nimport FilterRange from './FilterRange.vue'\nimport FilterDateRange from './FilterDateRange.vue'\nimport FilterOptions from './FilterOptions.vue'\n\nconst props = defineProps({\n filters: {\n type: Array,\n required: true\n },\n immediate: {\n type: Boolean,\n default: false\n },\n showHeader: {\n type: Boolean,\n default: true\n },\n showApplyButton: {\n type: Boolean,\n default: false\n },\n showResetButton: {\n type: Boolean,\n default: true\n }\n})\n\nconst selected = defineModel('selected', {\n type: Object,\n default: () => ({})\n})\n\nconst { returnCurrency } = useGlobalMixins()\n\nconst workingValues = reactive({})\n\n// Initialize working values\nwatch(() => props.filters, (newFilters) => {\n newFilters.forEach(filter => {\n if (!workingValues[filter.value]) {\n if (filter.type === 'checkbox') {\n workingValues[filter.value] = [...(selected.value[filter.value] || [])]\n } else if (filter.type === 'range') {\n workingValues[filter.value] = { ...(selected.value[filter.value] || { min: '', max: '' }) }\n } else if (filter.type === 'date') {\n workingValues[filter.value] = selected.value[filter.value] || null\n } else {\n workingValues[filter.value] = selected.value[filter.value] || null\n }\n }\n })\n}, { immediate: true, deep: true })\n\n// Sync selected to workingValues\nwatch(selected, (newValue) => {\n Object.keys(newValue).forEach(key => {\n const filter = props.filters.find(f => f.value === key)\n if (filter) {\n if (filter.type === 'checkbox') {\n workingValues[key] = [...(newValue[key] || [])]\n } else if (filter.type === 'range') {\n workingValues[key] = { ...(newValue[key] || { min: '', max: '' }) }\n } else {\n workingValues[key] = newValue[key]\n }\n }\n })\n}, { deep: true })\n\nconst handleApply = (filterValue) => {\n if (props.immediate) {\n const updated = { ...selected.value }\n updated[filterValue] = workingValues[filterValue]\n selected.value = updated\n }\n}\n\nconst applyFilters = () => {\n const updated = {}\n Object.keys(workingValues).forEach(key => {\n updated[key] = workingValues[key]\n })\n selected.value = updated\n}\n\nconst resetFilters = () => {\n props.filters.forEach(filter => {\n if (filter.type === 'checkbox') {\n workingValues[filter.value] = []\n } else if (filter.type === 'range') {\n workingValues[filter.value] = { min: '', max: '' }\n } else if (filter.type === 'date') {\n workingValues[filter.value] = null\n } else {\n workingValues[filter.value] = null\n }\n
|
|
1
|
+
{"version":3,"file":"FiltersGroup.vue.js","sources":["../../../../../../../../../src/modules/core/views/components/sections/filters/FiltersGroup.vue"],"sourcesContent":["<template>\n <div>\n <div v-if=\"showHeader\" class=\"flex-v-center flex-nowrap flex mn-b-medium\">\n <h3 class=\"flex-child-full\">Filters</h3>\n </div>\n\n <div class=\"filters-content\">\n <div\n v-for=\"filter in filters\"\n :key=\"filter.value\"\n class=\"mn-b-medium\"\n >\n <h4 class=\"mn-b-small\">{{ filter.title }}</h4>\n\n <!-- Checkbox Filter -->\n <FilterCheckbox\n v-if=\"filter.type === 'checkbox'\"\n v-model=\"workingValues[filter.value]\"\n :options=\"filter.options\"\n @apply=\"handleApply(filter.value)\"\n />\n\n <!-- Range Filter -->\n <FilterRange\n v-else-if=\"filter.type === 'range'\"\n v-model=\"workingValues[filter.value]\"\n :minPlaceholder=\"filter.minPlaceholder || 'Min'\"\n :maxPlaceholder=\"filter.maxPlaceholder || 'Max'\"\n :label=\"filter.label\"\n @apply=\"handleApply(filter.value)\"\n />\n\n <!-- Date Filter -->\n <FilterDateRange\n v-else-if=\"filter.type === 'date'\"\n v-model=\"workingValues[filter.value]\"\n @apply=\"handleApply(filter.value)\"\n />\n\n <!-- Radio/Options Filter -->\n <FilterOptions\n v-else-if=\"filter.type === 'radio'\"\n v-model=\"workingValues[filter.value]\"\n :options=\"filter.options\"\n />\n </div>\n </div>\n\n <div class=\"flex gap-thin mn-t-medium\">\n <button\n v-if=\"showApplyButton\"\n @click=\"applyFilters\"\n class=\"button bg-main flex-child-full\"\n >\n Apply\n </button>\n <button\n v-if=\"showResetButton\"\n @click=\"resetFilters\"\n class=\"button bg-light\"\n :class=\"{ 'flex-child-full': !showApplyButton }\"\n >\n Reset Filters\n </button>\n </div>\n </div>\n</template>\n\n<script setup>\nimport { ref, reactive, watch } from 'vue'\nimport { useGlobalMixins } from '@martyrs/src/modules/core/views/mixins/mixins.js'\nimport FilterCheckbox from './FilterCheckbox.vue'\nimport FilterRange from './FilterRange.vue'\nimport FilterDateRange from './FilterDateRange.vue'\nimport FilterOptions from './FilterOptions.vue'\n\nconst props = defineProps({\n filters: {\n type: Array,\n required: true\n },\n immediate: {\n type: Boolean,\n default: false\n },\n showHeader: {\n type: Boolean,\n default: true\n },\n showApplyButton: {\n type: Boolean,\n default: false\n },\n showResetButton: {\n type: Boolean,\n default: true\n }\n})\n\nconst selected = defineModel('selected', {\n type: Object,\n default: () => ({})\n})\n\nconst { returnCurrency } = useGlobalMixins()\n\nconst workingValues = reactive({})\n\n// Initialize working values\nwatch(() => props.filters, (newFilters) => {\n newFilters.forEach(filter => {\n if (!workingValues[filter.value]) {\n if (filter.type === 'checkbox') {\n workingValues[filter.value] = [...(selected.value[filter.value] || [])]\n } else if (filter.type === 'range') {\n workingValues[filter.value] = { ...(selected.value[filter.value] || { min: '', max: '' }) }\n } else if (filter.type === 'date') {\n workingValues[filter.value] = selected.value[filter.value] || null\n } else {\n workingValues[filter.value] = selected.value[filter.value] || null\n }\n }\n })\n}, { immediate: true, deep: true })\n\n// Sync selected to workingValues\nwatch(selected, (newValue) => {\n Object.keys(newValue).forEach(key => {\n const filter = props.filters.find(f => f.value === key)\n if (filter) {\n if (filter.type === 'checkbox') {\n workingValues[key] = [...(newValue[key] || [])]\n } else if (filter.type === 'range') {\n workingValues[key] = { ...(newValue[key] || { min: '', max: '' }) }\n } else {\n workingValues[key] = newValue[key]\n }\n }\n })\n}, { deep: true })\n\nconst handleApply = (filterValue) => {\n if (props.immediate) {\n const updated = { ...selected.value }\n updated[filterValue] = workingValues[filterValue]\n selected.value = updated\n }\n}\n\nconst applyFilters = () => {\n const updated = {}\n Object.keys(workingValues).forEach(key => {\n updated[key] = workingValues[key]\n })\n selected.value = updated\n}\n\nconst resetFilters = () => {\n props.filters.forEach(filter => {\n if (filter.type === 'checkbox') {\n workingValues[filter.value] = []\n } else if (filter.type === 'range') {\n workingValues[filter.value] = { min: '', max: '' }\n } else if (filter.type === 'date') {\n workingValues[filter.value] = null\n } else {\n workingValues[filter.value] = null\n }\n\n // Удаляем ключ из selected\n delete selected.value[filter.value]\n })\n}\n</script>\n\n<style scoped>\n</style>\n"],"names":["_useModel"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4EA,UAAM,QAAQ;AAuBd,UAAM,WAAWA,SAAW,SAAC,UAG5B;AAED,UAAM,EAAE,eAAc,IAAK,gBAAe;AAE1C,UAAM,gBAAgB,SAAS,CAAA,CAAE;AAGjC,UAAM,MAAM,MAAM,SAAS,CAAC,eAAe;AACzC,iBAAW,QAAQ,YAAU;AAC3B,YAAI,CAAC,cAAc,OAAO,KAAK,GAAG;AAChC,cAAI,OAAO,SAAS,YAAY;AAC9B,0BAAc,OAAO,KAAK,IAAI,CAAC,GAAI,SAAS,MAAM,OAAO,KAAK,KAAK,EAAG;AAAA,UACxE,WAAW,OAAO,SAAS,SAAS;AAClC,0BAAc,OAAO,KAAK,IAAI,EAAE,GAAI,SAAS,MAAM,OAAO,KAAK,KAAK,EAAE,KAAK,IAAI,KAAK,GAAE,EAAG;AAAA,UAC3F,WAAW,OAAO,SAAS,QAAQ;AACjC,0BAAc,OAAO,KAAK,IAAI,SAAS,MAAM,OAAO,KAAK,KAAK;AAAA,UAChE,OAAO;AACL,0BAAc,OAAO,KAAK,IAAI,SAAS,MAAM,OAAO,KAAK,KAAK;AAAA,UAChE;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH,GAAG,EAAE,WAAW,MAAM,MAAM,KAAI,CAAE;AAGlC,UAAM,UAAU,CAAC,aAAa;AAC5B,aAAO,KAAK,QAAQ,EAAE,QAAQ,SAAO;AACnC,cAAM,SAAS,MAAM,QAAQ,KAAK,OAAK,EAAE,UAAU,GAAG;AACtD,YAAI,QAAQ;AACV,cAAI,OAAO,SAAS,YAAY;AAC9B,0BAAc,GAAG,IAAI,CAAC,GAAI,SAAS,GAAG,KAAK,EAAG;AAAA,UAChD,WAAW,OAAO,SAAS,SAAS;AAClC,0BAAc,GAAG,IAAI,EAAE,GAAI,SAAS,GAAG,KAAK,EAAE,KAAK,IAAI,KAAK,GAAE,EAAG;AAAA,UACnE,OAAO;AACL,0BAAc,GAAG,IAAI,SAAS,GAAG;AAAA,UACnC;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH,GAAG,EAAE,MAAM,KAAI,CAAE;AAEjB,UAAM,cAAc,CAAC,gBAAgB;AACnC,UAAI,MAAM,WAAW;AACnB,cAAM,UAAU,EAAE,GAAG,SAAS,MAAK;AACnC,gBAAQ,WAAW,IAAI,cAAc,WAAW;AAChD,iBAAS,QAAQ;AAAA,MACnB;AAAA,IACF;AAEA,UAAM,eAAe,MAAM;AACzB,YAAM,UAAU,CAAA;AAChB,aAAO,KAAK,aAAa,EAAE,QAAQ,SAAO;AACxC,gBAAQ,GAAG,IAAI,cAAc,GAAG;AAAA,MAClC,CAAC;AACD,eAAS,QAAQ;AAAA,IACnB;AAEA,UAAM,eAAe,MAAM;AACzB,YAAM,QAAQ,QAAQ,YAAU;AAC9B,YAAI,OAAO,SAAS,YAAY;AAC9B,wBAAc,OAAO,KAAK,IAAI,CAAA;AAAA,QAChC,WAAW,OAAO,SAAS,SAAS;AAClC,wBAAc,OAAO,KAAK,IAAI,EAAE,KAAK,IAAI,KAAK,GAAE;AAAA,QAClD,WAAW,OAAO,SAAS,QAAQ;AACjC,wBAAc,OAAO,KAAK,IAAI;AAAA,QAChC,OAAO;AACL,wBAAc,OAAO,KAAK,IAAI;AAAA,QAChC;AAGA,eAAO,SAAS,MAAM,OAAO,KAAK;AAAA,MACpC,CAAC;AAAA,IACH;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -22,7 +22,7 @@ const _sfc_main = {
|
|
|
22
22
|
return (_ctx, _cache) => {
|
|
23
23
|
return openBlock(), createElementBlock("section", _hoisted_1, [
|
|
24
24
|
createElementVNode("h2", {
|
|
25
|
-
class: "w-100 w-max-50r mn-b-small",
|
|
25
|
+
class: "w-100 w-max-50r mn-l-auto mn-r-auto mn-b-small",
|
|
26
26
|
innerHTML: unref(t)("title")
|
|
27
27
|
}, null, 8, _hoisted_2),
|
|
28
28
|
createElementVNode("div", _hoisted_3, [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SectionFeatures.vue.js","sources":["../../../../../../../src/modules/landing/components/sections/SectionFeatures.vue"],"sourcesContent":["<template>\n <section id=\"howtobuy\">\n <h2 class=\"w-100 w-max-50r mn-b-small\" v-html=\"t('title')\"/>\n \n <div class=\"cols-3 mobile:cols-1 gap-thin\">\n <div \n v-for=\"feature in tm('features')\" \n :key=\"feature.title\" \n class=\"pd-medium radius-medium\"\n >\n <p class=\"h2 i-extra radius-extra bg-main flex-center d-inline-flex mn-b-medium\">\n {{ feature.icon }}\n </p>\n <h3 class=\"mn-b-medium\">\n {{ feature.title }}\n </h3>\n <p class=\"t-transp\">\n {{ feature.description }}\n </p>\n </div>\n </div>\n </section>\n</template>\n\n\n<script setup>\n import { useI18n } from 'vue-i18n'\n\n const props = defineProps({\n content: {\n type: Object,\n required: true\n }\n })\n\n const { t, tm } = useI18n({\n messages: props.content\n })\n</script>\n\n<style lang=\"scss\">\n</style>\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AA4BE,UAAM,QAAQ;AAOd,UAAM,EAAE,GAAG,GAAE,IAAK,QAAQ;AAAA,MACxB,UAAU,MAAM;AAAA,IACpB,CAAG;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
1
|
+
{"version":3,"file":"SectionFeatures.vue.js","sources":["../../../../../../../src/modules/landing/components/sections/SectionFeatures.vue"],"sourcesContent":["<template>\n <section id=\"howtobuy\">\n <h2 class=\"w-100 w-max-50r mn-l-auto mn-r-auto mn-b-small\" v-html=\"t('title')\"/>\n \n <div class=\"cols-3 mobile:cols-1 gap-thin\">\n <div \n v-for=\"feature in tm('features')\" \n :key=\"feature.title\" \n class=\"pd-medium radius-medium\"\n >\n <p class=\"h2 i-extra radius-extra bg-main flex-center d-inline-flex mn-b-medium\">\n {{ feature.icon }}\n </p>\n <h3 class=\"mn-b-medium\">\n {{ feature.title }}\n </h3>\n <p class=\"t-transp\">\n {{ feature.description }}\n </p>\n </div>\n </div>\n </section>\n</template>\n\n\n<script setup>\n import { useI18n } from 'vue-i18n'\n\n const props = defineProps({\n content: {\n type: Object,\n required: true\n }\n })\n\n const { t, tm } = useI18n({\n messages: props.content\n })\n</script>\n\n<style lang=\"scss\">\n</style>\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AA4BE,UAAM,QAAQ;AAOd,UAAM,EAAE,GAAG,GAAE,IAAK,QAAQ;AAAA,MACxB,UAAU,MAAM;AAAA,IACpB,CAAG;;;;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import addRoutes from "../core/views/router/addRoutes.js";
|
|
2
|
-
import { getRoutes } from "./marketplace.router.js";
|
|
2
|
+
import { getRoutes } from "./views/router/marketplace.router.js";
|
|
3
3
|
import * as marketplace from "./views/store/marketplace.js";
|
|
4
|
-
import _sfc_main from "./views/components/
|
|
5
|
-
import _sfc_main$
|
|
6
|
-
import _sfc_main$1 from "./views/components/pages/Catalog.vue.js";
|
|
4
|
+
import _sfc_main from "./views/components/pages/Marketplace.vue.js";
|
|
5
|
+
import _sfc_main$1 from "./views/components/sections/SectionMenu.vue.js";
|
|
7
6
|
function initializeMarketplace(app, store, router, options = {}) {
|
|
8
7
|
const routes = getRoutes(options);
|
|
9
8
|
routes.forEach(({ parentName, config }) => {
|
|
@@ -24,18 +23,15 @@ const ModuleMarketplace = {
|
|
|
24
23
|
// Elements
|
|
25
24
|
// Blocks
|
|
26
25
|
// Sections
|
|
27
|
-
SectionMenu: _sfc_main$
|
|
26
|
+
SectionMenu: _sfc_main$1,
|
|
28
27
|
// Pages
|
|
29
|
-
Catalog: _sfc_main$1,
|
|
30
|
-
// Layouts
|
|
31
28
|
Marketplace: _sfc_main
|
|
32
29
|
}
|
|
33
30
|
}
|
|
34
31
|
};
|
|
35
32
|
export {
|
|
36
|
-
_sfc_main$1 as Catalog,
|
|
37
33
|
_sfc_main as Marketplace,
|
|
38
|
-
_sfc_main$
|
|
34
|
+
_sfc_main$1 as SectionMenu,
|
|
39
35
|
ModuleMarketplace as default
|
|
40
36
|
};
|
|
41
37
|
//# sourceMappingURL=marketplace.client.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"marketplace.client.js","sources":["../../../../../src/modules/marketplace/marketplace.client.js"],"sourcesContent":["// Router\nimport addRoutes from '@martyrs/src/modules/core/views/router/addRoutes.js';\nimport { getRoutes } from './marketplace.router.js';\n\n//Store\nimport * as storeMarketplace from './views/store/marketplace.js';\n\n//
|
|
1
|
+
{"version":3,"file":"marketplace.client.js","sources":["../../../../../src/modules/marketplace/marketplace.client.js"],"sourcesContent":["// Router\nimport addRoutes from '@martyrs/src/modules/core/views/router/addRoutes.js';\nimport { getRoutes } from './views/router/marketplace.router.js';\n\n//Store\nimport * as storeMarketplace from './views/store/marketplace.js';\n\n// Pages\nimport Marketplace from './views/components/pages/Marketplace.vue';\n\n// Sections\nimport SectionMenu from './views/components/sections/SectionMenu.vue';\n\n// Пример функции инициализации для модуля маркетплейса\nfunction initializeMarketplace(app, store, router, options = {}) {\n const routes = getRoutes(options);\n routes.forEach(({ parentName, config }) => {\n addRoutes(router, { ...config, parentName });\n });\n\n store.addStore('marketplace', storeMarketplace);\n}\n\nconst ModuleMarketplace = {\n initialize: initializeMarketplace,\n views: {\n store: {\n storeMarketplace,\n },\n router: {\n getRoutes,\n },\n components: {\n // Elements\n // Blocks\n // Sections\n SectionMenu,\n // Pages\n Marketplace,\n },\n },\n};\n\nexport {\n // Elements\n // Pages\n Marketplace,\n // Blocks\n // Sections\n SectionMenu,\n};\n\nexport default ModuleMarketplace;\n"],"names":["storeMarketplace","SectionMenu","Marketplace"],"mappings":";;;;;AAcA,SAAS,sBAAsB,KAAK,OAAO,QAAQ,UAAU,CAAA,GAAI;AAC/D,QAAM,SAAS,UAAU,OAAO;AAChC,SAAO,QAAQ,CAAC,EAAE,YAAY,OAAM,MAAO;AACzC,cAAU,QAAQ,EAAE,GAAG,QAAQ,WAAU,CAAE;AAAA,EAC7C,CAAC;AAED,QAAM,SAAS,eAAeA,WAAgB;AAChD;AAEK,MAAC,oBAAoB;AAAA,EACxB,YAAY;AAAA,EACZ,OAAO;AAAA,IACL,OAAO;AAAA,MACX,kBAAMA;AAAAA,IACN;AAAA,IACI,QAAQ;AAAA,MACN;AAAA,IACN;AAAA,IACI,YAAY;AAAA;AAAA;AAAA;AAAA,MAIhB,aAAMC;AAAAA;AAAAA,MAEN,aAAMC;AAAAA,IACN;AAAA,EACA;AACA;"}
|
package/dist/martyrs/src/modules/marketplace/views/components/{layouts → pages}/Marketplace.vue.js
RENAMED
|
@@ -15,7 +15,10 @@ const _hoisted_3 = { class: "" };
|
|
|
15
15
|
const _hoisted_4 = { class: "cols-2-1_3 br-1px br-solid br-light z-index-3 pos-relative" };
|
|
16
16
|
const _hoisted_5 = { class: "o-y-scroll br-r br-solid br-light pd-medium z-index-2 desktop-only h-100 pos-relative" };
|
|
17
17
|
const _hoisted_6 = { class: "w-100 o-y-scroll h-100" };
|
|
18
|
-
const _hoisted_7 = {
|
|
18
|
+
const _hoisted_7 = {
|
|
19
|
+
key: 0,
|
|
20
|
+
class: "mn-b-medium"
|
|
21
|
+
};
|
|
19
22
|
const _hoisted_8 = { class: "gap-micro" };
|
|
20
23
|
const _hoisted_9 = ["onClick"];
|
|
21
24
|
const _hoisted_10 = { class: "w-100 rows-1 pd-thin pos-relative o-hidden" };
|
|
@@ -34,13 +37,6 @@ const _sfc_main = {
|
|
|
34
37
|
});
|
|
35
38
|
const localLocation = ref(null);
|
|
36
39
|
const searchLocation = ref("");
|
|
37
|
-
const selectedFilters = ref({
|
|
38
|
-
price: { min: null, max: null },
|
|
39
|
-
delivery: [],
|
|
40
|
-
payment: [],
|
|
41
|
-
availabilityDate: null,
|
|
42
|
-
rating: null
|
|
43
|
-
});
|
|
44
40
|
if (route.params) {
|
|
45
41
|
let newState = {
|
|
46
42
|
country: denormalizeUrlParam(route.params.country),
|
|
@@ -150,7 +146,7 @@ const _sfc_main = {
|
|
|
150
146
|
createElementVNode("div", _hoisted_4, [
|
|
151
147
|
createElementVNode("div", _hoisted_5, [
|
|
152
148
|
createElementVNode("div", _hoisted_6, [
|
|
153
|
-
|
|
149
|
+
!unref(route).params.country && !unref(route).params.state && !unref(route).params.city ? (openBlock(), createElementBlock("div", _hoisted_7, [
|
|
154
150
|
_cache[8] || (_cache[8] = createElementVNode("h4", { class: "mn-b-small" }, "Location", -1)),
|
|
155
151
|
createVNode(Field, {
|
|
156
152
|
modelValue: searchLocation.value,
|
|
@@ -168,11 +164,11 @@ const _sfc_main = {
|
|
|
168
164
|
}, toDisplayString(location.label), 9, _hoisted_9);
|
|
169
165
|
}), 128))
|
|
170
166
|
])
|
|
171
|
-
]),
|
|
167
|
+
])) : createCommentVNode("", true),
|
|
172
168
|
createVNode(_sfc_main$1, {
|
|
173
169
|
filters: state.filter.options,
|
|
174
|
-
selected:
|
|
175
|
-
"onUpdate:selected": _cache[3] || (_cache[3] = ($event) =>
|
|
170
|
+
selected: state.filter.selected,
|
|
171
|
+
"onUpdate:selected": _cache[3] || (_cache[3] = ($event) => state.filter.selected = $event),
|
|
176
172
|
immediate: true,
|
|
177
173
|
showHeader: false,
|
|
178
174
|
showApplyButton: false,
|
|
@@ -202,10 +198,10 @@ const _sfc_main = {
|
|
|
202
198
|
location: localLocation.value?.location,
|
|
203
199
|
lookup: ["products", "spots"],
|
|
204
200
|
contain: ["products"],
|
|
205
|
-
priceMin:
|
|
206
|
-
priceMax:
|
|
207
|
-
delivery:
|
|
208
|
-
payment:
|
|
201
|
+
priceMin: state.filter.selected.price?.min,
|
|
202
|
+
priceMax: state.filter.selected.price?.max,
|
|
203
|
+
delivery: state.filter.selected.delivery?.length > 0 ? state.filter.selected.delivery.join(",") : void 0,
|
|
204
|
+
payment: state.filter.selected.payment?.length > 0 ? state.filter.selected.payment.join(",") : void 0
|
|
209
205
|
},
|
|
210
206
|
class: "rows-1 gap-thin"
|
|
211
207
|
}, {
|
|
@@ -216,8 +212,8 @@ const _sfc_main = {
|
|
|
216
212
|
createVNode(Filters, {
|
|
217
213
|
filters: state.filter.options,
|
|
218
214
|
"onUpdate:filters": _cache[4] || (_cache[4] = ($event) => state.filter.options = $event),
|
|
219
|
-
selected:
|
|
220
|
-
"onUpdate:selected": _cache[5] || (_cache[5] = ($event) =>
|
|
215
|
+
selected: state.filter.selected,
|
|
216
|
+
"onUpdate:selected": _cache[5] || (_cache[5] = ($event) => state.filter.selected = $event),
|
|
221
217
|
class: ""
|
|
222
218
|
}, null, 8, ["filters", "selected"])
|
|
223
219
|
]),
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Marketplace.vue.js","sources":["../../../../../../../../src/modules/marketplace/views/components/pages/Marketplace.vue"],"sourcesContent":["<template>\n <div class=\"pos-relative\">\n <header class=\"pd-medium mn-b-thin\">\n <h2 class=\"\">\n <span class=\"\">Weed Deliveries in </span>\n\n <span\n v-if=\"localPosition.city || localPosition.state || localPosition.country\"\n @click=\"a => { store.core.state.isOpenLocationPopup = true }\"\n class=\"t-main t-semi cursor-pointer \"\n >\n <template v-if=\"localPosition.city\">{{localPosition.city}}, </template>\n <template v-if=\"localPosition.state\">{{localPosition.state}}, </template>\n <template v-if=\"localPosition.country\">{{localPosition.country}}</template>\n </span>\n\n <span v-else @click=\"a => { store.core.state.isOpenLocationPopup = true }\" class=\"t-main t-semi cursor-pointer\">The World</span>\n </h2>\n </header>\n\n <div class=\"cols-2-1_3 br-1px br-solid br-light z-index-3 pos-relative\">\n\n <div class=\"o-y-scroll br-r br-solid br-light pd-medium z-index-2 desktop-only h-100 pos-relative\">\n <div class=\"w-100 o-y-scroll h-100\">\n <!-- Location Filter -->\n <div v-if=\"!route.params.country && !route.params.state && !route.params.city\" class=\"mn-b-medium\">\n <h4 class=\"mn-b-small\">Location</h4>\n <Field\n v-model=\"searchLocation\"\n placeholder=\"Search location...\"\n type=\"text\"\n class=\"w-100 bg-light pd-small radius-small mn-b-small\"\n />\n <div class=\"gap-micro\">\n <div\n v-for=\"location in marketplace.state.locationOptions\"\n :key=\"location.label\"\n @click=\"router.push(location.path)\"\n class=\"cursor-pointer hover-t-underline mn-b-regular transition-all\"\n >\n {{ location.label }}\n </div>\n </div>\n </div>\n\n <!-- Filters Group -->\n <FiltersGroup\n :filters=\"marketplace.state.filter.options\"\n v-model:selected=\"marketplace.state.filter.selected\"\n :immediate=\"true\"\n :showHeader=\"false\"\n :showApplyButton=\"false\"\n :showResetButton=\"true\"\n />\n </div>\n </div>\n\n <div class=\"w-100 rows-1 pd-thin pos-relative o-hidden\">\n <Feed\n :search=\"true\"\n v-model:sort=\"marketplace.state.sort\"\n :showLoadMore=\"false\"\n :states=\"{\n empty: {\n title: 'No Shops Found',\n description: 'Currently, there are no shops.'\n }\n }\"\n :store=\"{\n read: (options) => marketplaceStore.readCatalog(options)\n }\"\n :options=\"{\n country: localPosition.country,\n state: localPosition.state,\n city: localPosition.city,\n location: localLocation?.location,\n lookup: ['products','spots'],\n contain: ['products'],\n priceMin: marketplace.state.filter.selected.price?.min,\n priceMax: marketplace.state.filter.selected.price?.max,\n delivery: marketplace.state.filter.selected.delivery?.length > 0 ? marketplace.state.filter.selected.delivery.join(',') : undefined,\n payment: marketplace.state.filter.selected.payment?.length > 0 ? marketplace.state.filter.selected.payment.join(',') : undefined\n }\"\n v-slot=\"{\n items\n }\"\n class=\"rows-1 gap-thin\"\n >\n <div class=\"mn-b-thin mobile-only\">\n <Filters\n v-model:filters=\"marketplace.state.filter.options\"\n v-model:selected=\"marketplace.state.filter.selected\"\n class=\"\"\n />\n </div>\n\n <CardOrganization\n v-for=\"organization in items\"\n :key=\"organization._id\"\n :organization=\"organization\"\n :showRating=\"true\"\n :showFollowers=\"false\"\n :showProducts=\"true\"\n class=\"bg-light w-100 o-hidden radius-medium pd-small \"\n />\n </Feed>\n\n </div>\n </div>\n </div>\n\n</template>\n\n\n<script setup=\"props\">\n // Import libs\n import { onMounted, watch, ref } from 'vue'\n import { useRoute, useRouter } from 'vue-router'\n import { useI18n } from 'vue-i18n'\n\n import Feed from '@martyrs/src/components/Feed/Feed.vue'\n import Filters from '@martyrs/src/modules/core/views/components/sections/Filters.vue'\n import FiltersGroup from '@martyrs/src/modules/core/views/components/sections/filters/FiltersGroup.vue'\n import Field from \"@martyrs/src/components/Field/Field.vue\"\n\n import CardOrganization from '@martyrs/src/modules/organizations/components/blocks/CardOrganization.vue'\n\n import { useStore } from '@martyrs/src/modules/core/views/store/core.store.js'\n import * as organization from '@martyrs/src/modules/organizations/store/organizations.js'\n import * as marketplace from '../../store/marketplace'\n import marketplaceStore from '../../store/marketplace'\n import { useGlobalMixins } from '@martyrs/src/modules/core/views/mixins/mixins.js'\n\n const route = useRoute()\n const router = useRouter()\n const store = useStore()\n const { returnCurrency } = useGlobalMixins()\n\n const localPosition = ref({\n city: null,\n state: null,\n country: null\n });\n\n const localLocation = ref(null);\n // Location filter\n const searchLocation = ref('');\n\n if (route.params) {\n // Загружаем новые значения из параметров маршрута в состояние\n let newState = {\n country: denormalizeUrlParam(route.params.country),\n state: denormalizeUrlParam(route.params.state),\n city: denormalizeUrlParam(route.params.city),\n };\n\n\t // Обновляем глобальное состояние\n\t localPosition.value = newState;\n\t}\n\n\tif (route.query) {\n\t \tconst query = route.query;\n\n\t\tmarketplace.state.filter.selected.categories = query.categories ? query.categories.split(',') : [];\n\t\tmarketplace.state.filter.selected.prices = query.prices ? query.prices.split(',') : [];\n\t\tmarketplace.state.filter.selected.delivery = query.delivery ? query.delivery.split(',') : [];\n\t}\n\n\tif (route.query.sortParam) marketplace.state.sort.param = route.query.sortParam\n\tif (route.query.sortOrder) marketplace.state.sort.order = route.query.sortOrder\n\n function denormalizeUrlParam(param) {\n return param\n .replace(/-/g, ' ')\n .replace(/\\b\\w/g, l => l.toUpperCase());\n }\n\n function normalizeUrlParam(param) {\n return param\n .toLowerCase()\n .replace(/ /g, '-')\n .replace(/[^a-z0-9-]/g, '');\n }\n\n\twatch(() => marketplace.state.sort, (newSortValue, oldSortValue) => {\n\t\tlet query = { ...route.query}\n\t\t\n\t\tquery.sortParam = newSortValue.param\n\t\tquery.sortOrder = newSortValue.order\n\t \n\t // replace the current route\n\t router.replace({ query });\n\t}, { deep: true });\n\n\n\twatch(() => marketplace.state.filter.selectedFilters, (newFilterValue, oldFilterValue) => {\n\t // Переводим фильтр в формат query\n\t const query = { ...route.query };\n\n\t // Удаляем старые значения фильтра из query\n\t Object.keys(oldFilterValue).forEach(key => {\n\t if (query[key]) {\n\t delete query[key];\n\t }\n\t });\n\n\t // Добавляем новые значения фильтра в query\n\t const newQueryValues = Object.fromEntries(\n\t Object.entries(newFilterValue)\n\t .filter(([key, value]) => Array.isArray(value) && value.length > 0)\n\t .map(([key, value]) => [key, value.join(',')])\n\t );\n\n\t delete query.options;\n\t Object.assign(query, newQueryValues);\n\n\t // Обновляем маршрут с новым query\n\t router.replace({ query });\n\t}, { deep: true })\n\n\twatch(() => store.core.state.position, (newPosition) => {\n // get the current route\n const currentRoute = { ...router.currentRoute.value };\n\t \n // create new parameters based on globals state position\n let newParams = {\n country: normalizeUrlParam(newPosition.country),\n state: normalizeUrlParam(newPosition.state),\n city: normalizeUrlParam(newPosition.city),\n };\n\n let newState = {\n country: denormalizeUrlParam(newPosition.country),\n state: denormalizeUrlParam(newPosition.state),\n city: denormalizeUrlParam(newPosition.city),\n };\n \n // update route params\n localPosition.value = newState;\n currentRoute.params = newParams;\n\n \n // replace the current route\n router.replace(currentRoute);\n\t}, { deep: true });\n\n const text = {\n locale: 'en',\n messages: {\n en: {\n meta: {\n title: \"Marketplace – Shop Our Wide Selection of Quality Weed for Delivery\",\n description: \"Browse our marketplace of top-grade weed strains and choose from a variety of delivery options. Order now and have your favorite strains delivered straight to your door. Safe, fast, and reliable.\",\n }\n },\n ru: {\n meta: {\n title: \"Маркетплейс – Выбирайте из нашего ассортимента качественной травки для доставки\",\n description: \"Маркетплейс – Изучите наши продукты высокого качества и выбирайте из различных вариантов доставки. Закажите сейчас и получите свои любимые сорта на дом. Безопасно, быстро и надежно.\",\n }\n }\n }\n }\n\n const { t } = useI18n(text)\n</script>\n\n<style lang=\"scss\">\n\n\n</style>\n\n\n"],"names":["marketplace.state"],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
function buildMarketplaceTree(options = {}) {
|
|
2
|
+
const marketplaceComponent = options.marketplaceComponent || (() => import(
|
|
3
|
+
/* webpackChunkName: 'marketplace-page' */
|
|
4
|
+
"../components/pages/Marketplace.vue.js"
|
|
5
|
+
));
|
|
6
|
+
const buildName = (suffix) => {
|
|
7
|
+
const prefix = options.routeNamePrefix || "";
|
|
8
|
+
return suffix ? `${prefix}${suffix}` : prefix || void 0;
|
|
9
|
+
};
|
|
10
|
+
return [
|
|
11
|
+
{
|
|
12
|
+
path: ":country?/:state?/:city?",
|
|
13
|
+
name: buildName("Marketplace") || "Marketplace",
|
|
14
|
+
component: marketplaceComponent,
|
|
15
|
+
meta: {
|
|
16
|
+
title: {
|
|
17
|
+
en: "Marketplace",
|
|
18
|
+
ru: "Маркетплейс"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
];
|
|
23
|
+
}
|
|
24
|
+
function getRoutes(options = {}) {
|
|
25
|
+
const route = options.route || "Home";
|
|
26
|
+
const routes = [];
|
|
27
|
+
routes.push({
|
|
28
|
+
parentName: route,
|
|
29
|
+
config: {
|
|
30
|
+
basePath: options.basePath || "marketplace",
|
|
31
|
+
routes: buildMarketplaceTree(options)
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
return routes;
|
|
35
|
+
}
|
|
36
|
+
export {
|
|
37
|
+
getRoutes
|
|
38
|
+
};
|
|
39
|
+
//# sourceMappingURL=marketplace.router.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"marketplace.router.js","sources":["../../../../../../../src/modules/marketplace/views/router/marketplace.router.js"],"sourcesContent":["function buildMarketplaceTree(options = {}) {\n const marketplaceComponent = options.marketplaceComponent || (() => import(\n /* webpackChunkName: 'marketplace-page' */\n '../components/pages/Marketplace.vue'\n ));\n\n const buildName = (suffix) => {\n const prefix = options.routeNamePrefix || '';\n return suffix ? `${prefix}${suffix}` : prefix || undefined;\n };\n\n return [\n {\n path: ':country?/:state?/:city?',\n name: buildName('Marketplace') || 'Marketplace',\n component: marketplaceComponent,\n meta: {\n title: {\n en: 'Marketplace',\n ru: 'Маркетплейс',\n },\n },\n },\n ];\n}\n\nexport function getRoutes(options = {}) {\n const route = options.route || 'Home';\n const routes = [];\n\n routes.push({\n parentName: route,\n config: {\n basePath: options.basePath || 'marketplace',\n routes: buildMarketplaceTree(options),\n },\n });\n\n return routes;\n}\n\nexport default { getRoutes };\n"],"names":[],"mappings":"AAAA,SAAS,qBAAqB,UAAU,IAAI;AAC1C,QAAM,uBAAuB,QAAQ,yBAAyB,MAAM;AAAA;AAAA,IAElE;AAAA,EACJ;AAEE,QAAM,YAAY,CAAC,WAAW;AAC5B,UAAM,SAAS,QAAQ,mBAAmB;AAC1C,WAAO,SAAS,GAAG,MAAM,GAAG,MAAM,KAAK,UAAU;AAAA,EACnD;AAEA,SAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN,MAAM,UAAU,aAAa,KAAK;AAAA,MAClC,WAAW;AAAA,MACX,MAAM;AAAA,QACJ,OAAO;AAAA,UACL,IAAI;AAAA,UACJ,IAAI;AAAA,QACd;AAAA,MACA;AAAA,IACA;AAAA,EACA;AACA;AAEO,SAAS,UAAU,UAAU,IAAI;AACtC,QAAM,QAAQ,QAAQ,SAAS;AAC/B,QAAM,SAAS,CAAA;AAEf,SAAO,KAAK;AAAA,IACV,YAAY;AAAA,IACZ,QAAQ;AAAA,MACN,UAAU,QAAQ,YAAY;AAAA,MAC9B,QAAQ,qBAAqB,OAAO;AAAA,IAC1C;AAAA,EACA,CAAG;AAED,SAAO;AACT;"}
|