update projek tugas akhir

This commit is contained in:
alyaaghania 2026-06-17 23:13:54 +07:00
parent 7f316d73ed
commit 89b85dd377
11 changed files with 373 additions and 17 deletions

View File

@ -49,6 +49,7 @@ class PrediksiController extends Controller
'DISPEPSIA' => 'Dispepsia', 'DISPEPSIA' => 'Dispepsia',
]; ];
$hasil = $mapping[$hasil] ?? $hasil; $hasil = $mapping[$hasil] ?? $hasil;
$indikasi = array_map(fn($i) => $mapping[$i] ?? $i, $indikasi);
// Simpan ke database // Simpan ke database
if ($hasil != "Tidak ada hasil" && Auth::check()) { if ($hasil != "Tidak ada hasil" && Auth::check()) {

View File

@ -486,7 +486,7 @@
color: var(--green-deep); color: var(--green-deep);
letter-spacing: -0.3px; letter-spacing: -0.3px;
line-height: 1.2; line-height: 1.2;
margin-bottom: 18px; margin-bottom: 4px;
} }
.result-divider { .result-divider {
@ -626,3 +626,136 @@
box-shadow: 0 6px 20px rgba(45,90,61,0.35); box-shadow: 0 6px 20px rgba(45,90,61,0.35);
transform: translateY(-1px); transform: translateY(-1px);
} }
/* ─── Tombol Apa Itu (link style) ─── */
.btn-apa-itu {
display: inline-flex;
align-items: center;
gap: 4px;
font-size: 12px;
color: var(--green-mid);
font-weight: 500;
background: none;
border: none;
padding: 0;
cursor: pointer;
text-decoration: underline;
text-underline-offset: 3px;
font-family: 'Plus Jakarta Sans', sans-serif;
margin-bottom: 14px;
transition: color 0.2s;
}
.btn-apa-itu:hover { color: var(--green-deep); }
/* ─── Kotak Indikasi Lain ─── */
.indikasi-box {
background: rgba(255, 255, 255, 0.6);
border: 1px solid rgba(245, 217, 122, 0.5);
border-radius: 10px;
padding: 10px 12px;
margin-bottom: 14px;
}
.indikasi-label {
font-size: 10px;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.7px;
color: #9a6c00;
margin-bottom: 8px;
}
.indikasi-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 4px 0;
}
.indikasi-item + .indikasi-item {
border-top: 1px solid rgba(245, 217, 122, 0.3);
margin-top: 4px;
padding-top: 8px;
}
.indikasi-name {
font-size: 13px;
color: var(--text-dark);
font-weight: 600;
}
.indikasi-sub {
font-size: 10.5px;
color: var(--text-muted);
font-weight: 400;
margin-top: 2px;
}
/* ─── Tombol Pelajari (di indikasi) ─── */
.btn-pelajari.inline {
font-size: 11px;
color: var(--green-mid);
border: 1px solid var(--green-mid);
border-radius: 20px;
padding: 2px 9px;
background: transparent;
cursor: pointer;
font-weight: 500;
font-family: 'Plus Jakarta Sans', sans-serif;
transition: all 0.2s;
}
.btn-pelajari.inline:hover {
background: var(--green-mid);
color: white;
}
/* ─── Modal Pelajari Penyakit ─── */
.disease-modal-overlay {
display: none;
position: fixed;
inset: 0;
background: rgba(28, 43, 34, 0.5);
z-index: 9999;
align-items: center;
justify-content: center;
backdrop-filter: blur(3px);
}
.disease-modal-overlay.show {
display: flex;
}
.disease-modal-box {
background: var(--white);
border-radius: var(--radius-lg);
border: 1px solid var(--border);
box-shadow: var(--shadow-md);
padding: 36px 32px 32px;
max-width: 420px;
width: 90%;
position: relative;
text-align: center;
animation: alertPop 0.25s ease;
}
.disease-modal-close {
position: absolute;
top: 14px;
right: 18px;
background: none;
border: none;
font-size: 18px;
color: var(--text-muted);
cursor: pointer;
line-height: 1;
transition: color 0.2s;
}
.disease-modal-close:hover { color: var(--text-dark); }
.disease-modal-icon {
font-size: 40px;
margin-bottom: 12px;
}
.disease-modal-title {
font-size: 20px;
font-weight: 700;
color: var(--green-deep);
margin-bottom: 14px;
}
.disease-modal-desc {
font-size: 13px;
color: var(--text-muted);
line-height: 1.7;
text-align: left;
}

View File

@ -204,3 +204,16 @@
padding: 4px 10px; padding: 4px 10px;
border-radius: 50px; border-radius: 50px;
} }
/* ─── Saran ─── */
.riwayat-saran-text {
font-size: 12.5px;
color: #5a4a00;
line-height: 1.65;
background: #fffbee;
border: 1px solid rgba(245, 217, 122, 0.5);
border-left: 3px solid #e6a800;
border-radius: 8px;
padding: 10px 13px;
margin: 0;
}

View File

@ -469,11 +469,77 @@ body {
#timelineSvg { display: none; } #timelineSvg { display: none; }
} }
/*
PENYAKIT SECTION
*/
.penyakit-section {
background: var(--white);
padding: 80px 0;
}
.penyakit-card {
background: var(--white);
border: 1px solid rgba(125,170,110,0.2);
border-radius: var(--radius-lg);
padding: 32px 28px;
height: 100%;
display: flex;
flex-direction: column;
gap: 12px;
box-shadow: var(--shadow-card);
transition: all 0.3s ease;
}
.penyakit-card:hover {
transform: translateY(-5px);
box-shadow: var(--shadow-lg);
border-color: var(--green-soft);
}
/* .penyakit-card.featured {
border-color: var(--green-mid);
border-width: 2px;
} */
.penyakit-icon {
font-size: 2rem;
line-height: 1;
}
.penyakit-name {
font-weight: 800;
font-size: 1.15rem;
color: var(--green-deep);
margin: 0;
}
.penyakit-desc {
font-size: 13px;
color: var(--text-muted);
line-height: 1.7;
margin: 0;
flex: 1;
}
/* .penyakit-tags {
display: flex;
flex-wrap: wrap;
gap: 6px;
margin-top: 4px;
}
.penyakit-tags span {
font-size: 11px;
font-weight: 600;
padding: 4px 10px;
border-radius: 50px;
background: var(--green-pale);
color: var(--green-deep);
border: 1px solid rgba(125,170,110,0.3);
} */
/* /*
GEJALA SECTION GEJALA SECTION
*/ */
.gejala-section { .gejala-section {
background: var(--white); background: var(--green-pale);
padding: 80px 0; padding: 80px 0;
} }
@ -502,13 +568,13 @@ body {
.gejala-card { .gejala-card {
padding: 20px; padding: 20px;
border-radius: var(--radius-md); border-radius: var(--radius-md);
background: var(--green-mist); background: var(--white);
border: 1px solid transparent; border: 1px solid transparent;
transition: all 0.3s ease; transition: all 0.3s ease;
height: 100%; height: 100%;
} }
.gejala-card:hover { .gejala-card:hover {
background: var(--white); background: var(--green-pale);
border-color: rgba(125,170,110,0.3); border-color: rgba(125,170,110,0.3);
box-shadow: var(--shadow-card); box-shadow: var(--shadow-card);
transform: translateY(-3px); transform: translateY(-3px);

View File

@ -16,7 +16,7 @@
<body> <body>
<nav class="navbar navbar-expand-lg fixed-top"> <nav class="navbar navbar-expand-lg fixed-top">
<div class="container py-2"> <div class="container py-2">
<a class="navbar-brand" href="/"> <a class="navbar-brand" href="{{ url('/') }}">
<img src="{{ asset('img/sehati-logo.png') }}" alt="Logo SEHATI" class="navbar-logo"> <img src="{{ asset('img/sehati-logo.png') }}" alt="Logo SEHATI" class="navbar-logo">
SEHATI SEHATI
</a> </a>
@ -35,9 +35,10 @@
<!-- Menu --> <!-- Menu -->
<div class="collapse navbar-collapse" id="navbarMenu"> <div class="collapse navbar-collapse" id="navbarMenu">
<ul class="navbar-nav ms-auto align-items-lg-center gap-lg-1"> <ul class="navbar-nav ms-auto align-items-lg-center gap-lg-1">
<li class="nav-item"><a class="nav-link mx-1" href="/#home">Home</a></li> <li class="nav-item"><a class="nav-link mx-1" href="{{ url('/') }}#home">Home</a></li>
<li class="nav-item"><a class="nav-link mx-1" href="/#tentang">Tentang</a></li> <li class="nav-item"><a class="nav-link mx-1" href="{{ url('/') }}#tentang">Tentang</a></li>
<li class="nav-item"><a class="nav-link mx-1" href="/#gejala">Gejala</a></li> <li class="nav-item"><a class="nav-link mx-1" href="{{ url('/') }}#penyakit">Penyakit</a></li>
<li class="nav-item"><a class="nav-link mx-1" href="{{ url('/') }}#gejala">Gejala</a></li>
<li class="nav-item mt-2 mt-lg-0 ms-lg-2"> <li class="nav-item mt-2 mt-lg-0 ms-lg-2">
@auth @auth
<div class="dropdown"> <div class="dropdown">

View File

@ -40,6 +40,7 @@
placeholder="email@example.com" placeholder="email@example.com"
value="{{ old('email') }}" value="{{ old('email') }}"
autocomplete="email" autocomplete="email"
required
> >
</div> </div>
@error('email') @error('email')
@ -58,6 +59,7 @@
name="password" name="password"
class="login-input" class="login-input"
placeholder="Minimal 8 karakter" placeholder="Minimal 8 karakter"
required
> >
</div> </div>
@error('password') @error('password')
@ -76,6 +78,7 @@
name="password_confirmation" name="password_confirmation"
class="login-input" class="login-input"
placeholder="Ulangi password baru" placeholder="Ulangi password baru"
required
> >
</div> </div>
<small id="pesan-konfirmasi" style="font-size:12px; margin-top:-10px; display:block;"></small> <small id="pesan-konfirmasi" style="font-size:12px; margin-top:-10px; display:block;"></small>

View File

@ -41,6 +41,7 @@
placeholder="email@example.com" placeholder="email@example.com"
value="{{ old('email') }}" value="{{ old('email') }}"
autocomplete="email" autocomplete="email"
required
> >
</div> </div>
@error('email') @error('email')
@ -60,6 +61,7 @@
class="login-input" class="login-input"
placeholder="Minimal 8 karakter" placeholder="Minimal 8 karakter"
autocomplete="new-password" autocomplete="new-password"
required
> >
</div> </div>
@error('password') @error('password')
@ -79,6 +81,7 @@
class="login-input" class="login-input"
placeholder="Ulangi password" placeholder="Ulangi password"
autocomplete="new-password" autocomplete="new-password"
required
> >
</div> </div>
<small id="pesan-konfirmasi" style="font-size:12px; margin-top:-10px; display:block;"></small> <small id="pesan-konfirmasi" style="font-size:12px; margin-top:-10px; display:block;"></small>

View File

@ -29,6 +29,16 @@
<div class="alert alert-success">{{ session('success') }}</div> <div class="alert alert-success">{{ session('success') }}</div>
@endif @endif
@if ($errors->any())
<div class="alert alert-danger">
<ul style="margin:0; padding-left:15px;">
@foreach ($errors->all() as $error)
<li style="font-size:13px;">{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
{{-- Form --}} {{-- Form --}}
<form action="{{ route('login') }}" method="POST"> <form action="{{ route('login') }}" method="POST">
@csrf @csrf
@ -38,7 +48,7 @@
<label class="login-label" for="email">Email</label> <label class="login-label" for="email">Email</label>
<div class="login-input-wrap"> <div class="login-input-wrap">
<i class="fa-solid fa-envelope login-input-icon"></i> <i class="fa-solid fa-envelope login-input-icon"></i>
<input type="email" id="email" name="email" class="login-input" placeholder="email@example.com" autocomplete="email"> <input type="email" id="email" name="email" class="login-input" placeholder="email@example.com" autocomplete="email" required>
</div> </div>
</div> </div>
@ -47,7 +57,7 @@
<label class="login-label" for="password">Password</label> <label class="login-label" for="password">Password</label>
<div class="login-input-wrap"> <div class="login-input-wrap">
<i class="fa-solid fa-lock login-input-icon"></i> <i class="fa-solid fa-lock login-input-icon"></i>
<input type="password" id="password" name="password" class="login-input" placeholder="Masukkan password"> <input type="password" id="password" name="password" class="login-input" placeholder="Masukkan password" required>
</div> </div>
</div> </div>

View File

@ -74,8 +74,8 @@
<div class="field-group"> <div class="field-group">
<label for="umur">Umur</label> <label for="umur">Umur</label>
<input type="number" id="umur" name="umur" placeholder="cth. 28" min="1" max="120"> <input type="number" id="umur" name="umur" placeholder="cth. 28" min="15" max="120">
<span class="field-error" id="err-umur">Masukkan umur yang valid.</span> <span class="field-error" id="err-umur"></span>
</div> </div>
<div class="form-nav"> <div class="form-nav">
@ -93,6 +93,7 @@
<div class="field-group"> <div class="field-group">
<label>Pilih gejala yang sesuai</label> <label>Pilih gejala yang sesuai</label>
<p class="field-hint" style="margin-bottom: 10px;">Pilih <strong>minimal 2 gejala</strong> yang paling sesuai dengan kondisi Anda saat ini.</p>
<div class="symptom-grid"> <div class="symptom-grid">
@php @php
$gejala = [ $gejala = [
@ -148,6 +149,7 @@
<div class="field-group"> <div class="field-group">
<label>Kebiasaan Merokok</label> <label>Kebiasaan Merokok</label>
<small class="field-hint">Perokok aktif (≥10 batang/hari) atau perokok pasif</small>
<div class="radio-group"> <div class="radio-group">
<div class="radio-option"> <div class="radio-option">
<input type="radio" name="merokok" id="rokok_tidak" value="tidak"> <input type="radio" name="merokok" id="rokok_tidak" value="tidak">
@ -163,6 +165,7 @@
<div class="field-group"> <div class="field-group">
<label>Konsumsi Alkohol</label> <label>Konsumsi Alkohol</label>
<small class="field-hint">Sering konsumsi lebih dari 3-4 kali dalam seminggu</small>
<div class="radio-group"> <div class="radio-group">
<div class="radio-option"> <div class="radio-option">
<input type="radio" name="alkohol" id="alkohol_tidak" value="tidak"> <input type="radio" name="alkohol" id="alkohol_tidak" value="tidak">
@ -212,10 +215,23 @@
</div> </div>
<div class="disease-name">{{ $hasil }}</div> <div class="disease-name">{{ $hasil }}</div>
<button type="button" class="btn-apa-itu" onclick="openDiseaseModal('{{ $hasil }}')">
Apa itu {{ $hasil }}?
</button>
@if(!empty($indikasi)) @if(!empty($indikasi))
<p class="result-desc"> <div class="indikasi-box">
Terdapat gejala yang juga mengarah ke: <strong>{{ implode(', ', $indikasi) }}</strong>. Disarankan untuk pemeriksaan lebih lanjut. <div class="indikasi-label">Indikasi lain terdeteksi</div>
</p> @foreach($indikasi as $ind)
<div class="indikasi-item">
<div>
<span class="indikasi-name">{{ $ind }}</span>
<div class="indikasi-sub">Disarankan untuk pemeriksaan lebih lanjut.</div>
</div>
<button type="button" class="btn-pelajari inline" onclick="openDiseaseModal('{{ $ind }}')">Pelajari</button>
</div>
@endforeach
</div>
@endif @endif
<div class="result-divider"></div> <div class="result-divider"></div>
@ -290,6 +306,15 @@
</div> </div>
</div> </div>
<div class="disease-modal-overlay" id="diseaseModalOverlay" onclick="closeDiseaseModal()">
<div class="disease-modal-box" onclick="event.stopPropagation()">
<button class="disease-modal-close" onclick="closeDiseaseModal()"></button>
<div class="disease-modal-icon">🩺</div>
<h3 class="disease-modal-title" id="diseaseModalTitle"></h3>
<p class="disease-modal-desc" id="diseaseModalDesc"></p>
</div>
</div>
@push('scripts') @push('scripts')
<script> <script>
let currentSlide = {{ Auth::check() ? 2 : 1 }}; let currentSlide = {{ Auth::check() ? 2 : 1 }};
@ -306,7 +331,7 @@
clearErrors(); clearErrors();
if (!nama.value.trim()) { showError('nama', nama); valid = false; } if (!nama.value.trim()) { showError('nama', nama); valid = false; }
if (!jk) { showError('jk'); valid = false; } if (!jk) { showError('jk'); valid = false; }
if (!umur.value || umur.value < 1 || umur.value > 120) { if (!umur.value || umur.value < 15 || umur.value > 120) {
showError('umur', umur); valid = false; showError('umur', umur); valid = false;
} }
return valid; return valid;
@ -413,7 +438,24 @@
} }
document.querySelectorAll('input, select').forEach(el => { document.querySelectorAll('input, select').forEach(el => {
el.addEventListener('input', () => el.classList.remove('error')); el.addEventListener('input', () => el.classList.remove('error'));
});
document.getElementById('umur')?.addEventListener('input', function () {
const val = parseInt(this.value);
const errEl = document.getElementById('err-umur');
if (this.value && val < 15) {
this.classList.add('error');
errEl.textContent = 'Umur minimal 15 tahun.';
errEl.classList.add('show');
} else if (this.value && val > 120) {
this.classList.add('error');
errEl.textContent = 'Masukkan umur yang valid.';
errEl.classList.add('show');
} else {
this.classList.remove('error');
errEl.classList.remove('show');
}
}); });
@if(isset($hasil)) @if(isset($hasil))
@ -429,6 +471,24 @@
updateProgress(); updateProgress();
}); });
@endif @endif
const diseaseInfo = {
'Dispepsia': 'Dispepsia merupakan gangguan yang kompleks, mengacu pada kumpulan gejala seperti sensasi nyeri atau tak nyaman di perut bagian atas, terbakar, mual muntah, penuh dan kembung yang bersifat berulang.',
'Gerd': 'GERD merupakan suatu gangguan di mana isi lambung mengalami refluks secara berulang ke dalam esofagus, dan menyebabkan terjadinya gejala atau komplikasi yang mengganggu.',
'Gastritis': 'Gastritis adalah peradangan mukosa lambung yang dapat bersifat akut, kronik yang disebabkan rusaknya lapisan mukosa pelindung lambung.'
};
function openDiseaseModal(nama) {
const info = diseaseInfo[nama];
if (!info) return;
document.getElementById('diseaseModalTitle').textContent = nama;
document.getElementById('diseaseModalDesc').textContent = info;
document.getElementById('diseaseModalOverlay').classList.add('show');
}
function closeDiseaseModal() {
document.getElementById('diseaseModalOverlay').classList.remove('show');
}
</script> </script>
@endpush @endpush

View File

@ -94,6 +94,20 @@
</div> </div>
@endif @endif
{{-- Saran --}}
<div class="riwayat-section">
<p class="riwayat-section-label">💡 Saran</p>
<p class="riwayat-saran-text">
@if($item->hasil == 'Gastritis')
Makan secara teratur dan dalam porsi yang cukup, menghindari makanan pedas atau asam, tidak merokok dan tidak mengonsumsi alkohol, serta membatasi penggunaan obat anti inflamasi.
@elseif($item->hasil == 'Gerd')
Hindari makanan yang berpotensi memicu gejala refluks seperti kopi, minuman bersoda, makanan pedas dan asam, serta makanan dengan kandungan lemak tinggi. Selain itu, hindari merokok dan konsumsi alkohol.
@elseif($item->hasil == 'Dispepsia')
Makan secara teratur, mengontrol stres, serta menghindari makanan pemicu seperti makanan pedas, asam, dan tinggi lemak.
@endif
</p>
</div>
</div> </div>
@endforeach @endforeach
</div> </div>

View File

@ -253,6 +253,58 @@
</div> </div>
</section> </section>
{{-- ════════════════════════════════
PENYAKIT
════════════════════════════════ --}}
<section id="penyakit" class="penyakit-section">
<div class="container">
<div class="text-center reveal">
<h2 class="section-title">Kenali Penyakitnya</h2>
<div class="section-divider"></div>
</div>
<div class="row g-4">
<div class="col-md-4 reveal reveal-delay-1">
<div class="penyakit-card">
{{-- <div class="penyakit-icon">🌀</div> --}}
<h5 class="penyakit-name">DISPEPSIA</h5>
<p class="penyakit-desc">Kumpulan gejala berupa rasa nyeri atau tidak nyaman di perut bagian atas, mual, penuh dan kembung yang bersifat berulang.</p>
{{-- <div class="penyakit-tags">
<span>Perut Penuh</span>
<span>Nafsu Makan Turun</span>
<span>Kembung</span>
</div> --}}
</div>
</div>
<div class="col-md-4 reveal reveal-delay-2">
<div class="penyakit-card featured">
{{-- <div class="penyakit-icon"></div> --}}
<h5 class="penyakit-name">GERD</h5>
<p class="penyakit-desc">Gangguan di mana isi lambung mengalami refluks secara berulang ke dalam esofagus, menyebabkan gejala atau komplikasi yang mengganggu.</p>
{{-- <div class="penyakit-tags">
<span>Heartburn</span>
<span>Refluks Asam</span>
<span>Dada Terbakar</span>
</div> --}}
</div>
</div>
<div class="col-md-4 reveal reveal-delay-3">
<div class="penyakit-card">
{{-- <div class="penyakit-icon">🔥</div> --}}
<h5 class="penyakit-name">GASTRITIS</h5>
<p class="penyakit-desc">Peradangan pada lapisan mukosa lambung yang dapat bersifat akut maupun kronis, akibat rusaknya lapisan pelindung lambung.</p>
{{-- <div class="penyakit-tags">
<span>Nyeri Ulu Hati</span>
<span>Mual</span>
<span>Kembung</span>
</div> --}}
</div>
</div>
</div>
</div>
</section>
{{-- ════════════════════════════════ {{-- ════════════════════════════════
GEJALA GEJALA
════════════════════════════════ --}} ════════════════════════════════ --}}