2414 lines
66 KiB
PHP
2414 lines
66 KiB
PHP
<!DOCTYPE html>
|
|
<html>
|
|
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css" rel="stylesheet">
|
|
<link href="https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700;800&display=swap" rel="stylesheet">
|
|
<link rel="icon" type="image/png" href="{{ asset('images/logo-pmi.png') }}">
|
|
<title>PREDIKSI BARANG - UDD PMI KABUPATEN JEMBER</title>
|
|
|
|
<style>
|
|
:root {
|
|
--primary: #c62828;
|
|
--primary-dark: #8e0000;
|
|
--primary-light: #ffebee;
|
|
--secondary: #37474f;
|
|
--secondary-soft: #eceff1;
|
|
--bg: #f7faff;
|
|
--card: rgba(255, 255, 255, 0.92);
|
|
--border: #d8dee6;
|
|
--text: #1f2937;
|
|
--text-soft: #6b7280;
|
|
--success: #16a34a;
|
|
--danger: #dc2626;
|
|
--shadow:
|
|
0 10px 30px rgba(15, 23, 42, 0.08);
|
|
--shadow-hover:
|
|
0 18px 40px rgba(15, 23, 42, 0.12);
|
|
}
|
|
|
|
.autocomplete-box {
|
|
position: absolute;
|
|
background: #f8d3d3;
|
|
width: 100%;
|
|
z-index: 10;
|
|
max-height: 180px;
|
|
overflow-y: auto;
|
|
border-radius: 6px;
|
|
}
|
|
|
|
.autocomplete-item {
|
|
padding: 8px 10px;
|
|
cursor: pointer;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.autocomplete-item:hover {
|
|
background: #ffadad;
|
|
}
|
|
|
|
body {
|
|
font-family: "Poppins", sans-serif;
|
|
background: var(--bg);
|
|
margin: 0;
|
|
padding: 40px;
|
|
}
|
|
|
|
.container {
|
|
max-width: 1050px;
|
|
margin: auto;
|
|
}
|
|
|
|
.card {
|
|
position: relative;
|
|
overflow: visible;
|
|
background: var(--card);
|
|
backdrop-filter: blur(14px);
|
|
padding: 30px;
|
|
border-radius: 8px;
|
|
border: 1px solid rgba(255, 95, 95, 0.6);
|
|
margin-bottom: 20px;
|
|
box-shadow: var(--shadow);
|
|
transition: .25s ease;
|
|
}
|
|
|
|
/* .card:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow: var(--shadow-hover);
|
|
} */
|
|
|
|
.card h2 {
|
|
position: relative;
|
|
border-radius: 8px 8px 0 0;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 14px;
|
|
background:
|
|
linear-gradient(135deg,
|
|
#d32f2f 0%,
|
|
#b71c1c 45%,
|
|
#7f0000 100%);
|
|
font-size: 18px;
|
|
font-weight: 700;
|
|
letter-spacing: .4px;
|
|
color: white;
|
|
padding: 20px 30px;
|
|
margin: -30px -30px 30px -30px;
|
|
overflow: hidden;
|
|
border-bottom:
|
|
1px solid rgba(255, 255, 255, 0.08);
|
|
}
|
|
|
|
.card h2::before {
|
|
content: "";
|
|
position: absolute;
|
|
top: -60px;
|
|
right: -50px;
|
|
width: 180px;
|
|
height: 180px;
|
|
background:
|
|
radial-gradient(circle,
|
|
rgba(255, 255, 255, .18) 0%,
|
|
rgba(255, 255, 255, 0) 70%);
|
|
border-radius: 50%;
|
|
pointer-events: none;
|
|
}
|
|
|
|
.card h2::after {
|
|
content: "";
|
|
position: absolute;
|
|
top: 0;
|
|
left: -120px;
|
|
width: 80px;
|
|
height: 100%;
|
|
background:
|
|
linear-gradient(120deg,
|
|
transparent,
|
|
rgba(255, 255, 255, .18),
|
|
transparent);
|
|
transform: skewX(-25deg);
|
|
animation: shineMove 5s linear infinite;
|
|
}
|
|
|
|
.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);
|
|
}
|
|
|
|
h2 {
|
|
margin: 0 0 20px;
|
|
font-weight: 600;
|
|
color: var(--primary);
|
|
}
|
|
|
|
.header {
|
|
justify-content: space-between;
|
|
position: relative;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 14px;
|
|
background:
|
|
linear-gradient(135deg,
|
|
#d32f2f 0%,
|
|
#b71c1c 45%,
|
|
#7f0000 100%);
|
|
font-size: 18px;
|
|
font-weight: 700;
|
|
letter-spacing: .4px;
|
|
color: white;
|
|
padding: 20px 30px;
|
|
margin: -30px -30px 30px -30px;
|
|
overflow: hidden;
|
|
border-radius: 8px 8px 0 0;
|
|
border-bottom: 1px solid rgba(255, 255, 255, .08);
|
|
}
|
|
|
|
.header-left {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 14px;
|
|
min-width: 0;
|
|
}
|
|
|
|
.header-left span {
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.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;
|
|
height: auto;
|
|
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);
|
|
}
|
|
|
|
.header .fa-chart-column,
|
|
.header .fa-clock-rotate-left,
|
|
.header .fa-boxes-stacked,
|
|
.header .fa-pie-chart {
|
|
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);
|
|
}
|
|
|
|
.section-title {
|
|
font-size: 14px;
|
|
color: #890000c7;
|
|
margin-bottom: 12px;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.item-row {
|
|
display: grid;
|
|
grid-template-columns: 140px 1fr 180px 90px;
|
|
gap: 10px;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.item-row input {
|
|
width: 100%;
|
|
}
|
|
|
|
input,
|
|
select {
|
|
width: 100%;
|
|
height: 46px;
|
|
padding: 0 14px;
|
|
border-radius: 4px;
|
|
border: 1px solid var(--border);
|
|
background: rgba(255, 255, 255, 0.95);
|
|
font-size: 14px;
|
|
font-family: "Poppins", sans-serif;
|
|
color: var(--text);
|
|
box-sizing: border-box;
|
|
transition: .2s ease;
|
|
}
|
|
|
|
input:focus,
|
|
select:focus {
|
|
outline: none;
|
|
border-color: #c62828;
|
|
background: white;
|
|
box-shadow:
|
|
0 0 0 4px rgba(198, 40, 40, 0.08);
|
|
}
|
|
|
|
.input-soft,
|
|
.jenis-barang {
|
|
background:
|
|
linear-gradient(180deg,
|
|
#fff5f5 0%,
|
|
#ffe8e8 100%);
|
|
border: 1px solid #efb6b6;
|
|
color: #7f1d1d;
|
|
box-shadow:
|
|
inset 0 3px 8px rgba(127, 29, 29, 0.10),
|
|
inset 0 -2px 3px rgba(255, 255, 255, 0.9),
|
|
0 1px 2px rgba(0, 0, 0, 0.03);
|
|
transition: all .22s ease;
|
|
}
|
|
|
|
.input-soft:hover,
|
|
.jenis-barang:hover {
|
|
background:
|
|
linear-gradient(180deg,
|
|
#ffecec 0%,
|
|
#ffdede 100%);
|
|
border-color: #e78d8d;
|
|
box-shadow:
|
|
inset 0 3px 10px rgba(127, 29, 29, 0.14),
|
|
0 4px 10px rgba(198, 40, 40, 0.08);
|
|
}
|
|
|
|
.input-soft:focus,
|
|
.jenis-barang:focus {
|
|
background: #fffafa;
|
|
border-color: #c62828;
|
|
color: #4a0404;
|
|
box-shadow:
|
|
inset 0 3px 10px rgba(127, 29, 29, 0.12),
|
|
0 0 0 4px rgba(198, 40, 40, 0.14),
|
|
0 8px 18px rgba(198, 40, 40, 0.12);
|
|
}
|
|
|
|
.jenis-barang {
|
|
cursor: not-allowed;
|
|
font-weight: 500;
|
|
font-size: 11px;
|
|
}
|
|
|
|
.jenis-barang::placeholder {
|
|
color: #9b4b4b;
|
|
}
|
|
|
|
.input-icon-wrapper {
|
|
position: relative;
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.input-icon {
|
|
position: absolute;
|
|
left: 14px;
|
|
z-index: 2;
|
|
color: #b23b3b;
|
|
font-size: 14px;
|
|
opacity: .8;
|
|
pointer-events: none;
|
|
transition: .2s ease;
|
|
}
|
|
|
|
.input-icon-wrapper input {
|
|
padding-left: 42px;
|
|
}
|
|
|
|
.input-icon-wrapper:hover .input-icon {
|
|
color: #c62828;
|
|
transform: scale(1.08);
|
|
opacity: 1;
|
|
}
|
|
|
|
.section-divider {
|
|
height: 1px;
|
|
margin: 20px -30px;
|
|
background: rgba(81, 85, 92, 0.3);
|
|
}
|
|
|
|
.items-info {
|
|
margin-top: 12px;
|
|
font-size: 12px;
|
|
font-weight: 500;
|
|
color: #7f1d1d;
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
}
|
|
|
|
.items-info i {
|
|
width: 24px;
|
|
height: 24px;
|
|
border-radius: 4px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
background: linear-gradient(135deg, #ef4444, #b91c1c);
|
|
color: white;
|
|
font-size: 11px;
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.info-danger {
|
|
color: #b91c1c;
|
|
}
|
|
|
|
.info-danger i {
|
|
background: linear-gradient(135deg, #ef4444, #b91c1c);
|
|
}
|
|
|
|
.info-success {
|
|
color: #15803d;
|
|
}
|
|
|
|
.info-success i {
|
|
background: linear-gradient(135deg, #22c55e, #15803d);
|
|
}
|
|
|
|
.info-warning {
|
|
color: #ca8a04;
|
|
}
|
|
|
|
.info-warning i {
|
|
background: linear-gradient(135deg, #facc15, #ca8a04);
|
|
}
|
|
|
|
.section-block {
|
|
padding-top: 10px;
|
|
}
|
|
|
|
.section-block,
|
|
#items {
|
|
position: relative;
|
|
}
|
|
|
|
.btn-group {
|
|
display: flex;
|
|
gap: 5px;
|
|
}
|
|
|
|
button {
|
|
border: none;
|
|
border-radius: 6px;
|
|
cursor: pointer;
|
|
font-size: 14px;
|
|
height: 40px;
|
|
}
|
|
|
|
.btn-add {
|
|
background:
|
|
linear-gradient(135deg,
|
|
#34d399 0%,
|
|
#10b981 45%,
|
|
#059669 100%);
|
|
color: white;
|
|
width: 40px;
|
|
position: relative;
|
|
overflow: hidden;
|
|
box-shadow:
|
|
0 6px 14px rgba(16, 185, 129, 0.28),
|
|
inset 0 1px 1px rgba(255, 255, 255, 0.28);
|
|
}
|
|
|
|
.btn-remove {
|
|
background:
|
|
linear-gradient(135deg,
|
|
#fb7185 0%,
|
|
#ef4444 45%,
|
|
#dc2626 100%);
|
|
color: white;
|
|
width: 40px;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
position: relative;
|
|
overflow: hidden;
|
|
box-shadow:
|
|
0 6px 14px rgba(239, 68, 68, 0.28),
|
|
inset 0 1px 1px rgba(255, 255, 255, 0.24);
|
|
}
|
|
|
|
/* .btn-add::before,
|
|
.btn-remove::before {
|
|
content: "";
|
|
position: absolute;
|
|
top: 0;
|
|
left: -80%;
|
|
width: 55%;
|
|
height: 100%;
|
|
background:
|
|
linear-gradient(120deg,
|
|
transparent,
|
|
rgba(255, 255, 255, 0.45),
|
|
transparent);
|
|
transform: skewX(-25deg);
|
|
transition: .55s ease;
|
|
}
|
|
|
|
.btn-add:hover::before,
|
|
.btn-remove:hover::before {
|
|
left: 140%;
|
|
} */
|
|
|
|
.btn-add,
|
|
.btn-remove {
|
|
transition:
|
|
transform .22s ease,
|
|
box-shadow .22s ease,
|
|
filter .22s ease;
|
|
transform: translateY(0);
|
|
}
|
|
|
|
.btn-add:hover {
|
|
transform: translateY(-2px) scale(1.06);
|
|
filter: brightness(1.05);
|
|
box-shadow:
|
|
0 12px 22px rgba(16, 185, 129, 0.38),
|
|
inset 0 1px 1px rgba(255, 255, 255, 0.3);
|
|
}
|
|
|
|
.btn-remove:hover {
|
|
transform: translateY(-2px) scale(1.06);
|
|
filter: brightness(1.05);
|
|
box-shadow:
|
|
0 12px 22px rgba(239, 68, 68, 0.36),
|
|
inset 0 1px 1px rgba(255, 255, 255, 0.28);
|
|
}
|
|
|
|
.btn-add:active,
|
|
.btn-remove:active {
|
|
transform: scale(0.94);
|
|
filter: brightness(.96);
|
|
}
|
|
|
|
.btn-add i,
|
|
.btn-remove i {
|
|
position: relative;
|
|
z-index: 2;
|
|
font-size: 13px;
|
|
}
|
|
|
|
.form-row {
|
|
display: grid;
|
|
grid-template-columns: 1fr 280px;
|
|
gap: 14px;
|
|
align-items: stretch;
|
|
}
|
|
|
|
.form-row>div {
|
|
display: flex;
|
|
flex-direction: column;
|
|
}
|
|
|
|
.form-row>div:last-child {
|
|
justify-content: flex-end;
|
|
}
|
|
|
|
label {
|
|
font-size: 13px;
|
|
color: #555;
|
|
margin-bottom: 5px;
|
|
display: block;
|
|
}
|
|
|
|
.btn-predict {
|
|
background: linear-gradient(135deg, #d32f2f, #9a0007);
|
|
color: white;
|
|
font-weight: 700;
|
|
width: 100%;
|
|
height: 48px;
|
|
border-radius: 8px;
|
|
font-size: 14px;
|
|
letter-spacing: .5px;
|
|
transition:
|
|
transform .22s ease,
|
|
box-shadow .22s ease,
|
|
filter .22s ease,
|
|
background .22s ease;
|
|
box-shadow:
|
|
0 10px 24px rgba(220, 38, 38, 0.28),
|
|
0 2px 6px rgba(127, 29, 29, 0.18),
|
|
inset 0 1px 1px rgba(255, 255, 255, 0.16);
|
|
}
|
|
|
|
.btn-predict:hover {
|
|
background:
|
|
linear-gradient(135deg,
|
|
#f87171 0%,
|
|
#ef4444 32%,
|
|
#dc2626 65%,
|
|
#991b1b 100%);
|
|
transform: translateY(-2px);
|
|
filter: saturate(1.08);
|
|
box-shadow:
|
|
0 16px 30px rgba(220, 38, 38, 0.34),
|
|
0 4px 10px rgba(127, 29, 29, 0.2);
|
|
}
|
|
|
|
.btn-predict:active {
|
|
transform: scale(0.98);
|
|
filter: brightness(.96);
|
|
box-shadow:
|
|
0 6px 14px rgba(220, 38, 38, 0.22);
|
|
}
|
|
|
|
label {
|
|
font-size: 13px;
|
|
font-weight: 600;
|
|
color: #444;
|
|
margin-bottom: 6px;
|
|
display: block;
|
|
letter-spacing: .2px;
|
|
}
|
|
|
|
.form-row {
|
|
display: grid;
|
|
grid-template-columns: 1fr 180px;
|
|
gap: 14px;
|
|
align-items: stretch;
|
|
}
|
|
|
|
.popup-overlay {
|
|
position: fixed;
|
|
inset: 0;
|
|
background: rgba(15, 23, 42, 0.45);
|
|
backdrop-filter: blur(6px);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
z-index: 9999;
|
|
padding: 20px;
|
|
animation: fadeOverlay .2s ease;
|
|
}
|
|
|
|
.popup-box {
|
|
position: relative;
|
|
overflow: hidden;
|
|
background: rgba(255, 255, 255, .96);
|
|
backdrop-filter: blur(12px);
|
|
border-radius: 10px;
|
|
width: 420px;
|
|
max-width: 95%;
|
|
padding: 30px 28px 24px;
|
|
text-align: center;
|
|
border: 1px solid rgba(255, 255, 255, .5);
|
|
box-shadow:
|
|
0 25px 50px rgba(15, 23, 42, 0.18),
|
|
0 10px 20px rgba(15, 23, 42, 0.08);
|
|
animation: popupIn .28s cubic-bezier(.2, .8, .2, 1);
|
|
}
|
|
|
|
.popup-box::before {
|
|
content: "";
|
|
position: absolute;
|
|
inset: 0;
|
|
background:
|
|
linear-gradient(135deg,
|
|
rgba(255, 255, 255, .45),
|
|
transparent 40%);
|
|
pointer-events: none;
|
|
}
|
|
|
|
.popup-icon {
|
|
width: 82px;
|
|
height: 82px;
|
|
margin: 0 auto 18px;
|
|
border-radius: 50%;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
font-size: 34px;
|
|
position: relative;
|
|
animation: popupBounce .45s ease;
|
|
}
|
|
|
|
.popup-icon::after {
|
|
content: "";
|
|
position: absolute;
|
|
inset: -8px;
|
|
border-radius: 50%;
|
|
border: 2px solid rgba(255, 255, 255, .4);
|
|
animation: pulseRing 1.8s infinite;
|
|
}
|
|
|
|
.popup-warning .popup-icon {
|
|
background:
|
|
linear-gradient(135deg, #f59e0b, #d97706);
|
|
color: white;
|
|
box-shadow:
|
|
0 12px 24px rgba(245, 158, 11, .35);
|
|
}
|
|
|
|
.popup-error .popup-icon {
|
|
background:
|
|
linear-gradient(135deg, #ef4444, #dc2626);
|
|
color: white;
|
|
box-shadow:
|
|
0 12px 24px rgba(239, 68, 68, .35);
|
|
}
|
|
|
|
.popup-success-type .popup-icon {
|
|
background:
|
|
linear-gradient(135deg, #22c55e, #16a34a);
|
|
color: white;
|
|
box-shadow:
|
|
0 12px 24px rgba(34, 197, 94, .35);
|
|
}
|
|
|
|
.popup-box h3 {
|
|
margin: 0 0 10px;
|
|
font-size: 24px;
|
|
font-weight: 700;
|
|
color: #111827;
|
|
}
|
|
|
|
.popup-box p {
|
|
margin: 0;
|
|
font-size: 14px;
|
|
line-height: 1.7;
|
|
color: #6b7280;
|
|
}
|
|
|
|
.popup-buttons {
|
|
display: flex;
|
|
justify-content: center;
|
|
gap: 12px;
|
|
margin-top: 24px;
|
|
}
|
|
|
|
.popup-buttons button {
|
|
min-width: 130px;
|
|
height: 46px;
|
|
border: none;
|
|
border-radius: 10px;
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
cursor: pointer;
|
|
transition: .22s ease;
|
|
}
|
|
|
|
.popup-warning .popup-confirm {
|
|
background:
|
|
linear-gradient(135deg, #fbbf24, #d97706);
|
|
color: white;
|
|
box-shadow:
|
|
0 12px 24px rgba(245, 158, 11, .28);
|
|
}
|
|
|
|
.popup-warning .popup-confirm:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow:
|
|
0 16px 30px rgba(245, 158, 11, .36);
|
|
}
|
|
|
|
.popup-error .popup-confirm {
|
|
background:
|
|
linear-gradient(135deg, #ef4444, #b91c1c);
|
|
color: white;
|
|
box-shadow:
|
|
0 12px 24px rgba(239, 68, 68, .25);
|
|
}
|
|
|
|
.popup-error .popup-confirm:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow:
|
|
0 16px 30px rgba(239, 68, 68, .32);
|
|
}
|
|
|
|
.popup-success-type .popup-success {
|
|
background:
|
|
linear-gradient(135deg, #22c55e, #15803d);
|
|
color: white;
|
|
box-shadow:
|
|
0 12px 24px rgba(34, 197, 94, .25);
|
|
}
|
|
|
|
.popup-success-type .popup-success:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow:
|
|
0 16px 30px rgba(34, 197, 94, .34);
|
|
}
|
|
|
|
.popup-cancel {
|
|
background:
|
|
linear-gradient(135deg, #cbd5e1, #b6c4d3);
|
|
color: #1e293b;
|
|
border: 1px solid #aebdcd;
|
|
box-shadow:
|
|
0 10px 18px rgba(100, 116, 139, .22),
|
|
inset 0 1px 1px rgba(255, 255, 255, .65);
|
|
}
|
|
|
|
.popup-cancel:hover {
|
|
background:
|
|
linear-gradient(135deg, #c6cfda, #afbbc9);
|
|
transform: translateY(-2px);
|
|
box-shadow:
|
|
0 14px 24px rgba(100, 116, 139, .28);
|
|
}
|
|
|
|
.popup-success {
|
|
background:
|
|
linear-gradient(135deg, #22c55e, #15803d);
|
|
color: white;
|
|
box-shadow:
|
|
0 12px 24px rgba(34, 197, 94, .25);
|
|
}
|
|
|
|
.popup-success:hover {
|
|
transform: translateY(-2px);
|
|
}
|
|
|
|
.popup-confirm:active,
|
|
.popup-cancel:active,
|
|
.popup-success:active {
|
|
transform: scale(.96);
|
|
}
|
|
|
|
.popup-cancel:active,
|
|
.popup-confirm:active {
|
|
transform: scale(.97);
|
|
}
|
|
|
|
.popup-box::-webkit-scrollbar,
|
|
.popup-box div::-webkit-scrollbar {
|
|
width: 8px;
|
|
height: 8px;
|
|
}
|
|
|
|
.popup-box::-webkit-scrollbar-thumb,
|
|
.popup-box div::-webkit-scrollbar-thumb {
|
|
background: #d8d8d8;
|
|
border-radius: 10px;
|
|
}
|
|
|
|
.popup-box::-webkit-scrollbar-thumb:hover {
|
|
background: #bcbcbc;
|
|
}
|
|
|
|
.result-popup {
|
|
width: 760px !important;
|
|
max-width: 95%;
|
|
padding: 26px 26px 22px;
|
|
text-align: left;
|
|
}
|
|
|
|
.result-popup-header {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
gap: 14px;
|
|
margin-bottom: 18px;
|
|
}
|
|
|
|
.result-popup-title {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 14px;
|
|
}
|
|
|
|
.result-popup-title-icon {
|
|
width: 54px;
|
|
height: 54px;
|
|
border-radius: 8px;
|
|
background:
|
|
linear-gradient(135deg, #ff3b3b 0%, #e11d1d 45%, #8b0000 100%);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
color: white;
|
|
font-size: 22px;
|
|
box-shadow:
|
|
0 14px 28px rgba(225, 29, 29, .38),
|
|
0 4px 10px rgba(139, 0, 0, .22),
|
|
inset 0 1px 1px rgba(255, 255, 255, .18);
|
|
}
|
|
|
|
.result-popup-title h3 {
|
|
margin: 0;
|
|
font-size: 18px;
|
|
font-weight: 700;
|
|
color: #111827;
|
|
}
|
|
|
|
.result-popup-title h3 span {
|
|
color: #b91c1c;
|
|
font-weight: 800;
|
|
}
|
|
|
|
.result-popup-title p {
|
|
margin: 4px 0 0;
|
|
font-size: 13px;
|
|
color: #6b7280;
|
|
}
|
|
|
|
.result-list {
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 12px;
|
|
max-height: 420px;
|
|
overflow-y: auto;
|
|
padding-right: 4px;
|
|
margin-top: 20px;
|
|
}
|
|
|
|
.result-item {
|
|
display: grid;
|
|
grid-template-columns: 110px 1fr auto;
|
|
align-items: center;
|
|
gap: 18px;
|
|
padding: 14px 16px;
|
|
border-radius: 10px;
|
|
background:
|
|
linear-gradient(135deg,
|
|
rgba(255, 255, 255, .96),
|
|
rgba(255, 255, 255, .96));
|
|
border: 1px solid rgba(239, 68, 68, 0.26);
|
|
transition: .2s ease;
|
|
}
|
|
|
|
.result-kode {
|
|
font-size: 12px;
|
|
font-weight: 700;
|
|
letter-spacing: .5px;
|
|
color: #b91c1c;
|
|
background: #ffe2e2;
|
|
padding: 10px 12px;
|
|
border-radius: 6px;
|
|
text-align: center;
|
|
}
|
|
|
|
.result-info {
|
|
min-width: 0;
|
|
}
|
|
|
|
.result-nama {
|
|
font-size: 14px;
|
|
font-weight: 600;
|
|
color: #111827;
|
|
white-space: nowrap;
|
|
overflow: hidden;
|
|
text-overflow: ellipsis;
|
|
}
|
|
|
|
.result-meta {
|
|
display: flex;
|
|
align-items: center;
|
|
flex-wrap: wrap;
|
|
gap: 8px;
|
|
margin-top: 5px;
|
|
font-size: 12px;
|
|
color: #6b7280;
|
|
}
|
|
|
|
.result-meta span {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 5px;
|
|
}
|
|
|
|
.result-prediksi {
|
|
text-align: right;
|
|
}
|
|
|
|
.result-prediksi-value {
|
|
font-size: 21px;
|
|
font-weight: 700;
|
|
line-height: 1;
|
|
color: #b91c1c;
|
|
}
|
|
|
|
.result-prediksi-label {
|
|
margin-top: 6px;
|
|
font-size: 12px;
|
|
color: #6b7280;
|
|
font-weight: 400;
|
|
letter-spacing: .2px;
|
|
}
|
|
|
|
.result-popup .popup-buttons {
|
|
margin-top: 22px;
|
|
justify-content: center;
|
|
align-items: center;
|
|
}
|
|
|
|
.result-popup .popup-cancel,
|
|
.result-popup .popup-confirm {
|
|
min-width: 150px;
|
|
}
|
|
|
|
.result-popup .btn-save {
|
|
background:
|
|
linear-gradient(135deg, #dc2626, #991b1b);
|
|
color: white;
|
|
box-shadow:
|
|
0 12px 24px rgba(220, 38, 38, .24);
|
|
}
|
|
|
|
.result-popup .btn-save:hover {
|
|
transform: translateY(-2px);
|
|
box-shadow:
|
|
0 16px 30px rgba(220, 38, 38, .32);
|
|
}
|
|
|
|
.btn-save.loading {
|
|
pointer-events: none;
|
|
opacity: .9;
|
|
position: relative;
|
|
color: transparent !important;
|
|
}
|
|
|
|
.btn-save.loading::after {
|
|
content: "";
|
|
position: absolute;
|
|
width: 18px;
|
|
height: 18px;
|
|
top: 50%;
|
|
left: 50%;
|
|
margin-top: -9px;
|
|
margin-left: -9px;
|
|
border-radius: 50%;
|
|
border: 2px solid rgba(255, 255, 255, .35);
|
|
border-top-color: white;
|
|
animation: spinBtn .7s linear infinite;
|
|
}
|
|
|
|
select {
|
|
padding: 10px;
|
|
border-radius: 6px;
|
|
border: 1px solid var(--border);
|
|
font-size: 14px;
|
|
height: 40px;
|
|
box-sizing: border-box;
|
|
width: 100%;
|
|
appearance: none;
|
|
background: white;
|
|
}
|
|
|
|
select:focus {
|
|
border-color: var(--primary);
|
|
box-shadow: 0 0 0 2px rgba(211, 47, 47, 0.1);
|
|
}
|
|
|
|
.period-wrapper {
|
|
position: relative;
|
|
}
|
|
|
|
.period-wrapper i {
|
|
position: absolute;
|
|
right: 14px;
|
|
top: 50%;
|
|
transform: translateY(-50%);
|
|
color: #9a0007;
|
|
font-size: 16px;
|
|
pointer-events: none;
|
|
opacity: .7;
|
|
transition: .2s;
|
|
}
|
|
|
|
.period-wrapper:hover i {
|
|
transform: translateY(-50%) scale(1.2);
|
|
opacity: 1;
|
|
}
|
|
|
|
input[type="month"] {
|
|
width: 100%;
|
|
height: 48px;
|
|
padding: 0 42px 0 14px;
|
|
border: 1px solid #e4b3b3;
|
|
border-radius: 6px;
|
|
font-size: 14px;
|
|
font-family: "Poppins", sans-serif;
|
|
font-weight: 500;
|
|
color: #7f1d1d;
|
|
background: #ffd6d6;
|
|
box-shadow:
|
|
inset 0 2px 4px rgba(0, 0, 0, 0.05),
|
|
0 4px 10px rgba(211, 47, 47, 0.08);
|
|
transition: all .25s ease;
|
|
cursor: pointer;
|
|
}
|
|
|
|
input[type="month"]:hover {
|
|
border-color: #ef9a9a;
|
|
background: #ffb7b7;
|
|
box-shadow:
|
|
inset 0 2px 4px rgba(0, 0, 0, 0.05),
|
|
0 6px 14px rgba(211, 47, 47, 0.12);
|
|
}
|
|
|
|
input[type="month"]:focus {
|
|
outline: none;
|
|
border-color: #d32f2f;
|
|
background: #fff;
|
|
box-shadow:
|
|
0 0 0 4px rgba(211, 47, 47, 0.12),
|
|
0 8px 18px rgba(211, 47, 47, 0.15);
|
|
}
|
|
|
|
input[type="month"]::-webkit-calendar-picker-indicator {
|
|
cursor: pointer;
|
|
opacity: 0;
|
|
position: absolute;
|
|
right: 0;
|
|
width: 100%;
|
|
}
|
|
|
|
input[type="month"]:focus {
|
|
animation: glowFocus .3s ease;
|
|
}
|
|
|
|
.loading-overlay {
|
|
position: fixed;
|
|
inset: 0;
|
|
background: rgba(15, 23, 42, 0.45);
|
|
backdrop-filter: blur(8px);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
z-index: 99999;
|
|
animation: fadeOverlay .2s ease;
|
|
}
|
|
|
|
.loading-box {
|
|
width: 340px;
|
|
max-width: 92%;
|
|
background: rgba(255, 255, 255, .96);
|
|
border-radius: 16px;
|
|
padding: 34px 28px;
|
|
text-align: center;
|
|
position: relative;
|
|
overflow: hidden;
|
|
box-shadow:
|
|
0 25px 50px rgba(15, 23, 42, .18),
|
|
0 10px 20px rgba(15, 23, 42, .08);
|
|
}
|
|
|
|
.loading-box::before {
|
|
content: "";
|
|
position: absolute;
|
|
inset: 0;
|
|
background:
|
|
linear-gradient(135deg,
|
|
rgba(255, 255, 255, .45),
|
|
transparent 40%);
|
|
pointer-events: none;
|
|
}
|
|
|
|
.loading-spinner {
|
|
width: 72px;
|
|
height: 72px;
|
|
margin: 0 auto 22px;
|
|
border-radius: 50%;
|
|
position: relative;
|
|
background:
|
|
conic-gradient(from 0deg,
|
|
#ffb3b3,
|
|
#ef4444,
|
|
#991b1b,
|
|
#ffb3b3);
|
|
animation: spinLoader 1s linear infinite;
|
|
padding: 5px;
|
|
}
|
|
|
|
.loading-spinner::before {
|
|
content: "";
|
|
position: absolute;
|
|
inset: 5px;
|
|
background: white;
|
|
border-radius: 50%;
|
|
}
|
|
|
|
.loading-spinner::after {
|
|
content: "";
|
|
position: absolute;
|
|
width: 18px;
|
|
height: 18px;
|
|
background: #ef4444;
|
|
border-radius: 50%;
|
|
top: 4px;
|
|
left: 50%;
|
|
transform: translateX(-50%);
|
|
box-shadow:
|
|
0 0 12px rgba(239, 68, 68, .55);
|
|
}
|
|
|
|
.loading-title {
|
|
font-size: 22px;
|
|
font-weight: 700;
|
|
color: #111827;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.loading-text {
|
|
font-size: 14px;
|
|
line-height: 1.7;
|
|
color: #6b7280;
|
|
}
|
|
|
|
.loading-dots::after {
|
|
content: "";
|
|
animation: dotsAnim 1.4s infinite;
|
|
}
|
|
|
|
.barang-table-wrapper {
|
|
margin-top: 15px;
|
|
border: 1px solid #e7bcbc;
|
|
border-radius: 8px;
|
|
overflow: hidden;
|
|
background: white;
|
|
box-shadow: 0 4px 12px rgba(0, 0, 0, .05);
|
|
}
|
|
|
|
.table-toolbar {
|
|
padding: 12px 14px;
|
|
background: linear-gradient(135deg,
|
|
#d32f2f 0%,
|
|
#b71c1c 45%,
|
|
#7f0000 100%);
|
|
border-bottom: 1px solid rgba(255, 255, 255, .08);
|
|
}
|
|
|
|
.check-all-label {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 10px;
|
|
margin: 0;
|
|
cursor: pointer;
|
|
color: #fff;
|
|
font-size: 13px;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.check-all-label input[type="checkbox"] {
|
|
width: 18px;
|
|
height: 18px;
|
|
margin: 0;
|
|
flex-shrink: 0;
|
|
vertical-align: middle;
|
|
}
|
|
|
|
.check-all-label span {
|
|
display: flex;
|
|
align-items: center;
|
|
line-height: 18px;
|
|
}
|
|
|
|
.table-container {
|
|
max-height: 400px;
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.barang-table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
}
|
|
|
|
.barang-table thead th {
|
|
position: sticky;
|
|
top: 0;
|
|
z-index: 5;
|
|
background: linear-gradient(135deg,
|
|
#d32f2f,
|
|
#9a0007);
|
|
color: white;
|
|
font-size: 13px;
|
|
font-weight: 600;
|
|
padding: 14px;
|
|
text-align: left;
|
|
}
|
|
|
|
.barang-table tbody td {
|
|
padding: 12px 14px;
|
|
border-bottom: 1px solid #f1f1f1;
|
|
font-size: 13px;
|
|
}
|
|
|
|
.barang-table tbody tr {
|
|
transition: .2s;
|
|
}
|
|
|
|
.barang-table tbody tr:hover {
|
|
background: #fff5f5;
|
|
}
|
|
|
|
.barang-table tbody tr.selected {
|
|
background: #ffe7e7;
|
|
}
|
|
|
|
.barang-table input[type="checkbox"],
|
|
#checkAllBarang {
|
|
width: 18px;
|
|
height: 18px;
|
|
cursor: pointer;
|
|
accent-color: #dc2626;
|
|
}
|
|
|
|
#checkAllBarang {
|
|
flex-shrink: 0;
|
|
}
|
|
|
|
.kode-cell {
|
|
font-weight: 700;
|
|
color: #b91c1c;
|
|
}
|
|
|
|
.jenis-badge {
|
|
display: inline-block;
|
|
padding: 5px 10px;
|
|
border-radius: 999px;
|
|
background: #ffe5e5;
|
|
color: #991b1b;
|
|
font-size: 11px;
|
|
font-weight: 600;
|
|
}
|
|
|
|
/* =========================
|
|
RESPONSIVE BREAKPOINTS
|
|
========================= */
|
|
@media (max-width:1024px) {
|
|
.header {
|
|
flex-direction: column;
|
|
align-items: stretch;
|
|
}
|
|
|
|
.header-nav {
|
|
width: 100%;
|
|
}
|
|
}
|
|
|
|
@media (max-width:768px) {
|
|
.header {
|
|
margin: -18px -18px 20px -18px;
|
|
padding: 16px 18px;
|
|
}
|
|
|
|
.header-nav {
|
|
flex-direction: column;
|
|
}
|
|
}
|
|
|
|
@media (min-width: 2560px) {
|
|
.container {
|
|
max-width: 1400px;
|
|
}
|
|
|
|
.card {
|
|
padding: 40px;
|
|
}
|
|
|
|
.card h2 {
|
|
font-size: 22px;
|
|
}
|
|
|
|
input,
|
|
select,
|
|
button {
|
|
font-size: 15px;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 1440px) {
|
|
.container {
|
|
max-width: 1100px;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 1200px) {
|
|
.container {
|
|
max-width: 95%;
|
|
}
|
|
|
|
.item-row {
|
|
grid-template-columns: 130px 1fr 170px 90px;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 1024px) {
|
|
body {
|
|
padding: 24px;
|
|
}
|
|
|
|
.card {
|
|
padding: 24px;
|
|
}
|
|
|
|
.form-row {
|
|
grid-template-columns: 1fr 240px !important;
|
|
}
|
|
|
|
.item-row {
|
|
grid-template-columns: 120px 1fr 150px 90px;
|
|
}
|
|
|
|
.result-popup {
|
|
width: 95% !important;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
body {
|
|
padding: 16px;
|
|
}
|
|
|
|
.card {
|
|
padding: 18px;
|
|
}
|
|
|
|
.card h2 {
|
|
margin: -18px -18px 20px -18px;
|
|
padding: 16px 18px;
|
|
font-size: 16px;
|
|
}
|
|
|
|
.card h2 i {
|
|
width: 34px;
|
|
height: 34px;
|
|
font-size: 15px;
|
|
}
|
|
|
|
.section-title {
|
|
font-size: 13px;
|
|
}
|
|
|
|
.item-row {
|
|
grid-template-columns: 1fr;
|
|
gap: 8px;
|
|
}
|
|
|
|
.btn-group {
|
|
justify-content: flex-end;
|
|
}
|
|
|
|
.form-row {
|
|
grid-template-columns: 1fr !important;
|
|
}
|
|
|
|
.btn-predict {
|
|
width: 100%;
|
|
}
|
|
|
|
.result-popup {
|
|
width: 100% !important;
|
|
padding: 18px;
|
|
}
|
|
|
|
.result-item {
|
|
grid-template-columns: 1fr;
|
|
gap: 10px;
|
|
}
|
|
|
|
.result-prediksi {
|
|
text-align: left;
|
|
}
|
|
|
|
.popup-buttons {
|
|
flex-direction: column;
|
|
}
|
|
|
|
.popup-buttons button {
|
|
width: 100%;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 576px) {
|
|
body {
|
|
padding: 12px;
|
|
}
|
|
|
|
.card {
|
|
padding: 14px;
|
|
border-radius: 12px;
|
|
}
|
|
|
|
.card h2 {
|
|
margin: -14px -14px 18px -14px;
|
|
padding: 14px;
|
|
font-size: 15px;
|
|
gap: 10px;
|
|
}
|
|
|
|
.card h2 i {
|
|
width: 32px;
|
|
height: 32px;
|
|
font-size: 14px;
|
|
}
|
|
|
|
input,
|
|
select {
|
|
height: 44px;
|
|
font-size: 13px;
|
|
}
|
|
|
|
.btn-add,
|
|
.btn-remove {
|
|
width: 42px;
|
|
height: 42px;
|
|
}
|
|
|
|
.btn-predict {
|
|
height: 44px;
|
|
font-size: 13px;
|
|
}
|
|
|
|
.popup-box {
|
|
padding: 16px;
|
|
}
|
|
|
|
.popup-box h3 {
|
|
font-size: 18px;
|
|
}
|
|
|
|
.popup-box p {
|
|
font-size: 13px;
|
|
}
|
|
|
|
.result-popup-title {
|
|
align-items: flex-start;
|
|
}
|
|
|
|
.result-popup-title-icon {
|
|
width: 44px;
|
|
height: 44px;
|
|
font-size: 18px;
|
|
}
|
|
|
|
.result-popup-title h3 {
|
|
font-size: 15px;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 480px) {
|
|
body {
|
|
padding: 10px;
|
|
}
|
|
|
|
.card {
|
|
padding: 12px;
|
|
}
|
|
|
|
.card h2 {
|
|
margin: -12px -12px 16px -12px;
|
|
font-size: 14px;
|
|
}
|
|
|
|
.card h2 i {
|
|
width: 30px;
|
|
height: 30px;
|
|
}
|
|
|
|
input,
|
|
select {
|
|
font-size: 12px;
|
|
}
|
|
|
|
.jenis-barang {
|
|
font-size: 10px;
|
|
}
|
|
|
|
.items-info {
|
|
font-size: 11px;
|
|
}
|
|
|
|
.result-kode {
|
|
font-size: 11px;
|
|
}
|
|
|
|
.result-nama {
|
|
font-size: 13px;
|
|
}
|
|
|
|
.result-prediksi-value {
|
|
font-size: 18px;
|
|
}
|
|
|
|
.loading-box {
|
|
width: 92%;
|
|
padding: 20px;
|
|
}
|
|
|
|
.loading-title {
|
|
font-size: 18px;
|
|
}
|
|
|
|
.loading-text {
|
|
font-size: 13px;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 375px) {
|
|
.card h2 {
|
|
font-size: 13px;
|
|
padding: 12px;
|
|
}
|
|
|
|
.card h2 i {
|
|
width: 28px;
|
|
height: 28px;
|
|
font-size: 12px;
|
|
}
|
|
|
|
input,
|
|
select {
|
|
height: 42px;
|
|
padding-left: 12px;
|
|
padding-right: 12px;
|
|
}
|
|
|
|
.btn-predict {
|
|
font-size: 12px;
|
|
}
|
|
|
|
.popup-box {
|
|
padding: 14px;
|
|
}
|
|
|
|
.popup-icon {
|
|
width: 64px;
|
|
height: 64px;
|
|
font-size: 24px;
|
|
}
|
|
|
|
.popup-box h3 {
|
|
font-size: 16px;
|
|
}
|
|
|
|
.popup-box p {
|
|
font-size: 12px;
|
|
}
|
|
}
|
|
|
|
@media (max-width: 320px) {
|
|
body {
|
|
padding: 8px;
|
|
}
|
|
|
|
.card {
|
|
padding: 10px;
|
|
}
|
|
|
|
.card h2 {
|
|
margin: -10px -10px 14px -10px;
|
|
font-size: 12px;
|
|
}
|
|
|
|
.card h2 i {
|
|
display: none;
|
|
}
|
|
|
|
.btn-group {
|
|
width: 100%;
|
|
}
|
|
|
|
.btn-add,
|
|
.btn-remove {
|
|
flex: 1;
|
|
width: auto;
|
|
}
|
|
|
|
.popup-box {
|
|
padding: 12px;
|
|
}
|
|
|
|
.popup-buttons button {
|
|
min-width: 100%;
|
|
}
|
|
}
|
|
|
|
@media (max-height: 700px) {
|
|
|
|
.popup-box,
|
|
.result-popup {
|
|
max-height: 90vh;
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.result-list {
|
|
max-height: 250px;
|
|
}
|
|
}
|
|
|
|
@media (max-height: 500px) and (orientation: landscape) {
|
|
|
|
.popup-box,
|
|
.result-popup {
|
|
max-height: 85vh;
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.result-list {
|
|
max-height: 180px;
|
|
}
|
|
|
|
.loading-box {
|
|
transform: scale(.9);
|
|
}
|
|
}
|
|
|
|
/* =========================
|
|
ANIMATIONS
|
|
========================= */
|
|
@keyframes spinLoader {
|
|
to {
|
|
transform: rotate(360deg);
|
|
}
|
|
}
|
|
|
|
@keyframes dotsAnim {
|
|
0% {
|
|
content: "";
|
|
}
|
|
|
|
33% {
|
|
content: ".";
|
|
}
|
|
|
|
66% {
|
|
content: "..";
|
|
}
|
|
|
|
100% {
|
|
content: "...";
|
|
}
|
|
}
|
|
|
|
@keyframes spinBtn {
|
|
to {
|
|
transform: rotate(360deg);
|
|
}
|
|
}
|
|
|
|
/* @keyframes shineMove {
|
|
0% {
|
|
left: -120px;
|
|
}
|
|
|
|
100% {
|
|
left: 120%;
|
|
}
|
|
} */
|
|
|
|
@keyframes glowFocus {
|
|
from {
|
|
box-shadow: 0 0 0 0 rgba(211, 47, 47, 0);
|
|
}
|
|
|
|
to {
|
|
box-shadow: 0 0 0 4px rgba(211, 47, 47, 0.12);
|
|
}
|
|
}
|
|
|
|
@keyframes popupShow {
|
|
from {
|
|
transform: scale(.9);
|
|
opacity: 0
|
|
}
|
|
|
|
to {
|
|
transform: scale(1);
|
|
opacity: 1
|
|
}
|
|
}
|
|
|
|
@keyframes popupIn {
|
|
from {
|
|
opacity: 0;
|
|
transform:
|
|
translateY(18px) scale(.92);
|
|
}
|
|
|
|
to {
|
|
opacity: 1;
|
|
transform:
|
|
translateY(0) scale(1);
|
|
}
|
|
}
|
|
|
|
@keyframes fadeOverlay {
|
|
from {
|
|
opacity: 0;
|
|
}
|
|
|
|
to {
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
@keyframes popupBounce {
|
|
0% {
|
|
transform: scale(.7);
|
|
opacity: 0;
|
|
}
|
|
|
|
60% {
|
|
transform: scale(1.08);
|
|
}
|
|
|
|
100% {
|
|
transform: scale(1);
|
|
opacity: 1;
|
|
}
|
|
}
|
|
|
|
@keyframes pulseRing {
|
|
0% {
|
|
transform: scale(.9);
|
|
opacity: .7;
|
|
}
|
|
|
|
100% {
|
|
transform: scale(1.25);
|
|
opacity: 0;
|
|
}
|
|
}
|
|
</style>
|
|
|
|
</head>
|
|
|
|
<body class="p-8">
|
|
<div class="w-full mx-auto">
|
|
<div class="card">
|
|
<div class="header">
|
|
<div class="header-left">
|
|
<i class="fa-solid fa-chart-column"
|
|
style="background: linear-gradient(135deg, #5b8def, #3c6fd7);
|
|
width: 50px; height: 50px; font-size: 22px;"></i>
|
|
<span>PREDIKSI KEBUTUHAN BARANG</span>
|
|
</div>
|
|
<div class="header-nav">
|
|
<a href="/prediksi-barang" class="header-btn active">
|
|
<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">
|
|
<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-title">PILIH BARANG</div>
|
|
<div class="search-section">
|
|
<div class="input-icon-wrapper">
|
|
<i class="fa-solid fa-magnifying-glass input-icon"></i>
|
|
<input type="text" id="searchBarang" class="input-soft"
|
|
placeholder="Cari kode atau nama barang...">
|
|
</div>
|
|
<div class="barang-table-wrapper">
|
|
<div class="table-toolbar">
|
|
<label class="check-all-label">
|
|
<input type="checkbox" id="checkAllBarang">
|
|
<span id="checkAllText">Pilih Semua Barang Pada Sistem</span>
|
|
</label>
|
|
</div>
|
|
<div class="table-container" id="tableContainer" style="display:none;">
|
|
<table class="barang-table">
|
|
<thead>
|
|
<tr>
|
|
<th width="60">Pilih</th>
|
|
<th width="130">Kode</th>
|
|
<th>Nama Barang</th>
|
|
<th width="180">Jenis</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody id="barangList">
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</div>
|
|
<div id="barangList" style="margin-top:15px;"></div>
|
|
</div>
|
|
<div class="items-info" id="itemsInfo">
|
|
Belum ada barang dipilih
|
|
</div>
|
|
<div class="section-divider"></div>
|
|
<div class="section-block">
|
|
<div class="section-title">PERIODE PREDIKSI</div>
|
|
<div class="form-row" style="grid-template-columns: 1fr 280px;">
|
|
<div>
|
|
<div class="period-wrapper">
|
|
<input type="month" id="periode">
|
|
<i class="fa-solid fa-calendar"></i>
|
|
</div>
|
|
</div>
|
|
<div>
|
|
<button class="btn-predict">PREDIKSI</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
const items = document.getElementById("items");
|
|
document.addEventListener("change", function(e) {
|
|
if (e.target.classList.contains("barang-checkbox")) {
|
|
if (e.target.checked) {
|
|
selectedBarang.add(e.target.value);
|
|
} else {
|
|
selectedBarang.delete(e.target.value);
|
|
}
|
|
updateItemsInfo();
|
|
}
|
|
if (e.target.id === "checkAllBarang") {
|
|
const keyword =
|
|
searchInput.value.trim();
|
|
if (keyword === "") {
|
|
if (e.target.checked) {
|
|
allBarang.forEach(item => {
|
|
selectedBarang.add(item.kode);
|
|
});
|
|
} else {
|
|
selectedBarang.clear();
|
|
}
|
|
} else {
|
|
document
|
|
.querySelectorAll(".barang-checkbox")
|
|
.forEach(cb => {
|
|
cb.checked = e.target.checked;
|
|
if (e.target.checked) {
|
|
selectedBarang.add(cb.value);
|
|
} else {
|
|
selectedBarang.delete(cb.value);
|
|
}
|
|
});
|
|
}
|
|
console.log(selectedBarang.size);
|
|
updateItemsInfo();
|
|
}
|
|
});
|
|
|
|
function updateItemsInfo() {
|
|
const info = document.getElementById("itemsInfo");
|
|
info.className = "items-info";
|
|
let checked = selectedBarang.size;
|
|
if (
|
|
document.getElementById("checkAllBarang").checked &&
|
|
searchInput.value.trim() === ""
|
|
) {
|
|
checked = allBarang.length;
|
|
}
|
|
if (checked === 0) {
|
|
info.classList.add("info-danger");
|
|
info.innerHTML = `
|
|
<i class="fa-solid fa-circle-exclamation"></i>
|
|
Belum ada barang dipilih
|
|
`;
|
|
return;
|
|
}
|
|
info.classList.add("info-success");
|
|
info.innerHTML = `
|
|
<i class="fa-solid fa-circle-check"></i>
|
|
${checked} barang dipilih
|
|
`;
|
|
}
|
|
|
|
function closeAllDropdowns() {
|
|
document.querySelectorAll(".autocomplete-box").forEach(box => {
|
|
box.innerHTML = "";
|
|
});
|
|
}
|
|
|
|
document.addEventListener("DOMContentLoaded", function() {
|
|
const periodeInput = document.getElementById("periode");
|
|
const now = new Date();
|
|
const minYear = now.getFullYear();
|
|
const minMonth = String(now.getMonth() + 1).padStart(2, "0");
|
|
const maxDate = new Date();
|
|
maxDate.setFullYear(maxDate.getFullYear() + 5);
|
|
const maxYear = maxDate.getFullYear();
|
|
const maxMonth = String(maxDate.getMonth() + 1).padStart(2, "0");
|
|
periodeInput.min = `${minYear}-${minMonth}`;
|
|
periodeInput.max = `${maxYear}-${maxMonth}`;
|
|
periodeInput.value = `${minYear}-${minMonth}`;
|
|
updateItemsInfo();
|
|
});
|
|
|
|
const searchInput = document.getElementById("searchBarang");
|
|
const barangList = document.getElementById("barangList");
|
|
const tableContainer = document.getElementById("tableContainer");
|
|
const checkAllText = document.getElementById("checkAllText");
|
|
const selectedCount = document.getElementById("selectedCount");
|
|
let allBarang = [];
|
|
let selectedBarang = new Set();
|
|
fetch("/all-items")
|
|
.then(res => res.json())
|
|
.then(data => {
|
|
allBarang = data;
|
|
});
|
|
async function loadBarang(keyword = "") {
|
|
if (allBarang.length === 0) {
|
|
const res = await fetch("/all-items");
|
|
allBarang = await res.json();
|
|
}
|
|
barangList.innerHTML = "";
|
|
const filtered = allBarang.filter(item =>
|
|
item.nama_barang.toLowerCase().includes(keyword.toLowerCase()) ||
|
|
item.kode.toLowerCase().includes(keyword.toLowerCase())
|
|
);
|
|
if (keyword.trim() === "") {
|
|
tableContainer.style.display = "none";
|
|
checkAllText.textContent =
|
|
"Pilih Semua Barang Pada Sistem";
|
|
updateItemsInfo();
|
|
return;
|
|
}
|
|
tableContainer.style.display = "block";
|
|
checkAllText.textContent =
|
|
"Pilih Semua Barang Pada Tabel";
|
|
filtered.forEach(item => {
|
|
barangList.innerHTML += `
|
|
<tr>
|
|
<td>
|
|
<input
|
|
type="checkbox"
|
|
class="barang-checkbox"
|
|
value="${item.kode}"
|
|
${selectedBarang.has(item.kode) ? "checked" : ""}
|
|
>
|
|
</td>
|
|
<td class="kode-cell">
|
|
${item.kode}
|
|
</td>
|
|
<td>
|
|
${item.nama_barang}
|
|
</td>
|
|
<td>
|
|
<span class="jenis-badge">
|
|
${item.jenis}
|
|
</span>
|
|
</td>
|
|
</tr>
|
|
`;
|
|
});
|
|
updateItemsInfo();
|
|
}
|
|
searchInput.addEventListener("input", function() {
|
|
loadBarang(this.value);
|
|
});
|
|
document.addEventListener("click", function(e) {
|
|
if (!e.target.classList.contains("kode-barang") &&
|
|
!e.target.classList.contains("nama-barang")) {
|
|
closeAllDropdowns();
|
|
}
|
|
});
|
|
|
|
function showDeletePopup(callback) {
|
|
const overlay = document.createElement("div");
|
|
overlay.className = "popup-overlay";
|
|
overlay.innerHTML = `
|
|
<div class="popup-box popup-warning">
|
|
<div class="popup-icon">
|
|
<i class="fa-solid fa-trash"></i>
|
|
</div>
|
|
<h3>Hapus Barang</h3>
|
|
<p>
|
|
Apakah yakin ingin menghapus barang ini?
|
|
</p>
|
|
<div class="popup-buttons">
|
|
<button class="popup-cancel">Batal</button>
|
|
<button class="popup-confirm">Hapus</button>
|
|
</div>
|
|
</div>
|
|
`;
|
|
document.body.appendChild(overlay);
|
|
overlay.querySelector(".popup-cancel").onclick = () => {
|
|
overlay.remove();
|
|
};
|
|
overlay.querySelector(".popup-confirm").onclick = () => {
|
|
callback();
|
|
overlay.remove();
|
|
};
|
|
}
|
|
|
|
function showConfirmReset(callback) {
|
|
const overlay = document.createElement("div");
|
|
overlay.className = "popup-overlay";
|
|
overlay.innerHTML = `
|
|
<div class="popup-box popup-warning">
|
|
<div class="popup-icon">
|
|
<i class="fa-solid fa-triangle-exclamation"></i>
|
|
</div>
|
|
<h3>Reset Semua</h3>
|
|
<p>
|
|
Yakin ingin menghapus semua barang?
|
|
</p>
|
|
<div class="popup-buttons">
|
|
<button class="popup-cancel">Batal</button>
|
|
<button class="popup-confirm">Hapus Semua</button>
|
|
</div>
|
|
</div>
|
|
`;
|
|
document.body.appendChild(overlay);
|
|
overlay.querySelector(".popup-cancel").onclick = () => {
|
|
overlay.remove();
|
|
};
|
|
overlay.querySelector(".popup-confirm").onclick = () => {
|
|
callback();
|
|
overlay.remove();
|
|
};
|
|
}
|
|
|
|
function showLoadingPopup() {
|
|
const overlay = document.createElement("div");
|
|
overlay.className = "loading-overlay";
|
|
overlay.id = "loadingOverlay";
|
|
overlay.innerHTML = `
|
|
<div class="loading-box">
|
|
<div class="loading-spinner"></div>
|
|
<div class="loading-title">
|
|
Memproses Prediksi
|
|
</div>
|
|
<div class="loading-text">
|
|
Sedang menghitung data
|
|
<span class="loading-dots"></span>
|
|
</div>
|
|
</div>
|
|
`;
|
|
document.body.appendChild(overlay);
|
|
}
|
|
|
|
function hideLoadingPopup() {
|
|
const overlay = document.getElementById("loadingOverlay");
|
|
if (overlay) {
|
|
overlay.remove();
|
|
}
|
|
}
|
|
|
|
document.querySelector(".btn-predict").addEventListener("click", function() {
|
|
const periode = document.getElementById("periode").value;
|
|
if (!periode) {
|
|
showErrorPopup("Periode waktu wajib diisi.");
|
|
return;
|
|
}
|
|
const parts = periode.split("-");
|
|
const tahun = parts[0];
|
|
const bulan = parseInt(parts[1]);
|
|
const kode_barang = [...selectedBarang];
|
|
if (kode_barang.length === 0) {
|
|
showErrorPopup(
|
|
"Pilih minimal satu barang."
|
|
);
|
|
return;
|
|
}
|
|
showLoadingPopup();
|
|
fetch("/prediksi-barang/run", {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
"X-CSRF-TOKEN": "{{ csrf_token() }}"
|
|
},
|
|
body: JSON.stringify({
|
|
kode_barang: kode_barang,
|
|
bulan: bulan,
|
|
tahun: tahun
|
|
})
|
|
})
|
|
.then(res => res.json())
|
|
.then(data => {
|
|
hideLoadingPopup();
|
|
if (data.error) {
|
|
showErrorPopup(data.error);
|
|
return;
|
|
}
|
|
showResultPopup(data);
|
|
resetFormPrediksi();
|
|
})
|
|
.catch(err => {
|
|
hideLoadingPopup();
|
|
console.error(err);
|
|
showErrorPopup("Terjadi error saat menghubungi server.");
|
|
});
|
|
});
|
|
|
|
function showErrorPopup(message) {
|
|
const overlay = document.createElement("div");
|
|
overlay.className = "popup-overlay";
|
|
overlay.innerHTML = `
|
|
<div class="popup-box popup-error">
|
|
<div class="popup-icon">
|
|
<i class="fa-solid fa-circle-exclamation"></i>
|
|
</div>
|
|
<h3>Peringatan</h3>
|
|
<p>${message}</p>
|
|
<div class="popup-buttons">
|
|
<button class="popup-confirm">OK</button>
|
|
</div>
|
|
</div>
|
|
`;
|
|
document.body.appendChild(overlay);
|
|
overlay.querySelector(".popup-confirm").onclick = () => {
|
|
overlay.remove();
|
|
};
|
|
}
|
|
|
|
function showSuccessPopup(message) {
|
|
const overlay = document.createElement("div");
|
|
overlay.className = "popup-overlay";
|
|
overlay.innerHTML = `
|
|
<div class="popup-box popup-success-type">
|
|
<div class="popup-icon">
|
|
<i class="fa-solid fa-circle-check"></i>
|
|
</div>
|
|
<h3>Berhasil</h3>
|
|
<p>${message}</p>
|
|
<div class="popup-buttons">
|
|
<button class="popup-success">OK</button>
|
|
</div>
|
|
</div>
|
|
`;
|
|
document.body.appendChild(overlay);
|
|
overlay.querySelector(".popup-success").onclick = () => {
|
|
overlay.remove();
|
|
};
|
|
}
|
|
|
|
function showResultPopup(data) {
|
|
const namaBulan = [
|
|
"", "Januari", "Februari", "Maret", "April", "Mei", "Juni",
|
|
"Juli", "Agustus", "September", "Oktober", "November", "Desember"
|
|
];
|
|
let resultHtml = "";
|
|
data.forEach(item => {
|
|
resultHtml += `
|
|
<div class="result-item">
|
|
<div class="result-kode">
|
|
${item.kode}
|
|
</div>
|
|
<div class="result-info">
|
|
<div class="result-nama">
|
|
${item.nama_barang}
|
|
</div>
|
|
</div>
|
|
<div class="result-prediksi">
|
|
<div class="result-prediksi-value">
|
|
${Math.round(item.prediction)}
|
|
</div>
|
|
<div class="result-prediksi-label">
|
|
${item.satuan}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
`;
|
|
});
|
|
const bulanTahun = `${namaBulan[data[0].bulan]} ${data[0].tahun}`;
|
|
const overlay = document.createElement("div");
|
|
overlay.className = "popup-overlay";
|
|
overlay.innerHTML = `
|
|
<div class="popup-box result-popup">
|
|
<div class="result-popup-header">
|
|
<div class="result-popup-title">
|
|
<div class="result-popup-title-icon">
|
|
<i class="fa-solid fa-chart-column"></i>
|
|
</div>
|
|
<div>
|
|
<h3>
|
|
Hasil Prediksi
|
|
<span>${bulanTahun}</span>
|
|
</h3>
|
|
<p>
|
|
Total ${data.length} barang berhasil diprediksi
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="result-list">
|
|
${resultHtml}
|
|
</div>
|
|
<div class="popup-buttons">
|
|
<button class="popup-cancel">
|
|
Tutup
|
|
</button>
|
|
<button class="popup-confirm btn-save">
|
|
Simpan Hasil
|
|
</button>
|
|
</div>
|
|
</div>
|
|
`;
|
|
document.body.appendChild(overlay);
|
|
overlay.querySelector(".popup-cancel").onclick = () => {
|
|
overlay.remove();
|
|
};
|
|
overlay.querySelector(".btn-save").onclick = function() {
|
|
const saveBtn = this;
|
|
if (saveBtn.classList.contains("loading")) return;
|
|
saveBtn.classList.add("loading");
|
|
saveBtn.disabled = true;
|
|
fetch("/prediksi-barang/save", {
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
"X-CSRF-TOKEN": "{{ csrf_token() }}"
|
|
},
|
|
body: JSON.stringify({
|
|
results: data
|
|
})
|
|
})
|
|
.then(res => res.json())
|
|
.then(res => {
|
|
overlay.remove();
|
|
if (res.success) {
|
|
showSuccessPopup("Hasil prediksi berhasil disimpan.");
|
|
} else {
|
|
showErrorPopup("Gagal menyimpan data.");
|
|
}
|
|
})
|
|
.catch(err => {
|
|
overlay.remove();
|
|
showErrorPopup("Terjadi error saat menyimpan.");
|
|
});
|
|
};
|
|
}
|
|
|
|
function resetFormPrediksi() {
|
|
const periodeInput =
|
|
document.getElementById("periode");
|
|
const now = new Date();
|
|
const year = now.getFullYear();
|
|
const month =
|
|
String(now.getMonth() + 1)
|
|
.padStart(2, "0");
|
|
periodeInput.value =
|
|
`${year}-${month}`;
|
|
document
|
|
.getElementById("checkAllBarang")
|
|
.checked = false;
|
|
loadBarang();
|
|
updateItemsInfo();
|
|
}
|
|
</script>
|
|
|
|
</body>
|
|
|
|
</html>
|