From c5d311a59debc60f95e78f83289459d9041f36de Mon Sep 17 00:00:00 2001
From: Kritkhanin Anantakul <65160144@go.buu.ac.th>
Date: Mon, 3 Mar 2025 22:24:18 +0700
Subject: [PATCH] dialog order fix and color

---
 src/components/GanttChart/GanttChart.vue  | 228 +++++++++++-----------
 src/components/GanttChart/OrderDialog.vue | 143 +++++++++++---
 2 files changed, 233 insertions(+), 138 deletions(-)

diff --git a/src/components/GanttChart/GanttChart.vue b/src/components/GanttChart/GanttChart.vue
index de84e2a..9be07e0 100644
--- a/src/components/GanttChart/GanttChart.vue
+++ b/src/components/GanttChart/GanttChart.vue
@@ -40,35 +40,35 @@
               :style="getLineStyle(hour)"
             ></div>
 
-            <!-- แสดง Order ที่ตรงกับวันที่ (selectedDate), Page, และ Machine -->
+            <!-- แสดง Queue ที่ตรงกับวันที่ (selectedDate), Page, และ Machine -->
             <div
-              v-for="order in filteredOrders(machine.machineID)"
-              :key="order.queueID"
+              v-for="item in filteredQueue(machine.machineID)"
+              :key="item.queueID"
               class="order"
-              :class="{ 'faded': draggingOrder && draggingOrder.queueID === order.queueID }"
-              :style="getOrderStyle(order)"
+              :class="{ 'faded': draggingQueue && draggingQueue.queueID === item.queueID }"
+              :style="getQueueStyle(item)"
             >
               <!-- Handle สำหรับ Resize ด้านซ้าย -->
               <div
                 class="resize-handle left"
-                @mousedown="onResizeStart($event, order, 'left')"
+                @mousedown="onResizeStart($event, item, 'left')"
               ></div>
 
               <!-- ส่วนกลางของ Order ใช้สำหรับลาก และเปิด Dialog เมื่อคลิก -->
               <div
                 class="order-content"
                 draggable="true"
-                @dragstart="onDragStart($event, order)"
-                @dragend="onDragEnd($event, order)"
-                @click.stop="openOrderDialog(order)"
+                @dragstart="onDragStart($event, item)"
+                @dragend="onDragEnd($event, item)"
+                @click.stop="openQueueDialog(item)"
               >
-                {{ order.orderID }} ({{ getTimeString(order.startTime) }} - {{ getTimeString(order.finishTime) }})
+                {{ item.orderID }} ({{ getTimeString(item.startTime) }} - {{ getTimeString(item.finishTime) }})
               </div>
 
               <!-- Handle สำหรับ Resize ด้านขวา -->
               <div
                 class="resize-handle right"
-                @mousedown="onResizeStart($event, order, 'right')"
+                @mousedown="onResizeStart($event, item, 'right')"
               ></div>
             </div>
           </div>
@@ -76,8 +76,9 @@
       </div>
 
       <!-- Ghost Order ขณะลาก -->
-      <div v-if="ghostOrder" class="drag-ghost" :style="ghostStyle">
-        {{ ghostOrder.orderID }} ({{ getTimeString(ghostOrder.startTime) }} - {{ getTimeString(ghostOrder.finishTime) }})
+      <div v-if="ghostQueue" class="drag-ghost" :style="ghostStyle">
+        {{ ghostQueue.orderID }}
+        ({{ getTimeString(ghostQueue.startTime) }} - {{ getTimeString(ghostQueue.finishTime) }})
       </div>
 
       <v-divider :thickness="7"></v-divider>
@@ -105,11 +106,12 @@
 
       <!-- Order Dialog -->
       <OrderDialog
-        v-if="selectedOrder"
-        :order="selectedOrder"
-        @close="closeOrderDialog"
-        @edit="editOrder"
-        @delete="deleteOrder"
+        v-if="selectedQueueItem"
+        :queueItem="selectedQueueItem"
+        :color="getQueueColor(selectedQueueItem.orderID)"
+        @close="closeQueueDialog"
+        @edit="editQueueItem"
+        @delete="deleteQueueItem"
       />
     </div>
   </div>
@@ -144,12 +146,12 @@ export default {
         { id: 5, machineID: 'MC5' },
       ],
 
-      // ข้อมูล Order ตามโครงสร้าง Queue
-      orders: [
+      // เปลี่ยนจาก orders เป็น Queue
+      Queue: [
         {
           queueID: 1,
           machineID: 'MC1',
-          orderID: 1,
+          orderID: 5,
           pageNumber: 1,
           startTime: '1/1/2024 09:00',
           finishTime: '1/1/2024 11:00',
@@ -160,7 +162,7 @@ export default {
         {
           queueID: 2,
           machineID: 'MC2',
-          orderID: 2,
+          orderID: 1,
           pageNumber: 1,
           startTime: '1/1/2024 13:00',
           finishTime: '1/1/2024 15:00',
@@ -171,7 +173,7 @@ export default {
         {
           queueID: 3,
           machineID: 'MC1',
-          orderID: 3,
+          orderID: 2,
           pageNumber: 2,
           startTime: '1/1/2024 10:00',
           finishTime: '1/1/2024 12:00',
@@ -182,7 +184,7 @@ export default {
         {
           queueID: 4,
           machineID: 'MC5',
-          orderID: 4,
+          orderID: 2,
           pageNumber: 2,
           startTime: '1/1/2024 14:00',
           finishTime: '1/1/2024 16:00',
@@ -204,13 +206,13 @@ export default {
       ],
 
       // จัดการการลาก, Resize
-      draggingOrder: null,
+      draggingQueue: null,
       dragOffset: 0,
-      resizingOrder: null,
+      resizingQueue: null,
       resizeDirection: null,
 
       // Ghost Order (ขณะลาก)
-      ghostOrder: null,
+      ghostQueue: null,
       ghostStyle: {
         position: 'fixed',
         top: '0px',
@@ -233,7 +235,7 @@ export default {
       pageToShowDelete: null,
 
       // Dialog
-      selectedOrder: null,
+      selectedQueueItem: null,
     };
   },
   computed: {
@@ -245,9 +247,12 @@ export default {
     },
   },
   methods: {
+    // แปลงเลขชั่วโมงเป็น "HH:00"
+    formatHour(hour) {
+      return (hour < 10 ? '0' + hour : hour) + ':00';
+    },
     // แยก date ส่วนหน้า (1/1/2024) ออกจาก startTime/finishTime
     getDateString(dateTimeStr) {
-      // สมมติ format = '1/1/2024 09:00'
       return dateTimeStr.split(' ')[0];
     },
     // แยกเฉพาะส่วนเวลา (09:00)
@@ -255,45 +260,50 @@ export default {
       return dateTimeStr.split(' ')[1];
     },
 
-    // ฟิลเตอร์ order ตาม machineID, pageNumber, และ selectedDate
-    filteredOrders(machineID) {
-      return this.orders.filter((o) => {
-        const orderDate = this.getDateString(o.startTime);
+    // ฟิลเตอร์ Queue ตาม machineID, pageNumber, และ selectedDate
+    filteredQueue(machineID) {
+      return this.Queue.filter((q) => {
+        const queueDate = this.getDateString(q.startTime);
         return (
-          o.machineID === machineID &&
-          o.pageNumber === this.currentPage &&
-          orderDate === this.selectedDate
+          q.machineID === machineID &&
+          q.pageNumber === this.currentPage &&
+          queueDate === this.selectedDate
         );
       });
     },
 
-    // แปลงเลขชั่วโมงเป็น "HH:00"
-    formatHour(hour) {
-      return (hour < 10 ? '0' + hour : hour) + ':00';
+    // ฟังก์ชันเลือกสีจาก orderID
+    getQueueColor(orderID) {
+    const colors = ['#F58181', '#FDDC5C', '#C5A1BC', '#49E060']; // 4 สีที่กำหนด
+    return colors[(orderID - 1) % colors.length]; // ใช้ modulo (%) เพื่อให้วนกลับไปที่สีแรกเมื่อเกิน 4
     },
 
-    // สไตล์ตำแหน่งของ Order
-    getOrderStyle(order) {
-      // แยกเวลาเฉพาะส่วน HH:mm
-      const start = this.getTimeString(order.startTime); // ex "09:00"
-      const end = this.getTimeString(order.finishTime);  // ex "11:00"
-
-      const startDecimal = this.timeToDecimal(start);
-      const endDecimal = this.timeToDecimal(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);
+    // สไตล์ตำแหน่ง + สีของ Queue
+    getQueueStyle(item) {
+    const start = this.getTimeString(item.startTime);
+    const end = this.getTimeString(item.finishTime);
+    const startDecimal = this.timeToDecimal(start);
+    const endDecimal = this.timeToDecimal(end);
+    const timelineStart = this.timeToDecimal(this.startTime);
+    const timelineEnd = this.timeToDecimal(this.endTime);
 
-      return {
-        left: ratioStart * 100 + '%',
-        width: (ratioEnd - ratioStart) * 100 + '%',
-        backgroundColor: '#4caf50', // สามารถปรับตาม status หรืออื่นๆ ได้
-      };
-    },
+    const ratioStart = (startDecimal - timelineStart) / (timelineEnd - timelineStart);
+    const ratioEnd = (endDecimal - timelineStart) / (timelineEnd - timelineStart);
 
-    // สไตล์ของเส้นแนวตั้ง (grid lines)
+    return {
+      left: ratioStart * 100 + '%', // คำนวณตำแหน่งซ้าย
+      width: (ratioEnd - ratioStart) * 100 + '%', // คำนวณความกว้าง
+      backgroundColor: this.getQueueColor(item.orderID), // ใช้สีตาม orderID
+      color: '#fff', // ข้อความสีขาวให้อ่านง่าย
+      borderRadius: '10px', // ขอบโค้งมนให้ดูสวยขึ้น
+      textAlign: 'center',
+      display: 'flex',
+      alignItems: 'center',
+      justifyContent: 'center',
+      padding: '5px',
+      fontSize: '14px',
+    };
+  },
     getLineStyle(hour) {
       const timelineStart = this.timeToDecimal(this.startTime);
       const timelineEnd = this.timeToDecimal(this.endTime);
@@ -302,22 +312,19 @@ export default {
         left: ratio * 100 + '%',
       };
     },
-
-    // แปลงเวลา "HH:MM" -> เลขทศนิยม
     timeToDecimal(timeStr) {
       const [hours, minutes] = timeStr.split(':').map(Number);
       return hours + minutes / 60;
     },
-    // แปลงเลขทศนิยม -> "HH:MM"
     decimalToTime(decimal) {
       const hours = Math.floor(decimal);
       const minutes = Math.round((decimal - hours) * 60);
       return (hours < 10 ? '0' + hours : hours) + ':' + (minutes < 10 ? '0' + minutes : minutes);
     },
 
-    // Event ลาก (DragStart)
-    onDragStart(event, order) {
-      this.draggingOrder = order;
+    // ==================== Drag/Drop ====================
+    onDragStart(event, item) {
+      this.draggingQueue = item;
       const rect = event.target.getBoundingClientRect();
       this.dragOffset = rect.width / 2;
       // ปิด preview เริ่มต้นของ HTML5 Drag & Drop
@@ -325,9 +332,10 @@ export default {
       emptyImg.src = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=';
       event.dataTransfer.setDragImage(emptyImg, 0, 0);
 
-      this.ghostOrder = { ...order };
+      this.ghostQueue = { ...item };
       this.ghostStyle.display = 'block';
-      this.ghostStyle.backgroundColor = '#4caf50';
+      // ใช้สีเดียวกับ orderID
+      this.ghostStyle.backgroundColor = this.getQueueColor(item.orderID);
 
       document.addEventListener('dragover', this.onDragOverGlobal);
       document.addEventListener('dragend', this.onDragEndGlobal);
@@ -350,8 +358,8 @@ export default {
       const timelineEnd = this.timeToDecimal(this.endTime);
 
       // คำนวณเวลาเริ่มใหม่ (เฉพาะส่วนเวลา)
-      const startDecimal = this.timeToDecimal(this.getTimeString(this.draggingOrder.startTime));
-      const endDecimal = this.timeToDecimal(this.getTimeString(this.draggingOrder.finishTime));
+      const startDecimal = this.timeToDecimal(this.getTimeString(this.draggingQueue.startTime));
+      const endDecimal = this.timeToDecimal(this.getTimeString(this.draggingQueue.finishTime));
       const duration = endDecimal - startDecimal;
 
       let newStartDecimal = timelineStart + ratio * (timelineEnd - timelineStart);
@@ -364,12 +372,12 @@ export default {
       }
 
       // สร้าง String ใหม่ "วัน/เดือน/ปี เวลา"
-      const datePart = this.getDateString(this.draggingOrder.startTime); // ex "1/1/2024"
+      const datePart = this.getDateString(this.draggingQueue.startTime);
       const newStartStr = datePart + ' ' + this.decimalToTime(newStartDecimal);
       const newEndStr = datePart + ' ' + this.decimalToTime(newEndDecimal);
 
-      this.ghostOrder.startTime = newStartStr;
-      this.ghostOrder.finishTime = newEndStr;
+      this.ghostQueue.startTime = newStartStr;
+      this.ghostQueue.finishTime = newEndStr;
 
       const snappedRatioStart = (newStartDecimal - timelineStart) / (timelineEnd - timelineStart);
       const snappedLeft = timelineRect.left + snappedRatioStart * timelineWidth;
@@ -391,7 +399,7 @@ export default {
       });
 
       if (closestRow) {
-        this.ghostOrder.machineID = closestRow.querySelector('.machine-label').textContent.trim();
+        this.ghostQueue.machineID = closestRow.querySelector('.machine-label').textContent.trim();
         this.ghostStyle.top = closestRow.getBoundingClientRect().top + 'px';
       }
 
@@ -399,43 +407,43 @@ export default {
       this.ghostStyle.width = snappedWidth + 'px';
     },
     onDragEndGlobal() {
-      this.ghostOrder = null;
+      this.ghostQueue = null;
       this.ghostStyle.display = 'none';
-      this.draggingOrder = null;
+      this.draggingQueue = null;
       document.removeEventListener('dragend', this.onDragEndGlobal);
     },
-    onDragEnd(event, order) {
-      if (!this.ghostOrder) return;
-      order.startTime = this.ghostOrder.startTime;
-      order.finishTime = this.ghostOrder.finishTime;
-      order.machineID = this.ghostOrder.machineID;
+    onDragEnd(event, item) {
+      if (!this.ghostQueue) return;
+      item.startTime = this.ghostQueue.startTime;
+      item.finishTime = this.ghostQueue.finishTime;
+      item.machineID = this.ghostQueue.machineID;
       document.removeEventListener('dragover', this.onDragOverGlobal);
-      this.ghostOrder = null;
+      this.ghostQueue = null;
       this.ghostStyle.display = 'none';
-      this.draggingOrder = null;
+      this.draggingQueue = null;
     },
     onDrop(event, newMachine) {
       event.preventDefault();
-      if (this.draggingOrder && this.ghostOrder) {
-        this.draggingOrder.startTime = this.ghostOrder.startTime;
-        this.draggingOrder.finishTime = this.ghostOrder.finishTime;
-        this.draggingOrder.machineID = newMachine;
+      if (this.draggingQueue && this.ghostQueue) {
+        this.draggingQueue.startTime = this.ghostQueue.startTime;
+        this.draggingQueue.finishTime = this.ghostQueue.finishTime;
+        this.draggingQueue.machineID = newMachine;
       }
-      this.ghostOrder = null;
+      this.ghostQueue = null;
       this.ghostStyle.display = 'none';
-      this.draggingOrder = null;
+      this.draggingQueue = null;
     },
 
-    // Resize
-    onResizeStart(event, order, direction) {
+    // ==================== Resize ====================
+    onResizeStart(event, item, direction) {
       event.preventDefault();
-      this.resizingOrder = order;
+      this.resizingQueue = item;
       this.resizeDirection = direction;
       document.addEventListener('mousemove', this.onResizing);
       document.addEventListener('mouseup', this.onResizeEnd);
     },
     onResizing(event) {
-      if (!this.resizingOrder) return;
+      if (!this.resizingQueue) return;
       const rowTimeline = document.querySelector('.row-timeline');
       if (!rowTimeline) return;
       const timelineRect = rowTimeline.getBoundingClientRect();
@@ -448,32 +456,32 @@ export default {
       const timelineStart = this.timeToDecimal(this.startTime);
       const timelineEnd = this.timeToDecimal(this.endTime);
 
-      const startDec = this.timeToDecimal(this.getTimeString(this.resizingOrder.startTime));
-      const endDec = this.timeToDecimal(this.getTimeString(this.resizingOrder.finishTime));
+      const startDec = this.timeToDecimal(this.getTimeString(this.resizingQueue.startTime));
+      const endDec = this.timeToDecimal(this.getTimeString(this.resizingQueue.finishTime));
 
       let newTimeDecimal = timelineStart + ratio * (timelineEnd - timelineStart);
       newTimeDecimal = Math.round(newTimeDecimal * 2) / 2;
 
-      const datePart = this.getDateString(this.resizingOrder.startTime); // ex: "1/1/2024"
+      const datePart = this.getDateString(this.resizingQueue.startTime); // ex: "1/1/2024"
 
       if (this.resizeDirection === 'left') {
         if (newTimeDecimal >= endDec) return;
         const newStartStr = datePart + ' ' + this.decimalToTime(newTimeDecimal);
-        this.resizingOrder.startTime = newStartStr;
+        this.resizingQueue.startTime = newStartStr;
       } else if (this.resizeDirection === 'right') {
         if (newTimeDecimal <= startDec) return;
         const newEndStr = datePart + ' ' + this.decimalToTime(newTimeDecimal);
-        this.resizingOrder.finishTime = newEndStr;
+        this.resizingQueue.finishTime = newEndStr;
       }
     },
     onResizeEnd() {
-      this.resizingOrder = null;
+      this.resizingQueue = null;
       this.resizeDirection = null;
       document.removeEventListener('mousemove', this.onResizing);
       document.removeEventListener('mouseup', this.onResizeEnd);
     },
 
-    // Pagination
+    // ==================== Pagination ====================
     addPage() {
       const newPage = this.pages.length + 1;
       this.pages.push(newPage);
@@ -498,22 +506,22 @@ export default {
       }
     },
 
-    // Dialog
-    openOrderDialog(order) {
-      this.selectedOrder = { ...order };
+    // ==================== Dialog ====================
+    openQueueDialog(item) {
+      this.selectedQueueItem = { ...item };
     },
-    closeOrderDialog() {
-      this.selectedOrder = null;
+    closeQueueDialog() {
+      this.selectedQueueItem = null;
     },
-    editOrder(order) {
-      alert('Edit functionality not implemented yet.\nOrder ID: ' + order.orderID);
+    editQueueItem(item) {
+      alert('Edit functionality not implemented yet.\nOrder ID: ' + item.orderID);
     },
-    deleteOrder(order) {
-      this.orders = this.orders.filter((o) => o.queueID !== order.queueID);
-      this.closeOrderDialog();
+    deleteQueueItem(item) {
+      this.Queue = this.Queue.filter((q) => q.queueID !== item.queueID);
+      this.closeQueueDialog();
     },
   },
-  mounted() {
+  mounted() { 
     document.addEventListener('click', this.onDocumentClick);
   },
   beforeUnmount() {
diff --git a/src/components/GanttChart/OrderDialog.vue b/src/components/GanttChart/OrderDialog.vue
index 81adfb3..60e053b 100644
--- a/src/components/GanttChart/OrderDialog.vue
+++ b/src/components/GanttChart/OrderDialog.vue
@@ -1,35 +1,122 @@
 <template>
     <div class="order-dialog-overlay">
-      <div class="order-dialog">
-        <h3>Order Details</h3>
-        <p><strong>QueueID:</strong> {{ order.queueID }}</p>
-        <p><strong>Machine:</strong> {{ order.machineID }}</p>
-        <p><strong>OrderID:</strong> {{ order.orderID }}</p>
-        <p><strong>PageNumber:</strong> {{ order.pageNumber }}</p>
-        <p><strong>Start:</strong> {{ order.startTime }}</p>
-        <p><strong>Finish:</strong> {{ order.finishTime }}</p>
-        <p><strong>Status:</strong> {{ order.status }}</p>
-        <p><strong>Bottle Size:</strong> {{ order.bottleSize }}</p>
-        <p><strong>Produced:</strong> {{ order.producedQuantity }}</p>
-  
-        <div class="dialog-buttons">
-          <button @click="$emit('edit', order)">Edit</button>
-          <button @click="$emit('delete', order)">Delete</button>
-          <button @click="$emit('close')">Close</button>
+        <div class="order-dialog" :style="{ backgroundColor: color }">
+            <div class="dialog-header">
+                <h3 class="order-title">{{ queueItem.orderName }}</h3>
+                <div class="dialog-buttons">
+                    <button @click="$emit('edit', queueItem)" class="icon-button">
+                        <span class="mdi mdi-pencil"></span>
+                    </button>
+                    <button @click="$emit('delete', queueItem)" class="icon-button">
+                        <span class="mdi mdi-delete"></span>
+                    </button>
+                    <button @click="$emit('close')" class="icon-button">
+                        <span class="mdi mdi-close"></span>
+                    </button>
+                </div>
+            </div>
+            <div class="order-details">
+                <p><strong>เป่าขวดจำนวน</strong> {{ queueItem.producedQuantity }} ขวด</p>
+                <p><strong>ตั้งแต่เวลา</strong> {{ queueItem.startTime }} - {{ queueItem.finishTime }}</p>
+            </div>
+            <div class="order-assignments">
+                <div class="machine">
+                    <span class="icon">🛠</span> {{ queueItem.machineID }}
+                </div>
+                <div class="employees" v-for="(employee, index) in queueItem.employees" :key="index">
+                    <span class="icon">👤</span> {{ employee }}
+                </div>
+            </div>
         </div>
-      </div>
     </div>
-  </template>
-  
-  <script>
-  export default {
+</template>
+
+<script>
+export default {
     name: 'OrderDialog',
     props: {
-      order: {
-        type: Object,
-        required: true,
-      },
+        queueItem: {
+            type: Object,
+            required: true,
+        },
+        color: {
+            type: String,
+            default: '#F28B82', // สีโทนแดงอ่อน
+        },
     },
-  };
-  </script>
-  
\ No newline at end of file
+};
+</script>
+
+<style scoped>
+.order-dialog-overlay {
+    position: fixed;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    background: rgba(0, 0, 0, 0.3);
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    z-index: 10000;
+}
+
+.order-dialog {
+    background: #F28B82;
+    padding: 15px;
+    border-radius: 12px;
+    width: 280px;
+    text-align: left;
+    position: relative;
+    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
+}
+
+.dialog-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+}
+
+.order-title {
+    font-size: 1.2rem;
+    font-weight: bold;
+}
+
+.dialog-buttons {
+    display: flex;
+    gap: 5px;
+}
+
+.icon-button {
+    background: none;
+    border: none;
+    cursor: pointer;
+    font-size: 18px;
+}
+
+.order-details {
+    background: white;
+    padding: 10px;
+    border-radius: 8px;
+    margin-top: 8px;
+    font-size: 0.9rem;
+}
+
+.order-assignments {
+    margin-top: 10px;
+}
+
+.machine, .employees {
+    background: white;
+    padding: 5px;
+    border-radius: 5px;
+    margin-top: 5px;
+    display: flex;
+    align-items: center;
+    gap: 5px;
+}
+
+.icon {
+    font-size: 1rem;
+}
+</style>
-- 
GitLab