APKKP / templates /index.html
indahPurnamaSarii
Initial deployment
f227f03
<!DOCTYPE html>
<html lang="id" class="scroll-smooth">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>BPVP Sorong - Website Satu Halaman</title>
<!-- Memuat Tailwind CSS -->
<script src="https://cdn.tailwindcss.com"></script>
<!-- Memuat Google Fonts: Inter -->
<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=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<!-- Memuat Font Awesome untuk Ikon -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css">
<!-- Konfigurasi warna kustom untuk Tailwind -->
<script>
tailwind.config = {
theme: {
extend: {
colors: {
'pastel-blue': '#334155', // Biru pastel
'pastel-pink': '#f3d6e4', // Pink pastel
'dark-text': '#334155',
},
fontFamily: {
sans: ['Inter', 'sans-serif'],
},
}
}
}
</script>
<!-- Menghubungkan ke file CSS eksternal -->
<link rel="stylesheet" href="../static/css/style.css">
</head>
<body class="bg-gray-50 font-sans text-dark-text">
<!-- BAGIAN HEADER -->
<header id="header" class="fixed top-0 left-0 right-0 z-50 transition-all duration-300 bg-white/50 backdrop-blur-sm shadow-md">
<nav class="container mx-auto px-6 py-4 flex justify-between items-center">
<!-- Logo di Kiri -->
<div class="flex items-center space-x-4">
<div class="relative h-14 w-14">
<img id="logo-dark" src="/static/Galeri/logo.png" alt="Logo BPVP Sorong" class="h-14 w-14 absolute top-0 left-0 transition-opacity duration-300 opacity-100">
<img id="logo-white" src="/static/Galeri/logo1.png" alt="Logo BPVP Sorong Putih" class="h-14 w-14 absolute top-0 left-0 transition-opacity duration-300 opacity-0">
</div>
<div>
<p class="text-sm font-medium text-dark-text tracking-wider">KEMENTERIAN KETENAGAKERJAAN</p>
<p class="text-2xl font-bold text-dark-text">BPVP SORONG</p>
</div>
</div>
<!-- Menu di Kanan -->
<ul class="hidden md:flex items-center space-x-8">
<li><a href="#beranda" class="text-dark-text hover:text-pastel-blue font-semibold">Beranda</a></li>
<li><a href="#profil" class="text-dark-text hover:text-pastel-blue font-semibold">Profil</a></li>
<li><a href="#pelatihan" class="text-dark-text hover:text-pastel-blue font-semibold">Pelatihan</a></li>
<li><a href="#kontak" class="text-dark-text hover:text-pastel-blue font-semibold">Kontak</a></li>
</ul>
<!-- Tombol Menu Mobile -->
<button id="mobile-menu-button" class="md:hidden text-dark-text">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16m-7 6h7" />
</svg>
</button>
</nav>
<!-- Menu Mobile Dropdown -->
<div id="mobile-menu" class="hidden md:hidden bg-white/90 backdrop-blur-sm rounded-b-xl overflow-hidden">
<a href="#beranda" class="block py-2 px-6 text-dark-text hover:bg-pastel-blue/50">Beranda</a>
<a href="#profil" class="block py-2 px-6 text-dark-text hover:bg-pastel-blue/50">Profil</a>
<a href="#pelatihan" class="block py-2 px-6 text-dark-text hover:bg-pastel-blue/50">Pelatihan</a>
<a href="#kontak" class="block py-2 px-6 text-dark-text hover:bg-pastel-blue/50">Kontak</a>
</div>
</header>
<main>
<!-- BAGIAN BERANDA (HERO SECTION DENGAN SLIDER) -->
<section id="beranda" class="relative w-full h-screen overflow-hidden">
<!-- Kontainer untuk gambar slider -->
<div id="slider-container" class="flex w-full h-full transition-transform duration-500 ease-in-out">
<!-- Gambar 1 -->
<div class="w-full h-full flex-shrink-0 bg-cover bg-center" style="background-image: url('/static/Galeri/hero1.jpg');">
<div class="w-full h-full bg-black/40 flex items-center justify-center">
<div class="text-center text-white p-4">
<h1 class="text-4xl md:text-6xl font-bold mb-4">Membangun Kompetensi Unggul</h1>
<p class="text-lg md:text-xl max-w-2xl">Mencetak tenaga kerja profesional dan berdaya saing tinggi di tanah Papua.</p>
</div>
</div>
</div>
<!-- Gambar 2 -->
<div class="w-full h-full flex-shrink-0 bg-cover bg-center" style="background-image: url('/static/Galeri/hero2.jpg');">
<div class="w-full h-full bg-black/40 flex items-center justify-center">
<div class="text-center text-white p-4">
<h1 class="text-4xl md:text-6xl font-bold mb-4">Didukung Fasilitas Modern</h1>
<p class="text-lg md:text-xl max-w-2xl">Peralatan dan ruang praktik standar industri untuk hasil belajar maksimal.</p>
</div>
</div>
</div>
<!-- Gambar 3 -->
<div class="w-full h-full flex-shrink-0 bg-cover bg-center" style="background-image: url('/static/Galeri/hero3.jpg');">
<div class="w-full h-full bg-black/40 flex items-center justify-center">
<div class="text-center text-white p-4">
<h1 class="text-4xl md:text-6xl font-bold mb-4">Lulusan Siap Kerja</h1>
<p class="text-lg md:text-xl max-w-2xl">Program pelatihan relevan dengan kebutuhan dunia usaha dan industri.</p>
</div>
</div>
</div>
</div>
<!-- Tombol Navigasi Slider -->
<button id="prevBtn" class="absolute top-1/2 left-4 transform -translate-y-1/2 bg-white/40 p-2 rounded-full hover:bg-white/80">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-dark-text" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7" /></svg>
</button>
<button id="nextBtn" class="absolute top-1/2 right-4 transform -translate-y-1/2 bg-white/40 p-2 rounded-full hover:bg-white/80">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-dark-text" fill="none" viewBox="0 0 24 24" stroke="currentColor"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" /></svg>
</button>
<!-- Indikator Dots -->
<div id="dots-container" class="absolute bottom-8 left-1/2 -translate-x-1/2 flex space-x-3"></div>
</section>
<!-- BAGIAN PROFIL -->
<section id="profil" class="py-24 bg-white">
<div class="container mx-auto px-6 grid md:grid-cols-2 gap-16 items-center">
<!-- Kolom Kiri: Teks -->
<div>
<h2 class="text-4xl font-bold mb-8 text-left">Tentang Kami</h2>
<div class="border-l-4 border-pastel-blue pl-6 space-y-6">
<p class="text-lg leading-relaxed">
Balai Pelatihan Vokasi dan Produktivitas Sorong atau di singkat BPVP Sorong didirikan berdasarkan Permenaker No 1 Tahun 2022 tentang Organisasi dan Tata Kerja Unit Pelaksana Teknis di Kementerian Ketenagakerjaan.
</p>
<p class="text-lg leading-relaxed">
Balai Latihan Kerja Sorong yang selanjutnya disebut BLK Sorong telah berubah nama menjadi Balai Pelatihan Vokasi dan Produktivitas Sorong atau di singkat BPVP Sorong yang merupakan Unit Pelaksana Teknis Pusat (UPTP) Bidang Pelatihan Vokasi dan Produktivitas berada di bawah dan bertanggung jawab kepada Direktorat Jenderal Pembinaan Pelatihan Vokasi dan Produktivitas.
</p>
</div>
</div>
<!-- Kolom Kanan: Gambar -->
<div class="relative h-96 md:h-auto md:min-h-[30rem]">
<img src="/static/Galeri/profil.png" alt="Gedung BPVP Sorong" class="absolute top-0 left-1/2 -translate-x-1/2 w-[90%] md:w-full max-w-lg h-auto rounded-xl shadow-2xl object-cover">
</div>
</div>
</section>
<!-- BAGIAN PELATIHAN -->
<section id="pelatihan" class="py-16 md:py-24 bg-gray-100">
<div class="container mx-auto px-6">
<h2 class="text-3xl md:text-4xl font-bold mb-12 text-center">Program Pelatihan Kami</h2>
<!-- Mengubah grid menjadi 2 kolom di HP dan menyesuaikan jarak (gap) -->
<div class="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4 md:gap-6">
<!-- Kartu Layanan: Teknik Las -->
<div class="bg-white p-4 rounded-lg shadow-md flex flex-col text-center items-center h-full">
<div class="flex-shrink-0 mb-3">
<svg xmlns="http://www.w3.org/2000/svg" class="h-10 w-10 text-blue-500" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z" />
</svg>
</div>
<div class="flex flex-col justify-between flex-grow">
<h3 class="text-sm font-bold text-dark-text leading-tight">PELATIHAN TEKNIK LAS</h3>
<p class="text-xs text-gray-500 mt-2">Jumlah Lulusan: 144</p>
</div>
</div>
<!-- Kartu Layanan: Teknik Listrik -->
<div class="bg-white p-4 rounded-lg shadow-md flex flex-col text-center items-center h-full">
<div class="flex-shrink-0 mb-3">
<svg xmlns="http://www.w3.org/2000/svg" class="h-10 w-10 text-yellow-500" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M13 10V3L4 14h7v7l9-11h-7z" />
</svg>
</div>
<div class="flex flex-col justify-between flex-grow">
<h3 class="text-sm font-bold text-dark-text leading-tight">PELATIHAN TEKNIK LISTRIK</h3>
<p class="text-xs text-gray-500 mt-2">Jumlah Lulusan: 144</p>
</div>
</div>
<!-- Kartu Layanan: Teknik Otomotif -->
<div class="bg-white p-4 rounded-lg shadow-md flex flex-col text-center items-center h-full">
<div class="flex-shrink-0 mb-3">
<svg xmlns="http://www.w3.org/2000/svg" class="h-10 w-10 text-cyan-500" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M9 17a2 2 0 11-4 0 2 2 0 014 0zM19 17a2 2 0 11-4 0 2 2 0 014 0z" />
<path stroke-linecap="round" stroke-linejoin="round" d="M13 16V6a1 1 0 00-1-1H4a1 1 0 00-1 1v10l2-2h8a1 1 0 001-1z" />
</svg>
</div>
<div class="flex flex-col justify-between flex-grow">
<h3 class="text-sm font-bold text-dark-text leading-tight">PELATIHAN TEKNIK OTOMOTIF</h3>
<p class="text-xs text-gray-500 mt-2">Jumlah Lulusan: 240</p>
</div>
</div>
<!-- Kartu Layanan: Teknik Manufaktur -->
<div class="bg-white p-4 rounded-lg shadow-md flex flex-col text-center items-center h-full">
<div class="flex-shrink-0 mb-3">
<svg xmlns="http://www.w3.org/2000/svg" class="h-10 w-10 text-green-500" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M10.325 4.317c.426-1.756 2.924-1.756 3.35 0a1.724 1.724 0 002.573 1.066c1.543-.94 3.31.826 2.37 2.37a1.724 1.724 0 001.065 2.572c1.756.426 1.756 2.924 0 3.35a1.724 1.724 0 00-1.066 2.573c.94 1.543-.826 3.31-2.37 2.37a1.724 1.724 0 00-2.572 1.065c-.426 1.756-2.924 1.756-3.35 0a1.724 1.724 0 00-2.573-1.066c-1.543.94-3.31-.826-2.37-2.37a1.724 1.724 0 00-1.065-2.572c-1.756-.426-1.756-2.924 0-3.35a1.724 1.724 0 001.066-2.573c-.94-1.543.826-3.31 2.37-2.37.996.608 2.296.07 2.572-1.065z" />
<path stroke-linecap="round" stroke-linejoin="round" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
</div>
<div class="flex flex-col justify-between flex-grow">
<h3 class="text-sm font-bold text-dark-text leading-tight">PELATIHAN TEKNIK MANUFAKTUR</h3>
<p class="text-xs text-gray-500 mt-2">Jumlah Lulusan: 64</p>
</div>
</div>
<!-- Kartu Layanan: Teknik Elektronika -->
<div class="bg-white p-4 rounded-lg shadow-md flex flex-col text-center items-center h-full">
<div class="flex-shrink-0 mb-3">
<svg xmlns="http://www.w3.org/2000/svg" class="h-10 w-10 text-indigo-500" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M12 6V4m0 2a2 2 0 100 4m0-4a2 2 0 110 4m-6 8a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4m6 6v10m6-2a2 2 0 100-4m0 4a2 2 0 110-4m0 4v2m0-6V4" />
</svg>
</div>
<div class="flex flex-col justify-between flex-grow">
<h3 class="text-sm font-bold text-dark-text leading-tight">PELATIHAN TEKNIK ELEKTRONIKA</h3>
<p class="text-xs text-gray-500 mt-2">Jumlah Lulusan: 112</p>
</div>
</div>
<!-- Kartu Layanan: Kejuruan TIK -->
<div class="bg-white p-4 rounded-lg shadow-md flex flex-col text-center items-center h-full">
<div class="flex-shrink-0 mb-3">
<svg xmlns="http://www.w3.org/2000/svg" class="h-10 w-10 text-orange-500" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
</svg>
</div>
<div class="flex flex-col justify-between flex-grow">
<h3 class="text-sm font-bold text-dark-text leading-tight">PELATIHAN KEJURUAN TIK</h3>
<p class="text-xs text-gray-500 mt-2">Jumlah Lulusan: 208</p>
</div>
</div>
<!-- Kartu Layanan: Kejuruan Processing -->
<div class="bg-white p-4 rounded-lg shadow-md flex flex-col text-center items-center h-full">
<div class="flex-shrink-0 mb-3">
<svg xmlns="http://www.w3.org/2000/svg" class="h-10 w-10 text-blue-500" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M19 21V5a2 2 0 00-2-2H7a2 2 0 00-2 2v16m14 0h2m-2 0h-5m-9 0H3m2 0h5M9 7h1m-1 4h1m4-4h1m-1 4h1m-5 10v-5a1 1 0 011-1h2a1 1 0 011 1v5m-4 0h4" />
</svg>
</div>
<div class="flex flex-col justify-between flex-grow">
<h3 class="text-sm font-bold text-dark-text leading-tight">PELATIHAN KEJURUAN PROCESSING</h3>
<p class="text-xs text-gray-500 mt-2">Jumlah Lulusan: 432</p>
</div>
</div>
<!-- Kartu Layanan: Pariwisata -->
<div class="bg-white p-4 rounded-lg shadow-md flex flex-col text-center items-center h-full">
<div class="flex-shrink-0 mb-3">
<svg xmlns="http://www.w3.org/2000/svg" class="h-10 w-10 text-yellow-500" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M3.055 11H5a2 2 0 012 2v1a2 2 0 002 2h8a2 2 0 002-2v-1a2 2 0 012-2h1.945M7.88 15.12A3 3 0 015.33 12.033m13.34 0A3 3 0 0118.12 15.12M12 12a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
</div>
<div class="flex flex-col justify-between flex-grow">
<h3 class="text-sm font-bold text-dark-text leading-tight">PELATIHAN KEJURUAN PARIWISATA</h3>
<p class="text-xs text-gray-500 mt-2">Jumlah Lulusan: 96</p>
</div>
</div>
<!-- Kartu Layanan: Bangunan -->
<div class="bg-white p-4 rounded-lg shadow-md flex flex-col text-center items-center h-full">
<div class="flex-shrink-0 mb-3">
<svg xmlns="http://www.w3.org/2000/svg" class="h-10 w-10 text-cyan-500" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-6 0a1 1 0 001-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 001 1m-6 0h6" />
</svg>
</div>
<div class="flex flex-col justify-between flex-grow">
<h3 class="text-sm font-bold text-dark-text leading-tight">PELATIHAN KEJURUAN BANGUNAN</h3>
<p class="text-xs text-gray-500 mt-2">Jumlah Lulusan: 176</p>
</div>
</div>
<!-- Kartu Layanan: Tata Rias -->
<div class="bg-white p-4 rounded-lg shadow-md flex flex-col text-center items-center h-full">
<div class="flex-shrink-0 mb-3">
<svg xmlns="http://www.w3.org/2000/svg" class="h-10 w-10 text-blue-500" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M14.121 15.536c-1.171 1.952-3.07 1.952-4.242 0-1.172-1.953-1.172-5.119 0-7.072 1.171-1.952 3.07-1.952 4.242 0 1.172 1.953 1.172 5.119 0 7.072z" />
<path stroke-linecap="round" stroke-linejoin="round" d="M12 10.5v5.25m-2.25-.916a2.25 2.25 0 00-1.99 2.185 2.25 2.25 0 002.25 2.25 2.25 2.25 0 002.25-2.25 2.25 2.25 0 00-1.423-2.065" />
</svg>
</div>
<div class="flex flex-col justify-between flex-grow">
<h3 class="text-sm font-bold text-dark-text leading-tight">PELATIHAN KEJURUAN TATA RIAS</h3>
<p class="text-xs text-gray-500 mt-2">Jumlah Lulusan: 160</p>
</div>
</div>
<!-- Kartu Layanan: Bisnis & Manajemen -->
<div class="bg-white p-4 rounded-lg shadow-md flex flex-col text-center items-center h-full">
<div class="flex-shrink-0 mb-3">
<svg xmlns="http://www.w3.org/2000/svg" class="h-10 w-10 text-yellow-500" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M21 13.255A23.931 23.931 0 0112 15c-3.183 0-6.22-.62-9-1.745M16 6V4a2 2 0 00-2-2h-4a2 2 0 00-2 2v2m4 6h.01M5 20h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
</svg>
</div>
<div class="flex flex-col justify-between flex-grow">
<h3 class="text-sm font-bold text-dark-text leading-tight">PELATIHAN BISNIS DAN MANAJEMEN</h3>
<p class="text-xs text-gray-500 mt-2">Jumlah Lulusan: 160</p>
</div>
</div>
<!-- Kartu Layanan: Fashion Technology -->
<div class="bg-white p-4 rounded-lg shadow-md flex flex-col text-center items-center h-full">
<div class="flex-shrink-0 mb-3">
<svg xmlns="http://www.w3.org/2000/svg" class="h-10 w-10 text-cyan-500" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
<path stroke-linecap="round" stroke-linejoin="round" d="M15 10l4.553-2.276A1 1 0 0121 8.618v6.764a1 1 0 01-1.447.894L15 14M5 18h8a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v8a2 2 0 002 2z" />
</svg>
</div>
<div class="flex flex-col justify-between flex-grow">
<h3 class="text-sm font-bold text-dark-text leading-tight">PELATIHAN FASHION TECHNOLOGY</h3>
<p class="text-xs text-gray-500 mt-2">Jumlah Lulusan: 256</p>
</div>
</div>
</div>
</div>
</section>
<section id="kontak" class="py-24 bg-pastel-blue">
<div class="container mx-auto px-6 grid md:grid-cols-2 gap-16 items-center">
<!-- Kolom Kiri: Info Kontak -->
<div class="text-white text-center md:text-left">
<h2 class="text-4xl font-bold mb-6">Kunjungi Kami</h2>
<p class="text-lg mb-8 leading-relaxed">
Punya pertanyaan, saran, atau ingin mendaftar program pelatihan kami? Jangan ragu untuk menghubungi kami atau datang langsung ke alamat kami yang tertera di peta.
</p>
<div class="bg-white/20 p-6 rounded-xl inline-block">
<p class="mb-2"><strong>Alamat:</strong> Jl. Basuki Rahmat, Sawagumu, Kota Sorong, Papua Barat Daya - 98412</p>
<p class="mb-2"><strong>Email:</strong> blksorong@kemnaker.go.id</p>
<p><strong>Telepon:</strong> (0951) 324776</p>
</div>
</div>
<!-- Kolom Kanan: Peta Lokasi -->
<div class="w-full h-96 md:h-full rounded-xl overflow-hidden shadow-lg">
<iframe
src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d3989.287893325603!2d131.2902648749652!3d-0.9015993990428178!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x2d595469440307cb%3A0x7055c82432857d42!2sBalai%20Latihan%20Kerja%20Industri%20Sorong!5e0!3m2!1sid!2sid!4v1725944519491!5m2!1sid!2sid"
width="100%"
height="100%"
style="border:0;"
allowfullscreen=""
loading="lazy"
referrerpolicy="no-referrer-when-downgrade">
</iframe>
</div>
</div>
</section>
</main>
<!-- ICON BANTUAN Pojok Kanan Bawah -->
<a href="#" id="open-chat-btn" class="fixed bottom-5 right-5 bg-pastel-blue p-3 rounded-full shadow-lg hover:bg-blue-500 transition-transform hover:scale-110">
<svg xmlns="http://www.w3.org/2000/svg" class="h-6 w-6 text-white" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8.228 9c.549-1.165 2.03-2 3.772-2 2.21 0 4 1.343 4 3 0 1.4-1.278 2.575-3.006 2.907-.542.104-.994.546-.994 1.093m0 3h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
</a>
<!-- CHATBOT MODAL -->
<div id="chat-modal" class="chat-modal-overlay">
<div class="chat-modal-content">
<div id="chatbot-widget-container">
<div class="chatbot-container" id="main-container">
<div id="chatbot-header">
<button id="end-chat-button" title="Akhiri & Hapus Sesi"><i class="fas fa-times"></i></button>
</div>
<div id="chatbot">
<div id="conversation"></div>
<form id="input-form">
<div class="message-container">
<input id="input-field" type="text" placeholder="Ketik pertanyaan Anda...">
<button id="submit-button" type="submit"><i class="fas fa-paper-plane"></i></button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<!-- CUSTOM ALERT MODAL -->
<div id="custom-alert-modal" class="modal">
<div class="modal-content">
<p id="custom-alert-message"></p>
<button id="custom-alert-ok">OK</button>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
// --- FUNGSI UNTUK SLIDER GAMBAR ---
const sliderContainer = document.getElementById('slider-container');
if (sliderContainer) {
const prevBtn = document.getElementById('prevBtn');
const nextBtn = document.getElementById('nextBtn');
const dotsContainer = document.getElementById('dots-container');
const images = sliderContainer.children;
const totalImages = images.length;
let currentIndex = 0;
let slideInterval;
for (let i = 0; i < totalImages; i++) {
const dot = document.createElement('div');
dot.classList.add('w-3', 'h-3', 'rounded-full', 'cursor-pointer', 'bg-white/50', 'transition-colors');
dot.addEventListener('click', () => goToSlide(i));
dotsContainer.appendChild(dot);
}
const dots = dotsContainer.children;
function updateSlider() {
sliderContainer.style.transform = `translateX(-${currentIndex * 100}%)`;
Array.from(dots).forEach((dot, i) => {
dot.classList.toggle('bg-white', i === currentIndex);
dot.classList.toggle('bg-white/50', i !== currentIndex);
});
}
function goToSlide(index) {
currentIndex = index;
updateSlider();
resetInterval();
}
function resetInterval() {
clearInterval(slideInterval);
slideInterval = setInterval(() => {
currentIndex = (currentIndex + 1) % totalImages;
updateSlider();
}, 5000);
}
nextBtn.addEventListener('click', () => {
currentIndex = (currentIndex + 1) % totalImages;
updateSlider();
resetInterval();
});
prevBtn.addEventListener('click', () => {
currentIndex = (currentIndex - 1 + totalImages) % totalImages;
updateSlider();
resetInterval();
});
updateSlider();
resetInterval();
}
// --- FUNGSI UNTUK MENU MOBILE ---
const mobileMenuButton = document.getElementById('mobile-menu-button');
const mobileMenu = document.getElementById('mobile-menu');
if(mobileMenuButton && mobileMenu){
mobileMenuButton.addEventListener('click', () => {
mobileMenu.classList.toggle('hidden');
});
mobileMenu.querySelectorAll('a').forEach(link => {
link.addEventListener('click', () => {
mobileMenu.classList.add('hidden');
});
});
}
// --- FUNGSI UNTUK CHATBOT ---
const openChatBtn = document.getElementById('open-chat-btn');
const chatModal = document.getElementById('chat-modal');
let isHistoryLoaded = false;
const conversation = document.getElementById('conversation');
const inputForm = document.getElementById('input-form');
const inputField = document.getElementById('input-field');
const endChatBtn = document.getElementById('end-chat-button');
const customAlertModal = document.getElementById('custom-alert-modal');
const customAlertMessage = document.getElementById('custom-alert-message');
const customAlertOk = document.getElementById('custom-alert-ok');
const API_BASE_URL = 'http://127.0.0.1:5000';
if (openChatBtn) {
openChatBtn.addEventListener('click', (e) => {
e.preventDefault();
chatModal.style.display = 'flex';
if (!isHistoryLoaded) {
showInitialMessage();
isHistoryLoaded = true;
}
});
}
const getCurrentTime = () => new Date().toLocaleTimeString('id-ID', { hour: '2-digit', minute: '2-digit' });
const showAlert = (message, onOk) => {
if (customAlertMessage) customAlertMessage.textContent = message;
if (customAlertModal) customAlertModal.style.display = 'flex';
// Clone and replace the OK button to remove old event listeners
const newOkButton = customAlertOk.cloneNode(true);
customAlertOk.parentNode.replaceChild(newOkButton, customAlertOk);
// Add the new listener
newOkButton.addEventListener('click', () => {
if (customAlertModal) customAlertModal.style.display = 'none';
if (onOk) onOk();
}, { once: true });
};
// --- FUNGSI createMessage DENGAN FORMATTING YANG LEBIH BAIK ---
const createMessage = (content, sender, time = getCurrentTime()) => {
const message = document.createElement('div');
message.classList.add('chatbot-message', sender);
const contentDiv = document.createElement('div');
contentDiv.classList.add('chatbot-text');
// --- Improved Markdown-like Parser ---
// 1. First, process inline formatting like **bold** across the entire content.
// This is more robust than processing line-by-line.
// The regex /\*\*(.*?)\*\*/g correctly finds text surrounded by double asterisks.
let processedContent = String(content).replace(/\*\*(.*?)\*\*/g, '<strong>$1</strong>');
// 2. Normalize newlines. Server responses might have escaped newlines ('\\n').
// We replace them with actual newline characters ('\n') for consistent splitting.
processedContent = processedContent.replace(/\\n/g, '\n');
const lines = processedContent.split('\n');
let currentList = null;
let listType = null; // Can be 'ul' or 'ol'
// Helper function to append the current list to the main content div.
// This avoids duplicating code and ensures any open list is added before a new element.
const appendCurrentList = () => {
if (currentList) {
contentDiv.appendChild(currentList);
currentList = null;
listType = null;
}
};
lines.forEach(line => {
const trimmedLine = line.trim();
// ### for Subheadings (h3)
if (trimmedLine.startsWith('### ')) {
appendCurrentList();
const h3 = document.createElement('h3');
// The text already has <strong> tags from the initial processing.
h3.innerHTML = trimmedLine.substring(4);
h3.className = 'text-lg font-semibold mt-4 mb-2';
contentDiv.appendChild(h3);
}
// * or - for Unordered Lists (ul)
else if (trimmedLine.startsWith('* ') || trimmedLine.startsWith('- ')) {
if (listType !== 'ul') {
appendCurrentList();
currentList = document.createElement('ul');
// Using Tailwind classes for clean styling.
currentList.className = 'list-disc list-inside my-2 pl-4 space-y-1';
listType = 'ul';
}
const li = document.createElement('li');
li.innerHTML = trimmedLine.substring(2);
currentList.appendChild(li);
}
// 1., 2., etc. for Ordered Lists (ol)
// The regex /^\d+\.\s/ matches lines starting with a number, a dot, and a space.
else if (trimmedLine.match(/^\d+\.\s/)) {
if (listType !== 'ol') {
appendCurrentList();
currentList = document.createElement('ol');
currentList.className = 'list-decimal list-inside my-2 pl-4 space-y-1';
listType = 'ol';
}
const li = document.createElement('li');
li.innerHTML = trimmedLine.replace(/^\d+\.\s/, '');
currentList.appendChild(li);
}
// Any other non-empty line is a paragraph
else if (trimmedLine) {
appendCurrentList();
const p = document.createElement('p');
p.innerHTML = trimmedLine;
p.className = 'mb-3 last:mb-0'; // Increased margin for better paragraph separation
contentDiv.appendChild(p);
} else {
// An empty line signifies a paragraph break, so we just end any current list.
appendCurrentList();
}
});
// After the loop, append the last list if it exists.
appendCurrentList();
message.appendChild(contentDiv);
const footer = document.createElement('div');
footer.className = 'message-footer';
footer.innerHTML = `<span class="time">${time}</span>`;
message.appendChild(footer);
return message;
};
const addMessageToConversation = (message) => {
if (conversation) {
conversation.appendChild(message);
conversation.scrollTop = conversation.scrollHeight;
}
};
const showInitialMessage = async () => {
try {
const response = await fetch(`${API_BASE_URL}/load_history`);
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
const history = await response.json();
if (history && history.length > 0) {
history.forEach(item => {
const sender = item.sender === 'user' ? 'user-message' : 'chatbot';
addMessageToConversation(createMessage(item.message, sender));
});
} else {
addMessageToConversation(createMessage('Halo! Ada yang bisa saya bantu terkait dengan informasi di BPVP Sorong?', 'chatbot'));
}
} catch (error) {
console.error("Could not load history:", error);
addMessageToConversation(createMessage('Halo! Ada yang bisa saya bantu terkait dengan informasi di BPVP Sorong?', 'chatbot'));
}
};
if (inputForm) {
inputForm.addEventListener('submit', async (event) => {
event.preventDefault();
const input = inputField.value.trim();
if (!input) return;
inputField.value = '';
addMessageToConversation(createMessage(input, 'user-message'));
const typingMessage = createMessage('Sedang berpikir...', 'chatbot');
addMessageToConversation(typingMessage);
try {
const response = await fetch(`${API_BASE_URL}/get?msg=${encodeURIComponent(input)}`);
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
const result = await response.json();
typingMessage.remove();
addMessageToConversation(createMessage(result.error || result, 'chatbot'));
} catch (error) {
console.error('Error fetching AI response:', error);
typingMessage.remove();
const errorMessage = "Aduh, sepertinya ada kendala. Silahkan mencoba beberapa saat lagi.";
addMessageToConversation(createMessage(errorMessage, 'chatbot'));
}
});
}
const clearChatAction = async () => {
try {
await fetch(`${API_BASE_URL}/clear_history`, { method: 'POST' });
if (conversation) conversation.innerHTML = '';
if (chatModal) chatModal.style.display = 'none';
isHistoryLoaded = false;
} catch (error) {
showAlert("Gagal menghapus riwayat di server.");
}
};
if (endChatBtn) {
endChatBtn.addEventListener('click', () => {
showAlert("Anda yakin ingin mengakhiri sesi ini? Riwayat percakapan akan dihapus.", clearChatAction);
});
}
});
</script>
</body>
</html>