diff --git a/package-lock.json b/package-lock.json index 0663271b54e2bdf8edda4c9d37eb495bd58b874c..518706d0ad674e49b5204b0c6e44850ab6cfa2c2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "class-transformer": "^0.5.1", "class-validator": "^0.14.1", "d3": "^7.9.0", + "date-fns": "^4.1.0", "dayjs": "^1.11.10", "install": "^0.13.0", "jsplumb": "^2.15.6", @@ -2836,6 +2837,16 @@ "node": ">=12" } }, + "node_modules/date-fns": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz", + "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/kossnocorp" + } + }, "node_modules/dayjs": { "version": "1.11.10", "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", diff --git a/package.json b/package.json index 1eae4b7ab36a16bf2c3207c16275a23b6145f727..2e257eda09ee4e3dc7b354964a91d4645f7be909 100644 --- a/package.json +++ b/package.json @@ -20,6 +20,7 @@ "class-transformer": "^0.5.1", "class-validator": "^0.14.1", "d3": "^7.9.0", + "date-fns": "^4.1.0", "dayjs": "^1.11.10", "install": "^0.13.0", "jsplumb": "^2.15.6", diff --git a/src/components/GanttChart/AddQueueDialog.vue b/src/components/GanttChart/AddQueueDialog.vue new file mode 100644 index 0000000000000000000000000000000000000000..7dcf482b289c1ca968d5f437b4b729ce33cfd045 --- /dev/null +++ b/src/components/GanttChart/AddQueueDialog.vue @@ -0,0 +1,193 @@ +<template> + <div class="add-queue-dialog-overlay" v-if="visible"> + <div class="add-queue-dialog"> + <h3>{{ isEditing ? "Edit Queue" : "Add New Queue" }}</h3> + <form @submit.prevent="handleSubmit"> + <div class="form-group"> + <label>Machine ID:</label> + <input v-model="form.machineID" type="text" required /> + </div> + <div class="form-group"> + <label>Order ID:</label> + <input v-model.number="form.orderID" type="number" required /> + </div> + <div class="form-group"> + <label>Page Number:</label> + <input v-model.number="form.pageNumber" type="number" required /> + </div> + <div class="form-group"> + <label>Start Time:</label> + <input v-model="form.startTime" type="text" required /> + </div> + <div class="form-group"> + <label>Finish Time:</label> + <input v-model="form.finishTime" type="text" required /> + </div> + <div class="form-group"> + <label>Status:</label> + <input v-model="form.status" type="text" required /> + </div> + <div class="form-group"> + <label>Bottle Size:</label> + <input v-model="form.bottleSize" type="text" required /> + </div> + <div class="form-group"> + <label>Produced Quantity:</label> + <input v-model.number="form.producedQuantity" type="number" required /> + </div> + + <!-- ปุ่ม Add หรือ Save Changes --> + <div class="dialog-buttons"> + <button type="submit" class="primary-btn"> + {{ isEditing ? "Save Changes" : "Add" }} + </button> + <button type="button" @click="closeDialog" class="secondary-btn">Cancel</button> + </div> + </form> + </div> + </div> + </template> + + + <script> +export default { + name: 'AddQueueDialog', + props: { + visible: Boolean, + queueItem: Object, // รับ queueItem ถ้ามี + }, + data() { + return { + form: { + machineID: '', + orderID: null, + pageNumber: null, + startTime: '', + finishTime: '', + status: '', + bottleSize: '', + producedQuantity: null, + }, + isEditing: false, // เช็คว่าเป็นโหมด Edit หรือไม่ + }; + }, + watch: { + queueItem(newItem) { + if (newItem) { + this.form = { ...newItem }; // ถ้าเป็น Edit โยนค่ามาใส่ฟอร์ม + this.isEditing = true; + } else { + this.resetForm(); + this.isEditing = false; + } + }, + }, + methods: { + closeDialog() { + console.log("Closing dialog"); // Debugging + this.$emit("close"); + this.resetForm(); + }, + handleSubmit() { + if (this.isEditing) { + this.$emit("edit", { ...this.form }); // ส่งข้อมูลไปอัปเดต Queue + } else { + this.$emit("add", { ...this.form, queueID: Date.now() }); // กรณีเพิ่มใหม่ต้องให้ queueID ไม่ซ้ำ + } + this.closeDialog(); + }, + resetForm() { + this.form = { + machineID: '', + orderID: null, + pageNumber: null, + startTime: '', + finishTime: '', + status: '', + bottleSize: '', + producedQuantity: null, + }; + }, + }, +}; +</script> + + + <style scoped> + .add-queue-dialog-overlay { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: rgba(0, 0, 0, 0.5); + display: flex; + align-items: center; + justify-content: center; + z-index: 10000; + } + + .add-queue-dialog { + background: #fff; + padding: 20px; + border-radius: 8px; + width: 400px; + position: relative; + } + + .form-group { + margin-bottom: 10px; + } + + .form-group label { + display: block; + font-weight: bold; + margin-bottom: 5px; + } + + .form-group input { + width: 100%; + padding: 5px; + box-sizing: border-box; + } + + .dialog-buttons { + display: flex; + justify-content: flex-end; + gap: 10px; + margin-top: 15px; + } + + .primary-btn { + background-color: #2B2E3F; + color: white; + border: none; + padding: 8px 16px; + border-radius: 4px; + cursor: pointer; + } + + .secondary-btn { + background-color: #ccc; + color: #333; + border: none; + padding: 8px 16px; + border-radius: 4px; + cursor: pointer; + } + + .icon-button { + position: absolute; + top: 10px; + right: 10px; + background: transparent; + border: none; + cursor: pointer; + } + + .icon-button .mdi { + font-size: 24px; + color: #2B2E3F; + } + </style> + \ No newline at end of file diff --git a/src/components/GanttChart/GanttCalendar.vue b/src/components/GanttChart/GanttCalendar.vue index 376830ae915a8edd8b2c95d4a74e79667b9d3384..eec687e851d22452d04824bf229d6098f753a7e3 100644 --- a/src/components/GanttChart/GanttCalendar.vue +++ b/src/components/GanttChart/GanttCalendar.vue @@ -1,35 +1,42 @@ <script setup> import { ref, watch } from 'vue'; +import { format, parse } from 'date-fns'; // ใช้ format และ parse วันที่ const props = defineProps({ modelValue: { type: String, - default: '1/1/2024', + default: '1/1/2024', // ฟอร์แมต "d/M/yyyy" }, }); + const emits = defineEmits(['update:modelValue']); const selectedDate = ref(props.modelValue); +// ฟังก์ชันเพิ่ม/ลดวัน +const changeDate = (days) => { + const currentDate = parse(selectedDate.value, 'd/M/yyyy', new Date()); + const newDate = new Date(currentDate); + newDate.setDate(currentDate.getDate() + days); + selectedDate.value = format(newDate, 'd/M/yyyy'); // อัปเดตวันที่ +}; + // เมื่อ selectedDate เปลี่ยน ให้ emit ออกไปเป็น v-model watch(selectedDate, (newVal) => { emits('update:modelValue', newVal); }); - -// (ตัวอย่าง) คุณอาจทำปุ่ม Back/Next ให้เปลี่ยนวันที่ได้จริง -// แต่ตอนนี้เป็นเพียง placeholder </script> <template> <v-col - cols="auto" - class="d-inline-flex align-center" - style="background-color: #7E9CD3; border-radius: 15px; max-width: fit-content; padding: 8px 16px;" -> + 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="selectedDate.value = '1/1/2024'" + @click="changeDate(-1)" > < Back </v-btn> @@ -41,7 +48,7 @@ watch(selectedDate, (newVal) => { <v-btn class="ml-2" style="background-color: #2B2E3F; color: white; border-radius: 10px;" - @click="selectedDate.value = '1/2/2024'" + @click="changeDate(1)" > Next > </v-btn> diff --git a/src/components/GanttChart/GanttChart.vue b/src/components/GanttChart/GanttChart.vue index 9be07e07b3125cf61d6b61cfc81ed4c09c2c80f2..2365234786d04452f45bcc798ea050e7fb386f42 100644 --- a/src/components/GanttChart/GanttChart.vue +++ b/src/components/GanttChart/GanttChart.vue @@ -9,11 +9,7 @@ <div class="header"> <div class="machine-label"></div> <div class="time-scale"> - <div - v-for="hour in hours" - :key="hour" - class="time-cell" - > + <div v-for="hour in hours" :key="hour" class="time-cell"> {{ formatHour(hour) }} </div> </div> @@ -49,68 +45,72 @@ :style="getQueueStyle(item)" > <!-- Handle สำหรับ Resize ด้านซ้าย --> - <div - class="resize-handle left" - @mousedown="onResizeStart($event, item, 'left')" - ></div> + <div class="resize-handle left" @mousedown="onResizeStart($event, item, 'left')"></div> <!-- ส่วนกลางของ Order ใช้สำหรับลาก และเปิด Dialog เมื่อคลิก --> - <div - class="order-content" - draggable="true" + <div class="order-content" draggable="true" @dragstart="onDragStart($event, item)" @dragend="onDragEnd($event, item)" - @click.stop="openQueueDialog(item)" - > + @click.stop="openQueueDialog(item)"> {{ item.orderID }} ({{ getTimeString(item.startTime) }} - {{ getTimeString(item.finishTime) }}) </div> <!-- Handle สำหรับ Resize ด้านขวา --> - <div - class="resize-handle right" - @mousedown="onResizeStart($event, item, 'right')" - ></div> + <div class="resize-handle right" @mousedown="onResizeStart($event, item, 'right')"></div> </div> </div> </div> </div> - <!-- Ghost Order ขณะลาก --> + <!-- Ghost Queue (ขณะลาก) --> <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> <!-- Pagination --> - <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)" - > - {{ p }} - <button - v-if="pageToShowDelete === p" - class="delete-btn" - @click.stop="deletePage(p)" - > - Delete + <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)"> + {{ p }} + <button v-if="pageToShowDelete === p" class="delete-btn" @click.stop="deletePage(p)"> + Delete + </button> + </button> + + <!-- ปุ่มเพิ่มหน้า + (แบบปกติ) --> + <button class="page-btn add-page" @click="addPage" :disabled="pages.length >= 10"> + + </button> - </button> - <button class="page-btn add-page" @click="addPage">+</button> + </div> + + <!-- ปุ่ม Add Queue อยู่ขวาสุด --> + <div class="pagination-right"> + <v-btn class="add-page-btn" @click="openAddQueueDialog" icon> + <v-icon>mdi-plus</v-icon> + </v-btn> + </div> + + <!-- AddQueueDialog (สำหรับเพิ่ม/แก้ไข) --> + <AddQueueDialog + :visible="showAddDialog" + :queueItem="selectedQueueItem" + @close="closeAddQueueDialog" + @add="handleAddQueue" + @edit="handleEditQueue" + /> </div> - <!-- Order Dialog --> + <!-- Order Dialog (สำหรับดูรายละเอียดเพิ่มเติม) --> <OrderDialog - v-if="selectedQueueItem" + v-if="selectedQueueItem && !showAddDialog" :queueItem="selectedQueueItem" :color="getQueueColor(selectedQueueItem.orderID)" @close="closeQueueDialog" - @edit="editQueueItem" + @edit="openAddQueueDialogForEdit" @delete="deleteQueueItem" /> </div> @@ -120,6 +120,7 @@ <script> import GanttCalendar from './GanttCalendar.vue'; import OrderDialog from './OrderDialog.vue'; +import AddQueueDialog from './AddQueueDialog.vue'; import './ganttChart.css'; export default { @@ -127,9 +128,11 @@ export default { components: { GanttCalendar, OrderDialog, + AddQueueDialog, }, data() { return { + showAddDialog: false, // ค่าจาก Calendar selectedDate: '1/1/2024', @@ -197,21 +200,21 @@ export default { machineID: 'MC5', orderID: 4, pageNumber: 1, - startTime: '2/1/2024 14:00', - finishTime: '2/1/2024 16:00', + startTime: '2/1/2024 8:00', + finishTime: '2/1/2024 12:00', status: 'Process', bottleSize: '600ml', producedQuantity: 500, }, ], - // จัดการการลาก, Resize + // Drag/Drop และ Resize draggingQueue: null, dragOffset: 0, resizingQueue: null, resizeDirection: null, - // Ghost Order (ขณะลาก) + // Ghost Queue (ขณะลาก) ghostQueue: null, ghostStyle: { position: 'fixed', @@ -222,7 +225,7 @@ export default { height: '40px', lineHeight: '40px', padding: '0 10px', - borderRadius: '20px', + borderRadius: '10px', pointerEvents: 'none', backgroundColor: '#4caf50', color: '#fff', @@ -247,20 +250,58 @@ export default { }, }, methods: { - // แปลงเลขชั่วโมงเป็น "HH:00" + // -------------------- Dialog & Edit -------------------- + openQueueDialog(item) { + this.selectedQueueItem = { ...item }; + }, + closeQueueDialog() { + this.selectedQueueItem = null; + }, + openAddQueueDialog() { + this.selectedQueueItem = null; + this.showAddDialog = true; + }, + deleteQueueItem(item) { + this.Queue = this.Queue.filter(q => q.queueID !== item.queueID); + this.closeQueueDialog(); + }, + openAddQueueDialogForEdit(queueItem) { + // เมื่อกด Edit ใน OrderDialog ให้เปิด AddQueueDialog ในโหมดแก้ไข + this.selectedQueueItem = { ...queueItem }; + this.showAddDialog = true; + }, + closeAddQueueDialog() { + this.showAddDialog = false; + this.selectedQueueItem = null; + }, + handleAddQueue(newQueueItem) { + // เพิ่ม newQueueItem ลงใน Queue + this.Queue.push({ + queueID: this.Queue.length + 1, // กำหนด queueID ใหม่ + ...newQueueItem, + }); + this.showAddDialog = false; + }, + handleEditQueue(updatedQueueItem) { + // หา index ของ queue ที่ต้องแก้ไข + const index = this.Queue.findIndex(q => q.queueID === updatedQueueItem.queueID); + if (index !== -1) { + this.Queue.splice(index, 1, { ...updatedQueueItem }); + } + this.selectedQueueItem = null; + this.showAddDialog = false; + }, + + // -------------------- Utility Functions -------------------- formatHour(hour) { return (hour < 10 ? '0' + hour : hour) + ':00'; }, - // แยก date ส่วนหน้า (1/1/2024) ออกจาก startTime/finishTime getDateString(dateTimeStr) { return dateTimeStr.split(' ')[0]; }, - // แยกเฉพาะส่วนเวลา (09:00) getTimeString(dateTimeStr) { return dateTimeStr.split(' ')[1]; }, - - // ฟิลเตอร์ Queue ตาม machineID, pageNumber, และ selectedDate filteredQueue(machineID) { return this.Queue.filter((q) => { const queueDate = this.getDateString(q.startTime); @@ -271,46 +312,40 @@ export default { ); }); }, - - // ฟังก์ชันเลือกสีจาก orderID getQueueColor(orderID) { - const colors = ['#F58181', '#FDDC5C', '#C5A1BC', '#49E060']; // 4 สีที่กำหนด - return colors[(orderID - 1) % colors.length]; // ใช้ modulo (%) เพื่อให้วนกลับไปที่สีแรกเมื่อเกิน 4 + const colors = ['#F58181', '#FDDC5C', '#C5A1BC', '#49E060']; + return colors[(orderID - 1) % colors.length]; }, - - // สไตล์ตำแหน่ง + สีของ 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); + 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); - const ratioStart = (startDecimal - timelineStart) / (timelineEnd - timelineStart); - const ratioEnd = (endDecimal - timelineStart) / (timelineEnd - timelineStart); + const ratioStart = (startDecimal - timelineStart) / (timelineEnd - timelineStart); + const ratioEnd = (endDecimal - timelineStart) / (timelineEnd - timelineStart); - 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', - }; - }, + return { + left: ratioStart * 100 + '%', + width: (ratioEnd - ratioStart) * 100 + '%', + backgroundColor: this.getQueueColor(item.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); const ratio = (hour - timelineStart) / (timelineEnd - timelineStart); - return { - left: ratio * 100 + '%', - }; + return { left: ratio * 100 + '%' }; }, timeToDecimal(timeStr) { const [hours, minutes] = timeStr.split(':').map(Number); @@ -322,19 +357,17 @@ export default { return (hours < 10 ? '0' + hours : hours) + ':' + (minutes < 10 ? '0' + minutes : minutes); }, - // ==================== Drag/Drop ==================== + // -------------------- Drag/Drop & Resize -------------------- onDragStart(event, item) { this.draggingQueue = item; const rect = event.target.getBoundingClientRect(); this.dragOffset = rect.width / 2; - // ปิด preview เริ่มต้นของ HTML5 Drag & Drop const emptyImg = document.createElement('img'); emptyImg.src = 'data:image/gif;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs='; event.dataTransfer.setDragImage(emptyImg, 0, 0); this.ghostQueue = { ...item }; this.ghostStyle.display = 'block'; - // ใช้สีเดียวกับ orderID this.ghostStyle.backgroundColor = this.getQueueColor(item.orderID); document.addEventListener('dragover', this.onDragOverGlobal); @@ -356,22 +389,18 @@ export default { const timelineStart = this.timeToDecimal(this.startTime); const timelineEnd = this.timeToDecimal(this.endTime); - - // คำนวณเวลาเริ่มใหม่ (เฉพาะส่วนเวลา) 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); newStartDecimal = Math.round(newStartDecimal * 2) / 2; - let newEndDecimal = newStartDecimal + duration; if (newEndDecimal > timelineEnd) { newEndDecimal = timelineEnd; newStartDecimal = newEndDecimal - duration; } - // สร้าง String ใหม่ "วัน/เดือน/ปี เวลา" const datePart = this.getDateString(this.draggingQueue.startTime); const newStartStr = datePart + ' ' + this.decimalToTime(newStartDecimal); const newEndStr = datePart + ' ' + this.decimalToTime(newEndDecimal); @@ -384,11 +413,9 @@ export default { const snappedRatioEnd = (newEndDecimal - timelineStart) / (timelineEnd - timelineStart); const snappedWidth = (snappedRatioEnd - snappedRatioStart) * timelineWidth; - // หาแถว (machine) ที่ใกล้ที่สุด const rows = document.querySelectorAll('.row'); let closestRow = null; let minDistance = Infinity; - rows.forEach((row) => { const rect = row.getBoundingClientRect(); const distance = Math.abs(event.clientY - rect.top); @@ -433,8 +460,6 @@ export default { this.ghostStyle.display = 'none'; this.draggingQueue = null; }, - - // ==================== Resize ==================== onResizeStart(event, item, direction) { event.preventDefault(); this.resizingQueue = item; @@ -455,14 +480,11 @@ export default { const timelineStart = this.timeToDecimal(this.startTime); const timelineEnd = this.timeToDecimal(this.endTime); - 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.resizingQueue.startTime); // ex: "1/1/2024" + const datePart = this.getDateString(this.resizingQueue.startTime); if (this.resizeDirection === 'left') { if (newTimeDecimal >= endDec) return; @@ -480,11 +502,13 @@ export default { document.removeEventListener('mousemove', this.onResizing); document.removeEventListener('mouseup', this.onResizeEnd); }, - - // ==================== Pagination ==================== addPage() { - const newPage = this.pages.length + 1; - this.pages.push(newPage); + if (this.pages.length < 10) { + const newPage = this.pages.length + 1; + this.pages.push(newPage); + } else { + alert("Maximum of 10 pages allowed."); + } }, onPageRightClick(page, event) { event.preventDefault(); @@ -505,23 +529,8 @@ export default { this.pageToShowDelete = null; } }, - - // ==================== Dialog ==================== - openQueueDialog(item) { - this.selectedQueueItem = { ...item }; - }, - closeQueueDialog() { - this.selectedQueueItem = null; - }, - editQueueItem(item) { - alert('Edit functionality not implemented yet.\nOrder ID: ' + item.orderID); - }, - 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 657714692fbea7cbf1b6e29908e974f286534b7e..0044b7716b06c52cb5bda106f1e14e8d63f1eba9 100644 --- a/src/components/GanttChart/OrderDialog.vue +++ b/src/components/GanttChart/OrderDialog.vue @@ -7,9 +7,11 @@ <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> @@ -17,14 +19,16 @@ </div> <div class="order-details"> <p><strong>เป่าขวดจำนวน</strong> {{ queueItem.producedQuantity }} ขวด</p> + <p><strong>ขนาดขวด</strong> {{ queueItem.bottleSize }}</p> <p><strong>ตั้งแต่เวลา</strong> {{ queueItem.startTime }} - {{ queueItem.finishTime }}</p> </div> <div class="order-assignments"> <div class="machine"> - <span class="icon">🛠</span> {{ queueItem.machineID }} + <span >🛠</span> {{ queueItem.machineID }} </div> + <!-- พนักงาน --> <div class="employees" v-for="(employee, index) in queueItem.employees" :key="index"> - <span class="icon">👤</span> {{ employee }} + <span >👤</span> {{ employee }} </div> </div> </div> @@ -81,6 +85,7 @@ export default { font-size: 1.2rem; font-weight: bold; text-align: left; + color: white; /* เปลี่ยนเป็นสีขาว */ } .dialog-buttons { @@ -93,6 +98,7 @@ export default { border: none; cursor: pointer; font-size: 18px; + color: white; /* เปลี่ยนเป็นสีขาว */ } .order-details { @@ -107,7 +113,8 @@ export default { margin-top: 10px; } -.machine, .employees { +.machine, +.employees { background: white; padding: 5px; border-radius: 5px; @@ -119,5 +126,6 @@ export default { .icon { font-size: 1rem; + color: white; /* เปลี่ยนไอคอนเป็นสีขาว */ } </style> diff --git a/src/components/GanttChart/ganttChart.css b/src/components/GanttChart/ganttChart.css index b290d1e7bd20fd4c2e1fc9ffbf99d5027cb7674f..0612494eefa796ae263db1358a9ffc9d38c7daee 100644 --- a/src/components/GanttChart/ganttChart.css +++ b/src/components/GanttChart/ganttChart.css @@ -107,15 +107,23 @@ pointer-events: none; } - .pagination { + .pagination-container { display: flex; - justify-content: flex-start; + justify-content: space-between; align-items: center; - gap: 5px; width: 100%; - margin-top: 10px; } + .pagination { + display: flex; + gap: 10px; + } + + .pagination-right { + margin-left: auto; /* ดันไปขวาสุด */ + } + + .page-btn { background: #ffffff; border: 1px solid #ffffff; @@ -172,4 +180,25 @@ .dialog-buttons button { margin: 5px; } + .add-page-btn { + background-color: #2B2E3F !important; /* สีปุ่ม */ + color: white !important; /* สีไอคอน */ + border-radius: 50%; /* ทำให้เป็นวงกลม */ + width: 40px; + height: 40px; + display: flex; + align-items: center; + justify-content: center; + box-shadow: 0px 4px 6px rgba(0, 0, 0, 0.2); + transition: 0.2s; + } + + .add-page-btn:hover { + background-color: #1E1E2F !important; /* สีเข้มขึ้นเมื่อ hover */ + } + .add-page:disabled { + background-color: #ccc !important; /* เปลี่ยนสีเป็นสีจาง */ + cursor: not-allowed; + } + \ No newline at end of file