@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$4 = adminSdk.defineRouteConfig({
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$3 = adminSdk.defineRouteConfig({
1426
+ const config$2 = adminSdk.defineRouteConfig({
988
1427
  icon: icons.ArchiveBox,
989
1428
  label: "กล่องพัสดุ"
990
1429
  });
991
- const TH_PROVINCES = [
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 ServiceAreaModal = ({ area, onClose }) => {
1438
+ const MaterialCostModal = ({
1439
+ materialCost,
1440
+ onClose
1441
+ }) => {
1071
1442
  const [formData, setFormData] = react.useState({
1072
- kind: "PROVINCE",
1073
- value: "",
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 (area) {
1453
+ if (materialCost) {
1079
1454
  setFormData({
1080
- kind: area.kind,
1081
- value: area.value,
1082
- active: area.active
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
- }, [area]);
1464
+ }, [materialCost]);
1086
1465
  const handleSubmit = async (e) => {
1087
1466
  e.preventDefault();
1088
1467
  const errors = [];
1089
- const trimmedValue = formData.value.trim();
1090
- if (!trimmedValue) {
1091
- errors.push("กรุณากรอกค่า");
1468
+ if (!formData.name.trim()) {
1469
+ errors.push("กรุณากรอกชื่อวัสดุ");
1092
1470
  }
1093
- if (formData.kind === "PROVINCE") {
1094
- if (!TH_PROVINCES.includes(trimmedValue)) {
1095
- errors.push("จังหวัดไม่ถูกต้อง กรุณาตรวจสอบการสะกดชื่อจังหวัด");
1096
- }
1097
- } else if (formData.kind === "POSTCODE_PREFIX") {
1098
- if (!/^\d{1,5}$/.test(trimmedValue)) {
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
- kind: formData.kind,
1112
- value: trimmedValue,
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 = area ? `/admin/service-areas/${area.id}` : "/admin/service-areas";
1116
- const method = area ? "PUT" : "POST";
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: area ? "แก้ไขพื้นที่บริการแล้ว" : "สร้างพื้นที่บริการใหม่แล้ว"
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: area ? "แก้ไขพื้นที่บริการ" : "สร้างพื้นที่บริการใหม่" }) }),
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: "kind", children: "ประเภท *" }),
1145
- /* @__PURE__ */ jsxRuntime.jsxs(
1146
- ui.Select,
1524
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "name", children: "ชื่อวัสดุ *" }),
1525
+ /* @__PURE__ */ jsxRuntime.jsx(
1526
+ ui.Input,
1147
1527
  {
1148
- value: formData.kind,
1149
- onValueChange: (value) => setFormData({ ...formData, kind: value, value: "" }),
1150
- required: true,
1151
- children: [
1152
- /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, { placeholder: "เลือกประเภท" }) }),
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: "value", children: formData.kind === "PROVINCE" ? "ชื่อจังหวัด *" : "รหัสไปรษณีย์ (1-5 หลัก) *" }),
1163
- formData.kind === "PROVINCE" ? /* @__PURE__ */ jsxRuntime.jsxs(
1537
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "category", children: "หมวดหมู่ (ไม่บังคับ)" }),
1538
+ /* @__PURE__ */ jsxRuntime.jsxs(
1164
1539
  ui.Select,
1165
1540
  {
1166
- value: formData.value,
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: TH_PROVINCES.map((province) => /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: province, children: province }, province)) })
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
- ) : /* @__PURE__ */ jsxRuntime.jsx(
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: "value",
1178
- type: "text",
1179
- value: formData.value,
1180
- onChange: (e) => setFormData({ ...formData, value: e.target.value }),
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
- formData.kind === "POSTCODE_PREFIX" && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-ui-fg-subtle mt-1", children: 'ใส่รหัส 1-5 หลักเพื่อครอบคลุมหลายพื้นที่ เช่น "10" = กรุงเทพฯ ทั้งหมด' })
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 AREA_KINDS = [
1632
+ const CATEGORIES = [
1217
1633
  { value: "ALL", label: "ทั้งหมด" },
1218
- { value: "PROVINCE", label: "จังหวัด" },
1219
- { value: "POSTCODE_PREFIX", label: "รหัสไปรษณีย์" }
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 ServiceAreasTable = () => {
1222
- const [areas, setAreas] = react.useState([]);
1223
- const [filteredAreas, setFilteredAreas] = react.useState([]);
1641
+ const MaterialCostsTable = () => {
1642
+ const [materialCosts, setMaterialCosts] = react.useState([]);
1643
+ const [filteredMaterialCosts, setFilteredMaterialCosts] = react.useState([]);
1224
1644
  const [searchTerm, setSearchTerm] = react.useState("");
1225
- const [kindFilter, setKindFilter] = react.useState("ALL");
1645
+ const [categoryFilter, setCategoryFilter] = react.useState("ALL");
1226
1646
  const [isModalOpen, setIsModalOpen] = react.useState(false);
1227
- const [editingArea, setEditingArea] = react.useState(null);
1647
+ const [editingMaterialCost, setEditingMaterialCost] = react.useState(null);
1228
1648
  const [isLoading, setIsLoading] = react.useState(false);
1229
- const [deleteAreaId, setDeleteAreaId] = react.useState(null);
1230
- const [deleteAreaValue, setDeleteAreaValue] = react.useState("");
1649
+ const [deleteMaterialCostId, setDeleteMaterialCostId] = react.useState(null);
1650
+ const [deleteMaterialCostName, setDeleteMaterialCostName] = react.useState("");
1231
1651
  react.useEffect(() => {
1232
- fetchAreas();
1652
+ fetchMaterialCosts();
1233
1653
  }, []);
1234
1654
  react.useEffect(() => {
1235
- let filtered = areas;
1236
- if (kindFilter !== "ALL") {
1237
- filtered = filtered.filter((area) => area.kind === kindFilter);
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
- (area) => area.value.toLowerCase().includes(searchTerm.toLowerCase())
1661
+ (mc) => mc.name.toLowerCase().includes(searchTerm.toLowerCase())
1242
1662
  );
1243
1663
  }
1244
- setFilteredAreas(filtered);
1245
- }, [searchTerm, kindFilter, areas]);
1246
- const fetchAreas = async () => {
1664
+ setFilteredMaterialCosts(filtered);
1665
+ }, [searchTerm, categoryFilter, materialCosts]);
1666
+ const fetchMaterialCosts = async () => {
1247
1667
  setIsLoading(true);
1248
1668
  try {
1249
- const response = await fetch("/admin/service-areas", {
1669
+ const response = await fetch("/admin/material-costs", {
1250
1670
  credentials: "include"
1251
1671
  });
1252
1672
  const data = await response.json();
1253
- console.log("Fetched service areas:", data);
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 (area) => {
1682
+ const handleToggleActive = async (materialCost) => {
1264
1683
  try {
1265
- const response = await fetch(`/admin/service-areas/${area.id}`, {
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({ ...area, active: !area.active })
1688
+ body: JSON.stringify({ ...materialCost, active: !materialCost.active })
1270
1689
  });
1271
1690
  if (response.ok) {
1272
1691
  ui.toast.success("สำเร็จ", {
1273
- description: `${area.active ? "ปิดใช้งาน" : "เปิดใช้งาน"}พื้นที่ ${area.value} แล้ว`
1692
+ description: `${materialCost.active ? "ปิดใช้งาน" : "เปิดใช้งาน"}วัสดุ ${materialCost.name} แล้ว`
1274
1693
  });
1275
- fetchAreas();
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 (!deleteAreaId) return;
1705
+ if (!deleteMaterialCostId) return;
1287
1706
  try {
1288
- const response = await fetch(`/admin/service-areas/${deleteAreaId}`, {
1289
- method: "DELETE",
1290
- credentials: "include"
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: `ลบพื้นที่ ${deleteAreaValue} แล้ว`
1716
+ description: `ลบวัสดุ ${deleteMaterialCostName} แล้ว`
1295
1717
  });
1296
- fetchAreas();
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
- setDeleteAreaId(null);
1306
- setDeleteAreaValue("");
1727
+ setDeleteMaterialCostId(null);
1728
+ setDeleteMaterialCostName("");
1307
1729
  }
1308
1730
  };
1309
- const handleEdit = (area) => {
1310
- setEditingArea(area);
1731
+ const handleEdit = (materialCost) => {
1732
+ setEditingMaterialCost(materialCost);
1311
1733
  setIsModalOpen(true);
1312
1734
  };
1313
1735
  const handleCreateNew = () => {
1314
- setEditingArea(null);
1736
+ setEditingMaterialCost(null);
1315
1737
  setIsModalOpen(true);
1316
1738
  };
1317
1739
  const handleModalClose = () => {
1318
1740
  setIsModalOpen(false);
1319
- setEditingArea(null);
1320
- fetchAreas();
1741
+ setEditingMaterialCost(null);
1742
+ fetchMaterialCosts();
1321
1743
  };
1322
- const openDeletePrompt = (id, value) => {
1323
- setDeleteAreaId(id);
1324
- setDeleteAreaValue(value);
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: kindFilter, onValueChange: setKindFilter, children: [
1341
- /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Trigger, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Value, { placeholder: "ประเภท" }) }),
1342
- /* @__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)) })
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: "กำลังโหลด..." }) }) : 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: [
1358
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(ui.Badge, { color: area.kind === "PROVINCE" ? "blue" : "purple", children: area.kind === "PROVINCE" ? "จังหวัด" : "รหัสไปรษณีย์" }) }),
1359
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: area.value }),
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: area.active ? "green" : "grey",
1800
+ color: materialCost.active ? "green" : "grey",
1364
1801
  className: "cursor-pointer",
1365
- onClick: () => handleToggleActive(area),
1366
- children: area.active ? "เปิดใช้งาน" : "ปิดใช้งาน"
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(area),
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(area.id, area.value),
1821
+ onClick: () => openDeletePrompt(materialCost.id, materialCost.name),
1385
1822
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash, {})
1386
1823
  }
1387
1824
  )
1388
1825
  ] }) })
1389
- ] }, area.id)) })
1826
+ ] }, materialCost.id)) })
1390
1827
  ] })
1391
1828
  ] }),
1392
- isModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ServiceAreaModal, { area: editingArea, onClose: handleModalClose }),
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: !!deleteAreaId,
1840
+ open: !!deleteMaterialCostId,
1398
1841
  onOpenChange: () => {
1399
- setDeleteAreaId(null);
1400
- setDeleteAreaValue("");
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
- deleteAreaValue,
1849
+ 'คุณต้องการลบวัสดุ "',
1850
+ deleteMaterialCostName,
1408
1851
  '" ใช่หรือไม่? การดำเนินการนี้ไม่สามารถย้อนกลับได้'
1409
1852
  ] })
1410
1853
  ] }),
@@ -1417,63 +1860,98 @@ const ServiceAreasTable = () => {
1417
1860
  )
1418
1861
  ] });
1419
1862
  };
1420
- const AreasPage = () => {
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(ServiceAreasTable, {})
1424
- ] }) });
1425
- };
1426
- const config$2 = adminSdk.defineRouteConfig({
1427
- icon: icons.MapPin,
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 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: "อื่นๆ" }
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 MaterialCostModal = ({
1439
- materialCost,
1440
- onClose
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
- name: "",
1444
- unit: "",
1445
- cost_per_unit: "",
1886
+ carrier_type: "COMPANY_FLEET",
1887
+ service_code: "MESSENGER_3H",
1888
+ max_weight_kg: "",
1889
+ price: "",
1446
1890
  currency: "THB",
1447
- category: "",
1448
- description: "",
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
- if (materialCost) {
1903
+ var _a, _b, _c, _d;
1904
+ if (rate) {
1454
1905
  setFormData({
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
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
- }, [materialCost]);
1919
+ }, [rate]);
1465
1920
  const handleSubmit = async (e) => {
1466
1921
  e.preventDefault();
1467
1922
  const errors = [];
1468
- if (!formData.name.trim()) {
1469
- errors.push("กรุณากรอกชื่อวัสดุ");
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 (!formData.unit.trim()) {
1472
- errors.push("กรุณากรอกหน่วย");
1929
+ if (isNaN(price) || price < 0) {
1930
+ errors.push("ราคาต้องเป็นตัวเลขไม่ติดลบ");
1473
1931
  }
1474
- const costPerUnit = parseFloat(formData.cost_per_unit);
1475
- if (isNaN(costPerUnit) || costPerUnit < 0) {
1476
- errors.push("ต้นทุนต่อหน่วยต้องเป็นตัวเลขไม่ติดลบ");
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
- name: formData.name.trim(),
1488
- unit: formData.unit.trim(),
1489
- cost_per_unit: costPerUnit,
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
- category: formData.category || void 0,
1492
- description: formData.description.trim() || void 0,
1970
+ priority,
1493
1971
  active: formData.active
1494
1972
  };
1495
- const url = materialCost ? `/admin/material-costs/${materialCost.id}` : "/admin/material-costs";
1496
- const method = materialCost ? "PUT" : "POST";
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: materialCost ? "แก้ไขรายการต้นทุนวัสดุแล้ว" : "สร้างรายการต้นทุนวัสดุใหม่แล้ว"
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: materialCost ? "แก้ไขรายการต้นทุนวัสดุ" : "สร้างรายการต้นทุนวัสดุใหม่" }) }),
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: "name", children: "ชื่อวัสดุ *" }),
1525
- /* @__PURE__ */ jsxRuntime.jsx(
1526
- ui.Input,
2009
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "carrier", children: "ประเภทขนส่ง *" }),
2010
+ /* @__PURE__ */ jsxRuntime.jsxs(
2011
+ ui.Select,
1527
2012
  {
1528
- id: "name",
1529
- value: formData.name,
1530
- onChange: (e) => setFormData({ ...formData, name: e.target.value }),
1531
- placeholder: "เช่น พลาสติกกันกระแทก, กล่องกระดาษ",
1532
- required: true
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: "category", children: "หมวดหมู่ (ไม่บังคับ)" }),
2023
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "service", children: "บริการจัดส่ง *" }),
1538
2024
  /* @__PURE__ */ jsxRuntime.jsxs(
1539
2025
  ui.Select,
1540
2026
  {
1541
- value: formData.category || void 0,
1542
- onValueChange: (value) => setFormData({ ...formData, category: value }),
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: CATEGORIES$1.map((category) => /* @__PURE__ */ jsxRuntime.jsx(ui.Select.Item, { value: category.value, children: category.label }, category.value)) })
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: "unit", children: "หน่วย *" }),
2053
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "maxWeight", children: "น้ำหนักสูงสุด (kg) *" }),
1553
2054
  /* @__PURE__ */ jsxRuntime.jsx(
1554
2055
  ui.Input,
1555
2056
  {
1556
- id: "unit",
1557
- value: formData.unit,
1558
- onChange: (e) => setFormData({ ...formData, unit: e.target.value }),
1559
- placeholder: "เช่น ชิ้น, เมตร, กิโลกรัม",
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: "costPerUnit", children: "ต้นทุนต่อหน่วย *" }),
2069
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "price", children: "ราคา (THB) *" }),
1566
2070
  /* @__PURE__ */ jsxRuntime.jsx(
1567
2071
  ui.Input,
1568
2072
  {
1569
- id: "costPerUnit",
2073
+ id: "price",
1570
2074
  type: "number",
1571
2075
  step: "0.01",
1572
- value: formData.cost_per_unit,
1573
- onChange: (e) => setFormData({ ...formData, cost_per_unit: e.target.value }),
1574
- placeholder: "0.00",
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: "currency", children: "สกุลเงิน" }),
2086
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "priority", children: "ลำดับความสำคัญ" }),
1582
2087
  /* @__PURE__ */ jsxRuntime.jsx(
1583
2088
  ui.Input,
1584
2089
  {
1585
- id: "currency",
1586
- value: formData.currency,
1587
- onChange: (e) => setFormData({ ...formData, currency: e.target.value }),
1588
- placeholder: "THB"
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.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
- )
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 CATEGORIES = [
2166
+ const CARRIER_TYPES = [
1633
2167
  { value: "ALL", label: "ทั้งหมด" },
1634
- { value: "PACKAGING", label: "วัสดุหีบห่อ" },
1635
- { value: "PROTECTION", label: "วัสดุป้องกัน" },
1636
- { value: "FILLING", label: "วัสดุเติมช่องว่าง" },
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 MaterialCostsTable = () => {
1642
- const [materialCosts, setMaterialCosts] = react.useState([]);
1643
- const [filteredMaterialCosts, setFilteredMaterialCosts] = react.useState([]);
1644
- const [searchTerm, setSearchTerm] = react.useState("");
1645
- const [categoryFilter, setCategoryFilter] = react.useState("ALL");
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 [editingMaterialCost, setEditingMaterialCost] = react.useState(null);
2185
+ const [editingRate, setEditingRate] = react.useState(null);
1648
2186
  const [isLoading, setIsLoading] = react.useState(false);
1649
- const [deleteMaterialCostId, setDeleteMaterialCostId] = react.useState(null);
1650
- const [deleteMaterialCostName, setDeleteMaterialCostName] = react.useState("");
2187
+ const [deleteRateId, setDeleteRateId] = react.useState(null);
1651
2188
  react.useEffect(() => {
1652
- fetchMaterialCosts();
2189
+ fetchRates();
1653
2190
  }, []);
1654
2191
  react.useEffect(() => {
1655
- let filtered = materialCosts;
1656
- if (categoryFilter !== "ALL") {
1657
- filtered = filtered.filter((mc) => mc.category === categoryFilter);
2192
+ let filtered = rates;
2193
+ if (carrierFilter !== "ALL") {
2194
+ filtered = filtered.filter((rate) => rate.carrier_type === carrierFilter);
1658
2195
  }
1659
- if (searchTerm) {
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
- setFilteredMaterialCosts(filtered);
1665
- }, [searchTerm, categoryFilter, materialCosts]);
1666
- const fetchMaterialCosts = async () => {
2199
+ setFilteredRates(filtered);
2200
+ }, [carrierFilter, serviceFilter, rates]);
2201
+ const fetchRates = async () => {
1667
2202
  setIsLoading(true);
1668
2203
  try {
1669
- const response = await fetch("/admin/material-costs", {
2204
+ const response = await fetch("/admin/shipping-rates", {
1670
2205
  credentials: "include"
1671
2206
  });
1672
2207
  const data = await response.json();
1673
- setMaterialCosts(data.material_costs || []);
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 (!deleteMaterialCostId) return;
2218
+ if (!deleteRateId) return;
1706
2219
  try {
1707
- const response = await fetch(
1708
- `/admin/material-costs/${deleteMaterialCostId}`,
1709
- {
1710
- method: "DELETE",
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: `ลบวัสดุ ${deleteMaterialCostName} แล้ว`
2226
+ description: "ลบอัตราค่าขนส่งแล้ว"
1717
2227
  });
1718
- fetchMaterialCosts();
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
- setDeleteMaterialCostId(null);
1728
- setDeleteMaterialCostName("");
2237
+ setDeleteRateId(null);
1729
2238
  }
1730
2239
  };
1731
- const handleEdit = (materialCost) => {
1732
- setEditingMaterialCost(materialCost);
2240
+ const handleEdit = (rate) => {
2241
+ setEditingRate(rate);
1733
2242
  setIsModalOpen(true);
1734
2243
  };
1735
2244
  const handleCreateNew = () => {
1736
- setEditingMaterialCost(null);
2245
+ setEditingRate(null);
1737
2246
  setIsModalOpen(true);
1738
2247
  };
1739
2248
  const handleModalClose = () => {
1740
2249
  setIsModalOpen(false);
1741
- setEditingMaterialCost(null);
1742
- fetchMaterialCosts();
2250
+ setEditingRate(null);
2251
+ fetchRates();
1743
2252
  };
1744
- const openDeletePrompt = (id, name) => {
1745
- setDeleteMaterialCostId(id);
1746
- setDeleteMaterialCostName(name);
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 getCategoryLabel = (category) => {
2257
+ const getServiceLabel = (code) => {
1749
2258
  var _a;
1750
- if (!category) return "-";
1751
- return ((_a = CATEGORIES.find((c) => c.value === category)) == null ? void 0 : _a.label) || category;
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 flex-1", children: [
1757
- /* @__PURE__ */ jsxRuntime.jsx(
1758
- ui.Input,
1759
- {
1760
- type: "search",
1761
- placeholder: "ค้นหาชื่อวัสดุ...",
1762
- value: searchTerm,
1763
- onChange: (e) => setSearchTerm(e.target.value),
1764
- className: "max-w-md"
1765
- }
1766
- ),
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)) })
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: "กำลังโหลด..." }) }) : 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 }),
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
- materialCost.cost_per_unit.toFixed(2),
1793
- " ",
1794
- materialCost.currency
2308
+ "≤ ",
2309
+ rate.max_weight_kg,
2310
+ " kg"
1795
2311
  ] }),
1796
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "max-w-xs truncate", children: materialCost.description || "-" }),
1797
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: /* @__PURE__ */ jsxRuntime.jsx(
1798
- ui.Badge,
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(materialCost),
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: () => openDeletePrompt(materialCost.id, materialCost.name),
2330
+ onClick: () => setDeleteRateId(rate.id),
1822
2331
  children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash, {})
1823
2332
  }
1824
2333
  )
1825
2334
  ] }) })
1826
- ] }, materialCost.id)) })
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: !!deleteMaterialCostId,
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.jsxs(ui.Prompt.Description, { children: [
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 MaterialCostsPage = () => {
1864
- return /* @__PURE__ */ jsxRuntime.jsx(ui.Container, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-y-4", children: [
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: "ต้นทุนวัสดุ"
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
- carrier_type: "COMPANY_FLEET",
1887
- service_code: "MESSENGER_3H",
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, _c, _d;
2372
+ var _a, _b;
1904
2373
  if (rate) {
1905
2374
  setFormData({
1906
- carrier_type: rate.carrier_type,
1907
- service_code: rate.service_code,
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 maxWeight = parseFloat(formData.max_weight_kg);
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(maxWeight) || maxWeight <= 0) {
1927
- errors.push("น้ำหนักสูงสุดต้องเป็นตัวเลขมากกว่า 0");
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: formData.carrier_type,
1966
- service_code: formData.service_code,
1967
- max_weight_kg: maxWeight,
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: formData.currency,
2418
+ currency: "THB",
1970
2419
  priority,
1971
2420
  active: formData.active
1972
2421
  };
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";
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
- ui.toast.success("สำเร็จ", {
1990
- description: rate ? "แก้ไขอัตราค่าขนส่งแล้ว" : "สร้างอัตราค่าขนส่งใหม่แล้ว"
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: "maxWeight", children: "น้ำหนักสูงสุด (kg) *" }),
2451
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "min_distance_km", children: "ระยะทางเริ่มต้น (กม.) *" }),
2054
2452
  /* @__PURE__ */ jsxRuntime.jsx(
2055
2453
  ui.Input,
2056
2454
  {
2057
- id: "maxWeight",
2455
+ id: "min_distance_km",
2058
2456
  type: "number",
2059
- step: "0.1",
2060
2457
  min: "0",
2061
- value: formData.max_weight_kg,
2062
- onChange: (e) => setFormData({ ...formData, max_weight_kg: e.target.value }),
2063
- placeholder: "เช่น 3",
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: "price", children: "ราคา (THB) *" }),
2466
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Label, { htmlFor: "max_distance_km", children: "ระยะทางสูงสุด (กม.)" }),
2070
2467
  /* @__PURE__ */ jsxRuntime.jsx(
2071
2468
  ui.Input,
2072
2469
  {
2073
- id: "price",
2470
+ id: "max_distance_km",
2074
2471
  type: "number",
2075
- step: "0.01",
2076
2472
  min: "0",
2077
- value: formData.price,
2078
- onChange: (e) => setFormData({ ...formData, price: e.target.value }),
2079
- placeholder: "เช่น 80",
2080
- required: true
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: "ตัวเลขสูงกว่าจะถูกเสนอให้เลือกก่อน (ค่าเริ่มต้น 0)" })
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(ui.Button, { type: "button", variant: "secondary", onClick: onClose, disabled: isSaving, children: "ยกเลิก" }),
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 CARRIER_TYPES = [
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 [filteredRates, setFilteredRates] = react.useState([]);
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 [isLoading, setIsLoading] = react.useState(false);
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.useEffect(() => {
2192
- let filtered = rates;
2193
- if (carrierFilter !== "ALL") {
2194
- filtered = filtered.filter((rate) => rate.carrier_type === carrierFilter);
2195
- }
2196
- if (serviceFilter !== "ALL") {
2197
- filtered = filtered.filter((rate) => rate.service_code === serviceFilter);
2198
- }
2199
- setFilteredRates(filtered);
2200
- }, [carrierFilter, serviceFilter, rates]);
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("/admin/shipping-rates", {
2205
- credentials: "include"
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.rates || []);
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 (!deleteRateId) return;
2580
+ if (!deleteId) return;
2219
2581
  try {
2220
- const response = await fetch(`/admin/shipping-rates/${deleteRateId}`, {
2221
- method: "DELETE",
2222
- credentials: "include"
2223
- });
2224
- if (response.ok) {
2225
- ui.toast.success("สำเร็จ", {
2226
- description: "ลบอัตราค่าขนส่งแล้ว"
2227
- });
2228
- fetchRates();
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
- setDeleteRateId(null);
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 getCarrierLabel = (type) => {
2254
- var _a;
2255
- return ((_a = CARRIER_TYPES.find((c) => c.value === type)) == null ? void 0 : _a.label) || type;
2256
- };
2257
- const getServiceLabel = (code) => {
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 flex-col gap-y-4", children: [
2272
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-x-4", children: [
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
- ] })
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.Table, { children: [
2295
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Header, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { 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" }),
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
- isModalOpen && /* @__PURE__ */ jsxRuntime.jsx(ShippingRateModal, { rate: editingRate, onClose: handleModalClose }),
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: !!deleteRateId,
2344
- onOpenChange: () => setDeleteRateId(null),
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: "/base-pricing",
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
  };