MIF_E31231060/resources/views/rencana-pengadaan.blade.php

1804 lines
56 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css">
<title>RENCANA PENGADAAN - UDD PMI KABUPATEN JEMBER</title>
<link rel="icon" type="image/png" href="{{ asset('images/logo-pmi.png') }}">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap" rel="stylesheet">
<script src="https://cdn.tailwindcss.com"></script>
<style>
body {
font-family: 'Poppins', sans-serif;
background: #f7faff;
padding: 28px;
box-sizing: border-box;
overflow-x: hidden;
overflow-y: auto;
margin: 0;
color: #1f2937;
}
.super-card {
position: relative;
width: 100%;
background: rgba(255, 255, 255, 0.92);
backdrop-filter: blur(14px);
border-radius: 8px !important;
border: 1px solid rgba(255, 95, 95, 0.6);
box-shadow: 0 10px 30px rgba(15, 23, 42, 0.08);
overflow: hidden;
}
.header {
position: relative;
display: flex;
align-items: center;
gap: 14px;
background:
linear-gradient(135deg,
#d32f2f 0%,
#b71c1c 45%,
#7f0000 100%);
color: white;
padding: 20px 30px;
overflow: hidden;
border-bottom:
1px solid rgba(255, 255, 255, 0.08);
}
.header h1 {
font-size: 18px;
font-weight: 700 !important;
letter-spacing: .3px;
}
.header-left i,
.header-btn i {
position: relative;
font-size: 18px;
width: 40px;
height: 40px;
border-radius: 5px;
display: flex;
align-items: center;
justify-content: center;
color: rgba(255, 255, 255, .96);
background: linear-gradient(145deg,
rgba(255, 255, 255, .22),
rgba(255, 255, 255, .08));
border: 1px solid rgba(255, 255, 255, .18);
backdrop-filter: blur(10px);
box-shadow:
inset 0 1px 1px rgba(255, 255, 255, .24),
inset 0 -1px 1px rgba(255, 255, 255, .05),
0 10px 18px rgba(0, 0, 0, .16),
0 4px 8px rgba(0, 0, 0, .10);
}
.header {
justify-content: space-between;
}
.header-left {
display: flex;
align-items: center;
gap: 14px;
}
.header-nav {
display: flex;
gap: 10px;
width: 600px;
}
.header-btn {
flex: 1;
display: flex;
align-items: center;
gap: 10px;
padding: 10px 14px;
border-radius: 5px;
text-decoration: none;
font-size: 13px;
font-weight: 600;
transition: .25s ease;
border: 1px solid rgba(255, 255, 255, .15);
color: white;
}
.header-btn:nth-child(1) {
background: linear-gradient(135deg,
#5b8def,
#3c6fd7);
}
.header-btn:nth-child(1):hover {
background: linear-gradient(135deg,
#6e9fff,
#4b84f7);
}
.header-btn:nth-child(1) i {
color: #eaf2ff;
}
.header-btn:nth-child(2) {
background: linear-gradient(135deg,
#d98a3d,
#c97828);
}
.header-btn:nth-child(2):hover {
background: linear-gradient(135deg,
#e69c5a,
#d98a3d);
}
.header-btn:nth-child(2) i {
color: #fff4e8;
}
.header-btn:nth-child(3) {
background: linear-gradient(135deg,
#22c55e,
#15803d);
}
/* .header-btn:nth-child(3):hover {
background: linear-gradient(135deg,
#34d399,
#16a34a);
} */
.header-btn:nth-child(3) i {
color: #fff1f1;
}
.header-btn:hover {
transform: translateY(-2px);
filter: brightness(1.05);
color: white;
}
.header-btn.active {
pointer-events: none;
cursor: default;
}
.refresh-btn {
min-width: 45px;
align-self: stretch;
border: none;
border-radius: 5px;
background:
linear-gradient(135deg,
#ef4444,
#b91c1c);
color: white;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: .25s;
}
.refresh-icon {
font-size: 20px;
transition: transform .3s ease;
}
.refresh-btn:hover .refresh-icon {
transform: rotate(180deg);
}
.section {
padding: 20px 24px;
background:
linear-gradient(180deg,
rgba(255, 255, 255, .88),
rgba(255, 255, 255, .72));
backdrop-filter: blur(10px);
}
.section+.section {
border-top: 1px solid rgba(255, 0, 0, 0.06);
}
.section-divider {
height: 1px;
background: rgba(215, 215, 215, 0.7);
}
.section.table-section {
flex: 1;
min-height: 0;
display: flex;
flex-direction: column;
padding: 26px 0 0 0;
}
.section.table-section h2 {
font-size: 17px;
color: #8f0000;
font-weight: 700;
letter-spacing: 0.5px;
}
.table-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 16px 14px 16px;
gap: 16px;
}
.periode-highlight {
/* background: linear-gradient(135deg, #3b82f6, #1d4ed8); */
/* -webkit-background-clip: text; */
/* -webkit-text-fill-color: transparent; */
color: #dc2626;
font-weight: 750;
margin-left: 4px;
}
.table-tools {
display: flex;
align-items: stretch;
gap: 14px;
}
.filter-status,
.search-box,
.data-info-pill {
height: 42px;
display: flex;
align-items: center;
}
.search-box {
position: relative;
}
.search-box input {
width: 220px;
height: 100%;
box-sizing: border-box;
padding: 10px 12px 10px 38px;
border-radius: 8px;
border: 1px solid #f1b5b5;
background: linear-gradient(145deg, #fff, #fff5f5);
box-shadow:
inset 0 2px 5px rgba(0, 0, 0, 0.06),
0 4px 12px rgba(211, 47, 47, 0.08);
transition: all .25s ease;
font-size: 13px;
}
.search-box input:focus {
outline: none;
border-color: #d32f2f;
box-shadow:
0 0 0 3px rgba(211, 47, 47, 0.15),
0 6px 18px rgba(211, 47, 47, 0.2);
}
.search-box i {
position: absolute;
left: 12px;
top: 50%;
transform: translateY(-50%);
color: #d32f2f;
font-size: 14px;
opacity: .8;
}
.filter-status {
display: flex;
background: #fff5f5;
padding: 4px;
border-radius: 8px;
box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.08);
}
.data-info-pill {
gap: 6px;
padding: 6px 10px;
border-radius: 8px;
background: linear-gradient(135deg, #fff5f5, #ffeaea);
border: 1px solid #f1b5b5;
color: #7f1d1d;
font-size: 11px;
font-weight: 600;
box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.08);
white-space: nowrap;
}
.data-info-pill span {
font-size: 10px;
font-weight: 700;
}
.status-btn {
border: none;
padding: 8px 14px;
border-radius: 10px;
font-size: 12px;
font-weight: 600;
background: transparent;
color: #9a0007;
cursor: pointer;
transition: all .25s ease;
}
.status-btn:hover {
background: rgba(211, 47, 47, 0.1);
}
.status-btn.active {
background: linear-gradient(135deg, #d32f2f, #9a0007);
color: white;
box-shadow: 0 4px 12px rgba(211, 47, 47, 0.35);
}
.top-grid {
position: relative;
display: grid;
grid-template-columns: 1.2fr repeat(4, 1fr);
grid-template-rows: auto;
gap: 14px;
padding: 18px;
border-radius: 8px;
overflow: hidden;
background: #fde9e9;
box-shadow: inset 0 0 0 1px rgba(211, 47, 47, 0.08);
}
.periode-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 8px;
gap: 12px;
font-weight: 600;
font-size: 14px !important;
color: #890000c7 !important;
}
.periode-note {
padding: 4px 10px;
border-radius: 999px;
background: #fff1f2;
border: 1px solid #fecdd3;
color: #b91c1c;
font-size: 11px;
display: flex;
align-items: center;
gap: 6px;
white-space: nowrap;
flex-shrink: 0;
}
.periode-note i {
font-size: 12px;
}
.filter-card {
grid-row: auto;
background: rgba(255, 255, 255, 0.95);
border-radius: 6px;
padding: 16px;
border: 1px solid rgba(239, 68, 68, 0.19);
box-shadow:
0 10px 30px rgba(15, 23, 42, 0.06),
inset 0 1px 0 rgba(255, 255, 255, 0.7);
transition: all .3s ease;
display: flex;
flex-direction: column;
justify-content: center;
backdrop-filter: blur(10px);
}
.filter-box {
display: grid;
grid-template-columns: 1fr auto auto;
gap: 16px;
align-items: end;
}
.filter-box select {
width: 100%;
border-radius: 10px;
border: 1px solid #e5e7eb;
padding: 12px;
transition: .2s;
}
.btn {
border-radius: 7px;
padding: 12px 3rem;
font-weight: 600;
transition: .25s;
}
.btn-primary {
background: linear-gradient(135deg, #d32f2f, #9a0007);
color: white;
padding: 12px 7rem;
box-shadow: 0 10px 25px rgba(211, 47, 47, .3);
transition: all .25s ease;
}
.btn-primary:hover {
transform: translateY(-2px);
box-shadow: 0 10px 25px rgba(211, 47, 47, .3);
}
.btn-dark {
background:
linear-gradient(135deg,
#ffa94d 0%,
#f97316 45%,
#ea580c 100%);
color: white;
transition: all .25s ease;
box-shadow: 0 10px 25px rgba(234, 88, 12, 0.35);
}
.btn-dark:hover {
background: linear-gradient(135deg, #fb923c, #f97316);
transform: translateY(-2px);
box-shadow: 0 14px 30px rgba(234, 88, 12, 0.45);
}
.summary {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20px;
}
.summary-box {
background: rgba(255, 255, 255, 0.92);
border-radius: 6px;
padding: 16px;
border: 1px solid rgba(239, 68, 68, 0.12);
box-shadow:
0 10px 25px rgba(15, 23, 42, 0.06),
inset 0 1px 0 rgba(255, 255, 255, 0.6);
position: relative;
overflow: hidden;
min-height: 70px;
display: grid;
grid-template-columns: 52px 1fr;
grid-template-rows: auto auto;
backdrop-filter: blur(10px);
transition: all .35s ease;
}
.summary-box:hover {
transform: translateY(-6px) scale(1.01);
box-shadow:
0 18px 40px rgba(15, 23, 42, 0.12),
0 0 0 1px rgba(211, 47, 47, 0.15);
}
.summary-text {
display: flex;
flex-direction: column;
}
.summary-title {
font-size: 13px;
color: #6b7280;
font-weight: 500;
line-height: 1.2;
}
.summary-value {
font-size: 22px;
font-weight: 700;
grid-column: 1 / 2;
justify-self: center;
margin-top: 6px;
}
.summary-icon {
position: absolute;
font-size: 80px;
right: -8px;
bottom: -8px;
opacity: 0.08;
transform: rotate(-15deg);
pointer-events: none;
transition: all .3s ease;
}
.summary-box:nth-child(1) .summary-icon {
color: #6b7280;
}
.summary-box:nth-child(2) .summary-icon {
color: #1d4ed8;
}
.summary-box:nth-child(3) .summary-icon {
color: #b91c1c;
}
.summary-box:nth-child(4) .summary-icon {
color: #15803d;
}
.summary-box:nth-child(5) .summary-icon {
color: #c2410c;
}
.summary-box:hover .summary-icon {
transform: rotate(-10deg) scale(1.1);
opacity: 0.12;
}
.summary-content {
grid-column: 1 / 3;
display: grid;
grid-template-columns: 52px 1fr;
align-items: center;
gap: 16px;
}
.summary-left-icon {
width: 52px;
height: 52px;
border-radius: 6px;
display: flex;
align-items: center;
justify-content: center;
font-size: 24px;
background: #f3f4f6;
flex-shrink: 0;
transition: all .25s ease;
}
.summary-box:hover .summary-left-icon {
transform: scale(1.08);
}
.summary-box:nth-child(1) .summary-left-icon {
background: linear-gradient(135deg, #f3f4f6, #d6d8dc);
color: #4b5563;
}
.summary-box:nth-child(2) .summary-left-icon {
background: linear-gradient(135deg, #dbeafe, #a8d0ff);
color: #1d4ed8;
}
.summary-box:nth-child(3) .summary-left-icon {
background: linear-gradient(135deg, #fee2e2, #ffb3b3);
color: #b91c1c;
}
.summary-box:nth-child(4) .summary-left-icon {
background: linear-gradient(135deg, #dcfce7, #9beeba);
color: #15803d;
}
.summary-box:nth-child(5) .summary-left-icon {
background: linear-gradient(135deg, #ffedd5, #ffc88e);
color: #c2410c;
}
.table-wrap {
width: 100%;
overflow-x: auto;
overflow-y: hidden;
-webkit-overflow-scrolling: touch;
border-top: 1px solid rgba(215, 215, 215, 0.7);
border-bottom: 1px solid rgba(215, 215, 215, 0.7);
}
.table-wrap::-webkit-scrollbar {
width: 6px;
height: 6px;
}
.table-wrap::-webkit-scrollbar-thumb {
background: #d32f2f;
border-radius: 10px;
}
table {
width: 100%;
min-width: 1100px;
table-layout: fixed;
border-collapse: separate;
border-spacing: 0;
}
thead {
background: linear-gradient(135deg, #d32f2f, #f87171);
color: white;
}
thead th {
z-index: 5;
background:
linear-gradient(180deg,
#fff5f5,
#ffeaea);
font-size: 14px;
color: #991b1b;
font-weight: 700;
padding: 16px 14px;
border-bottom: 1px solid #f0d4d4;
box-shadow:
0 4px 10px rgba(15, 23, 42, .04);
letter-spacing: .2px;
}
tbody td {
padding: 16px;
border-bottom: 1px solid #eee;
font-size: 13px;
}
tbody tr:nth-child(even) {
background: #fafafa;
}
tbody tr:hover {
background:
linear-gradient(90deg,
rgba(255, 245, 245, .9),
rgba(255, 255, 255, .95));
}
thead th:nth-child(2),
thead th:nth-child(8) {
text-align: left;
}
tbody td:nth-child(1),
tbody td:nth-child(3),
tbody td:nth-child(4),
tbody td:nth-child(5),
tbody td:nth-child(6),
tbody td:nth-child(7),
tbody td:nth-child(9) {
text-align: center;
}
thead th:nth-child(1),
thead th:nth-child(3),
thead th:nth-child(4),
thead th:nth-child(5),
thead th:nth-child(6),
thead th:nth-child(7),
thead th:nth-child(9) {
text-align: center;
}
.badge {
padding: 6px 14px;
border-radius: 8px;
font-size: 12px;
font-weight: 600;
letter-spacing: 0.3px;
display: inline-flex;
align-items: center;
gap: 6px;
border: 1px solid transparent;
backdrop-filter: blur(6px);
transition: all 0.2s ease;
}
.badge:hover {
transform: translateY(-1px);
}
.badge-red {
background: linear-gradient(135deg, #fee2e2, #fecaca);
color: #991b1b;
}
.badge-green {
background: linear-gradient(135deg, #dcfce7, #bbf7d0);
color: #14532d;
}
.kode-badge {
padding: 7px 12px;
border-radius: 8px;
font-size: 12px;
font-weight: 600;
background:
linear-gradient(135deg,
#fff1f1,
#ffdede);
color: #991b1b;
border: 1px solid #f4b4b4;
}
.action-btn {
padding: 8px 14px;
border-radius: 8px;
font-size: 12px;
font-weight: 600;
}
.save-btn {
background: #16a34a;
color: white;
}
.detail-btn {
background:
linear-gradient(135deg,
#ffa94d 0%,
#f97316 45%,
#ea580c 100%);
color: white;
border: none;
position: relative;
overflow: hidden;
transition: all .2s ease;
display: inline-flex;
box-shadow: 0 6px 14px rgba(235, 149, 37, 0.35);
}
.detail-btn:hover {
transform: translateY(-3px) scale(1.05);
box-shadow: 0 10px 20px rgba(235, 166, 37, 0.45);
}
.detail-btn:active {
transform: scale(0.96);
}
.detail-btn:hover::after {
left: 130%;
}
.month-wrapper {
position: relative;
display: flex;
align-items: center;
}
.month-input {
width: 100%;
padding: 8px 12px 8px 36px;
font-size: 13px;
border-radius: 6px;
border: 1px solid rgba(211, 47, 47, 0.48);
background: linear-gradient(145deg, #ffffff, #fff5f5);
box-shadow:
inset 0 2px 6px rgba(0, 0, 0, 0.08),
0 4px 10px rgba(211, 47, 47, 0.08);
transition: all .25s ease;
}
.month-input:hover {
border-color: #d32f2f;
box-shadow:
inset 0 2px 6px rgba(0, 0, 0, 0.08),
0 6px 16px rgba(211, 47, 47, 0.15);
}
.month-input:focus {
outline: none;
border-color: #d32f2f;
background: linear-gradient(145deg, #fff, #ffecec);
box-shadow:
inset 0 2px 6px rgba(0, 0, 0, 0.08),
0 0 0 3px rgba(211, 47, 47, 0.15),
0 10px 25px rgba(211, 47, 47, 0.2);
}
.month-input::-webkit-calendar-picker-indicator {
opacity: 0;
position: absolute;
right: 0;
width: 100%;
height: 100%;
cursor: pointer;
}
.month-icon {
position: absolute;
left: 14px;
font-size: 18px;
background: linear-gradient(135deg, #d32f2f, #9a0007);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
opacity: .75;
transition: .25s ease;
}
.month-wrapper:hover .month-icon {
opacity: 1;
transform: translateY(-1px) scale(1.1);
}
.month-wrapper:focus-within .month-icon {
opacity: 1;
transform: scale(1.15);
filter: drop-shadow(0 2px 6px rgba(211, 47, 47, .35));
}
.sort-icons {
display: inline-flex;
flex-direction: column;
margin-left: 6px;
vertical-align: middle;
}
.sort-icons i {
font-size: 9px;
line-height: 9px;
color: #9a0007;
transition: all .2s ease;
cursor: pointer;
}
th:hover .sort-icons i {
color: #9a0007;
}
.sort-icons i:hover {
transform: scale(1.2);
color: #d32f2f;
}
.sort-icons .active {
color: #d32f2f;
transform: scale(1.15);
}
.footer {
flex-shrink: 0;
color: #ebebeb;
font-size: 14px;
padding: 16px 22px;
display: flex;
justify-content: space-between;
align-items: center;
border-top: 1px solid #c2c2c2;
background-color: #d32f2f;
}
.pagination {
display: flex;
align-items: center;
gap: 8px;
}
.page-btn {
width: 34px;
height: 34px;
border: none;
border-radius: 6px;
background: #ffffff;
cursor: pointer;
font-size: 13px;
color: #111827;
}
.page-btn.arrow {
color: #9ca3af;
}
.page-btn.active {
background: #760006;
border: 1px solid #9a0007;
color: #fff;
}
.page-ellipsis {
display: flex;
align-items: center;
padding: 0 8px;
color: #9ca3af;
}
.page-btn:hover {
transform: translateY(-2px);
box-shadow: 0 14px 24px rgba(211, 47, 47, 0.28);
}
.page-size-select {
height: 100%;
padding: 8px 10px;
border-radius: 8px;
border: 1px solid #e5e7eb;
font-size: 10px;
outline: none;
}
/* =========================
RESPONSIVE BREAKPOINTS
========================= */
@media (max-width: 992px) {
.header {
flex-direction: column;
align-items: stretch;
}
.header-nav {
width: 100%;
}
}
@media (max-width: 768px) {
.header-nav {
flex-direction: column;
}
}
@media (min-width:1921px) {
.super-card {
max-width: 1800px;
margin: auto;
}
body {
padding: 40px;
}
.table-header,
.section {
padding-left: 32px;
padding-right: 32px;
}
}
@media (max-width:1600px) {
.top-grid {
grid-template-columns: 1.4fr repeat(4, 1fr);
}
}
@media (max-width:1400px) {
.top-grid {
grid-template-columns: 1.5fr 1fr 1fr;
}
.summary-value {
font-size: 20px;
}
.btn-primary {
padding: 12px 4rem;
}
}
@media (max-width:1200px) {
.top-grid {
grid-template-columns: 1fr 1fr;
}
.filter-card {
grid-column: 1 / -1;
}
.table-tools {
flex-wrap: wrap;
}
.search-box input {
width: 180px;
}
}
@media (max-width:992px) {
body {
padding: 16px;
}
.top-grid {
grid-template-columns: 1fr 1fr;
}
.summary-box {
min-height: auto;
}
.summary-content {
gap: 12px;
}
.table-header {
flex-direction: column;
align-items: stretch;
}
.table-tools {
width: 100%;
justify-content: space-between;
}
.search-box {
flex: 1;
}
.search-box input {
width: 100%;
}
table {
min-width: 1100px;
}
.table-wrap {
overflow-x: auto;
overflow-y: hidden;
}
}
@media (max-width:768px) {
body {
padding: 12px;
}
.header {
padding: 16px;
}
.header h1 {
font-size: 15px;
}
.section {
padding: 14px;
}
.top-grid {
grid-template-columns: 1fr;
}
.summary-box {
min-height: 85px;
}
.summary-value {
font-size: 18px;
}
.summary-left-icon {
width: 46px;
height: 46px;
font-size: 20px;
}
.table-tools {
flex-direction: column;
align-items: stretch;
}
.filter-status {
width: 100%;
justify-content: center;
}
.search-box {
width: 100%;
}
.search-box input {
width: 100%;
}
.data-info-pill {
justify-content: center;
}
.footer {
flex-direction: column;
gap: 12px;
text-align: center;
}
.pagination {
flex-wrap: wrap;
justify-content: center;
}
}
@media (max-width:576px) {
body {
padding: 10px;
}
.header {
padding: 14px;
gap: 10px;
}
.header i {
width: 34px;
height: 34px;
font-size: 15px;
}
.header h1 {
font-size: 14px;
}
.periode-header {
flex-direction: column;
align-items: flex-start;
}
.periode-note {
width: 100%;
}
.filter-card {
padding: 12px;
}
.filter-card .flex {
flex-direction: column;
}
.btn,
.btn-primary,
.btn-dark {
width: 100%;
padding: 12px;
}
.summary-content {
grid-template-columns: 44px 1fr;
}
.summary-left-icon {
width: 44px;
height: 44px;
font-size: 18px;
}
.summary-value {
font-size: 17px;
}
.summary-title {
font-size: 12px;
}
.status-btn {
flex: 1;
padding: 10px;
}
.page-btn {
width: 32px;
height: 32px;
}
table {
min-width: 1000px;
}
}
@media (max-width:480px) {
body {
padding: 8px;
}
.section {
padding: 10px;
}
.header h1 {
font-size: 13px;
}
.summary-box {
padding: 12px;
}
.summary-title {
font-size: 11px;
}
.summary-value {
font-size: 16px;
}
.summary-icon {
font-size: 55px;
}
.data-info-pill {
flex-wrap: wrap;
height: auto;
padding: 10px;
}
.page-size-select {
width: 100%;
}
.footer {
padding: 12px;
font-size: 12px;
}
}
@media (max-width:360px) {
body {
padding: 6px;
}
.header {
padding: 12px;
}
.header i {
width: 30px;
height: 30px;
font-size: 13px;
}
.header h1 {
font-size: 12px;
}
.summary-box {
padding: 10px;
}
.summary-title {
font-size: 10px;
}
.summary-value {
font-size: 14px;
}
.status-btn {
font-size: 10px;
padding: 8px;
}
.page-btn {
width: 28px;
height: 28px;
font-size: 11px;
}
.footer {
font-size: 11px;
}
}
@media (max-width:320px) {
.header {
flex-direction: column;
text-align: center;
}
.summary-content {
grid-template-columns: 1fr;
text-align: center;
}
.summary-left-icon {
margin: auto;
}
.filter-status {
flex-direction: column;
}
.status-btn {
width: 100%;
}
}
</style>
</head>
@php
\Carbon\Carbon::setLocale('id');
@endphp
<body class="p-8">
<div class="w-full mx-auto">
<div class="super-card">
<div class="header">
<div class="header-left">
<i class="fa-solid fa-boxes-stacked"
style="background: linear-gradient(135deg, #22c55e, #15803d);
width: 50px; height: 50px; font-size: 22px;"></i>
<h1>RENCANA PENGADAAN BARANG</h1>
</div>
<div class="header-nav">
<a href="/prediksi-barang" class="header-btn">
<i class="fa-solid fa-chart-column"></i>
Prediksi
</a>
<a href="/riwayat-prediksi" class="header-btn">
<i class="fa-solid fa-clock-rotate-left"></i>
Riwayat
</a>
<a href="/rencana-pengadaan" class="header-btn active">
<i class="fa-solid fa-boxes-stacked"></i>
Pengadaan
</a>
<button class="refresh-btn" onclick="location.reload()">
<i class="fa-solid fa-rotate-right refresh-icon"></i>
</button>
</div>
</div>
<div class="section">
<div class="top-grid">
<form method="POST" action="/rencana-pengadaan/set-periode" class="filter-card">
@csrf
<div class="periode-header">
<label class="text-sm periode-label">PERIODE PENGADAAN</label>
<div id="periodeNote" class="periode-note hidden">
<i class="bi bi-exclamation-circle"></i>
Tidak ada data prediksi untuk bulan ini.
</div>
</div>
<div class="month-wrapper mb-4">
<i class="bi bi-calendar3 month-icon"></i>
<input type="month" name="periode" id="periodeInput" class="month-input"
value="{{ $periodeDefault ?? '' }}" min="{{ $minPeriode ?? '' }}"
max="{{ $maxPeriode ?? '' }}">
</div>
<div class="flex gap-3">
<button type="submit" id="btnTampilkan" class="btn btn-primary w-full">Tampilkan</button>
<a id="btnCetak" href="{{ url('/rencana-pengadaan/cetak') }}" target="_blank"
class="btn btn-dark w-full text-center inline-block">
Cetak
</a>
</div>
</form>
<div class="summary-box">
<i class="bi bi-box-seam summary-icon"></i>
<div class="summary-content">
<div class="summary-left-icon">
<i class="bi bi-clipboard-data"></i>
</div>
<div>
<div class="summary-title">Total Barang Dicek</div>
</div>
</div>
<div class="summary-value">{{ $totalBarang }}</div>
</div>
<div class="summary-box">
<i class="bi bi-exclamation-triangle summary-icon"></i>
<div class="summary-content">
<div class="summary-left-icon">
<i class="bi bi-arrow-down-circle"></i>
</div>
<div>
<div class="summary-title">Perlu Restock</div>
</div>
</div>
<div class="summary-value text-red-600">{{ $perluRestock }}</div>
</div>
<div class="summary-box">
<i class="bi bi-check-circle summary-icon"></i>
<div class="summary-content">
<div class="summary-left-icon">
<i class="bi bi-shield-check"></i>
</div>
<div>
<div class="summary-title">Status Aman</div>
</div>
</div>
<div class="summary-value text-black-600">{{ $aman }}</div>
</div>
<div class="summary-box">
<i class="bi bi-cart-plus summary-icon"></i>
<div class="summary-content">
<div class="summary-left-icon">
<i class="bi bi-bag-plus"></i>
</div>
<div>
<div class="summary-title">Total Usulan Pembelian</div>
</div>
</div>
<div class="summary-value text-yellow-600">{{ $totalUsulan }}</div>
</div>
</div>
</div>
<div class="section-divider"></div>
<div class="section table-section">
<div class="table-header">
<h2 id="tableTitle">
Daftar Rencana Pengadaan
<span class="periode-highlight">
{{ \Carbon\Carbon::createFromFormat('Y-m', $periodeDefault)->translatedFormat('F Y') }}
</span>
</h2>
<div class="table-tools">
<div class="filter-status">
<button class="status-btn active" data-status="all">Semua</button>
<button class="status-btn" data-status="aman">Aman</button>
<button class="status-btn" data-status="restock">Restock</button>
</div>
<div class="search-box">
<i class="fa-solid fa-magnifying-glass"></i>
<input type="text" id="searchInput" placeholder="Cari barang...">
</div>
<div class="data-info-pill">
Tampilkan
<select id="pageSize" class="page-size-select">
<option value="10" selected>10</option>
<option value="25">25</option>
<option value="50">50</option>
<option value="100">100</option>
</select>
data
</div>
</div>
</div>
<div class="table-wrap">
<table>
<thead>
<tr>
<th>
Kode
<span class="sort-icons">
<i class="fa-solid fa-chevron-up"></i>
<i class="fa-solid fa-chevron-down"></i>
</span>
</th>
<th>
Nama Barang
<span class="sort-icons">
<i class="fa-solid fa-chevron-up"></i>
<i class="fa-solid fa-chevron-down"></i>
</span>
</th>
<th>
Prediksi
<span class="sort-icons">
<i class="fa-solid fa-chevron-up"></i>
<i class="fa-solid fa-chevron-down"></i>
</span>
</th>
<th>
Stok
<span class="sort-icons">
<i class="fa-solid fa-chevron-up"></i>
<i class="fa-solid fa-chevron-down"></i>
</span>
</th>
<th>
Selisih
<span class="sort-icons">
<i class="fa-solid fa-chevron-up"></i>
<i class="fa-solid fa-chevron-down"></i>
</span>
</th>
<th>
Usulan Beli
<span class="sort-icons">
<i class="fa-solid fa-chevron-up"></i>
<i class="fa-solid fa-chevron-down"></i>
</span>
</th>
<th>
Satuan
<span class="sort-icons">
<i class="fa-solid fa-chevron-up"></i>
<i class="fa-solid fa-chevron-down"></i>
</span>
</th>
<th>
Status
<span class="sort-icons">
<i class="fa-solid fa-chevron-up"></i>
<i class="fa-solid fa-chevron-down"></i>
</span>
</th>
<th>
Aksi
<span class="sort-icons">
<i class="fa-solid fa-chevron-up"></i>
<i class="fa-solid fa-chevron-down"></i>
</span>
</th>
</tr>
</thead>
<tbody>
@forelse($rows as $row)
<tr>
<td>
<span class="kode-badge">{{ $row['kode'] }}</span>
</td>
<td>{{ $row['nama_barang'] }}</td>
<td>{{ $row['prediksi'] }}</td>
<td>{{ $row['stok'] }}</td>
<td
class="{{ $row['selisih'] < 0 ? 'text-red-600' : 'text-green-600' }} font-semibold">
{{ $row['selisih'] > 0 ? '+' : '' }}{{ $row['selisih'] }}
</td>
<td>{{ $row['usulan'] }}</td>
<td>{{ $row['satuan'] }}</td>
<td>
@if ($row['status'] == 'Perlu Restock')
<span class="badge badge-red">Perlu Restock</span>
@else
<span class="badge badge-green">Aman</span>
@endif
</td>
<td>
<a href="{{ url('/detail-rencana-pengadaan/' . $row['kode'] . '/' . session('periode_pengadaan', $periodeDefault)) }}"
class="action-btn detail-btn">
Detail
</a>
</td>
</tr>
@empty
<tr>
<td colspan="9" class="text-center py-6 text-gray-500">
Tidak ada data untuk periode ini
</td>
</tr>
@endforelse
</tbody>
</table>
</div>
<div class="footer">
<div class="flex items-center gap-3 text-sm">
<span id="rangeText">Menampilkan 0 sampai 0 dari 0 data</span>
</div>
<div class="pagination" id="pagination"></div>
</div>
</div>
</div>
</div>
<script>
document.addEventListener("DOMContentLoaded", function() {
const table = document.querySelector("table");
const tbody = table.querySelector("tbody");
const headers = table.querySelectorAll("thead th");
let rows = Array.from(tbody.querySelectorAll("tr"));
let currentPage = 1;
let pageSize = 10;
function getValue(row, index) {
let text = row.children[index].innerText.trim();
if (!isNaN(text.replace(/[^0-9\-]/g, ""))) {
return parseInt(text.replace(/[^0-9\-]/g, "")) || 0;
}
return text.toLowerCase();
}
function clearActive() {
document.querySelectorAll(".sort-icons i").forEach(i => {
i.classList.remove("active");
});
}
headers.forEach((th, index) => {
if (index === 8) return;
const up = th.querySelector(".fa-chevron-up");
const down = th.querySelector(".fa-chevron-down");
if (!up || !down) return;
up.addEventListener("click", () => {
rows.sort((a, b) => {
let A = getValue(a, index);
let B = getValue(b, index);
return A > B ? 1 : -1;
});
clearActive();
up.classList.add("active");
tbody.innerHTML = "";
rows.forEach(r => tbody.appendChild(r));
});
down.addEventListener("click", () => {
rows.sort((a, b) => {
let A = getValue(a, index);
let B = getValue(b, index);
return A < B ? 1 : -1;
});
clearActive();
down.classList.add("active");
tbody.innerHTML = "";
rows.forEach(r => tbody.appendChild(r));
});
});
const searchInput = document.getElementById("searchInput");
const statusButtons = document.querySelectorAll(".status-btn");
let currentStatus = "all";
function filterTable() {
const keyword = searchInput.value.toLowerCase();
let visibleCount = 0;
rows.forEach(row => {
const kode = row.children[0].innerText.toLowerCase();
const nama = row.children[1].innerText.toLowerCase();
const statusText = row.children[7].innerText.toLowerCase();
let matchSearch = kode.includes(keyword) || nama.includes(keyword);
let matchStatus = true;
if (currentStatus === "aman") {
matchStatus = statusText.includes("aman");
} else if (currentStatus === "restock") {
matchStatus = statusText.includes("restock");
}
const show = matchSearch && matchStatus;
row.style.display = show ? "" : "none";
if (show) visibleCount++;
});
let emptyRow = document.getElementById("emptyFilterRow");
if (visibleCount === 0) {
if (!emptyRow) {
emptyRow = document.createElement("tr");
emptyRow.id = "emptyFilterRow";
emptyRow.innerHTML = `
<td colspan="9" class="text-center py-6 text-gray-500 font-medium">
</td>
`;
tbody.appendChild(emptyRow);
}
let message = "Data tidak ditemukan";
if (currentStatus === "aman") {
message = "Barang dengan status aman tidak ada";
} else if (currentStatus === "restock") {
message = "Barang dengan status restock tidak ada";
}
emptyRow.querySelector("td").innerText = message;
} else {
if (emptyRow) {
emptyRow.remove();
}
}
currentPage = 1;
renderTable();
updateFooter();
}
function renderTable() {
tbody.innerHTML = "";
const visibleRows = rows.filter(r => r.style.display !== "none");
const start = (currentPage - 1) * pageSize;
const end = start + pageSize;
const pageRows = visibleRows.slice(start, end);
pageRows.forEach(r => tbody.appendChild(r));
renderPagination();
updateFooter();
}
function renderPagination() {
const pagination = document.getElementById("pagination");
pagination.innerHTML = "";
const visibleRows = rows.filter(r => r.style.display !== "none");
const totalPages = Math.ceil(visibleRows.length / pageSize);
function createBtn(label, page, disabled = false, active = false, isArrow = false) {
const btn = document.createElement("button");
btn.className = "page-btn";
btn.innerText = label;
if (isArrow) btn.classList.add("arrow");
if (active) btn.classList.add("active");
if (disabled) {
btn.disabled = true;
btn.style.opacity = "0.5";
btn.style.cursor = "not-allowed";
}
btn.addEventListener("click", () => {
if (!disabled) {
currentPage = page;
renderTable();
}
});
return btn;
}
pagination.appendChild(
createBtn("", currentPage - 1, currentPage === 1, false, true)
);
let pages = [];
if (totalPages <= 7) {
for (let i = 1; i <= totalPages; i++) {
pages.push(i);
}
} else {
pages.push(1);
let start = Math.max(2, currentPage - 1);
let end = Math.min(totalPages - 1, currentPage + 1);
if (currentPage <= 3) {
start = 2;
end = 4;
}
if (currentPage >= totalPages - 2) {
start = totalPages - 3;
end = totalPages - 1;
}
if (start > 2) pages.push("...");
for (let i = start; i <= end; i++) pages.push(i);
if (end < totalPages - 1) pages.push("...");
pages.push(totalPages);
}
pages.forEach(p => {
if (p === "...") {
const span = document.createElement("span");
span.className = "page-ellipsis";
span.innerText = "...";
span.style.padding = "0 8px";
span.style.color = "#fff";
pagination.appendChild(span);
} else {
pagination.appendChild(
createBtn(p, p, false, p === currentPage)
);
}
});
pagination.appendChild(
createBtn("", currentPage + 1, currentPage === totalPages, false, true)
);
}
function updateFooter() {
const visibleRows = rows.filter(r => r.style.display !== "none");
const total = visibleRows.length;
const start = total === 0 ? 0 : (currentPage - 1) * pageSize + 1;
const end = Math.min(currentPage * pageSize, total);
document.getElementById("rangeText").innerText =
`Menampilkan ${start} sampai ${end} dari ${total} data`;
}
searchInput.addEventListener("input", filterTable);
statusButtons.forEach(btn => {
btn.addEventListener("click", () => {
statusButtons.forEach(b => b.classList.remove("active"));
btn.classList.add("active");
currentStatus = btn.dataset.status;
filterTable();
});
});
const pageSizeEl = document.getElementById("pageSize");
if (pageSizeEl) {
pageSizeEl.addEventListener("change", function(e) {
pageSize = parseInt(e.target.value);
currentPage = 1;
renderTable();
});
}
const periodeInput = document.getElementById("periodeInput");
const tableTitle = document.getElementById("tableTitle");
const periodeValid = @json($periodeList);
const btnTampilkan = document.getElementById("btnTampilkan");
const btnCetak = document.getElementById("btnCetak");
const periodeNote = document.getElementById("periodeNote");
function validatePeriode() {
const val = periodeInput.value;
if (!periodeValid.includes(val)) {
periodeNote.classList.remove("hidden");
btnTampilkan.disabled = true;
btnTampilkan.classList.add("opacity-50", "cursor-not-allowed");
btnCetak.classList.add("pointer-events-none", "opacity-50");
} else {
periodeNote.classList.add("hidden");
btnTampilkan.disabled = false;
btnTampilkan.classList.remove("opacity-50", "cursor-not-allowed");
btnCetak.classList.remove("pointer-events-none", "opacity-50");
btnCetak.href = `/rencana-pengadaan/cetak?periode=${val}`;
}
}
periodeInput.addEventListener("input", validatePeriode);
validatePeriode();
filterTable();
});
</script>
</body>
</html>