From d6d151a3c76b98316f0c41fe31306b3b35f853b5 Mon Sep 17 00:00:00 2001 From: ArifHilmi Date: Thu, 20 Mar 2025 15:46:52 +0800 Subject: [PATCH] Update & Fix Eerror --- .../Pages/Account/ForgotPassword.cshtml | 1 - .../Account/ForgotPasswordConfirmation.cshtml | 1 - .../Views/InventoryMaster/ItemMovement.cshtml | 370 ++++++++++++------ .../ProductRegistration.cshtml | 2 +- .../ItemMovement/ItemMovementUser.cshtml | 258 +++++++++++- .../Views/ItemMovement/ItemRequest.cshtml | 4 +- .../Inventory/Views/_InventoryPartial.cshtml | 2 +- Controllers/API/IdentityAPI.cs | 39 -- Controllers/API/Inventory/InvMainAPI.cs | 2 + Views/Home/Index2.cshtml | 2 +- Views/Shared/_Layout.cshtml | 4 +- 11 files changed, 501 insertions(+), 184 deletions(-) diff --git a/Areas/Identity/Pages/Account/ForgotPassword.cshtml b/Areas/Identity/Pages/Account/ForgotPassword.cshtml index 106b8d1..a2c92c4 100644 --- a/Areas/Identity/Pages/Account/ForgotPassword.cshtml +++ b/Areas/Identity/Pages/Account/ForgotPassword.cshtml @@ -4,7 +4,6 @@ ViewData["Title"] = "Forgot your password?"; } -

@ViewData["Title"]

Enter your email.


diff --git a/Areas/Identity/Pages/Account/ForgotPasswordConfirmation.cshtml b/Areas/Identity/Pages/Account/ForgotPasswordConfirmation.cshtml index 4f5ae99..a9c6d11 100644 --- a/Areas/Identity/Pages/Account/ForgotPasswordConfirmation.cshtml +++ b/Areas/Identity/Pages/Account/ForgotPasswordConfirmation.cshtml @@ -4,7 +4,6 @@ ViewData["Title"] = "Forgot password confirmation"; } -

@ViewData["Title"]

Please check your email to reset your password.

diff --git a/Areas/Inventory/Views/InventoryMaster/ItemMovement.cshtml b/Areas/Inventory/Views/InventoryMaster/ItemMovement.cshtml index 7a79775..cbd88c9 100644 --- a/Areas/Inventory/Views/InventoryMaster/ItemMovement.cshtml +++ b/Areas/Inventory/Views/InventoryMaster/ItemMovement.cshtml @@ -44,10 +44,57 @@ color: purple; } - .ms-auto { margin-left: auto !important; /* Push Complete/Incomplete to right */ } + + .dropdown { + position: relative; + width: 100%; + } + + .dropdown-toggle-box { + display: flex; + align-items: center; + border: 1px solid #ddd; + border-radius: 5px; + overflow: hidden; + } + + .dropdown-toggle-box input { + flex: 1; + border: none; + padding: 8px; + } + + .dropdown-btn { + border: none; + background-color: #007bff; + color: white; + padding: 8px 12px; + cursor: pointer; + } + + .dropdown-content { + position: absolute; + width: 100%; + max-height: 200px; + overflow-y: auto; + background: #fff; + border: 1px solid #ddd; + z-index: 10; + } + + .dropdown-content option { + padding: 10px; + cursor: pointer; + display: block; + } + + .dropdown-content option:hover { + background-color: #f1f1f1; + } + @await Html.PartialAsync("~/Areas/Inventory/Views/_InventoryPartial.cshtml")
@@ -73,14 +120,31 @@

Search Station:

- +
-

Pending Item Movement

+

Pending Item Transit

@@ -96,6 +160,9 @@

Complete Item Movement

+
+

All Item Movement

+
@@ -104,6 +171,18 @@
+
+

Assign Station

+
+
+
+
+ Loading... +
+
+
+
@@ -130,7 +209,7 @@ Loading...
-
+
@*

Item : {{ group.uniqueID }}

*@

Item : {{ group.uniqueID }}

@@ -159,13 +238,13 @@ -
-

{{movement.action === 'Assign' ? 'Assign Date' : 'Send Date'}}

- {{ movement.sendDate }} +
+

{{movement.action === 'Assign' ? 'Assign Date' : movement.action === 'Register' ? 'Register Date' : 'Send Date'}}

+ {{movement.action !== 'Register' ? movement.sendDate : movement.date }}
-
+

Receive Date:

{{ movement.receiveDate || 'Not arrive' }}
@@ -260,13 +339,13 @@ -
-

{{movement.action === 'Assign' ? 'Assign Date' : 'Send Date'}}

- {{ movement.sendDate }} +
+

{{movement.action === 'Assign' ? 'Assign Date' : movement.action === 'Register' ? 'Register Date' : 'Send Date'}}

+ {{movement.action !== 'Register' ? movement.sendDate : movement.date }}
-
+

Receive Date:

{{ movement.receiveDate || 'Not arrive' }}
@@ -347,11 +426,9 @@
- -
-
@@ -363,7 +440,7 @@
-
+
@*

Item : {{ group.uniqueID }}

*@ @@ -390,14 +467,14 @@ - -
-

{{movement.action === 'Assign' ? 'Assign Date' : 'Send Date'}}

- {{ movement.sendDate }} + +
+

{{movement.action === 'Assign' ? 'Assign Date' : movement.action === 'Register' ? 'Register Date' : 'Send Date'}}

+ {{movement.action !== 'Register' ? movement.sendDate : movement.date }}
-
+

Receive Date:

{{ movement.receiveDate || 'Not arrive' }}
@@ -484,14 +561,14 @@ - -
-

{{movement.action === 'Assign' ? 'Assign Date' : 'Send Date'}}

- {{ movement.sendDate }} + +
+

{{movement.action === 'Assign' ? 'Assign Date' : movement.action === 'Register' ? 'Register Date' : 'Send Date'}}

+ {{movement.action !== 'Register' ? movement.sendDate : movement.date }}
-
+

Receive Date:

{{ movement.receiveDate || 'Not arrive' }}
@@ -602,6 +679,28 @@
+
+ + + Page {{ currentPage }} of {{ totalPages }} + + +
+ +
+ + + Page {{ currentPageStation }} of {{ itemsPerPageStation }} + +
@@ -644,6 +743,7 @@ selectedTeamType: "", selectedtoStation: "", consignmentNoteUrl: "", + assignStationDatatable: null, showItemModal: false, loading: false, items: [], @@ -651,20 +751,39 @@ currentUserCompanyDept: null, sortBy: "all", searchQuery: "", + searchQueryStation: "", categoryVisible: {}, historyVisible: {}, detailsVisible: {}, currentRole:"", stationName: "", searchStation: "", - + currentPage: 1, + itemsPerPage: 10, + currentPageStation : 1, + itemsPerPageStation: 10, + dropdownOpen: false, } }, mounted() { this.fetchItem(); - + this.fetchStation(); }, computed: { + paginatedItems() { + const start = (this.currentPage - 1) * this.itemsPerPage; + const end = start + this.itemsPerPage; + return Object.fromEntries( + Object.entries(this.filteredItems).slice(start, end) + ); + }, + totalPages() { + return Math.ceil(Object.keys(this.filteredItems).length / this.itemsPerPage); + }, + + totalPagesStation() { + return Math.ceil(Object.keys(this.filteredStation).length / this.itemsPerPage); + }, groupedItems() { let grouped = this.items.reduce((acc, movement) => { if (!acc[movement.itemId]) { @@ -761,16 +880,16 @@ }, filteredStation() { - if (!this.searchStation) { + if (!this.searchQueryStation) { return this.groupedByStation; } - let searchQuery = this.searchStation.toLowerCase(); + let searchQueryStation = this.toLowerCase(); let grouped = this.groupedByStation; let filtered = {}; Object.keys(grouped).forEach(station => { - if (station.toLowerCase().includes(searchQuery)) { + if (station.toLowerCase().includes(searchQueryStation)) { filtered[station] = grouped[station]; } }); @@ -780,6 +899,30 @@ }, methods: { + paginatedItemsStation(item) { + const start = (this.currentPageStation - 1) * this.itemsPerPageStation; + const end = start + this.itemsPerPageStation; + return Object.fromEntries( + Object.entries(item).slice(start, end) + ); + }, + selectStation(item) { + this.searchQueryStation = item.stationName; + this.dropdownOpen = false; + }, + closeDropdown() { + this.dropdownOpen = false; // Tutup dropdown + }, + goToPage(page) { + if (page >= 1 && page <= this.totalPages) { + this.currentPage = page; + } + }, + goToPageStation(page) { + if (page >= 1 && page <= this.itemsPerPageStation) { + this.currentPageStation = page; + } + }, remark(remark) { document.getElementById("remarkContent").innerText = remark || "No remark message provide."; let modal = new bootstrap.Modal(document.getElementById("remarkModal")); @@ -963,6 +1106,25 @@ console.error('There was a problem with the fetch operation:', error); } }, + async fetchStation() { + try { + const response = await fetch('/InvMainAPI/StationList', { + method: 'POST', // Specify the HTTP method + headers: { + 'Content-Type': 'application/json' + } + }); + if (!response.ok) { + throw new Error('Failed to fetch Station'); + } + + const data = await response.json(); + this.stations = data; + + } catch (error) { + console.error('Error fetching Station:', error); + } + }, handleSorting() { this.renderTables(); }, @@ -979,11 +1141,15 @@ if (this.itemMovementCompleteDatatable) { this.itemMovementCompleteDatatable.destroy(); } + if (this.assignStationDatatable) { + this.assignStationDatatable.destroy(); + } this.itemMovementNotCompleteDatatable = $("#itemMovementNotCompleteDatatable").DataTable({ data: this.items.filter((m) => m.movementComplete == 0), columns: [ { title: "Unique Id", data: "id" }, + { title: "Product Name", data: "productName", render: (data, type, full) => { return `${data}
${renderFile(full.productImage)}`; } }, { title: "Product Code", data: "uniqueID" }, { title: "Action", data: "action" }, { title: "Send Date", data: "sendDate" }, @@ -994,35 +1160,7 @@ { title: "Start Status", data: "toOther" }, { title: "Product Category", data: "productCategory" }, { title: "Qty", data: "quantity" }, - { - 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: "Note", data: "consignmentNote", render: renderFile }, { title: "Remark", data: "remark" }, ], order: [[0, "desc"]], @@ -1030,9 +1168,10 @@ }); this.itemMovementCompleteDatatable = $("#itemMovementCompleteDatatable").DataTable({ - data: this.items.filter((m) => m.movementComplete == 1), + data: this.items.filter((m) => m.movementComplete == 1 && m.action !== "Assign"), columns: [ { title: "Unique Id", data: "id" }, + { title: "Product Name", data: "productName", render: (data, type, full) => { return `${data}
${renderFile(full.productImage)}`; } }, { title: "Product Code", data: "uniqueID" }, { title: "Send Date", data: "sendDate" }, { title: "Receive Date", data: "receiveDate" }, @@ -1046,85 +1185,57 @@ { title: "Start Status", data: "toOther" }, { title: "Latest Status", data: "latestStatus" }, { title: "Product Category", data: "productCategory" }, - { title: "Qty", data: "quantity" }, - { 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: "Note", data: "consignmentNote", render: renderFile }, { title: "Remark", data: "remark" }, ], order: [[0, "desc"]], responsive: true, }); - this.stationDatatable = $("#stationDatatable").DataTable({ + this.assignStationDatatable = $("#assignStationDatatable").DataTable({ data: this.items.filter((m) => m.action === "Assign" ), columns: [ { title: "Unique Id", data: "id" }, + { title: "Product Name", data: "productName", render: (data, type, full) => { return `${data}
${renderFile(full.productImage)}`; } }, { title: "Product Code", data: "uniqueID" }, { title: "Assign Date", data: "sendDate" }, - { title: "From User", data: "toUserName" }, + { title: "Action", data: "action" }, + { title: "Station User PIC", data: "toUserName" }, { title: "From Station", data: "toStationName" }, { title: "Last Station", data: "lastStationName" }, { title: "Qty", data: "quantity" }, - { - 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: "Note", data: "consignmentNote", render: renderFile }, { title: "Remark", data: "remark" }, ], responsive: true, }); - }, + + function renderFile(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`; + } + } + }, toggleCategory(itemId) { this.categoryVisible[itemId] = !this.categoryVisible[itemId]; @@ -1148,6 +1259,21 @@ }, }, + directives: { + clickOutside: { + beforeMount(el, binding) { + el.clickOutsideEvent = (event) => { + if (!(el.contains(event.target))) { + binding.value?.(); // Guna optional chaining untuk elak error + } + }; + document.body.addEventListener("click", el.clickOutsideEvent); + }, + unmounted(el) { + document.body.removeEventListener("click", el.clickOutsideEvent); + } + } + } }); } \ No newline at end of file diff --git a/Areas/Inventory/Views/InventoryMaster/ProductRegistration.cshtml b/Areas/Inventory/Views/InventoryMaster/ProductRegistration.cshtml index 6281bf4..dcf29ae 100644 --- a/Areas/Inventory/Views/InventoryMaster/ProductRegistration.cshtml +++ b/Areas/Inventory/Views/InventoryMaster/ProductRegistration.cshtml @@ -314,7 +314,7 @@ }); // Attach click event listener to the delete buttons - $('#productDatatable tbody').off('click', '.delete-btn').on('click', '.delete-btn', function () { + $('#productDatatable tbody').off('click', '.delete-btn').on('click', '.delete-btn', function () { const productId = $(this).data('id'); // Get the manufacturer ID from the button self.deleteProduct(productId); // Call the Vue method }); diff --git a/Areas/Inventory/Views/ItemMovement/ItemMovementUser.cshtml b/Areas/Inventory/Views/ItemMovement/ItemMovementUser.cshtml index ec360da..f16ee3b 100644 --- a/Areas/Inventory/Views/ItemMovement/ItemMovementUser.cshtml +++ b/Areas/Inventory/Views/ItemMovement/ItemMovementUser.cshtml @@ -28,6 +28,52 @@ margin-left: auto !important; /* Push Complete/Incomplete to right */ } + .dropdown { + position: relative; + width: 100%; + } + + .dropdown-toggle-box { + display: flex; + align-items: center; + border: 1px solid #ddd; + border-radius: 5px; + overflow: hidden; + } + + .dropdown-toggle-box input { + flex: 1; + border: none; + padding: 8px; + } + + .dropdown-btn { + border: none; + background-color: #007bff; + color: white; + padding: 8px 12px; + cursor: pointer; + } + + .dropdown-content { + position: absolute; + width: 100%; + max-height: 200px; + overflow-y: auto; + background: #fff; + border: 1px solid #ddd; + z-index: 10; + } + + .dropdown-content option { + padding: 10px; + cursor: pointer; + display: block; + } + + .dropdown-content option:hover { + background-color: #f1f1f1; + } @await Html.PartialAsync("~/Areas/Inventory/Views/_InventoryPartialUser.cshtml") @@ -54,14 +100,32 @@

Search Station:

- +
+
*Each Items will display one record only*
-

Pending Item Movement

+

Pending Item Transit

Complete Item Movement

+
+

All Item Movement

+
+
+

Assign Station

+
+
+
+
-
+

Item : {{ group.uniqueID }}

+
+ + + Page {{ currentPage }} of {{ totalPages }} + + +
+ +
+ + + Page {{ currentPageStation }} of {{ itemsPerPageStation }} + + +
@section Scripts { @@ -540,16 +637,18 @@ } diff --git a/Areas/Inventory/Views/ItemMovement/ItemRequest.cshtml b/Areas/Inventory/Views/ItemMovement/ItemRequest.cshtml index f4ea3c2..efe64a4 100644 --- a/Areas/Inventory/Views/ItemMovement/ItemRequest.cshtml +++ b/Areas/Inventory/Views/ItemMovement/ItemRequest.cshtml @@ -573,14 +573,14 @@ } }); if (!response.ok) { - throw new Error('Failed to fetch suppliers'); + throw new Error('Failed to fetch Station'); } const data = await response.json(); this.stations = data.filter(station => station.stationPicID === this.userId); } catch (error) { - console.error('Error fetching suppliers:', error); + console.error('Error fetching Station:', error); } }, diff --git a/Areas/Inventory/Views/_InventoryPartial.cshtml b/Areas/Inventory/Views/_InventoryPartial.cshtml index c5bb025..0083ed8 100644 --- a/Areas/Inventory/Views/_InventoryPartial.cshtml +++ b/Areas/Inventory/Views/_InventoryPartial.cshtml @@ -19,7 +19,7 @@

-
Manifacturer
+
Manufacturer
diff --git a/Controllers/API/IdentityAPI.cs b/Controllers/API/IdentityAPI.cs index e6c8d99..d069750 100644 --- a/Controllers/API/IdentityAPI.cs +++ b/Controllers/API/IdentityAPI.cs @@ -69,45 +69,6 @@ namespace PSTW_CentralSystem.Controllers.API return StatusCode(500, $"An error occurred: {ex.Message}"); } } - - //[HttpPost("GetTechnicianUserInformation")] - //public async Task GetTechnicianUserInformation() - //{ - // try - // { - // var users = await _identityDbContext.Users - // .Include(u => u.Department) - // .ToListAsync(); // Retrieve all users with department info - - // var technicianUsers = new List(); - - // foreach (var user in users) - // { - // var roles = await _userManager.GetRolesAsync(user); - // if (roles.Contains("Technician")) - // { - // technicianUsers.Add(new - // { - // id = user.Id, - // fullname = user.FullName, - // department = user.Department - // }); - // } - // } - - // if (!technicianUsers.Any()) - // { - // return NotFound(new { message = "No technicians found" }); - // } - - // return Ok(new { technicianUsers = technicianUsers }); - // } - // catch (Exception ex) - // { - // return StatusCode(500, new { message = $"An error occurred: {ex.Message}" }); - // } - - //} #endregion User #region LDAP Login diff --git a/Controllers/API/Inventory/InvMainAPI.cs b/Controllers/API/Inventory/InvMainAPI.cs index 0648175..4322b68 100644 --- a/Controllers/API/Inventory/InvMainAPI.cs +++ b/Controllers/API/Inventory/InvMainAPI.cs @@ -777,6 +777,7 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory ToUserName = i.NextUser?.FullName, ToStoreName = i.NextStore?.StoreName, ToStationName = i.NextStation?.StationName, + ProductImage = i.Item?.Product?.ImageProduct, i.ToOther, i.sendDate, i.Action, @@ -1503,6 +1504,7 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory i.Id, i.FullName, i.Department, + i.Department?.DepartmentName, })); } diff --git a/Views/Home/Index2.cshtml b/Views/Home/Index2.cshtml index dbef6d1..05a21b9 100644 --- a/Views/Home/Index2.cshtml +++ b/Views/Home/Index2.cshtml @@ -552,7 +552,7 @@