user feature
This commit is contained in:
parent
b0d1f6dcbc
commit
3b8990d6a3
|
@ -0,0 +1,84 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\User;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Addiction;
|
||||
use App\Models\History;
|
||||
use App\Models\Item;
|
||||
use App\Models\Likert;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
|
||||
class DashboardController extends Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('role:user');
|
||||
}
|
||||
|
||||
public function index()
|
||||
{
|
||||
$addictions = Addiction::where('status', 'active')
|
||||
->orderBy('min_percentage', 'desc')
|
||||
->get();
|
||||
return view('user.dashboard', compact('addictions'));
|
||||
}
|
||||
|
||||
public function history()
|
||||
{
|
||||
$histories = History::with('user', 'addiction')
|
||||
->where('user_id', Auth::id())
|
||||
->orderBy('created_at', 'desc')
|
||||
->get();
|
||||
|
||||
return view('user.history', compact('histories'));
|
||||
}
|
||||
|
||||
public function addiction()
|
||||
{
|
||||
$items = Item::with('factor')
|
||||
->get()
|
||||
->groupBy('factor.name');
|
||||
|
||||
$likerts = Likert::orderBy('score')->get();
|
||||
return view('user.addiction', compact('items', 'likerts'));
|
||||
}
|
||||
|
||||
public function storeAddiction(Request $request)
|
||||
{
|
||||
$values = $request->values;
|
||||
$answers = $request->answers;
|
||||
$maxLikert = Likert::orderBy('score', 'desc')->first()->score;
|
||||
|
||||
$userScores = [];
|
||||
$maxScores = [];
|
||||
|
||||
foreach ($values as $key => $value) {
|
||||
$userScores[] = $value * $answers[$key];
|
||||
$maxScores[] = $value * $maxLikert;
|
||||
}
|
||||
|
||||
$totalUserScore = array_sum($userScores);
|
||||
$totalMaxScore = array_sum($maxScores);
|
||||
|
||||
$percentage = round(($totalUserScore / $totalMaxScore) * 100, 2);
|
||||
|
||||
$addiction = Addiction::where('min_percentage', '<=', $percentage)
|
||||
->where('max_percentage', '>=', $percentage)
|
||||
->where('status', 'active')
|
||||
->first();
|
||||
|
||||
if ($addiction === null) {
|
||||
return redirect()->back()->with('error', 'Terjadi kesalahan saat mencari jenis kecanduan');
|
||||
}
|
||||
|
||||
History::create([
|
||||
'user_id' => Auth::id(),
|
||||
'addiction_id' => $addiction->id,
|
||||
'result' => $percentage.'%',
|
||||
]);
|
||||
|
||||
return redirect()->route('user.history')->with('success', 'Berhasil menambahkan riwayat');
|
||||
}
|
||||
}
|
|
@ -42,4 +42,9 @@ class User extends Authenticatable
|
|||
protected $casts = [
|
||||
'email_verified_at' => 'datetime',
|
||||
];
|
||||
|
||||
public function histories()
|
||||
{
|
||||
return $this->hasMany(History::class, 'user_id', 'id');
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -37,7 +37,7 @@
|
|||
<td>{{ $loop->iteration }}</td>
|
||||
<td>{{ $history->user->name }}</td>
|
||||
<td>{{ $history->addiction->name }}</td>
|
||||
<td>{{ $history->result }}</td>
|
||||
<td>{{ $history->result }}%</td>
|
||||
<td>{{ $history->created_at->format('d-m-Y H:i:s') }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
<!doctype html>
|
||||
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
||||
<meta name="description" content="Responsive HTML Admin Dashboard Template based on Bootstrap 5">
|
||||
<meta name="author" content="NobleUI">
|
||||
<meta name="keywords" content="nobleui, bootstrap, bootstrap 5, bootstrap5, admin, dashboard, template, responsive, css, sass, html, theme, front-end, ui kit, web">
|
||||
<meta name="csrf-token" content="{{ csrf_token() }}">
|
||||
|
||||
<title>@yield('title')</title>
|
||||
|
||||
<!-- color-modes:js -->
|
||||
<script src="{{ asset('assets/js/color-modes.js') }}"></script>
|
||||
<!-- endinject -->
|
||||
|
||||
<!-- Fonts -->
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700;900&display=swap" rel="stylesheet">
|
||||
<!-- End fonts -->
|
||||
|
||||
<!-- core:css -->
|
||||
<link rel="stylesheet" href="{{ asset('assets/vendors/core/core.css') }}">
|
||||
<!-- endinject -->
|
||||
|
||||
<!-- Plugin css for this page -->
|
||||
<link rel="stylesheet" href="{{ asset('assets/vendors/sweetalert2/sweetalert2.min.css') }}">
|
||||
@yield('styles')
|
||||
<!-- End plugin css for this page -->
|
||||
|
||||
<!-- inject:css -->
|
||||
<link rel="stylesheet" href="{{ asset('assets/vendors/mdi/css/materialdesignicons.min.css') }}">
|
||||
<link rel="stylesheet" href="{{ asset('assets/fonts/feather-font/css/iconfont.css') }}">
|
||||
<!-- endinject -->
|
||||
|
||||
<!-- Layout styles -->
|
||||
<link rel="stylesheet" href="{{ asset('assets/css/demo2/style.css') }}">
|
||||
<!-- End layout styles -->
|
||||
|
||||
<link rel="shortcut icon" href="{{ asset('assets/images/favicon.png') }}" />
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<!-- Begin page -->
|
||||
<div class="main-wrapper">
|
||||
|
||||
<!-- ========== Left Sidebar Start ========== -->
|
||||
@include('layouts.navbar')
|
||||
<!-- Left Sidebar End -->
|
||||
|
||||
<!-- ============================================================== -->
|
||||
<!-- Start right Content here -->
|
||||
<!-- ============================================================== -->
|
||||
<div class="page-wrapper">
|
||||
<!-- End topbar -->
|
||||
|
||||
@yield('content')
|
||||
<!-- End Page-content -->
|
||||
|
||||
<footer class="footer border-top">
|
||||
<div class="container d-flex flex-row align-items-center justify-content-between py-3 small">
|
||||
<p class="text-secondary mb-1 mb-md-0">Copyright © 2024 <a href="https://www.nobleui.com" target="_blank">NobleUI</a>.</p>
|
||||
<p class="text-secondary">Handcrafted With <i class="mb-1 text-primary ms-1 icon-sm" data-feather="heart"></i></p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
<!-- end main content-->
|
||||
|
||||
</div>
|
||||
<!-- END layout-wrapper -->
|
||||
@include('layouts.alert')
|
||||
<!-- JAVASCRIPT -->
|
||||
<!-- core:js -->
|
||||
<script src="{{ asset('assets/vendors/core/core.js') }}"></script>
|
||||
<!-- endinject -->
|
||||
|
||||
<!-- Plugin js for this page -->
|
||||
<script src="{{ asset('assets/vendors/jquery/jquery.min.js') }}"></script>
|
||||
<!-- End plugin js for this page -->
|
||||
|
||||
<!-- inject:js -->
|
||||
<script src="{{ asset('assets/vendors/sweetalert2/sweetalert2.min.js') }}"></script>
|
||||
<script src="{{ asset('assets/vendors/feather-icons/feather.min.js') }}"></script>
|
||||
<script src="{{ asset('assets/js/app.js') }}"></script>
|
||||
<!-- endinject -->
|
||||
|
||||
<!-- Custom js for this page -->
|
||||
<script>
|
||||
var n = Swal.mixin({
|
||||
customClass:{
|
||||
confirmButton:"btn btn-label-info btn-wide mx-1",
|
||||
denyButton:"btn btn-label-secondary btn-wide mx-1",
|
||||
cancelButton:"btn btn-label-danger btn-wide mx-1"
|
||||
},
|
||||
buttonsStyling:!1
|
||||
});
|
||||
</script>
|
||||
@yield('scripts')
|
||||
<!-- End custom js for this page -->
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,95 @@
|
|||
<div class="horizontal-menu">
|
||||
<nav class="navbar top-navbar">
|
||||
<div class="container">
|
||||
<div class="navbar-content">
|
||||
|
||||
<a href="#" class="navbar-brand d-none d-lg-flex">
|
||||
Noble<span>UI</span>
|
||||
</a>
|
||||
|
||||
<!-- Logo-mini for small screen devices (mobile/tablet) -->
|
||||
<div class="logo-mini-wrapper">
|
||||
<img src="{{ asset('assets/images/logo-mini-light.png') }}" class="logo-mini logo-mini-light" alt="logo">
|
||||
<img src="{{ asset('assets/images/logo-mini-dark.png') }}" class="logo-mini logo-mini-dark" alt="logo">
|
||||
</div>
|
||||
|
||||
<ul class="navbar-nav">
|
||||
<li class="theme-switcher-wrapper nav-item">
|
||||
<input type="checkbox" value="" id="theme-switcher">
|
||||
<label for="theme-switcher">
|
||||
<div class="box">
|
||||
<div class="ball"></div>
|
||||
<div class="icons">
|
||||
<i class="feather icon-sun"></i>
|
||||
<i class="feather icon-moon"></i>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
</li>
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" href="#" id="profileDropdown" role="button"
|
||||
data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<img class="w-30px h-30px ms-1 rounded-circle" src="{{ asset('assets/images/avatar-8.png') }}" alt="profile">
|
||||
</a>
|
||||
<div class="dropdown-menu p-0" aria-labelledby="profileDropdown">
|
||||
<div class="d-flex flex-column align-items-center border-bottom px-5 py-3">
|
||||
<div class="mb-3">
|
||||
<img class="w-80px h-80px rounded-circle" src="{{ asset('assets/images/avatar-8.png') }}" alt="">
|
||||
</div>
|
||||
<div class="text-center">
|
||||
<p class="fs-16px fw-bolder">{{ Auth::user()->name }}</p>
|
||||
<p class="fs-12px text-secondary">{{ Auth::user()->email }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<ul class="list-unstyled p-1">
|
||||
<li class="dropdown-item py-2">
|
||||
<a href="{{ route('logout') }}" class="text-body ms-0" onclick="event.preventDefault(); document.getElementById('logout-form').submit();">
|
||||
<i class="me-2 icon-md" data-feather="log-out"></i>
|
||||
<span>Log Out</span>
|
||||
</a>
|
||||
<form id="logout-form" action="{{ route('logout') }}" method="POST" class="d-none">
|
||||
@csrf
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<!-- navbar toggler for small devices -->
|
||||
<div data-toggle="horizontal-menu-toggle"
|
||||
class="navbar-toggler navbar-toggler-right d-lg-none align-self-center">
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
<nav class="bottom-navbar">
|
||||
<div class="container">
|
||||
<ul class="nav page-navigation">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link @if (Request::is('dashboard')) active @endif" href="{{ route('user.dashboard') }}">
|
||||
<i class="link-icon" data-feather="box"></i>
|
||||
<span class="menu-title">Dashboard</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link @if (Request::is('addiction')) active @endif" href="{{ route('user.addiction') }}">
|
||||
<i class="link-icon" data-feather="search"></i>
|
||||
<span class="menu-title">Addiction Test</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="{{ route('user.history') }}" class="nav-link @if (Request::is('history')) active @endif">
|
||||
<i class="link-icon" data-feather="bar-chart-2"></i>
|
||||
<span class="menu-title">History</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
|
@ -0,0 +1,70 @@
|
|||
@extends('layouts.masteruser')
|
||||
@section('title', 'Addiction Test')
|
||||
@section('styles')
|
||||
<link rel="stylesheet" href="{{ asset('assets/vendors/flatpickr/flatpickr.min.css') }}">
|
||||
@endsection
|
||||
@section('content')
|
||||
<div class="page-content">
|
||||
<div class="row">
|
||||
<div class="col-12">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8 grid-margin stretch-card">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title mb-0">Addiction Test</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form id="addiction-form" action="{{ route('user.addiction.store') }}" method="post" autocomplete="off">
|
||||
@csrf
|
||||
@method('POST')
|
||||
<table class="table table-bordered w-100 text-wrap align-middle">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Factor</th>
|
||||
<th class="text-center">Item</th>
|
||||
<th>Item Content</th>
|
||||
<th class="text-center">Select Answer</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach ($items as $factorName => $groupedItems)
|
||||
@foreach ($groupedItems as $item)
|
||||
<tr>
|
||||
@if ($loop->first)
|
||||
<td rowspan="{{ $groupedItems->count() }}">{{ $factorName }}</td>
|
||||
@endif
|
||||
<td class="text-center">{{ $item->code }}</td>
|
||||
<td class="text-wrap">{{ $item->content }}</td>
|
||||
<td class="text-center">
|
||||
<input type="hidden" name="values[]" value="{{ $item->value }}">
|
||||
<select name="answers[]" class="form-select" required>
|
||||
<option value="" hidden>Select Answer</option>
|
||||
@foreach ($likerts as $likert)
|
||||
<option value="{{ $likert->score }}" {{ in_array($likert->score, old('answers', [])) ? 'selected' : '' }}>
|
||||
{{ $likert->name }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
||||
<div class="card-footer text-end">
|
||||
<button type="submit" form="addiction-form" class="btn btn-primary">Submit</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
@section('scripts')
|
||||
<script src="{{ asset('assets/vendors/flatpickr/flatpickr.min.js') }}"></script>
|
||||
<script src="{{ asset('assets/vendors/apexcharts/apexcharts.min.js') }}"></script>
|
||||
<script src="{{ asset('assets/js/dashboard.js') }}"></script>
|
||||
@endsection
|
|
@ -0,0 +1,50 @@
|
|||
@extends('layouts.masteruser')
|
||||
@section('title', 'Dashboard')
|
||||
@section('styles')
|
||||
<link rel="stylesheet" href="{{ asset('assets/vendors/flatpickr/flatpickr.min.css') }}">
|
||||
@endsection
|
||||
@section('content')
|
||||
<div class="page-content">
|
||||
<div class="row">
|
||||
<div class="col-12 col-xl-12 stretch-card">
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-md-8 grid-margin stretch-card">
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h4 class="card-title mb-0">Tentang Sistem Pakar</h4>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="mb-3" style="text-align: justify">Sistem pakar adalah sistem berbasis komputer yang menggunakan pengetahuan, fakta dan teknik penalaran dalam memecahkan masalah yang biasanya hanya dapat dipecahkan oleh seorang pakar dalam bidang tersebut. Sistem pakar adalah salah satu cabang dari AI (Artitificial Inteligence) yang membuat pengguna secara luas knowledge yang khusus untuk penyelesaian masalah tingkat manusia yang pakar. Seorang pakar adalah orang yang mempunyai keahlian dalam bidang tertentu, yaitu pakar yang mempunyai knowledge atau kemampuan khusus yang orang lain tidak mengetahui atau mampu dalam bidang yang dimilikinya.</p>
|
||||
<p style="text-align: justify">Mekanisme inferensi adalah bagian dari sistem pakar yang melakukan penalaran dengan menggunakan isi daftar aturan berdasarkan urutan dan pola tertentu. Selama proses konsultasi antar sistem dan pemakai, mekanisme inferensi menguji aturan satu demi satu sampai kondisi aturan itu benar. Forward chaining (runut maju) berarti menggunakan himpunan aturan kondisi-aksi. Dalam metode ini, data digunakan untuk menentukan aturan mana yang akan dijalankan, kemudian aturan tersebut dijalankan. Mungkin menambahkan data ke memori kerja. Proses diulang sampai ditemukan suatu hasil.</p>
|
||||
<table class="table table-bordered align-middle mt-3">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Tingkat Kecanduan</th>
|
||||
<th>Persentase</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach ($addictions as $addiction)
|
||||
<tr>
|
||||
<td>{{ $addiction->name }}</td>
|
||||
<td>{{ $addiction->min_percentage }} - {{ $addiction->max_percentage }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="card-footer text-center">
|
||||
<a href="{{ route('user.addiction') }}" class="btn btn-primary">Mulai Konsultasi</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
@section('scripts')
|
||||
<script src="{{ asset('assets/vendors/flatpickr/flatpickr.min.js') }}"></script>
|
||||
<script src="{{ asset('assets/vendors/apexcharts/apexcharts.min.js') }}"></script>
|
||||
<script src="{{ asset('assets/js/dashboard.js') }}"></script>
|
||||
@endsection
|
|
@ -0,0 +1,64 @@
|
|||
@extends('layouts.masteruser')
|
||||
@section('title', 'Histories Datas')
|
||||
@section('styles')
|
||||
<!-- DataTables -->
|
||||
<link href="{{ asset('assets/vendors/datatables.net-bs5/css/dataTables.bootstrap5.min.css') }}" rel="stylesheet" type="text/css" />
|
||||
|
||||
<!-- Responsive datatable examples -->
|
||||
<link href="{{ asset('assets/vendors/datatables.net-responsive-bs5/css/responsive.bootstrap5.min.css') }}" rel="stylesheet" type="text/css" />
|
||||
@endsection
|
||||
@section('content')
|
||||
<div class="page-content">
|
||||
<nav class="page-breadcrumb">
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item"><a href="#">Master</a></li>
|
||||
<li class="breadcrumb-item active" aria-current="page">History</li>
|
||||
</ol>
|
||||
</nav>
|
||||
<div class="row">
|
||||
<div class="col-md-12 grid-margin stretch-card">
|
||||
<div class="card">
|
||||
<div class="card-body">
|
||||
<h4 class="card-title">History Data</h4>
|
||||
<div class="table-responsive">
|
||||
<table id="datatable" class="table align-middle">
|
||||
<thead>
|
||||
<tr>
|
||||
<th width="10px" class="text-center">#</th>
|
||||
<th>Addiction</th>
|
||||
<th>Result</th>
|
||||
<th>Date Time</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach ($histories as $history)
|
||||
<tr>
|
||||
<td>{{ $loop->iteration }}</td>
|
||||
<td>{{ $history->addiction->name }}</td>
|
||||
<td>{{ $history->result }}%</td>
|
||||
<td>{{ $history->created_at->format('d-m-Y H:i:s') }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- end col -->
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
@section('scripts')
|
||||
<!-- Required datatable js -->
|
||||
<script src="{{ asset('assets/vendors/datatables.net/js/jquery.dataTables.min.js') }}"></script>
|
||||
<script src="{{ asset('assets/vendors/datatables.net-bs5/js/dataTables.bootstrap5.min.js') }}"></script>
|
||||
|
||||
<!-- Responsive examples -->
|
||||
<script src="{{ asset('assets/vendors/datatables.net-responsive/js/dataTables.responsive.min.js') }}"></script>
|
||||
<script src="{{ asset('assets/vendors/datatables.net-responsive-bs5/js/responsive.bootstrap5.min.js') }}"></script>
|
||||
<script>
|
||||
$(function () {
|
||||
$('#datatable').DataTable();
|
||||
});
|
||||
</script>
|
||||
@endsection
|
|
@ -48,6 +48,10 @@
|
|||
|
||||
Route::middleware('role:user')->name('user.')->group(function () {
|
||||
Route::get('/home', [HomeController::class, 'index'])->name('dashboard');
|
||||
Route::get('dashboard', [App\Http\Controllers\User\DashboardController::class, 'index'])->name('dashboard');
|
||||
Route::get('history', [App\Http\Controllers\User\DashboardController::class, 'history'])->name('history');
|
||||
Route::get('addiction', [App\Http\Controllers\User\DashboardController::class, 'addiction'])->name('addiction');
|
||||
Route::post('addiction', [App\Http\Controllers\User\DashboardController::class, 'storeAddiction'])->name('addiction.store');
|
||||
});
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue