@ozdao/martyrs 0.2.511 → 0.2.513
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/{main-B1XN9Zjg.cjs → main-CVOBCkmD.cjs} +5 -5
- package/dist/{main-u7zgfMGL.js → main-CVRRj-vK.js} +259 -262
- package/dist/martyrs/src/components/Button/Button.vue2.cjs.map +1 -1
- package/dist/martyrs/src/components/Button/Button.vue2.js.map +1 -1
- package/dist/martyrs/src/components/Menu/{Menu.vue.cjs → Menu.vue2.cjs} +2 -2
- package/dist/martyrs/src/components/Menu/Menu.vue2.cjs.map +1 -0
- package/dist/martyrs/src/components/Menu/{Menu.vue.js → Menu.vue2.js} +2 -2
- package/dist/martyrs/src/components/Menu/Menu.vue2.js.map +1 -0
- package/dist/martyrs/src/components/Menu/MenuItem.vue.cjs +2 -2
- package/dist/martyrs/src/components/Menu/MenuItem.vue.cjs.map +1 -1
- package/dist/martyrs/src/components/Menu/MenuItem.vue.js +2 -2
- package/dist/martyrs/src/components/Menu/MenuItem.vue.js.map +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/Profile.vue.cjs +2 -2
- package/dist/martyrs/src/modules/auth/views/components/pages/Profile.vue.cjs.map +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/Profile.vue.js.map +1 -1
- package/dist/martyrs/src/modules/chats/components/sections/ChatWindow.vue.cjs +0 -2
- package/dist/martyrs/src/modules/chats/components/sections/ChatWindow.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/chats/components/sections/ChatWindow.vue.js +0 -2
- package/dist/martyrs/src/modules/chats/components/sections/ChatWindow.vue.js.map +1 -1
- package/dist/martyrs/src/modules/events/components/pages/EventsBackoffice.vue.cjs +3 -5
- package/dist/martyrs/src/modules/events/components/pages/EventsBackoffice.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/events/components/pages/EventsBackoffice.vue.js +3 -5
- package/dist/martyrs/src/modules/events/components/pages/EventsBackoffice.vue.js.map +1 -1
- package/dist/martyrs/src/modules/globals/globals.client.cjs +10 -1
- package/dist/martyrs/src/modules/globals/globals.client.cjs.map +1 -1
- package/dist/martyrs/src/modules/globals/globals.client.js +31 -22
- package/dist/martyrs/src/modules/globals/globals.client.js.map +1 -1
- package/dist/martyrs/src/modules/globals/views/components/layouts/Client.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/globals/views/components/layouts/Client.vue.js.map +1 -1
- package/dist/martyrs/src/modules/globals/views/components/sections/Filters.vue2.cjs +42 -46
- package/dist/martyrs/src/modules/globals/views/components/sections/Filters.vue2.cjs.map +1 -1
- package/dist/martyrs/src/modules/globals/views/components/sections/Filters.vue2.js +45 -49
- package/dist/martyrs/src/modules/globals/views/components/sections/Filters.vue2.js.map +1 -1
- package/dist/martyrs/src/modules/globals/views/components/sections/Walkthrough.vue.cjs +308 -0
- package/dist/martyrs/src/modules/globals/views/components/sections/Walkthrough.vue.cjs.map +1 -0
- package/dist/martyrs/src/modules/globals/views/components/sections/Walkthrough.vue.js +308 -0
- package/dist/martyrs/src/modules/globals/views/components/sections/Walkthrough.vue.js.map +1 -0
- package/dist/martyrs/src/modules/inventory/components/pages/Inventory.vue.cjs +14 -16
- package/dist/martyrs/src/modules/inventory/components/pages/Inventory.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/inventory/components/pages/Inventory.vue.js +13 -15
- package/dist/martyrs/src/modules/inventory/components/pages/Inventory.vue.js.map +1 -1
- package/dist/martyrs/src/modules/notifications/notifications.client.cjs +101 -32
- package/dist/martyrs/src/modules/notifications/notifications.client.cjs.map +1 -1
- package/dist/martyrs/src/modules/notifications/notifications.client.js +101 -32
- package/dist/martyrs/src/modules/notifications/notifications.client.js.map +1 -1
- package/dist/martyrs/src/modules/notifications/store/notifications.store.cjs +45 -12
- package/dist/martyrs/src/modules/notifications/store/notifications.store.cjs.map +1 -1
- package/dist/martyrs/src/modules/notifications/store/notifications.store.js +38 -5
- package/dist/martyrs/src/modules/notifications/store/notifications.store.js.map +1 -1
- package/dist/martyrs/src/modules/orders/components/blocks/CardOrderItem.vue.cjs +19 -18
- package/dist/martyrs/src/modules/orders/components/blocks/CardOrderItem.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/orders/components/blocks/CardOrderItem.vue.js +19 -18
- package/dist/martyrs/src/modules/orders/components/blocks/CardOrderItem.vue.js.map +1 -1
- package/dist/martyrs/src/modules/orders/components/forms/FormCustomerDetails.vue.cjs +82 -61
- package/dist/martyrs/src/modules/orders/components/forms/FormCustomerDetails.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/orders/components/forms/FormCustomerDetails.vue.js +83 -62
- package/dist/martyrs/src/modules/orders/components/forms/FormCustomerDetails.vue.js.map +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/OrderBackoffice.vue.cjs +3 -3
- package/dist/martyrs/src/modules/orders/components/pages/OrderBackoffice.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/OrderBackoffice.vue.js +3 -3
- package/dist/martyrs/src/modules/orders/components/pages/OrderBackoffice.vue.js.map +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/OrderCreate.vue.cjs +4 -2
- package/dist/martyrs/src/modules/orders/components/pages/OrderCreate.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/OrderCreate.vue.js +4 -2
- package/dist/martyrs/src/modules/orders/components/pages/OrderCreate.vue.js.map +1 -1
- package/dist/martyrs/src/modules/orders/components/sections/FormDelivery.vue.cjs +2 -2
- package/dist/martyrs/src/modules/orders/components/sections/FormDelivery.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/orders/components/sections/FormDelivery.vue.js +2 -2
- package/dist/martyrs/src/modules/orders/components/sections/FormDelivery.vue.js.map +1 -1
- package/dist/martyrs/src/modules/orders/orders.client.cjs +1 -0
- package/dist/martyrs/src/modules/orders/orders.client.cjs.map +1 -1
- package/dist/martyrs/src/modules/orders/orders.client.js +2 -0
- package/dist/martyrs/src/modules/orders/orders.client.js.map +1 -1
- package/dist/martyrs/src/modules/orders/store/shopcart.cjs +33 -23
- package/dist/martyrs/src/modules/orders/store/shopcart.cjs.map +1 -1
- package/dist/martyrs/src/modules/orders/store/shopcart.js +31 -21
- package/dist/martyrs/src/modules/orders/store/shopcart.js.map +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/Members.vue.cjs +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/Members.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/Organization.vue.cjs +3 -18
- package/dist/martyrs/src/modules/organizations/components/pages/Organization.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/Organization.vue.js +4 -19
- package/dist/martyrs/src/modules/organizations/components/pages/Organization.vue.js.map +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/OrganizationBackoffice.vue.cjs +1 -1
- package/dist/martyrs/src/modules/organizations/components/pages/OrganizationBackoffice.vue.js +1 -1
- package/dist/martyrs/src/modules/organizations/configs/navigation.organization.config.cjs +37 -43
- package/dist/martyrs/src/modules/organizations/configs/navigation.organization.config.cjs.map +1 -1
- package/dist/martyrs/src/modules/organizations/configs/navigation.organization.config.js +48 -54
- package/dist/martyrs/src/modules/organizations/configs/navigation.organization.config.js.map +1 -1
- package/dist/martyrs/src/modules/organizations/router/organizations.cjs +1 -1
- package/dist/martyrs/src/modules/organizations/router/organizations.js +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Products.vue.cjs +11 -8
- package/dist/martyrs/src/modules/products/components/pages/Products.vue.cjs.map +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Products.vue.js +11 -8
- package/dist/martyrs/src/modules/products/components/pages/Products.vue.js.map +1 -1
- package/dist/martyrs.cjs.js +1 -1
- package/dist/martyrs.css +1 -1
- package/dist/martyrs.es.js +1 -1
- package/dist/node_modules/.pnpm/capacitor-plugin-app-tracking-transparency@2.0.5_@capacitor_core@7.2.0/node_modules/capacitor-plugin-app-tracking-transparency/dist/esm/index.cjs +8 -0
- package/dist/node_modules/.pnpm/capacitor-plugin-app-tracking-transparency@2.0.5_@capacitor_core@7.2.0/node_modules/capacitor-plugin-app-tracking-transparency/dist/esm/index.cjs.map +1 -0
- package/dist/node_modules/.pnpm/capacitor-plugin-app-tracking-transparency@2.0.5_@capacitor_core@7.2.0/node_modules/capacitor-plugin-app-tracking-transparency/dist/esm/index.js +8 -0
- package/dist/node_modules/.pnpm/capacitor-plugin-app-tracking-transparency@2.0.5_@capacitor_core@7.2.0/node_modules/capacitor-plugin-app-tracking-transparency/dist/esm/index.js.map +1 -0
- package/dist/node_modules/.pnpm/capacitor-plugin-app-tracking-transparency@2.0.5_@capacitor_core@7.2.0/node_modules/capacitor-plugin-app-tracking-transparency/dist/esm/web.cjs +13 -0
- package/dist/node_modules/.pnpm/capacitor-plugin-app-tracking-transparency@2.0.5_@capacitor_core@7.2.0/node_modules/capacitor-plugin-app-tracking-transparency/dist/esm/web.cjs.map +1 -0
- package/dist/node_modules/.pnpm/capacitor-plugin-app-tracking-transparency@2.0.5_@capacitor_core@7.2.0/node_modules/capacitor-plugin-app-tracking-transparency/dist/esm/web.js +13 -0
- package/dist/node_modules/.pnpm/capacitor-plugin-app-tracking-transparency@2.0.5_@capacitor_core@7.2.0/node_modules/capacitor-plugin-app-tracking-transparency/dist/esm/web.js.map +1 -0
- package/dist/node_modules/.pnpm/embla-carousel-reactive-utils@8.6.0_embla-carousel@8.6.0/node_modules/embla-carousel-reactive-utils/esm/embla-carousel-reactive-utils.esm.cjs +43 -0
- package/dist/node_modules/.pnpm/embla-carousel-reactive-utils@8.6.0_embla-carousel@8.6.0/node_modules/embla-carousel-reactive-utils/esm/embla-carousel-reactive-utils.esm.cjs.map +1 -0
- package/dist/node_modules/.pnpm/embla-carousel-reactive-utils@8.6.0_embla-carousel@8.6.0/node_modules/embla-carousel-reactive-utils/esm/embla-carousel-reactive-utils.esm.js +43 -0
- package/dist/node_modules/.pnpm/embla-carousel-reactive-utils@8.6.0_embla-carousel@8.6.0/node_modules/embla-carousel-reactive-utils/esm/embla-carousel-reactive-utils.esm.js.map +1 -0
- package/dist/node_modules/.pnpm/embla-carousel-vue@8.6.0_vue@3.5.13_typescript@5.8.3_/node_modules/embla-carousel-vue/esm/embla-carousel-vue.esm.cjs +43 -0
- package/dist/node_modules/.pnpm/embla-carousel-vue@8.6.0_vue@3.5.13_typescript@5.8.3_/node_modules/embla-carousel-vue/esm/embla-carousel-vue.esm.cjs.map +1 -0
- package/dist/node_modules/.pnpm/embla-carousel-vue@8.6.0_vue@3.5.13_typescript@5.8.3_/node_modules/embla-carousel-vue/esm/embla-carousel-vue.esm.js +43 -0
- package/dist/node_modules/.pnpm/embla-carousel-vue@8.6.0_vue@3.5.13_typescript@5.8.3_/node_modules/embla-carousel-vue/esm/embla-carousel-vue.esm.js.map +1 -0
- package/dist/node_modules/.pnpm/embla-carousel@8.6.0/node_modules/embla-carousel/esm/embla-carousel.esm.cjs +1630 -0
- package/dist/node_modules/.pnpm/embla-carousel@8.6.0/node_modules/embla-carousel/esm/embla-carousel.esm.cjs.map +1 -0
- package/dist/node_modules/.pnpm/embla-carousel@8.6.0/node_modules/embla-carousel/esm/embla-carousel.esm.js +1630 -0
- package/dist/node_modules/.pnpm/embla-carousel@8.6.0/node_modules/embla-carousel/esm/embla-carousel.esm.js.map +1 -0
- package/dist/notifications.server.cjs +205 -11
- package/dist/notifications.server.js +205 -11
- package/dist/style.css +258 -242
- package/dist/{web--8-wgr6b.js → web-BW449LVt.js} +1 -1
- package/dist/{web-BS6utuAZ.cjs → web-CO3tWG6J.cjs} +1 -1
- package/package.json +1 -1
- package/src/components/Button/Button.vue +2 -2
- package/src/components/Menu/MenuItem.vue +11 -6
- package/src/modules/auth/views/components/pages/Profile.vue +1 -1
- package/src/modules/chats/components/sections/ChatWindow.vue +1 -1
- package/src/modules/events/components/pages/EventsBackoffice.vue +0 -1
- package/src/modules/globals/globals.client.js +17 -0
- package/src/modules/globals/views/components/layouts/Client.vue +1 -0
- package/src/modules/globals/views/components/sections/Filters.vue +2 -4
- package/src/modules/globals/views/components/sections/Walkthrough.vue +245 -57
- package/src/modules/inventory/components/pages/Inventory.vue +0 -1
- package/src/modules/notifications/FIXES.md +1 -0
- package/src/modules/notifications/controllers/notifications.controller.js +147 -7
- package/src/modules/notifications/models/user-device.model.js +10 -2
- package/src/modules/notifications/notifications.client.js +127 -41
- package/src/modules/notifications/routes/notifications.routes.js +4 -0
- package/src/modules/notifications/services/notification.service.js +93 -0
- package/src/modules/notifications/store/notifications.store.js +47 -7
- package/src/modules/orders/components/blocks/CardOrderItem.vue +1 -1
- package/src/modules/orders/components/forms/FormCustomerDetails.vue +52 -35
- package/src/modules/orders/components/pages/OrderBackoffice.vue +2 -2
- package/src/modules/orders/components/pages/OrderCreate.vue +3 -1
- package/src/modules/orders/components/sections/FormDelivery.vue +2 -2
- package/src/modules/orders/orders.client.js +2 -0
- package/src/modules/orders/store/shopcart.js +34 -23
- package/src/modules/organizations/components/pages/Organization.vue +6 -2
- package/src/modules/organizations/configs/navigation.organization.config.js +36 -36
- package/src/modules/products/components/pages/Products.vue +11 -9
- package/src/modules/products/migrations/categories-to-materialized-path.js +0 -3
- package/src/styles/base/backgrounds.scss +1 -0
- package/dist/martyrs/src/components/Menu/Menu.vue.cjs.map +0 -1
- package/dist/martyrs/src/components/Menu/Menu.vue.js.map +0 -1
|
@@ -35,10 +35,6 @@
|
|
|
35
35
|
>
|
|
36
36
|
<div class="flex-v-center flex-nowrap flex mn-b-medium">
|
|
37
37
|
<h3 class="flex-child-full">Filters</h3>
|
|
38
|
-
<IconCross
|
|
39
|
-
@click="showAllFilters = false"
|
|
40
|
-
class="i-regular cursor-pointer"
|
|
41
|
-
/>
|
|
42
38
|
</div>
|
|
43
39
|
|
|
44
40
|
<div class="filters-content">
|
|
@@ -168,12 +164,14 @@
|
|
|
168
164
|
v-model:field="tempSelected[filter.value].min"
|
|
169
165
|
:placeholder="filter.minPlaceholder || 'Min'"
|
|
170
166
|
type="number"
|
|
167
|
+
:label="returnCurrency()"
|
|
171
168
|
class="w-50 bg-light pd-small radius-small"
|
|
172
169
|
/>
|
|
173
170
|
<Field
|
|
174
171
|
v-model:field="tempSelected[filter.value].max"
|
|
175
172
|
:placeholder="filter.maxPlaceholder || 'Max'"
|
|
176
173
|
type="number"
|
|
174
|
+
:label="returnCurrency()"
|
|
177
175
|
class="w-50 bg-light pd-small radius-small"
|
|
178
176
|
/>
|
|
179
177
|
</div>
|
|
@@ -1,82 +1,210 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="pos-fixed
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
2
|
+
<div class="pos-fixed pos-t-0 pos-l-0 w-100 h-100vh z-index-6 bg-white flex embla" ref="emblaNode">
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
<div class="embla__container w-100 z-index-1">
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
<!-- SLIDE 1 -->
|
|
9
|
+
<!-- ------------------------------- -->
|
|
10
|
+
<div class="pos-relative flex-justify-center pd-thin t-center flex-column flex embla__slide">
|
|
11
|
+
<!-- <div class="pos-absolute w-100 h-100 z-index-0 pos-t-0 pos-r-0">
|
|
12
|
+
<div class="pos-absolute z-index-1 pos-t-0 pos-r-0 w-100 h-100 bg-black-grad"></div>
|
|
13
|
+
<img class="pos-absolute z-index-0 pos-t-0 pos-r-0 object-fit-cover h-100 w-100" src="/assets/walkthrough/1.png">
|
|
14
|
+
</div> -->
|
|
15
|
+
<div
|
|
16
|
+
class="flex flex-column flex-center pd-semi o-hidden pos-relative pos-b-0 z-index-1"
|
|
17
|
+
:style="{ opacity: tweenSlides.length ? tweenSlides[0] : undefined, transform: tweenSlides[0] ? `scale(${tweenSlides[0]})` : '' }"
|
|
18
|
+
>
|
|
19
|
+
<img
|
|
20
|
+
:src="'/logo/logo_square.svg'"
|
|
21
|
+
class="i-extra radius-medium mn-b-small"
|
|
22
|
+
>
|
|
23
|
+
|
|
24
|
+
<h3 class="h3 mn-b-medium">Welcome to 3SR</h3>
|
|
25
|
+
|
|
26
|
+
<p class="p-regular t-transp mn-b-big">
|
|
27
|
+
Access premium cameras, lenses, lighting, and audio gear through our app designed for filmmakers and content creators.
|
|
28
|
+
</p>
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
<button @click="nextSlide" class="bg-main p-big w-max button">
|
|
32
|
+
Get Started
|
|
33
|
+
</button>
|
|
34
|
+
</div>
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
<!-- SLIDE 2 -->
|
|
38
|
+
<!-- ------------------------------- -->
|
|
39
|
+
<div class="pos-relative flex-justify-center pd-thin t-center flex-column flex embla__slide">
|
|
40
|
+
<div class="flex flex-column flex-center pd-semi o-hidden pos-relative pos-b-0 z-index-1">
|
|
41
|
+
|
|
42
|
+
<div class="mn-b-small w-4r h-4r mn-auto pd-regular bg-main radius-regular t-white flex flex-center">
|
|
43
|
+
<IconBell/>
|
|
44
|
+
</div>
|
|
45
|
+
|
|
46
|
+
<h3 class="h3 mn-b-medium">Stay in the Loop</h3>
|
|
47
|
+
<p class="p-regular t-transp mn-b-big">
|
|
48
|
+
Get instant notifications about equipment availability, booking confirmations, and exclusive deals from our rental platform.
|
|
49
|
+
</p>
|
|
50
|
+
|
|
51
|
+
<div class="flex flex-column flex-center gap-small">
|
|
52
|
+
<button @click="requestNotificationPermission" class="bg-main p-big w-max button">
|
|
53
|
+
Enable Notifications
|
|
54
|
+
</button>
|
|
55
|
+
<button @click="nextSlide" class="bg-light p-big w-max button">
|
|
56
|
+
Maybe Later
|
|
57
|
+
</button>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
</div>
|
|
61
|
+
|
|
62
|
+
<!-- SLIDE 3 -->
|
|
63
|
+
<!-- ------------------------------- -->
|
|
64
|
+
<div class="pos-relative flex-justify-center pd-thin t-center flex-column flex embla__slide">
|
|
65
|
+
<div class="flex flex-column flex-center pd-semi o-hidden pos-relative pos-b-0 z-index-1">
|
|
66
|
+
|
|
67
|
+
<div class="mn-b-small w-4r h-4r mn-auto pd-regular bg-main radius-regular t-white flex flex-center">
|
|
68
|
+
<IconAddress/>
|
|
69
|
+
</div>
|
|
70
|
+
|
|
71
|
+
<h3 class="h3 mn-b-medium">Find Nearby Equipment</h3>
|
|
72
|
+
<p class="p-regular t-transp mn-b-big">
|
|
73
|
+
Discover rental locations and equipment availability near you. We'll show you the closest pickup points and delivery options.
|
|
74
|
+
</p>
|
|
75
|
+
|
|
76
|
+
<div class="flex flex-column flex-center gap-small">
|
|
77
|
+
<button @click="requestLocationPermission" class="bg-main p-big w-max button">
|
|
78
|
+
Enable Location
|
|
79
|
+
</button>
|
|
80
|
+
<button @click="nextSlide" class="bg-light p-big w-max button">
|
|
81
|
+
Skip for Now
|
|
82
|
+
</button>
|
|
83
|
+
</div>
|
|
84
|
+
</div>
|
|
13
85
|
</div>
|
|
14
86
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
>
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
87
|
+
<!-- SLIDE 4 - App Tracking Transparency -->
|
|
88
|
+
<!-- ------------------------------- -->
|
|
89
|
+
<div class="pos-relative flex-justify-center pd-thin t-center flex-column flex embla__slide">
|
|
90
|
+
<div class="flex flex-column flex-center pd-semi o-hidden pos-relative pos-b-0 z-index-1">
|
|
91
|
+
<div class="mn-b-small w-4r h-4r mn-auto pd-regular bg-main radius-regular t-white flex flex-center">
|
|
92
|
+
<IconShield/>
|
|
93
|
+
</div>
|
|
94
|
+
|
|
95
|
+
<h3 class="h3 mn-b-medium">Personalized Experience</h3>
|
|
96
|
+
<p class="p-regular t-transp mn-b-big">
|
|
97
|
+
Allow us to provide you with personalized recommendations and improve your app experience based on your preferences.
|
|
98
|
+
</p>
|
|
27
99
|
|
|
28
|
-
|
|
29
|
-
|
|
100
|
+
<div class="flex flex-column flex-center gap-small">
|
|
101
|
+
<button @click="requestTrackingPermission" class="bg-main p-big w-max button">
|
|
102
|
+
Allow Tracking
|
|
103
|
+
</button>
|
|
104
|
+
<button @click="nextSlide" class="bg-light p-big w-max button">
|
|
105
|
+
Ask App Not to Track
|
|
106
|
+
</button>
|
|
107
|
+
</div>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
|
|
111
|
+
<!-- SLIDE 5 - Final -->
|
|
112
|
+
<!-- ------------------------------- -->
|
|
113
|
+
<div class="pos-relative flex-justify-center pd-thin t-center flex-column flex embla__slide">
|
|
114
|
+
<div class="flex flex-column flex-center pd-semi o-hidden pos-relative pos-b-0 z-index-1">
|
|
115
|
+
<img loading="lazy"
|
|
116
|
+
:src="'/logo/logo_square.svg'"
|
|
117
|
+
class="i-extra radius-medium mn-b-small"
|
|
118
|
+
>
|
|
119
|
+
<h3 class="h3 mn-b-medium">Ready to Rent?</h3>
|
|
120
|
+
<p class="p-regular t-transp mn-b-big">Join thousands of creators who trust 3SR for their professional video equipment needs. Choose how you'd like to get started.</p>
|
|
121
|
+
|
|
122
|
+
<button @click="openFirstRoute('Sign Up')" class="bg-main p-big w-100 button mn-b-thin">Create Account</button>
|
|
123
|
+
<button @click="openFirstRoute('Sign In')" class="bg-light t-black p-big w-100 button mn-b-semi">Sign In</button>
|
|
124
|
+
|
|
125
|
+
<p class="p-small mn-b-medium t-transp">Or explore as a guest:</p>
|
|
126
|
+
<button @click="setFirstUseFalse()" class="bg-light p-big w-max button">Continue as Guest</button>
|
|
127
|
+
</div>
|
|
30
128
|
</div>
|
|
31
129
|
|
|
32
130
|
</div>
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
131
|
+
|
|
132
|
+
<div class="
|
|
133
|
+
embla__dots
|
|
134
|
+
z-index-5
|
|
135
|
+
h-4r
|
|
136
|
+
pos-absolute
|
|
137
|
+
pos-t-1r
|
|
138
|
+
flex-nowrap
|
|
139
|
+
flex
|
|
140
|
+
flex-center
|
|
141
|
+
gap-thin
|
|
142
|
+
w-100"
|
|
143
|
+
>
|
|
144
|
+
<button
|
|
45
145
|
v-for="(snap, index) in scrollSnaps"
|
|
46
146
|
:key="index"
|
|
47
147
|
@click="scrollTo(index)"
|
|
48
148
|
:class="[
|
|
49
|
-
'embla__dot i-small radius-extra
|
|
149
|
+
'embla__dot bg- i-small radius-extra',
|
|
50
150
|
{ 'bg-light': index !== selectedIndex },
|
|
51
151
|
{ 'bg-main': index === selectedIndex }
|
|
52
152
|
]"
|
|
53
153
|
>
|
|
54
|
-
</
|
|
154
|
+
</button>
|
|
55
155
|
|
|
56
|
-
<
|
|
57
|
-
|
|
58
|
-
|
|
156
|
+
<button
|
|
157
|
+
@click.native="setFirstUseFalse()"
|
|
158
|
+
class="
|
|
159
|
+
pd-small
|
|
160
|
+
bg-white
|
|
161
|
+
t-black
|
|
162
|
+
w-6r
|
|
163
|
+
pos-b-0r
|
|
164
|
+
flex-nowrap
|
|
165
|
+
flex
|
|
166
|
+
flex-center
|
|
167
|
+
pos-r-1r
|
|
168
|
+
pos-relative
|
|
169
|
+
radius-small
|
|
170
|
+
uppercase
|
|
171
|
+
pos-absolute
|
|
172
|
+
">
|
|
173
|
+
<span>Skip</span>
|
|
174
|
+
</button>
|
|
59
175
|
</div>
|
|
60
176
|
</div>
|
|
61
177
|
|
|
62
178
|
</template>
|
|
63
179
|
|
|
64
180
|
<script setup>
|
|
65
|
-
import { ref, onMounted } from 'vue';
|
|
181
|
+
import { ref, onMounted, reactive, inject } from 'vue';
|
|
66
182
|
import { useRoute, useRouter } from 'vue-router'
|
|
67
183
|
|
|
68
|
-
import emblaCarouselVue from 'embla-carousel-vue';
|
|
184
|
+
import emblaCarouselVue from 'embla-carousel-vue';
|
|
185
|
+
|
|
186
|
+
import IconBell from '@martyrs/src/modules/icons/entities/IconBell.vue';
|
|
187
|
+
import IconAddress from '@martyrs/src/modules/icons/entities/IconAddress.vue';
|
|
188
|
+
import IconShield from '@martyrs/src/modules/icons/entities/IconAddress.vue';
|
|
69
189
|
|
|
70
|
-
|
|
71
|
-
// import ColorsBackground from '@/components/icons/backgrounds/ColorsBackground.vue'
|
|
190
|
+
import { AppTrackingTransparency } from 'capacitor-plugin-app-tracking-transparency';
|
|
72
191
|
|
|
73
192
|
const props = defineProps(['slides', 'options']);
|
|
74
193
|
const emits = defineEmits(['updateFirstUse'])
|
|
75
194
|
const router = useRouter()
|
|
195
|
+
|
|
196
|
+
// Get notification manager directly
|
|
197
|
+
import ModuleNotifications from '@martyrs/src/modules/notifications/notifications.client.js'
|
|
76
198
|
|
|
77
199
|
// Set firstUse
|
|
78
200
|
import { Preferences } from '@capacitor/preferences';
|
|
79
201
|
|
|
202
|
+
const permissions = reactive({
|
|
203
|
+
notifications: false,
|
|
204
|
+
location: false,
|
|
205
|
+
tracking: false
|
|
206
|
+
})
|
|
207
|
+
|
|
80
208
|
async function setFirstUseFalse() {
|
|
81
209
|
await Preferences.set({
|
|
82
210
|
key: 'first-use',
|
|
@@ -96,17 +224,6 @@
|
|
|
96
224
|
|
|
97
225
|
emits('updateFirstUse', false);
|
|
98
226
|
}
|
|
99
|
-
// Set Slider
|
|
100
|
-
let walkthrough = [{
|
|
101
|
-
title: 'Communicate',
|
|
102
|
-
subtitle: 'Write posts, comments and put likes.'
|
|
103
|
-
},{
|
|
104
|
-
title: 'Party & Fun',
|
|
105
|
-
subtitle: 'Check the calendar for new events.'
|
|
106
|
-
},{
|
|
107
|
-
title: 'Discover',
|
|
108
|
-
subtitle: 'Browse the gallery of photos.'
|
|
109
|
-
}]
|
|
110
227
|
|
|
111
228
|
const [emblaNode, emblaApi] = emblaCarouselVue({ loop: false })
|
|
112
229
|
|
|
@@ -118,6 +235,12 @@
|
|
|
118
235
|
|
|
119
236
|
const scrollTo = (index) => emblaApi.value && emblaApi.value.scrollTo(index);
|
|
120
237
|
|
|
238
|
+
const nextSlide = () => {
|
|
239
|
+
if (emblaApi.value) {
|
|
240
|
+
emblaApi.value.scrollNext();
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
|
|
121
244
|
const onInit = (embla) => {
|
|
122
245
|
scrollSnaps.value = emblaApi.value.scrollSnapList();
|
|
123
246
|
};
|
|
@@ -179,6 +302,71 @@
|
|
|
179
302
|
emblaApi.value.on('select', onSelect);
|
|
180
303
|
emblaApi.value.on('scroll', onScroll)
|
|
181
304
|
});
|
|
305
|
+
|
|
306
|
+
const requestNotificationPermission = async () => {
|
|
307
|
+
try {
|
|
308
|
+
// Use notification manager from global store if available
|
|
309
|
+
const notificationManager = window.$store?.notificationManager;
|
|
310
|
+
|
|
311
|
+
if (notificationManager) {
|
|
312
|
+
await notificationManager.pushHandler.requestPermissions();
|
|
313
|
+
await notificationManager.registerWebPush(window.$store);
|
|
314
|
+
permissions.notifications = true;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
setTimeout(() => {
|
|
318
|
+
nextSlide()
|
|
319
|
+
}, 1000)
|
|
320
|
+
} catch (error) {
|
|
321
|
+
console.error('Notification permission error:', error)
|
|
322
|
+
nextSlide()
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const requestLocationPermission = async () => {
|
|
327
|
+
try {
|
|
328
|
+
if (!('geolocation' in navigator)) {
|
|
329
|
+
nextSlide()
|
|
330
|
+
return
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
navigator.geolocation.getCurrentPosition(
|
|
334
|
+
() => {
|
|
335
|
+
permissions.location = true
|
|
336
|
+
setTimeout(() => {
|
|
337
|
+
nextSlide()
|
|
338
|
+
}, 1000)
|
|
339
|
+
},
|
|
340
|
+
() => {
|
|
341
|
+
setTimeout(() => {
|
|
342
|
+
nextSlide()
|
|
343
|
+
}, 1000)
|
|
344
|
+
},
|
|
345
|
+
{ timeout: 8000 }
|
|
346
|
+
)
|
|
347
|
+
} catch (error) {
|
|
348
|
+
console.error('Location permission error:', error)
|
|
349
|
+
nextSlide()
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
const requestTrackingPermission = async () => {
|
|
354
|
+
try {
|
|
355
|
+
const { status } = await AppTrackingTransparency.requestPermission();
|
|
356
|
+
|
|
357
|
+
if (status === 'authorized') {
|
|
358
|
+
permissions.tracking = true;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
setTimeout(() => {
|
|
362
|
+
nextSlide();
|
|
363
|
+
}, 1000);
|
|
364
|
+
} catch (error) {
|
|
365
|
+
console.error('Tracking permission error:', error);
|
|
366
|
+
nextSlide();
|
|
367
|
+
}
|
|
368
|
+
};
|
|
369
|
+
|
|
182
370
|
</script>
|
|
183
371
|
|
|
184
372
|
<style lang="scss">
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
0. Нужно перерегистрировать девайс после аутентификации для связи с пользователем
|
|
1
2
|
1. У globals.ws нотификаций нет реактиновного состояния или инструментов крове listeners для получения текущего состояния сокетов. Если это синглтон в него надо добавить методы для получения такой информации.
|
|
2
3
|
2. Тоже самое касается NotificationManager - у него нет реактивного состояния и вообще хуй знает что он делает
|
|
3
4
|
3. Нету ABAC для нотификаций и мидлваров вообще никаких. Методы для отправки нотификаций вообще не нужно делать доступными по апи без сервисного ключа.
|
|
@@ -126,20 +126,56 @@ const NotificationsController = (db, wss, notificationService) => {
|
|
|
126
126
|
// Register device for push notifications
|
|
127
127
|
const registerDevice = async (req, res) => {
|
|
128
128
|
try {
|
|
129
|
-
const { userId, deviceId, deviceType, deviceToken } = req.body;
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
{
|
|
129
|
+
const { userId, anonymousId, deviceId, deviceType, deviceToken } = req.body;
|
|
130
|
+
|
|
131
|
+
// Validate that either userId or anonymousId is provided
|
|
132
|
+
if (!userId && !anonymousId) {
|
|
133
|
+
return res.status(400).json({ message: 'Either userId or anonymousId is required' });
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const isAnonymous = !userId;
|
|
137
|
+
let query, updateData;
|
|
138
|
+
|
|
139
|
+
if (isAnonymous) {
|
|
140
|
+
// For anonymous users
|
|
141
|
+
query = { anonymousId, deviceId };
|
|
142
|
+
updateData = {
|
|
143
|
+
anonymousId,
|
|
144
|
+
deviceId,
|
|
145
|
+
deviceType,
|
|
146
|
+
deviceToken,
|
|
147
|
+
isActive: true,
|
|
148
|
+
isAnonymous: true,
|
|
149
|
+
lastActive: Date.now(),
|
|
150
|
+
};
|
|
151
|
+
} else {
|
|
152
|
+
// For registered users - first delete any anonymous device with same deviceId/token
|
|
153
|
+
await db.userDevice.deleteMany({
|
|
154
|
+
$or: [
|
|
155
|
+
{ deviceId, isAnonymous: true },
|
|
156
|
+
{ deviceToken, isAnonymous: true }
|
|
157
|
+
]
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
query = { userId, deviceId };
|
|
161
|
+
updateData = {
|
|
134
162
|
userId,
|
|
135
163
|
deviceId,
|
|
136
164
|
deviceType,
|
|
137
165
|
deviceToken,
|
|
138
166
|
isActive: true,
|
|
167
|
+
isAnonymous: false,
|
|
139
168
|
lastActive: Date.now(),
|
|
140
|
-
}
|
|
141
|
-
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// Upsert device registration
|
|
173
|
+
const device = await db.userDevice.findOneAndUpdate(
|
|
174
|
+
query,
|
|
175
|
+
{ $set: updateData },
|
|
176
|
+
{ upsert: true, new: true, setDefaultsOnInsert: true }
|
|
142
177
|
);
|
|
178
|
+
|
|
143
179
|
return res.status(201).json(device);
|
|
144
180
|
} catch (err) {
|
|
145
181
|
return res.status(500).json({ message: err.message });
|
|
@@ -184,6 +220,108 @@ const NotificationsController = (db, wss, notificationService) => {
|
|
|
184
220
|
}
|
|
185
221
|
};
|
|
186
222
|
|
|
223
|
+
// Send notification to specific device tokens
|
|
224
|
+
const sendToTokens = async (req, res) => {
|
|
225
|
+
try {
|
|
226
|
+
const { tokens, title, body, data = {} } = req.body;
|
|
227
|
+
|
|
228
|
+
if (!tokens || !Array.isArray(tokens) || tokens.length === 0) {
|
|
229
|
+
return res.status(400).json({ message: 'tokens array is required' });
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (!title || !body) {
|
|
233
|
+
return res.status(400).json({ message: 'title and body are required' });
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Find devices by tokens
|
|
237
|
+
const devices = await db.userDevice.find({
|
|
238
|
+
deviceToken: { $in: tokens },
|
|
239
|
+
isActive: true
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
const results = [];
|
|
243
|
+
|
|
244
|
+
// Send to each device
|
|
245
|
+
for (const device of devices) {
|
|
246
|
+
try {
|
|
247
|
+
await notificationService.sendToDeviceToken({
|
|
248
|
+
deviceToken: device.deviceToken,
|
|
249
|
+
deviceType: device.deviceType,
|
|
250
|
+
title,
|
|
251
|
+
body,
|
|
252
|
+
data
|
|
253
|
+
});
|
|
254
|
+
results.push({ token: device.deviceToken, success: true });
|
|
255
|
+
} catch (error) {
|
|
256
|
+
results.push({ token: device.deviceToken, success: false, error: error.message });
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
return res.json({
|
|
261
|
+
message: 'Notifications sent',
|
|
262
|
+
results,
|
|
263
|
+
total: tokens.length,
|
|
264
|
+
found: devices.length
|
|
265
|
+
});
|
|
266
|
+
} catch (err) {
|
|
267
|
+
return res.status(500).json({ message: err.message });
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
|
|
271
|
+
// Send notification to anonymous devices
|
|
272
|
+
const sendToAnonymous = async (req, res) => {
|
|
273
|
+
try {
|
|
274
|
+
const { anonymousIds, title, body, data = {} } = req.body;
|
|
275
|
+
|
|
276
|
+
if (!title || !body) {
|
|
277
|
+
return res.status(400).json({ message: 'title and body are required' });
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
let devices;
|
|
281
|
+
|
|
282
|
+
if (anonymousIds && Array.isArray(anonymousIds)) {
|
|
283
|
+
// Send to specific anonymous IDs
|
|
284
|
+
devices = await db.userDevice.find({
|
|
285
|
+
anonymousId: { $in: anonymousIds },
|
|
286
|
+
isAnonymous: true,
|
|
287
|
+
isActive: true
|
|
288
|
+
});
|
|
289
|
+
} else {
|
|
290
|
+
// Send to all anonymous devices
|
|
291
|
+
devices = await db.userDevice.find({
|
|
292
|
+
isAnonymous: true,
|
|
293
|
+
isActive: true
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const results = [];
|
|
298
|
+
|
|
299
|
+
// Send to each device
|
|
300
|
+
for (const device of devices) {
|
|
301
|
+
try {
|
|
302
|
+
await notificationService.sendToDeviceToken({
|
|
303
|
+
deviceToken: device.deviceToken,
|
|
304
|
+
deviceType: device.deviceType,
|
|
305
|
+
title,
|
|
306
|
+
body,
|
|
307
|
+
data
|
|
308
|
+
});
|
|
309
|
+
results.push({ anonymousId: device.anonymousId, deviceToken: device.deviceToken, success: true });
|
|
310
|
+
} catch (error) {
|
|
311
|
+
results.push({ anonymousId: device.anonymousId, deviceToken: device.deviceToken, success: false, error: error.message });
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
return res.json({
|
|
316
|
+
message: 'Notifications sent to anonymous devices',
|
|
317
|
+
results,
|
|
318
|
+
devicesFound: devices.length
|
|
319
|
+
});
|
|
320
|
+
} catch (err) {
|
|
321
|
+
return res.status(500).json({ message: err.message });
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
|
|
187
325
|
return {
|
|
188
326
|
create,
|
|
189
327
|
createBatch,
|
|
@@ -193,6 +331,8 @@ const NotificationsController = (db, wss, notificationService) => {
|
|
|
193
331
|
updatePreferences,
|
|
194
332
|
getUserPreferences,
|
|
195
333
|
markAllAsRead,
|
|
334
|
+
sendToTokens,
|
|
335
|
+
sendToAnonymous,
|
|
196
336
|
};
|
|
197
337
|
};
|
|
198
338
|
export default NotificationsController;
|
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
export default (db, additionalFields = {}) => {
|
|
2
2
|
const schema = new db.mongoose.Schema({
|
|
3
|
-
userId: { type: db.mongoose.Schema.Types.ObjectId, ref: 'User', required:
|
|
3
|
+
userId: { type: db.mongoose.Schema.Types.ObjectId, ref: 'User', required: false },
|
|
4
|
+
anonymousId: { type: String, required: false }, // For anonymous users
|
|
4
5
|
deviceId: { type: String, required: true },
|
|
5
6
|
deviceType: { type: String, enum: ['ios', 'android', 'web'], required: true },
|
|
6
7
|
deviceToken: { type: String, required: true }, // Push token for mobile, or web token
|
|
7
8
|
isActive: { type: Boolean, default: true },
|
|
8
9
|
lastActive: { type: Date, default: Date.now },
|
|
10
|
+
isAnonymous: { type: Boolean, default: false }, // Flag to identify anonymous devices
|
|
9
11
|
});
|
|
10
|
-
|
|
12
|
+
|
|
13
|
+
// Compound indexes for both registered and anonymous users
|
|
14
|
+
schema.index({ userId: 1, deviceId: 1 }, { unique: true, sparse: true });
|
|
15
|
+
schema.index({ anonymousId: 1, deviceId: 1 }, { unique: true, sparse: true });
|
|
16
|
+
schema.index({ deviceToken: 1 }, { unique: true });
|
|
17
|
+
schema.index({ isAnonymous: 1, isActive: 1 });
|
|
18
|
+
|
|
11
19
|
return db.mongoose.model('UserDevice', schema);
|
|
12
20
|
};
|