@lodashventure/medusa-parcel-shipping 0.4.26 → 0.4.29
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.
|
@@ -236,6 +236,445 @@ const OrderShippingQuoteWidget = ({ data }) => {
|
|
|
236
236
|
adminSdk.defineWidgetConfig({
|
|
237
237
|
zone: "order.details.after"
|
|
238
238
|
});
|
|
239
|
+
const TH_PROVINCES = [
|
|
240
|
+
"กรุงเทพมหานคร",
|
|
241
|
+
"กระบี่",
|
|
242
|
+
"กาญจนบุรี",
|
|
243
|
+
"กาฬสินธุ์",
|
|
244
|
+
"กำแพงเพชร",
|
|
245
|
+
"ขอนแก่น",
|
|
246
|
+
"จันทบุรี",
|
|
247
|
+
"ฉะเชิงเทรา",
|
|
248
|
+
"ชลบุรี",
|
|
249
|
+
"ชัยนาท",
|
|
250
|
+
"ชัยภูมิ",
|
|
251
|
+
"ชุมพร",
|
|
252
|
+
"เชียงราย",
|
|
253
|
+
"เชียงใหม่",
|
|
254
|
+
"ตรัง",
|
|
255
|
+
"ตราด",
|
|
256
|
+
"ตาก",
|
|
257
|
+
"นครนายก",
|
|
258
|
+
"นครปฐม",
|
|
259
|
+
"นครพนม",
|
|
260
|
+
"นครราชสีมา",
|
|
261
|
+
"นครศรีธรรมราช",
|
|
262
|
+
"นครสวรรค์",
|
|
263
|
+
"นนทบุรี",
|
|
264
|
+
"นราธิวาส",
|
|
265
|
+
"น่าน",
|
|
266
|
+
"บึงกาฬ",
|
|
267
|
+
"บุรีรัมย์",
|
|
268
|
+
"ปทุมธานี",
|
|
269
|
+
"ประจวบคีรีขันธ์",
|
|
270
|
+
"ปราจีนบุรี",
|
|
271
|
+
"ปัตตานี",
|
|
272
|
+
"พระนครศรีอยุธยา",
|
|
273
|
+
"พะเยา",
|
|
274
|
+
"พังงา",
|
|
275
|
+
"พัทลุง",
|
|
276
|
+
"พิจิตร",
|
|
277
|
+
"พิษณุโลก",
|
|
278
|
+
"เพชรบุรี",
|
|
279
|
+
"เพชรบูรณ์",
|
|
280
|
+
"แพร่",
|
|
281
|
+
"ภูเก็ต",
|
|
282
|
+
"มหาสารคาม",
|
|
283
|
+
"มุกดาหาร",
|
|
284
|
+
"แม่ฮ่องสอน",
|
|
285
|
+
"ยโสธร",
|
|
286
|
+
"ยะลา",
|
|
287
|
+
"ร้อยเอ็ด",
|
|
288
|
+
"ระนอง",
|
|
289
|
+
"ระยอง",
|
|
290
|
+
"ราชบุรี",
|
|
291
|
+
"ลพบุรี",
|
|
292
|
+
"ลำปาง",
|
|
293
|
+
"ลำพูน",
|
|
294
|
+
"เลย",
|
|
295
|
+
"ศรีสะเกษ",
|
|
296
|
+
"สกลนคร",
|
|
297
|
+
"สงขลา",
|
|
298
|
+
"สตูล",
|
|
299
|
+
"สมุทรปราการ",
|
|
300
|
+
"สมุทรสงคราม",
|
|
301
|
+
"สมุทรสาคร",
|
|
302
|
+
"สระแก้ว",
|
|
303
|
+
"สระบุรี",
|
|
304
|
+
"สิงห์บุรี",
|
|
305
|
+
"สุโขทัย",
|
|
306
|
+
"สุพรรณบุรี",
|
|
307
|
+
"สุราษฎร์ธานี",
|
|
308
|
+
"สุรินทร์",
|
|
309
|
+
"หนองคาย",
|
|
310
|
+
"หนองบัวลำภู",
|
|
311
|
+
"อ่างทอง",
|
|
312
|
+
"อำนาจเจริญ",
|
|
313
|
+
"อุดรธานี",
|
|
314
|
+
"อุตรดิตถ์",
|
|
315
|
+
"อุทัยธานี",
|
|
316
|
+
"อุบลราชธานี"
|
|
317
|
+
];
|
|
318
|
+
const ServiceAreaModal = ({ area, onClose }) => {
|
|
319
|
+
const [formData, setFormData] = react.useState({
|
|
320
|
+
kind: "PROVINCE",
|
|
321
|
+
value: "",
|
|
322
|
+
active: true
|
|
323
|
+
});
|
|
324
|
+
const [isSaving, setIsSaving] = react.useState(false);
|
|
325
|
+
react.useEffect(() => {
|
|
326
|
+
if (area) {
|
|
327
|
+
setFormData({
|
|
328
|
+
kind: area.kind,
|
|
329
|
+
value: area.value,
|
|
330
|
+
active: area.active
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
}, [area]);
|
|
334
|
+
const handleSubmit = async (e) => {
|
|
335
|
+
e.preventDefault();
|
|
336
|
+
const errors = [];
|
|
337
|
+
const trimmedValue = formData.value.trim();
|
|
338
|
+
if (!trimmedValue) {
|
|
339
|
+
errors.push("กรุณากรอกค่า");
|
|
340
|
+
}
|
|
341
|
+
if (formData.kind === "PROVINCE") {
|
|
342
|
+
if (!TH_PROVINCES.includes(trimmedValue)) {
|
|
343
|
+
errors.push("จังหวัดไม่ถูกต้อง กรุณาตรวจสอบการสะกดชื่อจังหวัด");
|
|
344
|
+
}
|
|
345
|
+
} else if (formData.kind === "POSTCODE_PREFIX") {
|
|
346
|
+
if (!/^\d{1,5}$/.test(trimmedValue)) {
|
|
347
|
+
errors.push("รหัสไปรษณีย์ต้องเป็นตัวเลข 1-5 หลัก");
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
if (errors.length > 0) {
|
|
351
|
+
ui.toast.error("ข้อมูลไม่ถูกต้อง", {
|
|
352
|
+
description: errors.join(", ")
|
|
353
|
+
});
|
|
354
|
+
return;
|
|
355
|
+
}
|
|
356
|
+
setIsSaving(true);
|
|
357
|
+
try {
|
|
358
|
+
const payload = {
|
|
359
|
+
kind: formData.kind,
|
|
360
|
+
value: trimmedValue,
|
|
361
|
+
active: formData.active
|
|
362
|
+
};
|
|
363
|
+
const url = area ? `/admin/service-areas/${area.id}` : "/admin/service-areas";
|
|
364
|
+
const method = area ? "PUT" : "POST";
|
|
365
|
+
const response = await fetch(url, {
|
|
366
|
+
method,
|
|
367
|
+
headers: { "Content-Type": "application/json" },
|
|
368
|
+
credentials: "include",
|
|
369
|
+
body: JSON.stringify(payload)
|
|
370
|
+
});
|
|
371
|
+
if (response.ok) {
|
|
372
|
+
ui.toast.success("สำเร็จ", {
|
|
373
|
+
description: area ? "แก้ไขพื้นที่บริการแล้ว" : "สร้างพื้นที่บริการใหม่แล้ว"
|
|
374
|
+
});
|
|
375
|
+
onClose();
|
|
376
|
+
} else {
|
|
377
|
+
const error = await response.json();
|
|
378
|
+
throw new Error(error.message || "Failed to save");
|
|
379
|
+
}
|
|
380
|
+
} catch (error) {
|
|
381
|
+
ui.toast.error("ข้อผิดพลาด", {
|
|
382
|
+
description: error instanceof Error ? error.message : "ไม่สามารถบันทึกข้อมูลได้"
|
|
383
|
+
});
|
|
384
|
+
} finally {
|
|
385
|
+
setIsSaving(false);
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer, { open: true, onOpenChange: (open) => !open && onClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Drawer.Content, { children: [
|
|
389
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Title, { children: area ? "แก้ไขพื้นที่บริการ" : "สร้างพื้นที่บริการใหม่" }) }),
|
|
390
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, className: "flex flex-col gap-y-4", children: [
|
|
391
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
392
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "kind", children: "ประเภท *" }),
|
|
393
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
394
|
+
ui.Select,
|
|
395
|
+
{
|
|
396
|
+
value: formData.kind,
|
|
397
|
+
onValueChange: (value) => setFormData({ ...formData, kind: value, value: "" }),
|
|
398
|
+
required: true,
|
|
399
|
+
children: [
|
|
400
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, { placeholder: "เลือกประเภท" }) }),
|
|
401
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Select.Content, { children: [
|
|
402
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: "PROVINCE", children: "จังหวัด" }),
|
|
403
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: "POSTCODE_PREFIX", children: "รหัสไปรษณีย์" })
|
|
404
|
+
] })
|
|
405
|
+
]
|
|
406
|
+
}
|
|
407
|
+
)
|
|
408
|
+
] }),
|
|
409
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
410
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "value", children: formData.kind === "PROVINCE" ? "ชื่อจังหวัด *" : "รหัสไปรษณีย์ (1-5 หลัก) *" }),
|
|
411
|
+
formData.kind === "PROVINCE" ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
412
|
+
ui.Select,
|
|
413
|
+
{
|
|
414
|
+
value: formData.value,
|
|
415
|
+
onValueChange: (value) => setFormData({ ...formData, value }),
|
|
416
|
+
required: true,
|
|
417
|
+
children: [
|
|
418
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, { placeholder: "เลือกจังหวัด" }) }),
|
|
419
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Content, { children: TH_PROVINCES.map((province) => /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: province, children: province }, province)) })
|
|
420
|
+
]
|
|
421
|
+
}
|
|
422
|
+
) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
423
|
+
ui.Input,
|
|
424
|
+
{
|
|
425
|
+
id: "value",
|
|
426
|
+
type: "text",
|
|
427
|
+
value: formData.value,
|
|
428
|
+
onChange: (e) => setFormData({ ...formData, value: e.target.value }),
|
|
429
|
+
placeholder: "เช่น 10, 102, 10200",
|
|
430
|
+
maxLength: 5,
|
|
431
|
+
pattern: "\\d{1,5}",
|
|
432
|
+
required: true
|
|
433
|
+
}
|
|
434
|
+
),
|
|
435
|
+
formData.kind === "POSTCODE_PREFIX" && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-ui-fg-subtle mt-1", children: 'ใส่รหัส 1-5 หลักเพื่อครอบคลุมหลายพื้นที่ เช่น "10" = กรุงเทพฯ ทั้งหมด' })
|
|
436
|
+
] }),
|
|
437
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-2", children: [
|
|
438
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
439
|
+
ui.Switch,
|
|
440
|
+
{
|
|
441
|
+
id: "active",
|
|
442
|
+
checked: formData.active,
|
|
443
|
+
onCheckedChange: (checked) => setFormData({ ...formData, active: checked })
|
|
444
|
+
}
|
|
445
|
+
),
|
|
446
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "active", children: "เปิดใช้งาน" })
|
|
447
|
+
] }),
|
|
448
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Drawer.Footer, { children: [
|
|
449
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
450
|
+
ui.Button,
|
|
451
|
+
{
|
|
452
|
+
type: "button",
|
|
453
|
+
variant: "secondary",
|
|
454
|
+
onClick: onClose,
|
|
455
|
+
disabled: isSaving,
|
|
456
|
+
children: "ยกเลิก"
|
|
457
|
+
}
|
|
458
|
+
),
|
|
459
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { type: "submit", disabled: isSaving, children: isSaving ? "กำลังบันทึก..." : "บันทึก" })
|
|
460
|
+
] })
|
|
461
|
+
] }) })
|
|
462
|
+
] }) });
|
|
463
|
+
};
|
|
464
|
+
const AREA_KINDS = [
|
|
465
|
+
{ value: "ALL", label: "ทั้งหมด" },
|
|
466
|
+
{ value: "PROVINCE", label: "จังหวัด" },
|
|
467
|
+
{ value: "POSTCODE_PREFIX", label: "รหัสไปรษณีย์" }
|
|
468
|
+
];
|
|
469
|
+
const ServiceAreasTable = () => {
|
|
470
|
+
const [areas, setAreas] = react.useState([]);
|
|
471
|
+
const [filteredAreas, setFilteredAreas] = react.useState([]);
|
|
472
|
+
const [searchTerm, setSearchTerm] = react.useState("");
|
|
473
|
+
const [kindFilter, setKindFilter] = react.useState("ALL");
|
|
474
|
+
const [isModalOpen, setIsModalOpen] = react.useState(false);
|
|
475
|
+
const [editingArea, setEditingArea] = react.useState(null);
|
|
476
|
+
const [isLoading, setIsLoading] = react.useState(false);
|
|
477
|
+
const [deleteAreaId, setDeleteAreaId] = react.useState(null);
|
|
478
|
+
const [deleteAreaValue, setDeleteAreaValue] = react.useState("");
|
|
479
|
+
react.useEffect(() => {
|
|
480
|
+
fetchAreas();
|
|
481
|
+
}, []);
|
|
482
|
+
react.useEffect(() => {
|
|
483
|
+
let filtered = areas;
|
|
484
|
+
if (kindFilter !== "ALL") {
|
|
485
|
+
filtered = filtered.filter((area) => area.kind === kindFilter);
|
|
486
|
+
}
|
|
487
|
+
if (searchTerm) {
|
|
488
|
+
filtered = filtered.filter(
|
|
489
|
+
(area) => area.value.toLowerCase().includes(searchTerm.toLowerCase())
|
|
490
|
+
);
|
|
491
|
+
}
|
|
492
|
+
setFilteredAreas(filtered);
|
|
493
|
+
}, [searchTerm, kindFilter, areas]);
|
|
494
|
+
const fetchAreas = async () => {
|
|
495
|
+
setIsLoading(true);
|
|
496
|
+
try {
|
|
497
|
+
const response = await fetch("/admin/service-areas", {
|
|
498
|
+
credentials: "include"
|
|
499
|
+
});
|
|
500
|
+
const data = await response.json();
|
|
501
|
+
console.log("Fetched service areas:", data);
|
|
502
|
+
setAreas(data.service_areas || []);
|
|
503
|
+
} catch (error) {
|
|
504
|
+
ui.toast.error("ข้อผิดพลาด", {
|
|
505
|
+
description: "ไม่สามารถโหลดข้อมูลพื้นที่บริการได้"
|
|
506
|
+
});
|
|
507
|
+
} finally {
|
|
508
|
+
setIsLoading(false);
|
|
509
|
+
}
|
|
510
|
+
};
|
|
511
|
+
const handleToggleActive = async (area) => {
|
|
512
|
+
try {
|
|
513
|
+
const response = await fetch(`/admin/service-areas/${area.id}`, {
|
|
514
|
+
method: "PUT",
|
|
515
|
+
headers: { "Content-Type": "application/json" },
|
|
516
|
+
credentials: "include",
|
|
517
|
+
body: JSON.stringify({ ...area, active: !area.active })
|
|
518
|
+
});
|
|
519
|
+
if (response.ok) {
|
|
520
|
+
ui.toast.success("สำเร็จ", {
|
|
521
|
+
description: `${area.active ? "ปิดใช้งาน" : "เปิดใช้งาน"}พื้นที่ ${area.value} แล้ว`
|
|
522
|
+
});
|
|
523
|
+
fetchAreas();
|
|
524
|
+
} else {
|
|
525
|
+
throw new Error("Failed to update");
|
|
526
|
+
}
|
|
527
|
+
} catch (error) {
|
|
528
|
+
ui.toast.error("ข้อผิดพลาด", {
|
|
529
|
+
description: "ไม่สามารถอัพเดทสถานะได้"
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
};
|
|
533
|
+
const handleDelete = async () => {
|
|
534
|
+
if (!deleteAreaId) return;
|
|
535
|
+
try {
|
|
536
|
+
const response = await fetch(`/admin/service-areas/${deleteAreaId}`, {
|
|
537
|
+
method: "DELETE",
|
|
538
|
+
credentials: "include"
|
|
539
|
+
});
|
|
540
|
+
if (response.ok) {
|
|
541
|
+
ui.toast.success("สำเร็จ", {
|
|
542
|
+
description: `ลบพื้นที่ ${deleteAreaValue} แล้ว`
|
|
543
|
+
});
|
|
544
|
+
fetchAreas();
|
|
545
|
+
} else {
|
|
546
|
+
throw new Error("Failed to delete");
|
|
547
|
+
}
|
|
548
|
+
} catch (error) {
|
|
549
|
+
ui.toast.error("ข้อผิดพลาด", {
|
|
550
|
+
description: "ไม่สามารถลบพื้นที่ได้"
|
|
551
|
+
});
|
|
552
|
+
} finally {
|
|
553
|
+
setDeleteAreaId(null);
|
|
554
|
+
setDeleteAreaValue("");
|
|
555
|
+
}
|
|
556
|
+
};
|
|
557
|
+
const handleEdit = (area) => {
|
|
558
|
+
setEditingArea(area);
|
|
559
|
+
setIsModalOpen(true);
|
|
560
|
+
};
|
|
561
|
+
const handleCreateNew = () => {
|
|
562
|
+
setEditingArea(null);
|
|
563
|
+
setIsModalOpen(true);
|
|
564
|
+
};
|
|
565
|
+
const handleModalClose = () => {
|
|
566
|
+
setIsModalOpen(false);
|
|
567
|
+
setEditingArea(null);
|
|
568
|
+
fetchAreas();
|
|
569
|
+
};
|
|
570
|
+
const openDeletePrompt = (id, value) => {
|
|
571
|
+
setDeleteAreaId(id);
|
|
572
|
+
setDeleteAreaValue(value);
|
|
573
|
+
};
|
|
574
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
575
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-4", children: [
|
|
576
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-x-4", children: [
|
|
577
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-x-4 flex-1", children: [
|
|
578
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
579
|
+
ui.Input,
|
|
580
|
+
{
|
|
581
|
+
type: "search",
|
|
582
|
+
placeholder: "ค้นหาจังหวัดหรือรหัสไปรษณีย์...",
|
|
583
|
+
value: searchTerm,
|
|
584
|
+
onChange: (e) => setSearchTerm(e.target.value),
|
|
585
|
+
className: "max-w-md"
|
|
586
|
+
}
|
|
587
|
+
),
|
|
588
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Select, { value: kindFilter, onValueChange: setKindFilter, children: [
|
|
589
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, { placeholder: "ประเภท" }) }),
|
|
590
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Content, { children: AREA_KINDS.map((kind) => /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: kind.value, children: kind.label }, kind.value)) })
|
|
591
|
+
] })
|
|
592
|
+
] }),
|
|
593
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { onClick: handleCreateNew, children: [
|
|
594
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, {}),
|
|
595
|
+
"สร้างพื้นที่ใหม่"
|
|
596
|
+
] })
|
|
597
|
+
] }),
|
|
598
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Table, { children: [
|
|
599
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Header, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
|
|
600
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "ประเภท" }),
|
|
601
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "ค่า" }),
|
|
602
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "สถานะ" }),
|
|
603
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { className: "text-right", children: "การจัดการ" })
|
|
604
|
+
] }) }),
|
|
605
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Body, { children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Row, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "text-center", children: "กำลังโหลด..." }) }) : filteredAreas.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Row, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "text-center", children: "ไม่พบข้อมูลพื้นที่บริการ" }) }) : filteredAreas.map((area) => /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
|
|
606
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { color: area.kind === "PROVINCE" ? "blue" : "purple", children: area.kind === "PROVINCE" ? "จังหวัด" : "รหัสไปรษณีย์" }) }),
|
|
607
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: area.value }),
|
|
608
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
609
|
+
ui.Badge,
|
|
610
|
+
{
|
|
611
|
+
color: area.active ? "green" : "grey",
|
|
612
|
+
className: "cursor-pointer",
|
|
613
|
+
onClick: () => handleToggleActive(area),
|
|
614
|
+
children: area.active ? "เปิดใช้งาน" : "ปิดใช้งาน"
|
|
615
|
+
}
|
|
616
|
+
) }),
|
|
617
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "text-right", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
|
|
618
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
619
|
+
ui.Button,
|
|
620
|
+
{
|
|
621
|
+
variant: "transparent",
|
|
622
|
+
size: "small",
|
|
623
|
+
onClick: () => handleEdit(area),
|
|
624
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Edit, {})
|
|
625
|
+
}
|
|
626
|
+
),
|
|
627
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
628
|
+
ui.Button,
|
|
629
|
+
{
|
|
630
|
+
variant: "transparent",
|
|
631
|
+
size: "small",
|
|
632
|
+
onClick: () => openDeletePrompt(area.id, area.value),
|
|
633
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash, {})
|
|
634
|
+
}
|
|
635
|
+
)
|
|
636
|
+
] }) })
|
|
637
|
+
] }, area.id)) })
|
|
638
|
+
] })
|
|
639
|
+
] }),
|
|
640
|
+
isModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ServiceAreaModal, { area: editingArea, onClose: handleModalClose }),
|
|
641
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
642
|
+
ui.Prompt,
|
|
643
|
+
{
|
|
644
|
+
variant: "confirmation",
|
|
645
|
+
open: !!deleteAreaId,
|
|
646
|
+
onOpenChange: () => {
|
|
647
|
+
setDeleteAreaId(null);
|
|
648
|
+
setDeleteAreaValue("");
|
|
649
|
+
},
|
|
650
|
+
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Prompt.Content, { children: [
|
|
651
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Prompt.Header, { children: [
|
|
652
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Prompt.Title, { children: "ลบพื้นที่บริการ" }),
|
|
653
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Prompt.Description, { children: [
|
|
654
|
+
'คุณต้องการลบพื้นที่ "',
|
|
655
|
+
deleteAreaValue,
|
|
656
|
+
'" ใช่หรือไม่? การดำเนินการนี้ไม่สามารถย้อนกลับได้'
|
|
657
|
+
] })
|
|
658
|
+
] }),
|
|
659
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Prompt.Footer, { children: [
|
|
660
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Prompt.Cancel, { children: "ยกเลิก" }),
|
|
661
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Prompt.Action, { onClick: handleDelete, children: "ลบ" })
|
|
662
|
+
] })
|
|
663
|
+
] })
|
|
664
|
+
}
|
|
665
|
+
)
|
|
666
|
+
] });
|
|
667
|
+
};
|
|
668
|
+
const AreasPage = () => {
|
|
669
|
+
return /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-4", children: [
|
|
670
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "พื้นที่บริการ" }) }),
|
|
671
|
+
/* @__PURE__ */ jsxRuntime.jsx(ServiceAreasTable, {})
|
|
672
|
+
] }) });
|
|
673
|
+
};
|
|
674
|
+
const config$4 = adminSdk.defineRouteConfig({
|
|
675
|
+
icon: icons.MapPin,
|
|
676
|
+
label: "พื้นที่บริการ"
|
|
677
|
+
});
|
|
239
678
|
const MessengerBaseRateModal = ({
|
|
240
679
|
rate,
|
|
241
680
|
onClose
|
|
@@ -576,7 +1015,7 @@ const BasePricingPage = () => {
|
|
|
576
1015
|
/* @__PURE__ */ jsxRuntime.jsx(MessengerBasePricingTable, {})
|
|
577
1016
|
] }) });
|
|
578
1017
|
};
|
|
579
|
-
const config$
|
|
1018
|
+
const config$3 = adminSdk.defineRouteConfig({
|
|
580
1019
|
icon: icons.Directions,
|
|
581
1020
|
label: "ฐานราคาตามระยะทาง"
|
|
582
1021
|
});
|
|
@@ -984,120 +1423,57 @@ const BoxesPage = () => {
|
|
|
984
1423
|
/* @__PURE__ */ jsxRuntime.jsx(ParcelBoxesTable, {})
|
|
985
1424
|
] }) });
|
|
986
1425
|
};
|
|
987
|
-
const config$
|
|
1426
|
+
const config$2 = adminSdk.defineRouteConfig({
|
|
988
1427
|
icon: icons.ArchiveBox,
|
|
989
1428
|
label: "กล่องพัสดุ"
|
|
990
1429
|
});
|
|
991
|
-
const
|
|
992
|
-
"
|
|
993
|
-
"
|
|
994
|
-
"
|
|
995
|
-
"
|
|
996
|
-
"
|
|
997
|
-
"
|
|
998
|
-
"จันทบุรี",
|
|
999
|
-
"ฉะเชิงเทรา",
|
|
1000
|
-
"ชลบุรี",
|
|
1001
|
-
"ชัยนาท",
|
|
1002
|
-
"ชัยภูมิ",
|
|
1003
|
-
"ชุมพร",
|
|
1004
|
-
"เชียงราย",
|
|
1005
|
-
"เชียงใหม่",
|
|
1006
|
-
"ตรัง",
|
|
1007
|
-
"ตราด",
|
|
1008
|
-
"ตาก",
|
|
1009
|
-
"นครนายก",
|
|
1010
|
-
"นครปฐม",
|
|
1011
|
-
"นครพนม",
|
|
1012
|
-
"นครราชสีมา",
|
|
1013
|
-
"นครศรีธรรมราช",
|
|
1014
|
-
"นครสวรรค์",
|
|
1015
|
-
"นนทบุรี",
|
|
1016
|
-
"นราธิวาส",
|
|
1017
|
-
"น่าน",
|
|
1018
|
-
"บึงกาฬ",
|
|
1019
|
-
"บุรีรัมย์",
|
|
1020
|
-
"ปทุมธานี",
|
|
1021
|
-
"ประจวบคีรีขันธ์",
|
|
1022
|
-
"ปราจีนบุรี",
|
|
1023
|
-
"ปัตตานี",
|
|
1024
|
-
"พระนครศรีอยุธยา",
|
|
1025
|
-
"พะเยา",
|
|
1026
|
-
"พังงา",
|
|
1027
|
-
"พัทลุง",
|
|
1028
|
-
"พิจิตร",
|
|
1029
|
-
"พิษณุโลก",
|
|
1030
|
-
"เพชรบุรี",
|
|
1031
|
-
"เพชรบูรณ์",
|
|
1032
|
-
"แพร่",
|
|
1033
|
-
"ภูเก็ต",
|
|
1034
|
-
"มหาสารคาม",
|
|
1035
|
-
"มุกดาหาร",
|
|
1036
|
-
"แม่ฮ่องสอน",
|
|
1037
|
-
"ยโสธร",
|
|
1038
|
-
"ยะลา",
|
|
1039
|
-
"ร้อยเอ็ด",
|
|
1040
|
-
"ระนอง",
|
|
1041
|
-
"ระยอง",
|
|
1042
|
-
"ราชบุรี",
|
|
1043
|
-
"ลพบุรี",
|
|
1044
|
-
"ลำปาง",
|
|
1045
|
-
"ลำพูน",
|
|
1046
|
-
"เลย",
|
|
1047
|
-
"ศรีสะเกษ",
|
|
1048
|
-
"สกลนคร",
|
|
1049
|
-
"สงขลา",
|
|
1050
|
-
"สตูล",
|
|
1051
|
-
"สมุทรปราการ",
|
|
1052
|
-
"สมุทรสงคราม",
|
|
1053
|
-
"สมุทรสาคร",
|
|
1054
|
-
"สระแก้ว",
|
|
1055
|
-
"สระบุรี",
|
|
1056
|
-
"สิงห์บุรี",
|
|
1057
|
-
"สุโขทัย",
|
|
1058
|
-
"สุพรรณบุรี",
|
|
1059
|
-
"สุราษฎร์ธานี",
|
|
1060
|
-
"สุรินทร์",
|
|
1061
|
-
"หนองคาย",
|
|
1062
|
-
"หนองบัวลำภู",
|
|
1063
|
-
"อ่างทอง",
|
|
1064
|
-
"อำนาจเจริญ",
|
|
1065
|
-
"อุดรธานี",
|
|
1066
|
-
"อุตรดิตถ์",
|
|
1067
|
-
"อุทัยธานี",
|
|
1068
|
-
"อุบลราชธานี"
|
|
1430
|
+
const CATEGORIES$1 = [
|
|
1431
|
+
{ value: "PACKAGING", label: "วัสดุหีบห่อ" },
|
|
1432
|
+
{ value: "PROTECTION", label: "วัสดุป้องกัน" },
|
|
1433
|
+
{ value: "FILLING", label: "วัสดุเติมช่องว่าง" },
|
|
1434
|
+
{ value: "TAPE", label: "เทป/กาว" },
|
|
1435
|
+
{ value: "LABEL", label: "ฉลาก/สติกเกอร์" },
|
|
1436
|
+
{ value: "OTHER", label: "อื่นๆ" }
|
|
1069
1437
|
];
|
|
1070
|
-
const
|
|
1438
|
+
const MaterialCostModal = ({
|
|
1439
|
+
materialCost,
|
|
1440
|
+
onClose
|
|
1441
|
+
}) => {
|
|
1071
1442
|
const [formData, setFormData] = react.useState({
|
|
1072
|
-
|
|
1073
|
-
|
|
1443
|
+
name: "",
|
|
1444
|
+
unit: "",
|
|
1445
|
+
cost_per_unit: "",
|
|
1446
|
+
currency: "THB",
|
|
1447
|
+
category: "",
|
|
1448
|
+
description: "",
|
|
1074
1449
|
active: true
|
|
1075
1450
|
});
|
|
1076
1451
|
const [isSaving, setIsSaving] = react.useState(false);
|
|
1077
1452
|
react.useEffect(() => {
|
|
1078
|
-
if (
|
|
1453
|
+
if (materialCost) {
|
|
1079
1454
|
setFormData({
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1455
|
+
name: materialCost.name,
|
|
1456
|
+
unit: materialCost.unit,
|
|
1457
|
+
cost_per_unit: materialCost.cost_per_unit.toString(),
|
|
1458
|
+
currency: materialCost.currency,
|
|
1459
|
+
category: materialCost.category || "",
|
|
1460
|
+
description: materialCost.description || "",
|
|
1461
|
+
active: materialCost.active
|
|
1083
1462
|
});
|
|
1084
1463
|
}
|
|
1085
|
-
}, [
|
|
1464
|
+
}, [materialCost]);
|
|
1086
1465
|
const handleSubmit = async (e) => {
|
|
1087
1466
|
e.preventDefault();
|
|
1088
1467
|
const errors = [];
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
errors.push("กรุณากรอกค่า");
|
|
1468
|
+
if (!formData.name.trim()) {
|
|
1469
|
+
errors.push("กรุณากรอกชื่อวัสดุ");
|
|
1092
1470
|
}
|
|
1093
|
-
if (formData.
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
errors.push("รหัสไปรษณีย์ต้องเป็นตัวเลข 1-5 หลัก");
|
|
1100
|
-
}
|
|
1471
|
+
if (!formData.unit.trim()) {
|
|
1472
|
+
errors.push("กรุณากรอกหน่วย");
|
|
1473
|
+
}
|
|
1474
|
+
const costPerUnit = parseFloat(formData.cost_per_unit);
|
|
1475
|
+
if (isNaN(costPerUnit) || costPerUnit < 0) {
|
|
1476
|
+
errors.push("ต้นทุนต่อหน่วยต้องเป็นตัวเลขไม่ติดลบ");
|
|
1101
1477
|
}
|
|
1102
1478
|
if (errors.length > 0) {
|
|
1103
1479
|
ui.toast.error("ข้อมูลไม่ถูกต้อง", {
|
|
@@ -1108,12 +1484,16 @@ const ServiceAreaModal = ({ area, onClose }) => {
|
|
|
1108
1484
|
setIsSaving(true);
|
|
1109
1485
|
try {
|
|
1110
1486
|
const payload = {
|
|
1111
|
-
|
|
1112
|
-
|
|
1487
|
+
name: formData.name.trim(),
|
|
1488
|
+
unit: formData.unit.trim(),
|
|
1489
|
+
cost_per_unit: costPerUnit,
|
|
1490
|
+
currency: formData.currency,
|
|
1491
|
+
category: formData.category || void 0,
|
|
1492
|
+
description: formData.description.trim() || void 0,
|
|
1113
1493
|
active: formData.active
|
|
1114
1494
|
};
|
|
1115
|
-
const url =
|
|
1116
|
-
const method =
|
|
1495
|
+
const url = materialCost ? `/admin/material-costs/${materialCost.id}` : "/admin/material-costs";
|
|
1496
|
+
const method = materialCost ? "PUT" : "POST";
|
|
1117
1497
|
const response = await fetch(url, {
|
|
1118
1498
|
method,
|
|
1119
1499
|
headers: { "Content-Type": "application/json" },
|
|
@@ -1122,7 +1502,7 @@ const ServiceAreaModal = ({ area, onClose }) => {
|
|
|
1122
1502
|
});
|
|
1123
1503
|
if (response.ok) {
|
|
1124
1504
|
ui.toast.success("สำเร็จ", {
|
|
1125
|
-
description:
|
|
1505
|
+
description: materialCost ? "แก้ไขรายการต้นทุนวัสดุแล้ว" : "สร้างรายการต้นทุนวัสดุใหม่แล้ว"
|
|
1126
1506
|
});
|
|
1127
1507
|
onClose();
|
|
1128
1508
|
} else {
|
|
@@ -1138,53 +1518,89 @@ const ServiceAreaModal = ({ area, onClose }) => {
|
|
|
1138
1518
|
}
|
|
1139
1519
|
};
|
|
1140
1520
|
return /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer, { open: true, onOpenChange: (open) => !open && onClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Drawer.Content, { children: [
|
|
1141
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Title, { children:
|
|
1521
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Title, { children: materialCost ? "แก้ไขรายการต้นทุนวัสดุ" : "สร้างรายการต้นทุนวัสดุใหม่" }) }),
|
|
1142
1522
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, className: "flex flex-col gap-y-4", children: [
|
|
1143
1523
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1144
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "
|
|
1145
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1146
|
-
ui.
|
|
1524
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "name", children: "ชื่อวัสดุ *" }),
|
|
1525
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1526
|
+
ui.Input,
|
|
1147
1527
|
{
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Select.Content, { children: [
|
|
1154
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: "PROVINCE", children: "จังหวัด" }),
|
|
1155
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: "POSTCODE_PREFIX", children: "รหัสไปรษณีย์" })
|
|
1156
|
-
] })
|
|
1157
|
-
]
|
|
1528
|
+
id: "name",
|
|
1529
|
+
value: formData.name,
|
|
1530
|
+
onChange: (e) => setFormData({ ...formData, name: e.target.value }),
|
|
1531
|
+
placeholder: "เช่น พลาสติกกันกระแทก, กล่องกระดาษ",
|
|
1532
|
+
required: true
|
|
1158
1533
|
}
|
|
1159
1534
|
)
|
|
1160
1535
|
] }),
|
|
1161
1536
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1162
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "
|
|
1163
|
-
|
|
1537
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "category", children: "หมวดหมู่ (ไม่บังคับ)" }),
|
|
1538
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1164
1539
|
ui.Select,
|
|
1165
1540
|
{
|
|
1166
|
-
value: formData.
|
|
1167
|
-
onValueChange: (value) => setFormData({ ...formData, value }),
|
|
1168
|
-
required: true,
|
|
1541
|
+
value: formData.category || void 0,
|
|
1542
|
+
onValueChange: (value) => setFormData({ ...formData, category: value }),
|
|
1169
1543
|
children: [
|
|
1170
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, { placeholder: "
|
|
1171
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Content, { children:
|
|
1544
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, { placeholder: "เลือกหมวดหมู่ (ไม่บังคับ)" }) }),
|
|
1545
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Content, { children: CATEGORIES$1.map((category) => /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: category.value, children: category.label }, category.value)) })
|
|
1172
1546
|
]
|
|
1173
1547
|
}
|
|
1174
|
-
)
|
|
1548
|
+
)
|
|
1549
|
+
] }),
|
|
1550
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-x-4", children: [
|
|
1551
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1552
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "unit", children: "หน่วย *" }),
|
|
1553
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1554
|
+
ui.Input,
|
|
1555
|
+
{
|
|
1556
|
+
id: "unit",
|
|
1557
|
+
value: formData.unit,
|
|
1558
|
+
onChange: (e) => setFormData({ ...formData, unit: e.target.value }),
|
|
1559
|
+
placeholder: "เช่น ชิ้น, เมตร, กิโลกรัม",
|
|
1560
|
+
required: true
|
|
1561
|
+
}
|
|
1562
|
+
)
|
|
1563
|
+
] }),
|
|
1564
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1565
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "costPerUnit", children: "ต้นทุนต่อหน่วย *" }),
|
|
1566
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1567
|
+
ui.Input,
|
|
1568
|
+
{
|
|
1569
|
+
id: "costPerUnit",
|
|
1570
|
+
type: "number",
|
|
1571
|
+
step: "0.01",
|
|
1572
|
+
value: formData.cost_per_unit,
|
|
1573
|
+
onChange: (e) => setFormData({ ...formData, cost_per_unit: e.target.value }),
|
|
1574
|
+
placeholder: "0.00",
|
|
1575
|
+
required: true
|
|
1576
|
+
}
|
|
1577
|
+
)
|
|
1578
|
+
] })
|
|
1579
|
+
] }),
|
|
1580
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1581
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "currency", children: "สกุลเงิน" }),
|
|
1582
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1175
1583
|
ui.Input,
|
|
1176
1584
|
{
|
|
1177
|
-
id: "
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
placeholder: "เช่น 10, 102, 10200",
|
|
1182
|
-
maxLength: 5,
|
|
1183
|
-
pattern: "\\d{1,5}",
|
|
1184
|
-
required: true
|
|
1585
|
+
id: "currency",
|
|
1586
|
+
value: formData.currency,
|
|
1587
|
+
onChange: (e) => setFormData({ ...formData, currency: e.target.value }),
|
|
1588
|
+
placeholder: "THB"
|
|
1185
1589
|
}
|
|
1186
|
-
)
|
|
1187
|
-
|
|
1590
|
+
)
|
|
1591
|
+
] }),
|
|
1592
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1593
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "description", children: "คำอธิบาย" }),
|
|
1594
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1595
|
+
ui.Textarea,
|
|
1596
|
+
{
|
|
1597
|
+
id: "description",
|
|
1598
|
+
value: formData.description,
|
|
1599
|
+
onChange: (e) => setFormData({ ...formData, description: e.target.value }),
|
|
1600
|
+
placeholder: "คำอธิบายเพิ่มเติมเกี่ยวกับวัสดุนี้...",
|
|
1601
|
+
rows: 3
|
|
1602
|
+
}
|
|
1603
|
+
)
|
|
1188
1604
|
] }),
|
|
1189
1605
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-2", children: [
|
|
1190
1606
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -1213,66 +1629,69 @@ const ServiceAreaModal = ({ area, onClose }) => {
|
|
|
1213
1629
|
] }) })
|
|
1214
1630
|
] }) });
|
|
1215
1631
|
};
|
|
1216
|
-
const
|
|
1632
|
+
const CATEGORIES = [
|
|
1217
1633
|
{ value: "ALL", label: "ทั้งหมด" },
|
|
1218
|
-
{ value: "
|
|
1219
|
-
{ value: "
|
|
1634
|
+
{ value: "PACKAGING", label: "วัสดุหีบห่อ" },
|
|
1635
|
+
{ value: "PROTECTION", label: "วัสดุป้องกัน" },
|
|
1636
|
+
{ value: "FILLING", label: "วัสดุเติมช่องว่าง" },
|
|
1637
|
+
{ value: "TAPE", label: "เทป/กาว" },
|
|
1638
|
+
{ value: "LABEL", label: "ฉลาก/สติกเกอร์" },
|
|
1639
|
+
{ value: "OTHER", label: "อื่นๆ" }
|
|
1220
1640
|
];
|
|
1221
|
-
const
|
|
1222
|
-
const [
|
|
1223
|
-
const [
|
|
1641
|
+
const MaterialCostsTable = () => {
|
|
1642
|
+
const [materialCosts, setMaterialCosts] = react.useState([]);
|
|
1643
|
+
const [filteredMaterialCosts, setFilteredMaterialCosts] = react.useState([]);
|
|
1224
1644
|
const [searchTerm, setSearchTerm] = react.useState("");
|
|
1225
|
-
const [
|
|
1645
|
+
const [categoryFilter, setCategoryFilter] = react.useState("ALL");
|
|
1226
1646
|
const [isModalOpen, setIsModalOpen] = react.useState(false);
|
|
1227
|
-
const [
|
|
1647
|
+
const [editingMaterialCost, setEditingMaterialCost] = react.useState(null);
|
|
1228
1648
|
const [isLoading, setIsLoading] = react.useState(false);
|
|
1229
|
-
const [
|
|
1230
|
-
const [
|
|
1649
|
+
const [deleteMaterialCostId, setDeleteMaterialCostId] = react.useState(null);
|
|
1650
|
+
const [deleteMaterialCostName, setDeleteMaterialCostName] = react.useState("");
|
|
1231
1651
|
react.useEffect(() => {
|
|
1232
|
-
|
|
1652
|
+
fetchMaterialCosts();
|
|
1233
1653
|
}, []);
|
|
1234
1654
|
react.useEffect(() => {
|
|
1235
|
-
let filtered =
|
|
1236
|
-
if (
|
|
1237
|
-
filtered = filtered.filter((
|
|
1655
|
+
let filtered = materialCosts;
|
|
1656
|
+
if (categoryFilter !== "ALL") {
|
|
1657
|
+
filtered = filtered.filter((mc) => mc.category === categoryFilter);
|
|
1238
1658
|
}
|
|
1239
1659
|
if (searchTerm) {
|
|
1240
1660
|
filtered = filtered.filter(
|
|
1241
|
-
(
|
|
1661
|
+
(mc) => mc.name.toLowerCase().includes(searchTerm.toLowerCase())
|
|
1242
1662
|
);
|
|
1243
1663
|
}
|
|
1244
|
-
|
|
1245
|
-
}, [searchTerm,
|
|
1246
|
-
const
|
|
1664
|
+
setFilteredMaterialCosts(filtered);
|
|
1665
|
+
}, [searchTerm, categoryFilter, materialCosts]);
|
|
1666
|
+
const fetchMaterialCosts = async () => {
|
|
1247
1667
|
setIsLoading(true);
|
|
1248
1668
|
try {
|
|
1249
|
-
const response = await fetch("/admin/
|
|
1669
|
+
const response = await fetch("/admin/material-costs", {
|
|
1250
1670
|
credentials: "include"
|
|
1251
1671
|
});
|
|
1252
1672
|
const data = await response.json();
|
|
1253
|
-
|
|
1254
|
-
setAreas(data.service_areas || []);
|
|
1673
|
+
setMaterialCosts(data.material_costs || []);
|
|
1255
1674
|
} catch (error) {
|
|
1256
1675
|
ui.toast.error("ข้อผิดพลาด", {
|
|
1257
|
-
description: "
|
|
1676
|
+
description: "ไม่สามารถโหลดข้อมูลต้นทุนวัสดุได้"
|
|
1258
1677
|
});
|
|
1259
1678
|
} finally {
|
|
1260
1679
|
setIsLoading(false);
|
|
1261
1680
|
}
|
|
1262
1681
|
};
|
|
1263
|
-
const handleToggleActive = async (
|
|
1682
|
+
const handleToggleActive = async (materialCost) => {
|
|
1264
1683
|
try {
|
|
1265
|
-
const response = await fetch(`/admin/
|
|
1684
|
+
const response = await fetch(`/admin/material-costs/${materialCost.id}`, {
|
|
1266
1685
|
method: "PUT",
|
|
1267
1686
|
headers: { "Content-Type": "application/json" },
|
|
1268
1687
|
credentials: "include",
|
|
1269
|
-
body: JSON.stringify({ ...
|
|
1688
|
+
body: JSON.stringify({ ...materialCost, active: !materialCost.active })
|
|
1270
1689
|
});
|
|
1271
1690
|
if (response.ok) {
|
|
1272
1691
|
ui.toast.success("สำเร็จ", {
|
|
1273
|
-
description: `${
|
|
1692
|
+
description: `${materialCost.active ? "ปิดใช้งาน" : "เปิดใช้งาน"}วัสดุ ${materialCost.name} แล้ว`
|
|
1274
1693
|
});
|
|
1275
|
-
|
|
1694
|
+
fetchMaterialCosts();
|
|
1276
1695
|
} else {
|
|
1277
1696
|
throw new Error("Failed to update");
|
|
1278
1697
|
}
|
|
@@ -1283,45 +1702,53 @@ const ServiceAreasTable = () => {
|
|
|
1283
1702
|
}
|
|
1284
1703
|
};
|
|
1285
1704
|
const handleDelete = async () => {
|
|
1286
|
-
if (!
|
|
1705
|
+
if (!deleteMaterialCostId) return;
|
|
1287
1706
|
try {
|
|
1288
|
-
const response = await fetch(
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1707
|
+
const response = await fetch(
|
|
1708
|
+
`/admin/material-costs/${deleteMaterialCostId}`,
|
|
1709
|
+
{
|
|
1710
|
+
method: "DELETE",
|
|
1711
|
+
credentials: "include"
|
|
1712
|
+
}
|
|
1713
|
+
);
|
|
1292
1714
|
if (response.ok) {
|
|
1293
1715
|
ui.toast.success("สำเร็จ", {
|
|
1294
|
-
description:
|
|
1716
|
+
description: `ลบวัสดุ ${deleteMaterialCostName} แล้ว`
|
|
1295
1717
|
});
|
|
1296
|
-
|
|
1718
|
+
fetchMaterialCosts();
|
|
1297
1719
|
} else {
|
|
1298
1720
|
throw new Error("Failed to delete");
|
|
1299
1721
|
}
|
|
1300
1722
|
} catch (error) {
|
|
1301
1723
|
ui.toast.error("ข้อผิดพลาด", {
|
|
1302
|
-
description: "
|
|
1724
|
+
description: "ไม่สามารถลบวัสดุได้"
|
|
1303
1725
|
});
|
|
1304
1726
|
} finally {
|
|
1305
|
-
|
|
1306
|
-
|
|
1727
|
+
setDeleteMaterialCostId(null);
|
|
1728
|
+
setDeleteMaterialCostName("");
|
|
1307
1729
|
}
|
|
1308
1730
|
};
|
|
1309
|
-
const handleEdit = (
|
|
1310
|
-
|
|
1731
|
+
const handleEdit = (materialCost) => {
|
|
1732
|
+
setEditingMaterialCost(materialCost);
|
|
1311
1733
|
setIsModalOpen(true);
|
|
1312
1734
|
};
|
|
1313
1735
|
const handleCreateNew = () => {
|
|
1314
|
-
|
|
1736
|
+
setEditingMaterialCost(null);
|
|
1315
1737
|
setIsModalOpen(true);
|
|
1316
1738
|
};
|
|
1317
1739
|
const handleModalClose = () => {
|
|
1318
1740
|
setIsModalOpen(false);
|
|
1319
|
-
|
|
1320
|
-
|
|
1741
|
+
setEditingMaterialCost(null);
|
|
1742
|
+
fetchMaterialCosts();
|
|
1321
1743
|
};
|
|
1322
|
-
const openDeletePrompt = (id,
|
|
1323
|
-
|
|
1324
|
-
|
|
1744
|
+
const openDeletePrompt = (id, name) => {
|
|
1745
|
+
setDeleteMaterialCostId(id);
|
|
1746
|
+
setDeleteMaterialCostName(name);
|
|
1747
|
+
};
|
|
1748
|
+
const getCategoryLabel = (category) => {
|
|
1749
|
+
var _a;
|
|
1750
|
+
if (!category) return "-";
|
|
1751
|
+
return ((_a = CATEGORIES.find((c) => c.value === category)) == null ? void 0 : _a.label) || category;
|
|
1325
1752
|
};
|
|
1326
1753
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1327
1754
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-4", children: [
|
|
@@ -1331,39 +1758,49 @@ const ServiceAreasTable = () => {
|
|
|
1331
1758
|
ui.Input,
|
|
1332
1759
|
{
|
|
1333
1760
|
type: "search",
|
|
1334
|
-
placeholder: "
|
|
1761
|
+
placeholder: "ค้นหาชื่อวัสดุ...",
|
|
1335
1762
|
value: searchTerm,
|
|
1336
1763
|
onChange: (e) => setSearchTerm(e.target.value),
|
|
1337
1764
|
className: "max-w-md"
|
|
1338
1765
|
}
|
|
1339
1766
|
),
|
|
1340
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Select, { value:
|
|
1341
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, { placeholder: "
|
|
1342
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Content, { children:
|
|
1767
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Select, { value: categoryFilter, onValueChange: setCategoryFilter, children: [
|
|
1768
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, { placeholder: "หมวดหมู่" }) }),
|
|
1769
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Content, { children: CATEGORIES.map((category) => /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: category.value, children: category.label }, category.value)) })
|
|
1343
1770
|
] })
|
|
1344
1771
|
] }),
|
|
1345
1772
|
/* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { onClick: handleCreateNew, children: [
|
|
1346
1773
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, {}),
|
|
1347
|
-
"
|
|
1774
|
+
"สร้างรายการใหม่"
|
|
1348
1775
|
] })
|
|
1349
1776
|
] }),
|
|
1350
1777
|
/* @__PURE__ */ jsxRuntime.jsxs(ui.Table, { children: [
|
|
1351
1778
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Header, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
|
|
1352
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "
|
|
1353
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "
|
|
1779
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "ชื่อ" }),
|
|
1780
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "หมวดหมู่" }),
|
|
1781
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "หน่วย" }),
|
|
1782
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "ต้นทุนต่อหน่วย" }),
|
|
1783
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "คำอธิบาย" }),
|
|
1354
1784
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "สถานะ" }),
|
|
1355
1785
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { className: "text-right", children: "การจัดการ" })
|
|
1356
1786
|
] }) }),
|
|
1357
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Body, { children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Row, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "text-center", children: "กำลังโหลด..." }) }) :
|
|
1358
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children:
|
|
1359
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children:
|
|
1787
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Body, { children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Row, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "text-center", children: "กำลังโหลด..." }) }) : filteredMaterialCosts.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Row, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "text-center", children: "ไม่พบข้อมูลต้นทุนวัสดุ" }) }) : filteredMaterialCosts.map((materialCost) => /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
|
|
1788
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: materialCost.name }),
|
|
1789
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { color: "blue", children: getCategoryLabel(materialCost.category) }) }),
|
|
1790
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: materialCost.unit }),
|
|
1791
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Cell, { children: [
|
|
1792
|
+
materialCost.cost_per_unit.toFixed(2),
|
|
1793
|
+
" ",
|
|
1794
|
+
materialCost.currency
|
|
1795
|
+
] }),
|
|
1796
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "max-w-xs truncate", children: materialCost.description || "-" }),
|
|
1360
1797
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1361
1798
|
ui.Badge,
|
|
1362
1799
|
{
|
|
1363
|
-
color:
|
|
1800
|
+
color: materialCost.active ? "green" : "grey",
|
|
1364
1801
|
className: "cursor-pointer",
|
|
1365
|
-
onClick: () => handleToggleActive(
|
|
1366
|
-
children:
|
|
1802
|
+
onClick: () => handleToggleActive(materialCost),
|
|
1803
|
+
children: materialCost.active ? "เปิดใช้งาน" : "ปิดใช้งาน"
|
|
1367
1804
|
}
|
|
1368
1805
|
) }),
|
|
1369
1806
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "text-right", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
|
|
@@ -1372,7 +1809,7 @@ const ServiceAreasTable = () => {
|
|
|
1372
1809
|
{
|
|
1373
1810
|
variant: "transparent",
|
|
1374
1811
|
size: "small",
|
|
1375
|
-
onClick: () => handleEdit(
|
|
1812
|
+
onClick: () => handleEdit(materialCost),
|
|
1376
1813
|
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Edit, {})
|
|
1377
1814
|
}
|
|
1378
1815
|
),
|
|
@@ -1381,30 +1818,36 @@ const ServiceAreasTable = () => {
|
|
|
1381
1818
|
{
|
|
1382
1819
|
variant: "transparent",
|
|
1383
1820
|
size: "small",
|
|
1384
|
-
onClick: () => openDeletePrompt(
|
|
1821
|
+
onClick: () => openDeletePrompt(materialCost.id, materialCost.name),
|
|
1385
1822
|
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash, {})
|
|
1386
1823
|
}
|
|
1387
1824
|
)
|
|
1388
1825
|
] }) })
|
|
1389
|
-
] },
|
|
1826
|
+
] }, materialCost.id)) })
|
|
1390
1827
|
] })
|
|
1391
1828
|
] }),
|
|
1392
|
-
isModalOpen && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1829
|
+
isModalOpen && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1830
|
+
MaterialCostModal,
|
|
1831
|
+
{
|
|
1832
|
+
materialCost: editingMaterialCost,
|
|
1833
|
+
onClose: handleModalClose
|
|
1834
|
+
}
|
|
1835
|
+
),
|
|
1393
1836
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1394
1837
|
ui.Prompt,
|
|
1395
1838
|
{
|
|
1396
1839
|
variant: "confirmation",
|
|
1397
|
-
open: !!
|
|
1840
|
+
open: !!deleteMaterialCostId,
|
|
1398
1841
|
onOpenChange: () => {
|
|
1399
|
-
|
|
1400
|
-
|
|
1842
|
+
setDeleteMaterialCostId(null);
|
|
1843
|
+
setDeleteMaterialCostName("");
|
|
1401
1844
|
},
|
|
1402
1845
|
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Prompt.Content, { children: [
|
|
1403
1846
|
/* @__PURE__ */ jsxRuntime.jsxs(ui.Prompt.Header, { children: [
|
|
1404
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Prompt.Title, { children: "
|
|
1847
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Prompt.Title, { children: "ลบรายการต้นทุนวัสดุ" }),
|
|
1405
1848
|
/* @__PURE__ */ jsxRuntime.jsxs(ui.Prompt.Description, { children: [
|
|
1406
|
-
'
|
|
1407
|
-
|
|
1849
|
+
'คุณต้องการลบวัสดุ "',
|
|
1850
|
+
deleteMaterialCostName,
|
|
1408
1851
|
'" ใช่หรือไม่? การดำเนินการนี้ไม่สามารถย้อนกลับได้'
|
|
1409
1852
|
] })
|
|
1410
1853
|
] }),
|
|
@@ -1417,63 +1860,98 @@ const ServiceAreasTable = () => {
|
|
|
1417
1860
|
)
|
|
1418
1861
|
] });
|
|
1419
1862
|
};
|
|
1420
|
-
const
|
|
1863
|
+
const MaterialCostsPage = () => {
|
|
1421
1864
|
return /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-4", children: [
|
|
1422
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "
|
|
1423
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1424
|
-
] }) });
|
|
1425
|
-
};
|
|
1426
|
-
const config$
|
|
1427
|
-
icon: icons.
|
|
1428
|
-
label: "
|
|
1865
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "ต้นทุนวัสดุ" }) }),
|
|
1866
|
+
/* @__PURE__ */ jsxRuntime.jsx(MaterialCostsTable, {})
|
|
1867
|
+
] }) });
|
|
1868
|
+
};
|
|
1869
|
+
const config$1 = adminSdk.defineRouteConfig({
|
|
1870
|
+
icon: icons.CurrencyDollarSolid,
|
|
1871
|
+
label: "ต้นทุนวัสดุ"
|
|
1429
1872
|
});
|
|
1430
|
-
const
|
|
1431
|
-
{ value: "
|
|
1432
|
-
{ value: "
|
|
1433
|
-
{ value: "
|
|
1434
|
-
{ value: "TAPE", label: "เทป/กาว" },
|
|
1435
|
-
{ value: "LABEL", label: "ฉลาก/สติกเกอร์" },
|
|
1436
|
-
{ value: "OTHER", label: "อื่นๆ" }
|
|
1873
|
+
const CARRIER_TYPES$1 = [
|
|
1874
|
+
{ value: "COMPANY_FLEET", label: "บริษัทรถส่งของ (Messenger)" },
|
|
1875
|
+
{ value: "COMPANY_TRUCK", label: "รถบริษัท (Same Day)" },
|
|
1876
|
+
{ value: "PRIVATE_CARRIER", label: "ขนส่งเอกชน (EMS/Express)" }
|
|
1437
1877
|
];
|
|
1438
|
-
const
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1878
|
+
const SERVICE_CODES$1 = [
|
|
1879
|
+
{ value: "MESSENGER_3H", label: "ส่งด่วน 3 ชม.", usesHours: true },
|
|
1880
|
+
{ value: "SAME_DAY", label: "ส่งด่วนภายในวัน", usesHours: true },
|
|
1881
|
+
{ value: "STANDARD_3_5D", label: "EMS 3-5 วัน", usesHours: false },
|
|
1882
|
+
{ value: "EXPRESS_1_2D", label: "Express 1-2 วัน", usesHours: false }
|
|
1883
|
+
];
|
|
1884
|
+
const ShippingRateModal = ({ rate, onClose }) => {
|
|
1442
1885
|
const [formData, setFormData] = react.useState({
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1886
|
+
carrier_type: "COMPANY_FLEET",
|
|
1887
|
+
service_code: "MESSENGER_3H",
|
|
1888
|
+
max_weight_kg: "",
|
|
1889
|
+
price: "",
|
|
1446
1890
|
currency: "THB",
|
|
1447
|
-
|
|
1448
|
-
|
|
1891
|
+
priority: "0",
|
|
1892
|
+
eta_hours_min: "",
|
|
1893
|
+
eta_hours_max: "",
|
|
1894
|
+
eta_days_min: "",
|
|
1895
|
+
eta_days_max: "",
|
|
1449
1896
|
active: true
|
|
1450
1897
|
});
|
|
1451
1898
|
const [isSaving, setIsSaving] = react.useState(false);
|
|
1899
|
+
const selectedService = SERVICE_CODES$1.find((s) => s.value === formData.service_code);
|
|
1900
|
+
const usesHours = (selectedService == null ? void 0 : selectedService.usesHours) ?? false;
|
|
1901
|
+
const isMessenger = formData.carrier_type === "COMPANY_FLEET" && formData.service_code === "MESSENGER_3H";
|
|
1452
1902
|
react.useEffect(() => {
|
|
1453
|
-
|
|
1903
|
+
var _a, _b, _c, _d;
|
|
1904
|
+
if (rate) {
|
|
1454
1905
|
setFormData({
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1906
|
+
carrier_type: rate.carrier_type,
|
|
1907
|
+
service_code: rate.service_code,
|
|
1908
|
+
max_weight_kg: rate.max_weight_kg.toString(),
|
|
1909
|
+
price: rate.price.toString(),
|
|
1910
|
+
currency: rate.currency,
|
|
1911
|
+
priority: (rate.priority ?? 0).toString(),
|
|
1912
|
+
eta_hours_min: ((_a = rate.eta_hours_min) == null ? void 0 : _a.toString()) || "",
|
|
1913
|
+
eta_hours_max: ((_b = rate.eta_hours_max) == null ? void 0 : _b.toString()) || "",
|
|
1914
|
+
eta_days_min: ((_c = rate.eta_days_min) == null ? void 0 : _c.toString()) || "",
|
|
1915
|
+
eta_days_max: ((_d = rate.eta_days_max) == null ? void 0 : _d.toString()) || "",
|
|
1916
|
+
active: rate.active
|
|
1462
1917
|
});
|
|
1463
1918
|
}
|
|
1464
|
-
}, [
|
|
1919
|
+
}, [rate]);
|
|
1465
1920
|
const handleSubmit = async (e) => {
|
|
1466
1921
|
e.preventDefault();
|
|
1467
1922
|
const errors = [];
|
|
1468
|
-
|
|
1469
|
-
|
|
1923
|
+
const maxWeight = parseFloat(formData.max_weight_kg);
|
|
1924
|
+
const price = parseFloat(formData.price);
|
|
1925
|
+
const priority = parseInt(formData.priority);
|
|
1926
|
+
if (isNaN(maxWeight) || maxWeight <= 0) {
|
|
1927
|
+
errors.push("น้ำหนักสูงสุดต้องเป็นตัวเลขมากกว่า 0");
|
|
1470
1928
|
}
|
|
1471
|
-
if (
|
|
1472
|
-
errors.push("
|
|
1929
|
+
if (isNaN(price) || price < 0) {
|
|
1930
|
+
errors.push("ราคาต้องเป็นตัวเลขไม่ติดลบ");
|
|
1473
1931
|
}
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1932
|
+
if (isNaN(priority)) {
|
|
1933
|
+
errors.push("ลำดับความสำคัญต้องเป็นตัวเลข");
|
|
1934
|
+
}
|
|
1935
|
+
let etaHoursMin;
|
|
1936
|
+
let etaHoursMax;
|
|
1937
|
+
let etaDaysMin;
|
|
1938
|
+
let etaDaysMax;
|
|
1939
|
+
if (usesHours) {
|
|
1940
|
+
etaHoursMin = formData.eta_hours_min ? parseFloat(formData.eta_hours_min) : void 0;
|
|
1941
|
+
etaHoursMax = formData.eta_hours_max ? parseFloat(formData.eta_hours_max) : void 0;
|
|
1942
|
+
if (etaHoursMin === void 0 || etaHoursMax === void 0) {
|
|
1943
|
+
errors.push("กรุณากรอก ETA เป็นชั่วโมงให้ครบ");
|
|
1944
|
+
} else if (etaHoursMin > etaHoursMax) {
|
|
1945
|
+
errors.push("ETA ชั่วโมงต่ำสุดต้องน้อยกว่าหรือเท่ากับสูงสุด");
|
|
1946
|
+
}
|
|
1947
|
+
} else {
|
|
1948
|
+
etaDaysMin = formData.eta_days_min ? parseFloat(formData.eta_days_min) : void 0;
|
|
1949
|
+
etaDaysMax = formData.eta_days_max ? parseFloat(formData.eta_days_max) : void 0;
|
|
1950
|
+
if (etaDaysMin === void 0 || etaDaysMax === void 0) {
|
|
1951
|
+
errors.push("กรุณากรอก ETA เป็นวันให้ครบ");
|
|
1952
|
+
} else if (etaDaysMin > etaDaysMax) {
|
|
1953
|
+
errors.push("ETA วันต่ำสุดต้องน้อยกว่าหรือเท่ากับสูงสุด");
|
|
1954
|
+
}
|
|
1477
1955
|
}
|
|
1478
1956
|
if (errors.length > 0) {
|
|
1479
1957
|
ui.toast.error("ข้อมูลไม่ถูกต้อง", {
|
|
@@ -1484,16 +1962,23 @@ const MaterialCostModal = ({
|
|
|
1484
1962
|
setIsSaving(true);
|
|
1485
1963
|
try {
|
|
1486
1964
|
const payload = {
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1965
|
+
carrier_type: formData.carrier_type,
|
|
1966
|
+
service_code: formData.service_code,
|
|
1967
|
+
max_weight_kg: maxWeight,
|
|
1968
|
+
price,
|
|
1490
1969
|
currency: formData.currency,
|
|
1491
|
-
|
|
1492
|
-
description: formData.description.trim() || void 0,
|
|
1970
|
+
priority,
|
|
1493
1971
|
active: formData.active
|
|
1494
1972
|
};
|
|
1495
|
-
|
|
1496
|
-
|
|
1973
|
+
if (usesHours) {
|
|
1974
|
+
payload.eta_hours_min = etaHoursMin;
|
|
1975
|
+
payload.eta_hours_max = etaHoursMax;
|
|
1976
|
+
} else {
|
|
1977
|
+
payload.eta_days_min = etaDaysMin;
|
|
1978
|
+
payload.eta_days_max = etaDaysMax;
|
|
1979
|
+
}
|
|
1980
|
+
const url = rate ? `/admin/shipping-rates/${rate.id}` : "/admin/shipping-rates";
|
|
1981
|
+
const method = rate ? "PUT" : "POST";
|
|
1497
1982
|
const response = await fetch(url, {
|
|
1498
1983
|
method,
|
|
1499
1984
|
headers: { "Content-Type": "application/json" },
|
|
@@ -1502,7 +1987,7 @@ const MaterialCostModal = ({
|
|
|
1502
1987
|
});
|
|
1503
1988
|
if (response.ok) {
|
|
1504
1989
|
ui.toast.success("สำเร็จ", {
|
|
1505
|
-
description:
|
|
1990
|
+
description: rate ? "แก้ไขอัตราค่าขนส่งแล้ว" : "สร้างอัตราค่าขนส่งใหม่แล้ว"
|
|
1506
1991
|
});
|
|
1507
1992
|
onClose();
|
|
1508
1993
|
} else {
|
|
@@ -1518,89 +2003,147 @@ const MaterialCostModal = ({
|
|
|
1518
2003
|
}
|
|
1519
2004
|
};
|
|
1520
2005
|
return /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer, { open: true, onOpenChange: (open) => !open && onClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Drawer.Content, { children: [
|
|
1521
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Title, { children:
|
|
2006
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Title, { children: rate ? "แก้ไขอัตราค่าขนส่ง" : "สร้างอัตราค่าขนส่งใหม่" }) }),
|
|
1522
2007
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, className: "flex flex-col gap-y-4", children: [
|
|
1523
2008
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1524
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "
|
|
1525
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1526
|
-
ui.
|
|
2009
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "carrier", children: "ประเภทขนส่ง *" }),
|
|
2010
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2011
|
+
ui.Select,
|
|
1527
2012
|
{
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
2013
|
+
value: formData.carrier_type,
|
|
2014
|
+
onValueChange: (value) => setFormData({ ...formData, carrier_type: value }),
|
|
2015
|
+
children: [
|
|
2016
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, { placeholder: "เลือกประเภทขนส่ง" }) }),
|
|
2017
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Content, { children: CARRIER_TYPES$1.map((carrier) => /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: carrier.value, children: carrier.label }, carrier.value)) })
|
|
2018
|
+
]
|
|
1533
2019
|
}
|
|
1534
2020
|
)
|
|
1535
2021
|
] }),
|
|
1536
2022
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1537
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "
|
|
2023
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "service", children: "บริการจัดส่ง *" }),
|
|
1538
2024
|
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
1539
2025
|
ui.Select,
|
|
1540
2026
|
{
|
|
1541
|
-
value: formData.
|
|
1542
|
-
onValueChange: (value) => setFormData({
|
|
2027
|
+
value: formData.service_code,
|
|
2028
|
+
onValueChange: (value) => setFormData({
|
|
2029
|
+
...formData,
|
|
2030
|
+
service_code: value,
|
|
2031
|
+
eta_hours_min: "",
|
|
2032
|
+
eta_hours_max: "",
|
|
2033
|
+
eta_days_min: "",
|
|
2034
|
+
eta_days_max: ""
|
|
2035
|
+
}),
|
|
1543
2036
|
children: [
|
|
1544
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, { placeholder: "
|
|
1545
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Content, { children:
|
|
2037
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, { placeholder: "เลือกบริการ" }) }),
|
|
2038
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Content, { children: SERVICE_CODES$1.map((service) => /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: service.value, children: service.label }, service.value)) })
|
|
1546
2039
|
]
|
|
1547
2040
|
}
|
|
1548
2041
|
)
|
|
1549
2042
|
] }),
|
|
2043
|
+
isMessenger && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3 text-sm space-y-1", children: [
|
|
2044
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-semibold text-ui-fg-base", children: "ฐานราคาตามระยะทาง (Messenger)" }),
|
|
2045
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "ตั้งช่วงราคาตามระยะทาง เช่น 0-5, 5-20, 20-30, 30+ กม. สำหรับบริการส่งด่วน 3 ชม." }),
|
|
2046
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { asChild: true, size: "small", variant: "secondary", children: /* @__PURE__ */ jsxRuntime.jsxs("a", { href: "/base-pricing", target: "_blank", rel: "noreferrer", children: [
|
|
2047
|
+
"จัดการฐานราคา",
|
|
2048
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { className: "ml-1 h-4 w-4" })
|
|
2049
|
+
] }) }) })
|
|
2050
|
+
] }),
|
|
1550
2051
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-x-4", children: [
|
|
1551
2052
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1552
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "
|
|
2053
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "maxWeight", children: "น้ำหนักสูงสุด (kg) *" }),
|
|
1553
2054
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1554
2055
|
ui.Input,
|
|
1555
2056
|
{
|
|
1556
|
-
id: "
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
2057
|
+
id: "maxWeight",
|
|
2058
|
+
type: "number",
|
|
2059
|
+
step: "0.1",
|
|
2060
|
+
min: "0",
|
|
2061
|
+
value: formData.max_weight_kg,
|
|
2062
|
+
onChange: (e) => setFormData({ ...formData, max_weight_kg: e.target.value }),
|
|
2063
|
+
placeholder: "เช่น 3",
|
|
1560
2064
|
required: true
|
|
1561
2065
|
}
|
|
1562
2066
|
)
|
|
1563
2067
|
] }),
|
|
1564
2068
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1565
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "
|
|
2069
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "price", children: "ราคา (THB) *" }),
|
|
1566
2070
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1567
2071
|
ui.Input,
|
|
1568
2072
|
{
|
|
1569
|
-
id: "
|
|
2073
|
+
id: "price",
|
|
1570
2074
|
type: "number",
|
|
1571
2075
|
step: "0.01",
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
2076
|
+
min: "0",
|
|
2077
|
+
value: formData.price,
|
|
2078
|
+
onChange: (e) => setFormData({ ...formData, price: e.target.value }),
|
|
2079
|
+
placeholder: "เช่น 80",
|
|
1575
2080
|
required: true
|
|
1576
2081
|
}
|
|
1577
2082
|
)
|
|
1578
2083
|
] })
|
|
1579
2084
|
] }),
|
|
1580
2085
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1581
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "
|
|
2086
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "priority", children: "ลำดับความสำคัญ" }),
|
|
1582
2087
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1583
2088
|
ui.Input,
|
|
1584
2089
|
{
|
|
1585
|
-
id: "
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
2090
|
+
id: "priority",
|
|
2091
|
+
type: "number",
|
|
2092
|
+
value: formData.priority,
|
|
2093
|
+
onChange: (e) => setFormData({ ...formData, priority: e.target.value }),
|
|
2094
|
+
placeholder: "0"
|
|
1589
2095
|
}
|
|
1590
|
-
)
|
|
2096
|
+
),
|
|
2097
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-ui-fg-subtle mt-1", children: "ตัวเลขสูงกว่าจะถูกเสนอให้เลือกก่อน (ค่าเริ่มต้น 0)" })
|
|
1591
2098
|
] }),
|
|
1592
2099
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
1593
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
2100
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Label, { children: [
|
|
2101
|
+
usesHours ? "ETA (ชั่วโมง)" : "ETA (วัน)",
|
|
2102
|
+
" *"
|
|
2103
|
+
] }),
|
|
2104
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-x-4 mt-2", children: usesHours ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2105
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2106
|
+
ui.Input,
|
|
2107
|
+
{
|
|
2108
|
+
type: "number",
|
|
2109
|
+
placeholder: "ต่ำสุด",
|
|
2110
|
+
value: formData.eta_hours_min,
|
|
2111
|
+
onChange: (e) => setFormData({ ...formData, eta_hours_min: e.target.value }),
|
|
2112
|
+
required: true
|
|
2113
|
+
}
|
|
2114
|
+
),
|
|
2115
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2116
|
+
ui.Input,
|
|
2117
|
+
{
|
|
2118
|
+
type: "number",
|
|
2119
|
+
placeholder: "สูงสุด",
|
|
2120
|
+
value: formData.eta_hours_max,
|
|
2121
|
+
onChange: (e) => setFormData({ ...formData, eta_hours_max: e.target.value }),
|
|
2122
|
+
required: true
|
|
2123
|
+
}
|
|
2124
|
+
)
|
|
2125
|
+
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2126
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2127
|
+
ui.Input,
|
|
2128
|
+
{
|
|
2129
|
+
type: "number",
|
|
2130
|
+
placeholder: "ต่ำสุด",
|
|
2131
|
+
value: formData.eta_days_min,
|
|
2132
|
+
onChange: (e) => setFormData({ ...formData, eta_days_min: e.target.value }),
|
|
2133
|
+
required: true
|
|
2134
|
+
}
|
|
2135
|
+
),
|
|
2136
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2137
|
+
ui.Input,
|
|
2138
|
+
{
|
|
2139
|
+
type: "number",
|
|
2140
|
+
placeholder: "สูงสุด",
|
|
2141
|
+
value: formData.eta_days_max,
|
|
2142
|
+
onChange: (e) => setFormData({ ...formData, eta_days_max: e.target.value }),
|
|
2143
|
+
required: true
|
|
2144
|
+
}
|
|
2145
|
+
)
|
|
2146
|
+
] }) })
|
|
1604
2147
|
] }),
|
|
1605
2148
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-2", children: [
|
|
1606
2149
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -1614,202 +2157,168 @@ const MaterialCostModal = ({
|
|
|
1614
2157
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "active", children: "เปิดใช้งาน" })
|
|
1615
2158
|
] }),
|
|
1616
2159
|
/* @__PURE__ */ jsxRuntime.jsxs(ui.Drawer.Footer, { children: [
|
|
1617
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1618
|
-
ui.Button,
|
|
1619
|
-
{
|
|
1620
|
-
type: "button",
|
|
1621
|
-
variant: "secondary",
|
|
1622
|
-
onClick: onClose,
|
|
1623
|
-
disabled: isSaving,
|
|
1624
|
-
children: "ยกเลิก"
|
|
1625
|
-
}
|
|
1626
|
-
),
|
|
2160
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { type: "button", variant: "secondary", onClick: onClose, disabled: isSaving, children: "ยกเลิก" }),
|
|
1627
2161
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { type: "submit", disabled: isSaving, children: isSaving ? "กำลังบันทึก..." : "บันทึก" })
|
|
1628
2162
|
] })
|
|
1629
2163
|
] }) })
|
|
1630
2164
|
] }) });
|
|
1631
2165
|
};
|
|
1632
|
-
const
|
|
2166
|
+
const CARRIER_TYPES = [
|
|
1633
2167
|
{ value: "ALL", label: "ทั้งหมด" },
|
|
1634
|
-
{ value: "
|
|
1635
|
-
{ value: "
|
|
1636
|
-
{ value: "
|
|
1637
|
-
{ value: "TAPE", label: "เทป/กาว" },
|
|
1638
|
-
{ value: "LABEL", label: "ฉลาก/สติกเกอร์" },
|
|
1639
|
-
{ value: "OTHER", label: "อื่นๆ" }
|
|
2168
|
+
{ value: "COMPANY_FLEET", label: "บริษัทรถส่งของ (Messenger)" },
|
|
2169
|
+
{ value: "COMPANY_TRUCK", label: "รถบริษัท (Same Day)" },
|
|
2170
|
+
{ value: "PRIVATE_CARRIER", label: "ขนส่งเอกชน (EMS/Express)" }
|
|
1640
2171
|
];
|
|
1641
|
-
const
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
2172
|
+
const SERVICE_CODES = [
|
|
2173
|
+
{ value: "ALL", label: "ทั้งหมด" },
|
|
2174
|
+
{ value: "MESSENGER_3H", label: "ส่งด่วน 3 ชม." },
|
|
2175
|
+
{ value: "SAME_DAY", label: "ส่งด่วนภายในวัน" },
|
|
2176
|
+
{ value: "STANDARD_3_5D", label: "EMS 3-5 วัน" },
|
|
2177
|
+
{ value: "EXPRESS_1_2D", label: "Express 1-2 วัน" }
|
|
2178
|
+
];
|
|
2179
|
+
const ShippingRatesTable = () => {
|
|
2180
|
+
const [rates, setRates] = react.useState([]);
|
|
2181
|
+
const [filteredRates, setFilteredRates] = react.useState([]);
|
|
2182
|
+
const [carrierFilter, setCarrierFilter] = react.useState("ALL");
|
|
2183
|
+
const [serviceFilter, setServiceFilter] = react.useState("ALL");
|
|
1646
2184
|
const [isModalOpen, setIsModalOpen] = react.useState(false);
|
|
1647
|
-
const [
|
|
2185
|
+
const [editingRate, setEditingRate] = react.useState(null);
|
|
1648
2186
|
const [isLoading, setIsLoading] = react.useState(false);
|
|
1649
|
-
const [
|
|
1650
|
-
const [deleteMaterialCostName, setDeleteMaterialCostName] = react.useState("");
|
|
2187
|
+
const [deleteRateId, setDeleteRateId] = react.useState(null);
|
|
1651
2188
|
react.useEffect(() => {
|
|
1652
|
-
|
|
2189
|
+
fetchRates();
|
|
1653
2190
|
}, []);
|
|
1654
2191
|
react.useEffect(() => {
|
|
1655
|
-
let filtered =
|
|
1656
|
-
if (
|
|
1657
|
-
filtered = filtered.filter((
|
|
2192
|
+
let filtered = rates;
|
|
2193
|
+
if (carrierFilter !== "ALL") {
|
|
2194
|
+
filtered = filtered.filter((rate) => rate.carrier_type === carrierFilter);
|
|
1658
2195
|
}
|
|
1659
|
-
if (
|
|
1660
|
-
filtered = filtered.filter(
|
|
1661
|
-
(mc) => mc.name.toLowerCase().includes(searchTerm.toLowerCase())
|
|
1662
|
-
);
|
|
2196
|
+
if (serviceFilter !== "ALL") {
|
|
2197
|
+
filtered = filtered.filter((rate) => rate.service_code === serviceFilter);
|
|
1663
2198
|
}
|
|
1664
|
-
|
|
1665
|
-
}, [
|
|
1666
|
-
const
|
|
2199
|
+
setFilteredRates(filtered);
|
|
2200
|
+
}, [carrierFilter, serviceFilter, rates]);
|
|
2201
|
+
const fetchRates = async () => {
|
|
1667
2202
|
setIsLoading(true);
|
|
1668
2203
|
try {
|
|
1669
|
-
const response = await fetch("/admin/
|
|
2204
|
+
const response = await fetch("/admin/shipping-rates", {
|
|
1670
2205
|
credentials: "include"
|
|
1671
2206
|
});
|
|
1672
2207
|
const data = await response.json();
|
|
1673
|
-
|
|
2208
|
+
setRates(data.rates || []);
|
|
1674
2209
|
} catch (error) {
|
|
1675
2210
|
ui.toast.error("ข้อผิดพลาด", {
|
|
1676
|
-
description: "
|
|
2211
|
+
description: "ไม่สามารถโหลดข้อมูลอัตราค่าขนส่งได้"
|
|
1677
2212
|
});
|
|
1678
2213
|
} finally {
|
|
1679
2214
|
setIsLoading(false);
|
|
1680
2215
|
}
|
|
1681
2216
|
};
|
|
1682
|
-
const handleToggleActive = async (materialCost) => {
|
|
1683
|
-
try {
|
|
1684
|
-
const response = await fetch(`/admin/material-costs/${materialCost.id}`, {
|
|
1685
|
-
method: "PUT",
|
|
1686
|
-
headers: { "Content-Type": "application/json" },
|
|
1687
|
-
credentials: "include",
|
|
1688
|
-
body: JSON.stringify({ ...materialCost, active: !materialCost.active })
|
|
1689
|
-
});
|
|
1690
|
-
if (response.ok) {
|
|
1691
|
-
ui.toast.success("สำเร็จ", {
|
|
1692
|
-
description: `${materialCost.active ? "ปิดใช้งาน" : "เปิดใช้งาน"}วัสดุ ${materialCost.name} แล้ว`
|
|
1693
|
-
});
|
|
1694
|
-
fetchMaterialCosts();
|
|
1695
|
-
} else {
|
|
1696
|
-
throw new Error("Failed to update");
|
|
1697
|
-
}
|
|
1698
|
-
} catch (error) {
|
|
1699
|
-
ui.toast.error("ข้อผิดพลาด", {
|
|
1700
|
-
description: "ไม่สามารถอัพเดทสถานะได้"
|
|
1701
|
-
});
|
|
1702
|
-
}
|
|
1703
|
-
};
|
|
1704
2217
|
const handleDelete = async () => {
|
|
1705
|
-
if (!
|
|
2218
|
+
if (!deleteRateId) return;
|
|
1706
2219
|
try {
|
|
1707
|
-
const response = await fetch(
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
credentials: "include"
|
|
1712
|
-
}
|
|
1713
|
-
);
|
|
2220
|
+
const response = await fetch(`/admin/shipping-rates/${deleteRateId}`, {
|
|
2221
|
+
method: "DELETE",
|
|
2222
|
+
credentials: "include"
|
|
2223
|
+
});
|
|
1714
2224
|
if (response.ok) {
|
|
1715
2225
|
ui.toast.success("สำเร็จ", {
|
|
1716
|
-
description:
|
|
2226
|
+
description: "ลบอัตราค่าขนส่งแล้ว"
|
|
1717
2227
|
});
|
|
1718
|
-
|
|
2228
|
+
fetchRates();
|
|
1719
2229
|
} else {
|
|
1720
2230
|
throw new Error("Failed to delete");
|
|
1721
2231
|
}
|
|
1722
2232
|
} catch (error) {
|
|
1723
2233
|
ui.toast.error("ข้อผิดพลาด", {
|
|
1724
|
-
description: "
|
|
2234
|
+
description: "ไม่สามารถลบอัตราค่าขนส่งได้"
|
|
1725
2235
|
});
|
|
1726
2236
|
} finally {
|
|
1727
|
-
|
|
1728
|
-
setDeleteMaterialCostName("");
|
|
2237
|
+
setDeleteRateId(null);
|
|
1729
2238
|
}
|
|
1730
2239
|
};
|
|
1731
|
-
const handleEdit = (
|
|
1732
|
-
|
|
2240
|
+
const handleEdit = (rate) => {
|
|
2241
|
+
setEditingRate(rate);
|
|
1733
2242
|
setIsModalOpen(true);
|
|
1734
2243
|
};
|
|
1735
2244
|
const handleCreateNew = () => {
|
|
1736
|
-
|
|
2245
|
+
setEditingRate(null);
|
|
1737
2246
|
setIsModalOpen(true);
|
|
1738
2247
|
};
|
|
1739
2248
|
const handleModalClose = () => {
|
|
1740
2249
|
setIsModalOpen(false);
|
|
1741
|
-
|
|
1742
|
-
|
|
2250
|
+
setEditingRate(null);
|
|
2251
|
+
fetchRates();
|
|
1743
2252
|
};
|
|
1744
|
-
const
|
|
1745
|
-
|
|
1746
|
-
|
|
2253
|
+
const getCarrierLabel = (type) => {
|
|
2254
|
+
var _a;
|
|
2255
|
+
return ((_a = CARRIER_TYPES.find((c) => c.value === type)) == null ? void 0 : _a.label) || type;
|
|
1747
2256
|
};
|
|
1748
|
-
const
|
|
2257
|
+
const getServiceLabel = (code) => {
|
|
1749
2258
|
var _a;
|
|
1750
|
-
|
|
1751
|
-
|
|
2259
|
+
return ((_a = SERVICE_CODES.find((s) => s.value === code)) == null ? void 0 : _a.label) || code;
|
|
2260
|
+
};
|
|
2261
|
+
const formatETA = (rate) => {
|
|
2262
|
+
if (rate.eta_hours_min !== null && rate.eta_hours_min !== void 0 && rate.eta_hours_max !== null && rate.eta_hours_max !== void 0) {
|
|
2263
|
+
return `${rate.eta_hours_min}-${rate.eta_hours_max} ชม.`;
|
|
2264
|
+
}
|
|
2265
|
+
if (rate.eta_days_min !== null && rate.eta_days_min !== void 0 && rate.eta_days_max !== null && rate.eta_days_max !== void 0) {
|
|
2266
|
+
return `${rate.eta_days_min}-${rate.eta_days_max} วัน`;
|
|
2267
|
+
}
|
|
2268
|
+
return "-";
|
|
1752
2269
|
};
|
|
1753
2270
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
1754
2271
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-4", children: [
|
|
1755
2272
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-x-4", children: [
|
|
1756
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-x-4
|
|
1757
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1758
|
-
|
|
1759
|
-
{
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
}
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
2273
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-x-4 items-end", children: [
|
|
2274
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-1", children: [
|
|
2275
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium text-ui-fg-subtle", children: "ประเภทขนส่ง" }),
|
|
2276
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Select, { value: carrierFilter, onValueChange: setCarrierFilter, children: [
|
|
2277
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, { placeholder: "ทั้งหมด" }) }),
|
|
2278
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Content, { children: CARRIER_TYPES.map((type) => /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: type.value, children: type.label }, type.value)) })
|
|
2279
|
+
] })
|
|
2280
|
+
] }),
|
|
2281
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-1", children: [
|
|
2282
|
+
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium text-ui-fg-subtle", children: "บริการจัดส่ง" }),
|
|
2283
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Select, { value: serviceFilter, onValueChange: setServiceFilter, children: [
|
|
2284
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, { placeholder: "ทั้งหมด" }) }),
|
|
2285
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Content, { children: SERVICE_CODES.map((service) => /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: service.value, children: service.label }, service.value)) })
|
|
2286
|
+
] })
|
|
1770
2287
|
] })
|
|
1771
2288
|
] }),
|
|
1772
2289
|
/* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { onClick: handleCreateNew, children: [
|
|
1773
2290
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, {}),
|
|
1774
|
-
"
|
|
2291
|
+
"สร้างอัตราใหม่"
|
|
1775
2292
|
] })
|
|
1776
2293
|
] }),
|
|
1777
2294
|
/* @__PURE__ */ jsxRuntime.jsxs(ui.Table, { children: [
|
|
1778
2295
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Header, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
|
|
1779
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "
|
|
1780
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "
|
|
1781
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "
|
|
1782
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "
|
|
1783
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "
|
|
2296
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "ประเภทขนส่ง" }),
|
|
2297
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "บริการ" }),
|
|
2298
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "น้ำหนัก ≤ (kg)" }),
|
|
2299
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "ราคา (THB)" }),
|
|
2300
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "ETA" }),
|
|
1784
2301
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "สถานะ" }),
|
|
1785
2302
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { className: "text-right", children: "การจัดการ" })
|
|
1786
2303
|
] }) }),
|
|
1787
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Body, { children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Row, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "text-center", children: "กำลังโหลด..." }) }) :
|
|
1788
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children:
|
|
1789
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children:
|
|
1790
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: materialCost.unit }),
|
|
2304
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Body, { children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Row, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "text-center", children: "กำลังโหลด..." }) }) : filteredRates.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Row, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "text-center", children: "ไม่พบข้อมูลอัตราค่าขนส่ง" }) }) : filteredRates.map((rate) => /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
|
|
2305
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: getCarrierLabel(rate.carrier_type) }),
|
|
2306
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: getServiceLabel(rate.service_code) }),
|
|
1791
2307
|
/* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Cell, { children: [
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
2308
|
+
"≤ ",
|
|
2309
|
+
rate.max_weight_kg,
|
|
2310
|
+
" kg"
|
|
1795
2311
|
] }),
|
|
1796
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, {
|
|
1797
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
1798
|
-
|
|
1799
|
-
{
|
|
1800
|
-
color: materialCost.active ? "green" : "grey",
|
|
1801
|
-
className: "cursor-pointer",
|
|
1802
|
-
onClick: () => handleToggleActive(materialCost),
|
|
1803
|
-
children: materialCost.active ? "เปิดใช้งาน" : "ปิดใช้งาน"
|
|
1804
|
-
}
|
|
1805
|
-
) }),
|
|
2312
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: rate.price.toFixed(2) }),
|
|
2313
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { color: "blue", children: formatETA(rate) }) }),
|
|
2314
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { color: rate.active ? "green" : "grey", children: rate.active ? "เปิดใช้งาน" : "ปิดใช้งาน" }) }),
|
|
1806
2315
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "text-right", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
|
|
1807
2316
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1808
2317
|
ui.Button,
|
|
1809
2318
|
{
|
|
1810
2319
|
variant: "transparent",
|
|
1811
2320
|
size: "small",
|
|
1812
|
-
onClick: () => handleEdit(
|
|
2321
|
+
onClick: () => handleEdit(rate),
|
|
1813
2322
|
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Edit, {})
|
|
1814
2323
|
}
|
|
1815
2324
|
),
|
|
@@ -1818,38 +2327,25 @@ const MaterialCostsTable = () => {
|
|
|
1818
2327
|
{
|
|
1819
2328
|
variant: "transparent",
|
|
1820
2329
|
size: "small",
|
|
1821
|
-
onClick: () =>
|
|
2330
|
+
onClick: () => setDeleteRateId(rate.id),
|
|
1822
2331
|
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash, {})
|
|
1823
2332
|
}
|
|
1824
2333
|
)
|
|
1825
2334
|
] }) })
|
|
1826
|
-
] },
|
|
2335
|
+
] }, rate.id)) })
|
|
1827
2336
|
] })
|
|
1828
2337
|
] }),
|
|
1829
|
-
isModalOpen && /* @__PURE__ */ jsxRuntime.jsx(
|
|
1830
|
-
MaterialCostModal,
|
|
1831
|
-
{
|
|
1832
|
-
materialCost: editingMaterialCost,
|
|
1833
|
-
onClose: handleModalClose
|
|
1834
|
-
}
|
|
1835
|
-
),
|
|
2338
|
+
isModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ShippingRateModal, { rate: editingRate, onClose: handleModalClose }),
|
|
1836
2339
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
1837
2340
|
ui.Prompt,
|
|
1838
2341
|
{
|
|
1839
2342
|
variant: "confirmation",
|
|
1840
|
-
open: !!
|
|
1841
|
-
onOpenChange: () =>
|
|
1842
|
-
setDeleteMaterialCostId(null);
|
|
1843
|
-
setDeleteMaterialCostName("");
|
|
1844
|
-
},
|
|
2343
|
+
open: !!deleteRateId,
|
|
2344
|
+
onOpenChange: () => setDeleteRateId(null),
|
|
1845
2345
|
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Prompt.Content, { children: [
|
|
1846
2346
|
/* @__PURE__ */ jsxRuntime.jsxs(ui.Prompt.Header, { children: [
|
|
1847
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Prompt.Title, { children: "
|
|
1848
|
-
/* @__PURE__ */ jsxRuntime.
|
|
1849
|
-
'คุณต้องการลบวัสดุ "',
|
|
1850
|
-
deleteMaterialCostName,
|
|
1851
|
-
'" ใช่หรือไม่? การดำเนินการนี้ไม่สามารถย้อนกลับได้'
|
|
1852
|
-
] })
|
|
2347
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Prompt.Title, { children: "ลบอัตราค่าขนส่ง" }),
|
|
2348
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Prompt.Description, { children: "คุณต้องการลบอัตราค่าขนส่งนี้ใช่หรือไม่? การดำเนินการนี้ไม่สามารถย้อนกลับได้" })
|
|
1853
2349
|
] }),
|
|
1854
2350
|
/* @__PURE__ */ jsxRuntime.jsxs(ui.Prompt.Footer, { children: [
|
|
1855
2351
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Prompt.Cancel, { children: "ยกเลิก" }),
|
|
@@ -1860,59 +2356,26 @@ const MaterialCostsTable = () => {
|
|
|
1860
2356
|
)
|
|
1861
2357
|
] });
|
|
1862
2358
|
};
|
|
1863
|
-
const
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
] }) });
|
|
1868
|
-
};
|
|
1869
|
-
const config$1 = adminSdk.defineRouteConfig({
|
|
1870
|
-
icon: icons.CurrencyDollarSolid,
|
|
1871
|
-
label: "ต้นทุนวัสดุ"
|
|
1872
|
-
});
|
|
1873
|
-
const CARRIER_TYPES$1 = [
|
|
1874
|
-
{ value: "COMPANY_FLEET", label: "บริษัทรถส่งของ (Messenger)" },
|
|
1875
|
-
{ value: "COMPANY_TRUCK", label: "รถบริษัท (Same Day)" },
|
|
1876
|
-
{ value: "PRIVATE_CARRIER", label: "ขนส่งเอกชน (EMS/Express)" }
|
|
1877
|
-
];
|
|
1878
|
-
const SERVICE_CODES$1 = [
|
|
1879
|
-
{ value: "MESSENGER_3H", label: "ส่งด่วน 3 ชม.", usesHours: true },
|
|
1880
|
-
{ value: "SAME_DAY", label: "ส่งด่วนภายในวัน", usesHours: true },
|
|
1881
|
-
{ value: "STANDARD_3_5D", label: "EMS 3-5 วัน", usesHours: false },
|
|
1882
|
-
{ value: "EXPRESS_1_2D", label: "Express 1-2 วัน", usesHours: false }
|
|
1883
|
-
];
|
|
1884
|
-
const ShippingRateModal = ({ rate, onClose }) => {
|
|
2359
|
+
const CompanyTruckBaseRateModal = ({
|
|
2360
|
+
rate,
|
|
2361
|
+
onClose
|
|
2362
|
+
}) => {
|
|
1885
2363
|
const [formData, setFormData] = react.useState({
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
max_weight_kg: "",
|
|
2364
|
+
min_distance_km: "0",
|
|
2365
|
+
max_distance_km: "",
|
|
1889
2366
|
price: "",
|
|
1890
|
-
currency: "THB",
|
|
1891
2367
|
priority: "0",
|
|
1892
|
-
eta_hours_min: "",
|
|
1893
|
-
eta_hours_max: "",
|
|
1894
|
-
eta_days_min: "",
|
|
1895
|
-
eta_days_max: "",
|
|
1896
2368
|
active: true
|
|
1897
2369
|
});
|
|
1898
2370
|
const [isSaving, setIsSaving] = react.useState(false);
|
|
1899
|
-
const selectedService = SERVICE_CODES$1.find((s) => s.value === formData.service_code);
|
|
1900
|
-
const usesHours = (selectedService == null ? void 0 : selectedService.usesHours) ?? false;
|
|
1901
|
-
const isMessenger = formData.carrier_type === "COMPANY_FLEET" && formData.service_code === "MESSENGER_3H";
|
|
1902
2371
|
react.useEffect(() => {
|
|
1903
|
-
var _a, _b
|
|
2372
|
+
var _a, _b;
|
|
1904
2373
|
if (rate) {
|
|
1905
2374
|
setFormData({
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
max_weight_kg: rate.max_weight_kg.toString(),
|
|
2375
|
+
min_distance_km: ((_a = rate.min_distance_km) == null ? void 0 : _a.toString()) ?? "0",
|
|
2376
|
+
max_distance_km: ((_b = rate.max_distance_km) == null ? void 0 : _b.toString()) || "",
|
|
1909
2377
|
price: rate.price.toString(),
|
|
1910
|
-
currency: rate.currency,
|
|
1911
2378
|
priority: (rate.priority ?? 0).toString(),
|
|
1912
|
-
eta_hours_min: ((_a = rate.eta_hours_min) == null ? void 0 : _a.toString()) || "",
|
|
1913
|
-
eta_hours_max: ((_b = rate.eta_hours_max) == null ? void 0 : _b.toString()) || "",
|
|
1914
|
-
eta_days_min: ((_c = rate.eta_days_min) == null ? void 0 : _c.toString()) || "",
|
|
1915
|
-
eta_days_max: ((_d = rate.eta_days_max) == null ? void 0 : _d.toString()) || "",
|
|
1916
2379
|
active: rate.active
|
|
1917
2380
|
});
|
|
1918
2381
|
}
|
|
@@ -1920,11 +2383,16 @@ const ShippingRateModal = ({ rate, onClose }) => {
|
|
|
1920
2383
|
const handleSubmit = async (e) => {
|
|
1921
2384
|
e.preventDefault();
|
|
1922
2385
|
const errors = [];
|
|
1923
|
-
const
|
|
2386
|
+
const minDistance = parseFloat(formData.min_distance_km || "0");
|
|
2387
|
+
const hasMaxDistance = formData.max_distance_km !== "";
|
|
2388
|
+
const maxDistance = hasMaxDistance ? parseFloat(formData.max_distance_km) : void 0;
|
|
1924
2389
|
const price = parseFloat(formData.price);
|
|
1925
|
-
const priority = parseInt(formData.priority);
|
|
1926
|
-
if (isNaN(
|
|
1927
|
-
errors.push("
|
|
2390
|
+
const priority = parseInt(formData.priority || "0", 10);
|
|
2391
|
+
if (isNaN(minDistance) || minDistance < 0) {
|
|
2392
|
+
errors.push("ระยะทางเริ่มต้นต้องไม่ติดลบ");
|
|
2393
|
+
}
|
|
2394
|
+
if (hasMaxDistance && (maxDistance === void 0 || isNaN(maxDistance) || (maxDistance ?? 0) < minDistance)) {
|
|
2395
|
+
errors.push("ระยะทางสูงสุดต้องมากกว่าหรือเท่ากับระยะทางเริ่มต้น");
|
|
1928
2396
|
}
|
|
1929
2397
|
if (isNaN(price) || price < 0) {
|
|
1930
2398
|
errors.push("ราคาต้องเป็นตัวเลขไม่ติดลบ");
|
|
@@ -1932,27 +2400,6 @@ const ShippingRateModal = ({ rate, onClose }) => {
|
|
|
1932
2400
|
if (isNaN(priority)) {
|
|
1933
2401
|
errors.push("ลำดับความสำคัญต้องเป็นตัวเลข");
|
|
1934
2402
|
}
|
|
1935
|
-
let etaHoursMin;
|
|
1936
|
-
let etaHoursMax;
|
|
1937
|
-
let etaDaysMin;
|
|
1938
|
-
let etaDaysMax;
|
|
1939
|
-
if (usesHours) {
|
|
1940
|
-
etaHoursMin = formData.eta_hours_min ? parseFloat(formData.eta_hours_min) : void 0;
|
|
1941
|
-
etaHoursMax = formData.eta_hours_max ? parseFloat(formData.eta_hours_max) : void 0;
|
|
1942
|
-
if (etaHoursMin === void 0 || etaHoursMax === void 0) {
|
|
1943
|
-
errors.push("กรุณากรอก ETA เป็นชั่วโมงให้ครบ");
|
|
1944
|
-
} else if (etaHoursMin > etaHoursMax) {
|
|
1945
|
-
errors.push("ETA ชั่วโมงต่ำสุดต้องน้อยกว่าหรือเท่ากับสูงสุด");
|
|
1946
|
-
}
|
|
1947
|
-
} else {
|
|
1948
|
-
etaDaysMin = formData.eta_days_min ? parseFloat(formData.eta_days_min) : void 0;
|
|
1949
|
-
etaDaysMax = formData.eta_days_max ? parseFloat(formData.eta_days_max) : void 0;
|
|
1950
|
-
if (etaDaysMin === void 0 || etaDaysMax === void 0) {
|
|
1951
|
-
errors.push("กรุณากรอก ETA เป็นวันให้ครบ");
|
|
1952
|
-
} else if (etaDaysMin > etaDaysMax) {
|
|
1953
|
-
errors.push("ETA วันต่ำสุดต้องน้อยกว่าหรือเท่ากับสูงสุด");
|
|
1954
|
-
}
|
|
1955
|
-
}
|
|
1956
2403
|
if (errors.length > 0) {
|
|
1957
2404
|
ui.toast.error("ข้อมูลไม่ถูกต้อง", {
|
|
1958
2405
|
description: errors.join(", ")
|
|
@@ -1962,22 +2409,17 @@ const ShippingRateModal = ({ rate, onClose }) => {
|
|
|
1962
2409
|
setIsSaving(true);
|
|
1963
2410
|
try {
|
|
1964
2411
|
const payload = {
|
|
1965
|
-
carrier_type:
|
|
1966
|
-
|
|
1967
|
-
|
|
2412
|
+
carrier_type: "COMPANY_TRUCK",
|
|
2413
|
+
carrier: "COMPANY_TRUCK",
|
|
2414
|
+
service_code: "SAME_DAY",
|
|
2415
|
+
min_distance_km: minDistance,
|
|
2416
|
+
max_distance_km: maxDistance === void 0 || isNaN(maxDistance) ? null : maxDistance,
|
|
1968
2417
|
price,
|
|
1969
|
-
currency:
|
|
2418
|
+
currency: "THB",
|
|
1970
2419
|
priority,
|
|
1971
2420
|
active: formData.active
|
|
1972
2421
|
};
|
|
1973
|
-
|
|
1974
|
-
payload.eta_hours_min = etaHoursMin;
|
|
1975
|
-
payload.eta_hours_max = etaHoursMax;
|
|
1976
|
-
} else {
|
|
1977
|
-
payload.eta_days_min = etaDaysMin;
|
|
1978
|
-
payload.eta_days_max = etaDaysMax;
|
|
1979
|
-
}
|
|
1980
|
-
const url = rate ? `/admin/shipping-rates/${rate.id}` : "/admin/shipping-rates";
|
|
2422
|
+
const url = rate ? `/admin/base-shipping-prices/${rate.id}` : "/admin/base-shipping-prices";
|
|
1981
2423
|
const method = rate ? "PUT" : "POST";
|
|
1982
2424
|
const response = await fetch(url, {
|
|
1983
2425
|
method,
|
|
@@ -1985,15 +2427,14 @@ const ShippingRateModal = ({ rate, onClose }) => {
|
|
|
1985
2427
|
credentials: "include",
|
|
1986
2428
|
body: JSON.stringify(payload)
|
|
1987
2429
|
});
|
|
1988
|
-
if (response.ok) {
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
});
|
|
1992
|
-
onClose();
|
|
1993
|
-
} else {
|
|
1994
|
-
const error = await response.json();
|
|
1995
|
-
throw new Error(error.message || "Failed to save");
|
|
2430
|
+
if (!response.ok) {
|
|
2431
|
+
const error = await response.json().catch(() => ({}));
|
|
2432
|
+
throw new Error(error.message || "ไม่สามารถบันทึกข้อมูลได้");
|
|
1996
2433
|
}
|
|
2434
|
+
ui.toast.success("สำเร็จ", {
|
|
2435
|
+
description: rate ? "แก้ไขฐานราคาตามระยะทางแล้ว" : "สร้างฐานราคาตามระยะทางใหม่แล้ว"
|
|
2436
|
+
});
|
|
2437
|
+
onClose();
|
|
1997
2438
|
} catch (error) {
|
|
1998
2439
|
ui.toast.error("ข้อผิดพลาด", {
|
|
1999
2440
|
description: error instanceof Error ? error.message : "ไม่สามารถบันทึกข้อมูลได้"
|
|
@@ -2003,85 +2444,56 @@ const ShippingRateModal = ({ rate, onClose }) => {
|
|
|
2003
2444
|
}
|
|
2004
2445
|
};
|
|
2005
2446
|
return /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer, { open: true, onOpenChange: (open) => !open && onClose(), children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Drawer.Content, { children: [
|
|
2006
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Title, { children: rate ? "
|
|
2447
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Header, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Title, { children: rate ? "แก้ไขฐานราคาตามระยะทาง (รถบริษัท)" : "สร้างฐานราคาตามระยะทาง (รถบริษัท)" }) }),
|
|
2007
2448
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Drawer.Body, { children: /* @__PURE__ */ jsxRuntime.jsxs("form", { onSubmit: handleSubmit, className: "flex flex-col gap-y-4", children: [
|
|
2008
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2009
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "carrier", children: "ประเภทขนส่ง *" }),
|
|
2010
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2011
|
-
ui.Select,
|
|
2012
|
-
{
|
|
2013
|
-
value: formData.carrier_type,
|
|
2014
|
-
onValueChange: (value) => setFormData({ ...formData, carrier_type: value }),
|
|
2015
|
-
children: [
|
|
2016
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, { placeholder: "เลือกประเภทขนส่ง" }) }),
|
|
2017
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Content, { children: CARRIER_TYPES$1.map((carrier) => /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: carrier.value, children: carrier.label }, carrier.value)) })
|
|
2018
|
-
]
|
|
2019
|
-
}
|
|
2020
|
-
)
|
|
2021
|
-
] }),
|
|
2022
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2023
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "service", children: "บริการจัดส่ง *" }),
|
|
2024
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2025
|
-
ui.Select,
|
|
2026
|
-
{
|
|
2027
|
-
value: formData.service_code,
|
|
2028
|
-
onValueChange: (value) => setFormData({
|
|
2029
|
-
...formData,
|
|
2030
|
-
service_code: value,
|
|
2031
|
-
eta_hours_min: "",
|
|
2032
|
-
eta_hours_max: "",
|
|
2033
|
-
eta_days_min: "",
|
|
2034
|
-
eta_days_max: ""
|
|
2035
|
-
}),
|
|
2036
|
-
children: [
|
|
2037
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, { placeholder: "เลือกบริการ" }) }),
|
|
2038
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Content, { children: SERVICE_CODES$1.map((service) => /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: service.value, children: service.label }, service.value)) })
|
|
2039
|
-
]
|
|
2040
|
-
}
|
|
2041
|
-
)
|
|
2042
|
-
] }),
|
|
2043
|
-
isMessenger && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-ui-border-base bg-ui-bg-subtle p-3 text-sm space-y-1", children: [
|
|
2044
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-semibold text-ui-fg-base", children: "ฐานราคาตามระยะทาง (Messenger)" }),
|
|
2045
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-ui-fg-subtle", children: "ตั้งช่วงราคาตามระยะทาง เช่น 0-5, 5-20, 20-30, 30+ กม. สำหรับบริการส่งด่วน 3 ชม." }),
|
|
2046
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { asChild: true, size: "small", variant: "secondary", children: /* @__PURE__ */ jsxRuntime.jsxs("a", { href: "/base-pricing", target: "_blank", rel: "noreferrer", children: [
|
|
2047
|
-
"จัดการฐานราคา",
|
|
2048
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { className: "ml-1 h-4 w-4" })
|
|
2049
|
-
] }) }) })
|
|
2050
|
-
] }),
|
|
2051
2449
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-x-4", children: [
|
|
2052
2450
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2053
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "
|
|
2451
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "min_distance_km", children: "ระยะทางเริ่มต้น (กม.) *" }),
|
|
2054
2452
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2055
2453
|
ui.Input,
|
|
2056
2454
|
{
|
|
2057
|
-
id: "
|
|
2455
|
+
id: "min_distance_km",
|
|
2058
2456
|
type: "number",
|
|
2059
|
-
step: "0.1",
|
|
2060
2457
|
min: "0",
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2458
|
+
step: "0.1",
|
|
2459
|
+
value: formData.min_distance_km,
|
|
2460
|
+
onChange: (e) => setFormData({ ...formData, min_distance_km: e.target.value }),
|
|
2064
2461
|
required: true
|
|
2065
2462
|
}
|
|
2066
2463
|
)
|
|
2067
2464
|
] }),
|
|
2068
2465
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2069
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "
|
|
2466
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "max_distance_km", children: "ระยะทางสูงสุด (กม.)" }),
|
|
2070
2467
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2071
2468
|
ui.Input,
|
|
2072
2469
|
{
|
|
2073
|
-
id: "
|
|
2470
|
+
id: "max_distance_km",
|
|
2074
2471
|
type: "number",
|
|
2075
|
-
step: "0.01",
|
|
2076
2472
|
min: "0",
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2473
|
+
step: "0.1",
|
|
2474
|
+
placeholder: "ปล่อยว่างหากไม่มีที่สิ้นสุด",
|
|
2475
|
+
value: formData.max_distance_km,
|
|
2476
|
+
onChange: (e) => setFormData({ ...formData, max_distance_km: e.target.value })
|
|
2081
2477
|
}
|
|
2082
|
-
)
|
|
2478
|
+
),
|
|
2479
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-ui-fg-subtle mt-1", children: "เว้นว่างเพื่อกำหนดช่วงราคาแบบ 30+ กม." })
|
|
2083
2480
|
] })
|
|
2084
2481
|
] }),
|
|
2482
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2483
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "price", children: "ราคา (THB) *" }),
|
|
2484
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2485
|
+
ui.Input,
|
|
2486
|
+
{
|
|
2487
|
+
id: "price",
|
|
2488
|
+
type: "number",
|
|
2489
|
+
min: "0",
|
|
2490
|
+
step: "0.01",
|
|
2491
|
+
value: formData.price,
|
|
2492
|
+
onChange: (e) => setFormData({ ...formData, price: e.target.value }),
|
|
2493
|
+
required: true
|
|
2494
|
+
}
|
|
2495
|
+
)
|
|
2496
|
+
] }),
|
|
2085
2497
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2086
2498
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "priority", children: "ลำดับความสำคัญ" }),
|
|
2087
2499
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2094,56 +2506,7 @@ const ShippingRateModal = ({ rate, onClose }) => {
|
|
|
2094
2506
|
placeholder: "0"
|
|
2095
2507
|
}
|
|
2096
2508
|
),
|
|
2097
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-ui-fg-subtle mt-1", children: "
|
|
2098
|
-
] }),
|
|
2099
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2100
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Label, { children: [
|
|
2101
|
-
usesHours ? "ETA (ชั่วโมง)" : "ETA (วัน)",
|
|
2102
|
-
" *"
|
|
2103
|
-
] }),
|
|
2104
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-2 gap-x-4 mt-2", children: usesHours ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2105
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2106
|
-
ui.Input,
|
|
2107
|
-
{
|
|
2108
|
-
type: "number",
|
|
2109
|
-
placeholder: "ต่ำสุด",
|
|
2110
|
-
value: formData.eta_hours_min,
|
|
2111
|
-
onChange: (e) => setFormData({ ...formData, eta_hours_min: e.target.value }),
|
|
2112
|
-
required: true
|
|
2113
|
-
}
|
|
2114
|
-
),
|
|
2115
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2116
|
-
ui.Input,
|
|
2117
|
-
{
|
|
2118
|
-
type: "number",
|
|
2119
|
-
placeholder: "สูงสุด",
|
|
2120
|
-
value: formData.eta_hours_max,
|
|
2121
|
-
onChange: (e) => setFormData({ ...formData, eta_hours_max: e.target.value }),
|
|
2122
|
-
required: true
|
|
2123
|
-
}
|
|
2124
|
-
)
|
|
2125
|
-
] }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2126
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2127
|
-
ui.Input,
|
|
2128
|
-
{
|
|
2129
|
-
type: "number",
|
|
2130
|
-
placeholder: "ต่ำสุด",
|
|
2131
|
-
value: formData.eta_days_min,
|
|
2132
|
-
onChange: (e) => setFormData({ ...formData, eta_days_min: e.target.value }),
|
|
2133
|
-
required: true
|
|
2134
|
-
}
|
|
2135
|
-
),
|
|
2136
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2137
|
-
ui.Input,
|
|
2138
|
-
{
|
|
2139
|
-
type: "number",
|
|
2140
|
-
placeholder: "สูงสุด",
|
|
2141
|
-
value: formData.eta_days_max,
|
|
2142
|
-
onChange: (e) => setFormData({ ...formData, eta_days_max: e.target.value }),
|
|
2143
|
-
required: true
|
|
2144
|
-
}
|
|
2145
|
-
)
|
|
2146
|
-
] }) })
|
|
2509
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-ui-fg-subtle mt-1", children: "ใช้สำหรับจัดลำดับเมื่อมีช่วงราคาทับกัน (ค่าเริ่มต้น 0)" })
|
|
2147
2510
|
] }),
|
|
2148
2511
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-x-2", children: [
|
|
2149
2512
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -2157,195 +2520,163 @@ const ShippingRateModal = ({ rate, onClose }) => {
|
|
|
2157
2520
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "active", children: "เปิดใช้งาน" })
|
|
2158
2521
|
] }),
|
|
2159
2522
|
/* @__PURE__ */ jsxRuntime.jsxs(ui.Drawer.Footer, { children: [
|
|
2160
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2523
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2524
|
+
ui.Button,
|
|
2525
|
+
{
|
|
2526
|
+
type: "button",
|
|
2527
|
+
variant: "secondary",
|
|
2528
|
+
onClick: onClose,
|
|
2529
|
+
disabled: isSaving,
|
|
2530
|
+
children: "ยกเลิก"
|
|
2531
|
+
}
|
|
2532
|
+
),
|
|
2161
2533
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Button, { type: "submit", disabled: isSaving, children: isSaving ? "กำลังบันทึก..." : "บันทึก" })
|
|
2162
2534
|
] })
|
|
2163
2535
|
] }) })
|
|
2164
2536
|
] }) });
|
|
2165
2537
|
};
|
|
2166
|
-
const
|
|
2167
|
-
{ value: "ALL", label: "ทั้งหมด" },
|
|
2168
|
-
{ value: "COMPANY_FLEET", label: "บริษัทรถส่งของ (Messenger)" },
|
|
2169
|
-
{ value: "COMPANY_TRUCK", label: "รถบริษัท (Same Day)" },
|
|
2170
|
-
{ value: "PRIVATE_CARRIER", label: "ขนส่งเอกชน (EMS/Express)" }
|
|
2171
|
-
];
|
|
2172
|
-
const SERVICE_CODES = [
|
|
2173
|
-
{ value: "ALL", label: "ทั้งหมด" },
|
|
2174
|
-
{ value: "MESSENGER_3H", label: "ส่งด่วน 3 ชม." },
|
|
2175
|
-
{ value: "SAME_DAY", label: "ส่งด่วนภายในวัน" },
|
|
2176
|
-
{ value: "STANDARD_3_5D", label: "EMS 3-5 วัน" },
|
|
2177
|
-
{ value: "EXPRESS_1_2D", label: "Express 1-2 วัน" }
|
|
2178
|
-
];
|
|
2179
|
-
const ShippingRatesTable = () => {
|
|
2538
|
+
const CompanyTruckBasePricingTable = () => {
|
|
2180
2539
|
const [rates, setRates] = react.useState([]);
|
|
2181
|
-
const [
|
|
2182
|
-
const [carrierFilter, setCarrierFilter] = react.useState("ALL");
|
|
2183
|
-
const [serviceFilter, setServiceFilter] = react.useState("ALL");
|
|
2540
|
+
const [isLoading, setIsLoading] = react.useState(false);
|
|
2184
2541
|
const [isModalOpen, setIsModalOpen] = react.useState(false);
|
|
2185
2542
|
const [editingRate, setEditingRate] = react.useState(null);
|
|
2186
|
-
const [
|
|
2187
|
-
const [deleteRateId, setDeleteRateId] = react.useState(null);
|
|
2543
|
+
const [deleteId, setDeleteId] = react.useState(null);
|
|
2188
2544
|
react.useEffect(() => {
|
|
2189
2545
|
fetchRates();
|
|
2190
2546
|
}, []);
|
|
2191
|
-
react.
|
|
2192
|
-
|
|
2193
|
-
|
|
2194
|
-
|
|
2195
|
-
|
|
2196
|
-
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2200
|
-
}, [
|
|
2547
|
+
const orderedRates = react.useMemo(() => {
|
|
2548
|
+
return [...rates].sort((a, b) => {
|
|
2549
|
+
if (a.min_distance_km !== b.min_distance_km) {
|
|
2550
|
+
return a.min_distance_km - b.min_distance_km;
|
|
2551
|
+
}
|
|
2552
|
+
const aMax = a.max_distance_km ?? Number.POSITIVE_INFINITY;
|
|
2553
|
+
const bMax = b.max_distance_km ?? Number.POSITIVE_INFINITY;
|
|
2554
|
+
return aMax - bMax;
|
|
2555
|
+
});
|
|
2556
|
+
}, [rates]);
|
|
2201
2557
|
const fetchRates = async () => {
|
|
2202
2558
|
setIsLoading(true);
|
|
2203
2559
|
try {
|
|
2204
|
-
const response = await fetch(
|
|
2205
|
-
|
|
2206
|
-
|
|
2560
|
+
const response = await fetch(
|
|
2561
|
+
"/admin/base-shipping-prices?carrier_type=COMPANY_TRUCK&service_code=SAME_DAY",
|
|
2562
|
+
{
|
|
2563
|
+
credentials: "include"
|
|
2564
|
+
}
|
|
2565
|
+
);
|
|
2566
|
+
if (!response.ok) {
|
|
2567
|
+
throw new Error("failed_to_load_base_rates");
|
|
2568
|
+
}
|
|
2207
2569
|
const data = await response.json();
|
|
2208
|
-
setRates(data.
|
|
2570
|
+
setRates(data.base_rates || []);
|
|
2209
2571
|
} catch (error) {
|
|
2210
2572
|
ui.toast.error("ข้อผิดพลาด", {
|
|
2211
|
-
description: "
|
|
2573
|
+
description: "ไม่สามารถโหลดฐานราคาตามระยะทางได้"
|
|
2212
2574
|
});
|
|
2213
2575
|
} finally {
|
|
2214
2576
|
setIsLoading(false);
|
|
2215
2577
|
}
|
|
2216
2578
|
};
|
|
2217
2579
|
const handleDelete = async () => {
|
|
2218
|
-
if (!
|
|
2580
|
+
if (!deleteId) return;
|
|
2219
2581
|
try {
|
|
2220
|
-
const response = await fetch(
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2224
|
-
|
|
2225
|
-
|
|
2226
|
-
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
} else {
|
|
2230
|
-
throw new Error("Failed to delete");
|
|
2582
|
+
const response = await fetch(
|
|
2583
|
+
`/admin/base-shipping-prices/${deleteId}`,
|
|
2584
|
+
{
|
|
2585
|
+
method: "DELETE",
|
|
2586
|
+
credentials: "include"
|
|
2587
|
+
}
|
|
2588
|
+
);
|
|
2589
|
+
if (!response.ok) {
|
|
2590
|
+
throw new Error("failed_to_delete");
|
|
2231
2591
|
}
|
|
2592
|
+
ui.toast.success("สำเร็จ", {
|
|
2593
|
+
description: "ลบฐานราคาสำเร็จ"
|
|
2594
|
+
});
|
|
2595
|
+
fetchRates();
|
|
2232
2596
|
} catch (error) {
|
|
2233
2597
|
ui.toast.error("ข้อผิดพลาด", {
|
|
2234
|
-
description: "
|
|
2598
|
+
description: "ไม่สามารถลบฐานราคาได้"
|
|
2235
2599
|
});
|
|
2236
2600
|
} finally {
|
|
2237
|
-
|
|
2601
|
+
setDeleteId(null);
|
|
2238
2602
|
}
|
|
2239
2603
|
};
|
|
2240
|
-
const handleEdit = (rate) => {
|
|
2241
|
-
setEditingRate(rate);
|
|
2242
|
-
setIsModalOpen(true);
|
|
2243
|
-
};
|
|
2244
|
-
const handleCreateNew = () => {
|
|
2245
|
-
setEditingRate(null);
|
|
2246
|
-
setIsModalOpen(true);
|
|
2247
|
-
};
|
|
2248
2604
|
const handleModalClose = () => {
|
|
2249
2605
|
setIsModalOpen(false);
|
|
2250
2606
|
setEditingRate(null);
|
|
2251
2607
|
fetchRates();
|
|
2252
2608
|
};
|
|
2253
|
-
const
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
var _a;
|
|
2259
|
-
return ((_a = SERVICE_CODES.find((s) => s.value === code)) == null ? void 0 : _a.label) || code;
|
|
2260
|
-
};
|
|
2261
|
-
const formatETA = (rate) => {
|
|
2262
|
-
if (rate.eta_hours_min !== null && rate.eta_hours_min !== void 0 && rate.eta_hours_max !== null && rate.eta_hours_max !== void 0) {
|
|
2263
|
-
return `${rate.eta_hours_min}-${rate.eta_hours_max} ชม.`;
|
|
2264
|
-
}
|
|
2265
|
-
if (rate.eta_days_min !== null && rate.eta_days_min !== void 0 && rate.eta_days_max !== null && rate.eta_days_max !== void 0) {
|
|
2266
|
-
return `${rate.eta_days_min}-${rate.eta_days_max} วัน`;
|
|
2609
|
+
const formatDistanceRange = (rate) => {
|
|
2610
|
+
const min = rate.min_distance_km ?? 0;
|
|
2611
|
+
const max = rate.max_distance_km;
|
|
2612
|
+
if (max === void 0 || max === null) {
|
|
2613
|
+
return `${min}+ กม.`;
|
|
2267
2614
|
}
|
|
2268
|
-
return
|
|
2615
|
+
return `${min}-${max} กม.`;
|
|
2269
2616
|
};
|
|
2270
2617
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
2271
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex
|
|
2272
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", {
|
|
2273
|
-
/* @__PURE__ */ jsxRuntime.
|
|
2274
|
-
|
|
2275
|
-
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium text-ui-fg-subtle", children: "ประเภทขนส่ง" }),
|
|
2276
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Select, { value: carrierFilter, onValueChange: setCarrierFilter, children: [
|
|
2277
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, { placeholder: "ทั้งหมด" }) }),
|
|
2278
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Content, { children: CARRIER_TYPES.map((type) => /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: type.value, children: type.label }, type.value)) })
|
|
2279
|
-
] })
|
|
2280
|
-
] }),
|
|
2281
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-1", children: [
|
|
2282
|
-
/* @__PURE__ */ jsxRuntime.jsx("label", { className: "text-sm font-medium text-ui-fg-subtle", children: "บริการจัดส่ง" }),
|
|
2283
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Select, { value: serviceFilter, onValueChange: setServiceFilter, children: [
|
|
2284
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, { placeholder: "ทั้งหมด" }) }),
|
|
2285
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Select.Content, { children: SERVICE_CODES.map((service) => /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: service.value, children: service.label }, service.value)) })
|
|
2286
|
-
] })
|
|
2287
|
-
] })
|
|
2288
|
-
] }),
|
|
2289
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { onClick: handleCreateNew, children: [
|
|
2290
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, {}),
|
|
2291
|
-
"สร้างอัตราใหม่"
|
|
2292
|
-
] })
|
|
2618
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-x-4", children: [
|
|
2619
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2620
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold", children: "ฐานราคาตามระยะทาง (รถบริษัท - Same Day)" }),
|
|
2621
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-ui-fg-subtle text-sm", children: "กำหนดราคาเริ่มต้นตามระยะทาง เช่น 0-10, 10-30, 30-50, 50+ กม." })
|
|
2293
2622
|
] }),
|
|
2294
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.
|
|
2295
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2296
|
-
|
|
2297
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "บริการ" }),
|
|
2298
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "น้ำหนัก ≤ (kg)" }),
|
|
2299
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "ราคา (THB)" }),
|
|
2300
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "ETA" }),
|
|
2301
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "สถานะ" }),
|
|
2302
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { className: "text-right", children: "การจัดการ" })
|
|
2303
|
-
] }) }),
|
|
2304
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Body, { children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Row, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "text-center", children: "กำลังโหลด..." }) }) : filteredRates.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Row, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "text-center", children: "ไม่พบข้อมูลอัตราค่าขนส่ง" }) }) : filteredRates.map((rate) => /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
|
|
2305
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: getCarrierLabel(rate.carrier_type) }),
|
|
2306
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: getServiceLabel(rate.service_code) }),
|
|
2307
|
-
/* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Cell, { children: [
|
|
2308
|
-
"≤ ",
|
|
2309
|
-
rate.max_weight_kg,
|
|
2310
|
-
" kg"
|
|
2311
|
-
] }),
|
|
2312
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: rate.price.toFixed(2) }),
|
|
2313
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { color: "blue", children: formatETA(rate) }) }),
|
|
2314
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { color: rate.active ? "green" : "grey", children: rate.active ? "เปิดใช้งาน" : "ปิดใช้งาน" }) }),
|
|
2315
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "text-right", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
|
|
2316
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2317
|
-
ui.Button,
|
|
2318
|
-
{
|
|
2319
|
-
variant: "transparent",
|
|
2320
|
-
size: "small",
|
|
2321
|
-
onClick: () => handleEdit(rate),
|
|
2322
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Edit, {})
|
|
2323
|
-
}
|
|
2324
|
-
),
|
|
2325
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2326
|
-
ui.Button,
|
|
2327
|
-
{
|
|
2328
|
-
variant: "transparent",
|
|
2329
|
-
size: "small",
|
|
2330
|
-
onClick: () => setDeleteRateId(rate.id),
|
|
2331
|
-
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash, {})
|
|
2332
|
-
}
|
|
2333
|
-
)
|
|
2334
|
-
] }) })
|
|
2335
|
-
] }, rate.id)) })
|
|
2623
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Button, { onClick: () => setIsModalOpen(true), children: [
|
|
2624
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, {}),
|
|
2625
|
+
"เพิ่มช่วงราคา"
|
|
2336
2626
|
] })
|
|
2337
2627
|
] }),
|
|
2338
|
-
|
|
2628
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Table, { className: "mt-4", children: [
|
|
2629
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Header, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
|
|
2630
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "ช่วงระยะทาง" }),
|
|
2631
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "ราคา (THB)" }),
|
|
2632
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "ลำดับ" }),
|
|
2633
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "สถานะ" }),
|
|
2634
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { className: "text-right", children: "การจัดการ" })
|
|
2635
|
+
] }) }),
|
|
2636
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Body, { children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Row, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { colSpan: 5, className: "text-center", children: "กำลังโหลด..." }) }) : orderedRates.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Row, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { colSpan: 5, className: "text-center", children: "ยังไม่ได้ตั้งค่าฐานราคาตามระยะทาง (รถบริษัทจะใช้ราคาตามน้ำหนัก)" }) }) : orderedRates.map((rate) => /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
|
|
2637
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: formatDistanceRange(rate) }),
|
|
2638
|
+
/* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Cell, { children: [
|
|
2639
|
+
"฿",
|
|
2640
|
+
rate.price.toFixed(2)
|
|
2641
|
+
] }),
|
|
2642
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: rate.priority ?? 0 }),
|
|
2643
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { color: rate.active ? "green" : "grey", children: rate.active ? "เปิดใช้งาน" : "ปิดใช้งาน" }) }),
|
|
2644
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "text-right", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
|
|
2645
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2646
|
+
ui.Button,
|
|
2647
|
+
{
|
|
2648
|
+
variant: "transparent",
|
|
2649
|
+
size: "small",
|
|
2650
|
+
onClick: () => {
|
|
2651
|
+
setEditingRate(rate);
|
|
2652
|
+
setIsModalOpen(true);
|
|
2653
|
+
},
|
|
2654
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Edit, {})
|
|
2655
|
+
}
|
|
2656
|
+
),
|
|
2657
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2658
|
+
ui.Button,
|
|
2659
|
+
{
|
|
2660
|
+
variant: "transparent",
|
|
2661
|
+
size: "small",
|
|
2662
|
+
onClick: () => setDeleteId(rate.id),
|
|
2663
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash, {})
|
|
2664
|
+
}
|
|
2665
|
+
)
|
|
2666
|
+
] }) })
|
|
2667
|
+
] }, rate.id)) })
|
|
2668
|
+
] }),
|
|
2669
|
+
isModalOpen && /* @__PURE__ */ jsxRuntime.jsx(CompanyTruckBaseRateModal, { rate: editingRate, onClose: handleModalClose }),
|
|
2339
2670
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2340
2671
|
ui.Prompt,
|
|
2341
2672
|
{
|
|
2342
2673
|
variant: "confirmation",
|
|
2343
|
-
open: !!
|
|
2344
|
-
onOpenChange: () =>
|
|
2674
|
+
open: !!deleteId,
|
|
2675
|
+
onOpenChange: () => setDeleteId(null),
|
|
2345
2676
|
children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Prompt.Content, { children: [
|
|
2346
2677
|
/* @__PURE__ */ jsxRuntime.jsxs(ui.Prompt.Header, { children: [
|
|
2347
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Prompt.Title, { children: "
|
|
2348
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Prompt.Description, { children: "
|
|
2678
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Prompt.Title, { children: "ลบฐานราคา" }),
|
|
2679
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Prompt.Description, { children: "คุณต้องการลบช่วงราคานี้ใช่หรือไม่? การดำเนินการนี้ไม่สามารถย้อนกลับได้" })
|
|
2349
2680
|
] }),
|
|
2350
2681
|
/* @__PURE__ */ jsxRuntime.jsxs(ui.Prompt.Footer, { children: [
|
|
2351
2682
|
/* @__PURE__ */ jsxRuntime.jsx(ui.Prompt.Cancel, { children: "ยกเลิก" }),
|
|
@@ -2361,8 +2692,12 @@ const RatesPage = () => {
|
|
|
2361
2692
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "อัตราค่าขนส่ง" }) }),
|
|
2362
2693
|
/* @__PURE__ */ jsxRuntime.jsx(ShippingRatesTable, {}),
|
|
2363
2694
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t pt-4", children: [
|
|
2364
|
-
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-2 text-lg", children: "ฐานราคาตามระยะทาง (Messenger)" }),
|
|
2695
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-2 text-lg", children: "ฐานราคาตามระยะทาง (Messenger 3H)" }),
|
|
2365
2696
|
/* @__PURE__ */ jsxRuntime.jsx(MessengerBasePricingTable, {})
|
|
2697
|
+
] }),
|
|
2698
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t pt-4", children: [
|
|
2699
|
+
/* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h2", className: "mb-2 text-lg", children: "ฐานราคาตามระยะทาง (รถบริษัท - Same Day)" }),
|
|
2700
|
+
/* @__PURE__ */ jsxRuntime.jsx(CompanyTruckBasePricingTable, {})
|
|
2366
2701
|
] })
|
|
2367
2702
|
] }) });
|
|
2368
2703
|
};
|
|
@@ -2378,6 +2713,10 @@ const widgetModule = { widgets: [
|
|
|
2378
2713
|
] };
|
|
2379
2714
|
const routeModule = {
|
|
2380
2715
|
routes: [
|
|
2716
|
+
{
|
|
2717
|
+
Component: AreasPage,
|
|
2718
|
+
path: "/areas"
|
|
2719
|
+
},
|
|
2381
2720
|
{
|
|
2382
2721
|
Component: BasePricingPage,
|
|
2383
2722
|
path: "/base-pricing"
|
|
@@ -2386,10 +2725,6 @@ const routeModule = {
|
|
|
2386
2725
|
Component: BoxesPage,
|
|
2387
2726
|
path: "/boxes"
|
|
2388
2727
|
},
|
|
2389
|
-
{
|
|
2390
|
-
Component: AreasPage,
|
|
2391
|
-
path: "/areas"
|
|
2392
|
-
},
|
|
2393
2728
|
{
|
|
2394
2729
|
Component: MaterialCostsPage,
|
|
2395
2730
|
path: "/material-costs"
|
|
@@ -2402,35 +2737,45 @@ const routeModule = {
|
|
|
2402
2737
|
};
|
|
2403
2738
|
const menuItemModule = {
|
|
2404
2739
|
menuItems: [
|
|
2405
|
-
{
|
|
2406
|
-
label: config$2.label,
|
|
2407
|
-
icon: config$2.icon,
|
|
2408
|
-
path: "/areas",
|
|
2409
|
-
nested: void 0
|
|
2410
|
-
},
|
|
2411
2740
|
{
|
|
2412
2741
|
label: config$4.label,
|
|
2413
2742
|
icon: config$4.icon,
|
|
2414
|
-
path: "/
|
|
2415
|
-
nested: void 0
|
|
2743
|
+
path: "/areas",
|
|
2744
|
+
nested: void 0,
|
|
2745
|
+
rank: void 0,
|
|
2746
|
+
translationNs: void 0
|
|
2416
2747
|
},
|
|
2417
2748
|
{
|
|
2418
2749
|
label: config$3.label,
|
|
2419
2750
|
icon: config$3.icon,
|
|
2751
|
+
path: "/base-pricing",
|
|
2752
|
+
nested: void 0,
|
|
2753
|
+
rank: void 0,
|
|
2754
|
+
translationNs: void 0
|
|
2755
|
+
},
|
|
2756
|
+
{
|
|
2757
|
+
label: config$2.label,
|
|
2758
|
+
icon: config$2.icon,
|
|
2420
2759
|
path: "/boxes",
|
|
2421
|
-
nested: void 0
|
|
2760
|
+
nested: void 0,
|
|
2761
|
+
rank: void 0,
|
|
2762
|
+
translationNs: void 0
|
|
2422
2763
|
},
|
|
2423
2764
|
{
|
|
2424
2765
|
label: config$1.label,
|
|
2425
2766
|
icon: config$1.icon,
|
|
2426
2767
|
path: "/material-costs",
|
|
2427
|
-
nested: void 0
|
|
2768
|
+
nested: void 0,
|
|
2769
|
+
rank: void 0,
|
|
2770
|
+
translationNs: void 0
|
|
2428
2771
|
},
|
|
2429
2772
|
{
|
|
2430
2773
|
label: config.label,
|
|
2431
2774
|
icon: config.icon,
|
|
2432
2775
|
path: "/rates",
|
|
2433
|
-
nested: void 0
|
|
2776
|
+
nested: void 0,
|
|
2777
|
+
rank: void 0,
|
|
2778
|
+
translationNs: void 0
|
|
2434
2779
|
}
|
|
2435
2780
|
]
|
|
2436
2781
|
};
|