feat(tapops): add css modules, js scripts, and viewer page

This commit is contained in:
Dodo
2026-06-04 14:40:40 +07:00
parent 0ebc25809b
commit c9d96eabe4
16 changed files with 4379 additions and 302 deletions
+220 -301
View File
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!DOCTYPE html>
<html lang="id" class="scroll-smooth">
<head>
<meta charset="UTF-8">
@@ -8,290 +8,18 @@
<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+Condensed:ital,wght@0,100..900;1,100..900&family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
/* ===== MOBILE NAV STABILITY FIX =====
Prevents logo bar from collapsing/shifting on Android when
address bar hides/shows and triggers viewport reflow.
===================================== */
#nav-wrapper {
position: fixed !important;
top: 0;
left: 0;
right: 0;
z-index: 50;
backface-visibility: hidden;
-webkit-backface-visibility: hidden;
will-change: box-shadow;
}
#nav-wrapper>div:first-child {
transform: translateZ(0);
-webkit-transform: translateZ(0);
}
@media (max-width: 1023px) {
#nav-wrapper>div:first-child {
min-height: 0 !important;
max-height: none;
}
}
#pengumuman-bar {
z-index: 40;
}
#pengumuman-bar.is-stuck {
position: fixed;
left: 0;
right: 0;
z-index: 40;
}
@media (prefers-reduced-motion: reduce) {
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
}
}
/* Skip Link Styling */
.skip-link {
position: absolute;
top: -40px;
left: 0;
background: #003150;
color: white;
padding: 8px 16px;
z-index: 100;
transition: top 0.3s;
}
.skip-link:focus {
top: 0;
}
/* Focus visible for better keyboard navigation */
:focus-visible {
outline: 3px solid #feb401;
outline-offset: 2px;
}
/* Mega Menu Styles */
.hero-pagination .swiper-pagination-bullet {
width: 8px;
height: 8px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.4);
display: inline-block;
margin: 0 4px;
cursor: pointer;
transition: all 0.3s ease;
}
.hero-pagination .swiper-pagination-bullet-active {
background: rgba(255, 255, 255, 1);
width: 24px;
border-radius: 4px;
}
.mega-panel {
opacity: 0;
visibility: hidden;
transition: opacity 0.2s ease, visibility 0.2s ease;
position: absolute;
top: 100%;
left: 0;
right: 0;
}
.mega-panel.active {
opacity: 1;
visibility: visible;
}
/* Overlay transition */
#mega-overlay {
opacity: 0;
visibility: hidden;
transition: opacity 0.2s ease, visibility 0.2s ease;
}
#mega-overlay.active {
opacity: 1;
visibility: visible;
}
.mega-link-card {
display: flex;
align-items: flex-start;
gap: 1rem;
padding: 1rem;
border-radius: 0.75rem;
border: 1px solid #e2e8f0;
background: white;
transition: all 0.2s ease;
}
.mega-link-card:hover {
border-color: #3b82f6;
box-shadow: 0 4px 12px rgba(59, 130, 246, 0.15);
transform: translateY(-2px);
}
.mega-link-icon {
width: 2.5rem;
height: 2.5rem;
border-radius: 0.5rem;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
transition: all 0.2s ease;
}
.nav-menu-btn.active {
background: rgba(255, 255, 255, 0.9);
color: #1e40af;
}
.nav-menu-btn:hover {
background: rgba(255, 255, 255, 0.8);
}
/* Mega menu positioning - no gap */
#main-nav {
position: relative;
}
#mega-menu-container {
position: absolute;
top: 100%;
left: 0;
right: 0;
pointer-events: none;
}
#mega-menu-container .mega-panel {
pointer-events: auto;
}
/* Keep pointer bridge under nav to prevent hover loss */
.nav-menu-item {
position: relative;
}
.nav-menu-item::after {
content: '';
position: absolute;
bottom: -12px;
left: 0;
right: 0;
height: 12px;
}
/* ===== Luco Chatbot Animations ===== */
@keyframes slideInRight {
from {
transform: translateX(100px);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
@keyframes fadeInUp {
from {
transform: translateY(10px);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
@keyframes lucoPulse {
0%,
100% {
transform: scale(1);
}
50% {
transform: scale(1.05);
}
}
#luco-container {
animation: slideInRight 0.5s ease-out forwards;
}
#luco-bubble {
animation: fadeInUp 0.3s ease-out forwards;
width: min(18rem, calc(100vw - 2rem));
}
#luco-btn {
animation: lucoPulse 2s ease-in-out infinite;
}
#luco-btn:hover {
animation: none;
}
/* Typing indicator */
.typing-indicator span {
display: inline-block;
animation: bounce 1.4s infinite ease-in-out;
}
.typing-indicator span:nth-child(1) {
animation-delay: 0s;
}
.typing-indicator span:nth-child(2) {
animation-delay: 0.2s;
}
.typing-indicator span:nth-child(3) {
animation-delay: 0.4s;
}
@keyframes bounce {
0%,
80%,
100% {
transform: translateY(0);
}
40% {
transform: translateY(-6px);
}
}
/* Luco speech bubble arrow */
#luco-bubble .bubble-arrow {
position: absolute;
right: 24px;
bottom: -6px;
width: 12px;
height: 12px;
background: white;
transform: rotate(45deg);
border-right: 1px solid #e2e8f0;
border-bottom: 1px solid #e2e8f0;
}
</style>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"
integrity="sha384-iw3OoTErCYJJB9mCa8LNS2hbsQ7M3C0EpIsO/H5+EGAkPGc6rk+V8i04oW/K5xq0"
crossorigin="anonymous">
<!-- Navigation styles (extracted from inline) -->
<link rel="stylesheet" href="css/nav.css">
<!-- Document section styles -->
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/base-scoped.css">
<link rel="stylesheet" href="css/hero.css">
<link rel="stylesheet" href="css/documents.css">
<link rel="stylesheet" href="css/sections.css">
<link rel="stylesheet" href="css/responsive.css">
</head>
<body class="text-slate-800 antialiased bg-white selection:bg-untan-yellow selection:text-black">
@@ -345,7 +73,7 @@
<button
class="w-8 h-8 flex items-center justify-center rounded-sm hover:bg-white/10 transition-colors"
aria-label="Pengaturan aksesibilitas"
onclick="const p=document.getElementById('access-panel'); if (p) { p.classList.toggle('hidden'); p.classList.toggle('flex'); }">
onclick="var p=document.getElementById('access-panel'); if (p) { p.classList.toggle('hidden'); p.classList.toggle('flex'); }">
<i class="fas fa-universal-access" aria-hidden="true"></i>
</button>
<button
@@ -1013,7 +741,7 @@
<button
class="w-8 h-8 rounded-sm bg-white/10 hover:bg-white/20 flex items-center justify-center text-white transition-colors"
aria-label="Pengaturan aksesibilitas"
onclick="const p=document.getElementById('access-panel'); if (p) { p.classList.toggle('hidden'); p.classList.toggle('flex'); }">
onclick="var p=document.getElementById('access-panel'); if (p) { p.classList.toggle('hidden'); p.classList.toggle('flex'); }">
<i class="fas fa-universal-access" aria-hidden="true"></i>
</button>
</div>
@@ -1139,22 +867,211 @@
</div>
</div>
<main id="main-content" class="pt-[88px] lg:pt-[160px] min-h-screen bg-white">
<div class="container mx-auto px-4 lg:px-8 py-12">
<div class="mb-8 pb-8 border-b border-slate-200">
<span class="bg-untan-yellow text-slate-900 text-[10px] font-bold uppercase tracking-widest px-2 py-0.5 inline-block mb-3">Tugas Halaman Statis</span>
<h1 class="text-3xl lg:text-4xl font-bold text-slate-900 mb-2">Berkas Penting</h1>
<p class="text-slate-500 text-sm">Kelompok 09 &mdash; TAPOPS &nbsp;&middot;&nbsp; Informatika UNTAN 2026</p>
</div>
<div id="assignment-body" class="prose prose-slate max-w-none">
<!-- ================= START: BAGIAN YANG DIEDIT KELOMPOK ================= -->
<p>Tulis konten halaman kelompok di sini.</p>
<h3>Subjudul</h3>
<p>Gunakan paragraf, list, tabel, gambar, dan elemen konten lainnya.</p>
<!-- ================= END: BAGIAN YANG DIEDIT KELOMPOK ================= -->
<main id="main-content" class="tapops-doc-root pt-[72px] lg:pt-[160px]">
<!-- ═══════════════════════════════════════
HERO
═══════════════════════════════════════ -->
<section class="research-hero immersive-hero">
<div class="hero-container-centered">
<span class="hero-kicker" data-tp-i18n="hero_kicker">Digital Administrative Hub</span>
<h2 class="hero-title" data-tp-i18n="hero_title">Administrasi Akademik Digital</h2>
<p class="hero-tagline" data-tp-i18n="hero_tagline">
Satu pintu menuju semua dokumen penting. Akses terpusat menuju repositori dokumen akademik Program Studi
Informatika Universitas Tanjungpura untuk mahasiswa dan staf.
</p>
<div class="hero-actions">
<a href="#repository" class="btn-join"><span data-tp-i18n="hero_btn_search">Cari Dokumen</span> <i class="fas fa-search"></i></a>
<a href="#procedures" class="btn-outline"><span data-tp-i18n="hero_btn_flow">ALUR PENGAJUAN</span> <i class="fas fa-chevron-right"></i></a>
</div>
</div>
</main>
<div class="hero-floating-stat-bar">
<div class="stat-bar-item">
<span class="stat-bar-value" id="stat-active-value"></span>
<span class="stat-bar-label" data-tp-i18n="stat_active">Dokumen Aktif</span>
</div>
<div class="stat-bar-divider"></div>
<div class="stat-bar-item">
<span class="stat-bar-value" id="stat-updates-value"></span>
<span class="stat-bar-label" data-tp-i18n="stat_updates">Pembaruan Terbaru</span>
</div>
</div>
</section>
<!-- ═══════════════════════════════════════
DOCUMENT REPOSITORY
═══════════════════════════════════════ -->
<section id="repository" class="documents-section">
<div class="repo-dashboard-container">
<!-- Sidebar Filter -->
<aside class="repo-sidebar">
<div class="sidebar-sticky">
<h3 class="sidebar-title" data-tp-i18n="sidebar_category">KATEGORI BERKAS</h3>
<div class="document-filter-wrapper" id="tag-filter-wrapper">
<!-- Filter buttons are built dynamically from API tags by main.js -->
<div class="filter-skeleton">
<div class="filter-skeleton-item"></div>
<div class="filter-skeleton-item short"></div>
<div class="filter-skeleton-item"></div>
<div class="filter-skeleton-item short"></div>
</div>
</div>
<div class="sidebar-info-box">
<i class="fas fa-info-circle"></i>
<p data-tp-i18n="sidebar_info">Pastikan mengunduh versi terbaru untuk menjamin validitas berkas pengajuan.</p>
</div>
</div>
</aside>
<!-- Main Document Area (div, not main — only one <main> per page) -->
<div class="repo-main-content">
<div class="repo-content-header">
<div class="header-title-area">
<h2 class="section-title" data-tp-i18n="repo_title">Eksplorasi Dokumen Prodi</h2>
<p class="section-subtitle" data-tp-i18n="repo_subtitle">Temukan berkas administrasi dan akademik terbaru Program Studi
Informatika.</p>
</div>
<div class="repo-controls">
<div class="search-container">
<div class="search-input-group">
<i class="fas fa-search search-icon"></i>
<input type="text" id="doc-search" data-tp-i18n-placeholder="search_ph" placeholder="Cari nama berkas atau kata kunci...">
</div>
</div>
<div class="filter-controls">
<div class="control-group date-range-group">
<span class="control-label" data-tp-i18n="label_period">Periode Unggahan</span>
<div class="date-range-inputs">
<div class="input-wrapper">
<input type="date" id="date-start" placeholder="Mulai">
</div>
<span class="range-divider" data-tp-i18n="range_divider">s/d</span>
<div class="input-wrapper">
<input type="date" id="date-end" placeholder="Selesai">
</div>
</div>
</div>
<div class="control-group">
<span class="control-label" data-tp-i18n="label_sort">Urutkan</span>
<div id="sort-filter-wrapper"></div>
</div>
<div class="control-group mobile-category-control-group">
<span class="control-label" data-tp-i18n="sidebar_category">Kategori Berkas</span>
<div id="mobile-tag-filter-wrapper"></div>
</div>
</div>
</div>
</div>
<div class="document-grid" id="document-grid">
<div class="repo-loading" style="grid-column: 1 / -1; text-align: center; padding: 60px 20px; color: var(--primary-blue); font-weight: 700; font-size: 1.1rem; display: flex; flex-direction: column; align-items: center; gap: 15px;">
<i class="fas fa-circle-notch fa-spin" style="font-size: 2.5rem; color: var(--secondary-gold);"></i>
<span data-tp-i18n="loading">Menghubungkan ke repositori berkas...</span>
</div>
</div>
</div>
</div>
</section>
<!-- ═══════════════════════════════════════
PROCEDURES
═══════════════════════════════════════ -->
<section id="procedures" class="journey-section">
<div class="journey-container">
<div class="section-header centered">
<h2 class="section-title" data-tp-i18n="proc_title">Tata Cara Pengajuan Berkas</h2>
<span class="section-tag" data-tp-i18n="proc_tag">Alur Pengajuan</span>
</div>
<div class="process-flow-wrapper">
<!-- Step 01 -->
<div class="process-step">
<div class="step-visual">
<div class="step-icon-box"><i class="fas fa-file-download"></i></div>
<div class="step-number-badge">01</div>
<div class="step-connector"></div>
</div>
<div class="step-content">
<h3 data-tp-i18n="proc_s1_h">Unduh Formulir</h3>
<p data-tp-i18n="proc_s1_p">Pilih kategori pengajuan Anda, lalu unduh formulir versi terbaru. Pastikan kode revisi pada formulir sesuai dengan yang tertera di halaman ini.</p>
</div>
</div>
<!-- Step 02 -->
<div class="process-step">
<div class="step-visual">
<div class="step-icon-box"><i class="fas fa-edit"></i></div>
<div class="step-number-badge">02</div>
<div class="step-connector"></div>
</div>
<div class="step-content">
<h3 data-tp-i18n="proc_s2_h">Lengkapi Formulir</h3>
<p data-tp-i18n="proc_s2_p">Isi setiap kolom dengan lengkap dan teliti. Sertakan seluruh dokumen pendukung yang diminta sebelum pengiriman.</p>
</div>
</div>
<!-- Step 03 -->
<div class="process-step">
<div class="step-visual">
<div class="step-icon-box"><i class="fas fa-paper-plane"></i></div>
<div class="step-number-badge">03</div>
</div>
<div class="step-content">
<h3 data-tp-i18n="proc_s3_h">Kirim Berkas</h3>
<p data-tp-i18n="proc_s3_p">Kirimkan formulir beserta dokumen pendukung melalui email resmi atau WhatsApp admin prodi. Berkas yang lengkap akan langsung diproses oleh admin prodi.</p>
</div>
</div>
</div>
</div>
</section>
<!-- ═══════════════════════════════════════
HELP CENTER
═══════════════════════════════════════ -->
<section id="help" class="help-center-section">
<div class="help-container">
<div class="help-header-centered">
<h2 class="section-title" data-tp-i18n="help_title">Butuh Bantuan Lebih Lanjut?</h2>
<p data-tp-i18n="help_desc">Tim admin kami siap membantu Anda melalui kanal komunikasi resmi di bawah ini.</p>
</div>
<div class="help-cards-grid">
<div class="interaction-card help-official">
<div class="card-inner">
<div class="card-icon"><i class="fas fa-envelope-open-text"></i></div>
<h3 data-tp-i18n="help_email_title">Korespondensi Resmi (Email)</h3>
<p data-tp-i18n="help_email_desc">Gunakan untuk permohonan form khusus non-publik atau administrasi formal lainnya.</p>
<ul class="card-checklist">
<li><i class="fas fa-check"></i> <span data-tp-i18n="help_email_c1">Respon Maks. 24 Jam</span></li>
<li><i class="fas fa-check"></i> <span data-tp-i18n="help_email_c2">Pelayanan Formal</span></li>
</ul>
<a href="mailto:admin@informatika.untan.ac.id?subject=Layanan%20Administrasi%20%26%20CS%20Informatika%20UNTAN&body=Halo%20Admin%20Prodi%20Informatika%20UNTAN%2C%0A%0ASaya%20ingin%20mengajukan%20permohonan%20%2F%20melaporkan%20kendala%20terkait%20administrasi%20akademik.%20Berikut%20detail%20informasi%20saya%3A%0A%0ANama%3A%20%5BNama%20Lengkap%20Anda%5D%0ANIM%3A%20%5BNIM%20Anda%5D%0AKategori%20Layanan%3A%20%5BTata%20Cara%20Pengajuan%20%2F%20Kendala%20Teknis%20%26%20CS%5D%0A%0ADetail%20Masalah%20%2F%20Pengajuan%3A%0A%5BTuliskan%20pertanyaan%2C%20detail%20pengajuan%2C%20atau%20kendala%20Anda%20di%20sini...%5D%0A%0ATerima%20kasih." class="btn-interaction"><span data-tp-i18n="help_email_btn">HUBUNGI ADMIN</span> <i class="fas fa-paper-plane"></i></a>
</div>
</div>
<div class="interaction-card help-urgent">
<div class="card-inner">
<div class="card-icon"><i class="fab fa-whatsapp"></i></div>
<h3 data-tp-i18n="help_wa_title">Quick Support (WhatsApp)</h3>
<p data-tp-i18n="help_wa_desc">Konsultasi cepat alur birokrasi atau pelaporan kendala akses pada berkas repositori.</p>
<ul class="card-checklist">
<li><i class="fas fa-check"></i> <span data-tp-i18n="help_wa_c1">Respon Instan Jam Kerja</span></li>
<li><i class="fas fa-check"></i> <span data-tp-i18n="help_wa_c2">Konsultasi Teknis</span></li>
</ul>
<a href="https://wa.me/6285171655161?text=Halo%20Admin%20Prodi%20Informatika%20UNTAN%2C%0A%0ASaya%20ingin%20mengajukan%20permohonan%20%2F%20melaporkan%20kendala%20terkait%20administrasi%20akademik.%20Berikut%20detail%20informasi%20saya%3A%0A%0ANama%3A%20%5BNama%20Lengkap%20Anda%5D%0ANIM%3A%20%5BNIM%20Anda%5D%0AKategori%20Layanan%3A%20%5BTata%20Cara%20Pengajuan%20%2F%20Kendala%20Teknis%20%26%20CS%5D%0A%0ADetail%20Masalah%20%2F%20Pengajuan%3A%0A%5BTuliskan%20pertanyaan%2C%20detail%20pengajuan%2C%20atau%20kendala%20Anda%20di%20sini...%5D%0A%0ATerima%20kasih." class="btn-interaction-alt"><span data-tp-i18n="help_wa_btn">CHAT WHATSAPP</span> <i class="fab fa-whatsapp"></i></a>
</div>
</div>
</div>
</div>
</section>
</main>
<footer class="bg-untan-navy text-white pt-16 relative overflow-hidden mt-0">
<div class="container mx-auto px-4 lg:px-8 relative z-10 flex flex-col items-center justify-center text-center">
@@ -1334,5 +1251,7 @@
</script>
<script src="../../assets/global/localization.js"></script>
<script src="js/i18n-tapops.js"></script>
<script src="js/main.js"></script>
</body>
</html>