Update & Fix Eerror
This commit is contained in:
parent
7a08ac374a
commit
d6d151a3c7
@ -4,7 +4,6 @@
|
|||||||
ViewData["Title"] = "Forgot your password?";
|
ViewData["Title"] = "Forgot your password?";
|
||||||
}
|
}
|
||||||
|
|
||||||
<h1>@ViewData["Title"]</h1>
|
|
||||||
<h2>Enter your email.</h2>
|
<h2>Enter your email.</h2>
|
||||||
<hr />
|
<hr />
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|||||||
@ -4,7 +4,6 @@
|
|||||||
ViewData["Title"] = "Forgot password confirmation";
|
ViewData["Title"] = "Forgot password confirmation";
|
||||||
}
|
}
|
||||||
|
|
||||||
<h1>@ViewData["Title"]</h1>
|
|
||||||
<p>
|
<p>
|
||||||
Please check your email to reset your password.
|
Please check your email to reset your password.
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@ -44,10 +44,57 @@
|
|||||||
color: purple;
|
color: purple;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.ms-auto {
|
.ms-auto {
|
||||||
margin-left: auto !important; /* Push Complete/Incomplete to right */
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
@await Html.PartialAsync("~/Areas/Inventory/Views/_InventoryPartial.cshtml")
|
@await Html.PartialAsync("~/Areas/Inventory/Views/_InventoryPartial.cshtml")
|
||||||
<div id="registerItem" class="row">
|
<div id="registerItem" class="row">
|
||||||
@ -73,14 +120,31 @@
|
|||||||
<div class="row mb-3" v-if="sortBy === 'station'">
|
<div class="row mb-3" v-if="sortBy === 'station'">
|
||||||
<h4 class="col-sm-1 col-form-h2" style="min-width:150px;">Search Station:</h4>
|
<h4 class="col-sm-1 col-form-h2" style="min-width:150px;">Search Station:</h4>
|
||||||
<div class="col-sm-4">
|
<div class="col-sm-4">
|
||||||
<input type="text" class="form-control" v-model="searchStation" placeholder="Search by station name...">
|
<div class="dropdown" v-click-outside="closeDropdown">
|
||||||
|
<!-- Button + Input dalam satu box -->
|
||||||
|
<div class="dropdown-toggle-box" v-on:click="dropdownOpen = !dropdownOpen">
|
||||||
|
<input type="text" class="form-control" v-model="searchQueryStation"
|
||||||
|
placeholder="Search Station..." v-on:focus="dropdownOpen = true" v-on:click.stop />
|
||||||
|
<button type="button" class="btn btn-primary dropdown-btn" v-on:click.stop="dropdownOpen = !dropdownOpen">
|
||||||
|
▼
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Dropdown list -->
|
||||||
|
<div v-if="dropdownOpen" class="dropdown-content" v-on:click.stop>
|
||||||
|
<div v-for="(item, index) in stations"
|
||||||
|
:key="index" class="dropdown-item" v-on:mousedown.prevent="selectStation(item)">
|
||||||
|
{{ item.stationName }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="sortBy === 'all'">
|
<div v-if="sortBy === 'all'">
|
||||||
<div class="row card">
|
<div class="row card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h2>Pending Item Movement</h2>
|
<h2>Pending Item Transit</h2>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div v-if="loading">
|
<div v-if="loading">
|
||||||
@ -96,6 +160,9 @@
|
|||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h2>Complete Item Movement</h2>
|
<h2>Complete Item Movement</h2>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="card-header">
|
||||||
|
<h4>All Item Movement</h4>
|
||||||
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div v-if="loading">
|
<div v-if="loading">
|
||||||
<div class="spinner-border text-info" role="status">
|
<div class="spinner-border text-info" role="status">
|
||||||
@ -104,6 +171,18 @@
|
|||||||
</div>
|
</div>
|
||||||
<table class="table table-bordered table-hover table-striped no-wrap" id="itemMovementCompleteDatatable" style="width:100%;border-style: solid; border-width: 1px"></table>
|
<table class="table table-bordered table-hover table-striped no-wrap" id="itemMovementCompleteDatatable" style="width:100%;border-style: solid; border-width: 1px"></table>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="card-header">
|
||||||
|
<h4>Assign Station</h4>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<div v-if="loading">
|
||||||
|
<div class="spinner-border text-info" role="status">
|
||||||
|
<span class="visually-hidden">Loading...</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<table class="table table-bordered table-hover table-striped no-wrap" id="assignStationDatatable"
|
||||||
|
style="width:100%;border-style: solid; border-width: 1px"></table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -130,7 +209,7 @@
|
|||||||
<span class="visually-hidden">Loading...</span>
|
<span class="visually-hidden">Loading...</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-for="(group, itemId) in filteredItems" :key="itemId" class="row card">
|
<div v-for="(group, itemId) in paginatedItems" :key="itemId" class="row card">
|
||||||
<div class="card-header d-flex justify-content-between align-items-center">
|
<div class="card-header d-flex justify-content-between align-items-center">
|
||||||
@* <h2>Item : {{ group.uniqueID }}</h2> *@
|
@* <h2>Item : {{ group.uniqueID }}</h2> *@
|
||||||
<h2 v-if="group.uniqueID">Item : {{ group.uniqueID }}</h2>
|
<h2 v-if="group.uniqueID">Item : {{ group.uniqueID }}</h2>
|
||||||
@ -159,13 +238,13 @@
|
|||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<!-- Send Date -->
|
<!-- Send Date -->
|
||||||
<div class="d-flex flex-wrap align-items-center gap-2 flex-grow-1" style="max-width:285px; min-width:285px;">
|
<div class="d-flex flex-wrap align-items-center gap-2 flex-grow-1" style="max-width:310px; min-width:310px;">
|
||||||
<h4 class="fixed-label m-0 text-nowrap">{{movement.action === 'Assign' ? 'Assign Date' : 'Send Date'}}</h4>
|
<h4 class="fixed-label m-0 text-nowrap">{{movement.action === 'Assign' ? 'Assign Date' : movement.action === 'Register' ? 'Register Date' : 'Send Date'}}</h4>
|
||||||
<span class="fixed-value text-truncate">{{ movement.sendDate }}</span>
|
<span class="fixed-value text-truncate">{{movement.action !== 'Register' ? movement.sendDate : movement.date }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Receive Date -->
|
<!-- Receive Date -->
|
||||||
<div v-if="movement.action !== 'Assign'" class="d-flex flex-wrap align-items-center gap-2 flex-grow-1" style="max-width:290px; min-width:290px;">
|
<div v-if="movement.action !== 'Assign' && movement.action !== 'Register'" class="d-flex flex-wrap align-items-center gap-2 flex-grow-1" style="max-width:290px; min-width:290px;">
|
||||||
<h4 class="fixed-label m-0 text-nowrap">Receive Date:</h4>
|
<h4 class="fixed-label m-0 text-nowrap">Receive Date:</h4>
|
||||||
<span class="fixed-value text-truncate" style="max-width:160px;">{{ movement.receiveDate || 'Not arrive' }}</span>
|
<span class="fixed-value text-truncate" style="max-width:160px;">{{ movement.receiveDate || 'Not arrive' }}</span>
|
||||||
</div>
|
</div>
|
||||||
@ -260,13 +339,13 @@
|
|||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<!-- Send Date -->
|
<!-- Send Date -->
|
||||||
<div class="d-flex flex-wrap align-items-center gap-2 flex-grow-1" style="max-width:285px; min-width:285px;">
|
<div class="d-flex flex-wrap align-items-center gap-2 flex-grow-1" style="max-width:310px; min-width:310px;">
|
||||||
<h4 class="fixed-label m-0 text-nowrap">{{movement.action === 'Assign' ? 'Assign Date' : 'Send Date'}}</h4>
|
<h4 class="fixed-label m-0 text-nowrap">{{movement.action === 'Assign' ? 'Assign Date' : movement.action === 'Register' ? 'Register Date' : 'Send Date'}}</h4>
|
||||||
<span class="fixed-value text-truncate">{{ movement.sendDate }}</span>
|
<span class="fixed-value text-truncate">{{movement.action !== 'Register' ? movement.sendDate : movement.date }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Receive Date -->
|
<!-- Receive Date -->
|
||||||
<div v-if="movement.action !== 'Assign'" class="d-flex flex-wrap align-items-center gap-2 flex-grow-1" style="max-width:290px; min-width:290px;">
|
<div v-if="movement.action !== 'Assign' && movement.action !== 'Register'" class="d-flex flex-wrap align-items-center gap-2 flex-grow-1" style="max-width:290px; min-width:290px;">
|
||||||
<h4 class="fixed-label m-0 text-nowrap">Receive Date:</h4>
|
<h4 class="fixed-label m-0 text-nowrap">Receive Date:</h4>
|
||||||
<span class="fixed-value text-truncate" style="max-width:160px;">{{ movement.receiveDate || 'Not arrive' }}</span>
|
<span class="fixed-value text-truncate" style="max-width:160px;">{{ movement.receiveDate || 'Not arrive' }}</span>
|
||||||
</div>
|
</div>
|
||||||
@ -347,8 +426,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<!--------------------------------------------STATION CATEGORY---------------------------------------------------------------------->
|
<!--------------------------------------------STATION CATEGORY---------------------------------------------------------------------->
|
||||||
<div v-if="sortBy === 'station'">
|
<div v-if="sortBy === 'station'">
|
||||||
<div v-for="(items, station) in filteredStation " :key="stationName"
|
<div v-for="(items, station) in filteredStation " :key="stationName"
|
||||||
@ -363,7 +440,7 @@
|
|||||||
|
|
||||||
<!-- Show Items Under Each Station -->
|
<!-- Show Items Under Each Station -->
|
||||||
<div v-show="categoryVisible[station]" class="card-body">
|
<div v-show="categoryVisible[station]" class="card-body">
|
||||||
<div v-for="(group, itemId) in items" :key="itemId" class="row card">
|
<div v-for="(group, itemId) in paginatedItemsStation(items)" :key="itemId" class="row card">
|
||||||
<!-- Item Header -->
|
<!-- Item Header -->
|
||||||
<div class="card-header d-flex justify-content-between align-items-center">
|
<div class="card-header d-flex justify-content-between align-items-center">
|
||||||
@* <h2>Item : {{ group.uniqueID }}</h2> *@
|
@* <h2>Item : {{ group.uniqueID }}</h2> *@
|
||||||
@ -391,13 +468,13 @@
|
|||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<!-- Send Date -->
|
<!-- Send Date -->
|
||||||
<div class="d-flex flex-wrap align-items-center gap-2 flex-grow-1" style="max-width:285px; min-width:285px;">
|
<div class="d-flex flex-wrap align-items-center gap-2 flex-grow-1" style="max-width:310px; min-width:310px;">
|
||||||
<h4 class="fixed-label m-0 text-nowrap">{{movement.action === 'Assign' ? 'Assign Date' : 'Send Date'}}</h4>
|
<h4 class="fixed-label m-0 text-nowrap">{{movement.action === 'Assign' ? 'Assign Date' : movement.action === 'Register' ? 'Register Date' : 'Send Date'}}</h4>
|
||||||
<span class="fixed-value text-truncate">{{ movement.sendDate }}</span>
|
<span class="fixed-value text-truncate">{{movement.action !== 'Register' ? movement.sendDate : movement.date }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Receive Date -->
|
<!-- Receive Date -->
|
||||||
<div v-if="movement.action !== 'Assign'" class="d-flex flex-wrap align-items-center gap-2 flex-grow-1" style="max-width:290px; min-width:290px;">
|
<div v-if="movement.action !== 'Assign' && movement.action !== 'Register'" class="d-flex flex-wrap align-items-center gap-2 flex-grow-1" style="max-width:290px; min-width:290px;">
|
||||||
<h4 class="fixed-label m-0 text-nowrap">Receive Date:</h4>
|
<h4 class="fixed-label m-0 text-nowrap">Receive Date:</h4>
|
||||||
<span class="fixed-value text-truncate" style="max-width:160px;">{{ movement.receiveDate || 'Not arrive' }}</span>
|
<span class="fixed-value text-truncate" style="max-width:160px;">{{ movement.receiveDate || 'Not arrive' }}</span>
|
||||||
</div>
|
</div>
|
||||||
@ -485,13 +562,13 @@
|
|||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
<!-- Send Date -->
|
<!-- Send Date -->
|
||||||
<div class="d-flex flex-wrap align-items-center gap-2 flex-grow-1" style="max-width:285px; min-width:285px;">
|
<div class="d-flex flex-wrap align-items-center gap-2 flex-grow-1" style="max-width:310px; min-width:310px;">
|
||||||
<h4 class="fixed-label m-0 text-nowrap">{{movement.action === 'Assign' ? 'Assign Date' : 'Send Date'}}</h4>
|
<h4 class="fixed-label m-0 text-nowrap">{{movement.action === 'Assign' ? 'Assign Date' : movement.action === 'Register' ? 'Register Date' : 'Send Date'}}</h4>
|
||||||
<span class="fixed-value text-truncate">{{ movement.sendDate }}</span>
|
<span class="fixed-value text-truncate">{{movement.action !== 'Register' ? movement.sendDate : movement.date }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Receive Date -->
|
<!-- Receive Date -->
|
||||||
<div v-if="movement.action !== 'Assign'" class="d-flex flex-wrap align-items-center gap-2 flex-grow-1" style="max-width:290px; min-width:290px;">
|
<div v-if="movement.action !== 'Assign' && movement.action !== 'Register'" class="d-flex flex-wrap align-items-center gap-2 flex-grow-1" style="max-width:290px; min-width:290px;">
|
||||||
<h4 class="fixed-label m-0 text-nowrap">Receive Date:</h4>
|
<h4 class="fixed-label m-0 text-nowrap">Receive Date:</h4>
|
||||||
<span class="fixed-value text-truncate" style="max-width:160px;">{{ movement.receiveDate || 'Not arrive' }}</span>
|
<span class="fixed-value text-truncate" style="max-width:160px;">{{ movement.receiveDate || 'Not arrive' }}</span>
|
||||||
</div>
|
</div>
|
||||||
@ -602,6 +679,28 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center align-items-center mt-3" v-if="sortBy === 'item' && totalPages > 0">
|
||||||
|
<button class="btn btn-secondary mx-1" v-on:click="goToPage(currentPage - 1)" :disabled="currentPage === 1">
|
||||||
|
Previous
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<span class="mx-2">Page {{ currentPage }} of {{ totalPages }}</span>
|
||||||
|
|
||||||
|
<button class="btn btn-secondary mx-1" v-on:click="goToPage(currentPage + 1)" :disabled="currentPage === totalPages">
|
||||||
|
Next
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center align-items-center mt-3" v-if="sortBy === 'station' && totalPagesStation > 0">
|
||||||
|
<button class="btn btn-secondary mx-1" v-on:click="goToPageStation(currentPageStation - 1)" :disabled="currentPageStation === 1">
|
||||||
|
Previous
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<span class="mx-2">Page {{ currentPageStation }} of {{ itemsPerPageStation }}</span>
|
||||||
|
|
||||||
|
<button class="btn btn-secondary mx-1" v-on:click="goToPageStation(currentPageStation + 1)" :disabled="currentPageStation === totalPages">
|
||||||
|
Next
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -644,6 +743,7 @@
|
|||||||
selectedTeamType: "",
|
selectedTeamType: "",
|
||||||
selectedtoStation: "",
|
selectedtoStation: "",
|
||||||
consignmentNoteUrl: "",
|
consignmentNoteUrl: "",
|
||||||
|
assignStationDatatable: null,
|
||||||
showItemModal: false,
|
showItemModal: false,
|
||||||
loading: false,
|
loading: false,
|
||||||
items: [],
|
items: [],
|
||||||
@ -651,20 +751,39 @@
|
|||||||
currentUserCompanyDept: null,
|
currentUserCompanyDept: null,
|
||||||
sortBy: "all",
|
sortBy: "all",
|
||||||
searchQuery: "",
|
searchQuery: "",
|
||||||
|
searchQueryStation: "",
|
||||||
categoryVisible: {},
|
categoryVisible: {},
|
||||||
historyVisible: {},
|
historyVisible: {},
|
||||||
detailsVisible: {},
|
detailsVisible: {},
|
||||||
currentRole:"",
|
currentRole:"",
|
||||||
stationName: "",
|
stationName: "",
|
||||||
searchStation: "",
|
searchStation: "",
|
||||||
|
currentPage: 1,
|
||||||
|
itemsPerPage: 10,
|
||||||
|
currentPageStation : 1,
|
||||||
|
itemsPerPageStation: 10,
|
||||||
|
dropdownOpen: false,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.fetchItem();
|
this.fetchItem();
|
||||||
|
this.fetchStation();
|
||||||
},
|
},
|
||||||
computed: {
|
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() {
|
groupedItems() {
|
||||||
let grouped = this.items.reduce((acc, movement) => {
|
let grouped = this.items.reduce((acc, movement) => {
|
||||||
if (!acc[movement.itemId]) {
|
if (!acc[movement.itemId]) {
|
||||||
@ -761,16 +880,16 @@
|
|||||||
|
|
||||||
},
|
},
|
||||||
filteredStation() {
|
filteredStation() {
|
||||||
if (!this.searchStation) {
|
if (!this.searchQueryStation) {
|
||||||
return this.groupedByStation;
|
return this.groupedByStation;
|
||||||
}
|
}
|
||||||
|
|
||||||
let searchQuery = this.searchStation.toLowerCase();
|
let searchQueryStation = this.toLowerCase();
|
||||||
let grouped = this.groupedByStation;
|
let grouped = this.groupedByStation;
|
||||||
let filtered = {};
|
let filtered = {};
|
||||||
|
|
||||||
Object.keys(grouped).forEach(station => {
|
Object.keys(grouped).forEach(station => {
|
||||||
if (station.toLowerCase().includes(searchQuery)) {
|
if (station.toLowerCase().includes(searchQueryStation)) {
|
||||||
filtered[station] = grouped[station];
|
filtered[station] = grouped[station];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -780,6 +899,30 @@
|
|||||||
},
|
},
|
||||||
methods: {
|
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) {
|
remark(remark) {
|
||||||
document.getElementById("remarkContent").innerText = remark || "No remark message provide.";
|
document.getElementById("remarkContent").innerText = remark || "No remark message provide.";
|
||||||
let modal = new bootstrap.Modal(document.getElementById("remarkModal"));
|
let modal = new bootstrap.Modal(document.getElementById("remarkModal"));
|
||||||
@ -963,6 +1106,25 @@
|
|||||||
console.error('There was a problem with the fetch operation:', error);
|
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() {
|
handleSorting() {
|
||||||
this.renderTables();
|
this.renderTables();
|
||||||
},
|
},
|
||||||
@ -979,11 +1141,15 @@
|
|||||||
if (this.itemMovementCompleteDatatable) {
|
if (this.itemMovementCompleteDatatable) {
|
||||||
this.itemMovementCompleteDatatable.destroy();
|
this.itemMovementCompleteDatatable.destroy();
|
||||||
}
|
}
|
||||||
|
if (this.assignStationDatatable) {
|
||||||
|
this.assignStationDatatable.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
this.itemMovementNotCompleteDatatable = $("#itemMovementNotCompleteDatatable").DataTable({
|
this.itemMovementNotCompleteDatatable = $("#itemMovementNotCompleteDatatable").DataTable({
|
||||||
data: this.items.filter((m) => m.movementComplete == 0),
|
data: this.items.filter((m) => m.movementComplete == 0),
|
||||||
columns: [
|
columns: [
|
||||||
{ title: "Unique Id", data: "id" },
|
{ title: "Unique Id", data: "id" },
|
||||||
|
{ title: "Product Name", data: "productName", render: (data, type, full) => { return `${data} <br> ${renderFile(full.productImage)}`; } },
|
||||||
{ title: "Product Code", data: "uniqueID" },
|
{ title: "Product Code", data: "uniqueID" },
|
||||||
{ title: "Action", data: "action" },
|
{ title: "Action", data: "action" },
|
||||||
{ title: "Send Date", data: "sendDate" },
|
{ title: "Send Date", data: "sendDate" },
|
||||||
@ -994,35 +1160,7 @@
|
|||||||
{ title: "Start Status", data: "toOther" },
|
{ title: "Start Status", data: "toOther" },
|
||||||
{ title: "Product Category", data: "productCategory" },
|
{ title: "Product Category", data: "productCategory" },
|
||||||
{ title: "Qty", data: "quantity" },
|
{ title: "Qty", data: "quantity" },
|
||||||
{
|
{ title: "Note", data: "consignmentNote", render: renderFile },
|
||||||
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 `<a href="${data}" target="_blank" data-lightbox="image-1">
|
|
||||||
<img src="${data}" alt="Image" class="img-thumbnail" style="width: 100px; height: 100px;" />
|
|
||||||
</a>`;
|
|
||||||
}
|
|
||||||
else if (isPdf) {
|
|
||||||
return `<a href="${data}" target="_blank">
|
|
||||||
<img src="https://upload.wikimedia.org/wikipedia/commons/8/87/PDF_file_icon.svg"
|
|
||||||
alt="PDF Document" class="img-thumbnail"
|
|
||||||
style="width: 50px; height: 50px;" />
|
|
||||||
<br>View PDF
|
|
||||||
</a>`;
|
|
||||||
} else {
|
|
||||||
return `<a href="${data}" target="_blank">Download File</a>`;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ title: "Remark", data: "remark" },
|
{ title: "Remark", data: "remark" },
|
||||||
],
|
],
|
||||||
order: [[0, "desc"]],
|
order: [[0, "desc"]],
|
||||||
@ -1030,9 +1168,10 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.itemMovementCompleteDatatable = $("#itemMovementCompleteDatatable").DataTable({
|
this.itemMovementCompleteDatatable = $("#itemMovementCompleteDatatable").DataTable({
|
||||||
data: this.items.filter((m) => m.movementComplete == 1),
|
data: this.items.filter((m) => m.movementComplete == 1 && m.action !== "Assign"),
|
||||||
columns: [
|
columns: [
|
||||||
{ title: "Unique Id", data: "id" },
|
{ title: "Unique Id", data: "id" },
|
||||||
|
{ title: "Product Name", data: "productName", render: (data, type, full) => { return `${data} <br> ${renderFile(full.productImage)}`; } },
|
||||||
{ title: "Product Code", data: "uniqueID" },
|
{ title: "Product Code", data: "uniqueID" },
|
||||||
{ title: "Send Date", data: "sendDate" },
|
{ title: "Send Date", data: "sendDate" },
|
||||||
{ title: "Receive Date", data: "receiveDate" },
|
{ title: "Receive Date", data: "receiveDate" },
|
||||||
@ -1046,55 +1185,32 @@
|
|||||||
{ title: "Start Status", data: "toOther" },
|
{ title: "Start Status", data: "toOther" },
|
||||||
{ title: "Latest Status", data: "latestStatus" },
|
{ title: "Latest Status", data: "latestStatus" },
|
||||||
{ title: "Product Category", data: "productCategory" },
|
{ title: "Product Category", data: "productCategory" },
|
||||||
{ title: "Qty", data: "quantity" },
|
{ title: "Note", data: "consignmentNote", render: renderFile },
|
||||||
{ 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 `<a href="${data}" target="_blank" data-lightbox="image-1">
|
|
||||||
<img src="${data}" alt="Image" class="img-thumbnail" style="width: 100px; height: 100px;" />
|
|
||||||
</a>`;
|
|
||||||
}
|
|
||||||
else if (isPdf) {
|
|
||||||
return `<a href="${data}" target="_blank">
|
|
||||||
<img src="https://upload.wikimedia.org/wikipedia/commons/8/87/PDF_file_icon.svg"
|
|
||||||
alt="PDF Document" class="img-thumbnail"
|
|
||||||
style="width: 50px; height: 50px;" />
|
|
||||||
<br>View PDF
|
|
||||||
</a>`;
|
|
||||||
} else {
|
|
||||||
return `<a href="${data}" target="_blank">Download File</a>`;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
{ title: "Remark", data: "remark" },
|
{ title: "Remark", data: "remark" },
|
||||||
],
|
],
|
||||||
order: [[0, "desc"]],
|
order: [[0, "desc"]],
|
||||||
responsive: true,
|
responsive: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.stationDatatable = $("#stationDatatable").DataTable({
|
this.assignStationDatatable = $("#assignStationDatatable").DataTable({
|
||||||
data: this.items.filter((m) => m.action === "Assign" ),
|
data: this.items.filter((m) => m.action === "Assign" ),
|
||||||
columns: [
|
columns: [
|
||||||
{ title: "Unique Id", data: "id" },
|
{ title: "Unique Id", data: "id" },
|
||||||
|
{ title: "Product Name", data: "productName", render: (data, type, full) => { return `${data} <br> ${renderFile(full.productImage)}`; } },
|
||||||
{ title: "Product Code", data: "uniqueID" },
|
{ title: "Product Code", data: "uniqueID" },
|
||||||
{ title: "Assign Date", data: "sendDate" },
|
{ 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: "From Station", data: "toStationName" },
|
||||||
{ title: "Last Station", data: "lastStationName" },
|
{ title: "Last Station", data: "lastStationName" },
|
||||||
{ title: "Qty", data: "quantity" },
|
{ title: "Qty", data: "quantity" },
|
||||||
{
|
{ title: "Note", data: "consignmentNote", render: renderFile },
|
||||||
title: "Note",
|
{ title: "Remark", data: "remark" },
|
||||||
data: "consignmentNote",
|
],
|
||||||
render: function (data, type, full, meta) {
|
responsive: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
function renderFile(data, type, full, meta) {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
return "No Document";
|
return "No Document";
|
||||||
}
|
}
|
||||||
@ -1118,12 +1234,7 @@
|
|||||||
} else {
|
} else {
|
||||||
return `<a href="${data}" target="_blank">Download File</a>`;
|
return `<a href="${data}" target="_blank">Download File</a>`;
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
},
|
|
||||||
{ title: "Remark", data: "remark" },
|
|
||||||
],
|
|
||||||
responsive: true,
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
toggleCategory(itemId) {
|
toggleCategory(itemId) {
|
||||||
this.categoryVisible[itemId] = !this.categoryVisible[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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
}
|
}
|
||||||
@ -28,6 +28,52 @@
|
|||||||
margin-left: auto !important; /* Push Complete/Incomplete to right */
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
@await Html.PartialAsync("~/Areas/Inventory/Views/_InventoryPartialUser.cshtml")
|
@await Html.PartialAsync("~/Areas/Inventory/Views/_InventoryPartialUser.cshtml")
|
||||||
@ -54,14 +100,32 @@
|
|||||||
<div class="row mb-3" v-if="sortBy === 'station'">
|
<div class="row mb-3" v-if="sortBy === 'station'">
|
||||||
<h4 class="col-sm-1 col-form-h2" style="min-width:150px;">Search Station:</h4>
|
<h4 class="col-sm-1 col-form-h2" style="min-width:150px;">Search Station:</h4>
|
||||||
<div class="col-sm-4">
|
<div class="col-sm-4">
|
||||||
<input type="text" class="form-control" v-model="searchStation" placeholder="Search by station name...">
|
<div class="dropdown" v-click-outside="closeDropdown">
|
||||||
|
<!-- Button + Input dalam satu box -->
|
||||||
|
<div class="dropdown-toggle-box" v-on:click="dropdownOpen = !dropdownOpen">
|
||||||
|
<input type="text" class="form-control" v-model="searchQueryStation"
|
||||||
|
placeholder="Search Station..." v-on:focus="dropdownOpen = true" v-on:click.stop />
|
||||||
|
<button type="button" class="btn btn-primary dropdown-btn" v-on:click.stop="dropdownOpen = !dropdownOpen">
|
||||||
|
▼
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Dropdown list -->
|
||||||
|
<div v-if="dropdownOpen" class="dropdown-content" v-on:click.stop>
|
||||||
|
<div v-for="(item, index) in stations"
|
||||||
|
:key="index" class="dropdown-item" v-on:mousedown.prevent="selectStation(item)">
|
||||||
|
{{ item.stationName }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="sortBy === 'all'">
|
<div v-if="sortBy === 'all'">
|
||||||
|
<h5 style="color:cadetblue">*Each Items will display one record only*</h5>
|
||||||
<div class="row card">
|
<div class="row card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h2>Pending Item Movement</h2>
|
<h2>Pending Item Transit</h2>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<table class="table table-bordered table-hover table-striped no-wrap" id="itemMovementNotCompleteDatatable"
|
<table class="table table-bordered table-hover table-striped no-wrap" id="itemMovementNotCompleteDatatable"
|
||||||
@ -73,16 +137,26 @@
|
|||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h2>Complete Item Movement</h2>
|
<h2>Complete Item Movement</h2>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="card-header">
|
||||||
|
<h4>All Item Movement</h4>
|
||||||
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<table class="table table-bordered table-hover table-striped no-wrap" id="itemMovementCompleteDatatable"
|
<table class="table table-bordered table-hover table-striped no-wrap" id="itemMovementCompleteDatatable"
|
||||||
style="width:100%;border-style: solid; border-width: 1px"></table>
|
style="width:100%;border-style: solid; border-width: 1px"></table>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="card-header">
|
||||||
|
<h4>Assign Station</h4>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<table class="table table-bordered table-hover table-striped no-wrap" id="assignStationDatatable"
|
||||||
|
style="width:100%;border-style: solid; border-width: 1px"></table>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!--------------------------------------------ITEM CATEGORY---------------------------------------------------------------------->
|
<!--------------------------------------------ITEM CATEGORY---------------------------------------------------------------------->
|
||||||
<div v-if="sortBy === 'item'">
|
<div v-if="sortBy === 'item'">
|
||||||
<div v-for="(group, itemId) in filteredItems" :key="itemId" class="row card">
|
<div v-for="(group, itemId) in paginatedItems" :key="itemId" class="row card">
|
||||||
<div class="card-header d-flex justify-content-between align-items-center">
|
<div class="card-header d-flex justify-content-between align-items-center">
|
||||||
<h2>Item : {{ group.uniqueID }}</h2>
|
<h2>Item : {{ group.uniqueID }}</h2>
|
||||||
<button class="btn btn-light" v-on:click="toggleCategory(itemId)">
|
<button class="btn btn-light" v-on:click="toggleCategory(itemId)">
|
||||||
@ -532,6 +606,29 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="d-flex justify-content-center align-items-center mt-3" v-if="sortBy === 'item' && totalPages > 0">
|
||||||
|
<button class="btn btn-secondary mx-1" v-on:click="goToPage(currentPage - 1)" :disabled="currentPage === 1">
|
||||||
|
Previous
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<span class="mx-2">Page {{ currentPage }} of {{ totalPages }}</span>
|
||||||
|
|
||||||
|
<button class="btn btn-secondary mx-1" v-on:click="goToPage(currentPage + 1)" :disabled="currentPage === totalPages">
|
||||||
|
Next
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-center align-items-center mt-3" v-if="sortBy === 'station' && totalPagesStation > 0">
|
||||||
|
<button class="btn btn-secondary mx-1" v-on:click="goToPageStation(currentPageStation - 1)" :disabled="currentPageStation === 1">
|
||||||
|
Previous
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<span class="mx-2">Page {{ currentPageStation }} of {{ itemsPerPageStation }}</span>
|
||||||
|
|
||||||
|
<button class="btn btn-secondary mx-1" v-on:click="goToPageStation(currentPageStation + 1)" :disabled="currentPageStation === totalPages">
|
||||||
|
Next
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@section Scripts {
|
@section Scripts {
|
||||||
@ -545,11 +642,13 @@
|
|||||||
const app = Vue.createApp({
|
const app = Vue.createApp({
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
userId: null,
|
||||||
itemMovements: [],
|
itemMovements: [],
|
||||||
|
assignStationDatatable: null,
|
||||||
itemMovementCompleteDatatable: null,
|
itemMovementCompleteDatatable: null,
|
||||||
stationDatatable: null,
|
|
||||||
itemMovementNotCompleteDatatable: null,
|
itemMovementNotCompleteDatatable: null,
|
||||||
searchQuery: "",
|
searchQuery: "",
|
||||||
|
searchQueryStation: "",
|
||||||
searchStation: "",
|
searchStation: "",
|
||||||
sortBy: "all",
|
sortBy: "all",
|
||||||
historyVisible: {},
|
historyVisible: {},
|
||||||
@ -557,9 +656,29 @@
|
|||||||
categoryVisible: {},
|
categoryVisible: {},
|
||||||
consignmentNoteUrl: "",
|
consignmentNoteUrl: "",
|
||||||
stationName: "",
|
stationName: "",
|
||||||
|
currentPage: 1,
|
||||||
|
itemsPerPage: 10,
|
||||||
|
currentPageStation: 1,
|
||||||
|
itemsPerPageStation: 10,
|
||||||
|
dropdownOpen: false,
|
||||||
|
currentUser: null,
|
||||||
|
stations:[],
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
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);
|
||||||
|
},
|
||||||
processedGroupedItems() {
|
processedGroupedItems() {
|
||||||
let grouped = this.itemMovements.reduce((acc, movement) => {
|
let grouped = this.itemMovements.reduce((acc, movement) => {
|
||||||
if (!acc[movement.itemId]) {
|
if (!acc[movement.itemId]) {
|
||||||
@ -686,16 +805,16 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
filteredStation() {
|
filteredStation() {
|
||||||
if (!this.searchStation) {
|
if (!this.searchQueryStation) {
|
||||||
return this.groupedByStation;
|
return this.groupedByStation;
|
||||||
}
|
}
|
||||||
|
|
||||||
let searchQuery = this.searchStation.toLowerCase();
|
let searchQueryStation = this.searchQueryStation.toLowerCase();
|
||||||
let grouped = this.groupedByStation;
|
let grouped = this.groupedByStation;
|
||||||
let filtered = {};
|
let filtered = {};
|
||||||
|
|
||||||
Object.keys(grouped).forEach(station => {
|
Object.keys(grouped).forEach(station => {
|
||||||
if (station.toLowerCase().includes(searchQuery)) {
|
if (station.toLowerCase().includes(searchQueryStation)) {
|
||||||
filtered[station] = grouped[station];
|
filtered[station] = grouped[station];
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -703,10 +822,44 @@
|
|||||||
return filtered;
|
return filtered;
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
async mounted() {
|
||||||
this.fetchItemMovement();
|
this.fetchItemMovement();
|
||||||
|
await this.fetchUser();
|
||||||
|
await Promise.all([
|
||||||
|
this.fetchStation(),
|
||||||
|
]);
|
||||||
},
|
},
|
||||||
methods: {
|
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"));
|
||||||
|
modal.show();
|
||||||
|
},
|
||||||
|
|
||||||
remark(remark) {
|
remark(remark) {
|
||||||
document.getElementById("remarkContent").innerText = remark || "No remark message provide.";
|
document.getElementById("remarkContent").innerText = remark || "No remark message provide.";
|
||||||
let modal = new bootstrap.Modal(document.getElementById("remarkModal"));
|
let modal = new bootstrap.Modal(document.getElementById("remarkModal"));
|
||||||
@ -750,6 +903,45 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
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.filter(station => station.stationPicID === this.userId);
|
||||||
|
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error fetching Station:', error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async fetchUser() {
|
||||||
|
try {
|
||||||
|
const response = await fetch(`/IdentityAPI/GetUserInformation/`, {
|
||||||
|
method: 'POST',
|
||||||
|
});
|
||||||
|
if (response.ok) {
|
||||||
|
const data = await response.json();
|
||||||
|
this.currentUser = data?.userInfo || null;
|
||||||
|
this.userId = await this.currentUser.id;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.error(`Failed to fetch user: ${response.statusText}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
console.error('There was a problem with the fetch operation:', error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
handleSorting() {
|
handleSorting() {
|
||||||
this.renderTables();
|
this.renderTables();
|
||||||
},
|
},
|
||||||
@ -767,8 +959,8 @@
|
|||||||
if (this.itemMovementCompleteDatatable) {
|
if (this.itemMovementCompleteDatatable) {
|
||||||
this.itemMovementCompleteDatatable.destroy();
|
this.itemMovementCompleteDatatable.destroy();
|
||||||
}
|
}
|
||||||
if (this.stationDatatable) {
|
if (this.assignStationDatatable) {
|
||||||
this.stationDatatable.destroy();
|
this.assignStationDatatable.destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get latest movement per uniqueID after filtering
|
// Get latest movement per uniqueID after filtering
|
||||||
@ -808,6 +1000,7 @@
|
|||||||
|
|
||||||
let notCompleteData = [];
|
let notCompleteData = [];
|
||||||
let completeData = [];
|
let completeData = [];
|
||||||
|
let completeStationData = [];
|
||||||
|
|
||||||
latestMovements.forEach(movement => {
|
latestMovements.forEach(movement => {
|
||||||
let filteredMovements = filterMovements([movement]);
|
let filteredMovements = filterMovements([movement]);
|
||||||
@ -815,8 +1008,10 @@
|
|||||||
if (filteredMovements.length > 0) {
|
if (filteredMovements.length > 0) {
|
||||||
if (movement.movementComplete == 0) {
|
if (movement.movementComplete == 0) {
|
||||||
notCompleteData.push(movement);
|
notCompleteData.push(movement);
|
||||||
} else if (movement.movementComplete == 1) {
|
} else if (movement.movementComplete == 1 && movement.action !== "Assign") {
|
||||||
completeData.push(movement);
|
completeData.push(movement);
|
||||||
|
} else {
|
||||||
|
completeStationData.push(movement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -826,7 +1021,7 @@
|
|||||||
data: notCompleteData,
|
data: notCompleteData,
|
||||||
columns: [
|
columns: [
|
||||||
{ title: "Unique Id", data: "id" },
|
{ title: "Unique Id", data: "id" },
|
||||||
{ title: "Product Name", data: "productName" },
|
{ title: "Product Name", data: "productName", render: (data, type, full) => { return `${data} <br> ${renderFile(full.productImage)}`; } },
|
||||||
{ title: "Product Code", data: "uniqueID" },
|
{ title: "Product Code", data: "uniqueID" },
|
||||||
{ title: "Action", data: "action" },
|
{ title: "Action", data: "action" },
|
||||||
{ title: "Send Date", data: "sendDate" },
|
{ title: "Send Date", data: "sendDate" },
|
||||||
@ -847,7 +1042,7 @@
|
|||||||
data: completeData,
|
data: completeData,
|
||||||
columns: [
|
columns: [
|
||||||
{ title: "Unique Id", data: "id" },
|
{ title: "Unique Id", data: "id" },
|
||||||
{ title: "Product Name", data: "productName" },
|
{ title: "Product Name", data: "productName", render: (data, type, full) => { return `${data} <br> ${renderFile(full.productImage)}`; } },
|
||||||
{ title: "Product Code", data: "uniqueID" },
|
{ title: "Product Code", data: "uniqueID" },
|
||||||
{ title: "Send Date", data: "sendDate" },
|
{ title: "Send Date", data: "sendDate" },
|
||||||
{ title: "Receive Date", data: "receiveDate" },
|
{ title: "Receive Date", data: "receiveDate" },
|
||||||
@ -867,6 +1062,25 @@
|
|||||||
responsive: true,
|
responsive: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Table 3: Station Movements
|
||||||
|
this.assignStationDatatable = $("#assignStationDatatable").DataTable({
|
||||||
|
data: completeStationData,
|
||||||
|
columns: [
|
||||||
|
{ title: "Unique Id", data: "id" },
|
||||||
|
{ title: "Product Name", data: "productName", render: (data, type, full) => { return `${data} <br> ${renderFile(full.productImage)}`; }},
|
||||||
|
{ title: "Product Code", data: "uniqueID" },
|
||||||
|
{ title: "Assign Date", data: "sendDate" },
|
||||||
|
{ 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: renderFile },
|
||||||
|
{ title: "Remark", data: "remark" },
|
||||||
|
],
|
||||||
|
responsive: true,
|
||||||
|
});
|
||||||
|
|
||||||
// Function to render file (image/PDF)
|
// Function to render file (image/PDF)
|
||||||
function renderFile(data, type, full, meta) {
|
function renderFile(data, type, full, meta) {
|
||||||
if (!data) {
|
if (!data) {
|
||||||
@ -917,6 +1131,22 @@
|
|||||||
},
|
},
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@ -573,14 +573,14 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error('Failed to fetch suppliers');
|
throw new Error('Failed to fetch Station');
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await response.json();
|
const data = await response.json();
|
||||||
this.stations = data.filter(station => station.stationPicID === this.userId);
|
this.stations = data.filter(station => station.stationPicID === this.userId);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error fetching suppliers:', error);
|
console.error('Error fetching Station:', error);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@ -19,7 +19,7 @@
|
|||||||
<h1 class="font-light text-white">
|
<h1 class="font-light text-white">
|
||||||
<i class="mdi mdi-factory"></i>
|
<i class="mdi mdi-factory"></i>
|
||||||
</h1>
|
</h1>
|
||||||
<h6 class="text-white">Manifacturer</h6>
|
<h6 class="text-white">Manufacturer</h6>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -69,45 +69,6 @@ namespace PSTW_CentralSystem.Controllers.API
|
|||||||
return StatusCode(500, $"An error occurred: {ex.Message}");
|
return StatusCode(500, $"An error occurred: {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//[HttpPost("GetTechnicianUserInformation")]
|
|
||||||
//public async Task<IActionResult> GetTechnicianUserInformation()
|
|
||||||
//{
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// var users = await _identityDbContext.Users
|
|
||||||
// .Include(u => u.Department)
|
|
||||||
// .ToListAsync(); // Retrieve all users with department info
|
|
||||||
|
|
||||||
// var technicianUsers = new List<object>();
|
|
||||||
|
|
||||||
// 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
|
#endregion User
|
||||||
|
|
||||||
#region LDAP Login
|
#region LDAP Login
|
||||||
|
|||||||
@ -777,6 +777,7 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory
|
|||||||
ToUserName = i.NextUser?.FullName,
|
ToUserName = i.NextUser?.FullName,
|
||||||
ToStoreName = i.NextStore?.StoreName,
|
ToStoreName = i.NextStore?.StoreName,
|
||||||
ToStationName = i.NextStation?.StationName,
|
ToStationName = i.NextStation?.StationName,
|
||||||
|
ProductImage = i.Item?.Product?.ImageProduct,
|
||||||
i.ToOther,
|
i.ToOther,
|
||||||
i.sendDate,
|
i.sendDate,
|
||||||
i.Action,
|
i.Action,
|
||||||
@ -1503,6 +1504,7 @@ namespace PSTW_CentralSystem.Controllers.API.Inventory
|
|||||||
i.Id,
|
i.Id,
|
||||||
i.FullName,
|
i.FullName,
|
||||||
i.Department,
|
i.Department,
|
||||||
|
i.Department?.DepartmentName,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -552,7 +552,7 @@
|
|||||||
<div class="ms-auto text-end">
|
<div class="ms-auto text-end">
|
||||||
<nav aria-label="breadcrumb">
|
<nav aria-label="breadcrumb">
|
||||||
<ol class="breadcrumb">
|
<ol class="breadcrumb">
|
||||||
<li class="breadcrumb-item"><a href="#">Home</a></li>
|
<li class="breadcrumb-item"><a asp-area="" asp-controller="Home" asp-action="Index">Home</a></li>
|
||||||
<li class="breadcrumb-item active" aria-current="page">
|
<li class="breadcrumb-item active" aria-current="page">
|
||||||
Library
|
Library
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@ -123,7 +123,7 @@
|
|||||||
<!-- ============================================================== -->
|
<!-- ============================================================== -->
|
||||||
<!-- Logo -->
|
<!-- Logo -->
|
||||||
<!-- ============================================================== -->
|
<!-- ============================================================== -->
|
||||||
<a class="navbar-brand" href="index.html">
|
<a class="navbar-brand" asp-area="" asp-controller="Home" asp-action="Index">
|
||||||
<!-- Logo icon -->
|
<!-- Logo icon -->
|
||||||
<b class="logo-icon ps-2">
|
<b class="logo-icon ps-2">
|
||||||
<!--You can put here icon as well // <i class="wi wi-sunset"></i> //-->
|
<!--You can put here icon as well // <i class="wi wi-sunset"></i> //-->
|
||||||
@ -747,7 +747,7 @@
|
|||||||
<!-- footer -->
|
<!-- footer -->
|
||||||
<!-- ============================================================== -->
|
<!-- ============================================================== -->
|
||||||
<footer class="footer text-center">
|
<footer class="footer text-center">
|
||||||
All Rights Reserved by Matrix-admin. Designed and Developed by
|
All Rights Reserved by PSTW. Designed and Developed by
|
||||||
<a href="https://www.wrappixel.com">WrapPixel</a>.
|
<a href="https://www.wrappixel.com">WrapPixel</a>.
|
||||||
</footer>
|
</footer>
|
||||||
<!-- ============================================================== -->
|
<!-- ============================================================== -->
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user