inventory_mobile/pstw_centralizesystem/Areas/ItemMovement.txt
2025-12-15 15:35:35 +08:00

2160 lines
124 KiB
Plaintext
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html dir="ltr" lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<!-- Tell the browser to be responsive to screen width -->
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="keywords"
content="wrappixel, admin dashboard, html css dashboard, web dashboard, bootstrap 5 admin, bootstrap 5, css3 dashboard, bootstrap 5 dashboard, Matrix lite admin bootstrap 5 dashboard, frontend, responsive bootstrap 5 admin template, Matrix admin lite design, Matrix admin lite dashboard bootstrap 5 dashboard template" />
<meta name="description"
content="Matrix Admin Lite Free Version is powerful and clean admin dashboard template, inpired from Bootstrap Framework" />
<meta name="robots" content="noindex,nofollow" />
<title>PSTW Centralize Web System</title>
<!-- Favicon icon -->
<link rel="icon"
type="image/png"
sizes="16x16"
href="/assets/images/favicon.png" />
<!-- Custom CSS -->
<link rel="stylesheet" href="/assets/libs/select2/dist/css/select2.min.css" />
<link rel="stylesheet" href="/assets/libs/jquery-minicolors/jquery.minicolors.css" />
<link rel="stylesheet" href="/assets/libs/bootstrap-datepicker/dist/css/bootstrap-datepicker.min.css" />
<link rel="stylesheet" href="/assets/libs/quill/dist/quill.snow.css" />
<link href="/dist/css/style.min.css" rel="stylesheet" />
<link href="/lib/printjs/print.min.css" rel="stylesheet" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.5/font/bootstrap-icons.css">
<!-- DataTables CSS-->
<link href="/lib/datatables/datatables.css" rel="stylesheet" />
<!-- Vue Js -->
<script src="/js/vue.global.js"></script>
<!-- QR Js -->
<script src="/lib/qrcode/qrcode.min.js"></script>
<!-- HTML5 Shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.4.2/respond.min.js"></script>
<![endif]-->
</head>
<body>
<style>
.btn-teal {
background-color: #20c997; /* Teal color */
color: #ffffff; /* White text */
border: none; /* Remove border */
}
.btn-teal:hover {
background-color: #17a589; /* Darker teal on hover */
color: #ffffff;
}
.btn-teal:focus,
.btn-teal.focus {
box-shadow: 0 0 0 0.2rem rgba(32, 201, 151, 0.5); /* Teal shadow on focus */
}
</style>
<!-- ============================================================== -->
<!-- Preloader - style you can find in spinners.css -->
<!-- ============================================================== -->
<div b-lhtx71ohus id="preloader" class="preloader">
<div b-lhtx71ohus class="lds-ripple">
<div b-lhtx71ohus class="lds-pos"></div>
<div b-lhtx71ohus class="lds-pos"></div>
</div>
</div>
<div b-lhtx71ohus class="modal fade" id="loadingModal" data-bs-backdrop="static" tabindex="-1" aria-hidden="true" style="z-index: 1051;">
<div b-lhtx71ohus class="modal-dialog modal-dialog-centered">
<div b-lhtx71ohus class="modal-content">
<div b-lhtx71ohus class="modal-header">
<button b-lhtx71ohus type="button" class="closeModal" data-dismiss="modal" aria-label="Close">
<span b-lhtx71ohus aria-hidden="true">&times;</span>
</button>
</div>
<div b-lhtx71ohus class="modal-body text-center">
<div b-lhtx71ohus class="spinner-border text-primary" role="status">
<span b-lhtx71ohus class="visually-hidden">Loading...</span>
</div>
<p b-lhtx71ohus class="mt-3">Please wait while we process your request...</p>
</div>
</div>
</div>
</div>
<!-- ============================================================== -->
<!-- Main wrapper - style you can find in pages.scss -->
<!-- ============================================================== -->
<div b-lhtx71ohus id="main-wrapper"
data-layout="vertical"
data-navbarbg="skin5"
data-sidebartype="full"
data-sidebar-position="absolute"
data-header-position="absolute"
data-boxed-layout="full">
<!-- ============================================================== -->
<!-- Topbar header - style you can find in pages.scss -->
<!-- ============================================================== -->
<header b-lhtx71ohus class="topbar" data-navbarbg="skin5">
<nav b-lhtx71ohus class="navbar top-navbar navbar-expand-md navbar-dark">
<div b-lhtx71ohus class="navbar-header" data-logobg="skin5">
<!-- ============================================================== -->
<!-- Logo -->
<!-- ============================================================== -->
<a class="navbar-brand" href="/">
<!-- Logo icon -->
<b b-lhtx71ohus class="logo-icon ps-2">
<!--You can put here icon as well // <i class="wi wi-sunset"></i> //-->
<!-- Dark Logo icon -->
<img b-lhtx71ohus src="/assets/images/logo-icon.png"
alt="homepage"
class="light-logo"
width="25" />
</b>
<!--End Logo icon -->
<!-- Logo text -->
<span b-lhtx71ohus class="logo-text ms-2">
<!-- dark Logo text -->
<img b-lhtx71ohus src="/assets/images/logo-text.png"
alt="homepage"
class="light-logo" />
</span>
<!-- Logo icon -->
<!-- <b class="logo-icon"> -->
<!--You can put here icon as well // <i class="wi wi-sunset"></i> //-->
<!-- Dark Logo icon -->
<!-- <img src="/assets/images/logo-text.png" alt="homepage" class="light-logo" /> -->
<!-- </b> -->
<!--End Logo icon -->
</a>
<!-- ============================================================== -->
<!-- End Logo -->
<!-- ============================================================== -->
<!-- ============================================================== -->
<!-- Toggle which is visible on mobile only -->
<!-- ============================================================== -->
<a b-lhtx71ohus class="nav-toggler waves-effect waves-light d-block d-md-none"
href="javascript:void(0)">
<i b-lhtx71ohus class="ti-menu ti-close"></i>
</a>
</div>
<!-- ============================================================== -->
<!-- End Logo -->
<!-- ============================================================== -->
<div b-lhtx71ohus class="navbar-collapse collapse"
id="navbarSupportedContent"
data-navbarbg="skin5">
<!-- ============================================================== -->
<!-- toggle and nav items -->
<!-- ============================================================== -->
<ul b-lhtx71ohus class="navbar-nav float-start me-auto">
<li b-lhtx71ohus class="nav-item d-none d-lg-block">
<a b-lhtx71ohus class="nav-link sidebartoggler waves-effect waves-light"
href="javascript:void(0)"
data-sidebartype="mini-sidebar">
<i b-lhtx71ohus class="mdi mdi-menu font-24"></i>
</a>
</li>
<li b-lhtx71ohus class="nav-item">
<a class="nav-link" href="/">Home</a>
</li>
<li b-lhtx71ohus class="nav-item">
<a class="nav-link" href="/Home/Privacy">Privacy</a>
</li>
<!-- ============================================================== -->
<!-- create new -->
<!-- ============================================================== -->
<!--<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle"
href="#"
id="navbarDropdown"
role="button"
data-bs-toggle="dropdown"
aria-expanded="false">
<span class="d-none d-md-block">
Create New <i class="fa fa-angle-down"></i>
</span>
<span class="d-block d-md-none">
<i class="fa fa-plus"></i>
</span>
</a>
<ul class="dropdown-menu" aria-labelledby="navbarDropdown">
<li><a class="dropdown-item" href="#">Action</a></li>
<li><a class="dropdown-item" href="#">Another action</a></li>
<li><hr class="dropdown-divider" /></li>
<li>
<a class="dropdown-item" href="#">Something else here</a>
</li>
</ul>
</li> b-lhtx71ohus-->
<!-- ============================================================== -->
<!-- Search -->
<!-- ============================================================== -->
<!--<li class="nav-item search-box">
<a class="nav-link waves-effect waves-dark"
href="javascript:void(0)">
<i class="mdi mdi-magnify fs-4"></i>
</a>
<form class="app-search position-absolute">
<input type="text"
class="form-control"
placeholder="Search &amp; enter" />
<a class="srh-btn"><i class="mdi mdi-window-close"></i></a>
</form>
</li> b-lhtx71ohus-->
</ul>
<!-- ============================================================== -->
<!-- Right side toggle and nav items -->
<!-- ============================================================== -->
<ul b-lhtx71ohus class="navbar-nav float-end">
<!-- ============================================================== -->
<!-- Comment -->
<!-- ============================================================== -->
<li class="nav-item d-inline">
<a id="manage" class="nav-link" title="Manage" href="/Identity/Account/Manage">
Hello alim.aidrus@pstw.com.my!
</a>
</li>
<li class="nav-item d-inline">
<a id="logout" class="nav-link" href="javascript:void(0);" onclick="logout()">Logout</a>
</li>
<input name="__RequestVerificationToken" type="hidden" value="CfDJ8N0yQF8b8n9Ln4B-pzXVXnLgSKsm2oTGnTl08ApyqK4BkXzkb9QC17u7owmEsd8L7tDZfSfBPXARyM8WeueRKY9CPCg2C3JNJnbxbb4hkuO2JIkJN78yeqzwg4qAhs6uNvLKDXnNItAou3WPGEd88fZLU63MkzzfB_SawAOSOiINlvyEOwVSMtlu2p9SBfoK7Q" /> <script>
function logout() {
const returnUrl = '/';
fetch('/Identity/Account/Logout', {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
},
body: `__RequestVerificationToken=${document.querySelector('input[name="__RequestVerificationToken"]').value}&returnUrl=${encodeURIComponent(returnUrl)}`
}).then(response => {
if (response.ok) {
window.location.href = returnUrl;
} else {
alert('Logout failed.');
}
}).catch(error => {
console.error('Logout error:', error);
});
}
</script>
<!-- ============================================================== -->
<!-- End Comment -->
<!-- ============================================================== -->
<!-- ============================================================== -->
<!-- Messages -->
<!-- ============================================================== -->
<!-- ============================================================== -->
<!-- End Messages -->
<!-- ============================================================== -->
<!-- ============================================================== -->
<!-- User profile and search -->
<!-- ============================================================== -->
<!-- ============================================================== -->
<!-- User profile and search -->
<!-- ============================================================== -->
</ul>
</div>
</nav>
</header>
<!-- ============================================================== -->
<!-- End Topbar header -->
<!-- ============================================================== -->
<!-- ============================================================== -->
<!-- Left Sidebar - style you can find in sidebar.scss -->
<!-- ============================================================== -->
<aside b-lhtx71ohus class="left-sidebar" data-sidebarbg="skin5">
<!-- Sidebar scroll-->
<div b-lhtx71ohus class="scroll-sidebar">
<!-- Sidebar navigation-->
<nav b-lhtx71ohus class="sidebar-nav">
<ul b-lhtx71ohus id="sidebarnav" class="pt-4">
<li b-lhtx71ohus class="sidebar-item">
<a b-lhtx71ohus class="sidebar-link has-arrow waves-effect waves-dark"
href="javascript:void(0)"
aria-expanded="false">
<i b-lhtx71ohus class="mdi mdi-receipt"></i><span b-lhtx71ohus class="hide-menu">Administrator </span>
</a>
<ul b-lhtx71ohus aria-expanded="false" class="collapse first-level">
<li b-lhtx71ohus class="sidebar-item">
<a class="sidebar-link waves-effect waves-dark sidebar-link" aria-expanded="false" href="/Admin">
<i b-lhtx71ohus class="mdi mdi-view-dashboard"></i><span b-lhtx71ohus class="hide-menu">Admin Dashboard</span>
</a>
</li>
<li b-lhtx71ohus class="sidebar-item">
<a class="sidebar-link waves-effect waves-dark sidebar-link" aria-expanded="false" href="/Admin/ModuleAdmin">
<i b-lhtx71ohus class="mdi mdi-view-dashboard"></i><span b-lhtx71ohus class="hide-menu">Module Administration</span>
</a>
</li>
</ul>
</li>
<li b-lhtx71ohus class="sidebar-item">
<a b-lhtx71ohus class="sidebar-link waves-effect waves-dark sidebar-link"
href="#"
aria-expanded="false">
<i b-lhtx71ohus class="mdi mdi-view-dashboard"></i><span b-lhtx71ohus class="hide-menu">Dashboard</span>
</a>
</li>
<li b-lhtx71ohus class="sidebar-item">
<a b-lhtx71ohus class="sidebar-link has-arrow waves-effect waves-dark"
href="javascript:void(0)"
aria-expanded="false">
<i b-lhtx71ohus class="mdi mdi-receipt"></i><span b-lhtx71ohus class="hide-menu">Inventory </span>
</a>
<ul b-lhtx71ohus aria-expanded="false" class="collapse first-level">
<li b-lhtx71ohus class="sidebar-item">
<a class="sidebar-link waves-effect waves-dark sidebar-link" aria-expanded="false" href="/Inventory/InventoryMaster/AdminDashboard">
<i b-lhtx71ohus class="mdi mdi-view-dashboard"></i><span b-lhtx71ohus class="hide-menu">Admin Dashboard</span>
</a>
</li>
<li b-lhtx71ohus class="sidebar-item">
<a class="sidebar-link waves-effect waves-dark sidebar-link" aria-expanded="false" href="/Inventory/InventoryMaster/ProductRegistration">
<i b-lhtx71ohus class="mdi mdi-view-dashboard"></i><span b-lhtx71ohus class="hide-menu">Product Registration</span>
</a>
</li>
<li b-lhtx71ohus class="sidebar-item">
<a class="sidebar-link waves-effect waves-dark sidebar-link" aria-expanded="false" href="/Inventory/InventoryMaster/ItemRegistration">
<i b-lhtx71ohus class="mdi mdi-view-dashboard"></i><span b-lhtx71ohus class="hide-menu">Item Registration</span>
</a>
</li>
</ul>
</li>
<li b-lhtx71ohus class="sidebar-item">
<a b-lhtx71ohus class="sidebar-link has-arrow waves-effect waves-dark"
href="javascript:void(0)"
aria-expanded="false">
<i b-lhtx71ohus class="mdi mdi-receipt"></i><span b-lhtx71ohus class="hide-menu">Report</span>
</a>
<ul b-lhtx71ohus aria-expanded="false" class="collapse first-level">
<li b-lhtx71ohus class="sidebar-item">
<a class="sidebar-link waves-effect waves-dark sidebar-link" aria-expanded="false" href="/Report/Reporting">
<i b-lhtx71ohus class="mdi mdi-view-dashboard"></i><span b-lhtx71ohus class="hide-menu">Admin Dashboard</span>
</a>
</li>
<li b-lhtx71ohus class="sidebar-item">
<a class="sidebar-link waves-effect waves-dark sidebar-link" aria-expanded="false" href="/Report/Reporting/InventoryReport">
<i b-lhtx71ohus class="mdi mdi-view-dashboard"></i><span b-lhtx71ohus class="hide-menu">Inventory Report</span>
</a>
</li>
<!--MMS-->
<li b-lhtx71ohus class="sidebar-item">
<a b-lhtx71ohus class="sidebar-link has-arrow waves-effect waves-dark"
href="javascript:void(0)" aria-expanded="false">
<i b-lhtx71ohus class="mdi mdi-view-dashboard"></i><span b-lhtx71ohus class="hide-menu">MMS</span>
</a>
<ul b-lhtx71ohus aria-expanded="false" class="collapse first-level">
<!-- Marine subsection -->
<li b-lhtx71ohus class="sidebar-item">
<a b-lhtx71ohus class="sidebar-link has-arrow waves-effect waves-dark"
href="javascript:void(0)" aria-expanded="false">
<i b-lhtx71ohus class="mdi mdi-view-dashboard"></i><span b-lhtx71ohus class="hide-menu">Marine</span>
</a>
<ul b-lhtx71ohus aria-expanded="false" class="collapse second-level">
<!-- Tar Ball Sampling Form link -->
<li b-lhtx71ohus class="sidebar-item">
<a class="sidebar-link waves-effect waves-dark" aria-expanded="false" href="/MMS/Marine/TarBallForm">
<i b-lhtx71ohus class="mdi mdi-view-dashboard"></i><span b-lhtx71ohus class="hide-menu">Tarball Report</span>
</a>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li b-lhtx71ohus class="sidebar-item">
<a b-lhtx71ohus class="sidebar-link has-arrow waves-effect waves-dark"
href="javascript:void(0)"
aria-expanded="false">
<i b-lhtx71ohus class="mdi mdi-receipt"></i><span b-lhtx71ohus class="hide-menu">User Overtime</span>
</a>
<ul b-lhtx71ohus aria-expanded="false" class="collapse first-level">
<li b-lhtx71ohus class="sidebar-item">
<a class="sidebar-link waves-effect waves-dark sidebar-link" aria-expanded="false" href="/OTcalculate/Overtime/OtRegister">
<i b-lhtx71ohus class="mdi mdi-view-dashboard"></i><span b-lhtx71ohus class="hide-menu">OT Register</span>
</a>
</li>
<li b-lhtx71ohus class="sidebar-item">
<a class="sidebar-link waves-effect waves-dark sidebar-link" aria-expanded="false" href="/OTcalculate/Overtime/OtRecords">
<i b-lhtx71ohus class="mdi mdi-view-dashboard"></i><span b-lhtx71ohus class="hide-menu">OT Records</span>
</a>
</li>
<li b-lhtx71ohus class="sidebar-item">
<a class="sidebar-link waves-effect waves-dark sidebar-link" aria-expanded="false" href="/OTcalculate/Overtime/OtStatus">
<i b-lhtx71ohus class="mdi mdi-view-dashboard"></i><span b-lhtx71ohus class="hide-menu">OT Status</span>
</a>
</li>
</ul>
</li>
<li b-lhtx71ohus class="sidebar-item">
<a b-lhtx71ohus class="sidebar-link has-arrow waves-effect waves-dark"
href="javascript:void(0)"
aria-expanded="false">
<i b-lhtx71ohus class="mdi mdi-receipt"></i><span b-lhtx71ohus class="hide-menu">Overtime Approval</span>
</a>
<ul b-lhtx71ohus aria-expanded="false" class="collapse first-level">
<li b-lhtx71ohus class="sidebar-item">
<a class="sidebar-link waves-effect waves-dark sidebar-link" aria-expanded="false" href="/OTcalculate/ApprovalDashboard/Approval">
<i b-lhtx71ohus class="mdi mdi-view-dashboard"></i><span b-lhtx71ohus class="hide-menu">Pending Approval</span>
</a>
</li>
</ul>
</li>
<li b-lhtx71ohus class="sidebar-item">
<a b-lhtx71ohus class="sidebar-link has-arrow waves-effect waves-dark"
href="javascript:void(0)"
aria-expanded="false">
<i b-lhtx71ohus class="mdi mdi-receipt"></i><span b-lhtx71ohus class="hide-menu">HR Dashboard</span>
</a>
<ul b-lhtx71ohus aria-expanded="false" class="collapse first-level">
<li b-lhtx71ohus class="sidebar-item">
<a class="sidebar-link waves-effect waves-dark sidebar-link" aria-expanded="false" href="/OTcalculate/HrDashboard/Settings">
<i b-lhtx71ohus class="mdi mdi-view-dashboard"></i><span b-lhtx71ohus class="hide-menu">Settings</span>
</a>
</li>
</ul>
</li>
<li b-lhtx71ohus class="sidebar-item">
<a b-lhtx71ohus class="sidebar-link has-arrow waves-effect waves-dark"
href="javascript:void(0)"
aria-expanded="false">
<i b-lhtx71ohus class="mdi mdi-receipt"></i><span b-lhtx71ohus class="hide-menu">Rooms Booking</span>
</a>
<ul b-lhtx71ohus aria-expanded="false" class="collapse first-level">
<li b-lhtx71ohus class="sidebar-item">
<a class="sidebar-link waves-effect waves-dark sidebar-link" aria-expanded="false" href="/Bookings/Bookings/Managers">
<i b-lhtx71ohus class="mdi mdi-view-dashboard"></i><span b-lhtx71ohus class="hide-menu">Assign</span>
</a>
</li>
<li b-lhtx71ohus class="sidebar-item">
<a class="sidebar-link waves-effect waves-dark sidebar-link" aria-expanded="false" href="/Bookings/Bookings">
<i b-lhtx71ohus class="mdi mdi-view-dashboard"></i><span b-lhtx71ohus class="hide-menu">List</span>
</a>
</li>
<li b-lhtx71ohus class="sidebar-item">
<a class="sidebar-link waves-effect waves-dark sidebar-link" aria-expanded="false" href="/Bookings/Bookings/Calendar">
<i b-lhtx71ohus class="mdi mdi-view-dashboard"></i><span b-lhtx71ohus class="hide-menu">Calendar</span>
</a>
</li>
<li b-lhtx71ohus class="sidebar-item">
<a class="sidebar-link waves-effect waves-dark sidebar-link" aria-expanded="false" href="/Bookings/Bookings/Room">
<i b-lhtx71ohus class="mdi mdi-view-dashboard"></i><span b-lhtx71ohus class="hide-menu">Rooms</span>
</a>
</li>
</ul>
</li>
<li b-lhtx71ohus class="sidebar-item">
<a b-lhtx71ohus class="sidebar-link has-arrow waves-effect waves-dark"
href="javascript:void(0)"
aria-expanded="false">
<i b-lhtx71ohus class="mdi mdi-receipt"></i><span b-lhtx71ohus class="hide-menu">IT Request Form</span>
</a>
<ul b-lhtx71ohus aria-expanded="false" class="collapse first-level">
<li b-lhtx71ohus class="sidebar-item">
<a class="sidebar-link waves-effect waves-dark sidebar-link" aria-expanded="false" href="/IT/ApprovalDashboard/Admin">
<i b-lhtx71ohus class="mdi mdi-view-dashboard"></i><span b-lhtx71ohus class="hide-menu">Assignings</span>
</a>
</li>
<li b-lhtx71ohus class="sidebar-item">
<a class="sidebar-link waves-effect waves-dark sidebar-link" aria-expanded="false" href="/IT/ApprovalDashboard/Create">
<i b-lhtx71ohus class="mdi mdi-view-dashboard"></i><span b-lhtx71ohus class="hide-menu">Registeration</span>
</a>
</li>
<li b-lhtx71ohus class="sidebar-item">
<a class="sidebar-link waves-effect waves-dark sidebar-link" aria-expanded="false" href="/IT/ApprovalDashboard/MyRequests">
<i b-lhtx71ohus class="mdi mdi-view-dashboard"></i><span b-lhtx71ohus class="hide-menu">My Requests</span>
</a>
</li>
<li b-lhtx71ohus class="sidebar-item">
<a class="sidebar-link waves-effect waves-dark sidebar-link" aria-expanded="false" href="/IT/ApprovalDashboard/Approval">
<i b-lhtx71ohus class="mdi mdi-view-dashboard"></i><span b-lhtx71ohus class="hide-menu">Approval</span>
</a>
</li>
</ul>
</li>
<!-- <li class="sidebar-item">
<a class="sidebar-link waves-effect waves-dark sidebar-link"
href="charts.html"
aria-expanded="false">
<i class="mdi mdi-chart-bar"></i><span class="hide-menu">Charts</span>
</a>
</li>
<li class="sidebar-item">
<a class="sidebar-link waves-effect waves-dark sidebar-link"
href="widgets.html"
aria-expanded="false">
<i class="mdi mdi-chart-bubble"></i><span class="hide-menu">Widgets</span>
</a>
</li>
<li class="sidebar-item">
<a class="sidebar-link waves-effect waves-dark sidebar-link"
href="tables.html"
aria-expanded="false">
<i class="mdi mdi-border-inside"></i><span class="hide-menu">Tables</span>
</a>
</li>
<li class="sidebar-item">
<a class="sidebar-link waves-effect waves-dark sidebar-link"
href="grid.html"
aria-expanded="false">
<i class="mdi mdi-blur-linear"></i><span class="hide-menu">Full Width</span>
</a>
</li>
<li class="sidebar-item">
<a class="sidebar-link has-arrow waves-effect waves-dark"
href="javascript:void(0)"
aria-expanded="false">
<i class="mdi mdi-receipt"></i><span class="hide-menu">Forms </span>
</a>
<ul aria-expanded="false" class="collapse first-level">
<li class="sidebar-item">
<a href="form-basic.html" class="sidebar-link">
<i class="mdi mdi-note-outline"></i><span class="hide-menu"> Form Basic </span>
</a>
</li>
<li class="sidebar-item">
<a href="form-wizard.html" class="sidebar-link">
<i class="mdi mdi-note-plus"></i><span class="hide-menu"> Form Wizard </span>
</a>
</li>
</ul>
</li>
<li class="sidebar-item">
<a class="sidebar-link waves-effect waves-dark sidebar-link"
href="pages-buttons.html"
aria-expanded="false">
<i class="mdi mdi-relative-scale"></i><span class="hide-menu">Buttons</span>
</a>
</li>
<li class="sidebar-item">
<a class="sidebar-link has-arrow waves-effect waves-dark"
href="javascript:void(0)"
aria-expanded="false">
<i class="mdi mdi-face"></i><span class="hide-menu">Icons </span>
</a>
<ul aria-expanded="false" class="collapse first-level">
<li class="sidebar-item">
<a href="icon-material.html" class="sidebar-link">
<i class="mdi mdi-emoticon"></i><span class="hide-menu"> Material Icons </span>
</a>
</li>
<li class="sidebar-item">
<a href="icon-fontawesome.html" class="sidebar-link">
<i class="mdi mdi-emoticon-cool"></i><span class="hide-menu"> Font Awesome Icons </span>
</a>
</li>
</ul>
</li>
<li class="sidebar-item">
<a class="sidebar-link waves-effect waves-dark sidebar-link"
href="pages-elements.html"
aria-expanded="false">
<i class="mdi mdi-pencil"></i><span class="hide-menu">Elements</span>
</a>
</li>
<li class="sidebar-item">
<a class="sidebar-link has-arrow waves-effect waves-dark"
href="javascript:void(0)"
aria-expanded="false">
<i class="mdi mdi-move-resize-variant"></i><span class="hide-menu">Addons </span>
</a>
<ul aria-expanded="false" class="collapse first-level">
<li class="sidebar-item">
<a href="index2.html" class="sidebar-link">
<i class="mdi mdi-view-dashboard"></i><span class="hide-menu"> Dashboard-2 </span>
</a>
</li>
<li class="sidebar-item">
<a href="pages-gallery.html" class="sidebar-link">
<i class="mdi mdi-multiplication-box"></i><span class="hide-menu"> Gallery </span>
</a>
</li>
<li class="sidebar-item">
<a href="pages-calendar.html" class="sidebar-link">
<i class="mdi mdi-calendar-check"></i><span class="hide-menu"> Calendar </span>
</a>
</li>
<li class="sidebar-item">
<a href="pages-invoice.html" class="sidebar-link">
<i class="mdi mdi-bulletin-board"></i><span class="hide-menu"> Invoice </span>
</a>
</li>
<li class="sidebar-item">
<a href="pages-chat.html" class="sidebar-link">
<i class="mdi mdi-message-outline"></i><span class="hide-menu"> Chat Option </span>
</a>
</li>
</ul>
</li>
<li class="sidebar-item">
<a class="sidebar-link has-arrow waves-effect waves-dark"
href="javascript:void(0)"
aria-expanded="false">
<i class="mdi mdi-account-key"></i><span class="hide-menu">Authentication </span>
</a>
<ul aria-expanded="false" class="collapse first-level">
<li class="sidebar-item">
<a href="authentication-login.html" class="sidebar-link">
<i class="mdi mdi-all-inclusive"></i><span class="hide-menu"> Login </span>
</a>
</li>
<li class="sidebar-item">
<a href="authentication-register.html" class="sidebar-link">
<i class="mdi mdi-all-inclusive"></i><span class="hide-menu"> Register </span>
</a>
</li>
</ul>
</li>
<li class="sidebar-item">
<a class="sidebar-link has-arrow waves-effect waves-dark"
href="javascript:void(0)"
aria-expanded="false">
<i class="mdi mdi-alert"></i><span class="hide-menu">Errors </span>
</a>
<ul aria-expanded="false" class="collapse first-level">
<li class="sidebar-item">
<a href="error-403.html" class="sidebar-link">
<i class="mdi mdi-alert-octagon"></i><span class="hide-menu"> Error 403 </span>
</a>
</li>
<li class="sidebar-item">
<a href="error-404.html" class="sidebar-link">
<i class="mdi mdi-alert-octagon"></i><span class="hide-menu"> Error 404 </span>
</a>
</li>
<li class="sidebar-item">
<a href="error-405.html" class="sidebar-link">
<i class="mdi mdi-alert-octagon"></i><span class="hide-menu"> Error 405 </span>
</a>
</li>
<li class="sidebar-item">
<a href="error-500.html" class="sidebar-link">
<i class="mdi mdi-alert-octagon"></i><span class="hide-menu"> Error 500 </span>
</a>
</li>
</ul>
</li>
<li class="sidebar-item p-3">
<a href="https://github.com/wrappixel/matrix-admin-bt5"
target="_blank"
class="
w-100
btn btn-cyan
d-flex
align-items-center
text-white
">
<i class="mdi mdi-cloud-download font-20 me-2"></i>Download
Free
</a>
</li> -->
</ul>
</nav>
<!-- End Sidebar navigation -->
</div>
<!-- End Sidebar scroll-->
</aside>
<!-- ============================================================== -->
<!-- End Left Sidebar - style you can find in sidebar.scss -->
<!-- ============================================================== -->
<!-- ============================================================== -->
<!-- Page wrapper -->
<!-- ============================================================== -->
<div b-lhtx71ohus class="page-wrapper">
<!-- ============================================================== -->
<!-- Bread crumb and right sidebar toggle -->
<!-- ============================================================== -->
<div b-lhtx71ohus class="page-breadcrumb">
<div b-lhtx71ohus class="row">
<div b-lhtx71ohus class="col-12 d-flex no-block align-items-center">
<h1 b-lhtx71ohus class="m-0 page-title">Item Movement</h1>
<div b-lhtx71ohus class="ms-auto text-end">
<nav b-lhtx71ohus aria-label="breadcrumb">
<ol b-lhtx71ohus class="breadcrumb">
<li b-lhtx71ohus class="breadcrumb-item"><a b-lhtx71ohus href="#">Home</a></li>
<li b-lhtx71ohus class="breadcrumb-item active" aria-current="page">
Library
</li>
</ol>
</nav>
</div>
</div>
</div>
</div>
<!-- ============================================================== -->
<!-- End Bread crumb and right sidebar toggle -->
<!-- ============================================================== -->
<!-- ============================================================== -->
<!-- Container fluid -->
<!-- ============================================================== -->
<div b-lhtx71ohus class="container-fluid">
<!-- ============================================================== -->
<!-- Start Page Content -->
<!-- ============================================================== -->
<div b-lhtx71ohus class="row my-1">
<style>
@font-face {
font-family: 'OCR-A';
src: url('../assets/fonts/ocraext.ttf');
}
.QrPrintFont {
font-family: 'OCR-A', monospace;
}
.table td img {
display: block !important;
}
.text-true {
color: green;
}
.text-false {
color: red;
}
.text-primary {
color: blue; /* Warna asal untuk 'Receive' */
}
.text-warning {
color: orange; /* Warna oren untuk 'Return' */
}
.text-success {
color: greenyellow;
}
.text-numb {
color: brown;
}
.text-weird {
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;
}
</style>
<div class="row">
<div class="col-6 col-md-6 col-lg-3">
<div class="card card-hover">
<a href="/Inventory/InventoryMaster/SupplierRegistration">
<div class="box bg-info text-center">
<h1 class="font-light text-white">
<i class="mdi mdi-truck"></i>
</h1>
<h6 class="text-white">Supplier</h6>
</div>
</a>
</div>
</div>
<div class="col-6 col-md-6 col-lg-3">
<div class="card card-hover">
<a href="/Inventory/InventoryMaster/ManifacturerRegistration">
<div class="box bg-warning text-center">
<h1 class="font-light text-white">
<i class="mdi mdi-factory"></i>
</h1>
<h6 class="text-white">Manufacturer</h6>
</div>
</a>
</div>
</div>
<div class="col-6 col-md-6 col-lg-3">
<a href="/Inventory/InventoryMaster/ProductRegistration">
<div class="card card-hover">
<div class="box bg-cyan text-center">
<h1 class="font-light text-white">
<i class="mdi mdi-checkbox-multiple-blank"></i>
</h1>
<h6 class="text-white">Product</h6>
</div>
</div>
</a>
</div>
<div class="col-6 col-md-6 col-lg-3">
<div class="card card-hover">
<a href="/Inventory/InventoryMaster/ItemRegistration">
<div class="box bg-success text-center">
<h1 class="font-light text-white">
<i class="mdi mdi-checkbox-multiple-blank-circle"></i>
</h1>
<h6 class="text-white">Item</h6>
</div>
</a>
</div>
</div>
<div class="col-6 col-md-6 col-lg-3">
<div class="card card-hover">
<a href="/Inventory/InventoryMaster/StationRegistration">
<div class="box bg-warning text-center">
<h1 class="font-light text-white">
<i class="mdi mdi-truck"></i>
</h1>
<h6 class="text-white">Station</h6>
</div>
</a>
</div>
</div>
<div class="col-6 col-md-6 col-lg-3">
<div class="card card-hover">
<a href="/Inventory/InventoryMaster/ItemMovement">
<div class="box bg-cyan text-center">
<h1 class="font-light text-white">
<i class="mdi mdi-factory"></i>
</h1>
<h6 class="text-white">Item Movement</h6>
</div>
</a>
</div>
</div>
<div class="col-6 col-md-6 col-lg-3">
<div class="card card-hover">
<a href="/Inventory/InventoryMaster/ItemRequestMaster">
<div class="box bg-info text-center">
<h1 class="font-light text-white">
<i class="mdi mdi-checkbox-multiple-blank"></i>
</h1>
<h6 class="text-white">Product Request</h6>
</div>
</a>
</div>
</div>
<div class="col-6 col-md-6 col-lg-3">
<div class="card card-hover">
<a href="/Inventory/InventoryMaster/QrMaster">
<div class="box bg-success text-center">
<h1 class="font-light text-white">
<i class="mdi mdi-checkbox-multiple-blank-circle"></i>
</h1>
<h6 class="text-white">Scan Items</h6>
</div>
</a>
</div>
</div>
</div>
<div id="registerItem" class="row">
<div class="row mb-3" >
<h2 for="sortSelect" class="col-sm-1 col-form-h2" style="min-width:140px;">Sort by:</h2>
<div class="col-sm-4">
<select id="sortSelect" class="form-control" v-model="sortBy" v-on:change="handleSorting">
<option value="all" >All</option>
<option value="item">Item</option>
<option value="station">Station</option>
<option value="logs" v-if="currentRole == 'Super Admin'">Logs</option>
</select>
</div>
</div>
<div class="row mb-3" v-if="sortBy === 'item'">
<h4 class="col-sm-1 col-form-h2" style="min-width:140px;">Search Item:</h4>
<div class="col-sm-4">
<input type="text" class="form-control" v-model="searchQuery" placeholder="Search by item code...">
</div>
</div>
<div class="row mb-3" v-if="sortBy === 'station'">
<h4 class="col-sm-1 col-form-h2" style="min-width:150px;">Search Station:</h4>
<div class="col-sm-4">
<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 v-if="sortBy === 'all'">
<div class="row card">
<div class="card-header">
<h2>Pending Item Transit</h2>
</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="itemMovementNotCompleteDatatable" style="width:100%;border-style: solid; border-width: 1px"></table>
</div>
</div>
<div class="row card">
<div class="card-header">
<h2>Complete Item Movement</h2>
</div>
<div class="card-header">
<h4>All Item Movement</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="itemMovementCompleteDatatable" style="width:100%;border-style: solid; border-width: 1px"></table>
</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 v-if="sortBy === 'logs'">
<div v-if="loading">
<div class="spinner-border text-info" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
<div class="row card">
<div class="card-header">
<h2>Item Movement List</h2>
</div>
<div class="card-body">
<table class="table table-bordered table-hover table-striped no-wrap" id="itemDatatable"
style=" width:100%;border-style: solid; border-width: 1px"></table>
</div>
</div>
</div>
<div v-if="sortBy === 'item'">
<div v-if="loading">
<div class="spinner-border text-info" role="status">
<span class="visually-hidden">Loading...</span>
</div>
</div>
<div v-for="(group, itemId) in paginatedItems" :key="itemId" class="row card">
<div class="card-header d-flex justify-content-between align-items-center">
<h2 v-if="group.uniqueID">Item : {{ group.uniqueID }}</h2>
<h2 v-else>Item : No Item Tracked</h2>
<button class="btn btn-light" v-on:click="toggleCategory(itemId)">
<i :class="categoryVisible[itemId] ? 'fas fa-chevron-up' : 'fas fa-chevron-down'"></i> Show Details
</button>
</div>
<!-- Hide all details unless button is clicked -->
<div v-show="categoryVisible[itemId]" class="card-body">
<div v-for="(movement, index) in group.movements.sort((a, b) => a.id - b.id).reverse()" :key="movement.id" class="movement-row">
<!-- 📌 Show Only Latest Movement -->
<div v-if="index === 0" class="row">
<strong>Latest Movement</strong>
<div class="col-md-12 d-flex flex-wrap align-items-center gap-3 p-2 border-bottom">
<!-- Movement Type -->
<h3 :class="{'text-primary': movement.toOther === 'On Delivery', 'text-warning': movement.toOther === 'Return',
'text-success': movement.toStation !== null, 'text-info': movement.action === 'Assign' && movement.toStation === null,
'text-numb': movement.toOther === 'Faulty' || movement.toOther === 'Calibration' || movement.toOther === 'Repair',
'text-weird': movement.action === 'Register'}"
class="flex-shrink-0 text-nowrap" style="max-width:140px; min-width:90px;">
{{ movement.toOther === 'Return' ? 'Return' : (movement.toOther === 'On Delivery' ? 'Receive' : ( movement.toStation !== null ? 'Change' : ( movement.toOther == 'Faulty' || movement.toOther == 'Calibration' || movement.toOther == 'Repair' ? movement.toOther : ( movement.action == 'Register' ? 'Register' : 'Assign')))) }}
</h3>
<!-- Send Date -->
<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' : movement.action === 'Register' ? 'Register Date' : 'Send Date'}}</h4>
<span class="fixed-value text-truncate">{{movement.action !== 'Register' ? movement.sendDate : movement.date }}</span>
</div>
<!-- Receive Date -->
<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>
<span class="fixed-value text-truncate" style="max-width:160px;">{{ movement.receiveDate || 'Not arrive' }}</span>
</div>
<!-- Action -->
<div class="d-flex flex-wrap align-items-center gap-2 flex-grow-1" style="max-width:150px; min-width:150px;">
<h4 class="fixed-labelStatus m-0 text-nowrap">Action:</h4>
<span class="fixed-value text-truncate">{{ movement.action }}</span>
</div>
<!-- Status -->
<div class="d-flex flex-wrap align-items-center gap-2 flex-grow-1" style="max-width:160px; min-width:160px;">
<h4 class="fixed-labelStatus m-0 text-nowrap">Status:</h4>
<span class="fixed-value text-truncate" style="max-width:90px;">{{ movement.latestStatus || movement.toOther }}</span>
</div>
<!-- More Details Button -->
<button class="btn btn-info btn-sm ms-auto" v-on:click="toggleDetails(movement.id)">
More Details
</button>
<!-- Completion Status -->
<h4 :class="movement.action == 'Register' ? 'text-success' : movement.movementComplete == 1 && movement.latestStatus !== 'Ready To Deploy' ? 'text-success' : movement.toOther === 'Repair' || movement.toOther === 'Calibration' && movement.latestStatus === 'Ready To Deploy' ? 'text-success' :'text-danger'"
class="text-nowrap ms-3">
{{ movement.action == 'Register' ? 'Complete' : (movement.movementComplete == 1 && movement.latestStatus !== 'Ready To Deploy' ? 'Complete' : ( movement.toOther === 'Repair' || movement.toOther === 'Calibration' && movement.latestStatus === 'Ready To Deploy' ? 'Complete' : (movement.latestStatus === 'Ready To Deploy' ? 'Canceled' : 'Incomplete'))) }}
</h4>
</div>
<div v-show="detailsVisible[movement.id]" class="col-md-12 mt-2">
<div class="row">
<div class="col-md-4 text-center">
<!-- Conditionally render Start Icon -->
<i v-if="movement.toStation" class="fas fa-map-marker-alt"></i>
<i v-else-if="movement.toOther !== 'On Delivery'" class="fas fa-user fa-2x"></i>
<i v-else class="fas fa-warehouse fa-2x"></i>
<p><strong>Start</strong></p>
<p><strong>User:</strong> {{ movement.toUserName }}</p>
<p><strong>Station:</strong> {{ movement.toStationName }}</p>
<p><strong>Store:</strong> {{ movement.toStoreName }}</p>
</div>
<div class="col-md-4 text-center">
<p></p>
<i class="fas fa-arrow-right fa-2x"></i>
<p>{{ movement.latestStatus || movement.toOther }}</p>
<p>
<button class="btn btn-info btn-sm ms-auto" v-on:click="remark(movement.remark)" v-if="movement.toOther !== 'On Delivery'">
Remark
</button>
</p>
<p>
<button class="btn btn-info btn-sm ms-auto" v-on:click="consignmentNote(movement.consignmentNote)" v-if="movement.toOther !== 'On Delivery'">
Consignment Note
</button>
</p>
</div>
<div class="col-md-4 text-center">
<!-- Conditionally render End Icon -->
<i v-if="movement.lastStation" class="fas fa-map-marker-alt"></i>
<i v-else-if="movement.toOther !== 'On Delivery'" class="fas fa-warehouse fa-2x"></i>
<i v-else class="fas fa-user fa-2x"></i>
<p><strong>End</strong></p>
<p v-if="movement.lastUser !== null"><strong>User:</strong> {{ movement.lastUserName }}</p>
<p v-if="movement.lastStation !== null"><strong>Station:</strong> {{ movement.lastStationName }}</p>
<p v-if="movement.lastStore !== null"><strong>Store:</strong> {{ movement.lastStoreName }}</p>
</div>
</div>
</div>
</div>
</div>
<!-- 📌 Single View History Button -->
<button class="btn btn-light w-100 text-left" v-on:click="toggleHistory(itemId)">
<i :class="historyVisible[itemId] ? 'fas fa-chevron-up' : 'fas fa-chevron-down'"></i> View History
</button>
<div v-show="historyVisible[itemId]" class="history-row">
<div v-for="(movement, i) in group.movements.slice(1)" :key="i" class="row mt-2">
<div class="col-md-12 d-flex flex-wrap align-items-center gap-3 p-2 border-bottom">
<!-- Movement Type -->
<h3 :class="{'text-primary': movement.toOther === 'On Delivery', 'text-warning': movement.toOther === 'Return',
'text-success': movement.toStation !== null, 'text-info': movement.action === 'Assign' && movement.toStation === null,
'text-numb': movement.toOther === 'Faulty' || movement.toOther === 'Calibration' || movement.toOther === 'Repair',
'text-weird': movement.action === 'Register'}"
class="flex-shrink-0 text-nowrap" style="max-width:140px; min-width:90px;">
{{ movement.toOther === 'Return' ? 'Return' : (movement.toOther === 'On Delivery' ? 'Receive' :
( movement.toStation !== null ? 'Change' :
( movement.toOther == 'Faulty' || movement.toOther == 'Calibration' || movement.toOther == 'Repair' ? movement.toOther :
( movement.action == 'Register' ? 'Register' : 'Assign')))) }}
</h3>
<!-- Send Date -->
<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' : movement.action === 'Register' ? 'Register Date' : 'Send Date'}}</h4>
<span class="fixed-value text-truncate">{{movement.action !== 'Register' ? movement.sendDate : movement.date }}</span>
</div>
<!-- Receive Date -->
<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>
<span class="fixed-value text-truncate" style="max-width:160px;">{{ movement.receiveDate || 'Not arrive' }}</span>
</div>
<!-- Action -->
<div class="d-flex flex-wrap align-items-center gap-2 flex-grow-1" style="max-width:150px; min-width:150px;">
<h4 class="fixed-labelStatus m-0 text-nowrap">Action:</h4>
<span class="fixed-value text-truncate">{{ movement.action }}</span>
</div>
<!-- Status -->
<div class="d-flex flex-wrap align-items-center gap-2 flex-grow-1" style="max-width:160px; min-width:160px;">
<h4 class="fixed-labelStatus m-0 text-nowrap">Status:</h4>
<span class="fixed-value text-truncate" style="max-width:90px;">{{ movement.latestStatus || movement.toOther }}</span>
</div>
<!-- More Details Button -->
<button class="btn btn-info btn-sm ms-auto" v-on:click="toggleDetails(movement.id)">
More Details
</button>
<!-- Completion Status -->
<h4 :class="movement.action == 'Register' ? 'text-success' : movement.movementComplete == 1 && movement.latestStatus !== 'Ready To Deploy' ? 'text-success' :
movement.toOther === 'Repair' || movement.toOther === 'Calibration' && movement.latestStatus === 'Ready To Deploy' ? 'text-success' :'text-danger'"
class="text-nowrap ms-3">
{{ movement.action == 'Register' ? 'Complete' :
(movement.movementComplete == 1 && movement.latestStatus !== 'Ready To Deploy' ? 'Complete' :
( movement.toOther === 'Repair' || movement.toOther === 'Calibration' && movement.latestStatus === 'Ready To Deploy' ? 'Complete' :
(movement.latestStatus === 'Ready To Deploy' ? 'Canceled' : 'Incomplete'))) }}
</h4>
</div>
<!-- 📌 Details Section (Hidden by Default) -->
<div v-show="detailsVisible[movement.id]" class="col-md-12 mt-2">
<div class="row">
<div class="col-md-4 text-center">
<!-- Conditionally render Start Icon -->
<i v-if="movement.toStation" class="fas fa-map-marker-alt"></i>
<i v-else-if="movement.toOther !== 'On Delivery'" class="fas fa-user fa-2x"></i>
<i v-else class="fas fa-warehouse fa-2x"></i>
<p><strong>Start</strong></p>
<p><strong>User:</strong> {{ movement.toUserName }}</p>
<p><strong>Station:</strong> {{ movement.toStationName }}</p>
<p><strong>Store:</strong> {{ movement.toStoreName }}</p>
</div>
<div class="col-md-4 text-center">
<p></p>
<i class="fas fa-arrow-right fa-2x"></i>
<p>{{ movement.latestStatus || movement.toOther }}</p>
<p>
<button class="btn btn-info btn-sm ms-auto" v-on:click="remark(movement.remark)" v-if="movement.toOther !== 'On Delivery'">
Remark
</button>
</p>
<p>
<button class="btn btn-info btn-sm ms-auto" v-on:click="consignmentNote(movement.consignmentNote)" v-if="movement.toOther !== 'On Delivery'">
Consignment Note
</button>
</p>
</div>
<div class="col-md-4 text-center">
<!-- Conditionally render End Icon -->
<i v-if="movement.lastStation" class="fas fa-map-marker-alt"></i>
<i v-else-if="movement.toOther !== 'On Delivery'" class="fas fa-warehouse fa-2x"></i>
<i v-else class="fas fa-user fa-2x"></i>
<p><strong>End</strong></p>
<p v-if="movement.lastUser !== null"><strong>User:</strong> {{ movement.lastUserName }}</p>
<p v-if="movement.lastStation !== null"><strong>Station:</strong> {{ movement.lastStationName }}</p>
<p v-if="movement.lastStore !== null"><strong>Store:</strong> {{ movement.lastStoreName }}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<!--------------------------------------------STATION CATEGORY---------------------------------------------------------------------->
<div v-if="sortBy === 'station'">
<div v-for="(items, station) in filteredStation " :key="stationName"
:class="{'bg-light-gray': station === 'Unassign Station', 'bg-white': station !== 'Unassign Station'}" class="station-category card mt-3">
<!-- Station Header -->
<div class="card-header d-flex justify-content-between align-items-center">
<h3>{{ station }}</h3>
<button class="btn btn-light" v-on:click="toggleCategory(station)">
<i :class="categoryVisible[station] ? 'fas fa-chevron-up' : 'fas fa-chevron-down'"></i> Show Items
</button>
</div>
<!-- Show Items Under Each Station -->
<div v-show="categoryVisible[station]" class="card-body">
<div v-for="(group, itemId) in paginatedItemsStation(items)" :key="itemId" class="row card">
<!-- Item Header -->
<div class="card-header d-flex justify-content-between align-items-center">
<h2 v-if="group.uniqueID">Item : {{ group.uniqueID }}</h2>
<h2 v-else>Item : No Item Tracked</h2>
<button class="btn btn-light" v-on:click="toggleCategory(itemId)">
<i :class="categoryVisible[itemId] ? 'fas fa-chevron-up' : 'fas fa-chevron-down'"></i> Show Details
</button>
</div>
<!-- Show Movements for Each Item -->
<div v-show="categoryVisible[itemId]" class="card-body">
<div v-for="(movement, index) in group.movements.sort((a, b) => a.id - b.id).reverse()" :key="movement.id" class="movement-row">
<div v-if="index === 0" class="row">
<strong>Latest Movement</strong>
<div class="col-md-12 d-flex flex-wrap align-items-center gap-3 p-2 border-bottom">
<h3 :class="{'text-primary': movement.toOther === 'On Delivery', 'text-warning': movement.toOther === 'Return',
'text-success': movement.toStation !== null, 'text-info': movement.action === 'Assign' && movement.toStation === null,
'text-numb': movement.toOther === 'Faulty' || movement.toOther === 'Calibration' || movement.toOther === 'Repair',
'text-weird': movement.action === 'Register'}"
class="flex-shrink-0 text-nowrap" style="max-width:140px; min-width:90px;">
{{ movement.toOther === 'Return' ? 'Return' : (movement.toOther === 'On Delivery' ? 'Receive' : ( movement.toStation !== null ? 'Change' : ( movement.toOther == 'Faulty' || movement.toOther == 'Calibration' || movement.toOther == 'Repair' ? movement.toOther : ( movement.action == 'Register' ? 'Register' : 'Assign')))) }}
</h3>
<!-- Send Date -->
<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' : movement.action === 'Register' ? 'Register Date' : 'Send Date'}}</h4>
<span class="fixed-value text-truncate">{{movement.action !== 'Register' ? movement.sendDate : movement.date }}</span>
</div>
<!-- Receive Date -->
<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>
<span class="fixed-value text-truncate" style="max-width:160px;">{{ movement.receiveDate || 'Not arrive' }}</span>
</div>
<!-- Action -->
<div class="d-flex flex-wrap align-items-center gap-2 flex-grow-1" style="max-width:150px; min-width:150px;">
<h4 class="fixed-labelStatus m-0 text-nowrap">Action:</h4>
<span class="fixed-value text-truncate">{{ movement.action }}</span>
</div>
<!-- Status -->
<div class="d-flex flex-wrap align-items-center gap-2 flex-grow-1" style="max-width:160px; min-width:160px;">
<h4 class="fixed-labelStatus m-0 text-nowrap">Status:</h4>
<span class="fixed-value text-truncate" style="max-width:90px;">{{ movement.latestStatus || movement.toOther }}</span>
</div>
<!-- More Details Button -->
<button class="btn btn-info btn-sm ms-auto" v-on:click="toggleDetails(movement.id)">
More Details
</button>
<!-- Completion Status -->
<h4 :class="movement.action == 'Register' ? 'text-success' : movement.movementComplete == 1 && movement.latestStatus !== 'Ready To Deploy' ? 'text-success' : movement.toOther === 'Repair' || movement.toOther === 'Calibration' && movement.latestStatus === 'Ready To Deploy' ? 'text-success' :'text-danger'"
class="text-nowrap ms-3">
{{ movement.action == 'Register' ? 'Complete' : (movement.movementComplete == 1 && movement.latestStatus !== 'Ready To Deploy' ? 'Complete' : ( movement.toOther === 'Repair' || movement.toOther === 'Calibration' && movement.latestStatus === 'Ready To Deploy' ? 'Complete' : (movement.latestStatus === 'Ready To Deploy' ? 'Canceled' : 'Incomplete'))) }}
</h4>
</div>
<div v-show="detailsVisible[movement.id]" class="col-md-12 mt-2">
<div class="row">
<div class="col-md-4 text-center">
<i v-if="movement.toStation" class="fas fa-map-marker-alt"></i>
<i v-else-if="movement.toOther !== 'On Delivery'" class="fas fa-user fa-2x"></i>
<i v-else class="fas fa-warehouse fa-2x"></i>
<p><strong>Start</strong></p>
<p v-if="movement.toUser !== null"><strong>User:</strong> {{ movement.toUserName }}</p>
<p v-if="movement.toStation !== null"><strong>Station:</strong> {{ movement.toStationName }}</p>
<p v-if="movement.toStore !== null"><strong>Store:</strong> {{ movement.toStoreName }}</p>
</div>
<div class="col-md-4 text-center">
<i class="fas fa-arrow-right fa-2x"></i>
<p>{{ movement.latestStatus || movement.toOther }}</p>
<p>
<button class="btn btn-info btn-sm ms-auto" v-on:click="remark(movement.remark)">
Remark
</button>
</p>
<p>
<button class="btn btn-info btn-sm ms-auto" v-on:click="consignmentNote(movement.consignmentNote)">
Consignment Note
</button>
</p>
</div>
<div class="col-md-4 text-center">
<i v-if="movement.lastStation" class="fas fa-map-marker-alt"></i>
<i v-else-if="movement.toOther !== 'On Delivery'" class="fas fa-warehouse fa-2x"></i>
<i v-else class="fas fa-user fa-2x"></i>
<p><strong>End</strong></p>
<p v-if="movement.lastUser !== null"><strong>User:</strong> {{ movement.lastUserName }}</p>
<p v-if="movement.lastStation !== null"><strong>Station:</strong> {{ movement.lastStationName }}</p>
<p v-if="movement.lastStore !== null"><strong>Store:</strong> {{ movement.lastStoreName }}</p>
</div>
</div>
</div>
</div>
</div>
<!-- Single View History Button -->
<button class="btn btn-light w-100 text-left" v-on:click="toggleHistory(itemId)">
<i :class="historyVisible[itemId] ? 'fas fa-chevron-up' : 'fas fa-chevron-down'"></i> View History
</button>
<div v-show="historyVisible[itemId]" class="history-row">
<div v-for="(movement, i) in group.movements.slice(1)" :key="i" class="row mt-2">
<div class="col-md-12 d-flex flex-wrap align-items-center gap-3 p-2 border-bottom">
<!-- Movement Type -->
<h3 :class="{'text-primary': movement.toOther === 'On Delivery', 'text-warning': movement.toOther === 'Return',
'text-success': movement.toStation !== null, 'text-info': movement.action === 'Assign' && movement.toStation === null,
'text-numb': movement.toOther === 'Faulty' || movement.toOther === 'Calibration' || movement.toOther === 'Repair',
'text-weird': movement.action === 'Register'}"
class="flex-shrink-0 text-nowrap" style="max-width:140px; min-width:90px;">
{{ movement.toOther === 'Return' ? 'Return' : (movement.toOther === 'On Delivery' ? 'Receive' : ( movement.toStation !== null ? 'Change' : ( movement.toOther == 'Faulty' || movement.toOther == 'Calibration' || movement.toOther == 'Repair' ? movement.toOther : ( movement.action == 'Register' ? 'Register' : 'Assign')))) }}
</h3>
<!-- Send Date -->
<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' : movement.action === 'Register' ? 'Register Date' : 'Send Date'}}</h4>
<span class="fixed-value text-truncate">{{movement.action !== 'Register' ? movement.sendDate : movement.date }}</span>
</div>
<!-- Receive Date -->
<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>
<span class="fixed-value text-truncate" style="max-width:160px;">{{ movement.receiveDate || 'Not arrive' }}</span>
</div>
<!-- Action -->
<div class="d-flex flex-wrap align-items-center gap-2 flex-grow-1" style="max-width:150px; min-width:150px;">
<h4 class="fixed-labelStatus m-0 text-nowrap">Action:</h4>
<span class="fixed-value text-truncate">{{ movement.action }}</span>
</div>
<!-- Status -->
<div class="d-flex flex-wrap align-items-center gap-2 flex-grow-1" style="max-width:160px; min-width:160px;">
<h4 class="fixed-labelStatus m-0 text-nowrap">Status:</h4>
<span class="fixed-value text-truncate" style="max-width:90px;">{{ movement.latestStatus || movement.toOther }}</span>
</div>
<!-- More Details Button -->
<button class="btn btn-info btn-sm ms-auto" v-on:click="toggleDetails(movement.id)">
More Details
</button>
<!-- Completion Status -->
<h4 :class="movement.action == 'Register' ? 'text-success' : movement.movementComplete == 1 && movement.latestStatus !== 'Ready To Deploy' ? 'text-success' : movement.toOther === 'Repair' || movement.toOther === 'Calibration' && movement.latestStatus === 'Ready To Deploy' ? 'text-success' :'text-danger'"
class="text-nowrap ms-3">
{{ movement.action == 'Register' ? 'Complete' : (movement.movementComplete == 1 && movement.latestStatus !== 'Ready To Deploy' ? 'Complete' : ( movement.toOther === 'Repair' || movement.toOther === 'Calibration' && movement.latestStatus === 'Ready To Deploy' ? 'Complete' : (movement.latestStatus === 'Ready To Deploy' ? 'Canceled' : 'Incomplete'))) }}
</h4>
</div>
<!-- Details Section (Hidden by Default) -->
<div v-show="detailsVisible[movement.id]" class="col-md-12 mt-2">
<div class="row">
<div class="col-md-4 text-center">
<!-- Conditionally render Start Icon -->
<i v-if="movement.toOther !== 'On Delivery'" class="fas fa-user fa-2x"></i>
<i v-else class="fas fa-warehouse fa-2x"></i>
<p><strong>Start</strong></p>
<p v-if="movement.toUser !== null"><strong>User:</strong> {{ movement.toUserName }}</p>
<p v-if="movement.toStation !== null"><strong>Station:</strong> {{ movement.toStationName }}</p>
<p v-if="movement.toStore !== null"><strong>Store:</strong> {{ movement.toStoreName }}</p>
</div>
<div class="col-md-4 text-center">
<p></p>
<i class="fas fa-arrow-right fa-2x"></i>
<p>{{ movement.latestStatus || movement.toOther }}</p>
<p>
<button class="btn btn-info btn-sm ms-auto" v-on:click="remark(movement.remark)">
Remark
</button>
</p>
<p>
<button class="btn btn-info btn-sm ms-auto" v-on:click="consignmentNote(movement.consignmentNote)">
Consignment Note
</button>
</p>
</div>
<div class="col-md-4 text-center">
<!-- Conditionally render End Icon -->
<i v-if="movement.lastStation" class="fas fa-map-marker-alt"></i>
<i v-else-if="movement.toOther !== 'On Delivery'" class="fas fa-warehouse fa-2x"></i>
<i v-else class="fas fa-user fa-2x"></i>
<p><strong>End</strong></p>
<p v-if="movement.lastUser !== null"><strong>User:</strong> {{ movement.lastUserName }}</p>
<p v-if="movement.lastStation !== null"><strong>Station:</strong> {{ movement.lastStationName }}</p>
<p v-if="movement.lastStore !== null"><strong>Store:</strong> {{ movement.lastStoreName }}</p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal fade" id="remarkModal" tabindex="-1" aria-labelledby="remarkModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="remarkModalLabel">Remark</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body" id="remarkContent">
<!-- Remark Content Here -->
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div class="modal fade" id="consignmentModal" tabindex="-1" aria-labelledby="consignmentModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="consignmentModalLabel">Consignment Note</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body text-center">
<img v-if="/\.(jpeg|jpg|png|gif)$/i.test(consignmentNoteUrl)" :src="consignmentNoteUrl" class="img-fluid" alt="Consignment Note Image">
<iframe v-else-if="/\.pdf$/i.test(consignmentNoteUrl)" :src="consignmentNoteUrl" style="width:100%; height: 80vh;"></iframe>
<a v-else class="btn btn-primary">There's no Folder or Picture</a>
</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>
<!-- ============================================================== -->
<!-- End PAge Content -->
<!-- ============================================================== -->
<!-- ============================================================== -->
<!-- Right sidebar -->
<!-- ============================================================== -->
<!-- .right-sidebar -->
<!-- ============================================================== -->
<!-- End Right sidebar -->
<!-- ============================================================== -->
</div>
<!-- ============================================================== -->
<!-- End Container fluid -->
<!-- ============================================================== -->
<!-- ============================================================== -->
<!-- footer -->
<!-- ============================================================== -->
<footer b-lhtx71ohus class="footer text-center">
All Rights Reserved by PSTW. Designed and Developed by
<a b-lhtx71ohus href="https://www.wrappixel.com">WrapPixel</a>.
</footer>
<!-- ============================================================== -->
<!-- End footer -->
<!-- ============================================================== -->
</div>
<!-- ============================================================== -->
<!-- End Page wrapper -->
<!-- ============================================================== -->
</div>
<!-- ============================================================== -->
<!-- End Wrapper -->
<!-- ============================================================== -->
<!-- ============================================================== -->
<!-- All Jquery -->
<!-- ============================================================== -->
<script src="/assets/libs/jquery/dist/jquery.min.js"></script>
<script src="/dist/js/jquery-ui.min.js"></script>
<!-- VUE Multiselect-->
<script src="/lib/vue-multiselect/vue-multiselect.js"></script>
<link href="/lib/vue-multiselect/vue-multiselect.min.css" rel="stylesheet" />
<!-- VUE Date Picker-->
<link href="/lib/vue-datepicker/mainvuedate.css" rel="stylesheet" />
<script src="/lib/vue-datepicker/vue-datepicker.iife.js"></script>
<!-- Bootstrap tether Core JavaScript -->
<script src="/assets/libs/bootstrap/dist/js/bootstrap.bundle.min.js"></script>
<!-- slimscrollbar scrollbar JavaScript -->
<script src="/assets/libs/perfect-scrollbar/dist/perfect-scrollbar.jquery.min.js"></script>
<script src="/assets/extra-libs/sparkline/sparkline.js"></script>
<!--Wave Effects -->
<script src="/dist/js/waves.js"></script>
<!--Menu sidebar -->
<script src="/dist/js/sidebarmenu.js"></script>
<!--Custom JavaScript -->
<script src="/dist/js/custom.min.js"></script>
<!--Form JS-->
<script src="/assets/libs/inputmask/dist/min/jquery.inputmask.bundle.min.js"></script>
<script src="/dist/js/pages/mask/mask.init.js"></script>
<script src="/assets/libs/select2/dist/js/select2.full.min.js"></script>
<script src="/assets/libs/jquery-asColor/dist/jquery-asColor.min.js"></script>
<script src="/assets/libs/jquery-asGradient/dist/jquery-asGradient.js"></script>
<script src="/assets/libs/jquery-asColorPicker/dist/jquery-asColorPicker.min.js"></script>
<script src="/assets/libs/jquery-minicolors/jquery.minicolors.min.js"></script>
<script src="/assets/libs/bootstrap-datepicker/dist/js/bootstrap-datepicker.min.js"></script>
<script src="/assets/libs/quill/dist/quill.min.js"></script>
<script src="/lib/printjs/print.min.js"></script>
<script src="/lib/html2canvas/html2canvas.min.js"></script>
<script src="/lib/html2canvas/dom-to-image.min.js"></script>
<!-- Datatables JS-->
<script src="/lib/datatables/datatables.js"></script>
<script src="/lib/jquery-validation/dist/jquery.validate.min.js"></script>
<script src="/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.min.js"></script>
<script>
$(function () {
app.mount('#registerItem');
// Attach a click event listener to elements with the class 'btn-success'.
$('#addItemBtn').on('click', function () {
// Show the modal with the ID 'addManufacturerModal'.
$('#itemMovementModal').modal('show');
});
$('.closeModal').on('click', function () {
// Show the modal with the ID 'addManufacturerModal'.
$('.modal').modal('hide');
});
});
const app = Vue.createApp({
data() {
return {
warranty: 0,
EndWDate: null,
invoiceNo: null,
invoiceDate: null,
partNumber: null,
products: [],
depts: [],
stations: [],
stores: [],
users:[],
isModalOpen: false,
selectedProduct: "",
selectedSupplier: "",
selectedCompany: "",
selectedDepartment: "",
selectedTeamType: "",
selectedtoStation: "",
consignmentNoteUrl: "",
assignStationDatatable: null,
showItemModal: false,
loading: false,
items: [],
currentUser: null,
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]) {
acc[movement.itemId] = {
uniqueID: movement.uniqueID,
movements: [],
};
}
acc[movement.itemId].movements.push(movement);
return acc;
}, {});
// Sort items from newest to oldest & filter them
for (let itemId in grouped) {
let movements = grouped[itemId].movements
.sort((a, b) => b.id - a.id); // Newest to oldest
// Ensure at least 3 movements before stopping
let stopIndex = movements.slice(3).findIndex(m => m.toOther === 'Return' && m.movementComplete == 1);
if (stopIndex !== -1) {
stopIndex += 3; // Adjust index since we sliced after the first 3
movements = movements.slice(0, stopIndex + 1); // Keep at least 3 + the "Return" row
}
grouped[itemId].movements = movements;
}
return grouped;
},
groupedByStation() {
let groupedByItem = this.items.reduce((acc, movement) => {
if (!acc[movement.uniqueID]) {
acc[movement.uniqueID] = {
uniqueID: movement.uniqueID,
movements: [],
};
}
acc[movement.uniqueID].movements.push(movement);
return acc;
}, {});
let groupedByStation = {};
Object.keys(groupedByItem).forEach(itemId => {
let movements = groupedByItem[itemId].movements
.sort((a, b) => b.id - a.id); // Newest → Oldest
// Ensure at least 3 movements before stopping
let stopIndex = movements.slice(3).findIndex(m => m.toOther === 'Return' && m.movementComplete == 1);
// Remove older movements
if (stopIndex !== -1) {
stopIndex += 3; // Adjust index since we sliced after the first 3
movements = movements.slice(0, stopIndex);
}
if (movements.length > 0) {
let latestMovement = movements[0];
let station = latestMovement.lastStationName || latestMovement.toStationName || "Not Assigned";
if (!groupedByStation[station]) { groupedByStation[station] = {}; }
groupedByStation[station][itemId] = { uniqueID: itemId, movements };
}
});
// 4⃣ **Sort stations & move 'Unassign Station' to last**
let sortedKeys = Object.keys(groupedByStation).sort((a, b) => {
if (a === "Unassign Station") return 1;
if (b === "Unassign Station") return -1;
return a.localeCompare(b);
});
let sortedGrouped = {};
sortedKeys.forEach(key => {
sortedGrouped[key] = groupedByStation[key];
});
return sortedGrouped;
},
filteredItems() {
if (!this.searchQuery.trim()) {
return this.groupedItems;
}
const searchLower = this.searchQuery.toLowerCase();
return Object.fromEntries(
Object.entries(this.groupedItems).filter(([_, group]) =>
group.uniqueID.toLowerCase().includes(searchLower)
)
);
},
filteredStation() {
if (!this.searchQueryStation) {
return this.groupedByStation;
}
let searchQueryStation = String(this.searchQueryStation).toLowerCase();
let grouped = this.groupedByStation;
let filtered = {};
Object.keys(grouped).forEach(station => {
if (station.toLowerCase().includes(searchQueryStation)) {
filtered[station] = grouped[station];
}
});
return filtered;
},
},
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();
},
consignmentNote(consignmentNote) {
if (!consignmentNote) {
this.consignmentNoteUrl = "No consignment note available.";
new bootstrap.Modal(document.getElementById('consignmentModal')).show();
return;
}
// Pastikan URL betul
this.consignmentNoteUrl = consignmentNote;
// Tunggu Vue update sebelum buka modal
this.$nextTick(() => {
new bootstrap.Modal(document.getElementById('consignmentModal')).show();
});
},
initiateTable() {
this.loading = true;
self = this;
this.itemDatatable = $('#itemDatatable').DataTable({
"data": this.items,
"columns": [
{ title: "Unique Id", data: "id" },
{ title: "Product Code", data: "uniqueID" },
{ title: "From User", data: "toUserName" },
{ title: "Last User", data: "lastUserName" },
{ title: "Completion", data: "movementComplete", render: function (data) {return data ? "Completed" : "Pending";}},
{ 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: "Product Category", data: "productCategory" },
{ 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 `<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" },
],
order: [[0, "desc"]], // Sorting by "Product Code" (uniqueID) in descending order
responsive: true,
drawCallback: function (settings) {
// Generate QR codes after rows are rendered
// const api = this.api();
// api.rows().every(function () {
// const data = this.data();
// const containerId = `qr${data.id}`; containerid is by increments from API
// const container = $(`#${containerId}`);
// container.empty();
// container.append(`${data.item.itemId}`);
// if (container.length) {
// new QRCode(container[0], {
// text: data.qrString,
// width: 100,
// height: 100,
// colorDark: "#000000",
// colorLight: "#ffffff",
// correctLevel: QRCode.CorrectLevel.M,
// });
// }
// container.on('click', function() {
// window.open(data.qrString, '_blank');
// });
// });
},
})
this.loading = false;
},
async fetchItem() {
this.loading = true;
await this.fetchUser();
try {
// const token = localStorage.getItem('token'); // Get the token from localStorage
const response = await fetch('/InvMainAPI/ItemMovementList', {
method: 'POST', // Specify the HTTP method
headers: {
'Content-Type': 'application/json', // Set content type
// 'Authorization': `Bearer ${token}` // Include the token in the headers
}
});
if (!response.ok) {
throw new Error('Failed to fetch item');
}
if(this.currentRole == "Super Admin"){
this.items = await response.json();
this.initAllTables();
} else {
const data = await response.json();
this.items = data.filter(item =>
item.toUser === this.currentUser.id ||
item.lastUser === this.currentUser.id ||
item.toStore === this.currentUser.store ||
item.lastStore === this.currentUser.store
);
this.initAllTables();
}
if (this.itemDatatable) {
this.itemDatatable.clear().destroy();
}
this.initiateTable();
}
catch (error) {
console.error('Error fetching item:', error);
}
this.loading = false;
},
async fetchUser() {
try {
const response = await fetch(`/IdentityAPI/GetUserInformation/`, {
method: 'POST',
});
if (response.ok) {
const data = await response.json();
this.currentUser = data?.userInfo || null;
const companyDeptData = await this.currentUser.department;
this.currentUserCompanyDept = companyDeptData;
this.selectedCompany = companyDeptData?.companyId || "";
this.selectedDepartment = companyDeptData?.departmentId || "";
const roles = this.currentUser.role;
if (roles.includes("SuperAdmin")) {
this.currentRole = "Super Admin";
// this.sortBy = 'logs';
} else if (roles.includes("Inventory Master")) {
this.currentRole = "Inventory Master";
// this.sortBy = "item";
}
}
else {
console.error(`Failed to fetch user: ${response.statusText}`);
}
}
catch (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() {
this.renderTables();
},
renderTables() {
this.initAllTables();
this.initiateTable();
},
initAllTables() {
if (this.itemMovementNotCompleteDatatable) {
this.itemMovementNotCompleteDatatable.destroy();
}
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} <br> ${renderFile(full.productImage)}`; } },
{ title: "Product Code", data: "uniqueID" },
{ title: "Action", data: "action" },
{ title: "Send Date", data: "sendDate" },
{ title: "From User", data: "toUserName" },
{ title: "Last User", data: "lastUserName" },
{ title: "From Station", data: "toStationName" },
{ title: "From Store", data: "toStoreName" },
{ title: "Start Status", data: "toOther" },
{ title: "Product Category", data: "productCategory" },
{ title: "Qty", data: "quantity" },
{ title: "Note", data: "consignmentNote", render: renderFile },
{ title: "Remark", data: "remark" },
],
order: [[0, "desc"]],
responsive: true,
});
this.itemMovementCompleteDatatable = $("#itemMovementCompleteDatatable").DataTable({
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} <br> ${renderFile(full.productImage)}`; } },
{ title: "Product Code", data: "uniqueID" },
{ title: "Send Date", data: "sendDate" },
{ title: "Receive Date", data: "receiveDate" },
{ title: "Action", data: "action" },
{ 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: "Start Status", data: "toOther" },
{ title: "Latest Status", data: "latestStatus" },
{ title: "Product Category", data: "productCategory" },
{ title: "Note", data: "consignmentNote", render: renderFile },
{ title: "Remark", data: "remark" },
],
order: [[0, "desc"]],
responsive: true,
});
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} <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 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 `<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>`;
}
}
},
toggleCategory(itemId) {
this.categoryVisible[itemId] = !this.categoryVisible[itemId];
this.detailsVisible = {};
this.historyVisible = {};
},
toggleHistory(itemId) {
// Jika item yang ditekan sudah terbuka, tutup
if (this.historyVisible[itemId]) {
this.historyVisible[itemId] = false;
} else {
// Tutup semua history lain dahulu
this.historyVisible = {};
// Buka hanya item yang ditekan
this.historyVisible[itemId] = true;
}
},
toggleDetails(movementId) {
this.detailsVisible[movementId] = !this.detailsVisible[movementId];
},
},
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>
</body>
</html>