@lodashventure/medusa-booking-for-pickup 1.4.1 → 1.4.3
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/.medusa/server/src/admin/index.js +421 -30
- package/.medusa/server/src/admin/index.mjs +435 -44
- package/.medusa/server/src/api/admin/customers/[id]/pickup-history/route.js +77 -0
- package/.medusa/server/src/api/admin/orders/[id]/pickup-booking/route.js +158 -0
- package/.medusa/server/src/links/index.js +13 -0
- package/.medusa/server/src/modules/pickup-datetime/models/pickup-availability.js +13 -3
- package/.medusa/server/src/modules/pickup-datetime/models/pickup-date.js +14 -3
- package/.medusa/server/src/workflows/pickup-availablity/pickup/steps/validatePickupDateStep.js +16 -5
- package/package.json +17 -31
- package/.medusa/server/src/modules/pickup-datetime/migrations/Migration20250426021722.js +0 -18
- package/.medusa/server/src/modules/pickup-datetime/migrations/Migration20250427042133.js +0 -15
- package/.medusa/server/src/modules/pickup-datetime/migrations/Migration20250428021350.js +0 -14
- package/.medusa/server/src/modules/pickup-datetime/migrations/Migration20250503003504.js +0 -25
|
@@ -1,12 +1,343 @@
|
|
|
1
|
-
import { jsx, Fragment
|
|
2
|
-
import {
|
|
1
|
+
import { jsxs, jsx, Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useEffect, useMemo, useCallback } from "react";
|
|
3
|
+
import { Calendar, Package, ShoppingBag, Clock, MapPin, RefreshCw, ArrowLeft, Trash2 } from "lucide-react";
|
|
4
|
+
import { defineWidgetConfig as defineWidgetConfig$1, defineRouteConfig } from "@medusajs/admin-sdk";
|
|
5
|
+
import { Container as Container$1, Heading as Heading$1, Text as Text$1, Badge as Badge$1, Button as Button$1, toast, createDataTableColumnHelper, useDataTable, DataTable, Select, clx, Switch, IconButton } from "@medusajs/ui";
|
|
3
6
|
import { StackPerspective, Plus } from "@medusajs/icons";
|
|
4
|
-
import { createDataTableColumnHelper, useDataTable, Container, DataTable, Heading, Select, clx, Text, Button, Switch, IconButton, toast } from "@medusajs/ui";
|
|
5
|
-
import { useState, useMemo, useEffect, useCallback } from "react";
|
|
6
7
|
import { useNavigate, useParams, Navigate } from "react-router-dom";
|
|
7
|
-
import { useQuery } from "@tanstack/react-query";
|
|
8
8
|
import Medusa from "@medusajs/js-sdk";
|
|
9
|
-
|
|
9
|
+
const CustomerPickupHistoryWidget = ({ data }) => {
|
|
10
|
+
const [pickupHistory, setPickupHistory] = useState([]);
|
|
11
|
+
const [loading, setLoading] = useState(true);
|
|
12
|
+
const [error, setError] = useState(null);
|
|
13
|
+
const customer = data;
|
|
14
|
+
useEffect(() => {
|
|
15
|
+
fetchPickupHistory();
|
|
16
|
+
}, [customer.id]);
|
|
17
|
+
const fetchPickupHistory = async () => {
|
|
18
|
+
setLoading(true);
|
|
19
|
+
setError(null);
|
|
20
|
+
try {
|
|
21
|
+
const response = await fetch(
|
|
22
|
+
`/admin/customers/${customer.id}/pickup-history`,
|
|
23
|
+
{
|
|
24
|
+
credentials: "include"
|
|
25
|
+
}
|
|
26
|
+
);
|
|
27
|
+
if (!response.ok) {
|
|
28
|
+
throw new Error("Failed to fetch pickup history");
|
|
29
|
+
}
|
|
30
|
+
const data2 = await response.json();
|
|
31
|
+
setPickupHistory(data2.pickup_history || []);
|
|
32
|
+
} catch (err) {
|
|
33
|
+
console.error("Error fetching pickup history:", err);
|
|
34
|
+
setError(err.message);
|
|
35
|
+
} finally {
|
|
36
|
+
setLoading(false);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
const formatDate = (dateString) => {
|
|
40
|
+
const date = new Date(dateString);
|
|
41
|
+
return new Intl.DateTimeFormat("th-TH", {
|
|
42
|
+
year: "numeric",
|
|
43
|
+
month: "short",
|
|
44
|
+
day: "numeric",
|
|
45
|
+
hour: "2-digit",
|
|
46
|
+
minute: "2-digit"
|
|
47
|
+
}).format(date);
|
|
48
|
+
};
|
|
49
|
+
const formatCurrency = (amount, currency) => {
|
|
50
|
+
return new Intl.NumberFormat("th-TH", {
|
|
51
|
+
style: "currency",
|
|
52
|
+
currency: currency.toUpperCase()
|
|
53
|
+
}).format(amount / 100);
|
|
54
|
+
};
|
|
55
|
+
const getStatusBadge = (status) => {
|
|
56
|
+
const statusColors = {
|
|
57
|
+
completed: "green",
|
|
58
|
+
pending: "orange",
|
|
59
|
+
canceled: "red",
|
|
60
|
+
processing: "blue"
|
|
61
|
+
};
|
|
62
|
+
const statusLabels = {
|
|
63
|
+
completed: "เสร็จสิ้น",
|
|
64
|
+
pending: "รอดำเนินการ",
|
|
65
|
+
canceled: "ยกเลิก",
|
|
66
|
+
processing: "กำลังดำเนินการ"
|
|
67
|
+
};
|
|
68
|
+
return /* @__PURE__ */ jsx(Badge, { color: statusColors[status] || "grey", size: "small", children: statusLabels[status] || status });
|
|
69
|
+
};
|
|
70
|
+
if (loading) {
|
|
71
|
+
return /* @__PURE__ */ jsxs(Container, { className: "divide-y p-0", children: [
|
|
72
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-between px-6 py-4", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
|
|
73
|
+
/* @__PURE__ */ jsx(Calendar, { className: "text-ui-fg-subtle" }),
|
|
74
|
+
/* @__PURE__ */ jsx(Heading, { level: "h2", children: "ประวัติการจองรับสินค้า" })
|
|
75
|
+
] }) }),
|
|
76
|
+
/* @__PURE__ */ jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsx(Text, { className: "text-ui-fg-subtle", children: "กำลังโหลด..." }) })
|
|
77
|
+
] });
|
|
78
|
+
}
|
|
79
|
+
if (error) {
|
|
80
|
+
return /* @__PURE__ */ jsxs(Container, { className: "divide-y p-0", children: [
|
|
81
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-between px-6 py-4", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
|
|
82
|
+
/* @__PURE__ */ jsx(Calendar, { className: "text-ui-fg-subtle" }),
|
|
83
|
+
/* @__PURE__ */ jsx(Heading, { level: "h2", children: "ประวัติการจองรับสินค้า" })
|
|
84
|
+
] }) }),
|
|
85
|
+
/* @__PURE__ */ jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsx(Text, { className: "text-red-500", children: error }) })
|
|
86
|
+
] });
|
|
87
|
+
}
|
|
88
|
+
return /* @__PURE__ */ jsxs(Container, { className: "divide-y p-0", children: [
|
|
89
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-6 py-4", children: [
|
|
90
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
|
|
91
|
+
/* @__PURE__ */ jsx(Calendar, { className: "text-ui-fg-subtle" }),
|
|
92
|
+
/* @__PURE__ */ jsx(Heading, { level: "h2", children: "ประวัติการจองรับสินค้า" }),
|
|
93
|
+
pickupHistory.length > 0 && /* @__PURE__ */ jsx(Badge, { size: "small", children: pickupHistory.length })
|
|
94
|
+
] }),
|
|
95
|
+
/* @__PURE__ */ jsx(Button, { size: "small", variant: "transparent", onClick: fetchPickupHistory, children: "รีเฟรช" })
|
|
96
|
+
] }),
|
|
97
|
+
/* @__PURE__ */ jsx("div", { className: "px-6 py-4", children: pickupHistory.length === 0 ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-8 text-center", children: [
|
|
98
|
+
/* @__PURE__ */ jsx(Package, { className: "text-ui-fg-muted mb-4", size: 48 }),
|
|
99
|
+
/* @__PURE__ */ jsx(Text, { className: "text-ui-fg-subtle", children: "ยังไม่มีประวัติการจองรับสินค้า" })
|
|
100
|
+
] }) : /* @__PURE__ */ jsx("div", { className: "space-y-4", children: pickupHistory.map((pickup) => {
|
|
101
|
+
var _a;
|
|
102
|
+
return /* @__PURE__ */ jsxs(
|
|
103
|
+
"div",
|
|
104
|
+
{
|
|
105
|
+
className: "rounded-lg border p-4 hover:bg-ui-bg-subtle transition-colors",
|
|
106
|
+
children: [
|
|
107
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between mb-3", children: [
|
|
108
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
109
|
+
/* @__PURE__ */ jsx(ShoppingBag, { className: "text-ui-fg-subtle", size: 20 }),
|
|
110
|
+
/* @__PURE__ */ jsx("div", { children: pickup.order ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
111
|
+
/* @__PURE__ */ jsxs(Text, { weight: "plus", size: "small", children: [
|
|
112
|
+
"คำสั่งซื้อ #",
|
|
113
|
+
pickup.order.display_id
|
|
114
|
+
] }),
|
|
115
|
+
/* @__PURE__ */ jsxs(Text, { size: "xsmall", className: "text-ui-fg-subtle", children: [
|
|
116
|
+
((_a = pickup.order.items) == null ? void 0 : _a.length) || 0,
|
|
117
|
+
" รายการ"
|
|
118
|
+
] })
|
|
119
|
+
] }) : /* @__PURE__ */ jsxs(Text, { weight: "plus", size: "small", children: [
|
|
120
|
+
"คำสั่งซื้อ ",
|
|
121
|
+
pickup.order_id
|
|
122
|
+
] }) })
|
|
123
|
+
] }),
|
|
124
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col items-end gap-1", children: [
|
|
125
|
+
pickup.order && getStatusBadge(pickup.order.status),
|
|
126
|
+
pickup.order && /* @__PURE__ */ jsx(Text, { weight: "plus", size: "small", children: formatCurrency(
|
|
127
|
+
pickup.order.total,
|
|
128
|
+
pickup.order.currency_code
|
|
129
|
+
) })
|
|
130
|
+
] })
|
|
131
|
+
] }),
|
|
132
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4 text-sm", children: [
|
|
133
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 text-ui-fg-subtle", children: [
|
|
134
|
+
/* @__PURE__ */ jsx(Calendar, { size: 16 }),
|
|
135
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
136
|
+
"วันที่รับ: ",
|
|
137
|
+
formatDate(pickup.pickup_datetime)
|
|
138
|
+
] })
|
|
139
|
+
] }),
|
|
140
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 text-ui-fg-subtle", children: [
|
|
141
|
+
/* @__PURE__ */ jsx(Clock, { size: 16 }),
|
|
142
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
143
|
+
"จองเมื่อ: ",
|
|
144
|
+
formatDate(pickup.created_at)
|
|
145
|
+
] })
|
|
146
|
+
] })
|
|
147
|
+
] }),
|
|
148
|
+
pickup.order && pickup.order.shipping_methods && /* @__PURE__ */ jsx("div", { className: "mt-2 pt-2 border-t", children: /* @__PURE__ */ jsx(Text, { size: "xsmall", className: "text-ui-fg-subtle", children: pickup.order.shipping_methods.map((sm) => sm.name).join(", ") }) })
|
|
149
|
+
]
|
|
150
|
+
},
|
|
151
|
+
pickup.id
|
|
152
|
+
);
|
|
153
|
+
}) }) })
|
|
154
|
+
] });
|
|
155
|
+
};
|
|
156
|
+
defineWidgetConfig({
|
|
157
|
+
zone: "customer.details.after"
|
|
158
|
+
});
|
|
159
|
+
const OrderPickupBookingWidget = ({ data }) => {
|
|
160
|
+
var _a, _b;
|
|
161
|
+
const [pickupBooking, setPickupBooking] = useState(null);
|
|
162
|
+
const [loading, setLoading] = useState(true);
|
|
163
|
+
const [error, setError] = useState(null);
|
|
164
|
+
const order = data;
|
|
165
|
+
useEffect(() => {
|
|
166
|
+
fetchPickupBooking();
|
|
167
|
+
}, [order.id]);
|
|
168
|
+
const fetchPickupBooking = async () => {
|
|
169
|
+
setLoading(true);
|
|
170
|
+
setError(null);
|
|
171
|
+
try {
|
|
172
|
+
const response = await fetch(`/admin/orders/${order.id}/pickup-booking`, {
|
|
173
|
+
credentials: "include"
|
|
174
|
+
});
|
|
175
|
+
if (!response.ok) {
|
|
176
|
+
if (response.status === 404) {
|
|
177
|
+
setPickupBooking(null);
|
|
178
|
+
setLoading(false);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
throw new Error("Failed to fetch pickup booking");
|
|
182
|
+
}
|
|
183
|
+
const data2 = await response.json();
|
|
184
|
+
setPickupBooking(data2.pickup_booking);
|
|
185
|
+
} catch (err) {
|
|
186
|
+
console.error("Error fetching pickup booking:", err);
|
|
187
|
+
setError(err.message);
|
|
188
|
+
} finally {
|
|
189
|
+
setLoading(false);
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
const formatDate = (dateString) => {
|
|
193
|
+
const date = new Date(dateString);
|
|
194
|
+
return new Intl.DateTimeFormat("th-TH", {
|
|
195
|
+
year: "numeric",
|
|
196
|
+
month: "long",
|
|
197
|
+
day: "numeric"
|
|
198
|
+
}).format(date);
|
|
199
|
+
};
|
|
200
|
+
const formatTime = (dateString) => {
|
|
201
|
+
const date = new Date(dateString);
|
|
202
|
+
return new Intl.DateTimeFormat("th-TH", {
|
|
203
|
+
hour: "2-digit",
|
|
204
|
+
minute: "2-digit",
|
|
205
|
+
hour12: false
|
|
206
|
+
}).format(date);
|
|
207
|
+
};
|
|
208
|
+
const formatDateTime = (dateString) => {
|
|
209
|
+
const date = new Date(dateString);
|
|
210
|
+
return new Intl.DateTimeFormat("th-TH", {
|
|
211
|
+
year: "numeric",
|
|
212
|
+
month: "short",
|
|
213
|
+
day: "numeric",
|
|
214
|
+
hour: "2-digit",
|
|
215
|
+
minute: "2-digit"
|
|
216
|
+
}).format(date);
|
|
217
|
+
};
|
|
218
|
+
const getPickupStatus = () => {
|
|
219
|
+
const now = /* @__PURE__ */ new Date();
|
|
220
|
+
const pickupDate = pickupBooking ? new Date(pickupBooking.pickup_datetime) : null;
|
|
221
|
+
if (!pickupDate) return { label: "N/A", color: "grey" };
|
|
222
|
+
if (order.status === "completed" || order.status === "delivered") {
|
|
223
|
+
return { label: "รับสินค้าแล้ว", color: "green" };
|
|
224
|
+
}
|
|
225
|
+
if (order.status === "canceled") {
|
|
226
|
+
return { label: "ยกเลิก", color: "red" };
|
|
227
|
+
}
|
|
228
|
+
if (now > pickupDate) {
|
|
229
|
+
return { label: "เลยกำหนดรับ", color: "orange" };
|
|
230
|
+
}
|
|
231
|
+
return { label: "รอรับสินค้า", color: "blue" };
|
|
232
|
+
};
|
|
233
|
+
if (loading) {
|
|
234
|
+
return /* @__PURE__ */ jsxs(Container$1, { className: "divide-y p-0", children: [
|
|
235
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-between px-6 py-4", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
|
|
236
|
+
/* @__PURE__ */ jsx(Calendar, { className: "text-ui-fg-subtle" }),
|
|
237
|
+
/* @__PURE__ */ jsx(Heading$1, { level: "h2", children: "การจองรับสินค้า" })
|
|
238
|
+
] }) }),
|
|
239
|
+
/* @__PURE__ */ jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsx(Text$1, { className: "text-ui-fg-subtle", children: "กำลังโหลด..." }) })
|
|
240
|
+
] });
|
|
241
|
+
}
|
|
242
|
+
if (error) {
|
|
243
|
+
return /* @__PURE__ */ jsxs(Container$1, { className: "divide-y p-0", children: [
|
|
244
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-between px-6 py-4", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
|
|
245
|
+
/* @__PURE__ */ jsx(Calendar, { className: "text-ui-fg-subtle" }),
|
|
246
|
+
/* @__PURE__ */ jsx(Heading$1, { level: "h2", children: "การจองรับสินค้า" })
|
|
247
|
+
] }) }),
|
|
248
|
+
/* @__PURE__ */ jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsx(Text$1, { className: "text-red-500", children: error }) })
|
|
249
|
+
] });
|
|
250
|
+
}
|
|
251
|
+
if (!pickupBooking) {
|
|
252
|
+
return /* @__PURE__ */ jsxs(Container$1, { className: "divide-y p-0", children: [
|
|
253
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-between px-6 py-4", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
|
|
254
|
+
/* @__PURE__ */ jsx(Calendar, { className: "text-ui-fg-subtle" }),
|
|
255
|
+
/* @__PURE__ */ jsx(Heading$1, { level: "h2", children: "การจองรับสินค้า" })
|
|
256
|
+
] }) }),
|
|
257
|
+
/* @__PURE__ */ jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center py-8 text-center", children: [
|
|
258
|
+
/* @__PURE__ */ jsx(MapPin, { className: "text-ui-fg-muted mb-4", size: 48 }),
|
|
259
|
+
/* @__PURE__ */ jsx(Text$1, { className: "text-ui-fg-subtle", children: "คำสั่งซื้อนี้ไม่ได้จองรับสินค้าที่สาขา" }),
|
|
260
|
+
/* @__PURE__ */ jsx(Text$1, { size: "xsmall", className: "text-ui-fg-muted mt-2", children: "คำสั่งซื้อนี้อาจเป็นการจัดส่งแบบปกติ" })
|
|
261
|
+
] }) })
|
|
262
|
+
] });
|
|
263
|
+
}
|
|
264
|
+
const status = getPickupStatus();
|
|
265
|
+
return /* @__PURE__ */ jsxs(Container$1, { className: "divide-y p-0", children: [
|
|
266
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-6 py-4", children: [
|
|
267
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
|
|
268
|
+
/* @__PURE__ */ jsx(Calendar, { className: "text-ui-fg-subtle" }),
|
|
269
|
+
/* @__PURE__ */ jsx(Heading$1, { level: "h2", children: "การจองรับสินค้าที่สาขา" }),
|
|
270
|
+
/* @__PURE__ */ jsx(Badge$1, { color: status.color, size: "small", children: status.label })
|
|
271
|
+
] }),
|
|
272
|
+
/* @__PURE__ */ jsx(
|
|
273
|
+
Button$1,
|
|
274
|
+
{
|
|
275
|
+
size: "small",
|
|
276
|
+
variant: "transparent",
|
|
277
|
+
onClick: () => {
|
|
278
|
+
fetchPickupBooking();
|
|
279
|
+
toast.success("รีเฟรชข้อมูลแล้ว");
|
|
280
|
+
},
|
|
281
|
+
children: /* @__PURE__ */ jsx(RefreshCw, { size: 16 })
|
|
282
|
+
}
|
|
283
|
+
)
|
|
284
|
+
] }),
|
|
285
|
+
/* @__PURE__ */ jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
286
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
|
|
287
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
288
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-ui-fg-subtle", children: [
|
|
289
|
+
/* @__PURE__ */ jsx(Calendar, { size: 16 }),
|
|
290
|
+
/* @__PURE__ */ jsx(Text$1, { size: "xsmall", weight: "plus", children: "วันที่รับสินค้า" })
|
|
291
|
+
] }),
|
|
292
|
+
/* @__PURE__ */ jsx(Text$1, { weight: "plus", children: formatDate(pickupBooking.pickup_datetime) })
|
|
293
|
+
] }),
|
|
294
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
295
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-ui-fg-subtle", children: [
|
|
296
|
+
/* @__PURE__ */ jsx(Clock, { size: 16 }),
|
|
297
|
+
/* @__PURE__ */ jsx(Text$1, { size: "xsmall", weight: "plus", children: "เวลารับสินค้า" })
|
|
298
|
+
] }),
|
|
299
|
+
/* @__PURE__ */ jsx(Text$1, { weight: "plus", children: formatTime(pickupBooking.pickup_datetime) })
|
|
300
|
+
] })
|
|
301
|
+
] }),
|
|
302
|
+
pickupBooking.shipping_option && /* @__PURE__ */ jsx("div", { className: "rounded-lg border p-4 bg-ui-bg-subtle", children: /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2 mb-2", children: [
|
|
303
|
+
/* @__PURE__ */ jsx(MapPin, { className: "text-ui-fg-muted mt-1", size: 16 }),
|
|
304
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
|
|
305
|
+
/* @__PURE__ */ jsx(Text$1, { weight: "plus", size: "small", className: "mb-1", children: pickupBooking.shipping_option.name }),
|
|
306
|
+
((_b = (_a = pickupBooking.shipping_option.service_zone) == null ? void 0 : _a.fulfillment_set) == null ? void 0 : _b.location) && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
307
|
+
/* @__PURE__ */ jsx(Text$1, { size: "small", className: "text-ui-fg-subtle", children: pickupBooking.shipping_option.service_zone.fulfillment_set.location.name }),
|
|
308
|
+
pickupBooking.shipping_option.service_zone.fulfillment_set.location.address && /* @__PURE__ */ jsxs(Text$1, { size: "xsmall", className: "text-ui-fg-muted mt-1", children: [
|
|
309
|
+
pickupBooking.shipping_option.service_zone.fulfillment_set.location.address.address_1,
|
|
310
|
+
pickupBooking.shipping_option.service_zone.fulfillment_set.location.address.address_2 && `, ${pickupBooking.shipping_option.service_zone.fulfillment_set.location.address.address_2}`,
|
|
311
|
+
/* @__PURE__ */ jsx("br", {}),
|
|
312
|
+
pickupBooking.shipping_option.service_zone.fulfillment_set.location.address.city,
|
|
313
|
+
" ",
|
|
314
|
+
pickupBooking.shipping_option.service_zone.fulfillment_set.location.address.province,
|
|
315
|
+
" ",
|
|
316
|
+
pickupBooking.shipping_option.service_zone.fulfillment_set.location.address.postal_code
|
|
317
|
+
] })
|
|
318
|
+
] })
|
|
319
|
+
] })
|
|
320
|
+
] }) }),
|
|
321
|
+
/* @__PURE__ */ jsx("div", { className: "pt-4 border-t", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
|
|
322
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
323
|
+
/* @__PURE__ */ jsx(Text$1, { size: "xsmall", className: "text-ui-fg-subtle", children: "จองเมื่อ" }),
|
|
324
|
+
/* @__PURE__ */ jsx(Text$1, { size: "small", children: formatDateTime(pickupBooking.created_at) })
|
|
325
|
+
] }),
|
|
326
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
327
|
+
/* @__PURE__ */ jsx(Text$1, { size: "xsmall", className: "text-ui-fg-subtle", children: "อัปเดตล่าสุด" }),
|
|
328
|
+
/* @__PURE__ */ jsx(Text$1, { size: "small", children: formatDateTime(pickupBooking.updated_at) })
|
|
329
|
+
] })
|
|
330
|
+
] }) }),
|
|
331
|
+
/* @__PURE__ */ jsx("div", { className: "pt-4 border-t", children: /* @__PURE__ */ jsxs(Text$1, { size: "xsmall", className: "text-ui-fg-muted", children: [
|
|
332
|
+
"Booking ID: ",
|
|
333
|
+
pickupBooking.id
|
|
334
|
+
] }) })
|
|
335
|
+
] }) })
|
|
336
|
+
] });
|
|
337
|
+
};
|
|
338
|
+
defineWidgetConfig$1({
|
|
339
|
+
zone: "order.details.after"
|
|
340
|
+
});
|
|
10
341
|
const sdk = new Medusa({
|
|
11
342
|
baseUrl: "/",
|
|
12
343
|
debug: false,
|
|
@@ -14,25 +345,54 @@ const sdk = new Medusa({
|
|
|
14
345
|
type: "session"
|
|
15
346
|
}
|
|
16
347
|
});
|
|
17
|
-
const usePickupShippingOptions = (
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
348
|
+
const usePickupShippingOptions = () => {
|
|
349
|
+
const [data, setData] = useState(
|
|
350
|
+
null
|
|
351
|
+
);
|
|
352
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
353
|
+
const [error, setError] = useState(null);
|
|
354
|
+
const fetchOptions = async () => {
|
|
355
|
+
setIsLoading(true);
|
|
356
|
+
setError(null);
|
|
357
|
+
try {
|
|
358
|
+
const options = await sdk.admin.shippingOption.list({
|
|
359
|
+
fields: [
|
|
360
|
+
"id",
|
|
361
|
+
"name",
|
|
362
|
+
"shipping_profile.*",
|
|
363
|
+
"service_zone.*",
|
|
364
|
+
"service_zone.fulfillment_set.*"
|
|
365
|
+
].join(",")
|
|
24
366
|
});
|
|
25
|
-
const filteredOptions =
|
|
26
|
-
(option) =>
|
|
367
|
+
const filteredOptions = (options.shipping_options ?? []).filter(
|
|
368
|
+
(option) => {
|
|
369
|
+
var _a, _b;
|
|
370
|
+
return ((_b = (_a = option == null ? void 0 : option.service_zone) == null ? void 0 : _a.fulfillment_set) == null ? void 0 : _b.type) === "pickup";
|
|
371
|
+
}
|
|
27
372
|
);
|
|
28
|
-
|
|
373
|
+
setData({
|
|
29
374
|
shipping_options: filteredOptions,
|
|
30
375
|
count: filteredOptions.length,
|
|
31
|
-
limit:
|
|
32
|
-
offset:
|
|
33
|
-
};
|
|
376
|
+
limit: options.limit,
|
|
377
|
+
offset: options.offset
|
|
378
|
+
});
|
|
379
|
+
} catch (err) {
|
|
380
|
+
setError(
|
|
381
|
+
err instanceof Error ? err : new Error("Failed to fetch pickup shipping options")
|
|
382
|
+
);
|
|
383
|
+
} finally {
|
|
384
|
+
setIsLoading(false);
|
|
34
385
|
}
|
|
35
|
-
}
|
|
386
|
+
};
|
|
387
|
+
useEffect(() => {
|
|
388
|
+
fetchOptions();
|
|
389
|
+
}, []);
|
|
390
|
+
return {
|
|
391
|
+
data,
|
|
392
|
+
isLoading,
|
|
393
|
+
error,
|
|
394
|
+
refetch: fetchOptions
|
|
395
|
+
};
|
|
36
396
|
};
|
|
37
397
|
const columnHelper = createDataTableColumnHelper();
|
|
38
398
|
const columns = [
|
|
@@ -70,8 +430,8 @@ const ShippingOptionList = () => {
|
|
|
70
430
|
navigate(`/pickup-shipping/${row.id}`);
|
|
71
431
|
}
|
|
72
432
|
});
|
|
73
|
-
return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(Container, { className: "flex flex-col p-0 overflow-hidden", children: /* @__PURE__ */ jsxs(DataTable, { instance: table, children: [
|
|
74
|
-
/* @__PURE__ */ jsx(DataTable.Toolbar, { className: "flex flex-col items-start justify-between gap-2 md:flex-row md:items-center", children: /* @__PURE__ */ jsx(Heading, { children: "Pickup Shipping Options" }) }),
|
|
433
|
+
return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(Container$1, { className: "flex flex-col p-0 overflow-hidden", children: /* @__PURE__ */ jsxs(DataTable, { instance: table, children: [
|
|
434
|
+
/* @__PURE__ */ jsx(DataTable.Toolbar, { className: "flex flex-col items-start justify-between gap-2 md:flex-row md:items-center", children: /* @__PURE__ */ jsx(Heading$1, { children: "Pickup Shipping Options" }) }),
|
|
75
435
|
/* @__PURE__ */ jsx(DataTable.Table, {})
|
|
76
436
|
] }) }) });
|
|
77
437
|
};
|
|
@@ -1235,23 +1595,43 @@ axios$3.exports.default = axios$2;
|
|
|
1235
1595
|
var axiosExports = axios$3.exports;
|
|
1236
1596
|
var axios = axiosExports;
|
|
1237
1597
|
const axios$1 = /* @__PURE__ */ getDefaultExportFromCjs(axios);
|
|
1238
|
-
const usePickupAvailable = (id
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1598
|
+
const usePickupAvailable = (id) => {
|
|
1599
|
+
const [data, setData] = useState(null);
|
|
1600
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
1601
|
+
const [error, setError] = useState(null);
|
|
1602
|
+
const fetchPickupAvailable = async () => {
|
|
1603
|
+
if (!id) {
|
|
1604
|
+
setError(new Error("id is required"));
|
|
1605
|
+
setIsLoading(false);
|
|
1606
|
+
return;
|
|
1607
|
+
}
|
|
1608
|
+
setIsLoading(true);
|
|
1609
|
+
setError(null);
|
|
1610
|
+
try {
|
|
1246
1611
|
const option = await sdk.admin.shippingOption.retrieve(id, {
|
|
1247
1612
|
fields: "*.*,pickup_availabilities.*"
|
|
1248
1613
|
});
|
|
1249
1614
|
if (option.shipping_option.service_zone.fulfillment_set.type !== "pickup") {
|
|
1250
1615
|
throw new Error("shipping option is not pickup");
|
|
1251
1616
|
}
|
|
1252
|
-
|
|
1617
|
+
setData(option);
|
|
1618
|
+
} catch (err) {
|
|
1619
|
+
setError(
|
|
1620
|
+
err instanceof Error ? err : new Error("Failed to fetch pickup availability")
|
|
1621
|
+
);
|
|
1622
|
+
} finally {
|
|
1623
|
+
setIsLoading(false);
|
|
1253
1624
|
}
|
|
1254
|
-
}
|
|
1625
|
+
};
|
|
1626
|
+
useEffect(() => {
|
|
1627
|
+
fetchPickupAvailable();
|
|
1628
|
+
}, [id]);
|
|
1629
|
+
return {
|
|
1630
|
+
data,
|
|
1631
|
+
isLoading,
|
|
1632
|
+
error,
|
|
1633
|
+
refetch: fetchPickupAvailable
|
|
1634
|
+
};
|
|
1255
1635
|
};
|
|
1256
1636
|
const stringToMinutes = (time, defaultValue) => {
|
|
1257
1637
|
if (!time) return defaultValue;
|
|
@@ -1339,10 +1719,10 @@ function TimeTable({
|
|
|
1339
1719
|
});
|
|
1340
1720
|
};
|
|
1341
1721
|
if (timeSlots.length === 0) return null;
|
|
1342
|
-
return /* @__PURE__ */ jsxs(Container, { className: "p-4 overflow-x-auto", children: [
|
|
1343
|
-
/* @__PURE__ */ jsx(Heading, { className: "text-xl font-bold mb-4", children: "Pickup Hours Schedule" }),
|
|
1722
|
+
return /* @__PURE__ */ jsxs(Container$1, { className: "p-4 overflow-x-auto", children: [
|
|
1723
|
+
/* @__PURE__ */ jsx(Heading$1, { className: "text-xl font-bold mb-4", children: "Pickup Hours Schedule" }),
|
|
1344
1724
|
/* @__PURE__ */ jsxs("div", { className: "min-w-full flex", children: [
|
|
1345
|
-
/* @__PURE__ */ jsx("div", { className: "ml-2 mt-7 flex flex-col items-end", children: timeSlots.map((timeSlot) => /* @__PURE__ */ jsx(Text, { className: "h-8", children: timeSlot }, timeSlot)) }),
|
|
1725
|
+
/* @__PURE__ */ jsx("div", { className: "ml-2 mt-7 flex flex-col items-end", children: timeSlots.map((timeSlot) => /* @__PURE__ */ jsx(Text$1, { className: "h-8", children: timeSlot }, timeSlot)) }),
|
|
1346
1726
|
/* @__PURE__ */ jsxs("table", { className: "ml-2 w-full border-collapse", children: [
|
|
1347
1727
|
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { children: days.map((day) => /* @__PURE__ */ jsx(
|
|
1348
1728
|
"th",
|
|
@@ -1526,22 +1906,22 @@ function ShippingOptionDetails() {
|
|
|
1526
1906
|
return /* @__PURE__ */ jsx(Navigate, { to: "/pickup-shipping" });
|
|
1527
1907
|
}
|
|
1528
1908
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1529
|
-
/* @__PURE__ */ jsxs(Container, { className: "p-4 ", children: [
|
|
1909
|
+
/* @__PURE__ */ jsxs(Container$1, { className: "p-4 ", children: [
|
|
1530
1910
|
/* @__PURE__ */ jsxs(
|
|
1531
|
-
Button,
|
|
1911
|
+
Button$1,
|
|
1532
1912
|
{
|
|
1533
1913
|
onClick: () => navigate("/pickup-shipping"),
|
|
1534
1914
|
variant: "transparent",
|
|
1535
1915
|
className: "p-0 mb-4",
|
|
1536
1916
|
children: [
|
|
1537
1917
|
/* @__PURE__ */ jsx(ArrowLeft, { size: 20 }),
|
|
1538
|
-
/* @__PURE__ */ jsx(Text, { className: "ml-2", children: "Back" })
|
|
1918
|
+
/* @__PURE__ */ jsx(Text$1, { className: "ml-2", children: "Back" })
|
|
1539
1919
|
]
|
|
1540
1920
|
}
|
|
1541
1921
|
),
|
|
1542
1922
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4 mb-4", children: [
|
|
1543
|
-
/* @__PURE__ */ jsx(Heading, { className: "text-xl font-bold", children: "Pickup Hours" }),
|
|
1544
|
-
/* @__PURE__ */ jsx(Button, { onClick: handleUpdateSchedules, children: "Save" })
|
|
1923
|
+
/* @__PURE__ */ jsx(Heading$1, { className: "text-xl font-bold", children: "Pickup Hours" }),
|
|
1924
|
+
/* @__PURE__ */ jsx(Button$1, { onClick: handleUpdateSchedules, children: "Save" })
|
|
1545
1925
|
] }),
|
|
1546
1926
|
/* @__PURE__ */ jsx("div", { className: "space-y-4", children: Object.entries(schedule).map(([day, { enabled, timeSlots }]) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
1547
1927
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4 mb-2 h-8", children: [
|
|
@@ -1553,7 +1933,7 @@ function ShippingOptionDetails() {
|
|
|
1553
1933
|
},
|
|
1554
1934
|
`switch-${day}`
|
|
1555
1935
|
),
|
|
1556
|
-
/* @__PURE__ */ jsx(Text, { className: "capitalize", children: day }),
|
|
1936
|
+
/* @__PURE__ */ jsx(Text$1, { className: "capitalize", children: day }),
|
|
1557
1937
|
enabled && /* @__PURE__ */ jsx(
|
|
1558
1938
|
IconButton,
|
|
1559
1939
|
{
|
|
@@ -1578,7 +1958,7 @@ function ShippingOptionDetails() {
|
|
|
1578
1958
|
maxTime: slot.end
|
|
1579
1959
|
}
|
|
1580
1960
|
),
|
|
1581
|
-
/* @__PURE__ */ jsx(Text, { className: "text-gray-400", children: "-" }),
|
|
1961
|
+
/* @__PURE__ */ jsx(Text$1, { className: "text-gray-400", children: "-" }),
|
|
1582
1962
|
/* @__PURE__ */ jsx(
|
|
1583
1963
|
TimeSelect,
|
|
1584
1964
|
{
|
|
@@ -1608,7 +1988,16 @@ function ShippingOptionDetails() {
|
|
|
1608
1988
|
/* @__PURE__ */ jsx(TimeTable, { schedule })
|
|
1609
1989
|
] });
|
|
1610
1990
|
}
|
|
1611
|
-
const widgetModule = { widgets: [
|
|
1991
|
+
const widgetModule = { widgets: [
|
|
1992
|
+
{
|
|
1993
|
+
Component: CustomerPickupHistoryWidget,
|
|
1994
|
+
zone: ["customer.details.after"]
|
|
1995
|
+
},
|
|
1996
|
+
{
|
|
1997
|
+
Component: OrderPickupBookingWidget,
|
|
1998
|
+
zone: ["order.details.after"]
|
|
1999
|
+
}
|
|
2000
|
+
] };
|
|
1612
2001
|
const routeModule = {
|
|
1613
2002
|
routes: [
|
|
1614
2003
|
{
|
|
@@ -1635,12 +2024,14 @@ const formModule = { customFields: {} };
|
|
|
1635
2024
|
const displayModule = {
|
|
1636
2025
|
displays: {}
|
|
1637
2026
|
};
|
|
2027
|
+
const i18nModule = { resources: {} };
|
|
1638
2028
|
const plugin = {
|
|
1639
2029
|
widgetModule,
|
|
1640
2030
|
routeModule,
|
|
1641
2031
|
menuItemModule,
|
|
1642
2032
|
formModule,
|
|
1643
|
-
displayModule
|
|
2033
|
+
displayModule,
|
|
2034
|
+
i18nModule
|
|
1644
2035
|
};
|
|
1645
2036
|
export {
|
|
1646
2037
|
plugin as default
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GET = void 0;
|
|
4
|
+
const utils_1 = require("@medusajs/framework/utils");
|
|
5
|
+
const GET = async (req, res) => {
|
|
6
|
+
const { id: customer_id } = req.params;
|
|
7
|
+
const query = req.scope.resolve(utils_1.ContainerRegistrationKeys.QUERY);
|
|
8
|
+
try {
|
|
9
|
+
// Query pickup dates for orders associated with this customer
|
|
10
|
+
const result = await query.graph({
|
|
11
|
+
entity: "pickup_date",
|
|
12
|
+
fields: [
|
|
13
|
+
"id",
|
|
14
|
+
"pickup_datetime",
|
|
15
|
+
"order_id",
|
|
16
|
+
"created_at",
|
|
17
|
+
"updated_at",
|
|
18
|
+
],
|
|
19
|
+
filters: {
|
|
20
|
+
order: {
|
|
21
|
+
customer_id: customer_id,
|
|
22
|
+
},
|
|
23
|
+
},
|
|
24
|
+
pagination: {
|
|
25
|
+
order: {
|
|
26
|
+
created_at: "DESC",
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
// Enrich with order details
|
|
31
|
+
const pickupDates = result.data || [];
|
|
32
|
+
if (pickupDates.length > 0) {
|
|
33
|
+
// Get order details for each pickup
|
|
34
|
+
const orderIds = pickupDates.map((pd) => pd.order_id).filter(Boolean);
|
|
35
|
+
if (orderIds.length > 0) {
|
|
36
|
+
const orders = await query.graph({
|
|
37
|
+
entity: "order",
|
|
38
|
+
fields: [
|
|
39
|
+
"id",
|
|
40
|
+
"display_id",
|
|
41
|
+
"status",
|
|
42
|
+
"created_at",
|
|
43
|
+
"total",
|
|
44
|
+
"currency_code",
|
|
45
|
+
"items.*",
|
|
46
|
+
"shipping_methods.*",
|
|
47
|
+
],
|
|
48
|
+
filters: {
|
|
49
|
+
id: orderIds,
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
// Map orders to pickup dates
|
|
53
|
+
const orderMap = new Map(orders.data.map((order) => [order.id, order]));
|
|
54
|
+
const enrichedPickups = pickupDates.map((pickup) => ({
|
|
55
|
+
...pickup,
|
|
56
|
+
order: orderMap.get(pickup.order_id) || null,
|
|
57
|
+
}));
|
|
58
|
+
return res.status(200).json({
|
|
59
|
+
pickup_history: enrichedPickups,
|
|
60
|
+
count: enrichedPickups.length,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return res.status(200).json({
|
|
65
|
+
pickup_history: [],
|
|
66
|
+
count: 0,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
catch (error) {
|
|
70
|
+
console.error("Error fetching pickup history:", error);
|
|
71
|
+
return res.status(500).json({
|
|
72
|
+
error: error.message || "Failed to fetch pickup history",
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
exports.GET = GET;
|
|
77
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicm91dGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi8uLi9zcmMvYXBpL2FkbWluL2N1c3RvbWVycy9baWRdL3BpY2t1cC1oaXN0b3J5L3JvdXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUNBLHFEQUFzRTtBQUUvRCxNQUFNLEdBQUcsR0FBRyxLQUFLLEVBQUUsR0FBa0IsRUFBRSxHQUFtQixFQUFFLEVBQUU7SUFDbkUsTUFBTSxFQUFFLEVBQUUsRUFBRSxXQUFXLEVBQUUsR0FBRyxHQUFHLENBQUMsTUFBTSxDQUFDO0lBQ3ZDLE1BQU0sS0FBSyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLGlDQUF5QixDQUFDLEtBQUssQ0FBQyxDQUFDO0lBRWpFLElBQUksQ0FBQztRQUNILDhEQUE4RDtRQUM5RCxNQUFNLE1BQU0sR0FBRyxNQUFNLEtBQUssQ0FBQyxLQUFLLENBQUM7WUFDL0IsTUFBTSxFQUFFLGFBQWE7WUFDckIsTUFBTSxFQUFFO2dCQUNOLElBQUk7Z0JBQ0osaUJBQWlCO2dCQUNqQixVQUFVO2dCQUNWLFlBQVk7Z0JBQ1osWUFBWTthQUNiO1lBQ0QsT0FBTyxFQUFFO2dCQUNQLEtBQUssRUFBRTtvQkFDTCxXQUFXLEVBQUUsV0FBVztpQkFDekI7YUFDRjtZQUNELFVBQVUsRUFBRTtnQkFDVixLQUFLLEVBQUU7b0JBQ0wsVUFBVSxFQUFFLE1BQU07aUJBQ25CO2FBQ0Y7U0FDRixDQUFDLENBQUM7UUFFSCw0QkFBNEI7UUFDNUIsTUFBTSxXQUFXLEdBQUcsTUFBTSxDQUFDLElBQUksSUFBSSxFQUFFLENBQUM7UUFFdEMsSUFBSSxXQUFXLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRSxDQUFDO1lBQzNCLG9DQUFvQztZQUNwQyxNQUFNLFFBQVEsR0FBRyxXQUFXLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBTyxFQUFFLEVBQUUsQ0FBQyxFQUFFLENBQUMsUUFBUSxDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBRTNFLElBQUksUUFBUSxDQUFDLE1BQU0sR0FBRyxDQUFDLEVBQUUsQ0FBQztnQkFDeEIsTUFBTSxNQUFNLEdBQUcsTUFBTSxLQUFLLENBQUMsS0FBSyxDQUFDO29CQUMvQixNQUFNLEVBQUUsT0FBTztvQkFDZixNQUFNLEVBQUU7d0JBQ04sSUFBSTt3QkFDSixZQUFZO3dCQUNaLFFBQVE7d0JBQ1IsWUFBWTt3QkFDWixPQUFPO3dCQUNQLGVBQWU7d0JBQ2YsU0FBUzt3QkFDVCxvQkFBb0I7cUJBQ3JCO29CQUNELE9BQU8sRUFBRTt3QkFDUCxFQUFFLEVBQUUsUUFBUTtxQkFDYjtpQkFDRixDQUFDLENBQUM7Z0JBRUgsNkJBQTZCO2dCQUM3QixNQUFNLFFBQVEsR0FBRyxJQUFJLEdBQUcsQ0FDdEIsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFVLEVBQUUsRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLEVBQUUsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUNuRCxDQUFDO2dCQUVGLE1BQU0sZUFBZSxHQUFHLFdBQVcsQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFXLEVBQUUsRUFBRSxDQUFDLENBQUM7b0JBQ3hELEdBQUcsTUFBTTtvQkFDVCxLQUFLLEVBQUUsUUFBUSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLElBQUksSUFBSTtpQkFDN0MsQ0FBQyxDQUFDLENBQUM7Z0JBRUosT0FBTyxHQUFHLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFDLElBQUksQ0FBQztvQkFDMUIsY0FBYyxFQUFFLGVBQWU7b0JBQy9CLEtBQUssRUFBRSxlQUFlLENBQUMsTUFBTTtpQkFDOUIsQ0FBQyxDQUFDO1lBQ0wsQ0FBQztRQUNILENBQUM7UUFFRCxPQUFPLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDO1lBQzFCLGNBQWMsRUFBRSxFQUFFO1lBQ2xCLEtBQUssRUFBRSxDQUFDO1NBQ1QsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztJQUFDLE9BQU8sS0FBVSxFQUFFLENBQUM7UUFDcEIsT0FBTyxDQUFDLEtBQUssQ0FBQyxnQ0FBZ0MsRUFBRSxLQUFLLENBQUMsQ0FBQztRQUN2RCxPQUFPLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDO1lBQzFCLEtBQUssRUFBRSxLQUFLLENBQUMsT0FBTyxJQUFJLGdDQUFnQztTQUN6RCxDQUFDLENBQUM7SUFDTCxDQUFDO0FBQ0gsQ0FBQyxDQUFDO0FBL0VXLFFBQUEsR0FBRyxPQStFZCJ9
|