From df2ec7e88cc987ab7cd5b6ad5a7f740da51a450d Mon Sep 17 00:00:00 2001 From: ArifHilmi Date: Thu, 27 Feb 2025 16:32:32 +0800 Subject: [PATCH] update movement user view only --- .../ItemMovement/ItemMovementUser.cshtml | 537 +++++++++++------- .../Views/ItemMovement/ItemRequest.cshtml | 5 +- .../Views/ItemMovement/QrUser.cshtml | 23 +- .../Views/ItemMovement/UserDashboard.cshtml | 6 +- Controllers/API/Inventory/InvMainAPI.cs | 24 + ...f-5d63-4a96-9531-702bd56af1d89_Request.jpg | Bin 0 -> 2163779 bytes 6 files changed, 373 insertions(+), 222 deletions(-) create mode 100644 wwwroot/Media/Inventory/request/0_40d7022f-5d63-4a96-9531-702bd56af1d89_Request.jpg diff --git a/Areas/Inventory/Views/ItemMovement/ItemMovementUser.cshtml b/Areas/Inventory/Views/ItemMovement/ItemMovementUser.cshtml index 4357a51..a76270b 100644 --- a/Areas/Inventory/Views/ItemMovement/ItemMovementUser.cshtml +++ b/Areas/Inventory/Views/ItemMovement/ItemMovementUser.cshtml @@ -33,44 +33,15 @@ color: orange; /* Warna oren untuk 'Return' */ } - .fixed-label { - margin-left:100px; - font-weight: bold; - min-width: 120px; /* Ensure labels have same width */ - } - - .fixed-labelStatus { - margin-left: 25px; - font-weight: bold; - min-width: 20px; /* Ensure labels have same width */ - } - .fixed-value { - min-width: 150px; - margin-right:-20px; - display: inline-block; - } - - .gap-4 { - gap: 30px; /* Increase spacing between Send Date and Receive Date */ - } - - .gap-2 { - gap: 1rem !important; /* Ensure Status is closer to its value */ - } - - .me-5 { - margin-right: 2rem !important; /* Move Receive/Return further from Send Date */ - } - .ms-auto { margin-left: auto !important; /* Push Complete/Incomplete to right */ } -@await Html.PartialAsync("~/Areas/Inventory/Views/_InventoryPartialUser.cshtml"); +@await Html.PartialAsync("~/Areas/Inventory/Views/_InventoryPartialUser.cshtml")
-

Sort by:

+

Sort by:

+ +
+

Search Item:

+
+ +
+
+
@@ -99,76 +78,175 @@
-
-
-

Item Name: {{ group.productName }}

+
+
+

Item : {{ group.uniqueID }}

+
-
-
-
-
-

+ +
+
+ + +
+
+ +

{{ movement.toOther === 'On Delivery' ? 'Receive' : 'Return' }}

-
-

Send Date:

+ +
+

Send Date:

{{ movement.sendDate }}
-
-

Receive Date:

+ +
+

Receive Date:

{{ movement.receiveDate || 'Not arrive' }}
-
-

Action:

- {{ movement.action}} + +
+

Action:

+ {{ movement.action }}
-
-

Status:

+ +
+

Status:

{{ movement.latestStatus || movement.toOther }}
- + + -

+ +

{{ movement.movementComplete == 1 ? 'Complete' : 'Incomplete' }}

-
- -
-
-
- -

Information: {{ movement.toOther }}

-

User: {{ movement.toUserName }}

-

Station: {{ movement.toStationName }}

-

Store: {{ movement.toStoreName }}

-
-
- -

{{ movement.latestStatus || movement.toOther }}

-
-
- -

Information: {{ movement.latestStatus }}

-

User: {{ movement.lastUserName }}

-

Station: {{ movement.lastStationName }}

-

Store: {{ movement.lastStoreName }}

+ + +
+
+
+ +

Start

+

User: {{ movement.toUserName }}

+

Station: {{ movement.toStationName }}

+

Store: {{ movement.toStoreName }}

+
+
+

+ +

{{ movement.latestStatus || movement.toOther }}

+
+
+ +

End {{ movement.latestStatus }}

+

User: {{ movement.lastUserName }}

+

Station: {{ movement.lastStationName }}

+

Store: {{ movement.lastStoreName }}

+
-
+ + + + +
+
+
+ +

+ {{ movement.toOther === 'On Delivery' ? 'Receive' : 'Return' }} +

+ + +
+

Send Date:

+ {{ movement.sendDate }} +
+ + +
+

Receive Date:

+ {{ movement.receiveDate || 'Not arrive' }} +
+ + +
+

Action:

+ {{ movement.action }} +
+ + +
+

Status:

+ {{ movement.latestStatus || movement.toOther }} +
+ + + + + +

+ {{ movement.movementComplete == 1 ? 'Complete' : 'Incomplete' }} +

+
+ + + +
+
+
+ +

Start

+

User: {{ movement.toUserName }}

+

Station: {{ movement.toStationName }}

+

Store: {{ movement.toStoreName }}

+
+
+

+ +

{{ movement.latestStatus || movement.toOther }}

+
+
+ +

End

+

User: {{ movement.lastUserName }}

+

Station: {{ movement.lastStationName }}

+

Store: {{ movement.lastStoreName }}

+
+
+
+
+
+
+
+
@section Scripts { @@ -179,155 +257,194 @@ $(function () { app.mount('#ItemMovement'); }); - const app = Vue.createApp({ - data() { - return { - itemMovements: [], - itemMovementCompleteDatatable : null, - itemMovementNotCompleteDatatable : null, - itemDatatables: {}, // Store tables by ItemId - sortBy: 'all', // Sorting option - } - }, - mounted() { - console.log("Vue app mounted!"); - this.fetchItemMovement(); - }, - methods: { - getGroupedByItem() { - return this.itemMovements.reduce((acc, movement) => { - if (!acc[movement.itemId]) { - acc[movement.itemId] = { - productName: movement.productName, - movements: [] - }; - } - acc[movement.itemId].movements.push(movement); // Jangan reset showDetails - return acc; - }, {}); + const app = Vue.createApp({ + data() { + return { + itemMovements: [], + itemMovementCompleteDatatable: null, + itemMovementNotCompleteDatatable: null, + searchQuery: "", + sortBy: "all", + historyVisible: {}, + detailsVisible: {}, + categoryVisible: {}, + }; }, - async fetchItemMovement() { - try { - const response = await fetch('/InvMainAPI/ItemMovementUser', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', + computed: { + groupedItems() { + return this.itemMovements.reduce((acc, movement) => { + if (!acc[movement.itemId]) { + acc[movement.itemId] = { + uniqueID: movement.uniqueID, + movements: [], + }; } - }); - - if (!response.ok) { - throw new Error('Failed to fetch item movement'); + acc[movement.itemId].movements.push(movement); + return acc; + }, {}); + }, + filteredItems() { + if (!this.searchQuery.trim()) { + return this.groupedItems; } - const data = await response.json(); + const searchLower = this.searchQuery.toLowerCase(); + return Object.fromEntries( + Object.entries(this.groupedItems).filter(([_, group]) => + group.uniqueID.toLowerCase().includes(searchLower) + ) + ); + }, + }, + mounted() { + console.log("Vue app mounted!"); + this.fetchItemMovement(); + }, + methods: { + async fetchItemMovement() { + try { + const response = await fetch("/InvMainAPI/ItemMovementUser", { + method: "POST", + headers: { "Content-Type": "application/json" }, + }); - // Ensure showDetails is reactive - this.itemMovements = data.map(movement => ({ - ...movement, - showDetails: false - })); + if (!response.ok) throw new Error("Failed to fetch item movement"); + const data = await response.json(); + this.itemMovements = data.map((movement) => ({ + ...movement, + showDetails: false, + })); + + this.renderTables(); + } catch (error) { + console.error("Error fetching item:", error); + } + }, + + renderTables() { + if (this.sortBy === "all") { + this.initAllTables(); + } + }, + initAllTables() { if (this.itemMovementNotCompleteDatatable) { - this.itemMovementNotCompleteDatatable.clear().destroy(); + this.itemMovementNotCompleteDatatable.destroy(); } if (this.itemMovementCompleteDatatable) { - this.itemMovementCompleteDatatable.clear().destroy(); + this.itemMovementCompleteDatatable.destroy(); } - this.$forceUpdate(); + + this.itemMovementNotCompleteDatatable = $("#itemMovementNotCompleteDatatable").DataTable({ + data: this.itemMovements.filter((m) => m.movementComplete == 0), + columns: [ + { title: "Unique Id", data: "id" }, + { title: "Product Code", data: "uniqueID" }, + { title: "From User", data: "toUserName" }, + { title: "Last User", data: "lastUserName" }, + { title: "From Station", data: "toStationName" }, + { title: "From Store", data: "toStoreName" }, + { title: "Action", data: "action" }, + { title: "Start Status", data: "toOther" }, + { title: "Quantity", data: "quantity" }, + { title: "Send Date", data: "sendDate" }, + { + title: "Note", + data: "consignmentNote", + render: function (data, type, full, meta) { + if (!data) { + return "No Document"; + } + + // Check if the document is an image based on file extension + var isImage = /\.(jpeg|jpg|png|gif)$/i.test(data); + var isPdf = /\.pdf$/i.test(data); + + if (isImage) { + return ` + Image + `; + } + else if (isPdf) { + return ` + PDF Document +
View PDF +
`; + } else { + return `Download File`; + } + }, + }, + { title: "Remark", data: "remark" }, + ], + responsive: true, + }); + + this.itemMovementCompleteDatatable = $("#itemMovementCompleteDatatable").DataTable({ + data: this.itemMovements.filter((m) => m.movementComplete == 1), + columns: [ + { title: "Unique Id", data: "id" }, + { title: "Product Code", data: "uniqueID" }, + { title: "From User", data: "toUserName" }, + { title: "Last User", data: "lastUserName" }, + { title: "From Station", data: "toStationName" }, + { title: "Last Station", data: "lastStationName" }, + { title: "From Store", data: "toStoreName" }, + { title: "Last Store", data: "lastStoreName" }, + { title: "Action", data: "action" }, + { title: "Start Status", data: "toOther" }, + { title: "Latest Status", data: "latestStatus" }, + { title: "Qty", data: "quantity" }, + { title: "Send Date", data: "sendDate" }, + { title: "Receive Date", data: "receiveDate" }, + { title: "Note", + data: "consignmentNote", + render: function (data, type, full, meta) { + if (!data) { + return "No Document"; + } + + // Check if the document is an image based on file extension + var isImage = /\.(jpeg|jpg|png|gif)$/i.test(data); + var isPdf = /\.pdf$/i.test(data); + + if (isImage) { + return ` + Image + `; + } + else if (isPdf) { + return ` + PDF Document +
View PDF +
`; + } else { + return `Download File`; + } + }, + }, + { title: "Remark", data: "remark" }, + ], + responsive: true, + }); + }, + toggleCategory(itemId) { + this.categoryVisible[itemId] = !this.categoryVisible[itemId]; + }, + toggleHistory(itemId) { + this.historyVisible[itemId] = !this.historyVisible[itemId]; + }, + toggleDetails(movementId) { + this.detailsVisible[movementId] = !this.detailsVisible[movementId]; + }, + handleSorting() { this.renderTables(); - } - catch (error) { - console.error('Error fetching item:', error); - } + }, }, + }); - renderTables() { - if (this.sortBy === 'all') { - this.initAllTables(); - } - }, - - initAllTables() { - if (this.itemMovementNotCompleteDatatable) { - this.itemMovementNotCompleteDatatable.clear().destroy(); - } - if (this.itemMovementCompleteDatatable) { - this.itemMovementCompleteDatatable.clear().destroy(); - } - self = this; - this.itemMovementNotCompleteDatatable = $('#itemMovementNotCompleteDatatable').DataTable({ - "data": this.itemMovements.filter(movement => movement.movementComplete == 0), - "columns": [ - { - "title": "Unique Id", - "data": "id", - "createdCell": function (td, cellData, rowData, row, col) { - // Assign a unique ID to the element - $(td).attr('id', `qr${cellData}`); - }, - }, - { title: "From User", data: "toUserName" }, - { title: "Last User", data: "lastUserName" }, - { title: "From Station", data: "toStationName" }, - { title: "From Store", data: "toStoreName" }, - { title: "Action", data: "action" }, - { title: "Start Status", data: "toOther" }, - { title: "Quantity", data: "quantity" }, - { title: "Send Date", data: "sendDate" }, - { title: "Note", data: "consignmentNote" }, - { title: "Remark", data: "remark" }, - ], - responsive: true, - }); - - this.itemMovementCompleteDatatable = $('#itemMovementCompleteDatatable').DataTable({ - "data": this.itemMovements.filter(movement => movement.movementComplete == 1), - "columns": [ - { - "title": "Unique Id", - "data": "id", - "createdCell": function (td, cellData, rowData, row, col) { - // Assign a unique ID to the element - $(td).attr('id', `qr${cellData}`); - }, - }, - { "title": "From User", "data": "toUserName" }, - { "title": "Last User", "data": "lastUserName" }, - { "title": "From Station", "data": "toStationName" }, - { "title": "Last Station", "data": "lastStationName" }, - { "title": "From Store", "data": "toStoreName" }, - { "title": "Last Store", "data": "lastStoreName" }, - { "title": "Action", "data": "action" }, - { "title": "Start Status", "data": "toOther" }, - { "title": "Latest Status", "data": "latestStatus" }, - { "title": "Qty", "data": "quantity" }, - { "title": "Send Date", "data": "sendDate" }, - { "title": "Receive Date", "data": "receiveDate" }, - { "title": "Note", "data": "consignmentNote" }, - { "title": "Remark", "data": "remark" }, - ], - responsive: true, - }); - this.loading = false; - }, - - toggleDetails(id) { - const movement = this.itemMovements.find(mov => mov.id === id); - if (movement) { - movement.showDetails = !movement.showDetails; // Toggle value - } - }, - - - resetForm() { - this.itemMovement = ''; - }, - - handleSorting() { - this.$nextTick(() => this.fetchItemMovement()); - }, - - - }, - }); } \ No newline at end of file diff --git a/Areas/Inventory/Views/ItemMovement/ItemRequest.cshtml b/Areas/Inventory/Views/ItemMovement/ItemRequest.cshtml index a9823df..7ae780d 100644 --- a/Areas/Inventory/Views/ItemMovement/ItemRequest.cshtml +++ b/Areas/Inventory/Views/ItemMovement/ItemRequest.cshtml @@ -3,7 +3,7 @@ ViewData["Title"] = "Product Request"; Layout = "~/Views/Shared/_Layout.cshtml"; } -@await Html.PartialAsync("~/Areas/Inventory/Views/_InventoryPartialUser.cshtml"); +@await Html.PartialAsync("~/Areas/Inventory/Views/_InventoryPartialUser.cshtml")
@@ -576,14 +576,11 @@ this.productName = null; this.productCategory = null; - this.stations = []; this.selectedProduct = ""; this.selectedStation = ""; this.selectedCategory = ""; this.showRequestModal = false; this.loading = false; - this.product = []; - this.request = []; this.currentUser = null; }, diff --git a/Areas/Inventory/Views/ItemMovement/QrUser.cshtml b/Areas/Inventory/Views/ItemMovement/QrUser.cshtml index 1e66044..fd32e6d 100644 --- a/Areas/Inventory/Views/ItemMovement/QrUser.cshtml +++ b/Areas/Inventory/Views/ItemMovement/QrUser.cshtml @@ -18,7 +18,7 @@ -@await Html.PartialAsync("~/Areas/Inventory/Views/_InventoryPartialUser.cshtml"); +@await Html.PartialAsync("~/Areas/Inventory/Views/_InventoryPartialUser.cshtml")
@@ -242,7 +242,7 @@
- +
@@ -295,7 +295,7 @@
- +
@@ -361,6 +361,19 @@ this.startScanner(); }, methods: { + handleFileUpload(event) { + const file = event.target.files[0]; + + if (file) { + const reader = new FileReader(); + reader.onload = (e) => { + this.consignmentNote = e.target.result.split(',')[1]; // Get Base64 string (remove metadata) + }; + reader.readAsDataURL(file); + } else { + this.consignmentNote = null; + } + }, async updateItemMovement() { const requiredFields = ['selectedStation']; @@ -507,9 +520,9 @@ if (response.ok) { this.thisItem = await response.json(); - if (this.thisItem.movementId != null && this.thisItem.toOther === "On Delivery" && this.thisItem.latestStatus == null && this.thisItem.currentUserId == this.currentUserId) { + if (this.thisItem.movementId != null && this.thisItem.toOther === "On Delivery" && this.thisItem.latestStatus == null && this.thisItem.currentUserId == this.currentUserId && this.movementComplete == 0) { this.displayStatus = "arrived"; - } else if (this.thisItem.movementId != null && this.thisItem.toOther === "On Delivery" && this.thisItem.latestStatus != null && this.thisItem.currentUserId == this.currentUserId) { + } else if (this.thisItem.movementId != null && this.thisItem.toOther === "On Delivery" && this.thisItem.latestStatus != null && this.thisItem.currentUserId == this.currentUserId && this.thisItem.latestStatus != "Ready To Deploy") { this.displayStatus = "return"; } else if (this.thisItem.movementId != null && this.thisItem.toOther === "Return" && this.thisItem.latestStatus == null && this.thisItem.toUser == this.currentUserId) { this.displayStatus = "requestAgain"; diff --git a/Areas/Inventory/Views/ItemMovement/UserDashboard.cshtml b/Areas/Inventory/Views/ItemMovement/UserDashboard.cshtml index 9f400f4..3dad08d 100644 --- a/Areas/Inventory/Views/ItemMovement/UserDashboard.cshtml +++ b/Areas/Inventory/Views/ItemMovement/UserDashboard.cshtml @@ -13,9 +13,9 @@ @await Html.PartialAsync("~/Areas/Inventory/Views/_InventoryPartialUser.cshtml")
@section Scripts { -@{ - await Html.RenderPartialAsync("_ValidationScriptsPartial"); -} + @{ + await Html.RenderPartialAsync("_ValidationScriptsPartial"); + }