From 41c6eb42171421b7e96bfedb0b6ac0bef082c52f Mon Sep 17 00:00:00 2001
From: Kritkhanin Anantakul <65160144@go.buu.ac.th>
Date: Tue, 18 Mar 2025 16:42:49 +0700
Subject: [PATCH] all gantt service store / connect fontend backend / fix
 calendar format/ fix some ui

---
 src/components/GanttChart/AddQueueDialog.vue  | 231 +++++++++++-------
 src/components/GanttChart/CalendarPicker.vue  | 131 ++++------
 src/components/GanttChart/GanttCalendar.vue   |  64 ++---
 src/components/GanttChart/GanttChart.vue      | 142 +++++------
 src/components/GanttChart/OrderDialog.vue     |   2 +-
 .../GanttChart/scheduleCalculator.js          |   2 +-
 src/components/OrderItem.vue                  |  75 ------
 src/router/index.ts                           |  16 ++
 src/services/http.ts                          |   2 +-
 src/services/machine.ts                       |  41 ++++
 src/services/order.ts                         |  45 ++++
 src/services/queue.ts                         | 123 +++-------
 src/stores/machine.ts                         |  95 +++++++
 src/stores/order.ts                           | 100 ++++++++
 src/stores/queue.ts                           | 147 +++++++++--
 src/types/Machine.ts                          |  12 +
 src/types/Order.ts                            |  13 +
 src/types/Queue.ts                            |  44 +++-
 src/types/QueueItem.ts                        |  11 -
 src/views/MachineManagementView.vue           | 118 +++++++++
 20 files changed, 916 insertions(+), 498 deletions(-)
 delete mode 100644 src/components/OrderItem.vue
 create mode 100644 src/services/machine.ts
 create mode 100644 src/services/order.ts
 create mode 100644 src/stores/machine.ts
 create mode 100644 src/stores/order.ts
 create mode 100644 src/types/Machine.ts
 create mode 100644 src/types/Order.ts
 delete mode 100644 src/types/QueueItem.ts
 create mode 100644 src/views/MachineManagementView.vue

diff --git a/src/components/GanttChart/AddQueueDialog.vue b/src/components/GanttChart/AddQueueDialog.vue
index 90aba53..766a2ab 100644
--- a/src/components/GanttChart/AddQueueDialog.vue
+++ b/src/components/GanttChart/AddQueueDialog.vue
@@ -4,9 +4,10 @@
       <h3 class="white-text">{{ isEditing ? "Edit Queue" : "Add New Queue" }}</h3>
       <form @submit.prevent="handleSubmit">
         <div class="form-group">
-          <label class="white-text">Machine ID:</label>
-          <select v-model="form.status" class="border-input" required>
-            <option v-for="machine in machines" :key="machine.machineID" :value="machine.machineID">
+          <label class="white-text">Machine Name:</label>
+          <select v-model.number="form.machineID" class="border-input" required>
+            <option value="" disabled>เลือกเครื่องจักร</option>
+            <option v-for="machine in machines" :key="machine.MachineID" :value="machine.MachineID">
               {{ machine.name }}
             </option>
           </select>
@@ -14,29 +15,32 @@
 
         <div class="form-group">
           <label class="white-text">Order ID:</label>
-          <input class="border-input" v-model.number="form.orderID" type="number" required />
+          <select v-model.number="form.orderID" class="border-input" required>
+            <option value="" disabled>เลือกคำสั่งซื้อ</option>
+            <option v-for="order in orders" :key="order.OrderID" :value="order.OrderID">
+              {{ order.OrderID }}
+            </option>
+          </select>
         </div>
 
-        <!-- 🆕 Start Time & Finish Time: ใช้ DateTime Picker -->
         <div class="form-group">
           <label class="white-text">Start Time:</label>
-          <input class="border-input" type="datetime-local" v-model="form.startTime" required />
+          <input v-model="form.startTime" class="border-input" type="datetime-local" required />
         </div>
         <div class="form-group">
           <label class="white-text">Finish Time:</label>
-          <input class="border-input" type="datetime-local" v-model="form.finishTime" required />
+          <input v-model="form.finishTime" class="border-input" type="datetime-local" required />
         </div>
 
-        <!-- 🆕 Status: ใช้ Dropdown -->
         <div class="form-group">
           <label class="white-text">Status:</label>
           <select v-model="form.status" class="border-input" required>
-            <option value="ยังไม่ได้จัดส่ง">ยังไม่ได้จัดส่ง</option>
-            <option value="จัดส่งแล้ว">จัดส่งแล้ว</option>
+            <option value="Pending">Pending</option>
+            <option value="Process">Process</option>
+            <option value="Done">Done</option>
           </select>
         </div>
 
-        <!-- 🆕 Bottle Size: ใช้ Dropdown -->
         <div class="form-group">
           <label class="white-text">Bottle Size:</label>
           <select v-model="form.bottleSize" class="border-input" required>
@@ -48,10 +52,14 @@
 
         <div class="form-group">
           <label class="white-text">Produced Quantity:</label>
-          <input class="border-input" v-model.number="form.producedQuantity" type="number" required />
+          <input v-model.number="form.producedQuantity" class="border-input" type="number" required />
+        </div>
+
+        <div class="form-group">
+          <label class="white-text">Page ID:</label>
+          <input v-model.number="form.pageID" class="border-input" type="number" readonly />
         </div>
 
-        <!-- ปุ่ม Add หรือ Save Changes -->
         <div class="dialog-buttons">
           <button type="submit" class="primary-btn">
             {{ isEditing ? "Save Changes" : "Add" }}
@@ -64,100 +72,139 @@
 </template>
 
 <script setup lang="ts">
-import { reactive, ref, watch } from 'vue'
-
-interface QueueItem {
-  machineID: string
-  orderID: number | null
-  startTime: string
-  finishTime: string
-  status: string
-  bottleSize: string
-  producedQuantity: number | null
-  queueID?: number
-}
+import { reactive, ref, watch, onMounted, computed } from 'vue';
+import { useMachineStore } from '@/stores/machine';
+import { useOrderStore } from '@/stores/order';
+import { useQueueStore } from '@/stores/queue';
+import type { Queue } from '@/types/Queue';
 
-interface Machine {
-  machineID: string
-  name: string
-}
-
-// Props
 const props = defineProps<{
-  visible: boolean
-  queueItem?: QueueItem
-}>()
+  visible: boolean;
+  currentPage: number;
+  queueItem?: Queue;
+}>();
 
-// Emits
 const emit = defineEmits<{
-  (e: 'close'): void
-  (e: 'edit', payload: QueueItem): void
-  (e: 'add', payload: QueueItem): void
-}>()
-
-// Reactive form state
-const form = reactive<QueueItem>({
-  machineID: '',
-  orderID: null,
-  startTime: '',
-  finishTime: '',
-  status: 'ยังไม่ได้จัดส่ง',
-  bottleSize: '600 ml',
-  producedQuantity: null,
-})
-
-// Static machines list
-const machines: Machine[] = [
-  { machineID: 'MC1', name: 'เครื่องเป่าขวด' },
-  { machineID: 'MC2', name: 'เครื่องเป่าขวด2' },
-  { machineID: 'MC3', name: 'เครื่องสวมฉลาก' },
-  { machineID: 'MC4', name: 'เครื่องสวมฉลาก2' },
-  { machineID: 'MC5', name: 'เครื่องบรรจุ+แพ็ค' },
-]
-
-// Track editing mode
-const isEditing = ref(false)
-
-// Functions
-function resetForm() {
-  form.machineID = ''
-  form.orderID = null
-  form.startTime = ''
-  form.finishTime = ''
-  form.status = 'ยังไม่ได้จัดส่ง'
-  form.bottleSize = '600 ml'
-  form.producedQuantity = null
-}
+  (e: 'close'): void;
+}>();
 
-function closeDialog() {
-  console.log("Closing dialog")
-  emit("close")
-  resetForm()
-}
+const machineStore = useMachineStore();
+const orderStore = useOrderStore();
+const queueStore = useQueueStore();
 
-function handleSubmit() {
-  if (isEditing.value) {
-    emit("edit", { ...form })
-  } else {
-    emit("add", { ...form, queueID: Date.now() })
+const machines = computed(() => machineStore.machines);
+const orders = computed(() => orderStore.orders);
+
+onMounted(async () => {
+  await machineStore.fetchMachines();
+  await orderStore.fetchOrders();
+});
+
+const isEditing = ref(false);
+
+const form = reactive({
+  machineID: null as number | null,
+  orderID: null as number | null,
+  startTime: new Date().toISOString().slice(0, 16),
+  finishTime: new Date().toISOString().slice(0, 16),
+  status: "Pending",
+  bottleSize: "600 ml",
+  producedQuantity: null as number | null,
+  pageID: Number(props.currentPage),
+});
+
+// ฟังก์ชันแปลงเวลาให้เข้ากับ datetime-local
+function formatDateTime(dateTime: string | Date): string {
+  if (!dateTime) return "";
+
+  // ถ้า dateTime เป็น Date ให้แปลงเป็น ISO String ก่อน
+  if (dateTime instanceof Date) {
+    return dateTime.toISOString().slice(0, 16);
   }
-  closeDialog()
+
+  return dateTime.replace(" ", "T"); // แปลง "2025-01-01 09:00" เป็น "2025-01-01T09:00"
 }
 
-// Watch for changes on queueItem prop to toggle edit mode
+// โหลดข้อมูล queueItem เมื่อ Edit
 watch(
   () => props.queueItem,
-  (newItem) => {
-    if (newItem) {
-      Object.assign(form, newItem)
-      isEditing.value = true
+  (newQueueItem) => {
+    if (newQueueItem) {
+      console.log("🛠 queueItem received:", newQueueItem);
+
+      isEditing.value = true;
+      form.machineID = newQueueItem.machineID ?? null;
+      form.orderID = newQueueItem.orderID ?? null;
+      form.startTime = formatDateTime(newQueueItem.startTime);
+      form.finishTime = formatDateTime(newQueueItem.finishTime);
+      form.status = newQueueItem.status;
+      form.bottleSize = newQueueItem.bottleSize;
+      form.producedQuantity = newQueueItem.producedQuantity;
+      form.pageID = newQueueItem.pageID ?? Number(props.currentPage);
     } else {
-      resetForm()
-      isEditing.value = false
+      isEditing.value = false;
+      resetForm();
     }
   },
   { immediate: true }
-)
+);
+
+function closeDialog() {
+  console.log("🔴 Closing Dialog... Emitting 'close' event");
+  resetForm();
+  emit("close");
+}
+
+function resetForm() {
+  form.machineID = null;
+  form.orderID = null;
+  form.startTime = new Date().toISOString().slice(0, 16);
+  form.finishTime = new Date().toISOString().slice(0, 16);
+  form.status = "Pending";
+  form.bottleSize = "600 ml";
+  form.producedQuantity = null;
+  form.pageID = Number(props.currentPage);
+  isEditing.value = false;
+}
+
+function handleSubmit() {
+  console.log("🚀 Submitting Form:", form);
+
+  if (!form.machineID || !form.orderID || !form.startTime || !form.finishTime || !form.status || !form.bottleSize || !form.producedQuantity) {
+    console.warn("⚠️ กรุณากรอกข้อมูลให้ครบทุกช่อง!");
+    return;
+  }
+
+  const payload = {
+    MachineID: form.machineID,
+    OrderID: form.orderID,
+    PageID: form.pageID,
+    startTime: new Date(form.startTime).toISOString(),
+    finishTime: new Date(form.finishTime).toISOString(),
+    status: form.status,
+    bottleSize: form.bottleSize,
+    producedQuantity: form.producedQuantity,
+    EmployeeIds: [],
+  };
+
+  if (isEditing.value && props.queueItem) {
+    queueStore
+      .updateQueue(props.queueItem.QueueID, payload)
+      .then(() => {
+        console.log("✅ Queue updated successfully!", payload);
+        closeDialog();
+      })
+      .catch((error) => console.error("❌ Error updating queue:", error));
+  } else {
+    queueStore
+      .addQueue(payload)
+      .then(() => {
+        console.log("✅ Queue added successfully!", payload);
+        closeDialog();
+      })
+      .catch((error) => console.error("❌ Error adding queue:", error));
+  }
+}
 </script>
 
 <style scoped>
diff --git a/src/components/GanttChart/CalendarPicker.vue b/src/components/GanttChart/CalendarPicker.vue
index 17afce4..2f24006 100644
--- a/src/components/GanttChart/CalendarPicker.vue
+++ b/src/components/GanttChart/CalendarPicker.vue
@@ -1,120 +1,93 @@
 <script setup>
-import { ref, computed, watch } from 'vue';
-import { format, parse, parseISO, isValid } from 'date-fns';
+import { ref, computed, watch } from "vue";
+import { format, parse, parseISO, isValid } from "date-fns";
 
 const props = defineProps({
-    modelValue: String, // ค่าที่รับมาจาก GanttCalendar.vue
+  modelValue: String, // ค่าที่รับมาจาก GanttCalendar.vue
 });
 
 const emits = defineEmits(["update:modelValue"]);
 
-// ใช้ ref เก็บค่า selectedDate
-const selectedDate = ref(props.modelValue ? parseDateDMY(props.modelValue) : new Date());
+// ✅ ตรวจสอบและแปลงวันที่ให้เป็น Date Object
+function parseDate(dateString) {
+  if (!dateString) return new Date();
 
-// ฟังก์ชันแปลง `d/M/yyyy` หรือ `yyyy-MM-dd` → `Date`
-function parseDateDMY(dateString) {
-    if (!dateString) return new Date();
+  // ตรวจสอบว่าเป็นรูปแบบ "YYYY-MM-DD"
+  if (dateString.includes("-")) {
+    const parsedDate = parseISO(dateString);
+    if (isValid(parsedDate)) return parsedDate;
+  }
 
-    try {
-        const parts = dateString.includes('-') ? dateString.split('-') : dateString.split('/');
+  // ตรวจสอบว่าเป็นรูปแบบ "d/M/yyyy"
+  if (dateString.includes("/")) {
+    const parsedDate = parse(dateString, "d/M/yyyy", new Date());
+    if (isValid(parsedDate)) return parsedDate;
+  }
 
-        if (parts.length !== 3) throw new Error("Invalid date format");
-
-        const day = parseInt(parts[0], 10);
-        const month = parseInt(parts[1], 10) - 1; // `month` ใน JavaScript เริ่มที่ 0
-        const year = parseInt(parts[2], 10);
-
-        // ถ้าปีเป็นสองหลัก ให้บวก 2000 เข้าไป
-        const fullYear = year < 100 ? year + 2000 : year;
-
-        const parsedDate = new Date(fullYear, month, day);
-
-        if (!isValid(parsedDate)) throw new Error("Invalid parsed date");
-
-        return parsedDate;
-    } catch (error) {
-        console.error("📅 parseDateDMY ERROR:", error, "ค่าที่รับมา:", dateString);
-        return new Date();
-    }
+  return new Date(); // ถ้ารูปแบบไม่ถูกต้อง ให้ใช้วันที่ปัจจุบันแทน
 }
 
-// ฟังก์ชันแปลง `Date` → `d/M/yyyy`
-const formattedDate = computed(() => {
-    if (!selectedDate.value) return null;
-    const date = new Date(selectedDate.value);
-    return format(date, 'd/M/yyyy');
-});
+// ✅ ใช้ ref เก็บค่า selectedDate และแปลงจาก modelValue
+const selectedDate = ref(parseDate(props.modelValue));
 
-// watch `formattedDate` แล้ว emit กลับไปที่ `GanttCalendar.vue`
-watch(formattedDate, (newValue) => {
-    if (newValue !== null) {
-        console.log("📅 CalendarPicker - ส่งค่ากลับไปเป็น:", newValue);
-        emits("update:modelValue", newValue);
-    }
+// ✅ แปลง `Date` → `YYYY-MM-DD`
+const formattedDate = computed(() => format(selectedDate.value, "yyyy-MM-dd"));
+
+// ✅ เมื่อ `formattedDate` เปลี่ยน ให้ emit ค่าออกไปที่ `GanttCalendar.vue`
+watch(formattedDate, (newVal) => {
+  console.log("📅 CalendarPicker - ส่งค่ากลับเป็น:", newVal);
+  emits("update:modelValue", newVal);
 });
 
-// ฟังก์ชันอัปเดตวันที่จาก `v-date-picker`
+// ✅ ฟังก์ชันอัปเดตวันที่จาก `v-date-picker`
 const updateSelectedDate = (newValue) => {
-    selectedDate.value = newValue;
-};
-
-// ฟังก์ชันสลับเปิด-ปิด Date Picker
-const showDatePicker = ref(false);
-const toggleDatePicker = () => {
-    showDatePicker.value = !showDatePicker.value;
+  selectedDate.value = newValue;
 };
-
 </script>
 
-
-
 <template>
-    <v-container>
-        <v-row justify="center">
-            <v-date-picker v-model="selectedDate" color="#96A9DB" class="custom-date-picker"
-                @update:modelValue="updateSelectedDate">
-            </v-date-picker>
-        </v-row>
-    </v-container>
+  <v-container>
+    <v-row justify="center">
+      <v-date-picker
+        v-model="selectedDate"
+        color="#96A9DB"
+        class="custom-date-picker"
+        @update:modelValue="updateSelectedDate"
+      ></v-date-picker>
+    </v-row>
+  </v-container>
 </template>
 
 <style scoped>
 /* ✅ ปรับขนาด v-date-picker */
 .custom-date-picker {
-    width: 350px !important;
-    /* ✅ ลดความกว้าง */
-    height: 390px !important;
-    max-width: 350px;
-    font-size: 14px !important;
-    /* ✅ ลดขนาดตัวอักษร */
-    border-radius: 20px !important;
-    /* ✅ ทำให้ขอบโค้งมน */
+  width: 350px !important;
+  height: 390px !important;
+  max-width: 350px;
+  font-size: 14px !important;
+  border-radius: 20px !important;
 }
 
-/* ✅ ลดขนาดของตัวอักษรวันที่ (Mon, Jan 1) */
+/* ✅ ลดขนาดของตัวอักษรวันที่ */
 :deep(.v-date-picker-title) {
-    font-size: 14px !important;
+  font-size: 14px !important;
 }
 
 /* ✅ ปรับขนาดปุ่มวันที่ */
 :deep(.v-date-picker .v-btn) {
-    min-width: 32px !important;
-    /* ✅ ลดความกว้างของปุ่ม */
-    height: 32px !important;
-    /* ✅ ลดความสูงของปุ่ม */
-    font-size: 15px !important;
-    /* ✅ ลดขนาดตัวเลขในปฏิทิน */
-    border-radius: 60px !important;
-    /* ✅ ทำให้ปุ่มโค้งมน */
+  min-width: 32px !important;
+  height: 32px !important;
+  font-size: 15px !important;
+  border-radius: 60px !important;
 }
 
 /* ✅ ปรับขนาดชื่อเดือน-ปี */
 :deep(.v-date-picker-header) {
-    font-size: 16px !important;
+  font-size: 16px !important;
 }
 
-/* ✅ ปรับขนาดตัวอักษรชื่อวันในสัปดาห์ (S, M, T, W, T, F, S) */
+/* ✅ ปรับขนาดตัวอักษรชื่อวัน */
 :deep(.v-date-picker .v-date-picker-weekdays) {
-    font-size: 12px !important;
+  font-size: 12px !important;
 }
 </style>
diff --git a/src/components/GanttChart/GanttCalendar.vue b/src/components/GanttChart/GanttCalendar.vue
index b3ad73a..9fb888e 100644
--- a/src/components/GanttChart/GanttCalendar.vue
+++ b/src/components/GanttChart/GanttCalendar.vue
@@ -1,76 +1,81 @@
 <script setup>
-import { ref, watch } from 'vue';
-import { format, parse } from 'date-fns';
+import { ref, watch } from "vue";
+import { format, parse } from "date-fns";
 import CalendarPicker from "@/components/GanttChart/CalendarPicker.vue";
 
 const props = defineProps({
   modelValue: {
     type: String,
-    default: '1/1/2025', // เปลี่ยนเป็น format `d/M/yyyy`
+    default: "2025-01-01", // ✅ ใช้ "YYYY-MM-DD" เป็นค่าเริ่มต้น
   },
 });
 
-const emits = defineEmits(['update:modelValue']);
+const emits = defineEmits(["update:modelValue"]);
 const selectedDate = ref(props.modelValue);
 const showCalendar = ref(false);
 
-// ✅ ฟังก์ชันแปลง `d/M/yyyy` → `YYYY-MM-DD`
+// ✅ แปลงวันที่จาก "YYYY-MM-DD" เป็น `Date Object`
 const parseDate = (dateStr) => {
-  return format(parse(dateStr, "d/M/yyyy", new Date()), "yyyy-MM-dd");
+  return parse(dateStr, "yyyy-MM-dd", new Date());
 };
 
-
-
 // ✅ ฟังก์ชันเพิ่ม/ลดวัน และอัปเดต `selectedDate`
 const changeDate = (days) => {
-  const currentDate = parse(selectedDate.value, "d/M/yyyy", new Date());
+  const currentDate = parseDate(selectedDate.value);
   const newDate = new Date(currentDate);
   newDate.setDate(currentDate.getDate() + days);
-  selectedDate.value = format(newDate, 'd/M/yyyy');
+  selectedDate.value = format(newDate, "yyyy-MM-dd"); // ✅ ใช้ "YYYY-MM-DD"
 };
 
-
 // ✅ เมื่อ `selectedDate` เปลี่ยน ให้ emit ค่าออกไป
 watch(selectedDate, (newVal) => {
   console.log("📅 GanttCalendar - วันที่เปลี่ยน:", newVal);
-  emits('update:modelValue', newVal);
+  emits("update:modelValue", newVal);
 });
 
-// เมื่อเปิดปฏิทิน ให้ `selectedDate` ซิงค์กับ `v-date-picker`
-
-
-// ฟังก์ชันเปิดปฏิทิน
+// ✅ ฟังก์ชันเปิดปฏิทิน
 const openCalendar = () => {
   showCalendar.value = true;
   console.log("📅 ปุ่ม ... ถูกกด!");
 };
 
-// เมื่อเลือกวันที่ใน CalendarPicker จะปิด dialog
+// ✅ ปิดปฏิทินเมื่อเลือกวันที่
 const closeCalendarDialog = () => {
   showCalendar.value = false;
 };
-
-
 </script>
 
 <template>
   <v-container>
-    <v-col cols="auto" class="d-inline-flex align-center"
-      style="background-color: #7E9CD3; border-radius: 15px; max-width: fit-content; padding: 8px 16px;">
-
-      <v-btn class="mr-2" style="background-color: #2B2E3F; color: white; border-radius: 10px;" @click="changeDate(-1)">
+    <v-col
+      cols="auto"
+      class="d-inline-flex align-center"
+      style="background-color: #7e9cd3; border-radius: 15px; max-width: fit-content; padding: 8px 16px"
+    >
+      <v-btn
+        class="mr-2"
+        style="background-color: #2b2e3f; color: white; border-radius: 10px"
+        @click="changeDate(-1)"
+      >
         &lt; Back
       </v-btn>
 
-      <v-btn style="background-color: white; color: black; min-width: 200px; border-radius: 15px;">
+      <!-- ✅ ใช้ format YYYY-MM-DD -->
+      <v-btn
+        style="background-color: white; color: black; min-width: 200px; border-radius: 15px"
+      >
         {{ selectedDate }}
       </v-btn>
 
-      <v-btn class="ml-2" style="background-color: #2B2E3F; color: white; border-radius: 10px;" @click="changeDate(1)">
+      <v-btn
+        class="ml-2"
+        style="background-color: #2b2e3f; color: white; border-radius: 10px"
+        @click="changeDate(1)"
+      >
         Next &gt;
       </v-btn>
 
-      <!-- ✅ เปลี่ยนจาก v-dialog เป็น v-menu (Popover) -->
+      <!-- ✅ ใช้ v-menu (Popover) แทน v-dialog -->
       <v-menu v-model="showCalendar" :close-on-content-click="false" location="bottom">
         <template v-slot:activator="{ props }">
           <v-btn v-bind="props" class="ml-2 popover-btn">
@@ -78,29 +83,24 @@ const closeCalendarDialog = () => {
           </v-btn>
         </template>
 
-        <!-- ✅ ปรับขนาด Popover และใช้ CalendarPicker -->
+        <!-- ✅ ใช้ CalendarPicker ที่รองรับ YYYY-MM-DD -->
         <v-card class="pb-12 popover-card">
           <CalendarPicker v-model="selectedDate" @update:modelValue="closeCalendarDialog" />
         </v-card>
       </v-menu>
-
     </v-col>
   </v-container>
 </template>
 
 <style scoped>
-/* ✅ ปรับแต่งปุ่ม "..." */
 .popover-btn {
   background-color: white;
   color: black;
   border-radius: 10px;
 }
 
-/* ✅ ปรับแต่งขนาดและขอบโค้งของ Popover */
 .popover-card {
   border-radius: 25px !important;
-  /* ✅ กำหนดขอบโค้ง */
-
   box-shadow: 0px 4px 10px rgba(0, 0, 0, 0.2);
   background-color: white;
 }
diff --git a/src/components/GanttChart/GanttChart.vue b/src/components/GanttChart/GanttChart.vue
index a732f38..47c20fa 100644
--- a/src/components/GanttChart/GanttChart.vue
+++ b/src/components/GanttChart/GanttChart.vue
@@ -1,6 +1,5 @@
 <template>
   <div class="gantt-container">
-    <h2 class="gantt-title">ตารางคิวการผลิต</h2>
     <div class="gantt-header">
       <!-- Calendar: เชื่อมกับ selectedDate -->
       <GanttCalendar v-model:modelValue="selectedDate" />
@@ -22,44 +21,24 @@
 
       <!-- Rows: แสดงเครื่องจักรจาก Machine Store -->
       <div class="rows">
-        <div
-          v-for="machine in machineStore.machines"
-          :key="machine.MachineID"
-          class="row"
-          :data-machine-id="machine.MachineID"
-          @dragover.prevent="onDragOver($event)"
-          @drop="onDrop($event, machine.MachineID)"
-        >
+        <div v-for="machine in machineStore.machines" :key="machine.MachineID" class="row"
+          :data-machine-id="machine.MachineID" @dragover.prevent="onDragOver($event)"
+          @drop="onDrop($event, machine.MachineID)">
           <div class="machine-label">
             {{ machine.name }}
           </div>
           <div class="row-timeline">
             <!-- เส้นแนวตั้ง (Grid Lines) -->
-            <div
-              v-for="hour in hours"
-              :key="'line-' + hour"
-              class="vertical-line"
-              :style="getLineStyle(hour)"
-            ></div>
+            <div v-for="hour in hours" :key="'line-' + hour" class="vertical-line" :style="getLineStyle(hour)"></div>
 
             <!-- แสดง Queue ที่ตรงกับวันที่ (selectedDate), Page, และ Machine -->
-            <div
-              v-for="item in filteredQueue(machine.MachineID)"
-              :key="item.QueueID"
-              class="order"
-              :class="{ faded: draggingQueue && draggingQueue.QueueID === item.QueueID }"
-              :style="getQueueStyle(item)"
-            >
+            <div v-for="item in filteredQueue(machine.MachineID)" :key="item.QueueID" class="order"
+              :class="{ faded: draggingQueue && draggingQueue.QueueID === item.QueueID }" :style="getQueueStyle(item)">
               <!-- Handle สำหรับ Resize ด้านซ้าย -->
               <div class="resize-handle left" @mousedown="onResizeStart($event, item, 'left')"></div>
               <!-- ส่วนกลางของ Order ใช้สำหรับลาก และเปิด Dialog เมื่อคลิก -->
-              <div
-                class="order-content"
-                draggable="true"
-                @dragstart="onDragStart($event, item)"
-                @dragend="onDragEnd($event, item)"
-                @click.stop="openQueueDialog(item)"
-              >
+              <div class="order-content" draggable="true" @dragstart="onDragStart($event, item)"
+                @dragend="onDragEnd($event, item)" @click.stop="openQueueDialog(item)">
                 {{ item.orderID }} ({{ getTimeString(item.startTime) }} - {{ getTimeString(item.finishTime) }})
               </div>
               <!-- Handle สำหรับ Resize ด้านขวา -->
@@ -71,7 +50,8 @@
 
       <!-- Ghost Queue (ขณะลาก/resize) -->
       <div v-if="ghostQueue" class="drag-ghost" :style="ghostStyle">
-        {{ ghostQueue.orderID }} ({{ getTimeString(ghostQueue.startTime) }} - {{ getTimeString(ghostQueue.finishTime) }})
+        {{ ghostQueue.orderID }} ({{ getTimeString(ghostQueue.startTime) }} - {{ getTimeString(ghostQueue.finishTime)
+        }})
       </div>
 
       <v-divider :thickness="7"></v-divider>
@@ -79,13 +59,8 @@
       <!-- Pagination -->
       <div class="pagination-container">
         <div class="pagination">
-          <button
-            v-for="p in pages"
-            :key="p"
-            :class="['page-btn', { active: p === currentPage }]"
-            @click="currentPage = p"
-            @contextmenu.prevent="onPageRightClick(p, $event)"
-          >
+          <button v-for="p in pages" :key="p" :class="['page-btn', { active: p === currentPage }]"
+            @click="currentPage = p" @contextmenu.prevent="onPageRightClick(p, $event)">
             {{ p }}
             <button v-if="pageToShowDelete === p" class="delete-btn" @click.stop="deletePage(p)">
               Delete
@@ -100,22 +75,12 @@
             <v-icon>mdi-plus</v-icon>
           </v-btn>
         </div>
-        <AddQueueDialog
-          :visible="showAddDialog"
-          :queueItem="selectedQueueItem"
-          @close="closeAddQueueDialog"
-          @add="handleAddQueue"
-          @edit="handleEditQueue"
-        />
+        <AddQueueDialog :visible="showAddDialog" :queueItem="selectedQueueItem" :currentPage="currentPage"
+          @close="closeAddQueueDialog" />
       </div>
-      <OrderDialog
-        v-if="selectedQueueItem && !showAddDialog"
-        :queueItem="selectedQueueItem"
-        :color="getQueueColor(selectedQueueItem.orderID)"
-        @close="closeQueueDialog"
-        @edit="openAddQueueDialogForEdit"
-        @delete="deleteQueueItem"
-      />
+      <OrderDialog v-if="selectedQueueItem && !showAddDialog" :queueItem="selectedQueueItem"
+        :color="getQueueColor(selectedQueueItem.orderID)" @close="closeQueueDialog" @edit="openAddQueueDialogForEdit"
+        @delete="handleDelete" />
     </div>
   </div>
 </template>
@@ -223,28 +188,30 @@ function openAddQueueDialog() {
   selectedQueueItem.value = null;
   showAddDialog.value = true;
 }
-function deleteQueueItem(item: any) {
-  queueStore.removeQueue(item.QueueID);
-  closeQueueDialog();
-}
+
 function openAddQueueDialogForEdit(queueItem: any) {
   selectedQueueItem.value = { ...queueItem };
   showAddDialog.value = true;
 }
-function closeAddQueueDialog() {
-  showAddDialog.value = false;
-  selectedQueueItem.value = null;
+
+function handleDelete(queueItem: { QueueID: number; }) {
+  if (!queueItem) return;
+
+  queueStore
+    .deleteQueue(queueItem.QueueID)
+    .then(() => {
+      console.log(`✅ Queue ID ${queueItem.QueueID} ถูกลบสำเร็จ`);
+      closeAddQueueDialog();
+    })
+    .catch((error) => console.error(`❌ Error deleting queue:`, error));
 }
-async function handleAddQueue(newQueueItem: any) {
-  await queueStore.addQueue(newQueueItem);
+
+function closeAddQueueDialog() {
   showAddDialog.value = false;
-}
-async function handleEditQueue(updatedQueueItem: any) {
-  await queueStore.editQueue(updatedQueueItem.QueueID, updatedQueueItem);
   selectedQueueItem.value = null;
-  showAddDialog.value = false;
 }
 
+
 function formatHour(hour: number): string {
   return (hour < 10 ? '0' + hour : hour) + ':00';
 }
@@ -396,13 +363,14 @@ function onDragOverGlobal(event: DragEvent) {
 
   if (closestRow) {
     // ใช้ dataset เพื่อดึง machine id
-    const machineIDString = closestRow.dataset.machineId;
+    const machineIDString = (closestRow as HTMLElement).dataset.machineId;
     if (machineIDString) {
-      ghostQueue.value.machine = { MachineID: parseInt(machineIDString, 10) };
+      ghostQueue.value.machineID = parseInt(machineIDString, 10);
     }
-    ghostStyle.top = closestRow.getBoundingClientRect().top + 'px';
+    ghostStyle.top = (closestRow as HTMLElement).getBoundingClientRect().top + 'px';
   }
 
+
   ghostStyle.left = snappedLeft + 'px';
   ghostStyle.width = snappedWidth + 'px';
 }
@@ -431,22 +399,35 @@ async function onDragEnd(event: DragEvent, item: any) {
 }
 async function onDrop(event: DragEvent, newMachineID: number) {
   event.preventDefault();
-  if (draggingQueue.value && ghostQueue.value) {
-    draggingQueue.value.startTime = ghostQueue.value.startTime;
-    draggingQueue.value.finishTime = ghostQueue.value.finishTime;
-    draggingQueue.value.machine = { MachineID: newMachineID };
+
+  if (!draggingQueue.value || !ghostQueue.value) return;
+
+  console.log(`🔄 Dropped Queue ${draggingQueue.value.QueueID} to Machine ${newMachineID}`);
+
+  draggingQueue.value.startTime = ghostQueue.value.startTime;
+  draggingQueue.value.finishTime = ghostQueue.value.finishTime;
+  draggingQueue.value.machineID = newMachineID; // ✅ อัปเดต MachineID
+
+  try {
     await queueStore.updateQueue(draggingQueue.value.QueueID, {
       startTime: draggingQueue.value.startTime,
       finishTime: draggingQueue.value.finishTime,
-      machine: { MachineID: newMachineID, name: '' }
+      MachineID: newMachineID, // ✅ ส่งค่าไป Backend
     });
+
+    console.log(`✅ Queue ${draggingQueue.value.QueueID} updated to Machine ${newMachineID}`);
+  } catch (error) {
+    console.error(`❌ Error updating queue:`, error);
   }
+
   ghostQueue.value = null;
   ghostStyle.display = 'none';
   draggingQueue.value = null;
 }
+
 function onResizeStart(event: MouseEvent, item: any, direction: string) {
   event.preventDefault();
+  ghostQueue.value = { ...item };
   resizingQueue.value = item;
   resizeDirection.value = direction;
   document.addEventListener('mousemove', onResizing);
@@ -471,23 +452,12 @@ function onResizing(event: MouseEvent) {
   if (resizeDirection.value === 'left') {
     if (newTimeDecimal >= endDec) return;
     const newStartStr = datePart + ' ' + decimalToTime(newTimeDecimal);
-    // อัปเดต ghostQueue ให้แสดงผลแบบ real-time
     ghostQueue.value.startTime = newStartStr;
   } else if (resizeDirection.value === 'right') {
     if (newTimeDecimal <= startDec) return;
     const newEndStr = datePart + ' ' + decimalToTime(newTimeDecimal);
     ghostQueue.value.finishTime = newEndStr;
   }
-  // อัปเดต ghostStyle ตาม ghostQueue ใหม่
-  const start = getTimeString(ghostQueue.value.startTime);
-  const end = getTimeString(ghostQueue.value.finishTime);
-  const startDecimal = timeToDecimal(start);
-  const endDecimal = timeToDecimal(end);
-  const totalHours = hours.value.length;
-  const leftPercent = ((startDecimal - timeToDecimal(startTime.value)) / totalHours) * 100;
-  const widthPercent = ((endDecimal - startDecimal) / totalHours) * 100;
-  ghostStyle.left = `${leftPercent}%`;
-  ghostStyle.width = `${widthPercent}%`;
 }
 async function onResizeEnd() {
   if (!resizingQueue.value) return;
@@ -538,4 +508,8 @@ onMounted(() => {
 onBeforeUnmount(() => {
   document.removeEventListener('click', onDocumentClick);
 });
+
+function closeDialog() {
+  throw new Error('Function not implemented.');
+}
 </script>
diff --git a/src/components/GanttChart/OrderDialog.vue b/src/components/GanttChart/OrderDialog.vue
index 39e0fdd..8f2dacf 100644
--- a/src/components/GanttChart/OrderDialog.vue
+++ b/src/components/GanttChart/OrderDialog.vue
@@ -2,7 +2,7 @@
     <div class="order-dialog-overlay">
         <div class="order-dialog" :style="{ backgroundColor: color }">
             <div class="dialog-header">
-                <h3 class="order-title">QueueID: {{ queueItem.queueID }}</h3>
+                <h3 class="order-title">QueueID: {{ queueItem.QueueID }}</h3>
                 <div class="dialog-buttons">
                     <button @click="$emit('edit', queueItem)" class="icon-button">
                         <span class="mdi mdi-pencil"></span>
diff --git a/src/components/GanttChart/scheduleCalculator.js b/src/components/GanttChart/scheduleCalculator.js
index 4adf107..74f0a3f 100644
--- a/src/components/GanttChart/scheduleCalculator.js
+++ b/src/components/GanttChart/scheduleCalculator.js
@@ -286,7 +286,7 @@ function roundDownToHalfHour(dt) {
     for (const machineKey of Object.keys(schedule)) {
       for (const task of schedule[machineKey]) {
         queueItems.push({
-          queueID: idCounter++,
+          QueueID: idCounter++,
           machineID: machineKey,
           orderID: task.orderID,
           pageNumber: 1,
diff --git a/src/components/OrderItem.vue b/src/components/OrderItem.vue
deleted file mode 100644
index 763e0fa..0000000
--- a/src/components/OrderItem.vue
+++ /dev/null
@@ -1,75 +0,0 @@
-<template>
-  <div class="order" :style="getOrderStyle(order)">
-    <div class="resize-handle left" @mousedown="$emit('resize-start', order, 'left')"></div>
-    <div class="order-content" draggable="true" @dragstart="$emit('drag-start', order)" @dragend="$emit('drag-end', order)">
-      {{ order.name }} ({{ order.start }} - {{ order.end }})
-    </div>
-    <div class="resize-handle right" @mousedown="$emit('resize-start', order, 'right')"></div>
-  </div>
-</template>
-
-<script>
-export default {
-  props: {
-    order: Object,
-    startTime: String,
-    endTime: String
-  },
-  methods: {
-    timeToDecimal(timeStr) {
-      const [hours, minutes] = timeStr.split(':').map(Number);
-      return hours + minutes / 60;
-    },
-    getOrderStyle(order) {
-      const startDecimal = this.timeToDecimal(order.start);
-      const endDecimal = this.timeToDecimal(order.end);
-      const timelineStart = this.timeToDecimal(this.startTime);
-      const timelineEnd = this.timeToDecimal(this.endTime);
-      const ratioStart = (startDecimal - timelineStart) / (timelineEnd - timelineStart);
-      const ratioEnd = (endDecimal - timelineStart) / (timelineEnd - timelineStart);
-      return {
-        left: ratioStart * 100 + '%',
-        width: (ratioEnd - ratioStart) * 100 + '%',
-        backgroundColor: order.color || '#4caf50'
-      };
-    }
-  }
-};
-</script>
-
-<style scoped>
-.order {
-  position: absolute;
-  top: 10px;
-  height: 40px;
-  color: #fff;
-  border-radius: 20px;
-  user-select: none;
-  display: flex;
-  align-items: center;
-  z-index: 1;
-}
-
-.order-content {
-  flex: 1;
-  text-align: center;
-  line-height: 40px;
-  cursor: grab;
-  padding: 0 10px;
-}
-
-.resize-handle {
-  width: 5px;
-  height: 100%;
-  cursor: ew-resize;
-  position: absolute;
-}
-
-.resize-handle.left {
-  left: 0;
-}
-
-.resize-handle.right {
-  right: 0;
-}
-</style>
diff --git a/src/router/index.ts b/src/router/index.ts
index 5c0889f..769a12e 100644
--- a/src/router/index.ts
+++ b/src/router/index.ts
@@ -46,6 +46,22 @@ const router = createRouter({
         requireAuth: true
       }
     },
+    {
+      path: '/manage-machines',
+      name: 'manage-machines',
+      // route level code-splitting
+      // this generates a separate chunk (About.[hash].js) for this route
+      // which is lazy-loaded when the route is visited.
+      components: {
+        default: () => import('../views/MachineManagementView.vue'),
+        menu: () => import('../components/Navbar/MainMenu.vue'),
+        header: () => import('../components/Navbar/MainAppBar.vue')
+      },
+      meta: {
+        layout: 'MainLayout',
+        requireAuth: true
+      }
+    },
     {
       path: '/login',
       name: 'login',
diff --git a/src/services/http.ts b/src/services/http.ts
index b4023a3..6997076 100644
--- a/src/services/http.ts
+++ b/src/services/http.ts
@@ -31,7 +31,7 @@ instance.interceptors.response.use(
   async function (res) {
     console.log('response interceptor')
 
-    await delay(1)
+    await delay(0.1)
     return res
   },
   function (error) {
diff --git a/src/services/machine.ts b/src/services/machine.ts
new file mode 100644
index 0000000..a4fa58a
--- /dev/null
+++ b/src/services/machine.ts
@@ -0,0 +1,41 @@
+import http from './http';
+import type { Machine } from '@/types/Machine';
+
+/**
+ * ดึงรายการ Machine ทั้งหมดจาก backend
+ */
+export async function listMachines(): Promise<Machine[]> {
+  const { data } = await http.get('/machines');
+  return data;
+}
+
+/**
+ * ดึงข้อมูล Machine รายการเดียวโดยใช้ MachineID
+ */
+export async function getMachine(id: number): Promise<Machine> {
+  const { data } = await http.get(`/machines/${id}`);
+  return data;
+}
+
+/**
+ * สร้าง Machine ใหม่
+ */
+export async function createMachine(payload: Partial<Machine>): Promise<Machine> {
+  const { data } = await http.post('/machines', payload);
+  return data;
+}
+
+/**
+ * อัปเดต Machine ตาม MachineID
+ */
+export async function updateMachine(id: number, payload: Partial<Machine>): Promise<Machine> {
+  const { data } = await http.put(`/machines/${id}`, payload);
+  return data;
+}
+
+/**
+ * ลบ Machine ตาม MachineID
+ */
+export async function deleteMachine(id: number): Promise<void> {
+  await http.delete(`/machines/${id}`);
+}
diff --git a/src/services/order.ts b/src/services/order.ts
new file mode 100644
index 0000000..452eb65
--- /dev/null
+++ b/src/services/order.ts
@@ -0,0 +1,45 @@
+// /src/services/order.service.ts
+
+import http from './http';
+import type { Order } from '@/types/Order';
+
+/**
+ * ดึงรายการ Order ทั้งหมดจาก backend
+ */
+export async function listOrders(): Promise<Order[]> {
+  const { data } = await http.get('/orders');
+  console.log("API Response for Orders:", data); // เช็คข้อมูลที่ได้จาก API
+  return data;
+}
+
+
+/**
+ * ดึงข้อมูล Order รายการเดียวโดยใช้ OrderID
+ */
+export async function getOrder(id: number): Promise<Order> {
+  const { data } = await http.get(`/orders/${id}`);
+  return data;
+}
+
+/**
+ * สร้าง Order ใหม่
+ */
+export async function createOrder(payload: Partial<Order>): Promise<Order> {
+  const { data } = await http.post('/orders', payload);
+  return data;
+}
+
+/**
+ * อัปเดต Order ตาม OrderID
+ */
+export async function updateOrder(id: number, payload: Partial<Order>): Promise<Order> {
+  const { data } = await http.put(`/orders/${id}`, payload);
+  return data;
+}
+
+/**
+ * ลบ Order ตาม OrderID
+ */
+export async function deleteOrder(id: number): Promise<void> {
+  await http.delete(`/orders/${id}`);
+}
diff --git a/src/services/queue.ts b/src/services/queue.ts
index 710d5ca..28cdd75 100644
--- a/src/services/queue.ts
+++ b/src/services/queue.ts
@@ -1,92 +1,41 @@
-import axios from 'axios';
-import type { QueueItem } from '@/types/QueueItem';
-
-const makeQueue = async (): Promise<QueueItem[] | undefined> => {
-  try {
-    // เรียก API
-    const response = await axios.post('http://127.0.0.1:9000/run-simulation');
-    console.log('📌 Response:', response);
-
-    const queueData = response.data.production_log;
-    console.log('this is queueData queueservice', queueData);
-
-    if (!Array.isArray(queueData)) {
-      console.error('❌ Error: Invalid queue data format');
-      return undefined;
-    }
-
-    // ✅ แปลงข้อมูลเป็น JSON String แล้ว Parse กลับมาเป็น Object ใหม่
-    const queueItems: QueueItem[] = JSON.parse(
-      JSON.stringify(queueData.map(q => ({
-        queueID: q.queueID,
-        machineID: q.machineID,
-        orderID: q.orderID,
-        pageNumber: q.pageNumber ?? 1, // ถ้าไม่มี ให้ใช้ค่า default เป็น 1
-        startTime: q.startTime,
-        finishTime: q.finishTime,
-        status: q.status,
-        bottleSize: q.bottleSize,
-        producedQuantity: q.producedQuantity,
-      })))
-    );
-
-    return queueItems; // ✅ คืนค่าเป็น `QueueItem[]`
-  } catch (error: any) {
-    console.error('❌ Error:', error.message || error);
-    return undefined;
-  }
-};
-
-export default { makeQueue };
-
-
-
-export class QueueService {
-  private queue: Queue[] = [];
-
-  // ดึงรายการคิวทั้งหมด
-  getQueue(): Queue[] {
-    return this.queue;
-  }
-
-  // ค้นหารายการคิวโดยใช้ queueID
-  getQueueById(queueID: number): Queue | undefined {
-    return this.queue.find(item => item.queueID === queueID);
-  }
-
-  // เพิ่มรายการใหม่เข้า queue
-  addQueueItem(item: Queue): void {
-    this.queue.push(item);
-  }
-
-  // อัปเดตรายการ queue ที่มีอยู่
-  updateQueueItem(updatedItem: Queue): void {
-    const index = this.queue.findIndex(item => item.queueID === updatedItem.queueID);
-    if (index !== -1) {
-      this.queue[index] = updatedItem;
-    }
-  }
+import http from './http';
+import type { Queue, QueuePostData } from '@/types/Queue';
+
+/**
+ * ดึงรายการ Queue ทั้งหมดจาก backend
+ */
+export async function listQueues(): Promise<Queue[]> {
+  const { data } = await http.get('/queues');
+  return data;
+}
 
-  // ลบรายการ queue ตาม queueID
-  removeQueueItem(queueID: number): void {
-    this.queue = this.queue.filter(item => item.queueID !== queueID);
-  }
+/**
+ * ดึงข้อมูล Queue รายการเดียวโดยใช้ QueueID
+ */
+export async function getQueue(id: number): Promise<Queue> {
+  const { data } = await http.get(`/queues/${id}`);
+  return data;
+}
 
-  // เปลี่ยนสถานะของคิว
-  updateQueueStatus(queueID: number, status: 'pending' | 'in-progress' | 'completed' | 'canceled'): void {
-    const queueItem = this.getQueueById(queueID);
-    if (queueItem) {
-      queueItem.status = status;
-    }
-  }
+/**
+ * สร้าง Queue ใหม่ (ใช้ QueuePostData เพื่อให้โครงสร้างถูกต้อง)
+ */
+export async function createQueue(payload: QueuePostData): Promise<Queue> {
+  const { data } = await http.post('/queues', payload);
+  return data;
+}
 
-  // คำนวณเวลาการทำงานของ queue
-  calculateProductionTime(queueID: number): number | null {
-    const queueItem = this.getQueueById(queueID);
-    if (queueItem && queueItem.startTime && queueItem.finishTime) {
-      return (queueItem.finishTime.getTime() - queueItem.startTime.getTime()) / (1000 * 60); // แปลงเป็นนาที
-    }
-    return null;
-  }
+/**
+ * อัปเดต Queue ตาม QueueID (ใช้ QueuePostData)
+ */
+export async function updateQueue(id: number, payload: QueuePostData): Promise<Queue> {
+  const { data } = await http.patch(`/queues/${id}`, payload);
+  return data;
+}
 
+/**
+ * ลบ Queue ตาม QueueID
+ */
+export async function deleteQueue(id: number): Promise<void> {
+  await http.delete(`/queues/${id}`);
 }
diff --git a/src/stores/machine.ts b/src/stores/machine.ts
new file mode 100644
index 0000000..ce98548
--- /dev/null
+++ b/src/stores/machine.ts
@@ -0,0 +1,95 @@
+// /src/stores/machine.store.ts
+
+import { defineStore } from 'pinia';
+import { ref } from 'vue';
+import type { Machine } from '@/types/Machine';
+import * as machineService from '@/services/machine';
+
+export const useMachineStore = defineStore('machine', () => {
+  const machines = ref<Machine[]>([]);
+  const loading = ref<boolean>(false);
+  const error = ref<string | null>(null);
+
+  // ดึงรายการ Machine ทั้งหมดจาก backend
+  async function fetchMachines() {
+    loading.value = true;
+    error.value = null;
+    try {
+      machines.value = await machineService.listMachines();
+    } catch (e: any) {
+      error.value = e.message || 'Unknown Error';
+    } finally {
+      loading.value = false;
+    }
+  }
+
+  // ดึงข้อมูล Machine รายการเดียวโดยใช้ MachineID
+  async function fetchMachine(id: number): Promise<Machine | null> {
+    loading.value = true;
+    error.value = null;
+    try {
+      return await machineService.getMachine(id);
+    } catch (e: any) {
+      error.value = e.message || 'Unknown Error';
+      return null;
+    } finally {
+      loading.value = false;
+    }
+  }
+
+  // สร้าง Machine ใหม่แล้วเพิ่มเข้า state
+  async function addMachine(payload: Partial<Machine>) {
+    loading.value = true;
+    error.value = null;
+    try {
+      const newMachine = await machineService.createMachine(payload);
+      machines.value.push(newMachine);
+    } catch (e: any) {
+      error.value = e.message || 'Unknown Error';
+    } finally {
+      loading.value = false;
+    }
+  }
+
+  // อัปเดต Machine ที่มีอยู่ใน state
+  async function editMachine(id: number, payload: Partial<Machine>) {
+    loading.value = true;
+    error.value = null;
+    try {
+      const updatedMachine = await machineService.updateMachine(id, payload);
+      const index = machines.value.findIndex(m => m.MachineID === id);
+      if (index !== -1) {
+        machines.value[index] = updatedMachine;
+      }
+    } catch (e: any) {
+      error.value = e.message || 'Unknown Error';
+    } finally {
+      loading.value = false;
+    }
+  }
+
+  // ลบ Machine จาก backend และอัปเดต state
+  async function removeMachine(id: number) {
+    loading.value = true;
+    error.value = null;
+    try {
+      await machineService.deleteMachine(id);
+      machines.value = machines.value.filter(m => m.MachineID !== id);
+    } catch (e: any) {
+      error.value = e.message || 'Unknown Error';
+    } finally {
+      loading.value = false;
+    }
+  }
+
+  return {
+    machines,
+    loading,
+    error,
+    fetchMachines,
+    fetchMachine,
+    addMachine,
+    editMachine,
+    removeMachine,
+  };
+});
diff --git a/src/stores/order.ts b/src/stores/order.ts
new file mode 100644
index 0000000..00d00e2
--- /dev/null
+++ b/src/stores/order.ts
@@ -0,0 +1,100 @@
+// /src/stores/order.store.ts
+
+import { defineStore } from 'pinia';
+import { ref } from 'vue';
+import type { Order } from '@/types/Order';
+import * as orderService from '@/services/order';
+
+export const useOrderStore = defineStore('order', () => {
+  const orders = ref<Order[]>([]);
+  const loading = ref<boolean>(false);
+  const error = ref<string | null>(null);
+
+  // ดึงรายการ Order ทั้งหมดจาก backend
+  async function fetchOrders() {
+    loading.value = true;
+    error.value = null;
+    try {
+      const response = await orderService.listOrders();
+      console.log("Fetched orders from API:", response); // ✅ ตรวจสอบ API Response
+      orders.value = response;
+      console.log("Orders in store after update:", orders.value); // ✅ ตรวจสอบว่าถูกอัปเดตหรือไม่
+    } catch (e: any) {
+      error.value = e.message || "Unknown Error";
+    } finally {
+      loading.value = false;
+    }
+  }
+  
+  
+
+  // ดึงข้อมูล Order รายการเดียวโดยใช้ OrderID
+  async function fetchOrder(id: number): Promise<Order | null> {
+    loading.value = true;
+    error.value = null;
+    try {
+      return await orderService.getOrder(id);
+    } catch (e: any) {
+      error.value = e.message || 'Unknown Error';
+      return null;
+    } finally {
+      loading.value = false;
+    }
+  }
+
+  // สร้าง Order ใหม่แล้วเพิ่มเข้า state
+  async function addOrder(payload: Partial<Order>) {
+    loading.value = true;
+    error.value = null;
+    try {
+      const newOrder = await orderService.createOrder(payload);
+      orders.value.push(newOrder);
+    } catch (e: any) {
+      error.value = e.message || 'Unknown Error';
+    } finally {
+      loading.value = false;
+    }
+  }
+
+  // อัปเดต Order ที่มีอยู่ใน state
+  async function editOrder(id: number, payload: Partial<Order>) {
+    loading.value = true;
+    error.value = null;
+    try {
+      const updatedOrder = await orderService.updateOrder(id, payload);
+      const index = orders.value.findIndex(o => o.OrderID === id);
+      if (index !== -1) {
+        orders.value[index] = updatedOrder;
+      }
+    } catch (e: any) {
+      error.value = e.message || 'Unknown Error';
+    } finally {
+      loading.value = false;
+    }
+  }
+
+  // ลบ Order จาก backend และอัปเดต state
+  async function removeOrder(id: number) {
+    loading.value = true;
+    error.value = null;
+    try {
+      await orderService.deleteOrder(id);
+      orders.value = orders.value.filter(o => o.OrderID !== id);
+    } catch (e: any) {
+      error.value = e.message || 'Unknown Error';
+    } finally {
+      loading.value = false;
+    }
+  }
+
+  return {
+    orders,
+    loading,
+    error,
+    fetchOrders,
+    fetchOrder,
+    addOrder,
+    editOrder,
+    removeOrder,
+  };
+});
diff --git a/src/stores/queue.ts b/src/stores/queue.ts
index 370d79c..f3b6e0f 100644
--- a/src/stores/queue.ts
+++ b/src/stores/queue.ts
@@ -1,41 +1,134 @@
 import { defineStore } from 'pinia';
-import QueueService from '@/services/queue';
-import type { QueueItem } from '@/types/QueueItem'
 import { ref } from 'vue';
-import { useLoadingStore } from './loading';
-
-// ฟังก์ชัน Sleep ให้รอจริง ๆ
-function sleep(ms: number) {
-  return new Promise(resolve => setTimeout(resolve, ms));
-}
+import type { Queue, QueuePostData } from '@/types/Queue';
+import * as queueService from '@/services/queue';
 
 export const useQueueStore = defineStore('queue', () => {
-  const Queues = ref<QueueItem[]>([]);
-  const loadingStore = useLoadingStore();
+  const queues = ref<Queue[]>([]);
+  const loading = ref<boolean>(false);
+  const error = ref<string | null>(null);
+
+  // **ดึงรายการ Queue ทั้งหมดจาก backend**
+  async function fetchQueues() {
+    loading.value = true;
+    error.value = null;
+    try {
+      console.log("📡 Fetching Queues from Backend...");
+      const response = await queueService.listQueues();
+      console.log("✅ Queues Response from Backend:", response);
+      queues.value = response;
+    } catch (e: any) {
+      console.error("❌ Error fetching queues:", e.response?.data || e.message);
+      error.value = e.message || "Unknown Error";
+    } finally {
+      loading.value = false;
+    }
+  }
 
-  const makeQueue = async () => {
+  // **ดึง Queue รายการเดียวจาก backend**
+  async function getQueue(id: number): Promise<Queue> {
+    loading.value = true;
+    error.value = null;
     try {
-      // ✅ รอ 3 วินาทีจริง ๆ ก่อนเริ่มโหลด
-      loadingStore.isLoading = true;
-      console.log("Waiting for 3 seconds...");
-      await sleep(3000);
+      console.log(`📡 Fetching Queue ID: ${id} from Backend...`);
+      const queue = await queueService.getQueue(id);
+      console.log("✅ Queue Data Received:", queue);
+      return queue;
+    } catch (e: any) {
+      console.error(`❌ Error fetching Queue ID ${id}:`, e.response?.data || e.message);
+      error.value = e.message || "Unknown Error";
+      throw e;
+    } finally {
+      loading.value = false;
+    }
+  }
 
-      console.log("Fetching queue data...");
-      const queueData = await QueueService.makeQueue(); // ✅ รอ API
+  // **เพิ่ม Queue ลง Database (ใช้ QueuePostData)**
+  async function addQueue(newQueue: QueuePostData) {
+    loading.value = true;
+    error.value = null;
+    try {
+      console.log("➕ Adding Queue:", newQueue);
+      const createdQueue = await queueService.createQueue(newQueue);
+      queues.value.push(createdQueue);
+      console.log("✅ Queue Added:", createdQueue);
+    } catch (e: any) {
+      console.error("❌ Error adding queue:", e.response?.data || e.message);
+      error.value = e.message || "Unknown Error";
+    } finally {
+      loading.value = false;
+    }
+  }
 
-      if (queueData && Array.isArray(queueData)) {
-        console.log("Appending data to Queues...");
-        Queues.value = [...queueData]; // ✅ ใช้ spread แทน forEach()
+  // **อัปเดต Queue (ใช้ QueuePostData)**
+  async function updateQueue(id: number, updatedData: QueuePostData) {
+    if (!id) {
+      console.error("❌ queueID is undefined! Cannot update.");
+      return;
+    }
+
+    loading.value = true;
+    error.value = null;
+    try {
+      console.log(`🛠 Updating Queue ID: ${id}...`);
+      const updatedQueue = await queueService.updateQueue(id, updatedData);
+      const index = queues.value.findIndex(q => q.QueueID === id);
+      if (index !== -1) {
+        queues.value[index] = updatedQueue;
+        console.log(`✅ Queue ID: ${id} Updated Successfully`, updatedQueue);
       } else {
-        console.log("No queue data received.");
+        console.warn(`⚠️ Queue ID: ${id} Not Found in Store!`);
       }
+    } catch (e: any) {
+      console.error(`❌ Error updating Queue ID ${id}:`, e.response?.data || e.message);
+      error.value = e.message || "Unknown Error";
+    } finally {
+      loading.value = false;
+    }
+  }
 
-      loadingStore.isLoading = false; // ✅ ปิด loading เมื่อโหลดเสร็จ
-    } catch (error) {
-      console.error('❌ Error fetching queue:', error);
-      loadingStore.isLoading = false; // ปิด loading ถ้า error
+  // **ลบ Queue**
+  async function deleteQueue(id: number) {
+    loading.value = true;
+    error.value = null;
+    try {
+      console.log(`🗑 Deleting Queue ID: ${id}...`);
+      await queueService.deleteQueue(id);
+      // ลบ Queue ออกจาก Store
+      queues.value = queues.value.filter(q => q.QueueID !== id);
+      console.log(`✅ Queue ID: ${id} Deleted Successfully`);
+    } catch (e: any) {
+      console.error(`❌ Error deleting Queue ID ${id}:`, e.response?.data || e.message);
+      error.value = e.message || "Unknown Error";
+    } finally {
+      loading.value = false;
     }
-  };
+  }
+
+  function convertQueueToPostData(queue: Queue): QueuePostData {
+    return {
+      startTime: new Date(queue.startTime).toISOString(),
+      finishTime: new Date(queue.finishTime).toISOString(),
+      status: queue.status,
+      bottleSize: queue.bottleSize,
+      producedQuantity: queue.producedQuantity,
+      MachineID: queue.machine?.MachineID ?? 0, // ใช้ MachineID จาก object
+      PageID: queue.page?.PageID ?? 0,
+      OrderID: queue.order?.OrderID ?? 0,
+      EmployeeIds: queue.employees.map(emp => emp.EmployeeID), // แปลง employees เป็นแค่ array ของ ID
+    };
+  }
+  
 
-  return { Queues, makeQueue };
+  return {
+    queues,
+    loading,
+    error,
+    fetchQueues,
+    getQueue,
+    convertQueueToPostData,
+    addQueue,
+    updateQueue,
+    deleteQueue,
+  };
 });
diff --git a/src/types/Machine.ts b/src/types/Machine.ts
new file mode 100644
index 0000000..7cde028
--- /dev/null
+++ b/src/types/Machine.ts
@@ -0,0 +1,12 @@
+export interface Machine {
+    MachineID: number;                   // ใช้ตาม entity (ตัว Q ใหญ่)
+    name: string;                        // ชื่อเครื่องจักร
+    type: string;                        // ประเภทเครื่องจักร
+    lastMaintenanceDate?: string;        // วันที่ซ่อมบำรุงล่าสุด (ISO string)
+    status: 'ACTIVE' | 'INACTIVE' | 'MAINTENANCE'; // สถานะเครื่องจักร
+    notes?: string;                      // หมายเหตุเพิ่มเติม
+    // หากต้องการ include ความสัมพันธ์
+    // machineDetails?: MachineDetail[];
+    // queues?: Queue[];
+  }
+  
\ No newline at end of file
diff --git a/src/types/Order.ts b/src/types/Order.ts
new file mode 100644
index 0000000..b592e38
--- /dev/null
+++ b/src/types/Order.ts
@@ -0,0 +1,13 @@
+export interface Order {
+    OrderID: number;                  // ใช้ Q ใหญ่ตาม entity
+    customer: { CustomerID: number }; // ความสัมพันธ์กับ Customer
+    orderPriorities?: { OrderPriorityID: number }[]; // ความสัมพันธ์กับ OrderPriority (ถ้ามี)
+    orderDetails?: { OrderDetailID: number }[]; // ความสัมพันธ์กับ OrderDetail (ถ้ามี)
+    queues?: { QueueID: number }[];    // ความสัมพันธ์กับ Queue (ถ้ามี)
+    OrderDate: string;                // วันที่สร้างออเดอร์ (ISO string)
+    status: string;                    // สถานะออเดอร์
+    totalPriceall: number;              // ราคารวมทั้งหมด
+    quantity: number;                   // จำนวนสินค้าทั้งหมด
+    startDate?: string;                  // วันที่เริ่มต้น (ISO string)
+    finishDate?: string;                 // วันที่สิ้นสุด (ISO string)
+  }
\ No newline at end of file
diff --git a/src/types/Queue.ts b/src/types/Queue.ts
index ca35bf6..edfa6e6 100644
--- a/src/types/Queue.ts
+++ b/src/types/Queue.ts
@@ -1,11 +1,39 @@
-export type Queue = {
-  queueID: number | string;
-  machineID: number | string;
-  orderID: number | string;
+export interface Queue {
   pageID: number;
-  startTime: Date;
-  finishTime: Date;
-  status: 'pending' | 'in-progress' | 'completed' | 'canceled';
+  orderID: null;
+  machineID: null;
+  QueueID: number;
+  machine?: {
+    MachineID: number;
+    name: string;
+  };
+  page?: {
+    PageID: number;
+  };
+  order?: {
+    OrderID: number;
+  };
+  employees: Employee[];  
+  startTime: string | Date;   
+  finishTime: string | Date;  
+  status: string;
   bottleSize: string;
   producedQuantity: number;
-};
\ No newline at end of file
+}
+
+export interface Employee {
+  EmployeeID: number;
+  name: string;
+}
+
+export interface QueuePostData {
+  startTime: string;
+  finishTime: string;
+  status: string;
+  bottleSize: string;
+  producedQuantity: number;
+  MachineID: number;
+  PageID: number;
+  OrderID: number;
+  EmployeeIds: number[];
+}
diff --git a/src/types/QueueItem.ts b/src/types/QueueItem.ts
deleted file mode 100644
index b156202..0000000
--- a/src/types/QueueItem.ts
+++ /dev/null
@@ -1,11 +0,0 @@
-export type QueueItem = {
-  queueID: number;
-  machineID: string;
-  orderID: number;
-  pageNumber: number;
-  startTime: string;
-  finishTime: string;
-  status: string;
-  bottleSize: string;
-  producedQuantity: number;
-}
\ No newline at end of file
diff --git a/src/views/MachineManagementView.vue b/src/views/MachineManagementView.vue
new file mode 100644
index 0000000..5ff3aee
--- /dev/null
+++ b/src/views/MachineManagementView.vue
@@ -0,0 +1,118 @@
+<script lang="ts" setup>
+import { nextTick, onMounted, ref } from 'vue'
+import type { VForm } from 'vuetify/components'
+import type { Machine } from '@/types/Machine'
+import { useMachineStore } from '@/stores/machine'
+
+const machineStore = useMachineStore()
+const headers = [
+  { title: 'ID', key: 'MachineID', value: 'MachineID' },
+  { title: 'Name', key: 'name', value: 'name' },
+  { title: 'Type', key: 'type', value: 'type' },
+  { title: 'Status', key: 'status', value: 'status' },
+  { title: 'Last Maintenance', key: 'lastMaintenanceDate', value: 'lastMaintenanceDate' },
+  { title: 'Actions', key: 'actions', sortable: false }
+]
+
+const form = ref(false)
+const refForm = ref<VForm | null>(null)
+const dialog = ref(false)
+const dialogDelete = ref(false)
+const loading = ref(false)
+
+
+async function editItem(item: Machine) {
+  if (!item.MachineID) return
+  await machineStore.fetchMachine(item.MachineID)
+  dialog.value = true
+}
+
+async function deleteItem(item: Machine) {
+  if (!item.MachineID) return
+  await machineStore.fetchMachine(item.MachineID)
+  dialogDelete.value = true
+}
+
+
+onMounted(async () => {
+  await machineStore.fetchMachines()
+})
+</script>
+
+<template>
+  <div>
+    <v-data-table :headers="headers" :items="machineStore.machines">
+      <template v-slot:top>
+        <v-toolbar flat style="background-color: rgb(247, 156, 82)">
+          <v-toolbar-title style="color: white; font-weight: bold; font-size: 30px">Machines</v-toolbar-title>
+          <v-divider class="mx-4" inset vertical></v-divider>
+          <v-spacer></v-spacer>
+
+          <v-dialog v-model="dialog" persistent width="800">
+            <template v-slot:activator="{ props }">
+              <v-btn prepend-icon="mdi-plus" v-bind="props" style="color: white; background-color: green">
+                New Machine
+              </v-btn>
+            </template>
+            <v-card>
+              <v-card-title>
+                <span class="text-h5">Machine Details</span>
+              </v-card-title>
+              <v-card-text>
+                <v-form ref="refForm" v-model="form" @submit.prevent="save">
+                  <v-container>
+                    <v-row>
+                      <v-col cols="12" sm="6">
+                        <v-text-field v-model="machineStore.editedMachine.name" label="Machine Name"
+                          :rules="[(v) => !!v || 'Field is required']"></v-text-field>
+                      </v-col>
+                      <v-col cols="12" sm="6">
+                        <v-text-field v-model="machineStore.editedMachine.type" label="Machine Type"
+                          :rules="[(v) => !!v || 'Field is required']"></v-text-field>
+                      </v-col>
+                      <v-col cols="12" sm="6">
+                        <v-select v-model="machineStore.editedMachine.status" :items="['ACTIVE', 'INACTIVE', 'MAINTENANCE']"
+                          label="Status"></v-select>
+                      </v-col>
+                      <v-col cols="12" sm="6">
+                        <v-text-field v-model="machineStore.editedMachine.lastMaintenanceDate" label="Last Maintenance Date"
+                          type="date"></v-text-field>
+                      </v-col>
+                    </v-row>
+                  </v-container>
+                </v-form>
+              </v-card-text>
+              <v-card-actions>
+                <v-spacer></v-spacer>
+                <v-btn color="blue-darken-1" variant="text" @click="closeDialog">Close</v-btn>
+                <v-btn color="blue-darken-1" variant="text" @click="save">Save</v-btn>
+              </v-card-actions>
+            </v-card>
+          </v-dialog>
+
+          <!-- Delete Confirmation Dialog -->
+          <v-dialog v-model="dialogDelete" max-width="500px">
+            <v-card>
+              <v-card-title class="text-h5">Are you sure you want to delete this machine?</v-card-title>
+              <v-card-actions>
+                <v-spacer></v-spacer>
+                <v-btn color="blue-darken-1" variant="text" @click="dialogDelete = false">Cancel</v-btn>
+                <v-btn color="blue-darken-1" variant="text" @click="deleteItemConfirm">Delete</v-btn>
+                <v-spacer></v-spacer>
+              </v-card-actions>
+            </v-card>
+          </v-dialog>
+        </v-toolbar>
+      </template>
+
+      <template v-slot:[`item.actions`]="{ item }">
+        <v-icon size="small" class="me-2" @click="editItem(item)"> mdi-pencil </v-icon>
+        <v-icon size="small" @click="deleteItem(item)"> mdi-delete </v-icon>
+      </template>
+
+      <template v-slot:no-data>
+        <v-btn color="primary" @click="machineStore.fetchMachines">Reset</v-btn>
+      </template>
+    </v-data-table>
+  </div>
+</template>
-- 
GitLab