@lodashventure/medusa-parcel-shipping 0.4.30 → 0.4.34

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.
@@ -1,9 +1,9 @@
1
1
  import { jsxs, jsx, Fragment } from "react/jsx-runtime";
2
2
  import { defineWidgetConfig, defineRouteConfig } from "@medusajs/admin-sdk";
3
- import { Container, Heading, Button, Text, Badge, Drawer, Label, Input, Switch, toast, Table, Prompt, Select, Textarea } from "@medusajs/ui";
3
+ import { Container, Heading, Button, Text, Badge, Drawer, Label, Select, Input, Switch, toast, Table, Prompt, Textarea } from "@medusajs/ui";
4
4
  import { useState, useEffect, useMemo } from "react";
5
5
  import { Package, AlertCircle, Truck, Clock, Plus, Edit, Trash, ExternalLink } from "lucide-react";
6
- import { Directions, ArchiveBox, MapPin, CurrencyDollarSolid, HandTruck } from "@medusajs/icons";
6
+ import { MapPin, Directions, ArchiveBox, CurrencyDollarSolid, HandTruck } from "@medusajs/icons";
7
7
  import "@medusajs/admin-shared";
8
8
  const OrderShippingQuoteWidget = ({ data }) => {
9
9
  const [quote, setQuote] = useState(null);
@@ -235,49 +235,116 @@ const OrderShippingQuoteWidget = ({ data }) => {
235
235
  defineWidgetConfig({
236
236
  zone: "order.details.after"
237
237
  });
238
- const MessengerBaseRateModal = ({
239
- rate,
240
- onClose
241
- }) => {
238
+ const TH_PROVINCES = [
239
+ "กรุงเทพมหานคร",
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
+ const ServiceAreaModal = ({ area, onClose }) => {
242
318
  const [formData, setFormData] = useState({
243
- min_distance_km: "0",
244
- max_distance_km: "",
245
- price: "",
246
- priority: "0",
319
+ kind: "PROVINCE",
320
+ value: "",
247
321
  active: true
248
322
  });
249
323
  const [isSaving, setIsSaving] = useState(false);
250
324
  useEffect(() => {
251
- var _a, _b;
252
- if (rate) {
325
+ if (area) {
253
326
  setFormData({
254
- min_distance_km: ((_a = rate.min_distance_km) == null ? void 0 : _a.toString()) ?? "0",
255
- max_distance_km: ((_b = rate.max_distance_km) == null ? void 0 : _b.toString()) || "",
256
- price: rate.price.toString(),
257
- priority: (rate.priority ?? 0).toString(),
258
- active: rate.active
327
+ kind: area.kind,
328
+ value: area.value,
329
+ active: area.active
259
330
  });
260
331
  }
261
- }, [rate]);
332
+ }, [area]);
262
333
  const handleSubmit = async (e) => {
263
334
  e.preventDefault();
264
335
  const errors = [];
265
- const minDistance = parseFloat(formData.min_distance_km || "0");
266
- const hasMaxDistance = formData.max_distance_km !== "";
267
- const maxDistance = hasMaxDistance ? parseFloat(formData.max_distance_km) : void 0;
268
- const price = parseFloat(formData.price);
269
- const priority = parseInt(formData.priority || "0", 10);
270
- if (isNaN(minDistance) || minDistance < 0) {
271
- errors.push("ระยะทางเริ่มต้นต้องไม่ติดลบ");
272
- }
273
- if (hasMaxDistance && (maxDistance === void 0 || isNaN(maxDistance) || (maxDistance ?? 0) < minDistance)) {
274
- errors.push("ระยะทางสูงสุดต้องมากกว่าหรือเท่ากับระยะทางเริ่มต้น");
275
- }
276
- if (isNaN(price) || price < 0) {
277
- errors.push("ราคาต้องเป็นตัวเลขไม่ติดลบ");
336
+ const trimmedValue = formData.value.trim();
337
+ if (!trimmedValue) {
338
+ errors.push("กรุณากรอกค่า");
278
339
  }
279
- if (isNaN(priority)) {
280
- errors.push("ลำดับความสำคัญต้องเป็นตัวเลข");
340
+ if (formData.kind === "PROVINCE") {
341
+ if (!TH_PROVINCES.includes(trimmedValue)) {
342
+ errors.push("จังหวัดไม่ถูกต้อง กรุณาตรวจสอบการสะกดชื่อจังหวัด");
343
+ }
344
+ } else if (formData.kind === "POSTCODE_PREFIX") {
345
+ if (!/^\d{1,5}$/.test(trimmedValue)) {
346
+ errors.push("รหัสไปรษณีย์ต้องเป็นตัวเลข 1-5 หลัก");
347
+ }
281
348
  }
282
349
  if (errors.length > 0) {
283
350
  toast.error("ข้อมูลไม่ถูกต้อง", {
@@ -288,32 +355,27 @@ const MessengerBaseRateModal = ({
288
355
  setIsSaving(true);
289
356
  try {
290
357
  const payload = {
291
- carrier_type: "COMPANY_FLEET",
292
- carrier: "COMPANY_FLEET",
293
- service_code: "MESSENGER_3H",
294
- min_distance_km: minDistance,
295
- max_distance_km: maxDistance === void 0 || isNaN(maxDistance) ? null : maxDistance,
296
- price,
297
- currency: "THB",
298
- priority,
358
+ kind: formData.kind,
359
+ value: trimmedValue,
299
360
  active: formData.active
300
361
  };
301
- const url = rate ? `/admin/base-shipping-prices/${rate.id}` : "/admin/base-shipping-prices";
302
- const method = rate ? "PUT" : "POST";
362
+ const url = area ? `/admin/service-areas/${area.id}` : "/admin/service-areas";
363
+ const method = area ? "PUT" : "POST";
303
364
  const response = await fetch(url, {
304
365
  method,
305
366
  headers: { "Content-Type": "application/json" },
306
367
  credentials: "include",
307
368
  body: JSON.stringify(payload)
308
369
  });
309
- if (!response.ok) {
310
- const error = await response.json().catch(() => ({}));
311
- throw new Error(error.message || "ไม่สามารถบันทึกข้อมูลได้");
370
+ if (response.ok) {
371
+ toast.success("สำเร็จ", {
372
+ description: area ? "แก้ไขพื้นที่บริการแล้ว" : "สร้างพื้นที่บริการใหม่แล้ว"
373
+ });
374
+ onClose();
375
+ } else {
376
+ const error = await response.json();
377
+ throw new Error(error.message || "Failed to save");
312
378
  }
313
- toast.success("สำเร็จ", {
314
- description: rate ? "แก้ไขฐานราคาตามระยะทางแล้ว" : "สร้างฐานราคาตามระยะทางใหม่แล้ว"
315
- });
316
- onClose();
317
379
  } catch (error) {
318
380
  toast.error("ข้อผิดพลาด", {
319
381
  description: error instanceof Error ? error.message : "ไม่สามารถบันทึกข้อมูลได้"
@@ -323,69 +385,53 @@ const MessengerBaseRateModal = ({
323
385
  }
324
386
  };
325
387
  return /* @__PURE__ */ jsx(Drawer, { open: true, onOpenChange: (open) => !open && onClose(), children: /* @__PURE__ */ jsxs(Drawer.Content, { children: [
326
- /* @__PURE__ */ jsx(Drawer.Header, { children: /* @__PURE__ */ jsx(Drawer.Title, { children: rate ? "แก้ไขฐานราคาตามระยะทาง" : "สร้างฐานราคาตามระยะทาง" }) }),
388
+ /* @__PURE__ */ jsx(Drawer.Header, { children: /* @__PURE__ */ jsx(Drawer.Title, { children: area ? "แก้ไขพื้นที่บริการ" : "สร้างพื้นที่บริการใหม่" }) }),
327
389
  /* @__PURE__ */ jsx(Drawer.Body, { children: /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className: "flex flex-col gap-y-4", children: [
328
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-4", children: [
329
- /* @__PURE__ */ jsxs("div", { children: [
330
- /* @__PURE__ */ jsx(Label, { htmlFor: "min_distance_km", children: "ระยะทางเริ่มต้น (กม.) *" }),
331
- /* @__PURE__ */ jsx(
332
- Input,
333
- {
334
- id: "min_distance_km",
335
- type: "number",
336
- min: "0",
337
- step: "0.1",
338
- value: formData.min_distance_km,
339
- onChange: (e) => setFormData({ ...formData, min_distance_km: e.target.value }),
340
- required: true
341
- }
342
- )
343
- ] }),
344
- /* @__PURE__ */ jsxs("div", { children: [
345
- /* @__PURE__ */ jsx(Label, { htmlFor: "max_distance_km", children: "ระยะทางสูงสุด (กม.)" }),
346
- /* @__PURE__ */ jsx(
347
- Input,
348
- {
349
- id: "max_distance_km",
350
- type: "number",
351
- min: "0",
352
- step: "0.1",
353
- placeholder: "ปล่อยว่างหากไม่มีที่สิ้นสุด",
354
- value: formData.max_distance_km,
355
- onChange: (e) => setFormData({ ...formData, max_distance_km: e.target.value })
356
- }
357
- ),
358
- /* @__PURE__ */ jsx("p", { className: "text-xs text-ui-fg-subtle mt-1", children: "เว้นว่างเพื่อกำหนดช่วงราคาแบบ 30+ กม." })
359
- ] })
360
- ] }),
361
390
  /* @__PURE__ */ jsxs("div", { children: [
362
- /* @__PURE__ */ jsx(Label, { htmlFor: "price", children: "ราคา (THB) *" }),
363
- /* @__PURE__ */ jsx(
364
- Input,
391
+ /* @__PURE__ */ jsx(Label, { htmlFor: "kind", children: "ประเภท *" }),
392
+ /* @__PURE__ */ jsxs(
393
+ Select,
365
394
  {
366
- id: "price",
367
- type: "number",
368
- min: "0",
369
- step: "0.01",
370
- value: formData.price,
371
- onChange: (e) => setFormData({ ...formData, price: e.target.value }),
372
- required: true
395
+ value: formData.kind,
396
+ onValueChange: (value) => setFormData({ ...formData, kind: value, value: "" }),
397
+ required: true,
398
+ children: [
399
+ /* @__PURE__ */ jsx(Select.Trigger, { children: /* @__PURE__ */ jsx(Select.Value, { placeholder: "เลือกประเภท" }) }),
400
+ /* @__PURE__ */ jsxs(Select.Content, { children: [
401
+ /* @__PURE__ */ jsx(Select.Item, { value: "PROVINCE", children: "จังหวัด" }),
402
+ /* @__PURE__ */ jsx(Select.Item, { value: "POSTCODE_PREFIX", children: "รหัสไปรษณีย์" })
403
+ ] })
404
+ ]
373
405
  }
374
406
  )
375
407
  ] }),
376
408
  /* @__PURE__ */ jsxs("div", { children: [
377
- /* @__PURE__ */ jsx(Label, { htmlFor: "priority", children: "ลำดับความสำคัญ" }),
378
- /* @__PURE__ */ jsx(
409
+ /* @__PURE__ */ jsx(Label, { htmlFor: "value", children: formData.kind === "PROVINCE" ? "ชื่อจังหวัด *" : "รหัสไปรษณีย์ (1-5 หลัก) *" }),
410
+ formData.kind === "PROVINCE" ? /* @__PURE__ */ jsxs(
411
+ Select,
412
+ {
413
+ value: formData.value,
414
+ onValueChange: (value) => setFormData({ ...formData, value }),
415
+ required: true,
416
+ children: [
417
+ /* @__PURE__ */ jsx(Select.Trigger, { children: /* @__PURE__ */ jsx(Select.Value, { placeholder: "เลือกจังหวัด" }) }),
418
+ /* @__PURE__ */ jsx(Select.Content, { children: TH_PROVINCES.map((province) => /* @__PURE__ */ jsx(Select.Item, { value: province, children: province }, province)) })
419
+ ]
420
+ }
421
+ ) : /* @__PURE__ */ jsx(
379
422
  Input,
380
423
  {
381
- id: "priority",
382
- type: "number",
383
- value: formData.priority,
384
- onChange: (e) => setFormData({ ...formData, priority: e.target.value }),
385
- placeholder: "0"
424
+ id: "value",
425
+ type: "text",
426
+ value: formData.value,
427
+ onChange: (e) => setFormData({ ...formData, value: e.target.value }),
428
+ placeholder: "เช่น 10, 102, 10200",
429
+ maxLength: 5,
430
+ pattern: "\\d{1,5}",
431
+ required: true
386
432
  }
387
433
  ),
388
- /* @__PURE__ */ jsx("p", { className: "text-xs text-ui-fg-subtle mt-1", children: "ใช้สำหรับจัดลำดับเมื่อมีช่วงราคาทับกัน (ค่าเริ่มต้น 0)" })
434
+ formData.kind === "POSTCODE_PREFIX" && /* @__PURE__ */ jsx("p", { className: "text-xs text-ui-fg-subtle mt-1", children: 'ใส่รหัส 1-5 หลักเพื่อครอบคลุมหลายพื้นที่ เช่น "10" = กรุงเทพฯ ทั้งหมด' })
389
435
  ] }),
390
436
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
391
437
  /* @__PURE__ */ jsx(
@@ -414,148 +460,200 @@ const MessengerBaseRateModal = ({
414
460
  ] }) })
415
461
  ] }) });
416
462
  };
417
- const MessengerBasePricingTable = () => {
418
- const [rates, setRates] = useState([]);
419
- const [isLoading, setIsLoading] = useState(false);
420
- const [isModalOpen, setIsModalOpen] = useState(false);
421
- const [editingRate, setEditingRate] = useState(null);
422
- const [deleteId, setDeleteId] = useState(null);
423
- useEffect(() => {
424
- fetchRates();
425
- }, []);
426
- const orderedRates = useMemo(() => {
427
- return [...rates].sort((a, b) => {
428
- if (a.min_distance_km !== b.min_distance_km) {
429
- return a.min_distance_km - b.min_distance_km;
430
- }
431
- const aMax = a.max_distance_km ?? Number.POSITIVE_INFINITY;
432
- const bMax = b.max_distance_km ?? Number.POSITIVE_INFINITY;
433
- return aMax - bMax;
434
- });
435
- }, [rates]);
436
- const fetchRates = async () => {
463
+ const AREA_KINDS = [
464
+ { value: "ALL", label: "ทั้งหมด" },
465
+ { value: "PROVINCE", label: "จังหวัด" },
466
+ { value: "POSTCODE_PREFIX", label: "รหัสไปรษณีย์" }
467
+ ];
468
+ const ServiceAreasTable = () => {
469
+ const [areas, setAreas] = useState([]);
470
+ const [filteredAreas, setFilteredAreas] = useState([]);
471
+ const [searchTerm, setSearchTerm] = useState("");
472
+ const [kindFilter, setKindFilter] = useState("ALL");
473
+ const [isModalOpen, setIsModalOpen] = useState(false);
474
+ const [editingArea, setEditingArea] = useState(null);
475
+ const [isLoading, setIsLoading] = useState(false);
476
+ const [deleteAreaId, setDeleteAreaId] = useState(null);
477
+ const [deleteAreaValue, setDeleteAreaValue] = useState("");
478
+ useEffect(() => {
479
+ fetchAreas();
480
+ }, []);
481
+ useEffect(() => {
482
+ let filtered = areas;
483
+ if (kindFilter !== "ALL") {
484
+ filtered = filtered.filter((area) => area.kind === kindFilter);
485
+ }
486
+ if (searchTerm) {
487
+ filtered = filtered.filter(
488
+ (area) => area.value.toLowerCase().includes(searchTerm.toLowerCase())
489
+ );
490
+ }
491
+ setFilteredAreas(filtered);
492
+ }, [searchTerm, kindFilter, areas]);
493
+ const fetchAreas = async () => {
437
494
  setIsLoading(true);
438
495
  try {
439
- const response = await fetch(
440
- "/admin/base-shipping-prices?carrier_type=COMPANY_FLEET&service_code=MESSENGER_3H",
441
- {
442
- credentials: "include"
443
- }
444
- );
445
- if (!response.ok) {
446
- throw new Error("failed_to_load_base_rates");
447
- }
496
+ const response = await fetch("/admin/service-areas", {
497
+ credentials: "include"
498
+ });
448
499
  const data = await response.json();
449
- setRates(data.base_rates || []);
500
+ console.log("Fetched service areas:", data);
501
+ setAreas(data.service_areas || []);
450
502
  } catch (error) {
451
503
  toast.error("ข้อผิดพลาด", {
452
- description: "ไม่สามารถโหลดฐานราคาตามระยะทางได้"
504
+ description: "ไม่สามารถโหลดข้อมูลพื้นที่บริการได้"
453
505
  });
454
506
  } finally {
455
507
  setIsLoading(false);
456
508
  }
457
509
  };
458
- const handleDelete = async () => {
459
- if (!deleteId) return;
510
+ const handleToggleActive = async (area) => {
460
511
  try {
461
- const response = await fetch(
462
- `/admin/base-shipping-prices/${deleteId}`,
463
- {
464
- method: "DELETE",
465
- credentials: "include"
466
- }
467
- );
468
- if (!response.ok) {
469
- throw new Error("failed_to_delete");
512
+ const response = await fetch(`/admin/service-areas/${area.id}`, {
513
+ method: "PUT",
514
+ headers: { "Content-Type": "application/json" },
515
+ credentials: "include",
516
+ body: JSON.stringify({ ...area, active: !area.active })
517
+ });
518
+ if (response.ok) {
519
+ toast.success("สำเร็จ", {
520
+ description: `${area.active ? "ปิดใช้งาน" : "เปิดใช้งาน"}พื้นที่ ${area.value} แล้ว`
521
+ });
522
+ fetchAreas();
523
+ } else {
524
+ throw new Error("Failed to update");
470
525
  }
471
- toast.success("สำเร็จ", {
472
- description: "ลบฐานราคาสำเร็จ"
526
+ } catch (error) {
527
+ toast.error("ข้อผิดพลาด", {
528
+ description: "ไม่สามารถอัพเดทสถานะได้"
473
529
  });
474
- fetchRates();
530
+ }
531
+ };
532
+ const handleDelete = async () => {
533
+ if (!deleteAreaId) return;
534
+ try {
535
+ const response = await fetch(`/admin/service-areas/${deleteAreaId}`, {
536
+ method: "DELETE",
537
+ credentials: "include"
538
+ });
539
+ if (response.ok) {
540
+ toast.success("สำเร็จ", {
541
+ description: `ลบพื้นที่ ${deleteAreaValue} แล้ว`
542
+ });
543
+ fetchAreas();
544
+ } else {
545
+ throw new Error("Failed to delete");
546
+ }
475
547
  } catch (error) {
476
548
  toast.error("ข้อผิดพลาด", {
477
- description: "ไม่สามารถลบฐานราคาได้"
549
+ description: "ไม่สามารถลบพื้นที่ได้"
478
550
  });
479
551
  } finally {
480
- setDeleteId(null);
552
+ setDeleteAreaId(null);
553
+ setDeleteAreaValue("");
481
554
  }
482
555
  };
556
+ const handleEdit = (area) => {
557
+ setEditingArea(area);
558
+ setIsModalOpen(true);
559
+ };
560
+ const handleCreateNew = () => {
561
+ setEditingArea(null);
562
+ setIsModalOpen(true);
563
+ };
483
564
  const handleModalClose = () => {
484
565
  setIsModalOpen(false);
485
- setEditingRate(null);
486
- fetchRates();
566
+ setEditingArea(null);
567
+ fetchAreas();
487
568
  };
488
- const formatDistanceRange = (rate) => {
489
- const min = rate.min_distance_km ?? 0;
490
- const max = rate.max_distance_km;
491
- if (max === void 0 || max === null) {
492
- return `${min}+ กม.`;
493
- }
494
- return `${min}-${max} กม.`;
569
+ const openDeletePrompt = (id, value) => {
570
+ setDeleteAreaId(id);
571
+ setDeleteAreaValue(value);
495
572
  };
496
573
  return /* @__PURE__ */ jsxs(Fragment, { children: [
497
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-x-4", children: [
498
- /* @__PURE__ */ jsxs("div", { children: [
499
- /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold", children: "ฐานราคาตามระยะทาง (Messenger 3H)" }),
500
- /* @__PURE__ */ jsx("p", { className: "text-ui-fg-subtle text-sm", children: "กำหนดราคาเริ่มต้นตามระยะทาง เช่น 0-5, 5-20, 20-30, 30+ กม." })
501
- ] }),
502
- /* @__PURE__ */ jsxs(Button, { onClick: () => setIsModalOpen(true), children: [
503
- /* @__PURE__ */ jsx(Plus, {}),
504
- "เพิ่มช่วงราคา"
505
- ] })
506
- ] }),
507
- /* @__PURE__ */ jsxs(Table, { className: "mt-4", children: [
508
- /* @__PURE__ */ jsx(Table.Header, { children: /* @__PURE__ */ jsxs(Table.Row, { children: [
509
- /* @__PURE__ */ jsx(Table.HeaderCell, { children: "ช่วงระยะทาง" }),
510
- /* @__PURE__ */ jsx(Table.HeaderCell, { children: "ราคา (THB)" }),
511
- /* @__PURE__ */ jsx(Table.HeaderCell, { children: "ลำดับ" }),
512
- /* @__PURE__ */ jsx(Table.HeaderCell, { children: "สถานะ" }),
513
- /* @__PURE__ */ jsx(Table.HeaderCell, { className: "text-right", children: "การจัดการ" })
514
- ] }) }),
515
- /* @__PURE__ */ jsx(Table.Body, { children: isLoading ? /* @__PURE__ */ jsx(Table.Row, { children: /* @__PURE__ */ jsx(Table.Cell, { className: "text-center", children: "กำลังโหลด..." }) }) : orderedRates.length === 0 ? /* @__PURE__ */ jsx(Table.Row, { children: /* @__PURE__ */ jsx(Table.Cell, { className: "text-center", children: "ยังไม่ได้ตั้งค่าฐานราคาตามระยะทาง" }) }) : orderedRates.map((rate) => /* @__PURE__ */ jsxs(Table.Row, { children: [
516
- /* @__PURE__ */ jsx(Table.Cell, { children: formatDistanceRange(rate) }),
517
- /* @__PURE__ */ jsxs(Table.Cell, { children: [
518
- "฿",
519
- rate.price.toFixed(2)
520
- ] }),
521
- /* @__PURE__ */ jsx(Table.Cell, { children: rate.priority ?? 0 }),
522
- /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Badge, { color: rate.active ? "green" : "grey", children: rate.active ? "เปิดใช้งาน" : "ปิดใช้งาน" }) }),
523
- /* @__PURE__ */ jsx(Table.Cell, { className: "text-right", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
574
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-4", children: [
575
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-x-4", children: [
576
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-x-4 flex-1", children: [
524
577
  /* @__PURE__ */ jsx(
525
- Button,
578
+ Input,
526
579
  {
527
- variant: "transparent",
528
- size: "small",
529
- onClick: () => {
530
- setEditingRate(rate);
531
- setIsModalOpen(true);
532
- },
533
- children: /* @__PURE__ */ jsx(Edit, {})
580
+ type: "search",
581
+ placeholder: "ค้นหาจังหวัดหรือรหัสไปรษณีย์...",
582
+ value: searchTerm,
583
+ onChange: (e) => setSearchTerm(e.target.value),
584
+ className: "max-w-md"
534
585
  }
535
586
  ),
536
- /* @__PURE__ */ jsx(
537
- Button,
587
+ /* @__PURE__ */ jsxs(Select, { value: kindFilter, onValueChange: setKindFilter, children: [
588
+ /* @__PURE__ */ jsx(Select.Trigger, { children: /* @__PURE__ */ jsx(Select.Value, { placeholder: "ประเภท" }) }),
589
+ /* @__PURE__ */ jsx(Select.Content, { children: AREA_KINDS.map((kind) => /* @__PURE__ */ jsx(Select.Item, { value: kind.value, children: kind.label }, kind.value)) })
590
+ ] })
591
+ ] }),
592
+ /* @__PURE__ */ jsxs(Button, { onClick: handleCreateNew, children: [
593
+ /* @__PURE__ */ jsx(Plus, {}),
594
+ "สร้างพื้นที่ใหม่"
595
+ ] })
596
+ ] }),
597
+ /* @__PURE__ */ jsxs(Table, { children: [
598
+ /* @__PURE__ */ jsx(Table.Header, { children: /* @__PURE__ */ jsxs(Table.Row, { children: [
599
+ /* @__PURE__ */ jsx(Table.HeaderCell, { children: "ประเภท" }),
600
+ /* @__PURE__ */ jsx(Table.HeaderCell, { children: "ค่า" }),
601
+ /* @__PURE__ */ jsx(Table.HeaderCell, { children: "สถานะ" }),
602
+ /* @__PURE__ */ jsx(Table.HeaderCell, { className: "text-right", children: "การจัดการ" })
603
+ ] }) }),
604
+ /* @__PURE__ */ jsx(Table.Body, { children: isLoading ? /* @__PURE__ */ jsx(Table.Row, { children: /* @__PURE__ */ jsx(Table.Cell, { className: "text-center", children: "กำลังโหลด..." }) }) : filteredAreas.length === 0 ? /* @__PURE__ */ jsx(Table.Row, { children: /* @__PURE__ */ jsx(Table.Cell, { className: "text-center", children: "ไม่พบข้อมูลพื้นที่บริการ" }) }) : filteredAreas.map((area) => /* @__PURE__ */ jsxs(Table.Row, { children: [
605
+ /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Badge, { color: area.kind === "PROVINCE" ? "blue" : "purple", children: area.kind === "PROVINCE" ? "จังหวัด" : "รหัสไปรษณีย์" }) }),
606
+ /* @__PURE__ */ jsx(Table.Cell, { children: area.value }),
607
+ /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
608
+ Badge,
538
609
  {
539
- variant: "transparent",
540
- size: "small",
541
- onClick: () => setDeleteId(rate.id),
542
- children: /* @__PURE__ */ jsx(Trash, {})
610
+ color: area.active ? "green" : "grey",
611
+ className: "cursor-pointer",
612
+ onClick: () => handleToggleActive(area),
613
+ children: area.active ? "เปิดใช้งาน" : "ปิดใช้งาน"
543
614
  }
544
- )
545
- ] }) })
546
- ] }, rate.id)) })
615
+ ) }),
616
+ /* @__PURE__ */ jsx(Table.Cell, { className: "text-right", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
617
+ /* @__PURE__ */ jsx(
618
+ Button,
619
+ {
620
+ variant: "transparent",
621
+ size: "small",
622
+ onClick: () => handleEdit(area),
623
+ children: /* @__PURE__ */ jsx(Edit, {})
624
+ }
625
+ ),
626
+ /* @__PURE__ */ jsx(
627
+ Button,
628
+ {
629
+ variant: "transparent",
630
+ size: "small",
631
+ onClick: () => openDeletePrompt(area.id, area.value),
632
+ children: /* @__PURE__ */ jsx(Trash, {})
633
+ }
634
+ )
635
+ ] }) })
636
+ ] }, area.id)) })
637
+ ] })
547
638
  ] }),
548
- isModalOpen && /* @__PURE__ */ jsx(MessengerBaseRateModal, { rate: editingRate, onClose: handleModalClose }),
639
+ isModalOpen && /* @__PURE__ */ jsx(ServiceAreaModal, { area: editingArea, onClose: handleModalClose }),
549
640
  /* @__PURE__ */ jsx(
550
641
  Prompt,
551
642
  {
552
643
  variant: "confirmation",
553
- open: !!deleteId,
554
- onOpenChange: () => setDeleteId(null),
644
+ open: !!deleteAreaId,
645
+ onOpenChange: () => {
646
+ setDeleteAreaId(null);
647
+ setDeleteAreaValue("");
648
+ },
555
649
  children: /* @__PURE__ */ jsxs(Prompt.Content, { children: [
556
650
  /* @__PURE__ */ jsxs(Prompt.Header, { children: [
557
- /* @__PURE__ */ jsx(Prompt.Title, { children: "ลบฐานราคา" }),
558
- /* @__PURE__ */ jsx(Prompt.Description, { children: "คุณต้องการลบช่วงราคานี้ใช่หรือไม่? การดำเนินการนี้ไม่สามารถย้อนกลับได้" })
651
+ /* @__PURE__ */ jsx(Prompt.Title, { children: "ลบพื้นที่บริการ" }),
652
+ /* @__PURE__ */ jsxs(Prompt.Description, { children: [
653
+ 'คุณต้องการลบพื้นที่ "',
654
+ deleteAreaValue,
655
+ '" ใช่หรือไม่? การดำเนินการนี้ไม่สามารถย้อนกลับได้'
656
+ ] })
559
657
  ] }),
560
658
  /* @__PURE__ */ jsxs(Prompt.Footer, { children: [
561
659
  /* @__PURE__ */ jsx(Prompt.Cancel, { children: "ยกเลิก" }),
@@ -566,69 +664,60 @@ const MessengerBasePricingTable = () => {
566
664
  )
567
665
  ] });
568
666
  };
569
- const BasePricingPage = () => {
570
- return /* @__PURE__ */ jsx(Container, { children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-6", children: [
571
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-1", children: [
572
- /* @__PURE__ */ jsx(Heading, { level: "h1", children: "ฐานราคาตามระยะทาง (Messenger)" }),
573
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "ตั้งราคาฐานสำหรับบริการ Messenger 3 ชั่วโมงตามช่วงระยะทาง เช่น 0-5, 5-20, 20-30, 30+ กม." })
574
- ] }),
575
- /* @__PURE__ */ jsx(MessengerBasePricingTable, {})
667
+ const AreasPage = () => {
668
+ return /* @__PURE__ */ jsx(Container, { children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-4", children: [
669
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsx(Heading, { level: "h1", children: "พื้นที่บริการ" }) }),
670
+ /* @__PURE__ */ jsx(ServiceAreasTable, {})
576
671
  ] }) });
577
672
  };
578
673
  const config$4 = defineRouteConfig({
579
- icon: Directions,
580
- label: "ฐานราคาตามระยะทาง"
674
+ icon: MapPin,
675
+ label: "พื้นที่บริการ"
581
676
  });
582
- const ParcelBoxModal = ({ box, onClose }) => {
677
+ const MessengerBaseRateModal = ({
678
+ rate,
679
+ onClose
680
+ }) => {
583
681
  const [formData, setFormData] = useState({
584
- name: "",
585
- width_cm: "",
586
- length_cm: "",
587
- height_cm: "",
588
- max_weight_kg: "",
589
- price_thb: "",
682
+ min_distance_km: "0",
683
+ max_distance_km: "",
684
+ price: "",
685
+ priority: "0",
590
686
  active: true
591
687
  });
592
688
  const [isSaving, setIsSaving] = useState(false);
593
689
  useEffect(() => {
594
- if (box) {
690
+ var _a, _b;
691
+ if (rate) {
595
692
  setFormData({
596
- name: box.name,
597
- width_cm: box.width_cm.toString(),
598
- length_cm: box.length_cm.toString(),
599
- height_cm: box.height_cm.toString(),
600
- max_weight_kg: box.max_weight_kg.toString(),
601
- price_thb: box.price_thb.toString(),
602
- active: box.active
693
+ min_distance_km: ((_a = rate.min_distance_km) == null ? void 0 : _a.toString()) ?? "0",
694
+ max_distance_km: ((_b = rate.max_distance_km) == null ? void 0 : _b.toString()) || "",
695
+ price: rate.price.toString(),
696
+ priority: (rate.priority ?? 0).toString(),
697
+ active: rate.active
603
698
  });
604
699
  }
605
- }, [box]);
700
+ }, [rate]);
606
701
  const handleSubmit = async (e) => {
607
702
  e.preventDefault();
608
703
  const errors = [];
609
- if (!formData.name.trim()) {
610
- errors.push("กรุณากรอกชื่อกล่อง");
611
- }
612
- const width = parseFloat(formData.width_cm);
613
- const length = parseFloat(formData.length_cm);
614
- const height = parseFloat(formData.height_cm);
615
- const maxWeight = parseFloat(formData.max_weight_kg);
616
- const price = parseFloat(formData.price_thb);
617
- if (isNaN(width) || width <= 0) {
618
- errors.push("ความกว้างต้องเป็นตัวเลขมากกว่า 0");
619
- }
620
- if (isNaN(length) || length <= 0) {
621
- errors.push("ความยาวต้องเป็นตัวเลขมากกว่า 0");
622
- }
623
- if (isNaN(height) || height <= 0) {
624
- errors.push("ความสูงต้องเป็นตัวเลขมากกว่า 0");
704
+ const minDistance = parseFloat(formData.min_distance_km || "0");
705
+ const hasMaxDistance = formData.max_distance_km !== "";
706
+ const maxDistance = hasMaxDistance ? parseFloat(formData.max_distance_km) : void 0;
707
+ const price = parseFloat(formData.price);
708
+ const priority = parseInt(formData.priority || "0", 10);
709
+ if (isNaN(minDistance) || minDistance < 0) {
710
+ errors.push("ระยะทางเริ่มต้นต้องไม่ติดลบ");
625
711
  }
626
- if (isNaN(maxWeight) || maxWeight <= 0) {
627
- errors.push("น้ำหนักสูงสุดต้องเป็นตัวเลขมากกว่า 0");
712
+ if (hasMaxDistance && (maxDistance === void 0 || isNaN(maxDistance) || (maxDistance ?? 0) < minDistance)) {
713
+ errors.push("ระยะทางสูงสุดต้องมากกว่าหรือเท่ากับระยะทางเริ่มต้น");
628
714
  }
629
715
  if (isNaN(price) || price < 0) {
630
716
  errors.push("ราคาต้องเป็นตัวเลขไม่ติดลบ");
631
717
  }
718
+ if (isNaN(priority)) {
719
+ errors.push("ลำดับความสำคัญต้องเป็นตัวเลข");
720
+ }
632
721
  if (errors.length > 0) {
633
722
  toast.error("ข้อมูลไม่ถูกต้อง", {
634
723
  description: errors.join(", ")
@@ -638,31 +727,32 @@ const ParcelBoxModal = ({ box, onClose }) => {
638
727
  setIsSaving(true);
639
728
  try {
640
729
  const payload = {
641
- name: formData.name.trim(),
642
- width_cm: width,
643
- length_cm: length,
644
- height_cm: height,
645
- max_weight_kg: maxWeight,
646
- price_thb: price,
730
+ carrier_type: "COMPANY_FLEET",
731
+ carrier: "COMPANY_FLEET",
732
+ service_code: "MESSENGER_3H",
733
+ min_distance_km: minDistance,
734
+ max_distance_km: maxDistance === void 0 || isNaN(maxDistance) ? null : maxDistance,
735
+ price,
736
+ currency: "THB",
737
+ priority,
647
738
  active: formData.active
648
739
  };
649
- const url = box ? `/admin/boxes/${box.id}` : "/admin/boxes";
650
- const method = box ? "PUT" : "POST";
740
+ const url = rate ? `/admin/base-shipping-prices/${rate.id}` : "/admin/base-shipping-prices";
741
+ const method = rate ? "PUT" : "POST";
651
742
  const response = await fetch(url, {
652
743
  method,
653
744
  headers: { "Content-Type": "application/json" },
654
745
  credentials: "include",
655
746
  body: JSON.stringify(payload)
656
747
  });
657
- if (response.ok) {
658
- toast.success("สำเร็จ", {
659
- description: box ? "แก้ไขกล่องพัสดุแล้ว" : "สร้างกล่องพัสดุใหม่แล้ว"
660
- });
661
- onClose();
662
- } else {
663
- const error = await response.json();
664
- throw new Error(error.message || "Failed to save");
748
+ if (!response.ok) {
749
+ const error = await response.json().catch(() => ({}));
750
+ throw new Error(error.message || "ไม่สามารถบันทึกข้อมูลได้");
665
751
  }
752
+ toast.success("สำเร็จ", {
753
+ description: rate ? "แก้ไขฐานราคาตามระยะทางแล้ว" : "สร้างฐานราคาตามระยะทางใหม่แล้ว"
754
+ });
755
+ onClose();
666
756
  } catch (error) {
667
757
  toast.error("ข้อผิดพลาด", {
668
758
  description: error instanceof Error ? error.message : "ไม่สามารถบันทึกข้อมูลได้"
@@ -672,82 +762,40 @@ const ParcelBoxModal = ({ box, onClose }) => {
672
762
  }
673
763
  };
674
764
  return /* @__PURE__ */ jsx(Drawer, { open: true, onOpenChange: (open) => !open && onClose(), children: /* @__PURE__ */ jsxs(Drawer.Content, { children: [
675
- /* @__PURE__ */ jsx(Drawer.Header, { children: /* @__PURE__ */ jsx(Drawer.Title, { children: box ? "แก้ไขกล่องพัสดุ" : "สร้างกล่องพัสดุใหม่" }) }),
765
+ /* @__PURE__ */ jsx(Drawer.Header, { children: /* @__PURE__ */ jsx(Drawer.Title, { children: rate ? "แก้ไขฐานราคาตามระยะทาง" : "สร้างฐานราคาตามระยะทาง" }) }),
676
766
  /* @__PURE__ */ jsx(Drawer.Body, { children: /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className: "flex flex-col gap-y-4", children: [
677
- /* @__PURE__ */ jsxs("div", { children: [
678
- /* @__PURE__ */ jsx(Label, { htmlFor: "name", children: "ชื่อกล่อง *" }),
679
- /* @__PURE__ */ jsx(
680
- Input,
681
- {
682
- id: "name",
683
- value: formData.name,
684
- onChange: (e) => setFormData({ ...formData, name: e.target.value }),
685
- placeholder: "เช่น กล่อง S, กล่อง M",
686
- required: true
687
- }
688
- )
689
- ] }),
690
- /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-x-4", children: [
691
- /* @__PURE__ */ jsxs("div", { children: [
692
- /* @__PURE__ */ jsx(Label, { htmlFor: "width", children: "ความกว้าง (cm) *" }),
693
- /* @__PURE__ */ jsx(
694
- Input,
695
- {
696
- id: "width",
697
- type: "number",
698
- step: "0.1",
699
- value: formData.width_cm,
700
- onChange: (e) => setFormData({ ...formData, width_cm: e.target.value }),
701
- placeholder: "20",
702
- required: true
703
- }
704
- )
705
- ] }),
767
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-x-4", children: [
706
768
  /* @__PURE__ */ jsxs("div", { children: [
707
- /* @__PURE__ */ jsx(Label, { htmlFor: "length", children: "ความยาว (cm) *" }),
769
+ /* @__PURE__ */ jsx(Label, { htmlFor: "min_distance_km", children: "ระยะทางเริ่มต้น (กม.) *" }),
708
770
  /* @__PURE__ */ jsx(
709
771
  Input,
710
772
  {
711
- id: "length",
773
+ id: "min_distance_km",
712
774
  type: "number",
775
+ min: "0",
713
776
  step: "0.1",
714
- value: formData.length_cm,
715
- onChange: (e) => setFormData({ ...formData, length_cm: e.target.value }),
716
- placeholder: "30",
777
+ value: formData.min_distance_km,
778
+ onChange: (e) => setFormData({ ...formData, min_distance_km: e.target.value }),
717
779
  required: true
718
780
  }
719
781
  )
720
782
  ] }),
721
783
  /* @__PURE__ */ jsxs("div", { children: [
722
- /* @__PURE__ */ jsx(Label, { htmlFor: "height", children: "ความสูง (cm) *" }),
784
+ /* @__PURE__ */ jsx(Label, { htmlFor: "max_distance_km", children: "ระยะทางสูงสุด (กม.)" }),
723
785
  /* @__PURE__ */ jsx(
724
786
  Input,
725
787
  {
726
- id: "height",
788
+ id: "max_distance_km",
727
789
  type: "number",
790
+ min: "0",
728
791
  step: "0.1",
729
- value: formData.height_cm,
730
- onChange: (e) => setFormData({ ...formData, height_cm: e.target.value }),
731
- placeholder: "15",
732
- required: true
792
+ placeholder: "ปล่อยว่างหากไม่มีที่สิ้นสุด",
793
+ value: formData.max_distance_km,
794
+ onChange: (e) => setFormData({ ...formData, max_distance_km: e.target.value })
733
795
  }
734
- )
735
- ] })
736
- ] }),
737
- /* @__PURE__ */ jsxs("div", { children: [
738
- /* @__PURE__ */ jsx(Label, { htmlFor: "maxWeight", children: "น้ำหนักสูงสุด (kg) *" }),
739
- /* @__PURE__ */ jsx(
740
- Input,
741
- {
742
- id: "maxWeight",
743
- type: "number",
744
- step: "0.1",
745
- value: formData.max_weight_kg,
746
- onChange: (e) => setFormData({ ...formData, max_weight_kg: e.target.value }),
747
- placeholder: "0.5",
748
- required: true
749
- }
750
- )
796
+ ),
797
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-ui-fg-subtle mt-1", children: "เว้นว่างเพื่อกำหนดช่วงราคาแบบ 30+ กม." })
798
+ ] })
751
799
  ] }),
752
800
  /* @__PURE__ */ jsxs("div", { children: [
753
801
  /* @__PURE__ */ jsx(Label, { htmlFor: "price", children: "ราคา (THB) *" }),
@@ -756,14 +804,28 @@ const ParcelBoxModal = ({ box, onClose }) => {
756
804
  {
757
805
  id: "price",
758
806
  type: "number",
807
+ min: "0",
759
808
  step: "0.01",
760
- value: formData.price_thb,
761
- onChange: (e) => setFormData({ ...formData, price_thb: e.target.value }),
762
- placeholder: "10.00",
809
+ value: formData.price,
810
+ onChange: (e) => setFormData({ ...formData, price: e.target.value }),
763
811
  required: true
764
812
  }
765
813
  )
766
814
  ] }),
815
+ /* @__PURE__ */ jsxs("div", { children: [
816
+ /* @__PURE__ */ jsx(Label, { htmlFor: "priority", children: "ลำดับความสำคัญ" }),
817
+ /* @__PURE__ */ jsx(
818
+ Input,
819
+ {
820
+ id: "priority",
821
+ type: "number",
822
+ value: formData.priority,
823
+ onChange: (e) => setFormData({ ...formData, priority: e.target.value }),
824
+ placeholder: "0"
825
+ }
826
+ ),
827
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-ui-fg-subtle mt-1", children: "ใช้สำหรับจัดลำดับเมื่อมีช่วงราคาทับกัน (ค่าเริ่มต้น 0)" })
828
+ ] }),
767
829
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
768
830
  /* @__PURE__ */ jsx(
769
831
  Switch,
@@ -776,197 +838,163 @@ const ParcelBoxModal = ({ box, onClose }) => {
776
838
  /* @__PURE__ */ jsx(Label, { htmlFor: "active", children: "เปิดใช้งาน" })
777
839
  ] }),
778
840
  /* @__PURE__ */ jsxs(Drawer.Footer, { children: [
779
- /* @__PURE__ */ jsx(Button, { type: "button", variant: "secondary", onClick: onClose, disabled: isSaving, children: "ยกเลิก" }),
841
+ /* @__PURE__ */ jsx(
842
+ Button,
843
+ {
844
+ type: "button",
845
+ variant: "secondary",
846
+ onClick: onClose,
847
+ disabled: isSaving,
848
+ children: "ยกเลิก"
849
+ }
850
+ ),
780
851
  /* @__PURE__ */ jsx(Button, { type: "submit", disabled: isSaving, children: isSaving ? "กำลังบันทึก..." : "บันทึก" })
781
852
  ] })
782
853
  ] }) })
783
854
  ] }) });
784
855
  };
785
- const ParcelBoxesTable = () => {
786
- const [boxes, setBoxes] = useState([]);
787
- const [filteredBoxes, setFilteredBoxes] = useState([]);
788
- const [searchTerm, setSearchTerm] = useState("");
789
- const [isModalOpen, setIsModalOpen] = useState(false);
790
- const [editingBox, setEditingBox] = useState(null);
856
+ const MessengerBasePricingTable = () => {
857
+ const [rates, setRates] = useState([]);
791
858
  const [isLoading, setIsLoading] = useState(false);
792
- const [deleteBoxId, setDeleteBoxId] = useState(null);
793
- const [deleteBoxName, setDeleteBoxName] = useState("");
859
+ const [isModalOpen, setIsModalOpen] = useState(false);
860
+ const [editingRate, setEditingRate] = useState(null);
861
+ const [deleteId, setDeleteId] = useState(null);
794
862
  useEffect(() => {
795
- fetchBoxes();
863
+ fetchRates();
796
864
  }, []);
797
- useEffect(() => {
798
- const filtered = boxes.filter(
799
- (box) => box.name.toLowerCase().includes(searchTerm.toLowerCase())
800
- );
801
- setFilteredBoxes(filtered);
802
- }, [searchTerm, boxes]);
803
- const fetchBoxes = async () => {
865
+ const orderedRates = useMemo(() => {
866
+ return [...rates].sort((a, b) => {
867
+ if (a.min_distance_km !== b.min_distance_km) {
868
+ return a.min_distance_km - b.min_distance_km;
869
+ }
870
+ const aMax = a.max_distance_km ?? Number.POSITIVE_INFINITY;
871
+ const bMax = b.max_distance_km ?? Number.POSITIVE_INFINITY;
872
+ return aMax - bMax;
873
+ });
874
+ }, [rates]);
875
+ const fetchRates = async () => {
804
876
  setIsLoading(true);
805
877
  try {
806
- const response = await fetch("/admin/boxes", {
807
- credentials: "include"
808
- });
878
+ const response = await fetch(
879
+ "/admin/base-shipping-prices?carrier_type=COMPANY_FLEET&service_code=MESSENGER_3H",
880
+ {
881
+ credentials: "include"
882
+ }
883
+ );
884
+ if (!response.ok) {
885
+ throw new Error("failed_to_load_base_rates");
886
+ }
809
887
  const data = await response.json();
810
- setBoxes(data.boxes || []);
888
+ setRates(data.base_rates || []);
811
889
  } catch (error) {
812
890
  toast.error("ข้อผิดพลาด", {
813
- description: "ไม่สามารถโหลดข้อมูลกล่องพัสดุได้"
891
+ description: "ไม่สามารถโหลดฐานราคาตามระยะทางได้"
814
892
  });
815
893
  } finally {
816
894
  setIsLoading(false);
817
895
  }
818
896
  };
819
- const handleToggleActive = async (box) => {
820
- try {
821
- const response = await fetch(`/admin/boxes/${box.id}`, {
822
- method: "PUT",
823
- headers: { "Content-Type": "application/json" },
824
- credentials: "include",
825
- body: JSON.stringify({ ...box, active: !box.active })
826
- });
827
- if (response.ok) {
828
- toast.success("สำเร็จ", {
829
- description: `${box.active ? "ปิดใช้งาน" : "เปิดใช้งาน"}กล่อง ${box.name} แล้ว`
830
- });
831
- fetchBoxes();
832
- } else {
833
- throw new Error("Failed to update");
834
- }
835
- } catch (error) {
836
- toast.error("ข้อผิดพลาด", {
837
- description: "ไม่สามารถอัพเดทสถานะได้"
838
- });
839
- }
840
- };
841
897
  const handleDelete = async () => {
842
- if (!deleteBoxId) return;
898
+ if (!deleteId) return;
843
899
  try {
844
- const response = await fetch(`/admin/boxes/${deleteBoxId}`, {
845
- method: "DELETE",
846
- credentials: "include"
847
- });
848
- if (response.ok) {
849
- toast.success("สำเร็จ", {
850
- description: `ลบกล่อง ${deleteBoxName} แล้ว`
851
- });
852
- fetchBoxes();
853
- } else {
854
- throw new Error("Failed to delete");
900
+ const response = await fetch(
901
+ `/admin/base-shipping-prices/${deleteId}`,
902
+ {
903
+ method: "DELETE",
904
+ credentials: "include"
905
+ }
906
+ );
907
+ if (!response.ok) {
908
+ throw new Error("failed_to_delete");
855
909
  }
910
+ toast.success("สำเร็จ", {
911
+ description: "ลบฐานราคาสำเร็จ"
912
+ });
913
+ fetchRates();
856
914
  } catch (error) {
857
915
  toast.error("ข้อผิดพลาด", {
858
- description: "ไม่สามารถลบกล่องได้"
916
+ description: "ไม่สามารถลบฐานราคาได้"
859
917
  });
860
918
  } finally {
861
- setDeleteBoxId(null);
862
- setDeleteBoxName("");
919
+ setDeleteId(null);
863
920
  }
864
921
  };
865
- const handleEdit = (box) => {
866
- setEditingBox(box);
867
- setIsModalOpen(true);
868
- };
869
- const handleCreateNew = () => {
870
- setEditingBox(null);
871
- setIsModalOpen(true);
872
- };
873
922
  const handleModalClose = () => {
874
923
  setIsModalOpen(false);
875
- setEditingBox(null);
876
- fetchBoxes();
924
+ setEditingRate(null);
925
+ fetchRates();
877
926
  };
878
- const openDeletePrompt = (id, name) => {
879
- setDeleteBoxId(id);
880
- setDeleteBoxName(name);
927
+ const formatDistanceRange = (rate) => {
928
+ const min = rate.min_distance_km ?? 0;
929
+ const max = rate.max_distance_km;
930
+ if (max === void 0 || max === null) {
931
+ return `${min}+ กม.`;
932
+ }
933
+ return `${min}-${max} กม.`;
881
934
  };
882
935
  return /* @__PURE__ */ jsxs(Fragment, { children: [
883
- /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-4", children: [
884
- /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-x-4", children: [
885
- /* @__PURE__ */ jsx(
886
- Input,
887
- {
888
- type: "search",
889
- placeholder: "ค้นหาชื่อกล่อง...",
890
- value: searchTerm,
891
- onChange: (e) => setSearchTerm(e.target.value),
892
- className: "max-w-md"
893
- }
894
- ),
895
- /* @__PURE__ */ jsxs(Button, { onClick: handleCreateNew, children: [
896
- /* @__PURE__ */ jsx(Plus, {}),
897
- "สร้างกล่องใหม่"
898
- ] })
936
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-x-4", children: [
937
+ /* @__PURE__ */ jsxs("div", { children: [
938
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-semibold", children: "ฐานราคาตามระยะทาง (Messenger 3H)" }),
939
+ /* @__PURE__ */ jsx("p", { className: "text-ui-fg-subtle text-sm", children: "กำหนดราคาเริ่มต้นตามระยะทาง เช่น 0-5, 5-20, 20-30, 30+ กม." })
899
940
  ] }),
900
- /* @__PURE__ */ jsxs(Table, { children: [
901
- /* @__PURE__ */ jsx(Table.Header, { children: /* @__PURE__ */ jsxs(Table.Row, { children: [
902
- /* @__PURE__ */ jsx(Table.HeaderCell, { children: "ชื่อ" }),
903
- /* @__PURE__ */ jsx(Table.HeaderCell, { children: "ขนาด (กว้าง×ยาว×สูง cm)" }),
904
- /* @__PURE__ */ jsx(Table.HeaderCell, { children: "น้ำหนักสูงสุด (kg)" }),
905
- /* @__PURE__ */ jsx(Table.HeaderCell, { children: "ราคา (THB)" }),
906
- /* @__PURE__ */ jsx(Table.HeaderCell, { children: "สถานะ" }),
907
- /* @__PURE__ */ jsx(Table.HeaderCell, { className: "text-right", children: "การจัดการ" })
908
- ] }) }),
909
- /* @__PURE__ */ jsx(Table.Body, { children: isLoading ? /* @__PURE__ */ jsx(Table.Row, { children: /* @__PURE__ */ jsx(Table.Cell, { className: "text-center", children: "กำลังโหลด..." }) }) : filteredBoxes.length === 0 ? /* @__PURE__ */ jsx(Table.Row, { children: /* @__PURE__ */ jsx(Table.Cell, { className: "text-center", children: "ไม่พบข้อมูลกล่องพัสดุ" }) }) : filteredBoxes.map((box) => /* @__PURE__ */ jsxs(Table.Row, { children: [
910
- /* @__PURE__ */ jsx(Table.Cell, { children: box.name }),
911
- /* @__PURE__ */ jsxs(Table.Cell, { children: [
912
- box.width_cm,
913
- " × ",
914
- box.length_cm,
915
- " × ",
916
- box.height_cm
917
- ] }),
918
- /* @__PURE__ */ jsx(Table.Cell, { children: box.max_weight_kg }),
919
- /* @__PURE__ */ jsx(Table.Cell, { children: box.price_thb.toFixed(2) }),
920
- /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
921
- Badge,
922
- {
923
- color: box.active ? "green" : "grey",
924
- className: "cursor-pointer",
925
- onClick: () => handleToggleActive(box),
926
- children: box.active ? "เปิดใช้งาน" : "ปิดใช้งาน"
927
- }
928
- ) }),
929
- /* @__PURE__ */ jsx(Table.Cell, { className: "text-right", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
930
- /* @__PURE__ */ jsx(
931
- Button,
932
- {
933
- variant: "transparent",
934
- size: "small",
935
- onClick: () => handleEdit(box),
936
- children: /* @__PURE__ */ jsx(Edit, {})
937
- }
938
- ),
939
- /* @__PURE__ */ jsx(
940
- Button,
941
- {
942
- variant: "transparent",
943
- size: "small",
944
- onClick: () => openDeletePrompt(box.id, box.name),
945
- children: /* @__PURE__ */ jsx(Trash, {})
946
- }
947
- )
948
- ] }) })
949
- ] }, box.id)) })
941
+ /* @__PURE__ */ jsxs(Button, { onClick: () => setIsModalOpen(true), children: [
942
+ /* @__PURE__ */ jsx(Plus, {}),
943
+ "เพิ่มช่วงราคา"
950
944
  ] })
951
945
  ] }),
952
- isModalOpen && /* @__PURE__ */ jsx(ParcelBoxModal, { box: editingBox, onClose: handleModalClose }),
946
+ /* @__PURE__ */ jsxs(Table, { className: "mt-4", children: [
947
+ /* @__PURE__ */ jsx(Table.Header, { children: /* @__PURE__ */ jsxs(Table.Row, { children: [
948
+ /* @__PURE__ */ jsx(Table.HeaderCell, { children: "ช่วงระยะทาง" }),
949
+ /* @__PURE__ */ jsx(Table.HeaderCell, { children: "ราคา (THB)" }),
950
+ /* @__PURE__ */ jsx(Table.HeaderCell, { children: "ลำดับ" }),
951
+ /* @__PURE__ */ jsx(Table.HeaderCell, { children: "สถานะ" }),
952
+ /* @__PURE__ */ jsx(Table.HeaderCell, { className: "text-right", children: "การจัดการ" })
953
+ ] }) }),
954
+ /* @__PURE__ */ jsx(Table.Body, { children: isLoading ? /* @__PURE__ */ jsx(Table.Row, { children: /* @__PURE__ */ jsx(Table.Cell, { className: "text-center", children: "กำลังโหลด..." }) }) : orderedRates.length === 0 ? /* @__PURE__ */ jsx(Table.Row, { children: /* @__PURE__ */ jsx(Table.Cell, { className: "text-center", children: "ยังไม่ได้ตั้งค่าฐานราคาตามระยะทาง" }) }) : orderedRates.map((rate) => /* @__PURE__ */ jsxs(Table.Row, { children: [
955
+ /* @__PURE__ */ jsx(Table.Cell, { children: formatDistanceRange(rate) }),
956
+ /* @__PURE__ */ jsxs(Table.Cell, { children: [
957
+ "฿",
958
+ rate.price.toFixed(2)
959
+ ] }),
960
+ /* @__PURE__ */ jsx(Table.Cell, { children: rate.priority ?? 0 }),
961
+ /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Badge, { color: rate.active ? "green" : "grey", children: rate.active ? "เปิดใช้งาน" : "ปิดใช้งาน" }) }),
962
+ /* @__PURE__ */ jsx(Table.Cell, { className: "text-right", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
963
+ /* @__PURE__ */ jsx(
964
+ Button,
965
+ {
966
+ variant: "transparent",
967
+ size: "small",
968
+ onClick: () => {
969
+ setEditingRate(rate);
970
+ setIsModalOpen(true);
971
+ },
972
+ children: /* @__PURE__ */ jsx(Edit, {})
973
+ }
974
+ ),
975
+ /* @__PURE__ */ jsx(
976
+ Button,
977
+ {
978
+ variant: "transparent",
979
+ size: "small",
980
+ onClick: () => setDeleteId(rate.id),
981
+ children: /* @__PURE__ */ jsx(Trash, {})
982
+ }
983
+ )
984
+ ] }) })
985
+ ] }, rate.id)) })
986
+ ] }),
987
+ isModalOpen && /* @__PURE__ */ jsx(MessengerBaseRateModal, { rate: editingRate, onClose: handleModalClose }),
953
988
  /* @__PURE__ */ jsx(
954
989
  Prompt,
955
990
  {
956
991
  variant: "confirmation",
957
- open: !!deleteBoxId,
958
- onOpenChange: () => {
959
- setDeleteBoxId(null);
960
- setDeleteBoxName("");
961
- },
992
+ open: !!deleteId,
993
+ onOpenChange: () => setDeleteId(null),
962
994
  children: /* @__PURE__ */ jsxs(Prompt.Content, { children: [
963
995
  /* @__PURE__ */ jsxs(Prompt.Header, { children: [
964
- /* @__PURE__ */ jsx(Prompt.Title, { children: "ลบกล่องพัสดุ" }),
965
- /* @__PURE__ */ jsxs(Prompt.Description, { children: [
966
- 'คุณต้องการลบกล่อง "',
967
- deleteBoxName,
968
- '" ใช่หรือไม่? การดำเนินการนี้ไม่สามารถย้อนกลับได้'
969
- ] })
996
+ /* @__PURE__ */ jsx(Prompt.Title, { children: "ลบฐานราคา" }),
997
+ /* @__PURE__ */ jsx(Prompt.Description, { children: "คุณต้องการลบช่วงราคานี้ใช่หรือไม่? การดำเนินการนี้ไม่สามารถย้อนกลับได้" })
970
998
  ] }),
971
999
  /* @__PURE__ */ jsxs(Prompt.Footer, { children: [
972
1000
  /* @__PURE__ */ jsx(Prompt.Cancel, { children: "ยกเลิก" }),
@@ -977,126 +1005,68 @@ const ParcelBoxesTable = () => {
977
1005
  )
978
1006
  ] });
979
1007
  };
980
- const BoxesPage = () => {
981
- return /* @__PURE__ */ jsx(Container, { children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-4", children: [
982
- /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsx(Heading, { level: "h1", children: "กล่องพัสดุ" }) }),
983
- /* @__PURE__ */ jsx(ParcelBoxesTable, {})
1008
+ const BasePricingPage = () => {
1009
+ return /* @__PURE__ */ jsx(Container, { children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-6", children: [
1010
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-1", children: [
1011
+ /* @__PURE__ */ jsx(Heading, { level: "h1", children: "ฐานราคาตามระยะทาง (Messenger)" }),
1012
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "ตั้งราคาฐานสำหรับบริการ Messenger 3 ชั่วโมงตามช่วงระยะทาง เช่น 0-5, 5-20, 20-30, 30+ กม." })
1013
+ ] }),
1014
+ /* @__PURE__ */ jsx(MessengerBasePricingTable, {})
984
1015
  ] }) });
985
1016
  };
986
1017
  const config$3 = defineRouteConfig({
987
- icon: ArchiveBox,
988
- label: "กล่องพัสดุ"
1018
+ icon: Directions,
1019
+ label: "ฐานราคาตามระยะทาง"
989
1020
  });
990
- const TH_PROVINCES = [
991
- "กรุงเทพมหานคร",
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
- ];
1069
- const ServiceAreaModal = ({ area, onClose }) => {
1021
+ const ParcelBoxModal = ({ box, onClose }) => {
1070
1022
  const [formData, setFormData] = useState({
1071
- kind: "PROVINCE",
1072
- value: "",
1023
+ name: "",
1024
+ width_cm: "",
1025
+ length_cm: "",
1026
+ height_cm: "",
1027
+ max_weight_kg: "",
1028
+ price_thb: "",
1073
1029
  active: true
1074
1030
  });
1075
1031
  const [isSaving, setIsSaving] = useState(false);
1076
1032
  useEffect(() => {
1077
- if (area) {
1033
+ if (box) {
1078
1034
  setFormData({
1079
- kind: area.kind,
1080
- value: area.value,
1081
- active: area.active
1035
+ name: box.name,
1036
+ width_cm: box.width_cm.toString(),
1037
+ length_cm: box.length_cm.toString(),
1038
+ height_cm: box.height_cm.toString(),
1039
+ max_weight_kg: box.max_weight_kg.toString(),
1040
+ price_thb: box.price_thb.toString(),
1041
+ active: box.active
1082
1042
  });
1083
1043
  }
1084
- }, [area]);
1044
+ }, [box]);
1085
1045
  const handleSubmit = async (e) => {
1086
1046
  e.preventDefault();
1087
1047
  const errors = [];
1088
- const trimmedValue = formData.value.trim();
1089
- if (!trimmedValue) {
1090
- errors.push("กรุณากรอกค่า");
1048
+ if (!formData.name.trim()) {
1049
+ errors.push("กรุณากรอกชื่อกล่อง");
1091
1050
  }
1092
- if (formData.kind === "PROVINCE") {
1093
- if (!TH_PROVINCES.includes(trimmedValue)) {
1094
- errors.push("จังหวัดไม่ถูกต้อง กรุณาตรวจสอบการสะกดชื่อจังหวัด");
1095
- }
1096
- } else if (formData.kind === "POSTCODE_PREFIX") {
1097
- if (!/^\d{1,5}$/.test(trimmedValue)) {
1098
- errors.push("รหัสไปรษณีย์ต้องเป็นตัวเลข 1-5 หลัก");
1099
- }
1051
+ const width = parseFloat(formData.width_cm);
1052
+ const length = parseFloat(formData.length_cm);
1053
+ const height = parseFloat(formData.height_cm);
1054
+ const maxWeight = parseFloat(formData.max_weight_kg);
1055
+ const price = parseFloat(formData.price_thb);
1056
+ if (isNaN(width) || width <= 0) {
1057
+ errors.push("ความกว้างต้องเป็นตัวเลขมากกว่า 0");
1058
+ }
1059
+ if (isNaN(length) || length <= 0) {
1060
+ errors.push("ความยาวต้องเป็นตัวเลขมากกว่า 0");
1061
+ }
1062
+ if (isNaN(height) || height <= 0) {
1063
+ errors.push("ความสูงต้องเป็นตัวเลขมากกว่า 0");
1064
+ }
1065
+ if (isNaN(maxWeight) || maxWeight <= 0) {
1066
+ errors.push("น้ำหนักสูงสุดต้องเป็นตัวเลขมากกว่า 0");
1067
+ }
1068
+ if (isNaN(price) || price < 0) {
1069
+ errors.push("ราคาต้องเป็นตัวเลขไม่ติดลบ");
1100
1070
  }
1101
1071
  if (errors.length > 0) {
1102
1072
  toast.error("ข้อมูลไม่ถูกต้อง", {
@@ -1107,12 +1077,16 @@ const ServiceAreaModal = ({ area, onClose }) => {
1107
1077
  setIsSaving(true);
1108
1078
  try {
1109
1079
  const payload = {
1110
- kind: formData.kind,
1111
- value: trimmedValue,
1080
+ name: formData.name.trim(),
1081
+ width_cm: width,
1082
+ length_cm: length,
1083
+ height_cm: height,
1084
+ max_weight_kg: maxWeight,
1085
+ price_thb: price,
1112
1086
  active: formData.active
1113
1087
  };
1114
- const url = area ? `/admin/service-areas/${area.id}` : "/admin/service-areas";
1115
- const method = area ? "PUT" : "POST";
1088
+ const url = box ? `/admin/boxes/${box.id}` : "/admin/boxes";
1089
+ const method = box ? "PUT" : "POST";
1116
1090
  const response = await fetch(url, {
1117
1091
  method,
1118
1092
  headers: { "Content-Type": "application/json" },
@@ -1121,7 +1095,7 @@ const ServiceAreaModal = ({ area, onClose }) => {
1121
1095
  });
1122
1096
  if (response.ok) {
1123
1097
  toast.success("สำเร็จ", {
1124
- description: area ? "แก้ไขพื้นที่บริการแล้ว" : "สร้างพื้นที่บริการใหม่แล้ว"
1098
+ description: box ? "แก้ไขกล่องพัสดุแล้ว" : "สร้างกล่องพัสดุใหม่แล้ว"
1125
1099
  });
1126
1100
  onClose();
1127
1101
  } else {
@@ -1137,53 +1111,97 @@ const ServiceAreaModal = ({ area, onClose }) => {
1137
1111
  }
1138
1112
  };
1139
1113
  return /* @__PURE__ */ jsx(Drawer, { open: true, onOpenChange: (open) => !open && onClose(), children: /* @__PURE__ */ jsxs(Drawer.Content, { children: [
1140
- /* @__PURE__ */ jsx(Drawer.Header, { children: /* @__PURE__ */ jsx(Drawer.Title, { children: area ? "แก้ไขพื้นที่บริการ" : "สร้างพื้นที่บริการใหม่" }) }),
1114
+ /* @__PURE__ */ jsx(Drawer.Header, { children: /* @__PURE__ */ jsx(Drawer.Title, { children: box ? "แก้ไขกล่องพัสดุ" : "สร้างกล่องพัสดุใหม่" }) }),
1141
1115
  /* @__PURE__ */ jsx(Drawer.Body, { children: /* @__PURE__ */ jsxs("form", { onSubmit: handleSubmit, className: "flex flex-col gap-y-4", children: [
1142
1116
  /* @__PURE__ */ jsxs("div", { children: [
1143
- /* @__PURE__ */ jsx(Label, { htmlFor: "kind", children: "ประเภท *" }),
1144
- /* @__PURE__ */ jsxs(
1145
- Select,
1117
+ /* @__PURE__ */ jsx(Label, { htmlFor: "name", children: "ชื่อกล่อง *" }),
1118
+ /* @__PURE__ */ jsx(
1119
+ Input,
1120
+ {
1121
+ id: "name",
1122
+ value: formData.name,
1123
+ onChange: (e) => setFormData({ ...formData, name: e.target.value }),
1124
+ placeholder: "เช่น กล่อง S, กล่อง M",
1125
+ required: true
1126
+ }
1127
+ )
1128
+ ] }),
1129
+ /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-3 gap-x-4", children: [
1130
+ /* @__PURE__ */ jsxs("div", { children: [
1131
+ /* @__PURE__ */ jsx(Label, { htmlFor: "width", children: "ความกว้าง (cm) *" }),
1132
+ /* @__PURE__ */ jsx(
1133
+ Input,
1134
+ {
1135
+ id: "width",
1136
+ type: "number",
1137
+ step: "0.1",
1138
+ value: formData.width_cm,
1139
+ onChange: (e) => setFormData({ ...formData, width_cm: e.target.value }),
1140
+ placeholder: "20",
1141
+ required: true
1142
+ }
1143
+ )
1144
+ ] }),
1145
+ /* @__PURE__ */ jsxs("div", { children: [
1146
+ /* @__PURE__ */ jsx(Label, { htmlFor: "length", children: "ความยาว (cm) *" }),
1147
+ /* @__PURE__ */ jsx(
1148
+ Input,
1149
+ {
1150
+ id: "length",
1151
+ type: "number",
1152
+ step: "0.1",
1153
+ value: formData.length_cm,
1154
+ onChange: (e) => setFormData({ ...formData, length_cm: e.target.value }),
1155
+ placeholder: "30",
1156
+ required: true
1157
+ }
1158
+ )
1159
+ ] }),
1160
+ /* @__PURE__ */ jsxs("div", { children: [
1161
+ /* @__PURE__ */ jsx(Label, { htmlFor: "height", children: "ความสูง (cm) *" }),
1162
+ /* @__PURE__ */ jsx(
1163
+ Input,
1164
+ {
1165
+ id: "height",
1166
+ type: "number",
1167
+ step: "0.1",
1168
+ value: formData.height_cm,
1169
+ onChange: (e) => setFormData({ ...formData, height_cm: e.target.value }),
1170
+ placeholder: "15",
1171
+ required: true
1172
+ }
1173
+ )
1174
+ ] })
1175
+ ] }),
1176
+ /* @__PURE__ */ jsxs("div", { children: [
1177
+ /* @__PURE__ */ jsx(Label, { htmlFor: "maxWeight", children: "น้ำหนักสูงสุด (kg) *" }),
1178
+ /* @__PURE__ */ jsx(
1179
+ Input,
1146
1180
  {
1147
- value: formData.kind,
1148
- onValueChange: (value) => setFormData({ ...formData, kind: value, value: "" }),
1149
- required: true,
1150
- children: [
1151
- /* @__PURE__ */ jsx(Select.Trigger, { children: /* @__PURE__ */ jsx(Select.Value, { placeholder: "เลือกประเภท" }) }),
1152
- /* @__PURE__ */ jsxs(Select.Content, { children: [
1153
- /* @__PURE__ */ jsx(Select.Item, { value: "PROVINCE", children: "จังหวัด" }),
1154
- /* @__PURE__ */ jsx(Select.Item, { value: "POSTCODE_PREFIX", children: "รหัสไปรษณีย์" })
1155
- ] })
1156
- ]
1181
+ id: "maxWeight",
1182
+ type: "number",
1183
+ step: "0.1",
1184
+ value: formData.max_weight_kg,
1185
+ onChange: (e) => setFormData({ ...formData, max_weight_kg: e.target.value }),
1186
+ placeholder: "0.5",
1187
+ required: true
1157
1188
  }
1158
1189
  )
1159
1190
  ] }),
1160
1191
  /* @__PURE__ */ jsxs("div", { children: [
1161
- /* @__PURE__ */ jsx(Label, { htmlFor: "value", children: formData.kind === "PROVINCE" ? "ชื่อจังหวัด *" : "รหัสไปรษณีย์ (1-5 หลัก) *" }),
1162
- formData.kind === "PROVINCE" ? /* @__PURE__ */ jsxs(
1163
- Select,
1164
- {
1165
- value: formData.value,
1166
- onValueChange: (value) => setFormData({ ...formData, value }),
1167
- required: true,
1168
- children: [
1169
- /* @__PURE__ */ jsx(Select.Trigger, { children: /* @__PURE__ */ jsx(Select.Value, { placeholder: "เลือกจังหวัด" }) }),
1170
- /* @__PURE__ */ jsx(Select.Content, { children: TH_PROVINCES.map((province) => /* @__PURE__ */ jsx(Select.Item, { value: province, children: province }, province)) })
1171
- ]
1172
- }
1173
- ) : /* @__PURE__ */ jsx(
1192
+ /* @__PURE__ */ jsx(Label, { htmlFor: "price", children: "ราคา (THB) *" }),
1193
+ /* @__PURE__ */ jsx(
1174
1194
  Input,
1175
1195
  {
1176
- id: "value",
1177
- type: "text",
1178
- value: formData.value,
1179
- onChange: (e) => setFormData({ ...formData, value: e.target.value }),
1180
- placeholder: "เช่น 10, 102, 10200",
1181
- maxLength: 5,
1182
- pattern: "\\d{1,5}",
1196
+ id: "price",
1197
+ type: "number",
1198
+ step: "0.01",
1199
+ value: formData.price_thb,
1200
+ onChange: (e) => setFormData({ ...formData, price_thb: e.target.value }),
1201
+ placeholder: "10.00",
1183
1202
  required: true
1184
1203
  }
1185
- ),
1186
- formData.kind === "POSTCODE_PREFIX" && /* @__PURE__ */ jsx("p", { className: "text-xs text-ui-fg-subtle mt-1", children: 'ใส่รหัส 1-5 หลักเพื่อครอบคลุมหลายพื้นที่ เช่น "10" = กรุงเทพฯ ทั้งหมด' })
1204
+ )
1187
1205
  ] }),
1188
1206
  /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-x-2", children: [
1189
1207
  /* @__PURE__ */ jsx(
@@ -1197,81 +1215,59 @@ const ServiceAreaModal = ({ area, onClose }) => {
1197
1215
  /* @__PURE__ */ jsx(Label, { htmlFor: "active", children: "เปิดใช้งาน" })
1198
1216
  ] }),
1199
1217
  /* @__PURE__ */ jsxs(Drawer.Footer, { children: [
1200
- /* @__PURE__ */ jsx(
1201
- Button,
1202
- {
1203
- type: "button",
1204
- variant: "secondary",
1205
- onClick: onClose,
1206
- disabled: isSaving,
1207
- children: "ยกเลิก"
1208
- }
1209
- ),
1218
+ /* @__PURE__ */ jsx(Button, { type: "button", variant: "secondary", onClick: onClose, disabled: isSaving, children: "ยกเลิก" }),
1210
1219
  /* @__PURE__ */ jsx(Button, { type: "submit", disabled: isSaving, children: isSaving ? "กำลังบันทึก..." : "บันทึก" })
1211
1220
  ] })
1212
1221
  ] }) })
1213
1222
  ] }) });
1214
1223
  };
1215
- const AREA_KINDS = [
1216
- { value: "ALL", label: "ทั้งหมด" },
1217
- { value: "PROVINCE", label: "จังหวัด" },
1218
- { value: "POSTCODE_PREFIX", label: "รหัสไปรษณีย์" }
1219
- ];
1220
- const ServiceAreasTable = () => {
1221
- const [areas, setAreas] = useState([]);
1222
- const [filteredAreas, setFilteredAreas] = useState([]);
1224
+ const ParcelBoxesTable = () => {
1225
+ const [boxes, setBoxes] = useState([]);
1226
+ const [filteredBoxes, setFilteredBoxes] = useState([]);
1223
1227
  const [searchTerm, setSearchTerm] = useState("");
1224
- const [kindFilter, setKindFilter] = useState("ALL");
1225
1228
  const [isModalOpen, setIsModalOpen] = useState(false);
1226
- const [editingArea, setEditingArea] = useState(null);
1229
+ const [editingBox, setEditingBox] = useState(null);
1227
1230
  const [isLoading, setIsLoading] = useState(false);
1228
- const [deleteAreaId, setDeleteAreaId] = useState(null);
1229
- const [deleteAreaValue, setDeleteAreaValue] = useState("");
1231
+ const [deleteBoxId, setDeleteBoxId] = useState(null);
1232
+ const [deleteBoxName, setDeleteBoxName] = useState("");
1230
1233
  useEffect(() => {
1231
- fetchAreas();
1234
+ fetchBoxes();
1232
1235
  }, []);
1233
1236
  useEffect(() => {
1234
- let filtered = areas;
1235
- if (kindFilter !== "ALL") {
1236
- filtered = filtered.filter((area) => area.kind === kindFilter);
1237
- }
1238
- if (searchTerm) {
1239
- filtered = filtered.filter(
1240
- (area) => area.value.toLowerCase().includes(searchTerm.toLowerCase())
1241
- );
1242
- }
1243
- setFilteredAreas(filtered);
1244
- }, [searchTerm, kindFilter, areas]);
1245
- const fetchAreas = async () => {
1237
+ const filtered = boxes.filter(
1238
+ (box) => box.name.toLowerCase().includes(searchTerm.toLowerCase())
1239
+ );
1240
+ setFilteredBoxes(filtered);
1241
+ }, [searchTerm, boxes]);
1242
+ const fetchBoxes = async () => {
1246
1243
  setIsLoading(true);
1247
1244
  try {
1248
- const response = await fetch("/admin/service-areas", {
1245
+ const response = await fetch("/admin/boxes", {
1249
1246
  credentials: "include"
1250
1247
  });
1251
1248
  const data = await response.json();
1252
- console.log("Fetched service areas:", data);
1253
- setAreas(data.service_areas || []);
1249
+ setBoxes(data.boxes || []);
1254
1250
  } catch (error) {
1255
1251
  toast.error("ข้อผิดพลาด", {
1256
- description: "ไม่สามารถโหลดข้อมูลพื้นที่บริการได้"
1252
+ description: "ไม่สามารถโหลดข้อมูลกล่องพัสดุได้"
1257
1253
  });
1258
1254
  } finally {
1259
1255
  setIsLoading(false);
1260
1256
  }
1261
1257
  };
1262
- const handleToggleActive = async (area) => {
1258
+ const handleToggleActive = async (box) => {
1263
1259
  try {
1264
- const response = await fetch(`/admin/service-areas/${area.id}`, {
1260
+ const response = await fetch(`/admin/boxes/${box.id}`, {
1265
1261
  method: "PUT",
1266
1262
  headers: { "Content-Type": "application/json" },
1267
1263
  credentials: "include",
1268
- body: JSON.stringify({ ...area, active: !area.active })
1264
+ body: JSON.stringify({ ...box, active: !box.active })
1269
1265
  });
1270
1266
  if (response.ok) {
1271
1267
  toast.success("สำเร็จ", {
1272
- description: `${area.active ? "ปิดใช้งาน" : "เปิดใช้งาน"}พื้นที่ ${area.value} แล้ว`
1268
+ description: `${box.active ? "ปิดใช้งาน" : "เปิดใช้งาน"}กล่อง ${box.name} แล้ว`
1273
1269
  });
1274
- fetchAreas();
1270
+ fetchBoxes();
1275
1271
  } else {
1276
1272
  throw new Error("Failed to update");
1277
1273
  }
@@ -1282,87 +1278,91 @@ const ServiceAreasTable = () => {
1282
1278
  }
1283
1279
  };
1284
1280
  const handleDelete = async () => {
1285
- if (!deleteAreaId) return;
1281
+ if (!deleteBoxId) return;
1286
1282
  try {
1287
- const response = await fetch(`/admin/service-areas/${deleteAreaId}`, {
1283
+ const response = await fetch(`/admin/boxes/${deleteBoxId}`, {
1288
1284
  method: "DELETE",
1289
1285
  credentials: "include"
1290
1286
  });
1291
1287
  if (response.ok) {
1292
1288
  toast.success("สำเร็จ", {
1293
- description: `ลบพื้นที่ ${deleteAreaValue} แล้ว`
1289
+ description: `ลบกล่อง ${deleteBoxName} แล้ว`
1294
1290
  });
1295
- fetchAreas();
1291
+ fetchBoxes();
1296
1292
  } else {
1297
1293
  throw new Error("Failed to delete");
1298
1294
  }
1299
1295
  } catch (error) {
1300
1296
  toast.error("ข้อผิดพลาด", {
1301
- description: "ไม่สามารถลบพื้นที่ได้"
1297
+ description: "ไม่สามารถลบกล่องได้"
1302
1298
  });
1303
1299
  } finally {
1304
- setDeleteAreaId(null);
1305
- setDeleteAreaValue("");
1300
+ setDeleteBoxId(null);
1301
+ setDeleteBoxName("");
1306
1302
  }
1307
1303
  };
1308
- const handleEdit = (area) => {
1309
- setEditingArea(area);
1304
+ const handleEdit = (box) => {
1305
+ setEditingBox(box);
1310
1306
  setIsModalOpen(true);
1311
1307
  };
1312
1308
  const handleCreateNew = () => {
1313
- setEditingArea(null);
1309
+ setEditingBox(null);
1314
1310
  setIsModalOpen(true);
1315
1311
  };
1316
1312
  const handleModalClose = () => {
1317
1313
  setIsModalOpen(false);
1318
- setEditingArea(null);
1319
- fetchAreas();
1314
+ setEditingBox(null);
1315
+ fetchBoxes();
1320
1316
  };
1321
- const openDeletePrompt = (id, value) => {
1322
- setDeleteAreaId(id);
1323
- setDeleteAreaValue(value);
1317
+ const openDeletePrompt = (id, name) => {
1318
+ setDeleteBoxId(id);
1319
+ setDeleteBoxName(name);
1324
1320
  };
1325
1321
  return /* @__PURE__ */ jsxs(Fragment, { children: [
1326
1322
  /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-4", children: [
1327
1323
  /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-x-4", children: [
1328
- /* @__PURE__ */ jsxs("div", { className: "flex gap-x-4 flex-1", children: [
1329
- /* @__PURE__ */ jsx(
1330
- Input,
1331
- {
1332
- type: "search",
1333
- placeholder: "ค้นหาจังหวัดหรือรหัสไปรษณีย์...",
1334
- value: searchTerm,
1335
- onChange: (e) => setSearchTerm(e.target.value),
1336
- className: "max-w-md"
1337
- }
1338
- ),
1339
- /* @__PURE__ */ jsxs(Select, { value: kindFilter, onValueChange: setKindFilter, children: [
1340
- /* @__PURE__ */ jsx(Select.Trigger, { children: /* @__PURE__ */ jsx(Select.Value, { placeholder: "ประเภท" }) }),
1341
- /* @__PURE__ */ jsx(Select.Content, { children: AREA_KINDS.map((kind) => /* @__PURE__ */ jsx(Select.Item, { value: kind.value, children: kind.label }, kind.value)) })
1342
- ] })
1343
- ] }),
1324
+ /* @__PURE__ */ jsx(
1325
+ Input,
1326
+ {
1327
+ type: "search",
1328
+ placeholder: "ค้นหาชื่อกล่อง...",
1329
+ value: searchTerm,
1330
+ onChange: (e) => setSearchTerm(e.target.value),
1331
+ className: "max-w-md"
1332
+ }
1333
+ ),
1344
1334
  /* @__PURE__ */ jsxs(Button, { onClick: handleCreateNew, children: [
1345
1335
  /* @__PURE__ */ jsx(Plus, {}),
1346
- "สร้างพื้นที่ใหม่"
1336
+ "สร้างกล่องใหม่"
1347
1337
  ] })
1348
1338
  ] }),
1349
1339
  /* @__PURE__ */ jsxs(Table, { children: [
1350
1340
  /* @__PURE__ */ jsx(Table.Header, { children: /* @__PURE__ */ jsxs(Table.Row, { children: [
1351
- /* @__PURE__ */ jsx(Table.HeaderCell, { children: "ประเภท" }),
1352
- /* @__PURE__ */ jsx(Table.HeaderCell, { children: "ค่า" }),
1341
+ /* @__PURE__ */ jsx(Table.HeaderCell, { children: "ชื่อ" }),
1342
+ /* @__PURE__ */ jsx(Table.HeaderCell, { children: "ขนาด (กว้าง×ยาว×สูง cm)" }),
1343
+ /* @__PURE__ */ jsx(Table.HeaderCell, { children: "น้ำหนักสูงสุด (kg)" }),
1344
+ /* @__PURE__ */ jsx(Table.HeaderCell, { children: "ราคา (THB)" }),
1353
1345
  /* @__PURE__ */ jsx(Table.HeaderCell, { children: "สถานะ" }),
1354
1346
  /* @__PURE__ */ jsx(Table.HeaderCell, { className: "text-right", children: "การจัดการ" })
1355
1347
  ] }) }),
1356
- /* @__PURE__ */ jsx(Table.Body, { children: isLoading ? /* @__PURE__ */ jsx(Table.Row, { children: /* @__PURE__ */ jsx(Table.Cell, { className: "text-center", children: "กำลังโหลด..." }) }) : filteredAreas.length === 0 ? /* @__PURE__ */ jsx(Table.Row, { children: /* @__PURE__ */ jsx(Table.Cell, { className: "text-center", children: "ไม่พบข้อมูลพื้นที่บริการ" }) }) : filteredAreas.map((area) => /* @__PURE__ */ jsxs(Table.Row, { children: [
1357
- /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(Badge, { color: area.kind === "PROVINCE" ? "blue" : "purple", children: area.kind === "PROVINCE" ? "จังหวัด" : "รหัสไปรษณีย์" }) }),
1358
- /* @__PURE__ */ jsx(Table.Cell, { children: area.value }),
1348
+ /* @__PURE__ */ jsx(Table.Body, { children: isLoading ? /* @__PURE__ */ jsx(Table.Row, { children: /* @__PURE__ */ jsx(Table.Cell, { className: "text-center", children: "กำลังโหลด..." }) }) : filteredBoxes.length === 0 ? /* @__PURE__ */ jsx(Table.Row, { children: /* @__PURE__ */ jsx(Table.Cell, { className: "text-center", children: "ไม่พบข้อมูลกล่องพัสดุ" }) }) : filteredBoxes.map((box) => /* @__PURE__ */ jsxs(Table.Row, { children: [
1349
+ /* @__PURE__ */ jsx(Table.Cell, { children: box.name }),
1350
+ /* @__PURE__ */ jsxs(Table.Cell, { children: [
1351
+ box.width_cm,
1352
+ " × ",
1353
+ box.length_cm,
1354
+ " × ",
1355
+ box.height_cm
1356
+ ] }),
1357
+ /* @__PURE__ */ jsx(Table.Cell, { children: box.max_weight_kg }),
1358
+ /* @__PURE__ */ jsx(Table.Cell, { children: box.price_thb.toFixed(2) }),
1359
1359
  /* @__PURE__ */ jsx(Table.Cell, { children: /* @__PURE__ */ jsx(
1360
1360
  Badge,
1361
1361
  {
1362
- color: area.active ? "green" : "grey",
1362
+ color: box.active ? "green" : "grey",
1363
1363
  className: "cursor-pointer",
1364
- onClick: () => handleToggleActive(area),
1365
- children: area.active ? "เปิดใช้งาน" : "ปิดใช้งาน"
1364
+ onClick: () => handleToggleActive(box),
1365
+ children: box.active ? "เปิดใช้งาน" : "ปิดใช้งาน"
1366
1366
  }
1367
1367
  ) }),
1368
1368
  /* @__PURE__ */ jsx(Table.Cell, { className: "text-right", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-end gap-x-2", children: [
@@ -1371,7 +1371,7 @@ const ServiceAreasTable = () => {
1371
1371
  {
1372
1372
  variant: "transparent",
1373
1373
  size: "small",
1374
- onClick: () => handleEdit(area),
1374
+ onClick: () => handleEdit(box),
1375
1375
  children: /* @__PURE__ */ jsx(Edit, {})
1376
1376
  }
1377
1377
  ),
@@ -1380,30 +1380,30 @@ const ServiceAreasTable = () => {
1380
1380
  {
1381
1381
  variant: "transparent",
1382
1382
  size: "small",
1383
- onClick: () => openDeletePrompt(area.id, area.value),
1383
+ onClick: () => openDeletePrompt(box.id, box.name),
1384
1384
  children: /* @__PURE__ */ jsx(Trash, {})
1385
1385
  }
1386
1386
  )
1387
1387
  ] }) })
1388
- ] }, area.id)) })
1388
+ ] }, box.id)) })
1389
1389
  ] })
1390
1390
  ] }),
1391
- isModalOpen && /* @__PURE__ */ jsx(ServiceAreaModal, { area: editingArea, onClose: handleModalClose }),
1391
+ isModalOpen && /* @__PURE__ */ jsx(ParcelBoxModal, { box: editingBox, onClose: handleModalClose }),
1392
1392
  /* @__PURE__ */ jsx(
1393
1393
  Prompt,
1394
1394
  {
1395
1395
  variant: "confirmation",
1396
- open: !!deleteAreaId,
1396
+ open: !!deleteBoxId,
1397
1397
  onOpenChange: () => {
1398
- setDeleteAreaId(null);
1399
- setDeleteAreaValue("");
1398
+ setDeleteBoxId(null);
1399
+ setDeleteBoxName("");
1400
1400
  },
1401
1401
  children: /* @__PURE__ */ jsxs(Prompt.Content, { children: [
1402
1402
  /* @__PURE__ */ jsxs(Prompt.Header, { children: [
1403
- /* @__PURE__ */ jsx(Prompt.Title, { children: "ลบพื้นที่บริการ" }),
1403
+ /* @__PURE__ */ jsx(Prompt.Title, { children: "ลบกล่องพัสดุ" }),
1404
1404
  /* @__PURE__ */ jsxs(Prompt.Description, { children: [
1405
- 'คุณต้องการลบพื้นที่ "',
1406
- deleteAreaValue,
1405
+ 'คุณต้องการลบกล่อง "',
1406
+ deleteBoxName,
1407
1407
  '" ใช่หรือไม่? การดำเนินการนี้ไม่สามารถย้อนกลับได้'
1408
1408
  ] })
1409
1409
  ] }),
@@ -1416,15 +1416,15 @@ const ServiceAreasTable = () => {
1416
1416
  )
1417
1417
  ] });
1418
1418
  };
1419
- const AreasPage = () => {
1419
+ const BoxesPage = () => {
1420
1420
  return /* @__PURE__ */ jsx(Container, { children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-y-4", children: [
1421
- /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsx(Heading, { level: "h1", children: "พื้นที่บริการ" }) }),
1422
- /* @__PURE__ */ jsx(ServiceAreasTable, {})
1421
+ /* @__PURE__ */ jsx("div", { className: "flex items-center justify-between", children: /* @__PURE__ */ jsx(Heading, { level: "h1", children: "กล่องพัสดุ" }) }),
1422
+ /* @__PURE__ */ jsx(ParcelBoxesTable, {})
1423
1423
  ] }) });
1424
1424
  };
1425
1425
  const config$2 = defineRouteConfig({
1426
- icon: MapPin,
1427
- label: "พื้นที่บริการ"
1426
+ icon: ArchiveBox,
1427
+ label: "กล่องพัสดุ"
1428
1428
  });
1429
1429
  const CATEGORIES$1 = [
1430
1430
  { value: "PACKAGING", label: "วัสดุหีบห่อ" },
@@ -2712,6 +2712,10 @@ const widgetModule = { widgets: [
2712
2712
  ] };
2713
2713
  const routeModule = {
2714
2714
  routes: [
2715
+ {
2716
+ Component: AreasPage,
2717
+ path: "/areas"
2718
+ },
2715
2719
  {
2716
2720
  Component: BasePricingPage,
2717
2721
  path: "/base-pricing"
@@ -2720,10 +2724,6 @@ const routeModule = {
2720
2724
  Component: BoxesPage,
2721
2725
  path: "/boxes"
2722
2726
  },
2723
- {
2724
- Component: AreasPage,
2725
- path: "/areas"
2726
- },
2727
2727
  {
2728
2728
  Component: MaterialCostsPage,
2729
2729
  path: "/material-costs"
@@ -2737,24 +2737,24 @@ const routeModule = {
2737
2737
  const menuItemModule = {
2738
2738
  menuItems: [
2739
2739
  {
2740
- label: config$2.label,
2741
- icon: config$2.icon,
2740
+ label: config$4.label,
2741
+ icon: config$4.icon,
2742
2742
  path: "/areas",
2743
2743
  nested: void 0,
2744
2744
  rank: void 0,
2745
2745
  translationNs: void 0
2746
2746
  },
2747
2747
  {
2748
- label: config$4.label,
2749
- icon: config$4.icon,
2748
+ label: config$3.label,
2749
+ icon: config$3.icon,
2750
2750
  path: "/base-pricing",
2751
2751
  nested: void 0,
2752
2752
  rank: void 0,
2753
2753
  translationNs: void 0
2754
2754
  },
2755
2755
  {
2756
- label: config$3.label,
2757
- icon: config$3.icon,
2756
+ label: config$2.label,
2757
+ icon: config$2.icon,
2758
2758
  path: "/boxes",
2759
2759
  nested: void 0,
2760
2760
  rank: void 0,