update menu

This commit is contained in:
MufridaFaraDiani27 2026-02-22 11:54:24 +07:00
parent 7a8af446b6
commit 591962379a
10 changed files with 307 additions and 102 deletions

BIN
public/images/botani.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 206 KiB

BIN
public/images/papuma.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

BIN
public/images/tancak.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 132 KiB

BIN
public/images/watuulo.jpeg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

View File

@ -1,13 +1,12 @@
import './bootstrap'; import "./bootstrap";
import Alpine from 'alpinejs'; import Alpine from "alpinejs";
window.Alpine = Alpine; window.Alpine = Alpine;
Alpine.start(); Alpine.start();
import Chart from "chart.js/auto"; import Chart from "chart.js/auto";
document.addEventListener("DOMContentLoaded", function () { document.addEventListener("DOMContentLoaded", function () {
/* ================= PIE CHART ================= */ /* ================= PIE CHART ================= */
const pieCtx = document.getElementById("pieChart"); const pieCtx = document.getElementById("pieChart");
@ -16,19 +15,21 @@ document.addEventListener("DOMContentLoaded", function () {
type: "pie", type: "pie",
data: { data: {
labels: ["Positif", "Negatif", "Netral"], labels: ["Positif", "Negatif", "Netral"],
datasets: [{ datasets: [
data: [68, 20, 12], {
}] data: [68, 20, 12],
},
],
}, },
options: { options: {
responsive: true, responsive: true,
maintainAspectRatio: false, maintainAspectRatio: false,
plugins: { plugins: {
legend: { legend: {
position: "bottom" position: "bottom",
} },
} },
} },
}); });
} }
@ -39,7 +40,12 @@ document.addEventListener("DOMContentLoaded", function () {
new Chart(barCtx, { new Chart(barCtx, {
type: "bar", type: "bar",
data: { data: {
labels: ["Papuma", "Watu Ulo", "Sukorambi", "Rembangan"], labels: [
"Papuma",
"Watu Ulo",
"Sukorambi",
"Air Terjun Tancak Tulis",
],
datasets: [ datasets: [
{ {
label: "Positif", label: "Positif",
@ -52,24 +58,23 @@ document.addEventListener("DOMContentLoaded", function () {
{ {
label: "Netral", label: "Netral",
data: [10, 5, 8, 4], data: [10, 5, 8, 4],
} },
] ],
}, },
options: { options: {
responsive: true, responsive: true,
maintainAspectRatio: false, maintainAspectRatio: false,
plugins: { plugins: {
legend: { legend: {
position: "bottom" position: "bottom",
} },
}, },
scales: { scales: {
y: { y: {
beginAtZero: true beginAtZero: true,
} },
} },
} },
}); });
} }
}); });

View File

@ -1,47 +1,141 @@
<x-guest-layout> <!DOCTYPE html>
<!-- Session Status --> <html lang="id">
<x-auth-session-status class="mb-4" :status="session('status')" /> <head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login - SENTARA</title>
<form method="POST" action="{{ route('login') }}"> @vite(['resources/css/app.css','resources/js/app.js'])
@csrf
<!-- Email Address --> </head>
<div>
<x-input-label for="email" :value="__('Email')" /> <body class="min-h-screen flex items-center justify-center bg-gray-100 px-6">
<x-text-input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email')" required autofocus autocomplete="username" />
<x-input-error :messages="$errors->get('email')" class="mt-2" /> <!-- WRAPPER CARD -->
<div class="w-full max-w-6xl bg-white rounded-3xl shadow-2xl overflow-hidden flex">
<!-- LEFT SIDE LOGIN -->
<div class="w-1/2 flex flex-col justify-center px-14 py-16 bg-white">
<h1 class="text-4xl font-bold text-blue-900 mb-2">
SENTARA
</h1>
<p class="text-gray-500 mb-10">
Login untuk mengakses Dashboard Analisis Sentimen Wisata Jember
</p>
<!-- Login Form -->
<form method="POST" action="{{ route('login') }}" class="space-y-6">
@csrf
<!-- Email -->
<div>
<label class="block text-gray-700 font-medium mb-2">
Email
</label>
<input type="email" name="email" required
class="w-full border border-gray-300 rounded-xl px-4 py-3
focus:ring-2 focus:ring-blue-400 focus:outline-none">
</div>
<!-- Password -->
<div>
<label class="block text-gray-700 font-medium mb-2">
Password
</label>
<input type="password" name="password" required
class="w-full border border-gray-300 rounded-xl px-4 py-3
focus:ring-2 focus:ring-blue-400 focus:outline-none">
</div>
<!-- Button -->
<button type="submit"
class="w-full bg-blue-700 hover:bg-blue-800 text-white py-3
rounded-xl font-semibold shadow-md transition">
Login
</button>
<!-- Register Link -->
<p class="text-sm text-gray-500 text-center">
Belum punya akun?
<a href="{{ route('register') }}"
class="text-blue-700 font-semibold hover:underline">
Register
</a>
</p>
</form>
</div> </div>
<!-- Password -->
<div class="mt-4">
<x-input-label for="password" :value="__('Password')" />
<x-text-input id="password" class="block mt-1 w-full" <!-- RIGHT SIDE SLIDER -->
type="password" <div class="w-1/2 relative overflow-hidden">
name="password"
required autocomplete="current-password" /> <!-- Slides -->
<img src="{{ asset('images/papuma.jpg') }}"
class="slide absolute inset-0 w-full h-full object-cover">
<img src="{{ asset('images/watuulo.jpeg') }}"
class="slide hidden absolute inset-0 w-full h-full object-cover">
<img src="{{ asset('images/botani.jpg') }}"
class="slide hidden absolute inset-0 w-full h-full object-cover">
<img src="{{ asset('images/tancak.jpeg') }}"
class="slide hidden absolute inset-0 w-full h-full object-cover">
<!-- Overlay -->
<div class="absolute inset-0 bg-black/40 flex items-center justify-center">
<h2 class="text-white text-3xl font-bold text-center px-10">
Eksplorasi Wisata Kabupaten Jember
</h2>
</div>
<!-- LEFT ARROW -->
<button onclick="prevSlide()"
class="absolute left-5 top-1/2 -translate-y-1/2
bg-white/40 hover:bg-white/70 text-white
px-4 py-2 rounded-full text-2xl font-bold transition">
</button>
<!-- RIGHT ARROW -->
<button onclick="nextSlide()"
class="absolute right-5 top-1/2 -translate-y-1/2
bg-white/40 hover:bg-white/70 text-white
px-4 py-2 rounded-full text-2xl font-bold transition">
</button>
<x-input-error :messages="$errors->get('password')" class="mt-2" />
</div> </div>
<!-- Remember Me --> </div>
<div class="block mt-4">
<label for="remember_me" class="inline-flex items-center">
<input id="remember_me" type="checkbox" class="rounded border-gray-300 text-indigo-600 shadow-sm focus:ring-indigo-500" name="remember">
<span class="ms-2 text-sm text-gray-600">{{ __('Remember me') }}</span>
</label>
</div>
<div class="flex items-center justify-end mt-4">
@if (Route::has('password.request'))
<a class="underline text-sm text-gray-600 hover:text-gray-900 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" href="{{ route('password.request') }}">
{{ __('Forgot your password?') }}
</a>
@endif
<x-primary-button class="ms-3"> <!-- SLIDER SCRIPT -->
{{ __('Log in') }} <script>
</x-primary-button> let index = 0;
</div> const slides = document.querySelectorAll(".slide");
</form>
</x-guest-layout> function showSlide(i) {
slides.forEach(slide => slide.classList.add("hidden"));
slides[i].classList.remove("hidden");
}
function nextSlide() {
index = (index + 1) % slides.length;
showSlide(index);
}
function prevSlide() {
index = (index - 1 + slides.length) % slides.length;
showSlide(index);
}
// // Auto Slide setiap 3 detik
// setInterval(nextSlide, 3000);
</script>
</body>
</html>

View File

@ -1,52 +1,158 @@
<x-guest-layout> <!DOCTYPE html>
<form method="POST" action="{{ route('register') }}"> <html lang="id">
@csrf <head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Register - SENTARA</title>
<!-- Name --> @vite(['resources/css/app.css','resources/js/app.js'])
<div> </head>
<x-input-label for="name" :value="__('Name')" />
<x-text-input id="name" class="block mt-1 w-full" type="text" name="name" :value="old('name')" required autofocus autocomplete="name" /> <body class="min-h-screen flex items-center justify-center bg-gray-100 px-6">
<x-input-error :messages="$errors->get('name')" class="mt-2" />
<!-- WRAPPER -->
<div class="w-full max-w-6xl bg-white rounded-3xl shadow-2xl overflow-hidden flex">
<!-- LEFT SIDE REGISTER -->
<div class="w-1/2 flex flex-col justify-center px-14 py-16 bg-white">
<h1 class="text-4xl font-bold text-blue-900 mb-2">
SENTARA
</h1>
<p class="text-gray-500 mb-10">
Buat akun untuk mengakses Dashboard Analisis Sentimen Wisata Jember
</p>
<!-- Register Form -->
<form method="POST" action="{{ route('register') }}" class="space-y-6">
@csrf
<!-- Name -->
<div>
<label class="block text-gray-700 font-medium mb-2">
Nama
</label>
<input type="text" name="name" required
class="w-full border border-gray-300 rounded-xl px-4 py-3
focus:ring-2 focus:ring-blue-400 focus:outline-none">
</div>
<!-- Email -->
<div>
<label class="block text-gray-700 font-medium mb-2">
Email
</label>
<input type="email" name="email" required
class="w-full border border-gray-300 rounded-xl px-4 py-3
focus:ring-2 focus:ring-blue-400 focus:outline-none">
</div>
<!-- Password -->
<div>
<label class="block text-gray-700 font-medium mb-2">
Password
</label>
<input type="password" name="password" required
class="w-full border border-gray-300 rounded-xl px-4 py-3
focus:ring-2 focus:ring-blue-400 focus:outline-none">
</div>
<!-- Confirm Password -->
<div>
<label class="block text-gray-700 font-medium mb-2">
Konfirmasi Password
</label>
<input type="password" name="password_confirmation" required
class="w-full border border-gray-300 rounded-xl px-4 py-3
focus:ring-2 focus:ring-blue-400 focus:outline-none">
</div>
<!-- Button -->
<button type="submit"
class="w-full bg-green-600 hover:bg-green-700 text-white py-3
rounded-xl font-semibold shadow-md transition">
Register
</button>
<!-- Login Link -->
<p class="text-sm text-gray-500 text-center">
Sudah punya akun?
<a href="{{ route('login') }}"
class="text-blue-700 font-semibold hover:underline">
Login
</a>
</p>
</form>
</div> </div>
<!-- Email Address -->
<div class="mt-4"> <!-- RIGHT SIDE SLIDER -->
<x-input-label for="email" :value="__('Email')" /> <div class="w-1/2 relative overflow-hidden">
<x-text-input id="email" class="block mt-1 w-full" type="email" name="email" :value="old('email')" required autocomplete="username" />
<x-input-error :messages="$errors->get('email')" class="mt-2" /> <!-- Slides -->
<img src="{{ asset('images/papuma.jpg') }}"
class="slide absolute inset-0 w-full h-full object-cover">
<img src="{{ asset('images/watuulo.jpeg') }}"
class="slide hidden absolute inset-0 w-full h-full object-cover">
<img src="{{ asset('images/botani.jpg') }}"
class="slide hidden absolute inset-0 w-full h-full object-cover">
<img src="{{ asset('images/tancak.jpeg') }}"
class="slide hidden absolute inset-0 w-full h-full object-cover">
<!-- Overlay -->
<div class="absolute inset-0 bg-black/40 flex items-center justify-center">
<h2 class="text-white text-3xl font-bold text-center px-10">
Jelajahi Keindahan Wisata Jember
</h2>
</div>
<!-- LEFT ARROW -->
<button onclick="prevSlide()"
class="absolute left-5 top-1/2 -translate-y-1/2
bg-white/40 hover:bg-white/70 text-white
px-4 py-2 rounded-full text-2xl font-bold transition">
</button>
<!-- RIGHT ARROW -->
<button onclick="nextSlide()"
class="absolute right-5 top-1/2 -translate-y-1/2
bg-white/40 hover:bg-white/70 text-white
px-4 py-2 rounded-full text-2xl font-bold transition">
</button>
</div> </div>
<!-- Password --> </div>
<div class="mt-4">
<x-input-label for="password" :value="__('Password')" />
<x-text-input id="password" class="block mt-1 w-full"
type="password"
name="password"
required autocomplete="new-password" />
<x-input-error :messages="$errors->get('password')" class="mt-2" /> <!-- SLIDER SCRIPT -->
</div> <script>
let index = 0;
const slides = document.querySelectorAll(".slide");
<!-- Confirm Password --> function showSlide(i) {
<div class="mt-4"> slides.forEach(slide => slide.classList.add("hidden"));
<x-input-label for="password_confirmation" :value="__('Confirm Password')" /> slides[i].classList.remove("hidden");
}
<x-text-input id="password_confirmation" class="block mt-1 w-full" function nextSlide() {
type="password" index = (index + 1) % slides.length;
name="password_confirmation" required autocomplete="new-password" /> showSlide(index);
}
<x-input-error :messages="$errors->get('password_confirmation')" class="mt-2" /> function prevSlide() {
</div> index = (index - 1 + slides.length) % slides.length;
showSlide(index);
}
<div class="flex items-center justify-end mt-4"> setInterval(nextSlide, 3000);
<a class="underline text-sm text-gray-600 hover:text-gray-900 rounded-md focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500" href="{{ route('login') }}"> </script>
{{ __('Already registered?') }}
</a>
<x-primary-button class="ms-4"> </body>
{{ __('Register') }} </html>
</x-primary-button>
</div>
</form>
</x-guest-layout>

View File

@ -17,7 +17,7 @@ class="bg-white border border-gray-300 text-sm rounded-lg px-4 py-2 shadow-sm
<option>Pantai Papuma</option> <option>Pantai Papuma</option>
<option>Pantai Watu Ulo</option> <option>Pantai Watu Ulo</option>
<option>Taman Botani Sukorambi</option> <option>Taman Botani Sukorambi</option>
<option>Rembangan</option> <option>Air Terjun Tancak Tulis</option>
</select> --> </select> -->
</div> </div>

View File

@ -17,7 +17,7 @@ class="bg-white border border-gray-300 text-sm rounded-lg px-4 py-2 shadow-sm
<option>Pantai Papuma</option> <option>Pantai Papuma</option>
<option>Pantai Watu Ulo</option> <option>Pantai Watu Ulo</option>
<option>Taman Botani Sukorambi</option> <option>Taman Botani Sukorambi</option>
<option>Rembangan</option> <option>Air Terjun Tancak Tulis</option>
</select> </select>
</div> </div>

View File

@ -28,9 +28,6 @@
Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit'); Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');
Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update'); Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update');
Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy'); Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');
// Route::get('/data-ulasan', [UlasanController::class, 'index'])->name('data.ulasan');
// Route::get('/scrape-ulasan', [UlasanController::class, 'scrape'])->name('scrape.ulasan');
// Route::post('/analisis-ulasan', [UlasanController::class, 'analisis'])->name('analisis.ulasan');
Route::get('/ulasan', [UlasanController::class, 'index'])->name('ulasan.index'); Route::get('/ulasan', [UlasanController::class, 'index'])->name('ulasan.index');
Route::post('/ulasan/ambil', [UlasanController::class, 'ambilData'])->name('ulasan.ambil'); Route::post('/ulasan/ambil', [UlasanController::class, 'ambilData'])->name('ulasan.ambil');
Route::post('/ulasan/analisis', [UlasanController::class, 'analisisData'])->name('ulasan.analisis'); Route::post('/ulasan/analisis', [UlasanController::class, 'analisisData'])->name('ulasan.analisis');
@ -38,6 +35,9 @@
->name('analisis.index'); ->name('analisis.index');
Route::get('/rekomendasi', [RekomendasiController::class, 'index']) Route::get('/rekomendasi', [RekomendasiController::class, 'index'])
->name('rekomendasi.index');; ->name('rekomendasi.index');;
Route::get('/', function () {
return redirect()->route('login');
});
}); });