second update

This commit is contained in:
BintangRiz.github,io 2026-05-28 21:11:29 +07:00
parent 1047448209
commit 4ec833fb31
13 changed files with 1352 additions and 299 deletions

View File

@ -14,49 +14,66 @@
class DiagnosaController extends Controller
{
// =========================
// FORM DIAGNOSA
// =========================
public function index()
{
$gejalas = Gejala::all();
return view('user.diagnosa', compact('gejalas'));
}
// PROSES CF KOMBINASI + CF USER
// =========================
// PROSES CERTAINTY FACTOR
// =========================
public function proses(Request $request)
{
// validasi minimal 1 gejala dipilih
if (empty(array_filter($request->gejala ?? []))) {
return back()->with('error', 'Pilih minimal 1 gejala!');
}
// ambil input (format: [gejala_id => nilai_cf_user])
// format:
// [gejala_id => cf_user]
$inputGejala = array_filter($request->gejala);
// ambil rule sesuai gejala yang dipilih
$rules = Rule::whereIn('gejala_id', array_keys($inputGejala))->get();
// ambil rule berdasarkan gejala dipilih
$rules = Rule::whereIn(
'gejala_id',
array_keys($inputGejala)
)->get();
$hasil = [];
foreach ($rules as $rule) {
// CF dari pakar
// =========================
// CF PAKAR
// =========================
$cf_pakar = $rule->mb - $rule->md;
// CF dari user
// =========================
// CF USER
// =========================
$cf_user = $inputGejala[$rule->gejala_id];
// CF akhir
// =========================
// CF AKHIR
// =========================
$cf = $cf_pakar * $cf_user;
// =========================
// KOMBINASI CF
// =========================
if (!isset($hasil[$rule->penyakit_id])) {
$hasil[$rule->penyakit_id] = $cf;
} else {
// CF KOMBINASI
$hasil[$rule->penyakit_id] =
$hasil[$rule->penyakit_id] +
($cf * (1 - $hasil[$rule->penyakit_id]));
@ -65,121 +82,248 @@ public function proses(Request $request)
// jika tidak ada hasil
if (empty($hasil)) {
return back()->with('error', 'Tidak ada rule yang cocok!');
return back()->with(
'error',
'Tidak ada rule yang cocok!'
);
}
// ambil hasil tertinggi
// =========================
// HASIL TERTINGGI
// =========================
arsort($hasil);
$penyakit_id = array_key_first($hasil);
$cf_hasil = $hasil[$penyakit_id];
$pasien = Pasien::where('user_id', Auth::id())->latest()->first();
// =========================
// AMBIL DATA PASIEN
// =========================
$pasien = Pasien::where(
'user_id',
Auth::id()
)->latest()->first();
// simpan ke DB
// =========================
// SIMPAN DIAGNOSA
// =========================
$diagnosa = Diagnosa::create([
'pasien_id' => $pasien->id,
'penyakit_id' => $penyakit_id,
'cf_hasil' => $cf_hasil,
'gejala_dipilih' => json_encode($inputGejala)
'pasien_id' => $pasien->id,
'penyakit_id' => $penyakit_id,
'cf_hasil' => $cf_hasil,
// simpan gejala + nilai keyakinan user
// contoh:
// {"1":"0.8","2":"1"}
'gejala_dipilih' => json_encode($inputGejala)
]);
return redirect()->route('diagnosa.hasil', $diagnosa->id);
return redirect()->route(
'diagnosa.hasil',
$diagnosa->id
);
}
// =========================
// HASIL DIAGNOSA
public function hasil($id)
{
$diagnosa = Diagnosa::with(['pasien', 'penyakit'])->findOrFail($id);
// =========================
public function hasil($id)
{
$diagnosa = Diagnosa::with([
'pasien',
'penyakit'
])->findOrFail($id);
// ROLE
if (auth()->user()->role == 'admin') {
return view('admin.hasil', compact('diagnosa'));
// jika admin
if (auth()->user()->role == 'admin') {
return view(
'admin.hasil',
compact('diagnosa')
);
}
// jika user
return view(
'user.hasil',
compact('diagnosa')
);
}
return view('user.hasil', compact('diagnosa'));
}
// =========================
// CETAK PDF
// =========================
public function pdf($id)
{
$diagnosa = Diagnosa::with(['pasien','penyakit'])->findOrFail($id);
public function pdf($id)
{
$diagnosa = Diagnosa::with([
'pasien',
'penyakit'
])->findOrFail($id);
// ✅ ambil data gejala (id => cf_user)
$gejalaData = json_decode($diagnosa->gejala_dipilih, true) ?? [];
// =========================
// AMBIL DATA GEJALA DIPILIH
// =========================
$gejalaData = json_decode(
$diagnosa->gejala_dipilih,
true
) ?? [];
// ✅ ambil hanya ID
$gejalaIds = array_keys($gejalaData);
// ambil ID gejala
$gejalaIds = array_keys($gejalaData);
// ✅ ambil data gejala dari DB
$gejalas = Gejala::whereIn('id', $gejalaIds)->get();
// ambil data gejala dari database
$gejalas = Gejala::whereIn(
'id',
$gejalaIds
)->get();
$pdf = Pdf::loadView('pdf.diagnosa', compact('diagnosa','gejalas'));
// =========================
// TAMBAHKAN CF USER
// =========================
foreach ($gejalas as $g) {
return $pdf->download('hasil_diagnosa_'.$diagnosa->id.'.pdf');
}
// ambil nilai user
$g->cf_user = $gejalaData[$g->id] ?? 0;
// ubah ke teks
if ($g->cf_user == 1) {
$g->keterangan_cf = 'Sangat Yakin';
} elseif ($g->cf_user == 0.8) {
$g->keterangan_cf = 'Yakin';
} elseif ($g->cf_user == 0.6) {
$g->keterangan_cf = 'Cukup Yakin';
} elseif ($g->cf_user == 0.4) {
$g->keterangan_cf = 'Sedikit Yakin';
} elseif ($g->cf_user == 0.2) {
$g->keterangan_cf = 'Kurang Yakin';
} else {
$g->keterangan_cf = 'Tidak Yakin';
}
}
// =========================
// GENERATE PDF
// =========================
$pdf = Pdf::loadView(
'pdf.diagnosa',
compact(
'diagnosa',
'gejalas'
)
);
return $pdf->download(
'hasil_diagnosa_' .
$diagnosa->id .
'.pdf'
);
}
// =========================
// RIWAYAT USER
// =========================
public function riwayat()
{
$pasien = Pasien::where('user_id', Auth::id())->first();
public function riwayat()
{
$pasien = Pasien::where(
'user_id',
Auth::id()
)->first();
// jumlah data per halaman
$perPage = request()->perPage ?? 5;
// jumlah data per halaman
$perPage = request()->perPage ?? 5;
// jika belum isi data diri
if (!$pasien) {
// jika belum isi data diri
if (!$pasien) {
$data = Diagnosa::where('id', 0)
->paginate($perPage);
$data = Diagnosa::where('id', 0)
->paginate($perPage);
return view('user.riwayat', compact('data', 'perPage'));
}
return view(
'user.riwayat',
compact('data', 'perPage')
);
}
$data = Diagnosa::with(['penyakit', 'pasien'])
->where('pasien_id', $pasien->id)
->latest()
->paginate($perPage)
->withQueryString();
return view('user.riwayat', compact('data', 'perPage'));
}
public function dashboard(Request $request)
{
$pasien = \App\Models\Pasien::where('user_id', auth()->id())->first();
$perPage = $request->perPage ?? 5; // default 5
$totalDiagnosa = 0;
$lastDiagnosa = null;
$riwayat = collect();
if ($pasien) {
$riwayat = \App\Models\Diagnosa::with('penyakit')
$data = Diagnosa::with([
'penyakit',
'pasien'
])
->where('pasien_id', $pasien->id)
->latest()
->paginate($perPage)
->withQueryString();
$totalDiagnosa = \App\Models\Diagnosa::where('pasien_id', $pasien->id)->count();
$lastDiagnosa = \App\Models\Diagnosa::where('pasien_id', $pasien->id)->latest()->first();
return view(
'user.riwayat',
compact('data', 'perPage')
);
}
return view('user.dashboard', compact(
'totalDiagnosa',
'lastDiagnosa',
'riwayat',
'perPage'
));
}
}
// =========================
// DASHBOARD USER
// =========================
public function dashboard(Request $request)
{
$pasien = Pasien::where(
'user_id',
auth()->id()
)->first();
$perPage = $request->perPage ?? 5;
$totalDiagnosa = 0;
$lastDiagnosa = null;
$riwayat = collect();
if ($pasien) {
$riwayat = Diagnosa::with('penyakit')
->where('pasien_id', $pasien->id)
->latest()
->paginate($perPage)
->withQueryString();
$totalDiagnosa = Diagnosa::where(
'pasien_id',
$pasien->id
)->count();
$lastDiagnosa = Diagnosa::where(
'pasien_id',
$pasien->id
)->latest()->first();
}
return view(
'user.dashboard',
compact(
'totalDiagnosa',
'lastDiagnosa',
'riwayat',
'perPage'
)
);
}
}

View File

@ -93,4 +93,13 @@ public function destroy($id)
return redirect()->route('penyakit.index')
->with('success', 'Data berhasil dihapus');
}
}
public function show($id)
{
$penyakit = Penyakit::findOrFail($id);
return view('admin.penyakit.show', compact('penyakit'));
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

View File

@ -74,7 +74,7 @@ class="form-select form-select-sm">
<th width="70">No</th>
<th width="120">Kode</th>
<th>Nama Penyakit</th>
<th width="180">Aksi</th>
<th width="250">Aksi</th>
</tr>
</thead>
@ -88,30 +88,46 @@ class="form-select form-select-sm">
{{ $loop->iteration + ($penyakits->currentPage() - 1) * $penyakits->perPage() }}
</td>
<td>{{ $p->kode }}</td>
<td>
{{ $p->kode }}
</td>
<td>{{ $p->nama }}</td>
<td>
{{ $p->nama }}
</td>
<td>
<a href="{{ route('penyakit.edit', $p->id) }}"
class="btn btn-warning btn-sm">
Edit
</a>
<div class="d-flex gap-2 flex-wrap">
<form action="{{ route('penyakit.destroy', $p->id) }}"
method="POST"
style="display:inline;">
<!-- DETAIL -->
<a href="{{ route('penyakit.show', $p->id) }}"
class="btn btn-info btn-sm text-white">
Detail
</a>
@csrf
@method('DELETE')
<!-- EDIT -->
<a href="{{ route('penyakit.edit', $p->id) }}"
class="btn btn-warning btn-sm">
Edit
</a>
<button class="btn btn-danger btn-sm"
onclick="return confirm('Yakin ingin menghapus data ini?')">
Hapus
</button>
<!-- DELETE -->
<form action="{{ route('penyakit.destroy', $p->id) }}"
method="POST"
style="display:inline;">
</form>
@csrf
@method('DELETE')
<button class="btn btn-danger btn-sm"
onclick="return confirm('Yakin ingin menghapus data ini?')">
Hapus
</button>
</form>
</div>
</td>
@ -120,7 +136,7 @@ class="btn btn-warning btn-sm">
@empty
<tr>
<td colspan="4" class="text-center text-muted">
<td colspan="4" class="text-center text-muted py-4">
@if(request('search'))
Data penyakit tidak ditemukan

View File

@ -0,0 +1,69 @@
@extends('layouts.admin')
@section('title', 'Detail Penyakit')
@section('content')
<div class="card shadow-sm">
<div class="card-body">
<!-- HEADER -->
<div class="d-flex justify-content-between align-items-center mb-4">
<div>
<h4 class="fw-bold mb-1">
Detail Penyakit
</h4>
<small class="text-muted">
Informasi lengkap data penyakit
</small>
</div>
<a href="{{ route('penyakit.index') }}"
class="btn btn-secondary btn-sm">
Kembali
</a>
</div>
<!-- DETAIL -->
<table class="table table-bordered">
<tr>
<th width="200">Kode Penyakit</th>
<td>{{ $penyakit->kode }}</td>
</tr>
<tr>
<th>Nama Penyakit</th>
<td>{{ $penyakit->nama }}</td>
</tr>
<tr>
<th>Deskripsi</th>
<td>
{!! $penyakit->deskripsi ?? '-' !!}
</td>
</tr>
<tr>
<th>Solusi</th>
<td>
{!! $penyakit->solusi ?? '-' !!}
</td>
</tr>
<tr>
<th>Dibuat Pada</th>
<td>
{{ $penyakit->created_at->format('d-m-Y H:i') }}
</td>
</tr>
</table>
</div>
</div>
@endsection

View File

@ -13,42 +13,100 @@
<style>
body{
margin:0;
height:100vh;
background:#eaf2ff;
min-height:100vh;
background:linear-gradient(135deg,#2563eb,#0ea5e9);
display:flex;
align-items:center;
justify-content:center;
font-family: 'Segoe UI', sans-serif;
font-family:'Segoe UI',sans-serif;
padding:20px;
}
.login-wrapper{
width:1000px;
max-width:95%;
max-width:100%;
background:#fff;
border-radius:20px;
box-shadow:0 20px 40px rgba(0,0,0,0.08);
display:flex;
border-radius:24px;
overflow:hidden;
box-shadow:0 25px 50px rgba(0,0,0,0.12);
display:flex;
}
/* LEFT */
.login-left{
width:55%;
background:#f3f7ff;
width:50%;
background:linear-gradient(135deg,#2563eb,#0ea5e9);
color:white;
padding:60px;
display:flex;
flex-direction:column;
justify-content:center;
position:relative;
overflow:hidden;
}
.login-left::before{
content:'';
position:absolute;
width:300px;
height:300px;
background:rgba(255,255,255,0.08);
border-radius:50%;
top:-80px;
right:-80px;
}
.login-left::after{
content:'';
position:absolute;
width:220px;
height:220px;
background:rgba(255,255,255,0.05);
border-radius:50%;
bottom:-70px;
left:-70px;
}
.login-content{
position:relative;
z-index:2;
}
.login-left h1{
font-size:42px;
font-weight:700;
margin-bottom:20px;
line-height:1.2;
}
.login-left p{
font-size:16px;
line-height:1.8;
opacity:0.95;
margin-bottom:30px;
}
.login-feature{
display:flex;
align-items:center;
margin-bottom:18px;
font-size:15px;
}
.login-feature i{
width:40px;
height:40px;
border-radius:10px;
background:rgba(255,255,255,0.15);
display:flex;
align-items:center;
justify-content:center;
padding:40px;
}
.login-left img{
width:100%;
max-width:400px;
margin-right:15px;
}
/* RIGHT */
.login-right{
width:45%;
width:50%;
padding:60px 50px;
display:flex;
flex-direction:column;
@ -56,59 +114,102 @@
}
.login-right h2{
font-weight:700;
margin-bottom:30px;
color:#2563eb;
text-align:center;
font-weight:700;
color:#1e293b;
margin-bottom:10px;
}
.login-right .subtitle{
text-align:center;
color:#64748b;
margin-bottom:30px;
font-size:14px;
}
.form-label{
font-weight:600;
color:#334155;
margin-bottom:8px;
}
.form-control{
border-radius:10px;
padding:10px 12px;
border-radius:12px;
border:1px solid #dbeafe;
padding:12px 14px;
transition:0.3s;
}
.form-control:focus{
border-color:#2563eb;
box-shadow:none;
box-shadow:0 0 0 4px rgba(37,99,235,0.1);
}
.btn-login{
background:#2563eb;
background:linear-gradient(135deg,#2563eb,#0ea5e9);
border:none;
border-radius:10px;
padding:10px;
border-radius:12px;
padding:12px;
font-weight:600;
transition:0.3s;
}
.btn-login:hover{
background:#1d4ed8;
transform:translateY(-2px);
opacity:0.95;
}
.auth-links{
text-align:center;
margin-top:20px;
margin-top:25px;
font-size:14px;
}
.auth-links a{
text-decoration:none;
color:#2563eb;
text-decoration:none;
font-weight:600;
}
.auth-links a:hover{
text-decoration:underline;
}
.alert-danger{
border-radius:12px;
font-size:14px;
}
@media(max-width:768px){
body{
padding:15px;
}
.login-wrapper{
flex-direction:column;
}
.login-left,
.login-right{
width:100%;
}
.login-right{
.login-left{
padding:40px 30px;
text-align:center;
}
.login-left h1{
font-size:32px;
}
.login-feature{
justify-content:center;
}
.login-right{
padding:40px 25px;
}
}
</style>
@ -117,68 +218,111 @@
<div class="login-wrapper">
<!-- LEFT IMAGE -->
<!-- LEFT -->
<div class="login-left">
<!-- GANTI LINK GAMBAR SESUAI KEINGINAN -->
<img src="{{ asset('uploads/logo.png') }}" alt="Login Illustration">
<div class="login-content">
<h1>Selamat Datang</h1>
<p>
Sistem Pakar Diagnosa Penyakit Hipertensi berbasis metode
Certainty Factor untuk membantu proses analisa gejala
dan hasil diagnosa secara mandiri.
</p>
</div>
</div>
<!-- RIGHT FORM -->
<!-- RIGHT -->
<div class="login-right">
<h2>LOGIN</h2>
<div class="subtitle">
Silakan login untuk melanjutkan ke sistem
</div>
{{-- ERROR LOGIN --}}
@if ($errors->has('email'))
<div class="alert alert-danger">
Email atau password anda salah.
</div>
@endif
<form method="POST" action="{{ route('login') }}">
@csrf
<div class="mb-3">
<label class="form-label">
Email
</label>
<input type="email"
name="email"
class="form-control @error('email') is-invalid @enderror"
placeholder="Email"
placeholder="Masukkan email"
required
autofocus>
@error('email')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="mb-3">
<label class="form-label">
Password
</label>
<input type="password"
name="password"
class="form-control @error('password') is-invalid @enderror"
placeholder="Password"
placeholder="Masukkan password"
required>
@error('password')
<div class="invalid-feedback">{{ $message }}</div>
@enderror
</div>
<div class="mb-3 form-check">
<input type="checkbox" name="remember" class="form-check-input">
<label class="form-check-label">Remember Me</label>
<input type="checkbox"
name="remember"
class="form-check-input"
id="remember">
<label class="form-check-label" for="remember">
Ingatkan aku
</label>
</div>
<div class="d-grid">
<button type="submit" class="btn btn-login text-white">
<button type="submit"
class="btn btn-login text-white">
Login
</button>
</div>
</form>
<div class="auth-links">
@if (Route::has('password.request'))
<a href="{{ route('password.request') }}">
Forgot Password?
Lupa Password?
</a>
@endif
<br>
<a href="{{ route('register') }}">
Don't have an account? Sign Up
Belum punya akun? Daftar
</a>
</div>
</div>

View File

@ -6,184 +6,409 @@
<style>
body{
margin:0;
height:100vh;
background:#eaf2ff;
min-height:100vh;
background:linear-gradient(135deg,#2563eb,#0ea5e9);
display:flex;
align-items:center;
justify-content:center;
font-family: 'Segoe UI', sans-serif;
font-family:'Segoe UI',sans-serif;
padding:20px;
}
.register-wrapper{
width:1000px;
max-width:95%;
max-width:100%;
background:#fff;
border-radius:20px;
box-shadow:0 20px 40px rgba(0,0,0,0.08);
display:flex;
border-radius:24px;
overflow:hidden;
box-shadow:0 25px 50px rgba(0,0,0,0.12);
display:flex;
}
/* LEFT */
.register-left{
width:55%;
background:#f3f7ff;
width:50%;
background:linear-gradient(135deg,#2563eb,#0ea5e9);
color:white;
padding:60px;
display:flex;
flex-direction:column;
justify-content:center;
position:relative;
overflow:hidden;
}
.register-left::before{
content:'';
position:absolute;
width:300px;
height:300px;
background:rgba(255,255,255,0.08);
border-radius:50%;
top:-80px;
right:-80px;
}
.register-left::after{
content:'';
position:absolute;
width:220px;
height:220px;
background:rgba(255,255,255,0.05);
border-radius:50%;
bottom:-70px;
left:-70px;
}
.register-content{
position:relative;
z-index:2;
}
.register-left h1{
font-size:42px;
font-weight:700;
margin-bottom:20px;
line-height:1.2;
}
.register-left p{
font-size:16px;
line-height:1.8;
opacity:0.95;
margin-bottom:30px;
}
.register-feature{
display:flex;
align-items:center;
margin-bottom:18px;
font-size:15px;
}
.register-feature i{
width:40px;
height:40px;
border-radius:10px;
background:rgba(255,255,255,0.15);
display:flex;
align-items:center;
justify-content:center;
padding:40px;
}
.register-left img{
width:100%;
max-width:400px;
margin-right:15px;
}
/* RIGHT */
.register-right{
width:45%;
padding:50px;
width:50%;
padding:60px 50px;
display:flex;
flex-direction:column;
justify-content:center;
}
.register-right h2{
font-weight:700;
margin-bottom:30px;
color:#2563eb;
text-align:center;
font-weight:700;
color:#1e293b;
margin-bottom:10px;
}
.register-right .subtitle{
text-align:center;
color:#64748b;
margin-bottom:30px;
font-size:14px;
}
.form-label{
font-weight:600;
color:#334155;
margin-bottom:8px;
}
.form-control{
border-radius:10px;
padding:10px 12px;
border-radius:12px;
border:1px solid #dbeafe;
padding:12px 14px;
transition:0.3s;
}
.form-control:focus{
border-color:#2563eb;
box-shadow:none;
box-shadow:0 0 0 4px rgba(37,99,235,0.1);
}
.btn-register{
background:#2563eb;
background:linear-gradient(135deg,#2563eb,#0ea5e9);
border:none;
border-radius:10px;
padding:10px;
border-radius:12px;
padding:12px;
font-weight:600;
transition:0.3s;
}
.btn-register:hover{
background:#1d4ed8;
transform:translateY(-2px);
opacity:0.95;
}
.auth-links{
text-align:center;
margin-top:20px;
margin-top:25px;
font-size:14px;
}
.auth-links a{
text-decoration:none;
color:#2563eb;
text-decoration:none;
font-weight:600;
}
.auth-links a:hover{
text-decoration:underline;
}
.invalid-feedback{
display:block;
}
/* =========================
RESPONSIVE MOBILE
========================= */
@media(max-width:768px){
body{
height:auto;
padding:15px;
display:block;
}
.register-wrapper{
flex-direction:column;
width:100%;
border-radius:18px;
margin:20px auto;
}
.register-left,
/* LEFT */
.register-left{
width:100%;
padding:35px 25px;
text-align:center;
}
.register-left h1{
font-size:28px;
margin-bottom:15px;
}
.register-left p{
font-size:14px;
line-height:1.7;
}
.register-feature{
justify-content:center;
text-align:left;
font-size:14px;
}
.register-feature i{
width:35px;
height:35px;
font-size:14px;
margin-right:10px;
}
/* RIGHT */
.register-right{
width:100%;
padding:35px 20px;
}
.register-right{
padding:40px 30px;
.register-right h2{
font-size:28px;
}
.subtitle{
font-size:13px;
margin-bottom:25px;
}
.form-control{
padding:11px 12px;
font-size:14px;
}
.btn-register{
padding:11px;
font-size:15px;
}
.auth-links{
font-size:13px;
}
}
/* EXTRA SMALL DEVICE */
@media(max-width:480px){
.register-left{
padding:30px 20px;
}
.register-right{
padding:30px 18px;
}
.register-left h1{
font-size:24px;
}
.register-right h2{
font-size:24px;
}
.register-feature{
align-items:flex-start;
}
}
</style>
<div class="register-wrapper">
<!-- LEFT IMAGE -->
<!-- LEFT -->
<div class="register-left">
<!-- GANTI GAMBAR SESUAI KEINGINAN -->
<img src="https://illustrations.popsy.co/blue/sign-up.svg" alt="Register Illustration">
<div class="register-content">
<h1>Buat Akun Baru</h1>
<p>
Daftarkan akun anda untuk menggunakan Sistem Pakar
Diagnosa Penyakit Hipertensi berbasis metode
Certainty Factor.
</p>
</div>
</div>
<!-- RIGHT FORM -->
<!-- RIGHT -->
<div class="register-right">
<h2>REGISTER</h2>
<div class="subtitle">
Silakan lengkapi data untuk membuat akun
</div>
<form method="POST" action="{{ route('register') }}">
@csrf
<!-- Nama -->
<div class="mb-3">
<label class="form-label">
Nama Lengkap
</label>
<input type="text"
name="name"
class="form-control @error('name') is-invalid @enderror"
placeholder="Nama"
placeholder="Masukkan nama lengkap"
value="{{ old('name') }}"
required>
@error('name')
<div class="invalid-feedback">{{ $message }}</div>
<div class="invalid-feedback text-danger">
{{ $message }}
</div>
@enderror
</div>
<!-- Email -->
<div class="mb-3">
<label class="form-label">
Email
</label>
<input type="email"
name="email"
class="form-control @error('email') is-invalid @enderror"
placeholder="Email"
placeholder="Masukkan email"
value="{{ old('email') }}"
required>
@error('email')
<div class="invalid-feedback">{{ $message }}</div>
<div class="invalid-feedback text-danger">
{{ $message }}
</div>
@enderror
</div>
<!-- Password -->
<div class="mb-3">
<label class="form-label">
Password
</label>
<input type="password"
name="password"
class="form-control @error('password') is-invalid @enderror"
placeholder="Password"
placeholder="Masukkan password"
required>
@error('password')
<div class="invalid-feedback">{{ $message }}</div>
<div class="invalid-feedback text-danger">
{{ $message }}
</div>
@enderror
</div>
<!-- Konfirmasi -->
<!-- Konfirmasi Password -->
<div class="mb-3">
<label class="form-label">
Konfirmasi Password
</label>
<input type="password"
name="password_confirmation"
class="form-control"
placeholder="Konfirmasi Password"
placeholder="Ulangi password"
required>
</div>
<!-- BUTTON -->
<div class="d-grid">
<button type="submit" class="btn btn-register text-white">
<button type="submit"
class="btn btn-register text-white">
Daftar
</button>
</div>
</form>
<div class="auth-links">
Sudah punya akun?
<a href="{{ route('login') }}">Login</a>
<a href="{{ route('login') }}">
Login
</a>
</div>
</div>

View File

@ -2,7 +2,7 @@
<html lang="id">
<head>
<meta charset="UTF-8">
<title>Sistem Pakar Diagnosa</title>
<title>landing</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
@ -122,7 +122,7 @@
<div class="container">
<a class="navbar-brand" href="/">
<i class="fa fa-stethoscope me-2"></i>
Sistem Pakar
TensiKu
</a>
<div>
@ -139,10 +139,9 @@
<!-- HERO -->
<section class="hero">
<div class="container">
<h1>Sistem Pakar Diagnosa Penyakit</h1>
<h1>Yuk Deteksi Dini Penyakit Hipertensi</h1>
<p>
Platform modern berbasis metode Certainty Factor untuk membantu proses analisis
dan diagnosa secara cepat, akurat, dan terstruktur.
Sistem pakar deteksi dini penyakit hipertensi dengan metode Certainty Factor untuk membantu proses diagnosa secara mandiri.
</p>
<a href="{{ route('login') }}" class="btn btn-hero">
@ -174,9 +173,9 @@
<div class="feature-icon mx-auto">
<i class="fa fa-users"></i>
</div>
<h5 class="fw-bold">Multi User System</h5>
<h5 class="fw-bold">Edukasi</h5>
<p class="text-muted">
Mendukung akses admin dan user dengan hak yang berbeda.
menu edukasi menambah pengetahuan anda tentang penyakit hipertensi.
</p>
</div>
</div>

View File

@ -16,9 +16,11 @@
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css" rel="stylesheet">
<style>
body {
font-family: 'Inter', sans-serif;
background-color: #f1f5f9;
overflow-x: hidden;
}
/* SIDEBAR */
@ -27,6 +29,7 @@
min-height: 100vh;
background: #ffffff;
border-right: 1px solid #e5e7eb;
transition: 0.3s;
}
.sidebar h4 {
@ -86,9 +89,10 @@
border: none;
border-radius: 16px;
box-shadow: 0 10px 25px rgba(0,0,0,0.05);
overflow: hidden;
}
/* HERO CARD (seperti contoh gambar) */
/* HERO */
.card-hero {
background: linear-gradient(135deg, #38bdf8, #0ea5e9);
color: white;
@ -121,16 +125,84 @@
background: #0284c7;
}
/* MOBILE BUTTON */
.mobile-toggle{
display:none;
}
/* RESPONSIVE */
@media(max-width:768px){
.sidebar{
position: fixed;
left: -260px;
top: 0;
width: 250px;
height: 100%;
z-index: 999;
overflow-y: auto;
}
.sidebar.active{
left: 0;
}
.content{
width: 100%;
padding: 15px;
}
.topbar{
padding: 12px 15px;
}
.page-title{
font-size: 18px;
}
.table{
font-size: 14px;
}
.mobile-toggle{
display:block;
}
.nav-link{
font-size:14px;
}
.card-hero{
padding:20px;
}
.card-hero h2{
font-size:24px;
}
}
</style>
</head>
<body>
<div class="d-flex">
<!-- OVERLAY -->
<div id="sidebarOverlay"
style="
display:none;
position:fixed;
inset:0;
background:rgba(0,0,0,0.4);
z-index:998;
">
</div>
<!-- SIDEBAR -->
<div class="sidebar p-3">
<h4 class="text-center mb-3">Admin Panel</h4>
<h4 class="text-center mb-3">TensiKu</h4>
<hr>
<ul class="nav flex-column">
@ -186,16 +258,23 @@ class="nav-link {{ request()->is('admin/riwayat') ? 'active' : '' }}">
<!-- LOGOUT -->
<li class="nav-item mt-4">
<form action="{{ route('logout') }}" method="POST">
@csrf
<button type="submit"
class="nav-link text-danger border-0 bg-transparent text-start w-100">
<i class="fa fa-sign-out-alt me-2"></i> Logout
</button>
</form>
</li>
</ul>
</div>
<!-- CONTENT -->
@ -203,30 +282,54 @@ class="nav-link text-danger border-0 bg-transparent text-start w-100">
<!-- TOPBAR -->
<div class="topbar d-flex justify-content-between align-items-center">
<div>
<h5 class="page-title">@yield('title')</h5>
<div class="page-subtitle">
Sistem Pakar Diagnosa Penyakit Hipertensi
<div class="d-flex align-items-center gap-3">
<!-- TOGGLE -->
<button class="btn btn-primary mobile-toggle"
id="toggleSidebar">
<i class="fa fa-bars"></i>
</button>
<div>
<h5 class="page-title">
@yield('title')
</h5>
<div class="page-subtitle">
Sistem Pakar Diagnosa Penyakit Hipertensi
</div>
</div>
</div>
<div>
{{ auth()->user()->name ?? 'Admin' }}
</div>
</div>
<!-- HERO (OPSIONAL DI DASHBOARD) -->
<!-- HERO -->
@if(request()->is('admin/dashboard'))
<div class="card-hero mb-4">
<h2>Selamat Datang</h2>
<p>
Sistem pakar membantu diagnosa penyakit berdasarkan gejala
dengan metode Certainty Factor
</p>
</div>
@endif
<!-- CONTENT UTAMA -->
<!-- CONTENT -->
@yield('content')
</div>
@ -236,6 +339,37 @@ class="nav-link text-danger border-0 bg-transparent text-start w-100">
<!-- Bootstrap JS -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<script>
const toggleSidebar = document.getElementById('toggleSidebar');
const sidebar = document.querySelector('.sidebar');
const overlay = document.getElementById('sidebarOverlay');
if(toggleSidebar){
toggleSidebar.addEventListener('click', () => {
sidebar.classList.toggle('active');
if(sidebar.classList.contains('active')){
overlay.style.display = 'block';
}else{
overlay.style.display = 'none';
}
});
overlay.addEventListener('click', () => {
sidebar.classList.remove('active');
overlay.style.display = 'none';
});
}
</script>
@stack('scripts')
@yield('scripts')

View File

@ -16,28 +16,34 @@
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css" rel="stylesheet">
<style>
body {
font-family: 'Inter', sans-serif;
background-color: #f1f5f9;
overflow-x: hidden;
}
/* SIDEBAR */
/* =========================
SIDEBAR
========================= */
.sidebar {
width: 250px;
min-height: 100vh;
background: #ffffff;
border-right: 1px solid #e5e7eb;
transition: 0.3s;
}
.sidebar h4 {
font-weight: 600;
font-weight: 700;
color: #0f172a;
}
.nav-link {
color: #64748b !important;
border-radius: 10px;
padding: 10px 14px;
border-radius: 12px;
padding: 12px 14px;
margin-bottom: 6px;
transition: 0.3s;
font-size: 14px;
@ -53,7 +59,10 @@
color: white !important;
}
/* CONTENT */
/* =========================
CONTENT
========================= */
.content {
background-color: #f1f5f9;
min-height: 100vh;
@ -61,17 +70,20 @@
width: 100%;
}
/* TOPBAR */
/* =========================
TOPBAR
========================= */
.topbar {
background: white;
border-radius: 14px;
border-radius: 16px;
padding: 15px 20px;
margin-bottom: 20px;
box-shadow: 0 4px 15px rgba(0,0,0,0.05);
}
.page-title {
font-weight: 600;
font-weight: 700;
color: #0f172a;
margin-bottom: 0;
}
@ -81,14 +93,20 @@
color: #64748b;
}
/* CARD */
/* =========================
CARD
========================= */
.card {
border: none;
border-radius: 16px;
box-shadow: 0 10px 25px rgba(0,0,0,0.05);
}
/* HERO */
/* =========================
HERO
========================= */
.card-hero {
background: linear-gradient(135deg, #38bdf8, #0ea5e9);
color: white;
@ -97,21 +115,31 @@
}
.card-hero h2 {
font-weight: 600;
font-weight: 700;
}
.card-hero p {
opacity: 0.9;
}
/* TABLE */
/* =========================
TABLE
========================= */
.table {
background: white;
border-radius: 12px;
overflow: hidden;
}
/* BUTTON */
.table-responsive {
overflow-x: auto;
}
/* =========================
BUTTON
========================= */
.btn-primary {
background: #0ea5e9;
border: none;
@ -122,15 +150,17 @@
}
/* =========================
🔥 FIX PAGINATION (PENTING)
PAGINATION
========================= */
.pagination {
justify-content: center;
margin-top: 20px;
flex-wrap: wrap;
}
.page-item {
margin: 0 3px;
margin: 3px;
}
.page-link {
@ -140,10 +170,6 @@
border: 1px solid #e5e7eb;
color: #0ea5e9;
background: white;
display: inline-block !important;
width: auto !important;
height: auto !important;
transform: none !important;
}
.page-link:hover {
@ -162,60 +188,168 @@
background: #f8fafc;
}
/* =========================
MOBILE NAVBAR
========================= */
.mobile-topbar {
display: none;
background: white;
padding: 15px 20px;
box-shadow: 0 4px 10px rgba(0,0,0,0.05);
align-items: center;
justify-content: space-between;
}
.menu-btn {
border: none;
background: none;
font-size: 22px;
color: #0ea5e9;
}
/* =========================
RESPONSIVE
========================= */
@media(max-width: 991px) {
.sidebar {
position: fixed;
top: 0;
left: -260px;
z-index: 1050;
height: 100%;
}
.sidebar.active {
left: 0;
}
.content {
width: 100%;
padding: 20px;
}
.mobile-topbar {
display: flex;
}
.topbar {
flex-direction: column;
align-items: flex-start !important;
gap: 10px;
}
}
@media(max-width: 576px) {
.content {
padding: 15px;
}
.card {
border-radius: 14px;
}
.topbar {
padding: 15px;
}
.page-title {
font-size: 18px;
}
.page-subtitle {
font-size: 12px;
}
.table {
font-size: 13px;
}
.btn {
font-size: 13px;
}
}
</style>
</head>
<body>
<!-- MOBILE TOPBAR -->
<div class="mobile-topbar">
<h5 class="mb-0 fw-bold text-primary">
TensiKu
</h5>
<button class="menu-btn" id="menuToggle">
<i class="fa fa-bars"></i>
</button>
</div>
<div class="d-flex">
<!-- SIDEBAR -->
<div class="sidebar p-3">
<div class="sidebar p-3" id="sidebar">
<h4 class="text-center mb-3">User Panel</h4>
<h4 class="text-center mb-3">TensiKu</h4>
<hr>
<ul class="nav flex-column">
<li class="nav-item">
<a href="{{ url('/user/dashboard') }}"
<a href="{{ url('/user/dashboard') }}"
class="nav-link {{ request()->is('user/dashboard') ? 'active' : '' }}">
<i class="fa fa-home me-2"></i> Dashboard
<i class="fa fa-home me-2"></i> Dashboard
</a>
</li>
<li class="nav-item">
<a href="{{ url('/user/diagnosa') }}"
<a href="{{ url('/user/diagnosa') }}"
class="nav-link {{ request()->is('user/diagnosa') ? 'active' : '' }}">
<i class="fa fa-stethoscope me-2"></i> Diagnosa
<i class="fa fa-stethoscope me-2"></i> Diagnosa
</a>
</li>
<li class="nav-item">
<a href="{{ url('/user/riwayat') }}"
<a href="{{ url('/user/riwayat') }}"
class="nav-link {{ request()->is('user/riwayat') ? 'active' : '' }}">
<i class="fa fa-history me-2"></i> Riwayat
<i class="fa fa-history me-2"></i> Riwayat
</a>
</li>
<li class="nav-item">
<a href="{{ url('/user/edukasi') }}"
<a href="{{ url('/user/edukasi') }}"
class="nav-link {{ request()->is('user/edukasi*') ? 'active' : '' }}">
<i class="fa fa-book me-2"></i> Edukasi
<i class="fa fa-book me-2"></i> Edukasi
</a>
</li>
<!-- LOGOUT -->
<li class="nav-item mt-4">
<form action="{{ route('logout') }}" method="POST">
@csrf
<button
<button
class="nav-link text-danger border-0 bg-transparent text-start w-100">
<i class="fa fa-sign-out-alt me-2"></i> Logout
<i class="fa fa-sign-out-alt me-2"></i>
Logout
</button>
</form>
</li>
</ul>
</div>
<!-- CONTENT -->
@ -223,16 +357,19 @@ class="nav-link text-danger border-0 bg-transparent text-start w-100">
<!-- TOPBAR -->
<div class="topbar d-flex justify-content-between align-items-center">
<div>
<h5 class="page-title">@yield('title')</h5>
<div class="page-subtitle">
Sistem Pakar Diagnosa Penyakit
</div>
</div>
<div>
<div class="fw-semibold">
{{ auth()->user()->name ?? 'User' }}
</div>
</div>
<!-- CONTENT -->
@ -245,6 +382,17 @@ class="nav-link text-danger border-0 bg-transparent text-start w-100">
<!-- Bootstrap JS -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<script>
const menuToggle = document.getElementById('menuToggle');
const sidebar = document.getElementById('sidebar');
menuToggle.addEventListener('click', function () {
sidebar.classList.toggle('active');
});
</script>
@stack('scripts')
@yield('scripts')

View File

@ -2,125 +2,211 @@
<html>
<head>
<title>Surat Rujukan</title>
<style>
body { font-family: Arial, sans-serif; font-size: 12px; }
.center { text-align: center; }
.right { text-align: right; }
body {
font-family: Arial, sans-serif;
font-size: 12px;
line-height: 1.5;
}
.center {
text-align: center;
}
.right {
text-align: right;
}
table {
width: 100%;
border-collapse: collapse;
margin-bottom: 10px;
margin-bottom: 15px;
}
th, td {
padding: 6px;
padding: 8px;
vertical-align: top;
}
.bordered, .bordered td, .bordered th {
.bordered,
.bordered td,
.bordered th {
border: 1px solid black;
}
.section-title{
margin-top:20px;
margin-bottom:10px;
}
</style>
</head>
<body>
<!-- ================= HEADER ================= -->
<div class="center">
<h3>SURAT RUJUKAN PEMERIKSAAN</h3>
<p>Sistem Pakar Deteksi Dini Penyakit</p>
<h2>SURAT HASIL DIAGNOSA</h2>
<p>
Sistem Pakar Deteksi Dini Penyakit Hipertensi
</p>
</div>
<hr>
<p class="right">
Tanggal: {{ now()->format('d-m-Y') }}
Tanggal : {{ now()->format('d-m-Y') }}
</p>
<!-- ================= BIODATA ================= -->
<h4>Data Pasien</h4>
<!-- ================= DATA PASIEN ================= -->
<h4 class="section-title">Data Pasien</h4>
<table>
<tr>
<td width="30%">Nama</td>
<td>: {{ $diagnosa->pasien->nama }}</td>
</tr>
<tr>
<td>Jenis Kelamin</td>
<td>: {{ $diagnosa->pasien->jenis_kelamin }}</td>
</tr>
<tr>
<td>Tempat Lahir</td>
<td>: {{ $diagnosa->pasien->tempat_lahir}}</td>
<td>: {{ $diagnosa->pasien->tempat_lahir }}</td>
</tr>
<tr>
<td>Tanggal Lahir</td>
<td>: {{ $diagnosa->pasien->tanggal_lahir }}</td>
</tr>
<tr>
<td>Umur</td>
<td>: {{ \Carbon\Carbon::parse($diagnosa->pasien->tanggal_lahir)->age }} Tahun</td>
<td>
:
{{ \Carbon\Carbon::parse($diagnosa->pasien->tanggal_lahir)->age }}
Tahun
</td>
</tr>
<tr>
<td>Alamat</td>
<td>: {{ $diagnosa->pasien->alamat }}</td>
</tr>
<tr>
<td>No HP</td>
<td>: {{ $diagnosa->pasien->no_telp }}</td>
</tr>
</table>
<!-- ================= GEJALA ================= -->
<h4>Gejala yang Dialami</h4>
<h4 class="section-title">Gejala yang Dipilih</h4>
<table class="bordered">
<tr>
<th width="5%">No</th>
<th>Gejala</th>
<th width="30%">Tingkat Keyakinan</th>
</tr>
@foreach($gejalas as $g)
<tr>
<td>{{ $loop->iteration }}</td>
<td>{{ $g->nama }}</td>
<td>
{{ $g->keterangan_cf }}
({{ $g->cf_user }})
</td>
</tr>
@endforeach
</table>
<!-- ================= HASIL ================= -->
<h4>Hasil Analisis Sistem</h4>
<h4 class="section-title">Hasil Analisis Sistem</h4>
<table>
<tr>
<td width="30%">Indikasi Penyakit</td>
<td>: {{ $diagnosa->penyakit->nama }}</td>
</tr>
<tr>
<td>Tingkat Keyakinan</td>
<td>: {{ number_format($diagnosa->cf_hasil * 100, 2) }}%</td>
<td>
:
{{ number_format($diagnosa->cf_hasil * 100, 2) }}%
</td>
</tr>
</table>
<!-- ================= PENUTUP ================= -->
<br>
<p>
Berdasarkan hasil analisis oleh sistem pakar, pasien diindikasikan mengalami kondisi seperti di atas.
Disarankan untuk melakukan pemeriksaan lebih lanjut ke fasilitas kesehatan terdekat seperti
<b>Puskesmas</b> atau <b>Rumah Sakit</b> guna mendapatkan diagnosis medis lebih lanjut dan akurat.
<p align="justify">
Berdasarkan hasil analisis menggunakan metode
<b>Certainty Factor</b>,
sistem mendeteksi bahwa pasien memiliki indikasi
penyakit seperti yang tercantum di atas dengan tingkat
keyakinan sesuai hasil perhitungan sistem.
</p>
<p align="justify">
Hasil diagnosa ini bukan pengganti diagnosis medis,
namun dapat digunakan sebagai langkah awal untuk
deteksi dini penyakit.
Pasien disarankan melakukan pemeriksaan lebih lanjut
ke fasilitas kesehatan seperti
<b>Puskesmas</b>,
<b>Klinik</b>,
atau
<b>Rumah Sakit</b>
untuk mendapatkan penanganan yang lebih akurat.
</p>
<br><br>
<!-- <table width="100%">
<!-- ================= TTD ================= -->
<table width="100%">
<tr>
<td width="60%"></td>
<td class="center">
<p>Petugas Sistem</p>
<br><br><br>
<p><b>(...........................)</b></p>
</td>
</tr>
</table>
-->
</body>
</html>

View File

@ -4,39 +4,116 @@
@section('content')
<form action="{{ route('diagnosa.proses') }}" method="POST">
<div class="alert alert-info">
<h5 class="mb-1">Perhatian!</h5>
<p class="mb-0">
Silakan pilih semua gejala yang ada dibawh ini, Berdasarkan yang Anda alami dengan tingkat keyakinan yang sesuai.
</p>
</div>
@csrf
<div class="card shadow-sm border-0">
<div class="card-body p-4">
@foreach($gejalas as $g)
<div class="mb-3">
<label><b>{{ $g->nama }}</b></label>
<!-- HEADER -->
<div class="mb-4">
<h4 class="fw-bold text-primary mb-1">
Diagnosa Penyakit
</h4>
<select name="gejala[{{ $g->id }}]" class="form-control">
<option value="">-- Pilih --</option>
<option value="0">Tidak</option>
<option value="0.2">Tidak Yakin</option>
<option value="0.4">Sedikit Yakin</option>
<option value="0.6">Cukup Yakin</option>
<option value="0.8">Yakin</option>
<option value="1">Sangat Yakin</option>
</select>
</div>
@endforeach
<p class="text-muted mb-0">
Pilih gejala yang Anda alami beserta tingkat keyakinannya.
</p>
</div>
<button class="btn btn-primary">Diagnosa</button>
</form>
<!-- ALERT -->
<div class="alert alert-info border-0 rounded-4">
<h6 class="fw-bold mb-2">
<i class="fa fa-circle-info me-2"></i>
Perhatian
</h6>
<p class="mb-0">
Silakan pilih gejala sesuai kondisi yang Anda alami,
kemudian tentukan tingkat keyakinan Anda terhadap
gejala tersebut.
</p>
</div>
<!-- ERROR -->
@if(session('error'))
<div class="alert alert-danger">
{{ session('error') }}
</div>
@endif
<!-- FORM -->
<form action="{{ route('diagnosa.proses') }}" method="POST">
@csrf
<div class="row">
@foreach($gejalas as $g)
<div class="col-md-6 mb-4">
<div class="border rounded-4 p-3 h-100 bg-light">
<!-- NAMA GEJALA -->
<label class="fw-semibold mb-2 d-block">
{{ $g->nama }}
</label>
<!-- SELECT -->
<select
name="gejala[{{ $g->id }}]"
class="form-select">
<option value="">
-- Pilih Tingkat Keyakinan --
</option>
<option value="0">
Tidak
</option>
<option value="0.2">
Tidak Yakin
</option>
<option value="0.4">
Sedikit Yakin
</option>
<option value="0.6">
Cukup Yakin
</option>
<option value="0.8">
Yakin
</option>
<option value="1">
Sangat Yakin
</option>
</select>
</div>
</div>
@endforeach
</div>
<!-- BUTTON -->
<div class="d-grid mt-3">
<button class="btn btn-primary btn-lg rounded-3">
Proses Diagnosa
</button>
</div>
</form>
@error('gejala')
<div class="alert alert-danger">
{{ $message }}
</div>
@enderror
@endsection
</div>
@endsection

View File

@ -160,6 +160,8 @@
// DATA PENYAKIT
// =========================
Route::resource('penyakit', PenyakitController::class);
Route::get('/admin/penyakit/{id}', [PenyakitController::class, 'show'])
->name('penyakit.show');
// =========================