@lodashventure/medusa-booking-for-pickup 1.4.14 → 1.4.16
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.
|
@@ -0,0 +1,892 @@
|
|
|
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, useSdk } 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";
|
|
6
|
+
import { StackPerspective, Plus } from "@medusajs/icons";
|
|
7
|
+
import { useNavigate, useParams, Navigate } from "react-router-dom";
|
|
8
|
+
import Medusa from "@medusajs/js-sdk";
|
|
9
|
+
import "@medusajs/admin-shared";
|
|
10
|
+
const CustomerPickupHistoryWidget = ({ data }) => {
|
|
11
|
+
const [pickupHistory, setPickupHistory] = useState([]);
|
|
12
|
+
const [loading, setLoading] = useState(true);
|
|
13
|
+
const [error, setError] = useState(null);
|
|
14
|
+
const customer = data;
|
|
15
|
+
useEffect(() => {
|
|
16
|
+
fetchPickupHistory();
|
|
17
|
+
}, [customer.id]);
|
|
18
|
+
const fetchPickupHistory = async () => {
|
|
19
|
+
setLoading(true);
|
|
20
|
+
setError(null);
|
|
21
|
+
try {
|
|
22
|
+
const response = await fetch(
|
|
23
|
+
`/admin/customers/${customer.id}/pickup-history`,
|
|
24
|
+
{
|
|
25
|
+
credentials: "include"
|
|
26
|
+
}
|
|
27
|
+
);
|
|
28
|
+
if (!response.ok) {
|
|
29
|
+
throw new Error("Failed to fetch pickup history");
|
|
30
|
+
}
|
|
31
|
+
const data2 = await response.json();
|
|
32
|
+
setPickupHistory(data2.pickup_history || []);
|
|
33
|
+
} catch (err) {
|
|
34
|
+
console.error("Error fetching pickup history:", err);
|
|
35
|
+
setError(err.message);
|
|
36
|
+
} finally {
|
|
37
|
+
setLoading(false);
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
const formatDate = (dateString) => {
|
|
41
|
+
const date = new Date(dateString);
|
|
42
|
+
return new Intl.DateTimeFormat("th-TH", {
|
|
43
|
+
year: "numeric",
|
|
44
|
+
month: "short",
|
|
45
|
+
day: "numeric",
|
|
46
|
+
hour: "2-digit",
|
|
47
|
+
minute: "2-digit"
|
|
48
|
+
}).format(date);
|
|
49
|
+
};
|
|
50
|
+
const formatCurrency = (amount, currency) => {
|
|
51
|
+
return new Intl.NumberFormat("th-TH", {
|
|
52
|
+
style: "currency",
|
|
53
|
+
currency: currency.toUpperCase()
|
|
54
|
+
}).format(amount / 100);
|
|
55
|
+
};
|
|
56
|
+
const getStatusBadge = (status) => {
|
|
57
|
+
const statusColors = {
|
|
58
|
+
completed: "green",
|
|
59
|
+
pending: "orange",
|
|
60
|
+
canceled: "red",
|
|
61
|
+
processing: "blue"
|
|
62
|
+
};
|
|
63
|
+
const statusLabels = {
|
|
64
|
+
completed: "เสร็จสิ้น",
|
|
65
|
+
pending: "รอดำเนินการ",
|
|
66
|
+
canceled: "ยกเลิก",
|
|
67
|
+
processing: "กำลังดำเนินการ"
|
|
68
|
+
};
|
|
69
|
+
return /* @__PURE__ */ jsx(Badge, { color: statusColors[status] || "grey", size: "small", children: statusLabels[status] || status });
|
|
70
|
+
};
|
|
71
|
+
if (loading) {
|
|
72
|
+
return /* @__PURE__ */ jsxs(Container, { className: "divide-y p-0", children: [
|
|
73
|
+
/* @__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: [
|
|
74
|
+
/* @__PURE__ */ jsx(Calendar, { className: "text-ui-fg-subtle" }),
|
|
75
|
+
/* @__PURE__ */ jsx(Heading, { level: "h2", children: "ประวัติการจองรับสินค้า" })
|
|
76
|
+
] }) }),
|
|
77
|
+
/* @__PURE__ */ jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsx(Text, { className: "text-ui-fg-subtle", children: "กำลังโหลด..." }) })
|
|
78
|
+
] });
|
|
79
|
+
}
|
|
80
|
+
if (error) {
|
|
81
|
+
return /* @__PURE__ */ jsxs(Container, { className: "divide-y p-0", children: [
|
|
82
|
+
/* @__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: [
|
|
83
|
+
/* @__PURE__ */ jsx(Calendar, { className: "text-ui-fg-subtle" }),
|
|
84
|
+
/* @__PURE__ */ jsx(Heading, { level: "h2", children: "ประวัติการจองรับสินค้า" })
|
|
85
|
+
] }) }),
|
|
86
|
+
/* @__PURE__ */ jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsx(Text, { className: "text-red-500", children: error }) })
|
|
87
|
+
] });
|
|
88
|
+
}
|
|
89
|
+
return /* @__PURE__ */ jsxs(Container, { className: "divide-y p-0", children: [
|
|
90
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-6 py-4", children: [
|
|
91
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
|
|
92
|
+
/* @__PURE__ */ jsx(Calendar, { className: "text-ui-fg-subtle" }),
|
|
93
|
+
/* @__PURE__ */ jsx(Heading, { level: "h2", children: "ประวัติการจองรับสินค้า" }),
|
|
94
|
+
pickupHistory.length > 0 && /* @__PURE__ */ jsx(Badge, { size: "small", children: pickupHistory.length })
|
|
95
|
+
] }),
|
|
96
|
+
/* @__PURE__ */ jsx(Button, { size: "small", variant: "transparent", onClick: fetchPickupHistory, children: "รีเฟรช" })
|
|
97
|
+
] }),
|
|
98
|
+
/* @__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: [
|
|
99
|
+
/* @__PURE__ */ jsx(Package, { className: "text-ui-fg-muted mb-4", size: 48 }),
|
|
100
|
+
/* @__PURE__ */ jsx(Text, { className: "text-ui-fg-subtle", children: "ยังไม่มีประวัติการจองรับสินค้า" })
|
|
101
|
+
] }) : /* @__PURE__ */ jsx("div", { className: "space-y-4", children: pickupHistory.map((pickup) => {
|
|
102
|
+
var _a;
|
|
103
|
+
return /* @__PURE__ */ jsxs(
|
|
104
|
+
"div",
|
|
105
|
+
{
|
|
106
|
+
className: "rounded-lg border p-4 hover:bg-ui-bg-subtle transition-colors",
|
|
107
|
+
children: [
|
|
108
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between mb-3", children: [
|
|
109
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
110
|
+
/* @__PURE__ */ jsx(ShoppingBag, { className: "text-ui-fg-subtle", size: 20 }),
|
|
111
|
+
/* @__PURE__ */ jsx("div", { children: pickup.order ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
112
|
+
/* @__PURE__ */ jsxs(Text, { weight: "plus", size: "small", children: [
|
|
113
|
+
"คำสั่งซื้อ #",
|
|
114
|
+
pickup.order.display_id
|
|
115
|
+
] }),
|
|
116
|
+
/* @__PURE__ */ jsxs(Text, { size: "xsmall", className: "text-ui-fg-subtle", children: [
|
|
117
|
+
((_a = pickup.order.items) == null ? void 0 : _a.length) || 0,
|
|
118
|
+
" รายการ"
|
|
119
|
+
] })
|
|
120
|
+
] }) : /* @__PURE__ */ jsxs(Text, { weight: "plus", size: "small", children: [
|
|
121
|
+
"คำสั่งซื้อ ",
|
|
122
|
+
pickup.order_id
|
|
123
|
+
] }) })
|
|
124
|
+
] }),
|
|
125
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col items-end gap-1", children: [
|
|
126
|
+
pickup.order && getStatusBadge(pickup.order.status),
|
|
127
|
+
pickup.order && /* @__PURE__ */ jsx(Text, { weight: "plus", size: "small", children: formatCurrency(
|
|
128
|
+
pickup.order.total,
|
|
129
|
+
pickup.order.currency_code
|
|
130
|
+
) })
|
|
131
|
+
] })
|
|
132
|
+
] }),
|
|
133
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4 text-sm", children: [
|
|
134
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 text-ui-fg-subtle", children: [
|
|
135
|
+
/* @__PURE__ */ jsx(Calendar, { size: 16 }),
|
|
136
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
137
|
+
"วันที่รับ: ",
|
|
138
|
+
formatDate(pickup.pickup_datetime)
|
|
139
|
+
] })
|
|
140
|
+
] }),
|
|
141
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 text-ui-fg-subtle", children: [
|
|
142
|
+
/* @__PURE__ */ jsx(Clock, { size: 16 }),
|
|
143
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
144
|
+
"จองเมื่อ: ",
|
|
145
|
+
formatDate(pickup.created_at)
|
|
146
|
+
] })
|
|
147
|
+
] })
|
|
148
|
+
] }),
|
|
149
|
+
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(", ") }) })
|
|
150
|
+
]
|
|
151
|
+
},
|
|
152
|
+
pickup.id
|
|
153
|
+
);
|
|
154
|
+
}) }) })
|
|
155
|
+
] });
|
|
156
|
+
};
|
|
157
|
+
defineWidgetConfig({
|
|
158
|
+
zone: "customer.details.after"
|
|
159
|
+
});
|
|
160
|
+
const OrderPickupBookingWidget = ({ data }) => {
|
|
161
|
+
var _a, _b;
|
|
162
|
+
const [pickupBooking, setPickupBooking] = useState(null);
|
|
163
|
+
const [loading, setLoading] = useState(true);
|
|
164
|
+
const [error, setError] = useState(null);
|
|
165
|
+
const order = data;
|
|
166
|
+
useEffect(() => {
|
|
167
|
+
fetchPickupBooking();
|
|
168
|
+
}, [order.id]);
|
|
169
|
+
const fetchPickupBooking = async () => {
|
|
170
|
+
setLoading(true);
|
|
171
|
+
setError(null);
|
|
172
|
+
try {
|
|
173
|
+
const response = await fetch(`/admin/orders/${order.id}/pickup-booking`, {
|
|
174
|
+
credentials: "include"
|
|
175
|
+
});
|
|
176
|
+
if (!response.ok) {
|
|
177
|
+
if (response.status === 404) {
|
|
178
|
+
setPickupBooking(null);
|
|
179
|
+
setLoading(false);
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
throw new Error("Failed to fetch pickup booking");
|
|
183
|
+
}
|
|
184
|
+
const data2 = await response.json();
|
|
185
|
+
setPickupBooking(data2.pickup_booking);
|
|
186
|
+
} catch (err) {
|
|
187
|
+
console.error("Error fetching pickup booking:", err);
|
|
188
|
+
setError(err.message);
|
|
189
|
+
} finally {
|
|
190
|
+
setLoading(false);
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
const formatDate = (dateString) => {
|
|
194
|
+
const date = new Date(dateString);
|
|
195
|
+
return new Intl.DateTimeFormat("th-TH", {
|
|
196
|
+
year: "numeric",
|
|
197
|
+
month: "long",
|
|
198
|
+
day: "numeric"
|
|
199
|
+
}).format(date);
|
|
200
|
+
};
|
|
201
|
+
const formatTime = (dateString) => {
|
|
202
|
+
const date = new Date(dateString);
|
|
203
|
+
return new Intl.DateTimeFormat("th-TH", {
|
|
204
|
+
hour: "2-digit",
|
|
205
|
+
minute: "2-digit",
|
|
206
|
+
hour12: false
|
|
207
|
+
}).format(date);
|
|
208
|
+
};
|
|
209
|
+
const formatDateTime = (dateString) => {
|
|
210
|
+
const date = new Date(dateString);
|
|
211
|
+
return new Intl.DateTimeFormat("th-TH", {
|
|
212
|
+
year: "numeric",
|
|
213
|
+
month: "short",
|
|
214
|
+
day: "numeric",
|
|
215
|
+
hour: "2-digit",
|
|
216
|
+
minute: "2-digit"
|
|
217
|
+
}).format(date);
|
|
218
|
+
};
|
|
219
|
+
const getPickupStatus = () => {
|
|
220
|
+
const now = /* @__PURE__ */ new Date();
|
|
221
|
+
const pickupDate = pickupBooking ? new Date(pickupBooking.pickup_datetime) : null;
|
|
222
|
+
if (!pickupDate) return { label: "N/A", color: "grey" };
|
|
223
|
+
if (order.status === "completed" || order.status === "delivered") {
|
|
224
|
+
return { label: "รับสินค้าแล้ว", color: "green" };
|
|
225
|
+
}
|
|
226
|
+
if (order.status === "canceled") {
|
|
227
|
+
return { label: "ยกเลิก", color: "red" };
|
|
228
|
+
}
|
|
229
|
+
if (now > pickupDate) {
|
|
230
|
+
return { label: "เลยกำหนดรับ", color: "orange" };
|
|
231
|
+
}
|
|
232
|
+
return { label: "รอรับสินค้า", color: "blue" };
|
|
233
|
+
};
|
|
234
|
+
if (loading) {
|
|
235
|
+
return /* @__PURE__ */ jsxs(Container$1, { className: "divide-y p-0", children: [
|
|
236
|
+
/* @__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: [
|
|
237
|
+
/* @__PURE__ */ jsx(Calendar, { className: "text-ui-fg-subtle" }),
|
|
238
|
+
/* @__PURE__ */ jsx(Heading$1, { level: "h2", children: "การจองรับสินค้า" })
|
|
239
|
+
] }) }),
|
|
240
|
+
/* @__PURE__ */ jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsx(Text$1, { className: "text-ui-fg-subtle", children: "กำลังโหลด..." }) })
|
|
241
|
+
] });
|
|
242
|
+
}
|
|
243
|
+
if (error) {
|
|
244
|
+
return /* @__PURE__ */ jsxs(Container$1, { className: "divide-y p-0", children: [
|
|
245
|
+
/* @__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: [
|
|
246
|
+
/* @__PURE__ */ jsx(Calendar, { className: "text-ui-fg-subtle" }),
|
|
247
|
+
/* @__PURE__ */ jsx(Heading$1, { level: "h2", children: "การจองรับสินค้า" })
|
|
248
|
+
] }) }),
|
|
249
|
+
/* @__PURE__ */ jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsx(Text$1, { className: "text-red-500", children: error }) })
|
|
250
|
+
] });
|
|
251
|
+
}
|
|
252
|
+
if (!pickupBooking) {
|
|
253
|
+
return /* @__PURE__ */ jsxs(Container$1, { className: "divide-y p-0", children: [
|
|
254
|
+
/* @__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: [
|
|
255
|
+
/* @__PURE__ */ jsx(Calendar, { className: "text-ui-fg-subtle" }),
|
|
256
|
+
/* @__PURE__ */ jsx(Heading$1, { level: "h2", children: "การจองรับสินค้า" })
|
|
257
|
+
] }) }),
|
|
258
|
+
/* @__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: [
|
|
259
|
+
/* @__PURE__ */ jsx(MapPin, { className: "text-ui-fg-muted mb-4", size: 48 }),
|
|
260
|
+
/* @__PURE__ */ jsx(Text$1, { className: "text-ui-fg-subtle", children: "คำสั่งซื้อนี้ไม่ได้จองรับสินค้าที่สาขา" }),
|
|
261
|
+
/* @__PURE__ */ jsx(Text$1, { size: "xsmall", className: "text-ui-fg-muted mt-2", children: "คำสั่งซื้อนี้อาจเป็นการจัดส่งแบบปกติ" })
|
|
262
|
+
] }) })
|
|
263
|
+
] });
|
|
264
|
+
}
|
|
265
|
+
const status = getPickupStatus();
|
|
266
|
+
return /* @__PURE__ */ jsxs(Container$1, { className: "divide-y p-0", children: [
|
|
267
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between px-6 py-4", children: [
|
|
268
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
|
|
269
|
+
/* @__PURE__ */ jsx(Calendar, { className: "text-ui-fg-subtle" }),
|
|
270
|
+
/* @__PURE__ */ jsx(Heading$1, { level: "h2", children: "การจองรับสินค้าที่สาขา" }),
|
|
271
|
+
/* @__PURE__ */ jsx(Badge$1, { color: status.color, size: "small", children: status.label })
|
|
272
|
+
] }),
|
|
273
|
+
/* @__PURE__ */ jsx(
|
|
274
|
+
Button$1,
|
|
275
|
+
{
|
|
276
|
+
size: "small",
|
|
277
|
+
variant: "transparent",
|
|
278
|
+
onClick: () => {
|
|
279
|
+
fetchPickupBooking();
|
|
280
|
+
toast.success("รีเฟรชข้อมูลแล้ว");
|
|
281
|
+
},
|
|
282
|
+
children: /* @__PURE__ */ jsx(RefreshCw, { size: 16 })
|
|
283
|
+
}
|
|
284
|
+
)
|
|
285
|
+
] }),
|
|
286
|
+
/* @__PURE__ */ jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
287
|
+
/* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
|
|
288
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
289
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-ui-fg-subtle", children: [
|
|
290
|
+
/* @__PURE__ */ jsx(Calendar, { size: 16 }),
|
|
291
|
+
/* @__PURE__ */ jsx(Text$1, { size: "xsmall", weight: "plus", children: "วันที่รับสินค้า" })
|
|
292
|
+
] }),
|
|
293
|
+
/* @__PURE__ */ jsx(Text$1, { weight: "plus", children: formatDate(pickupBooking.pickup_datetime) })
|
|
294
|
+
] }),
|
|
295
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
296
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-ui-fg-subtle", children: [
|
|
297
|
+
/* @__PURE__ */ jsx(Clock, { size: 16 }),
|
|
298
|
+
/* @__PURE__ */ jsx(Text$1, { size: "xsmall", weight: "plus", children: "เวลารับสินค้า" })
|
|
299
|
+
] }),
|
|
300
|
+
/* @__PURE__ */ jsx(Text$1, { weight: "plus", children: formatTime(pickupBooking.pickup_datetime) })
|
|
301
|
+
] })
|
|
302
|
+
] }),
|
|
303
|
+
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: [
|
|
304
|
+
/* @__PURE__ */ jsx(MapPin, { className: "text-ui-fg-muted mt-1", size: 16 }),
|
|
305
|
+
/* @__PURE__ */ jsxs("div", { className: "flex-1", children: [
|
|
306
|
+
/* @__PURE__ */ jsx(Text$1, { weight: "plus", size: "small", className: "mb-1", children: pickupBooking.shipping_option.name }),
|
|
307
|
+
((_b = (_a = pickupBooking.shipping_option.service_zone) == null ? void 0 : _a.fulfillment_set) == null ? void 0 : _b.location) && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
308
|
+
/* @__PURE__ */ jsx(Text$1, { size: "small", className: "text-ui-fg-subtle", children: pickupBooking.shipping_option.service_zone.fulfillment_set.location.name }),
|
|
309
|
+
pickupBooking.shipping_option.service_zone.fulfillment_set.location.address && /* @__PURE__ */ jsxs(Text$1, { size: "xsmall", className: "text-ui-fg-muted mt-1", children: [
|
|
310
|
+
pickupBooking.shipping_option.service_zone.fulfillment_set.location.address.address_1,
|
|
311
|
+
pickupBooking.shipping_option.service_zone.fulfillment_set.location.address.address_2 && `, ${pickupBooking.shipping_option.service_zone.fulfillment_set.location.address.address_2}`,
|
|
312
|
+
/* @__PURE__ */ jsx("br", {}),
|
|
313
|
+
pickupBooking.shipping_option.service_zone.fulfillment_set.location.address.city,
|
|
314
|
+
" ",
|
|
315
|
+
pickupBooking.shipping_option.service_zone.fulfillment_set.location.address.province,
|
|
316
|
+
" ",
|
|
317
|
+
pickupBooking.shipping_option.service_zone.fulfillment_set.location.address.postal_code
|
|
318
|
+
] })
|
|
319
|
+
] })
|
|
320
|
+
] })
|
|
321
|
+
] }) }),
|
|
322
|
+
/* @__PURE__ */ jsx("div", { className: "pt-4 border-t", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
|
|
323
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
324
|
+
/* @__PURE__ */ jsx(Text$1, { size: "xsmall", className: "text-ui-fg-subtle", children: "จองเมื่อ" }),
|
|
325
|
+
/* @__PURE__ */ jsx(Text$1, { size: "small", children: formatDateTime(pickupBooking.created_at) })
|
|
326
|
+
] }),
|
|
327
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
328
|
+
/* @__PURE__ */ jsx(Text$1, { size: "xsmall", className: "text-ui-fg-subtle", children: "อัปเดตล่าสุด" }),
|
|
329
|
+
/* @__PURE__ */ jsx(Text$1, { size: "small", children: formatDateTime(pickupBooking.updated_at) })
|
|
330
|
+
] })
|
|
331
|
+
] }) }),
|
|
332
|
+
/* @__PURE__ */ jsx("div", { className: "pt-4 border-t", children: /* @__PURE__ */ jsxs(Text$1, { size: "xsmall", className: "text-ui-fg-muted", children: [
|
|
333
|
+
"Booking ID: ",
|
|
334
|
+
pickupBooking.id
|
|
335
|
+
] }) })
|
|
336
|
+
] }) })
|
|
337
|
+
] });
|
|
338
|
+
};
|
|
339
|
+
defineWidgetConfig$1({
|
|
340
|
+
zone: "order.details.after"
|
|
341
|
+
});
|
|
342
|
+
const sdk = new Medusa({
|
|
343
|
+
baseUrl: "/",
|
|
344
|
+
debug: false,
|
|
345
|
+
auth: {
|
|
346
|
+
type: "session"
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
const usePickupShippingOptions = () => {
|
|
350
|
+
const [data, setData] = useState(
|
|
351
|
+
null
|
|
352
|
+
);
|
|
353
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
354
|
+
const [error, setError] = useState(null);
|
|
355
|
+
const fetchOptions = async () => {
|
|
356
|
+
setIsLoading(true);
|
|
357
|
+
setError(null);
|
|
358
|
+
try {
|
|
359
|
+
const options = await sdk.admin.shippingOption.list({
|
|
360
|
+
fields: [
|
|
361
|
+
"id",
|
|
362
|
+
"name",
|
|
363
|
+
"shipping_profile.*",
|
|
364
|
+
"service_zone.*",
|
|
365
|
+
"service_zone.fulfillment_set.*"
|
|
366
|
+
].join(",")
|
|
367
|
+
});
|
|
368
|
+
const filteredOptions = (options.shipping_options ?? []).filter(
|
|
369
|
+
(option) => {
|
|
370
|
+
var _a, _b;
|
|
371
|
+
return ((_b = (_a = option == null ? void 0 : option.service_zone) == null ? void 0 : _a.fulfillment_set) == null ? void 0 : _b.type) === "pickup";
|
|
372
|
+
}
|
|
373
|
+
);
|
|
374
|
+
setData({
|
|
375
|
+
shipping_options: filteredOptions,
|
|
376
|
+
count: filteredOptions.length,
|
|
377
|
+
limit: options.limit,
|
|
378
|
+
offset: options.offset
|
|
379
|
+
});
|
|
380
|
+
} catch (err) {
|
|
381
|
+
setError(
|
|
382
|
+
err instanceof Error ? err : new Error("Failed to fetch pickup shipping options")
|
|
383
|
+
);
|
|
384
|
+
} finally {
|
|
385
|
+
setIsLoading(false);
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
useEffect(() => {
|
|
389
|
+
fetchOptions();
|
|
390
|
+
}, []);
|
|
391
|
+
return {
|
|
392
|
+
data,
|
|
393
|
+
isLoading,
|
|
394
|
+
error,
|
|
395
|
+
refetch: fetchOptions
|
|
396
|
+
};
|
|
397
|
+
};
|
|
398
|
+
const columnHelper = createDataTableColumnHelper();
|
|
399
|
+
const columns = [
|
|
400
|
+
columnHelper.accessor("shipping_profile.name", {
|
|
401
|
+
header: "Shipping Profile"
|
|
402
|
+
}),
|
|
403
|
+
columnHelper.accessor("service_zone.name", {
|
|
404
|
+
header: "Service Zone"
|
|
405
|
+
}),
|
|
406
|
+
columnHelper.accessor("name", {
|
|
407
|
+
header: "Pickup name"
|
|
408
|
+
}),
|
|
409
|
+
columnHelper.accessor("service_zone.fulfillment_set.name", {
|
|
410
|
+
header: "Fulfillment name"
|
|
411
|
+
})
|
|
412
|
+
];
|
|
413
|
+
const ShippingOptionList = () => {
|
|
414
|
+
const navigate = useNavigate();
|
|
415
|
+
const [pagination, setPagination] = useState({
|
|
416
|
+
pageSize: 1e3,
|
|
417
|
+
pageIndex: 0
|
|
418
|
+
});
|
|
419
|
+
const { data, isLoading } = usePickupShippingOptions();
|
|
420
|
+
const table = useDataTable({
|
|
421
|
+
columns,
|
|
422
|
+
data: (data == null ? void 0 : data.shipping_options) || [],
|
|
423
|
+
getRowId: (tier) => tier.id,
|
|
424
|
+
rowCount: (data == null ? void 0 : data.count) || 0,
|
|
425
|
+
isLoading,
|
|
426
|
+
pagination: {
|
|
427
|
+
state: pagination,
|
|
428
|
+
onPaginationChange: setPagination
|
|
429
|
+
},
|
|
430
|
+
onRowClick: (_, row) => {
|
|
431
|
+
navigate(`/pickup-shipping/${row.id}`);
|
|
432
|
+
}
|
|
433
|
+
});
|
|
434
|
+
return /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(Container$1, { className: "flex flex-col p-0 overflow-hidden", children: /* @__PURE__ */ jsxs(DataTable, { instance: table, children: [
|
|
435
|
+
/* @__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" }) }),
|
|
436
|
+
/* @__PURE__ */ jsx(DataTable.Table, {})
|
|
437
|
+
] }) }) });
|
|
438
|
+
};
|
|
439
|
+
const PickupShipping = () => {
|
|
440
|
+
return /* @__PURE__ */ jsx(ShippingOptionList, {});
|
|
441
|
+
};
|
|
442
|
+
const config = defineRouteConfig({
|
|
443
|
+
label: "Shipping Pickup",
|
|
444
|
+
icon: StackPerspective
|
|
445
|
+
});
|
|
446
|
+
const usePickupAvailable = (id) => {
|
|
447
|
+
const [data, setData] = useState(null);
|
|
448
|
+
const [isLoading, setIsLoading] = useState(true);
|
|
449
|
+
const [error, setError] = useState(null);
|
|
450
|
+
const fetchPickupAvailable = async () => {
|
|
451
|
+
if (!id) {
|
|
452
|
+
setError(new Error("id is required"));
|
|
453
|
+
setIsLoading(false);
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
setIsLoading(true);
|
|
457
|
+
setError(null);
|
|
458
|
+
try {
|
|
459
|
+
const option = await sdk.admin.shippingOption.retrieve(id, {
|
|
460
|
+
fields: "*.*,pickup_availabilities.*"
|
|
461
|
+
});
|
|
462
|
+
if (option.shipping_option.service_zone.fulfillment_set.type !== "pickup") {
|
|
463
|
+
throw new Error("shipping option is not pickup");
|
|
464
|
+
}
|
|
465
|
+
setData(option);
|
|
466
|
+
} catch (err) {
|
|
467
|
+
setError(
|
|
468
|
+
err instanceof Error ? err : new Error("Failed to fetch pickup availability")
|
|
469
|
+
);
|
|
470
|
+
} finally {
|
|
471
|
+
setIsLoading(false);
|
|
472
|
+
}
|
|
473
|
+
};
|
|
474
|
+
useEffect(() => {
|
|
475
|
+
fetchPickupAvailable();
|
|
476
|
+
}, [id]);
|
|
477
|
+
return {
|
|
478
|
+
data,
|
|
479
|
+
isLoading,
|
|
480
|
+
error,
|
|
481
|
+
refetch: fetchPickupAvailable
|
|
482
|
+
};
|
|
483
|
+
};
|
|
484
|
+
const stringToMinutes = (time, defaultValue) => {
|
|
485
|
+
if (!time) return defaultValue;
|
|
486
|
+
const [hours, minutes] = time.split(":");
|
|
487
|
+
return parseInt(hours) * 60 + parseInt(minutes);
|
|
488
|
+
};
|
|
489
|
+
const minutesToString = (minutes) => {
|
|
490
|
+
const hours = Math.floor(minutes / 60);
|
|
491
|
+
const remainingMinutes = minutes % 60;
|
|
492
|
+
return `${hours.toString().padStart(2, "0")}:${remainingMinutes.toString().padStart(2, "0")}`;
|
|
493
|
+
};
|
|
494
|
+
const dateToString = (date) => {
|
|
495
|
+
if (typeof date === "string") {
|
|
496
|
+
date = new Date(date);
|
|
497
|
+
}
|
|
498
|
+
const hours = date.getHours();
|
|
499
|
+
const minutes = date.getMinutes();
|
|
500
|
+
return `${hours.toString().padStart(2, "0")}:${minutes.toString().padStart(2, "0")}`;
|
|
501
|
+
};
|
|
502
|
+
const TimeSelect = ({
|
|
503
|
+
className,
|
|
504
|
+
intervalMinutes,
|
|
505
|
+
defaultValue,
|
|
506
|
+
onChange,
|
|
507
|
+
minTime,
|
|
508
|
+
maxTime
|
|
509
|
+
}) => {
|
|
510
|
+
const minTimeMinutes = stringToMinutes(minTime, 0);
|
|
511
|
+
const maxTimeMinutes = stringToMinutes(maxTime, 24 * 60);
|
|
512
|
+
const times = useMemo(() => {
|
|
513
|
+
const times2 = [];
|
|
514
|
+
for (let i = minTimeMinutes; i <= maxTimeMinutes; i += intervalMinutes) {
|
|
515
|
+
times2.push(minutesToString(i));
|
|
516
|
+
}
|
|
517
|
+
return times2;
|
|
518
|
+
}, [minTimeMinutes, maxTimeMinutes, intervalMinutes]);
|
|
519
|
+
return /* @__PURE__ */ jsxs(Select, { onValueChange: onChange, defaultValue, children: [
|
|
520
|
+
/* @__PURE__ */ jsx(Select.Trigger, { className: clx("w-24", className), children: /* @__PURE__ */ jsx(Select.Value, { placeholder: "Select a time" }) }),
|
|
521
|
+
/* @__PURE__ */ jsx(Select.Content, { children: times.map((time) => /* @__PURE__ */ jsx(Select.Item, { value: time, children: time }, time)) })
|
|
522
|
+
] });
|
|
523
|
+
};
|
|
524
|
+
function TimeTable({
|
|
525
|
+
schedule,
|
|
526
|
+
intervalMinutes = 30
|
|
527
|
+
}) {
|
|
528
|
+
const days = [
|
|
529
|
+
"monday",
|
|
530
|
+
"tuesday",
|
|
531
|
+
"wednesday",
|
|
532
|
+
"thursday",
|
|
533
|
+
"friday",
|
|
534
|
+
"saturday",
|
|
535
|
+
"sunday"
|
|
536
|
+
];
|
|
537
|
+
const timeSlots = useMemo(() => {
|
|
538
|
+
const minTimeMinutes = Math.min(
|
|
539
|
+
...Object.values(schedule).filter((d) => d.enabled).map((d) => d.timeSlots.map((s) => stringToMinutes(s.start, 0))).flat()
|
|
540
|
+
);
|
|
541
|
+
const maxTimeMinutes = Math.max(
|
|
542
|
+
...Object.values(schedule).filter((d) => d.enabled).map((d) => d.timeSlots.map((s) => stringToMinutes(s.end, 24 * 60))).flat()
|
|
543
|
+
);
|
|
544
|
+
const slots = [];
|
|
545
|
+
for (let i = Math.max(minTimeMinutes - 2 * intervalMinutes, 0); i <= Math.min(maxTimeMinutes + 2 * intervalMinutes, 24 * 60); i += intervalMinutes) {
|
|
546
|
+
slots.push(minutesToString(i));
|
|
547
|
+
}
|
|
548
|
+
return slots;
|
|
549
|
+
}, [schedule, intervalMinutes]);
|
|
550
|
+
const isWorkingHour = (day, timeSlot) => {
|
|
551
|
+
var _a;
|
|
552
|
+
if (!((_a = schedule[day]) == null ? void 0 : _a.enabled)) return false;
|
|
553
|
+
const [hours, minutes] = timeSlot.split(":");
|
|
554
|
+
const timeInMinutes = Number(hours) * 60 + Number(minutes);
|
|
555
|
+
return schedule[day].timeSlots.some((slot) => {
|
|
556
|
+
const startMatch = slot.start.match(/(\d+):(\d+)/);
|
|
557
|
+
if (!startMatch) return false;
|
|
558
|
+
let startHour = Number(startMatch[1]);
|
|
559
|
+
const startMinute = Number(startMatch[2]);
|
|
560
|
+
const startInMinutes = startHour * 60 + startMinute;
|
|
561
|
+
const endMatch = slot.end.match(/(\d+):(\d+)/);
|
|
562
|
+
if (!endMatch) return false;
|
|
563
|
+
let endHour = Number(endMatch[1]);
|
|
564
|
+
const endMinute = Number(endMatch[2]);
|
|
565
|
+
const endInMinutes = endHour * 60 + endMinute;
|
|
566
|
+
return timeInMinutes >= startInMinutes && timeInMinutes < endInMinutes;
|
|
567
|
+
});
|
|
568
|
+
};
|
|
569
|
+
if (timeSlots.length === 0) return null;
|
|
570
|
+
return /* @__PURE__ */ jsxs(Container$1, { className: "p-4 overflow-x-auto", children: [
|
|
571
|
+
/* @__PURE__ */ jsx(Heading$1, { className: "text-xl font-bold mb-4", children: "Pickup Hours Schedule" }),
|
|
572
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-full flex", children: [
|
|
573
|
+
/* @__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)) }),
|
|
574
|
+
/* @__PURE__ */ jsxs("table", { className: "ml-2 w-full border-collapse", children: [
|
|
575
|
+
/* @__PURE__ */ jsx("thead", { children: /* @__PURE__ */ jsx("tr", { children: days.map((day) => /* @__PURE__ */ jsx(
|
|
576
|
+
"th",
|
|
577
|
+
{
|
|
578
|
+
className: "py-2 px-4 border-b border-gray-800 text-center capitalize",
|
|
579
|
+
children: day.slice(0, 3)
|
|
580
|
+
},
|
|
581
|
+
day
|
|
582
|
+
)) }) }),
|
|
583
|
+
/* @__PURE__ */ jsx("tbody", { children: timeSlots.map((timeSlot) => /* @__PURE__ */ jsx("tr", { className: "hover:bg-ui-bg-base-hover", children: days.map((day) => /* @__PURE__ */ jsx(
|
|
584
|
+
"td",
|
|
585
|
+
{
|
|
586
|
+
className: clx(
|
|
587
|
+
`py-1 px-4 border-b border-gray-800 text-center h-8`,
|
|
588
|
+
isWorkingHour(day, timeSlot) && "bg-ui-bg-interactive"
|
|
589
|
+
),
|
|
590
|
+
children: ""
|
|
591
|
+
},
|
|
592
|
+
`${day}-${timeSlot}`
|
|
593
|
+
)) }, timeSlot)) })
|
|
594
|
+
] })
|
|
595
|
+
] })
|
|
596
|
+
] });
|
|
597
|
+
}
|
|
598
|
+
const INTERVAL_MINUTES = 30;
|
|
599
|
+
const DEFAULT_SCHEDULE = {
|
|
600
|
+
monday: {
|
|
601
|
+
enabled: false,
|
|
602
|
+
timeSlots: []
|
|
603
|
+
},
|
|
604
|
+
tuesday: {
|
|
605
|
+
enabled: false,
|
|
606
|
+
timeSlots: []
|
|
607
|
+
},
|
|
608
|
+
wednesday: {
|
|
609
|
+
enabled: false,
|
|
610
|
+
timeSlots: []
|
|
611
|
+
},
|
|
612
|
+
thursday: {
|
|
613
|
+
enabled: false,
|
|
614
|
+
timeSlots: []
|
|
615
|
+
},
|
|
616
|
+
friday: {
|
|
617
|
+
enabled: false,
|
|
618
|
+
timeSlots: []
|
|
619
|
+
},
|
|
620
|
+
saturday: {
|
|
621
|
+
enabled: false,
|
|
622
|
+
timeSlots: []
|
|
623
|
+
},
|
|
624
|
+
sunday: { enabled: false, timeSlots: [] }
|
|
625
|
+
};
|
|
626
|
+
function ShippingOptionDetails() {
|
|
627
|
+
const { id } = useParams();
|
|
628
|
+
const navigate = useNavigate();
|
|
629
|
+
const sdk2 = useSdk();
|
|
630
|
+
const [schedule, setSchedule] = useState(
|
|
631
|
+
structuredClone(DEFAULT_SCHEDULE)
|
|
632
|
+
);
|
|
633
|
+
const { data, refetch, error } = usePickupAvailable(id);
|
|
634
|
+
useEffect(() => {
|
|
635
|
+
if (!data) return;
|
|
636
|
+
const _schedule = structuredClone(DEFAULT_SCHEDULE);
|
|
637
|
+
data.shipping_option.pickup_availabilities.forEach((availability) => {
|
|
638
|
+
const timeSlots = _schedule[availability.day_of_week].timeSlots;
|
|
639
|
+
timeSlots.push({
|
|
640
|
+
start: dateToString(availability.timeStart),
|
|
641
|
+
end: dateToString(availability.timeEnd)
|
|
642
|
+
});
|
|
643
|
+
_schedule[availability.day_of_week] = {
|
|
644
|
+
enabled: availability.enable,
|
|
645
|
+
timeSlots
|
|
646
|
+
};
|
|
647
|
+
});
|
|
648
|
+
setSchedule({ ..._schedule });
|
|
649
|
+
}, [data]);
|
|
650
|
+
const toggleDay = useCallback((day) => {
|
|
651
|
+
setSchedule((prev) => ({
|
|
652
|
+
...prev,
|
|
653
|
+
[day]: {
|
|
654
|
+
...prev[day],
|
|
655
|
+
enabled: !prev[day].enabled
|
|
656
|
+
}
|
|
657
|
+
}));
|
|
658
|
+
}, []);
|
|
659
|
+
const handleUpdateSchedules = async () => {
|
|
660
|
+
const invalidSchedules = Object.entries(schedule).filter(
|
|
661
|
+
([_, schedule2]) => {
|
|
662
|
+
if (!schedule2.enabled) return false;
|
|
663
|
+
return schedule2.timeSlots.filter((slot) => {
|
|
664
|
+
if (!slot.start || !slot.end) {
|
|
665
|
+
return true;
|
|
666
|
+
}
|
|
667
|
+
}).length > 0;
|
|
668
|
+
}
|
|
669
|
+
);
|
|
670
|
+
if (invalidSchedules.length > 0) {
|
|
671
|
+
toast.error("Invalid time slot", {
|
|
672
|
+
description: "Please fill in all time slots",
|
|
673
|
+
duration: 2500,
|
|
674
|
+
dismissable: true
|
|
675
|
+
});
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
678
|
+
try {
|
|
679
|
+
await sdk2.client.fetch(`/admin/pickup-date/${id}`, {
|
|
680
|
+
method: "POST",
|
|
681
|
+
headers: {
|
|
682
|
+
"Content-Type": "application/json"
|
|
683
|
+
},
|
|
684
|
+
body: JSON.stringify({
|
|
685
|
+
schedules: Object.entries(schedule).filter(([_, daySchedule]) => daySchedule.enabled).map(([day, { enabled, timeSlots }]) => ({
|
|
686
|
+
day_of_week: day,
|
|
687
|
+
enable: enabled,
|
|
688
|
+
timeSlots: timeSlots.map((slot) => ({
|
|
689
|
+
start: slot.start,
|
|
690
|
+
end: slot.end
|
|
691
|
+
}))
|
|
692
|
+
}))
|
|
693
|
+
})
|
|
694
|
+
});
|
|
695
|
+
refetch();
|
|
696
|
+
toast.success("Availability updated", {
|
|
697
|
+
duration: 2500,
|
|
698
|
+
dismissable: true
|
|
699
|
+
});
|
|
700
|
+
} catch (error2) {
|
|
701
|
+
if (error2 instanceof Error) {
|
|
702
|
+
toast.error(error2.message, {
|
|
703
|
+
duration: 2500,
|
|
704
|
+
dismissable: true
|
|
705
|
+
});
|
|
706
|
+
return;
|
|
707
|
+
}
|
|
708
|
+
toast.error("Error while creating availability", {
|
|
709
|
+
duration: 2500,
|
|
710
|
+
dismissable: true
|
|
711
|
+
});
|
|
712
|
+
}
|
|
713
|
+
};
|
|
714
|
+
const updateTimeSlot = useCallback(
|
|
715
|
+
(day, index, field, value) => {
|
|
716
|
+
setSchedule((prev) => {
|
|
717
|
+
const newTimeSlots = [...prev[day].timeSlots];
|
|
718
|
+
newTimeSlots[index] = {
|
|
719
|
+
...newTimeSlots[index],
|
|
720
|
+
[field]: value
|
|
721
|
+
};
|
|
722
|
+
return {
|
|
723
|
+
...prev,
|
|
724
|
+
[day]: {
|
|
725
|
+
...prev[day],
|
|
726
|
+
timeSlots: newTimeSlots
|
|
727
|
+
}
|
|
728
|
+
};
|
|
729
|
+
});
|
|
730
|
+
},
|
|
731
|
+
[]
|
|
732
|
+
);
|
|
733
|
+
const addTimeSlot = useCallback((day) => {
|
|
734
|
+
setSchedule((prev) => {
|
|
735
|
+
const newTimeSlots = [...prev[day].timeSlots];
|
|
736
|
+
newTimeSlots.push({ start: "", end: "" });
|
|
737
|
+
return {
|
|
738
|
+
...prev,
|
|
739
|
+
[day]: {
|
|
740
|
+
...prev[day],
|
|
741
|
+
timeSlots: newTimeSlots
|
|
742
|
+
}
|
|
743
|
+
};
|
|
744
|
+
});
|
|
745
|
+
}, []);
|
|
746
|
+
const removeTimeSlot = useCallback((day, index) => {
|
|
747
|
+
setSchedule((prev) => {
|
|
748
|
+
const newTimeSlots = [...prev[day].timeSlots];
|
|
749
|
+
newTimeSlots.splice(index, 1);
|
|
750
|
+
return {
|
|
751
|
+
...prev,
|
|
752
|
+
[day]: {
|
|
753
|
+
...prev[day],
|
|
754
|
+
timeSlots: newTimeSlots
|
|
755
|
+
}
|
|
756
|
+
};
|
|
757
|
+
});
|
|
758
|
+
}, []);
|
|
759
|
+
if (error) {
|
|
760
|
+
return /* @__PURE__ */ jsx(Navigate, { to: "/pickup-shipping" });
|
|
761
|
+
}
|
|
762
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
763
|
+
/* @__PURE__ */ jsxs(Container$1, { className: "p-4 ", children: [
|
|
764
|
+
/* @__PURE__ */ jsxs(
|
|
765
|
+
Button$1,
|
|
766
|
+
{
|
|
767
|
+
onClick: () => navigate("/pickup-shipping"),
|
|
768
|
+
variant: "transparent",
|
|
769
|
+
className: "p-0 mb-4",
|
|
770
|
+
children: [
|
|
771
|
+
/* @__PURE__ */ jsx(ArrowLeft, { size: 20 }),
|
|
772
|
+
/* @__PURE__ */ jsx(Text$1, { className: "ml-2", children: "Back" })
|
|
773
|
+
]
|
|
774
|
+
}
|
|
775
|
+
),
|
|
776
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4 mb-4", children: [
|
|
777
|
+
/* @__PURE__ */ jsx(Heading$1, { className: "text-xl font-bold", children: "Pickup Hours" }),
|
|
778
|
+
/* @__PURE__ */ jsx(Button$1, { onClick: handleUpdateSchedules, children: "Save" })
|
|
779
|
+
] }),
|
|
780
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-4", children: Object.entries(schedule).map(([day, { enabled, timeSlots }]) => /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
781
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4 mb-2 h-8", children: [
|
|
782
|
+
/* @__PURE__ */ jsx(
|
|
783
|
+
Switch,
|
|
784
|
+
{
|
|
785
|
+
checked: enabled,
|
|
786
|
+
onCheckedChange: () => toggleDay(day)
|
|
787
|
+
},
|
|
788
|
+
`switch-${day}`
|
|
789
|
+
),
|
|
790
|
+
/* @__PURE__ */ jsx(Text$1, { className: "capitalize", children: day }),
|
|
791
|
+
enabled && /* @__PURE__ */ jsx(
|
|
792
|
+
IconButton,
|
|
793
|
+
{
|
|
794
|
+
variant: "transparent",
|
|
795
|
+
onClick: () => addTimeSlot(day),
|
|
796
|
+
children: /* @__PURE__ */ jsx(Plus, { className: "" })
|
|
797
|
+
}
|
|
798
|
+
)
|
|
799
|
+
] }),
|
|
800
|
+
enabled && /* @__PURE__ */ jsx("div", { className: "ml-12 space-y-2", children: timeSlots.map((slot, index) => /* @__PURE__ */ jsxs(
|
|
801
|
+
"div",
|
|
802
|
+
{
|
|
803
|
+
className: "flex items-center gap-2",
|
|
804
|
+
children: [
|
|
805
|
+
/* @__PURE__ */ jsx(
|
|
806
|
+
TimeSelect,
|
|
807
|
+
{
|
|
808
|
+
className: "w-40",
|
|
809
|
+
intervalMinutes: INTERVAL_MINUTES,
|
|
810
|
+
defaultValue: slot.start,
|
|
811
|
+
onChange: (value) => updateTimeSlot(day, index, "start", value),
|
|
812
|
+
maxTime: slot.end
|
|
813
|
+
}
|
|
814
|
+
),
|
|
815
|
+
/* @__PURE__ */ jsx(Text$1, { className: "text-gray-400", children: "-" }),
|
|
816
|
+
/* @__PURE__ */ jsx(
|
|
817
|
+
TimeSelect,
|
|
818
|
+
{
|
|
819
|
+
className: "w-40",
|
|
820
|
+
intervalMinutes: INTERVAL_MINUTES,
|
|
821
|
+
defaultValue: slot.end,
|
|
822
|
+
onChange: (value) => updateTimeSlot(day, index, "end", value),
|
|
823
|
+
minTime: slot.start
|
|
824
|
+
}
|
|
825
|
+
),
|
|
826
|
+
/* @__PURE__ */ jsx(
|
|
827
|
+
IconButton,
|
|
828
|
+
{
|
|
829
|
+
variant: "transparent",
|
|
830
|
+
onClick: () => removeTimeSlot(day, index),
|
|
831
|
+
className: " hover:text-red-400",
|
|
832
|
+
children: /* @__PURE__ */ jsx(Trash2, { className: "w-4 h-4" })
|
|
833
|
+
}
|
|
834
|
+
)
|
|
835
|
+
]
|
|
836
|
+
},
|
|
837
|
+
`${day}-slot-${index}`
|
|
838
|
+
)) })
|
|
839
|
+
] }, day)) })
|
|
840
|
+
] }),
|
|
841
|
+
/* @__PURE__ */ jsx("div", { className: "h-2" }),
|
|
842
|
+
/* @__PURE__ */ jsx(TimeTable, { schedule })
|
|
843
|
+
] });
|
|
844
|
+
}
|
|
845
|
+
const widgetModule = { widgets: [
|
|
846
|
+
{
|
|
847
|
+
Component: CustomerPickupHistoryWidget,
|
|
848
|
+
zone: ["customer.details.after"]
|
|
849
|
+
},
|
|
850
|
+
{
|
|
851
|
+
Component: OrderPickupBookingWidget,
|
|
852
|
+
zone: ["order.details.after"]
|
|
853
|
+
}
|
|
854
|
+
] };
|
|
855
|
+
const routeModule = {
|
|
856
|
+
routes: [
|
|
857
|
+
{
|
|
858
|
+
Component: PickupShipping,
|
|
859
|
+
path: "/pickup-shipping"
|
|
860
|
+
},
|
|
861
|
+
{
|
|
862
|
+
Component: ShippingOptionDetails,
|
|
863
|
+
path: "/pickup-shipping/:id"
|
|
864
|
+
}
|
|
865
|
+
]
|
|
866
|
+
};
|
|
867
|
+
const menuItemModule = {
|
|
868
|
+
menuItems: [
|
|
869
|
+
{
|
|
870
|
+
label: config.label,
|
|
871
|
+
icon: config.icon,
|
|
872
|
+
path: "/pickup-shipping",
|
|
873
|
+
nested: void 0
|
|
874
|
+
}
|
|
875
|
+
]
|
|
876
|
+
};
|
|
877
|
+
const formModule = { customFields: {} };
|
|
878
|
+
const displayModule = {
|
|
879
|
+
displays: {}
|
|
880
|
+
};
|
|
881
|
+
const i18nModule = { resources: {} };
|
|
882
|
+
const plugin = {
|
|
883
|
+
widgetModule,
|
|
884
|
+
routeModule,
|
|
885
|
+
menuItemModule,
|
|
886
|
+
formModule,
|
|
887
|
+
displayModule,
|
|
888
|
+
i18nModule
|
|
889
|
+
};
|
|
890
|
+
export {
|
|
891
|
+
plugin as default
|
|
892
|
+
};
|