@ozdao/martyrs 0.2.581 → 0.2.583
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/martyrs/src/components/Feed/Feed.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/Profile.vue.js +6 -12
- package/dist/martyrs/src/modules/auth/views/components/pages/Profile.vue.js.map +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/ProfileEdit.vue.js +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/ProfileEdit.vue.js.map +1 -1
- package/dist/martyrs/src/modules/auth/views/components/pages/UserDashboard.vue.js +182 -89
- package/dist/martyrs/src/modules/auth/views/components/pages/UserDashboard.vue.js.map +1 -1
- package/dist/martyrs/src/modules/auth/views/configs/navigation.user.config.js +11 -5
- package/dist/martyrs/src/modules/auth/views/configs/navigation.user.config.js.map +1 -1
- package/dist/martyrs/src/modules/auth/views/router/users.router.js +1 -2
- package/dist/martyrs/src/modules/auth/views/router/users.router.js.map +1 -1
- package/dist/martyrs/src/modules/backoffice/components/partials/Sidebar.vue.js +1 -1
- package/dist/martyrs/src/modules/core/views/classes/ws.manager.js +16 -1
- package/dist/martyrs/src/modules/core/views/classes/ws.manager.js.map +1 -1
- package/dist/martyrs/src/modules/core/views/components/sections/{Filters.vue.js → Filters.vue2.js} +2 -2
- package/dist/martyrs/src/modules/core/views/components/sections/Filters.vue2.js.map +1 -0
- package/dist/martyrs/src/modules/core/views/utils/vue-app-renderer.js +7 -0
- package/dist/martyrs/src/modules/core/views/utils/vue-app-renderer.js.map +1 -1
- package/dist/martyrs/src/modules/events/components/pages/EditEvent.vue.js +1 -1
- package/dist/martyrs/src/modules/events/components/pages/Event.vue.js +1 -1
- package/dist/martyrs/src/modules/gallery/components/sections/BackofficeGallery.vue.js +1 -1
- package/dist/martyrs/src/modules/marketplace/views/components/pages/Marketplace.vue.js +1 -1
- package/dist/martyrs/src/modules/notifications/components/elements/NotificationBadge.vue.js +3 -3
- package/dist/martyrs/src/modules/notifications/components/elements/NotificationBadge.vue.js.map +1 -1
- package/dist/martyrs/src/modules/notifications/components/layouts/NotificationsLayout.vue.js +11 -40
- package/dist/martyrs/src/modules/notifications/components/layouts/NotificationsLayout.vue.js.map +1 -1
- package/dist/martyrs/src/modules/notifications/components/pages/Notifications.vue.js +26 -21
- package/dist/martyrs/src/modules/notifications/components/pages/Notifications.vue.js.map +1 -1
- package/dist/martyrs/src/modules/notifications/components/sections/NotificationPreferences.vue.js +54 -48
- package/dist/martyrs/src/modules/notifications/components/sections/NotificationPreferences.vue.js.map +1 -1
- package/dist/martyrs/src/modules/notifications/components/sections/NotificationsList.vue.js +37 -117
- package/dist/martyrs/src/modules/notifications/components/sections/NotificationsList.vue.js.map +1 -1
- package/dist/martyrs/src/modules/notifications/notifications.client.js +18 -15
- package/dist/martyrs/src/modules/notifications/notifications.client.js.map +1 -1
- package/dist/martyrs/src/modules/orders/components/blocks/CardOrderUser.vue.js +90 -175
- package/dist/martyrs/src/modules/orders/components/blocks/CardOrderUser.vue.js.map +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/OrderBackoffice.vue.js +6 -6
- package/dist/martyrs/src/modules/orders/components/pages/OrderBackoffice.vue.js.map +1 -1
- package/dist/martyrs/src/modules/orders/components/pages/Orders.vue.js +41 -28
- package/dist/martyrs/src/modules/orders/components/pages/Orders.vue.js.map +1 -1
- package/dist/martyrs/src/modules/orders/components/sections/FormDelivery.vue.js +1 -1
- package/dist/martyrs/src/modules/orders/orders.client.js +14 -14
- package/dist/martyrs/src/modules/orders/orders.client.js.map +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 +88 -39
- package/dist/martyrs/src/modules/organizations/components/pages/OrganizationEdit.vue.js.map +1 -1
- package/dist/martyrs/src/modules/products/components/pages/CategoryEdit.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/pages/ProductEdit.vue.js +1 -1
- package/dist/martyrs/src/modules/products/components/pages/Products.vue.js +1 -1
- package/dist/style.css +73 -265
- package/package.json +1 -1
- package/src/modules/TASKS.MD +26 -1
- package/src/modules/auth/views/components/pages/Profile.vue +9 -15
- package/src/modules/auth/views/components/pages/ProfileEdit.vue +1 -1
- package/src/modules/auth/views/components/pages/UserDashboard.vue +214 -125
- package/src/modules/auth/views/configs/navigation.user.config.js +17 -11
- package/src/modules/auth/views/router/users.router.js +0 -1
- package/src/modules/core/views/classes/ws.manager.js +20 -1
- package/src/modules/core/views/utils/vue-app-renderer.js +9 -3
- package/src/modules/notifications/components/elements/NotificationBadge.vue +1 -1
- package/src/modules/notifications/components/layouts/NotificationsLayout.vue +9 -53
- package/src/modules/notifications/components/pages/Notifications.vue +21 -22
- package/src/modules/notifications/components/sections/NotificationPreferences.vue +41 -180
- package/src/modules/notifications/components/sections/NotificationsList.vue +39 -219
- package/src/modules/notifications/notifications.client.js +17 -16
- package/src/modules/orders/components/blocks/CardOrderUser.vue +88 -190
- package/src/modules/orders/components/pages/OrderBackoffice.vue +5 -5
- package/src/modules/orders/components/pages/Orders.vue +56 -50
- package/src/modules/organizations/components/pages/OrganizationEdit.vue +42 -11
- package/dist/martyrs/src/components/SelectMulti/SelectMulti.vue.js +0 -625
- package/dist/martyrs/src/components/SelectMulti/SelectMulti.vue.js.map +0 -1
- package/dist/martyrs/src/modules/auth/views/components/blocks/ProfileCard.vue.js +0 -44
- package/dist/martyrs/src/modules/auth/views/components/blocks/ProfileCard.vue.js.map +0 -1
- package/dist/martyrs/src/modules/core/views/components/sections/Filters.vue.js.map +0 -1
- package/dist/martyrs/src/modules/orders/components/icons/IconStatusCanceled.vue.js +0 -32
- package/dist/martyrs/src/modules/orders/components/icons/IconStatusCanceled.vue.js.map +0 -1
- package/dist/martyrs/src/modules/orders/components/icons/IconStatusConfirmed.vue.js +0 -32
- package/dist/martyrs/src/modules/orders/components/icons/IconStatusConfirmed.vue.js.map +0 -1
- package/dist/martyrs/src/modules/orders/components/icons/IconStatusCreated.vue.js +0 -32
- package/dist/martyrs/src/modules/orders/components/icons/IconStatusCreated.vue.js.map +0 -1
- package/dist/martyrs/src/modules/orders/components/icons/IconStatusDelay.vue.js +0 -32
- package/dist/martyrs/src/modules/orders/components/icons/IconStatusDelay.vue.js.map +0 -1
- package/dist/martyrs/src/modules/orders/components/icons/IconStatusFinished.vue.js +0 -32
- package/dist/martyrs/src/modules/orders/components/icons/IconStatusFinished.vue.js.map +0 -1
- package/dist/martyrs/src/modules/orders/components/icons/IconStatusInUse.vue.js +0 -32
- package/dist/martyrs/src/modules/orders/components/icons/IconStatusInUse.vue.js.map +0 -1
|
@@ -1,107 +1,82 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
<template v-if="positions.length > 0">
|
|
12
|
-
<div
|
|
13
|
-
v-for="index in 4"
|
|
14
|
-
:key="index"
|
|
15
|
-
style="min-height: 0"
|
|
16
|
-
class="w-100 h-100 bg-white-transp-50 radius-thin"
|
|
17
|
-
:class="{
|
|
18
|
-
'bg-white-transp-50': index <= positions.length && index <= 3,
|
|
19
|
-
'bg-white-transp-50': index > positions.length || (index === 4 && positions.length <= 3),
|
|
20
|
-
'bg-main': index === 4 && positions.length > 3
|
|
21
|
-
}"
|
|
22
|
-
>
|
|
23
|
-
<img
|
|
24
|
-
v-if="index > 0 && index <= positions.length && positions[index - 1]?.images?.[0]"
|
|
25
|
-
:src="`${FILE_SERVER_URL || ''}${positions[index - 1].images[0] || positions[index - 1].image}`"
|
|
26
|
-
class="radius-small object-fit-contain w-100 h-100"
|
|
27
|
-
:alt="positions[index - 1].name"
|
|
28
|
-
>
|
|
29
|
-
<div v-else-if="index === 4 && positions.length > 3" class="flex-center h-100">
|
|
30
|
-
<span class="fw-medium t-white">+{{ positions.length - 3 }}</span>
|
|
31
|
-
</div>
|
|
32
|
-
</div>
|
|
33
|
-
</template>
|
|
34
|
-
</div>
|
|
35
|
-
|
|
36
|
-
<!-- Правая часть - контент -->
|
|
37
|
-
<div class="flex-column flex w-100">
|
|
38
|
-
<!-- ID заказа и цена -->
|
|
39
|
-
<div class="mn-b-thin">
|
|
40
|
-
<Tooltip :text="orderId">
|
|
41
|
-
<p class="p-medium">
|
|
42
|
-
#{{ orderId.slice(0, 4) }}...{{ orderId.slice(-4) }}
|
|
43
|
-
</p>
|
|
44
|
-
</Tooltip>
|
|
45
|
-
<p class="t-transp">{{ positions.length }} items for {{ formatPrice(total) }}</p>
|
|
46
|
-
</div>
|
|
2
|
+
<div class="bg-light radius-medium pd-medium">
|
|
3
|
+
|
|
4
|
+
<!-- Header: Order ID | Date | Status -->
|
|
5
|
+
<div class="flex-nowrap flex-v-center flex-between flex mn-b-small">
|
|
6
|
+
<div class="flex-v-center gap-small flex">
|
|
7
|
+
<span class="fw-medium t-dark">{{ formatOrderId(orderId) }}</span>
|
|
8
|
+
<span class="t-transp">|</span>
|
|
9
|
+
<span class="t-transp">{{ formatDate(createdAt, { dayMonth: true, language: locale }) }}</span>
|
|
10
|
+
</div>
|
|
47
11
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
12
|
+
<!-- Status Badge -->
|
|
13
|
+
<div
|
|
14
|
+
class="pd-l-small pd-r-small pd-t-micro pd-b-micro radius-big p-small fw-semi flex-v-center gap-micro flex"
|
|
15
|
+
:class="statusClasses"
|
|
16
|
+
>
|
|
17
|
+
<span class="d-block radius-big" :class="dotClasses" style="width: 6px; height: 6px;"></span>
|
|
18
|
+
{{ statusLabel }}
|
|
53
19
|
</div>
|
|
54
20
|
</div>
|
|
55
21
|
|
|
56
|
-
<!--
|
|
57
|
-
<div
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
22
|
+
<!-- Product List -->
|
|
23
|
+
<div class="gap-thin flex-column flex mn-b-small">
|
|
24
|
+
<CardOrderItem
|
|
25
|
+
v-for="(item, index) in positions"
|
|
26
|
+
:key="`${item._id}_${item.variant || 'no-variant'}_${index}`"
|
|
27
|
+
:editable="false"
|
|
28
|
+
:productId="item._id"
|
|
29
|
+
:variantId="item.variant"
|
|
30
|
+
:images="item.images"
|
|
31
|
+
:name="item.name"
|
|
32
|
+
:quantity="item.quantity"
|
|
33
|
+
:unit="item.unit"
|
|
34
|
+
:dates="item.date"
|
|
35
|
+
:listing="item.listing"
|
|
36
|
+
:price="item.price"
|
|
37
|
+
class="bg-white radius-small pd-small"
|
|
38
|
+
/>
|
|
39
|
+
</div>
|
|
40
|
+
|
|
41
|
+
<!-- Footer: Total + Actions -->
|
|
42
|
+
<div class="flex-nowrap flex-v-center flex-between flex">
|
|
43
|
+
<div class="w-100">
|
|
44
|
+
<span class="fw-medium t-dark p-medium">Total</span>
|
|
45
|
+
<span class="fw-demi t-dark p-medium">{{ formatPrice(total) }}</span>
|
|
46
|
+
</div>
|
|
47
|
+
|
|
48
|
+
<div class="flex-nowrap gap-thin flex">
|
|
49
|
+
<button
|
|
50
|
+
v-if="status === 'delivered' || status === 'finished'"
|
|
51
|
+
class="button bg-white pd-t-thin pd-b-thin pd-l-small pd-r-small p-small fw-medium radius-small"
|
|
52
|
+
>
|
|
53
|
+
Rate
|
|
54
|
+
</button>
|
|
55
|
+
<button
|
|
56
|
+
v-if="status === 'created' || status === 'confirmed'"
|
|
57
|
+
class="button bg-main t-white pd-t-thin pd-b-thin pd-l-small pd-r-small p-small fw-medium radius-small"
|
|
58
|
+
>
|
|
59
|
+
Pay
|
|
60
|
+
</button>
|
|
61
|
+
<button class="button bg-white pd-t-thin pd-b-thin pd-l-small pd-r-small p-small fw-medium radius-small flex-v-center gap-micro flex">
|
|
62
|
+
Details
|
|
63
|
+
<IconChevronRight class="i-small" />
|
|
64
|
+
</button>
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
91
67
|
</div>
|
|
92
68
|
</template>
|
|
93
69
|
|
|
94
70
|
<script setup>
|
|
95
71
|
import { computed } from 'vue';
|
|
72
|
+
import { useI18n } from 'vue-i18n';
|
|
73
|
+
import { useGlobalMixins } from '@martyrs/src/modules/core/views/mixins/mixins.js';
|
|
96
74
|
|
|
97
|
-
import
|
|
75
|
+
import IconChevronRight from '@martyrs/src/modules/icons/navigation/IconChevronRight.vue';
|
|
76
|
+
import CardOrderItem from '@martyrs/src/modules/orders/components/blocks/CardOrderItem.vue';
|
|
98
77
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
import IconStatusInUse from '@martyrs/src/modules/orders/components/icons/IconStatusInUse.vue';
|
|
102
|
-
import IconStatusFinished from '@martyrs/src/modules/orders/components/icons/IconStatusFinished.vue';
|
|
103
|
-
import IconStatusCanceled from '@martyrs/src/modules/orders/components/icons/IconStatusCanceled.vue';
|
|
104
|
-
import IconStatusDelay from '@martyrs/src/modules/orders/components/icons/IconStatusDelay.vue';
|
|
78
|
+
const { locale } = useI18n();
|
|
79
|
+
const { formatPrice, formatDate } = useGlobalMixins();
|
|
105
80
|
|
|
106
81
|
const props = defineProps({
|
|
107
82
|
orderId: String,
|
|
@@ -112,112 +87,35 @@ const props = defineProps({
|
|
|
112
87
|
total: [String, Number]
|
|
113
88
|
});
|
|
114
89
|
|
|
115
|
-
const
|
|
116
|
-
'
|
|
117
|
-
|
|
118
|
-
'preparing': IconStatusInUse,
|
|
119
|
-
'inuse': IconStatusInUse,
|
|
120
|
-
'finished': IconStatusFinished,
|
|
121
|
-
'canceled': IconStatusCanceled,
|
|
122
|
-
'delay': IconStatusDelay
|
|
90
|
+
const formatOrderId = (id) => {
|
|
91
|
+
if (!id) return '';
|
|
92
|
+
return `#${id.slice(0, 3).toUpperCase()}-${id.slice(-4).toUpperCase()}-${new Date().getFullYear()}`;
|
|
123
93
|
};
|
|
124
94
|
|
|
125
|
-
const
|
|
126
|
-
|
|
127
|
-
|
|
95
|
+
const statusConfig = {
|
|
96
|
+
'delivered': { label: 'Delivered', class: 't-green bg-green-nano', dot: 'bg-green' },
|
|
97
|
+
'finished': { label: 'Delivered', class: 't-green bg-green-nano', dot: 'bg-green' },
|
|
98
|
+
'processing': { label: 'Processing', class: 't-main bg-main-nano', dot: 'bg-main' },
|
|
99
|
+
'created': { label: 'Processing', class: 't-main bg-main-nano', dot: 'bg-main' },
|
|
100
|
+
'confirmed': { label: 'Confirmed', class: 't-main bg-main-nano', dot: 'bg-main' },
|
|
101
|
+
'shipped': { label: 'Shipped', class: 't-second bg-second-nano', dot: 'bg-second' },
|
|
102
|
+
'preparing': { label: 'Preparing', class: 't-second bg-second-nano', dot: 'bg-second' },
|
|
103
|
+
'cancelled': { label: 'Cancelled', class: 't-grey bg-light', dot: 'bg-grey' },
|
|
104
|
+
'canceled': { label: 'Cancelled', class: 't-grey bg-light', dot: 'bg-grey' },
|
|
105
|
+
'returned': { label: 'Returned', class: 't-fourth bg-fourth-nano', dot: 'bg-fourth' }
|
|
128
106
|
};
|
|
129
107
|
|
|
130
|
-
const
|
|
131
|
-
const createdDate = formatDate(props.createdAt);
|
|
132
|
-
const updatedDate = formatDate(props.updatedAt);
|
|
133
|
-
|
|
134
|
-
switch(props.status.toLowerCase()) {
|
|
135
|
-
case 'created':
|
|
136
|
-
return `Created, ${createdDate}`;
|
|
137
|
-
case 'confirmed':
|
|
138
|
-
return `Confirmed, ${updatedDate}`;
|
|
139
|
-
case 'preparing':
|
|
140
|
-
case 'inuse':
|
|
141
|
-
if (props.positions?.length) {
|
|
142
|
-
const lastEndDate = new Date(props.positions[props.positions.length - 1].date.end);
|
|
143
|
-
return `up to ${formatDate(lastEndDate)}`;
|
|
144
|
-
}
|
|
145
|
-
return `up to 18:00, ${updatedDate}`;
|
|
146
|
-
case 'finished':
|
|
147
|
-
return `Finished, ${updatedDate}`;
|
|
148
|
-
case 'canceled':
|
|
149
|
-
return `Canceled, ${updatedDate}`;
|
|
150
|
-
default:
|
|
151
|
-
// Расчет задержки
|
|
152
|
-
if (props.positions?.length) {
|
|
153
|
-
const lastPosition = props.positions[props.positions.length - 1];
|
|
154
|
-
const lastEndDateRaw = lastPosition?.date?.end;
|
|
155
|
-
|
|
156
|
-
if (lastEndDateRaw) {
|
|
157
|
-
const lastEndDate = new Date(lastEndDateRaw);
|
|
158
|
-
const now = new Date();
|
|
159
|
-
const diffTime = Math.abs(now.getTime() - lastEndDate.getTime());
|
|
160
|
-
const diffDays = Math.ceil(diffTime / (1000 * 60 * 60 * 24));
|
|
108
|
+
const statusKey = computed(() => props.status?.toLowerCase() || 'created');
|
|
161
109
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
return `Created, ${createdDate}`;
|
|
168
|
-
|
|
169
|
-
}
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
// Выбор иконки
|
|
173
|
-
const statusIcon = computed(() => {
|
|
174
|
-
if (props.status === 'preparing' || props.status === 'inuse') {
|
|
175
|
-
// Проверка на задержку
|
|
176
|
-
if (props.positions?.length) {
|
|
177
|
-
const lastEndDate = new Date(props.positions[props.positions.length - 1].date.end);
|
|
178
|
-
if (new Date() > lastEndDate && props.status !== 'finished' && props.status !== 'canceled') {
|
|
179
|
-
return IconStatusDelay;
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
return IconStatusInUse;
|
|
183
|
-
}
|
|
184
|
-
return iconMap[props.status.toLowerCase()] || IconStatusCreated;
|
|
110
|
+
const statusLabel = computed(() => {
|
|
111
|
+
return statusConfig[statusKey.value]?.label || 'Processing';
|
|
185
112
|
});
|
|
186
113
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
const date = new Date(dateString);
|
|
190
|
-
date.setHours(0, 0, 0, 0);
|
|
191
|
-
return date;
|
|
192
|
-
};
|
|
193
|
-
|
|
194
|
-
// Текущая дата и дата через 3 дня
|
|
195
|
-
const today = getDateWithoutTime(new Date());
|
|
196
|
-
const threeDaysFromNow = new Date(today);
|
|
197
|
-
threeDaysFromNow.setDate(today.getDate() + 3);
|
|
198
|
-
|
|
199
|
-
// Показывать ли уведомление о возврате
|
|
200
|
-
const showReturnNotice = computed(() => {
|
|
201
|
-
return props.positions.some(position => {
|
|
202
|
-
const endDate = position?.date?.end ? getDateWithoutTime(position.date.end) : null;
|
|
203
|
-
return endDate !== null && endDate <= threeDaysFromNow;
|
|
204
|
-
});
|
|
114
|
+
const statusClasses = computed(() => {
|
|
115
|
+
return statusConfig[statusKey.value]?.class || 't-main bg-main-nano';
|
|
205
116
|
});
|
|
206
117
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
return props.positions.some(position => {
|
|
210
|
-
const endDate = position?.date?.end ? getDateWithoutTime(position.date.end) : null;
|
|
211
|
-
return endDate !== null && endDate < today;
|
|
212
|
-
});
|
|
118
|
+
const dotClasses = computed(() => {
|
|
119
|
+
return statusConfig[statusKey.value]?.dot || 'bg-main';
|
|
213
120
|
});
|
|
214
|
-
|
|
215
|
-
// Предполагается, что formatPrice определен где-то в коде
|
|
216
121
|
</script>
|
|
217
|
-
|
|
218
|
-
<style scoped>
|
|
219
|
-
/* Добавляем стиль для текста "просрочено" */
|
|
220
|
-
.t-red {
|
|
221
|
-
color: red;
|
|
222
|
-
}
|
|
223
|
-
</style>
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
</div>
|
|
10
10
|
|
|
11
11
|
<div class="flex-nowrap flex gap-thin pos-relative ">
|
|
12
|
-
<div v-for="(status, index) in
|
|
12
|
+
<div v-for="(status, index) in statuses" :key="index" class="w-20">
|
|
13
13
|
<div
|
|
14
14
|
class="bg-white br-anim br-glow radius-extra h-1r w-100"
|
|
15
15
|
:class="
|
|
@@ -325,7 +325,7 @@
|
|
|
325
325
|
const productsOrganization = ref(null)
|
|
326
326
|
const orderOrganization = ref(null)
|
|
327
327
|
|
|
328
|
-
const statuses = store.core.state.options
|
|
328
|
+
const statuses = store.core.state.options?.orders?.statuses || []
|
|
329
329
|
const statusLabels = ['Created', 'Confirmed', 'Preparing', 'In use', 'Finished'];
|
|
330
330
|
|
|
331
331
|
if (route.meta.context === 'user' &&
|
|
@@ -419,16 +419,16 @@ const deliveryCost = computed(() => {
|
|
|
419
419
|
|
|
420
420
|
|
|
421
421
|
function getNextStatus(currentStatus) {
|
|
422
|
-
const currentIndex =
|
|
422
|
+
const currentIndex = statuses.findIndex(status => status.value === currentStatus);
|
|
423
423
|
|
|
424
424
|
if (currentIndex !== -1 && currentIndex + 1 < statuses.length) {
|
|
425
|
-
return
|
|
425
|
+
return statuses[currentIndex + 1];
|
|
426
426
|
}
|
|
427
427
|
return null; // If next status doesn't exist
|
|
428
428
|
}
|
|
429
429
|
|
|
430
430
|
const isActiveStatus = (index) => {
|
|
431
|
-
return
|
|
431
|
+
return statuses.slice(index).some(status => status.value === order.value?.status);
|
|
432
432
|
};
|
|
433
433
|
|
|
434
434
|
async function changePaymentStatus() {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div class="mobile:pd-thin pd-medium">
|
|
2
|
+
<div class="mobile:pd-thin pd-medium">
|
|
3
3
|
<SectionPageTitle
|
|
4
4
|
v-if="!MOBILE_APP"
|
|
5
5
|
title="Orders"
|
|
@@ -29,9 +29,17 @@
|
|
|
29
29
|
<h3>{{formatPrice(totalPrice)}}</h3>
|
|
30
30
|
</div>
|
|
31
31
|
</div>
|
|
32
|
-
|
|
33
32
|
</Block>
|
|
34
33
|
|
|
34
|
+
<!-- Tabs for user context -->
|
|
35
|
+
<Tab
|
|
36
|
+
v-if="route.meta.context === 'user'"
|
|
37
|
+
:tabs="tabs"
|
|
38
|
+
v-model:selected="tab"
|
|
39
|
+
classTab="bg-light"
|
|
40
|
+
class="mn-b-small"
|
|
41
|
+
/>
|
|
42
|
+
|
|
35
43
|
<Feed
|
|
36
44
|
:search="true"
|
|
37
45
|
:states="{
|
|
@@ -47,24 +55,24 @@
|
|
|
47
55
|
limit: 15,
|
|
48
56
|
...(route.meta.context === 'organization' && { owner: route.params._id }),
|
|
49
57
|
...(route.meta.context === 'user' && { customer: route.params._id }),
|
|
50
|
-
...(tab !== 'all' && { status:
|
|
58
|
+
...(tab !== 'all' && { status: tabStatusFilter })
|
|
51
59
|
}"
|
|
52
|
-
v-slot="{
|
|
53
|
-
items
|
|
60
|
+
v-slot="{
|
|
61
|
+
items
|
|
54
62
|
}"
|
|
55
|
-
class="gap-thin cols-3 mobile:cols-1"
|
|
63
|
+
:class="route.meta.context === 'user' ? 'gap-small cols-1' : 'gap-thin cols-3 mobile:cols-1'"
|
|
56
64
|
>
|
|
57
|
-
<router-link
|
|
65
|
+
<router-link
|
|
58
66
|
v-if="route.meta.context !== 'user'"
|
|
59
|
-
v-for="order in items"
|
|
60
|
-
:to="{
|
|
61
|
-
name: route.meta.context === 'backoffice' ? 'BackofficeOrderEdit' : 'OrganizationOrderEdit',
|
|
62
|
-
params: route.meta.context === 'backoffice'
|
|
63
|
-
? { order: order._id }
|
|
67
|
+
v-for="order in items"
|
|
68
|
+
:to="{
|
|
69
|
+
name: route.meta.context === 'backoffice' ? 'BackofficeOrderEdit' : 'OrganizationOrderEdit',
|
|
70
|
+
params: route.meta.context === 'backoffice'
|
|
71
|
+
? { order: order._id }
|
|
64
72
|
: { order: order._id, organization: order.owner.target || order.owner._id }
|
|
65
|
-
}"
|
|
73
|
+
}"
|
|
66
74
|
>
|
|
67
|
-
<CardOrderBackoffice
|
|
75
|
+
<CardOrderBackoffice
|
|
68
76
|
:order="order"
|
|
69
77
|
:user="auth.state.user"
|
|
70
78
|
:formatDate="formatDate"
|
|
@@ -73,69 +81,72 @@
|
|
|
73
81
|
/>
|
|
74
82
|
</router-link>
|
|
75
83
|
|
|
76
|
-
<router-link
|
|
84
|
+
<router-link
|
|
77
85
|
v-if="route.meta.context === 'user'"
|
|
78
|
-
v-for="order in items"
|
|
79
|
-
:to="{
|
|
80
|
-
name: 'UserOrder',
|
|
81
|
-
params: {
|
|
82
|
-
order: order._id
|
|
83
|
-
}
|
|
84
|
-
}"
|
|
86
|
+
v-for="order in items"
|
|
87
|
+
:to="`/users/${route.params._id}/orders/${order._id}`"
|
|
85
88
|
>
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
89
|
+
<CardOrderUser
|
|
90
|
+
:orderId="order._id"
|
|
91
|
+
:status="order.status"
|
|
92
|
+
:createdAt="order.createdAt"
|
|
93
|
+
:updatedAt="order.updatedAt"
|
|
94
|
+
:positions="order.positions"
|
|
95
|
+
:total="orders.getters.getTotal(order.positions)"
|
|
96
|
+
/>
|
|
94
97
|
</router-link>
|
|
95
98
|
</Feed>
|
|
96
99
|
</div>
|
|
97
100
|
</template>
|
|
98
101
|
|
|
99
102
|
<script setup>
|
|
100
|
-
import { computed,
|
|
101
|
-
import { useRoute
|
|
103
|
+
import { computed, ref } from 'vue';
|
|
104
|
+
import { useRoute } from 'vue-router';
|
|
102
105
|
|
|
103
|
-
import Tab
|
|
106
|
+
import Tab from '@martyrs/src/components/Tab/Tab.vue'
|
|
104
107
|
import Block from '@martyrs/src/components/Block/Block.vue';
|
|
108
|
+
import Feed from '@martyrs/src/components/Feed/Feed.vue'
|
|
105
109
|
|
|
106
110
|
import * as orders from '@martyrs/src/modules/orders/store/orders.js';
|
|
107
111
|
import * as auth from '@martyrs/src/modules/auth/views/store/auth.js';
|
|
108
112
|
|
|
109
|
-
import CardOrder from '@martyrs/src/modules/orders/components/blocks/CardOrder.vue'
|
|
110
|
-
|
|
111
113
|
import CardOrderUser from '@martyrs/src/modules/orders/components/blocks/CardOrderUser.vue'
|
|
112
114
|
import CardOrderBackoffice from '@martyrs/src/modules/orders/components/blocks/CardOrderBackoffice.vue'
|
|
113
|
-
|
|
114
115
|
import SectionPageTitle from '@martyrs/src/modules/core/views/components/sections/SectionPageTitle.vue'
|
|
115
116
|
|
|
116
|
-
import Feed from '@martyrs/src/components/Feed/Feed.vue'
|
|
117
|
-
|
|
118
|
-
import IconTime from '@martyrs/src/modules/icons/entities/IconTime.vue'
|
|
119
117
|
import { useGlobalMixins } from '@martyrs/src/modules/core/views/mixins/mixins.js'
|
|
120
118
|
|
|
121
119
|
const route = useRoute();
|
|
122
|
-
const router = useRouter();
|
|
123
120
|
const { returnCurrency, formatPrice, formatDate } = useGlobalMixins()
|
|
124
121
|
|
|
125
|
-
const spoiler = ref(false)
|
|
126
|
-
|
|
127
122
|
// Tab logic
|
|
128
123
|
const tab = ref('all')
|
|
129
124
|
|
|
125
|
+
const tabs = [
|
|
126
|
+
{ label: 'All Orders', value: 'all' },
|
|
127
|
+
{ label: 'In Progress', value: 'in_progress' },
|
|
128
|
+
{ label: 'Returns & Cancellations', value: 'returns' }
|
|
129
|
+
]
|
|
130
|
+
|
|
131
|
+
const tabStatusFilter = computed(() => {
|
|
132
|
+
switch (tab.value) {
|
|
133
|
+
case 'in_progress':
|
|
134
|
+
return ['created', 'confirmed', 'processing', 'preparing', 'shipped']
|
|
135
|
+
case 'returns':
|
|
136
|
+
return ['cancelled', 'canceled', 'returned']
|
|
137
|
+
default:
|
|
138
|
+
return null
|
|
139
|
+
}
|
|
140
|
+
})
|
|
141
|
+
|
|
130
142
|
const totalPrice = computed(() => {
|
|
131
143
|
return calculateTotalSum(orders.state.all)
|
|
132
144
|
});
|
|
133
145
|
|
|
134
|
-
|
|
146
|
+
const totalPriceUnpaid = computed(() => {
|
|
135
147
|
return calculateSum(orders.state.all,'unpaid')
|
|
136
148
|
});
|
|
137
149
|
|
|
138
|
-
|
|
139
150
|
function calculateTotalSum(orders) {
|
|
140
151
|
return orders.reduce((totalSum, item) => {
|
|
141
152
|
return totalSum + item.positions.reduce((sum, position) => sum + position.price, 0);
|
|
@@ -144,15 +155,10 @@
|
|
|
144
155
|
|
|
145
156
|
function calculateSum(orders, status) {
|
|
146
157
|
return orders.reduce((totalSum, item) => {
|
|
147
|
-
if (item.payment
|
|
158
|
+
if (item.payment?.status === status) {
|
|
148
159
|
return totalSum + item.positions.reduce((sum, position) => sum + position.price, 0);
|
|
149
160
|
}
|
|
150
161
|
return totalSum;
|
|
151
162
|
}, 0);
|
|
152
163
|
}
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
onMounted(async () => {
|
|
156
|
-
|
|
157
|
-
});
|
|
158
164
|
</script>
|
|
@@ -1,17 +1,37 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div class="for-transition pd-thin">
|
|
3
3
|
|
|
4
|
-
<h3 class="mn-b-small">
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
4
|
+
<h3 class="mn-b-small">Access & Privacy</h3>
|
|
5
|
+
|
|
6
|
+
<div class="d-grid cols-1 tablet:cols-3 gap-regular mn-b-semi">
|
|
7
|
+
<button
|
|
8
|
+
v-for="option in typeOptions"
|
|
9
|
+
:key="option.value"
|
|
10
|
+
@click="organization.state.current.types = [option.value]"
|
|
11
|
+
:class="[
|
|
12
|
+
'd-flex items-start gap-regular pd-regular radius-semi br-1px t-left transition-timing-2',
|
|
13
|
+
isTypeSelected(option.value)
|
|
14
|
+
? 'br-main bg-main-transp-10'
|
|
15
|
+
: 'br-light dark:br-dark-thin hover:br-grey bg-white dark:bg-dark'
|
|
16
|
+
]"
|
|
17
|
+
>
|
|
18
|
+
<div :class="[
|
|
19
|
+
'pd-thin radius-[50%]',
|
|
20
|
+
isTypeSelected(option.value)
|
|
21
|
+
? 'bg-main t-white'
|
|
22
|
+
: 'bg-light dark:bg-dark-thin t-grey'
|
|
23
|
+
]">
|
|
24
|
+
<component :is="option.icon" class="i-medium" />
|
|
25
|
+
</div>
|
|
26
|
+
<div>
|
|
27
|
+
<div class="fw-semi t-black dark:t-white d-flex items-center gap-thin">
|
|
28
|
+
{{ option.label }}
|
|
29
|
+
<span v-if="isTypeSelected(option.value)" class="w-[0.5rem] h-[0.5rem] radius-[50%] bg-main"></span>
|
|
30
|
+
</div>
|
|
31
|
+
<p class="p-small t-grey dark:t-grey-thin mn-t-micro">{{ option.desc }}</p>
|
|
32
|
+
</div>
|
|
33
|
+
</button>
|
|
34
|
+
</div>
|
|
15
35
|
|
|
16
36
|
|
|
17
37
|
<h3 class="mn-b-small">Profile</h3>
|
|
@@ -115,6 +135,7 @@
|
|
|
115
135
|
|
|
116
136
|
import { useRoute, useRouter } from 'vue-router';
|
|
117
137
|
|
|
138
|
+
import { IconGroups, IconLock, IconShow } from '@martyrs/src/modules/icons/icons.client.js'
|
|
118
139
|
import Breadcrumbs from '@martyrs/src/components/Breadcrumbs/Breadcrumbs.vue'
|
|
119
140
|
import BlockTags from '@martyrs/src/components/FieldTags/BlockTags.vue'
|
|
120
141
|
import Tab from '@martyrs/src/components/Tab/Tab.vue';
|
|
@@ -134,6 +155,16 @@
|
|
|
134
155
|
|
|
135
156
|
organization.actions.reset();
|
|
136
157
|
|
|
158
|
+
const typeOptions = [
|
|
159
|
+
{ value: 'public', label: 'Public', icon: IconGroups, desc: 'Visible to everyone. Anyone can join.' },
|
|
160
|
+
{ value: 'exclusive', label: 'Exclusive', icon: IconLock, desc: 'Visible, but membership requires approval.' },
|
|
161
|
+
{ value: 'hidden', label: 'Hidden', icon: IconShow, desc: 'Invite only. Hidden from search.' }
|
|
162
|
+
];
|
|
163
|
+
|
|
164
|
+
function isTypeSelected(type) {
|
|
165
|
+
return organization.state.current.types?.includes(type);
|
|
166
|
+
}
|
|
167
|
+
|
|
137
168
|
onMounted(async()=>{
|
|
138
169
|
if (route.params._id) {
|
|
139
170
|
await organization.actions.read({ _id: route.params._id });
|