Gitlab@Informatics

Skip to content
Snippets Groups Projects
Commit 70653915 authored by Kritkhanin Anantakul's avatar Kritkhanin Anantakul
Browse files

fix targettable

parent 238f40c9
No related branches found
No related tags found
No related merge requests found
......@@ -2,20 +2,18 @@
import { ref, onMounted, computed } from 'vue'
import { useProductionTargetStore } from '@/stores/productionTarget'
import { usePageContextStore } from '@/stores/pageContext'
// ⬇️ ใช้ dateStore แทน props
import { useDateStore } from '@/stores/dateStore'
import { storeToRefs } from 'pinia'
const productionTargetStore = useProductionTargetStore()
const pageContext = usePageContextStore()
const { currentDate: selectedDate } = storeToRefs(useDateStore()) // ✅ ใช้จาก store
const { currentDate: selectedDate } = storeToRefs(useDateStore())
const currentPage = computed(() => pageContext.currentPage)
const headers = ref([
{ title: "รหัส", key: "id" },
{ title: "ชื่อ", key: "name" },
{ title: "ชื่อ", key: "name" },
{ title: "ขนาด", key: "size" },
{ title: "แบรนด์", key: "brand" },
{ title: "ชนิด", key: "type" },
......@@ -29,12 +27,15 @@ const groupBy = [{ key: 'customerGroup' }]
const savingRowIds = ref<number[]>([])
const recentlySavedIds = ref<number[]>([])
// ตั้งค่า delay (ms) หลังจากเรียก edit function ก่อน re-fetch data
const UPDATE_DELAY = 500
onMounted(async () => {
await productionTargetStore.fetchProductionTargets()
})
// ✅ กรองตาม PageID + selectedDate จาก store
const productionData = computed(() => {
// map rawData ให้มี field ที่จำเป็นสำหรับ UI และ API
const rawData = productionTargetStore.productionTargets
.filter((target) =>
target.page?.PageID === currentPage.value &&
......@@ -44,6 +45,10 @@ const productionData = computed(() => {
const customerName = target.order?.customer?.name || 'ไม่ระบุลูกค้า'
return {
id: target.ProductionTargetID,
// เปลี่ยน field จาก target.item?.ItemID เป็น target.item?.id
// ให้แน่ใจว่าฟิลด์นี้ตรงกับ structure ที่ backend ส่งมา
itemID: target.item?.id,
itemType: target.itemType,
name: target.item?.name || target.item?.brand || 'ไม่พบข้อมูล',
size: target.item?.size || '-',
brand: target.item?.brand || '-',
......@@ -57,11 +62,13 @@ const productionData = computed(() => {
}
})
// 🔄 รวมรายการซ้ำในกลุ่ม "วันนี้"
const todayGroupMap = new Map<string, any>()
console.log('✅ rawData:', rawData)
// รวมรายการซ้ำในกลุ่ม "วันนี้"
const todayGroupMap = new Map<string, any>()
rawData.forEach(item => {
const key = `${item.name}|${item.size}|${item.brand}|${item.type}`
// key รวม itemID เพื่อให้แน่ใจว่า itemID ไม่หาย
const key = `${item.itemID}|${item.name}|${item.size}|${item.brand}|${item.type}`
if (todayGroupMap.has(key)) {
const existing = todayGroupMap.get(key)
existing.target += item.target
......@@ -69,14 +76,18 @@ const productionData = computed(() => {
} else {
todayGroupMap.set(key, {
...item,
customerGroup: '0-รวมทั้งหมด', // กลุ่ม "วันนี้"
// force ให้แน่ใจว่า itemID กับ itemType ถูกเก็บไว้
itemID: item.itemID,
itemType: item.itemType,
customerGroup: '0-รวมทั้งหมด',
})
}
})
const todayItems = Array.from(todayGroupMap.values())
console.log('✅ todayItems:', todayItems)
// กลุ่มรายลูกค้า (ไม่ยุบ)
// กลุ่มรายลูกค้า (ไม่รวมกัน)
const customerItems = rawData.map(item => ({
...item,
customerGroup: `1-${item.customer}`,
......@@ -85,10 +96,6 @@ const productionData = computed(() => {
return [...todayItems, ...customerItems]
})
async function saveActualProduced(item: any) {
const id = item.id
const produced = Number(item.produced)
......@@ -98,22 +105,34 @@ async function saveActualProduced(item: any) {
savingRowIds.value.push(id)
try {
await productionTargetStore.editProductionTarget(id, {
ActualProduced: produced,
})
await productionTargetStore.fetchProductionTargets()
if (item.customerGroup?.startsWith('0-')) {
await productionTargetStore.editTodayTarget({
itemID: item.itemID,
itemType: item.itemType,
date: selectedDate.value.split('-').reverse().join('/'),
actualProduced: produced,
})
// ✅ optional: อาจต้อง fetch ใหม่ เพราะรวม target หลายรายการ
await productionTargetStore.fetchProductionTargets()
} else {
await productionTargetStore.editProductionTarget(id, {
ActualProduced: produced,
})
// ❌ ไม่ต้อง fetch
}
recentlySavedIds.value.push(id)
setTimeout(() => {
recentlySavedIds.value = recentlySavedIds.value.filter(rowId => rowId !== id)
recentlySavedIds.value = recentlySavedIds.value.filter((rowId) => rowId !== id)
}, 1000)
} catch (e) {
console.error('❌ Save failed:', e)
} finally {
savingRowIds.value = savingRowIds.value.filter(rowId => rowId !== id)
savingRowIds.value = savingRowIds.value.filter((rowId) => rowId !== id)
}
}
function blockInvalidKeys(event: KeyboardEvent) {
const invalidKeys = ['e', 'E', '+', '-', '.', ',']
if (invalidKeys.includes(event.key)) {
......@@ -132,25 +151,24 @@ function blockInvalidKeys(event: KeyboardEvent) {
item-value="name"
hide-default-footer
>
<template v-slot:group-header="{ item, columns, toggleGroup, isGroupOpen }">
<tr>
<td :colspan="columns.length">
<div class="d-flex align-center">
<v-btn
:icon="isGroupOpen(item) ? '$expand' : '$next'"
density="comfortable"
size="x-small"
variant="outlined"
@click="toggleGroup(item)"
/>
<span class="ms-2 text-caption">
{{ item.value.startsWith('0-') ? 'วันนี้' : 'ลูกค้า: ' + item.value.slice(2) }}
</span>
</div>
</td>
</tr>
</template>
<template v-slot:group-header="{ item, columns, toggleGroup, isGroupOpen }">
<tr>
<td :colspan="columns.length">
<div class="d-flex align-center">
<v-btn
:icon="isGroupOpen(item) ? '$expand' : '$next'"
density="comfortable"
size="x-small"
variant="outlined"
@click="toggleGroup(item)"
/>
<span class="ms-2 text-caption">
{{ item.value.startsWith('0-') ? 'วันนี้' : 'ลูกค้า: ' + item.value.slice(2) }}
</span>
</div>
</td>
</tr>
</template>
<template v-slot:item.produced="{ item }">
<div class="save-cell-wrapper" style="position: relative; display: inline-block;">
......@@ -190,10 +208,19 @@ function blockInvalidKeys(event: KeyboardEvent) {
.fade-check {
animation: fadeOut 1s ease-out forwards;
}
@keyframes fadeOut {
0% { opacity: 1; transform: scale(1); }
80% { opacity: 1; transform: scale(1.2); }
100% { opacity: 0; transform: scale(1); }
0% {
opacity: 1;
transform: scale(1);
}
80% {
opacity: 1;
transform: scale(1.2);
}
100% {
opacity: 0;
transform: scale(1);
}
}
</style>
......@@ -29,3 +29,10 @@ export async function updateProductionTarget(
export async function deleteProductionTarget(id: number): Promise<void> {
await http.delete(`/production-targets/${id}`);
}
export async function editTodayTarget(payload: {
ProductionTargetID: number;
ActualProduced: number;
}): Promise<void> {
await http.post('/production-targets/edit-today', payload);
}
\ No newline at end of file
......@@ -53,7 +53,11 @@ export const useProductionTargetStore = defineStore('productionTarget', () => {
const updated = await productionTargetService.updateProductionTarget(id, payload);
const index = productionTargets.value.findIndex(p => p.ProductionTargetID === id);
if (index !== -1) {
productionTargets.value[index] = updated;
// ✅ อัปเดตค่าจริงใน local state เพื่อให้ computed re-render
productionTargets.value[index] = {
...productionTargets.value[index],
...payload, // ใช้ payload (เช่น ActualProduced) ทับของเดิม
};
}
} catch (e: any) {
error.value = e.message || 'Unknown Error';
......@@ -61,6 +65,21 @@ export const useProductionTargetStore = defineStore('productionTarget', () => {
loading.value = false;
}
}
async function editTodayTarget(payload: { ProductionTargetID: number, ActualProduced: number }) {
loading.value = true;
error.value = null;
try {
await productionTargetService.editTodayTarget(payload);
} catch (e: any) {
error.value = e.message || 'Unknown Error';
throw e; // เพื่อให้ caller เช่นหน้า UI จับ error ได้
} finally {
loading.value = false;
}
}
async function removeProductionTarget(id: number) {
loading.value = true;
......@@ -82,6 +101,7 @@ export const useProductionTargetStore = defineStore('productionTarget', () => {
fetchProductionTargets,
fetchProductionTarget,
addProductionTarget,
editTodayTarget,
editProductionTarget,
removeProductionTarget,
};
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment