diff --git a/.gitignore b/.gitignore index 3bdd52e..26b2088 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,9 @@ node_modules/ dist/ .DS_Store +.env +.env.local +groups/**/.env +groups/**/.env.local +README.md +i18n.js \ No newline at end of file diff --git a/assets/global/localization.js b/assets/global/localization.js index 643e7db..ab488b7 100644 --- a/assets/global/localization.js +++ b/assets/global/localization.js @@ -570,6 +570,30 @@ const translations = { kontrib_guideline_4: "Hindari plagiarisme. Karya harus orisinal.", kontrib_guideline_5: "Tim redaksi berhak menyunting konten untuk keperluan editorial.", + // --- apeNameTeamE (Halaman Beasiswa) --- + ape_breadcrumb_profile: 'Profil', + ape_breadcrumb_scholarship: 'Beasiswa', + ape_hero_badge: 'Program Beasiswa', + ape_hero_title: 'Beasiswa Studi &
Penelitian', + ape_hero_subtitle: 'Teknik Informatika Universitas Tanjungpura', + ape_hero_desc: 'Temukan berbagai peluang beasiswa untuk mendukung perjalanan akademik dan penelitian Anda. Program Studi Informatika UNTAN berkomitmen membantu mahasiswa meraih prestasi terbaik.', + ape_hero_cta: 'Lihat Daftar Beasiswa', + ape_stats_total: 'Total Mahasiswa Penerima
Beasiswa Semester Ini', + ape_stats_s1: 'Total Penerima Beasiswa
Khusus S1', + ape_stats_studi: 'Total Penerima Beasiswa
Studi Lanjut', + ape_dir_label: 'Daftar Beasiswa', + ape_dir_title: 'Daftar Beasiswa', + ape_dir_desc: 'Temukan beragam beasiswa dari berbagai sumber resmi yang tersedia untuk mahasiswa aktif, alumni, dan calon mahasiswa Program Studi Informatika UNTAN.', + ape_dir_guide: 'Terima Bantuan Beasiswa?', + ape_filter_s1: 'Khusus S1', + ape_filter_studi: 'Studi Lanjut', + ape_search_placeholder: 'Cari Nama Beasiswa...', + ape_testimonial_title: 'Apa Kata Mereka?', + ape_testimonial_desc: 'Cerita inspiratif dari para penerima beasiswa Program Studi Informatika UNTAN', + ape_cta_title: 'Ingin Mengetahui Info Lebih Lanjut?', + ape_cta_desc: 'Hubungi admin prodi untuk informasi terbaru tentang beasiswa dan program akademik.', + ape_cta_btn1: 'DAFTAR BEASISWA', + ape_cta_btn2: 'Hubungi Kami', // ── Page ────────────────────────────────────────────────────────────── grp_habisiniseminar_page_title: 'Penerimaan Mahasiswa Baru Informatika UNTAN | Kelompok 02', grp_habisiniseminar_brand: 'Informatika UNTAN Penerimaan Mahasiswa Baru', @@ -1319,6 +1343,30 @@ const translations = { kontrib_guideline_4: "Avoid plagiarism. Work must be original.", kontrib_guideline_5: "The editorial team reserves the right to edit content for editorial purposes.", + // --- apeNameTeamE (Scholarship Page) --- + ape_breadcrumb_profile: 'Profile', + ape_breadcrumb_scholarship: 'Scholarship', + ape_hero_badge: 'Scholarship Program', + ape_hero_title: 'Study & Research
Scholarships', + ape_hero_subtitle: 'Informatics Engineering, Tanjungpura University', + ape_hero_desc: 'Discover various scholarship opportunities to support your academic and research journey. The Informatics Study Program at UNTAN is committed to helping students achieve excellence.', + ape_hero_cta: 'View Scholarships', + ape_stats_total: 'Total Scholarship
Recipients This Semester', + ape_stats_s1: 'Total Undergraduate
Scholarship Recipients', + ape_stats_studi: 'Total Postgraduate
Scholarship Recipients', + ape_dir_label: 'Scholarship Directory', + ape_dir_title: 'Scholarship Directory', + ape_dir_desc: 'Find various scholarships from official sources available for active students, alumni, and prospective students of the UNTAN Informatics Study Program.', + ape_dir_guide: 'Need Scholarship Aid?', + ape_filter_s1: 'Undergraduate', + ape_filter_studi: 'Postgraduate', + ape_search_placeholder: 'Search Scholarship Name...', + ape_testimonial_title: 'What They Say?', + ape_testimonial_desc: 'Inspiring stories from scholarship recipients at UNTAN Informatics Study Program', + ape_cta_title: 'Want to Know More?', + ape_cta_desc: 'Contact the program admin for the latest scholarship and academic program information.', + ape_cta_btn1: 'SCHOLARSHIP LIST', + ape_cta_btn2: 'Contact Us', // ── Page ────────────────────────────────────────────────────────────── grp_habisiniseminar_page_title: 'New Student Admission Informatics UNTAN | Group 02', grp_habisiniseminar_brand: 'Informatics UNTAN New Student Admission', diff --git a/groups/ACAAB/index.html b/groups/ACAAB/index.html index a781215..1be3821 100644 --- a/groups/ACAAB/index.html +++ b/groups/ACAAB/index.html @@ -997,7 +997,7 @@
- +
File ini adalah konteks utama proyek untuk AI assistant (Antigravity). +> Baca file ini setiap kali kamu membantu pengerjaan proyek ini. + +--- + +## 🎯 Apa yang Dibangun? + +**Single static landing page** berbasis HTML/CSS/JS murni (native web) untuk menampilkan informasi beasiswa bagi mahasiswa aktif, alumni, dan masyarakat umum Program Studi Informatika, Universitas Tanjungpura (UNTAN), Pontianak. + +Website ini bukan aplikasi web dinamis. Tidak ada backend, tidak ada database, tidak ada login. Update konten dilakukan dengan mengedit file JSON dan push ke GitHub → auto-deploy via Puify ke server prodi. + +--- + +## 🏗️ Tech Stack + +| Layer | Teknologi | +|---|---| +| Markup | HTML5 | +| Styling | CSS3 + Tailwind CSS | +| Interaktivitas | Vanilla JavaScript (ES6+) | +| Font | Google Fonts (Inter / Poppins) | +| Ikon | Font Awesome | +| Animasi | AOS.js (Animate on Scroll) | +| Carousel | Swiper.js | +| Hosting | Dedicated Server Prodi UNTAN via Puify | +| Version Control | Git + GitHub | + +**Tidak boleh menggunakan:** Framework berat (React, Vue, Angular), backend (Node.js, PHP, Python), database (MySQL, MongoDB). + +--- + +## 📐 Desain + +- **Figma Project:** https://www.figma.com/design/rG6JYG19CWziaPMhbJ2NPL/PPL-FIGMA?node-id=0-1 +- **Prototype:** https://www.figma.com/proto/rG6JYG19CWziaPMhbJ2NPL/PPL-FIGMA?node-id=120-1247 + +### Warna Utama + +| Variabel | Hex | Penggunaan | +|---|---|---| +| Primary (Biru) | `#2B4590` | Navbar, heading, tombol, border aktif | +| Secondary (Kuning) | `#F5A623` | CTA, aksen, badge | +| Background | `#FFFFFF` | Latar halaman | +| Text | `#1A1A1A` | Body text | +| Accent | `#6B7280` | Caption, label, border | +| Success | `#10B981` | Badge "Buka" | +| Danger | `#EF4444` | Badge "Ditutup" | +| Overlay | `#00000080` | Background popup | + +### Tipografi +- **Font:** Inter (utama) / Poppins (heading) +- H1: 48–64px bold | H2: 32–40px semibold | H3: 24–28px semibold +- Body: 16–18px regular | Caption: 12–14px + +--- + +## 📄 Struktur Halaman (Top → Bottom) + +``` +[NAVBAR - Sticky] + Logo UNTAN | Menu: Beranda, Beasiswa, Testimoni, Kontak | Toggle ID/EN + +[#hero - Hero Section] + Judul: "Beasiswa Studi & Penelitian" + Sub: Teknik Informatika Universitas Tanjungpura + Deskripsi singkat tentang beasiswa + CTA Button (kuning): "Lihat Daftar Beasiswa →" + Foto ilustrasi mahasiswa (kanan) + +[#statistics - Statistik Counter] + 3 angka dengan animasi scroll: + - Total Mahasiswa Penerima Beasiswa Semester Ini + - Total Penerima Beasiswa Pembiayaan Pemerintah + - Total Penerima Beasiswa Pembiayaan Swasta + +[#directory - Direktori Beasiswa] + - Tab filter: Semua | Sedang Buka | Ditutup | Pemerintah | Swasta + - Search bar (real-time) + - Grid kartu beasiswa: + * Desktop: 3 kolom + * Tablet: 2 kolom + * Mobile: 1 kolom + - Tiap kartu: thumbnail, badge status, nama, deskripsi singkat, tanggal, tombol "Selengkapnya →" + - Klik "Selengkapnya →" → buka POPUP MODAL + +[POPUP MODAL - Detail Beasiswa] + - Nama + thumbnail/logo beasiswa + - Badge status (Buka / Ditutup) + - Syarat umum (ringkasan/bullet) + - Kontak yang bisa dihubungi + - Tombol "Info Lebih Lanjut" → buka URL sumber resmi (tab baru) + - Tutup: tombol ×, klik luar area, tekan Escape + +[#testimonial - Testimoni Penerima Beasiswa] + - Carousel / grid kartu + - Tiap kartu: foto, nama, nama beasiswa yang diterima, kutipan singkat + - Navigasi carousel jika > 3 testimoni + +[#cta - Call to Action] + - Judul: "Ingin Mengetahui Info Lebih Lanjut?" + - Dua tombol: + * "Daftar Beasiswa" (scroll ke #directory) + * "Hubungi Kami" (WhatsApp admin) + +[#footer - Footer] + - Logo Informatika UNTAN + - Alamat prodi, email, telepon, WhatsApp + - Ikon media sosial + - Ilustrasi khas Pontianak (dekorasi bawah) +``` + +--- + +## 📁 Struktur File Proyek + +``` +project-root/ +├── index.html +├── assets/ +│ ├── css/ +│ │ └── style.css +│ ├── js/ +│ │ ├── main.js # Init AOS, smooth scroll, sticky navbar +│ │ ├── filter.js # Filter tab + real-time search +│ │ ├── popup.js # Modal detail beasiswa +│ │ ├── counter.js # Animasi counter statistik +│ │ ├── carousel.js # Carousel testimoni (Swiper.js) +│ │ └── i18n.js # Toggle bahasa ID/EN +│ └── images/ +│ ├── hero/ +│ ├── beasiswa/ # Logo/thumbnail beasiswa +│ └── testimoni/ # Foto penerima +├── data/ +│ ├── beasiswa.json +│ └── testimoni.json +└── README.md +``` + +--- + +## 🗃️ Format Data + +### `data/beasiswa.json` +```json +[ + { + "id": "bsw-001", + "nama": "Beasiswa Adaro Foundation 2026", + "kategori": "Swasta", + "status": "Ditutup", + "thumbnail": "assets/images/beasiswa/adaro.jpg", + "deskripsi_singkat": "Beasiswa untuk mahasiswa S1 & D4 dengan IPK minimal 3.00...", + "syarat_umum": [ + "Mahasiswa aktif S1/D4", + "IPK minimal 3.00", + "Berasal dari keluarga kurang mampu" + ], + "kontak": "Admin Prodi / Kemahasiswaan UNTAN", + "tanggal_buka": "2026-01-01", + "tanggal_tutup": "2026-04-09", + "url_sumber": "https://...", + "tags": ["S1", "Swasta"] + } +] +``` + +### `data/testimoni.json` +```json +[ + { + "id": "tsm-001", + "nama": "Aulia Rahman", + "foto": "assets/images/testimoni/aulia.jpg", + "nama_beasiswa": "Beasiswa Prestasi", + "kutipan": "Beasiswa ini benar-benar membuka jalan bagi saya untuk fokus sepenuhnya pada pendidikan..." + } +] +``` + +--- + +## ⚙️ Fitur Interaktif yang Harus Diimplementasikan + +| Fitur | Status | File | +|---|---|---| +| Sticky Navbar (transparent → solid saat scroll) | ⏳ | `main.js` | +| Hamburger Menu | ⏳ | `main.js` | +| Smooth Scroll ke seksi | ⏳ | `main.js` | +| Active State Navbar (IntersectionObserver) | ⏳ | `main.js` | +| Animasi AOS (elemen muncul saat scroll) | ⏳ | `main.js` | +| Counter Animasi Statistik | ⏳ | `counter.js` | +| Render kartu beasiswa dari JSON | ⏳ | `filter.js` | +| Filter tab (Semua/Buka/Ditutup/Pemerintah/Swasta) | ⏳ | `filter.js` | +| Real-time search | ⏳ | `filter.js` | +| Popup Modal detail beasiswa | ⏳ | `popup.js` | +| Tutup popup (×, klik luar, Escape) | ⏳ | `popup.js` | +| Carousel testimoni (Swiper.js) | ⏳ | `carousel.js` | +| Toggle bahasa ID/EN | ⏳ | `i18n.js` | + +--- + +## 📱 Responsive Breakpoints + +```css +/* Mobile first */ +/* Default: mobile < 768px */ +/* Tablet: */ @media (min-width: 768px) { ... } +/* Laptop: */ @media (min-width: 1024px) { ... } +/* Desktop: */ @media (min-width: 1280px) { ... } +``` + +--- + +## 🔒 Aturan Keamanan Kode + +- Semua link eksternal: `target="_blank" rel="noopener noreferrer"` +- Tidak ada hardcoded data sensitif di source code +- Input search di-sanitasi sebelum digunakan untuk filter DOM +- Tidak menggunakan `innerHTML` dengan input pengguna langsung (cegah XSS) + +--- + +## 👥 Tim & Peran + +| Nama | Peran | +|---|---| +| Djapianus Thebrianto | Project Manager | +| Derangga Aray Abimanyu | Backend Developer (data, scraping, JSON) | +| Destra Aulia Faza Ananda Putra | Frontend Developer (HTML, CSS, JS) | +| Dian Satrio Prayogo | UI/UX Designer (Figma) | +| Jonathan Geral Nababan | Quality Assurance (testing) | + +--- + +## 📋 Hal Penting untuk AI Assistant + +1. **Ini bukan React/Vue/Angular.** Semua harus ditulis dalam HTML/CSS/Tailwind/Vanilla JS. +2. **Data beasiswa dibaca dari `data/beasiswa.json`** — bukan hardcoded di HTML. +3. **Warna wajib sesuai palet resmi** — jangan gunakan warna lain sembarangan. +4. **Mobile-first** — tulis CSS dari ukuran kecil dulu, baru ke besar. +5. **Popup harus bisa ditutup 3 cara:** tombol ×, klik overlay, tekan Escape. +6. **Filter dan search bisa aktif bersamaan** (kumulatif, bukan saling menggantikan). +7. **Navbar berubah warna saat scroll** — transparent di atas hero, solid biru setelah scroll turun. +8. **Semua animasi pakai AOS.js** — inisialisasi di `main.js` dengan `AOS.init()`. +9. **Carousel testimoni pakai Swiper.js** — touch-friendly untuk mobile. +10. **Tidak ada `alert()`, `console.log()` di production code.** + +--- + +## 🚀 Cara Kerja Deployment + +``` +Developer push ke GitHub + ↓ + Puify detects push + ↓ + Auto-deploy ke server + ↓ + Website live (Dev) + ↓ + Approved → Production +``` + +--- + +## 📎 Dokumen Terkait + +- `SRS.md` — Spesifikasi kebutuhan lengkap (use case, NFR, batasan) +- `SDD.md` — Desain teknis lengkap (arsitektur, komponen, schema data) +- Figma: https://www.figma.com/design/rG6JYG19CWziaPMhbJ2NPL/PPL-FIGMA?node-id=0-1 diff --git a/groups/ApeNameTeamE/SDD.md b/groups/ApeNameTeamE/SDD.md new file mode 100644 index 0000000..ebbef87 --- /dev/null +++ b/groups/ApeNameTeamE/SDD.md @@ -0,0 +1,329 @@ +# Software Design Document (SDD) +## Website Statis Halaman Beasiswa — One-Page HTML +### Program Studi Informatika — Universitas Tanjungpura + +| Field | Detail | +|---|---| +| Nama Proyek | Pengembangan Website Statis Halaman Beasiswa | +| Kelompok | Ape Nama Team E | +| Versi | 1.0 | +| Fase SDLC | Design (aktif) | +| Dosen | Izuardo Zulkarnain, S.Pd., M.T | +| Semester | Genap 2025/2026 | + +--- + +## 1. Pendahuluan + +### 1.1 Tujuan Dokumen +SDD ini mendeskripsikan perancangan teknis website beasiswa Informatika UNTAN sebagai one-page HTML native. Dokumen ini menjadi panduan tim dalam mengimplementasikan: +- Fitur popup detail beasiswa +- Integrasi data hasil scraping & survei admin +- Otomatisasi deployment via Puify (push-to-deploy) + +### 1.2 Stack Teknologi + +| Layer | Teknologi | Keterangan | +|---|---|---| +| Markup | HTML5 | Struktur konten | +| Styling | CSS3 / Tailwind CSS | Layout responsif | +| Interaktivitas | JavaScript (Vanilla / Alpine.js) | Animasi, scroll, toggle | +| Font & Ikon | Google Fonts / Font Awesome | Tipografi & ikon | +| Hosting | Puify (SaaS) | Auto-deploy dari repo ke server | +| Server | Dedicated Server Prodi | Dev & Production | +| Version Control | Git + GitHub | Kolaborasi & push-to-deploy | + +### 1.3 Posisi dalam SDLC + +| Fase | Status | +|---|---| +| Requirement | ✅ Selesai | +| Design | 🔄 Aktif | +| Implementation | ⏳ Belum | +| Testing | ⏳ Belum | +| Deployment | ⏳ Belum | + +--- + +## 2. Arsitektur Halaman (Site Architecture) + +### 2.1 Konsep One-Page Website +Single-page statis — semua konten dalam satu file HTML utama. Navigasi menggunakan **smooth scroll**. Detail beasiswa (syarat umum) ditampilkan via **popup modal** agar halaman tetap bersih. + +### 2.2 Struktur Seksi (Vertikal, Atas → Bawah) + +| No | ID | Nama Seksi | Konten Utama | +|---|---|---|---| +| 1 | `#hero` | Hero / Landing | Judul "Beasiswa Studi & Penelitian", deskripsi, CTA "Lihat Daftar Beasiswa", foto ilustrasi mahasiswa | +| 2 | `#statistics` | Statistik Counter | 3 angka animasi: Total Penerima Semester Ini, Total Pemerintah, Total Swasta | +| 3 | `#directory` | Direktori Beasiswa | Grid kartu (3 kolom desktop, 2 tablet, 1 mobile), tab filter, real-time search, popup detail | +| 4 | `#testimonial` | Testimoni | Carousel/grid testimoni: foto, nama, beasiswa, kutipan singkat | +| 5 | `#cta` | Call-to-Action | Banner ajakan + tombol WhatsApp admin + Instagram kemahasiswaan | +| 6 | `#footer` | Footer | Logo prodi, alamat, email, telepon, WA, ikon sosmed, dekorasi ilustrasi Pontianak | + +### 2.3 Navigasi +**Sticky navbar** yang selalu terlihat saat scroll. + +| Perangkat | Perilaku Navbar | +|---|---| +| Desktop/Laptop | Horizontal, semua item terlihat | +| Tablet | Horizontal, item muat; sisanya dropdown | +| Mobile | Hamburger menu (≡) — tap untuk expand vertikal | + +--- + +## 3. Desain Visual & Identitas + +### 3.1 Color Palette + +| Peran | Nama | Hex | Digunakan Untuk | +|---|---|---|---| +| Primary | Biru Informatika | `#2B4590` | Navbar, heading, tombol primary, border aktif | +| Secondary | Kuning/Oranye | `#F5A623` | CTA button, aksen, badge | +| Background | White | `#FFFFFF` | Latar halaman utama | +| Text | Dark Gray | `#1A1A1A` | Body text, paragraf | +| Accent | Abu-abu | `#6B7280` | Caption, label, border | +| Success | Hijau | `#10B981` | Badge status "Buka" | +| Danger | Merah | `#EF4444` | Badge status "Ditutup" | +| Overlay | Hitam + Transparansi | `#00000080` | Background popup modal | + +### 3.2 Tipografi + +| Elemen | Font Family | Ukuran | Weight | +|---|---|---|---| +| Heading H1 | Poppins / Inter | 48–64px | 700 (Bold) | +| Heading H2 | Poppins / Inter | 32–40px | 600 (SemiBold) | +| Heading H3 | Poppins / Inter | 24–28px | 600 (SemiBold) | +| Body Text | Inter / Poppins | 16–18px | 400 (Regular) | +| Caption/Label | Inter / Poppins | 12–14px | 400–500 | +| Navbar | Inter | 14–16px | 500 (Medium) | +| Button | Inter | 14–16px | 600 (SemiBold) | + +### 3.3 Komponen UI + +| Komponen | Spesifikasi | +|---|---| +| Navbar | Sticky; transparent di atas hero → solid biru `#2B4590` saat scroll; toggle ID/EN di kanan | +| Hero Section | Full-height, overlay gradient gelap, judul besar, deskripsi, CTA kuning kontras | +| Card Beasiswa | Border subtle, shadow ringan; hover: scale sedikit + shadow lebih dalam; thumbnail 100% lebar | +| Button Primary | Solid biru, teks putih | +| Button Secondary | Outline biru | +| Button Ghost | Tanpa border | +| Badge Status | Rounded pill; Hijau "Buka", Merah "Ditutup" | +| Tab Filter | Underline active state, smooth transition, teks hitam, garis bawah aktif biru | +| Popup Modal | Center screen, dark overlay, border-radius 12px, close button (×) kanan atas | +| Footer | Background `#1A1A1A`, teks putih, 3–4 kolom desktop | + +--- + +## 4. Desain Mockup (UI/UX) + +### 4.1 Alat Desain +**Figma** — kolaborasi realtime, wireframe + hi-fidelity prototype. + +- **Figma Project:** https://www.figma.com/design/rG6JYG19CWziaPMhbJ2NPL/PPL-FIGMA?node-id=0-1 +- **Prototype Interaktif:** https://www.figma.com/proto/rG6JYG19CWziaPMhbJ2NPL/PPL-FIGMA?node-id=120-1247 + +### 4.2 Tahapan Desain +1. **Wireframe (Lo-Fi)** — sketsa hitam-putih, fokus layout & posisi elemen +2. **Mockup (Hi-Fi)** — desain lengkap dengan warna, font, dan aset visual +3. **Prototype** — mockup yang bisa diklik untuk simulasi navigasi antar seksi +4. **User Testing** — validasi desain bersama calon pengguna + +### 4.3 Breakpoint & Resolusi + +| Perangkat | Resolusi Mockup | +|---|---| +| Desktop Monitor | 1920 × 1080 | +| Laptop | 1366 × 768 | +| Tablet Portrait | 768 × 1024 | +| Tablet Landscape | 1024 × 768 | +| Mobile / HP | 390 × 844 | + +--- + +## 5. Desain Responsif + +### 5.1 Strategi: Mobile-First +Desain dimulai dari layar terkecil → diperluas ke layar lebih besar via CSS media query. Memastikan performa optimal di koneksi lambat. + +### 5.2 Breakpoint + +| Perangkat | Breakpoint | Resolusi Umum | +|---|---|---| +| Desktop Monitor | `>= 1280px` | 1920×1080, 2560×1440 | +| Laptop | `>= 1024px` | 1366×768, 1440×900 | +| Tablet | `>= 768px` | 768×1024, 820×1180 | +| Mobile | `< 768px` | 360×800, 390×844, 414×896 | + +### 5.3 Perubahan Layout per Breakpoint + +| Elemen | Mobile (<768px) | Tablet (768–1279px) | Desktop (≥1280px) | +|---|---|---|---| +| Navbar | Hamburger menu | Hamburger / partial menu | Horizontal full menu | +| Hero Section | Teks atas, gambar bawah | Teks kiri, gambar kanan 50/50 | Teks kiri, gambar kanan lebar | +| Card Grid | 1 kolom | 2 kolom | 3–4 kolom | +| Teks Body | 16px | 16–17px | 17–18px | +| Padding Section | 24px 16px | 40px 32px | 80px 64px | +| Footer | Stack vertikal | 2 kolom | 3–4 kolom | + +### 5.4 Hasil Uji Responsivitas + +| No | Perangkat/Browser | Ukuran | Status | Catatan | +|---|---|---|---|---| +| 1 | Chrome Desktop | 1920×1080 | ✅ Lulus | Layout proporsional, spacing rapi | +| 2 | Chrome Mobile Sim. | 390×844 | ✅ Lulus | Card grid 1 kolom, teks 16px nyaman | +| 3 | Firefox Desktop | 1440×900 | ✅ Lulus | Konsisten dengan Chrome Desktop | +| 4 | iPhone (Safari) | 390×844 | ✅ Lulus | Hero stack sempurna, padding aman | +| 5 | Android Chrome | 360×800 | ✅ Lulus | Touch target ideal, gambar proporsional | +| 6 | iPad (Safari) | 768×1024 | ✅ Lulus | Hero 50/50, spasi sentuh lega | + +--- + +## 6. Use Case Diagram + +### 6.1 Aktor Sistem + +| Aktor | Deskripsi | +|---|---| +| Pengunjung Umum | Mahasiswa aktif, alumni, calon mahasiswa, dosen, masyarakat — tanpa autentikasi | +| Admin Prodi | Pengelola konten: memperbarui data beasiswa, testimoni, statistik via push-to-repo | + +### 6.2 Daftar Use Case & Skenario + +Lihat detail lengkap di SRS.md. Ringkasan: + +| Kode | Nama | Aktor | +|---|---|---| +| UC-01 | Melihat Daftar Beasiswa | Pengunjung Umum | +| UC-02 | Memfilter Beasiswa Berdasarkan Kategori | Pengunjung Umum | +| UC-03 | Mencari Beasiswa | Pengunjung Umum | +| UC-04 | Melihat Detail Beasiswa (Popup) | Pengunjung Umum | +| UC-05 | Mengakses Sumber Resmi Beasiswa | Pengunjung Umum | +| UC-06 | Menghubungi Admin via CTA | Pengunjung Umum | +| UC-07 | Melihat Testimoni Penerima Beasiswa | Pengunjung Umum | +| UC-08 | Mengganti Bahasa Tampilan (ID/EN) | Pengunjung Umum | +| UC-09 | Memperbarui Data Beasiswa | Admin Prodi | + +**Relasi antar UC:** UC-04 `<>` UC-05 (popup detail menyertakan akses sumber resmi) + +--- + +## 7. Fitur Interaktif (Client-Side) + +Tidak ada backend API. Semua interaktivitas dijalankan di sisi klien. + +| No | Fitur | Teknologi | Keterangan | +|---|---|---|---| +| 1 | Smooth Scroll Navigasi | CSS `scroll-behavior` / JS | Scroll halus ke seksi saat klik menu | +| 2 | Sticky Navbar | CSS `position:sticky` / JS scroll | Navbar tetap di atas saat scroll | +| 3 | Hamburger Menu | JavaScript + CSS toggle | Menu responsif layar kecil | +| 4 | Active State Navbar | JS `IntersectionObserver` | Highlight menu sesuai seksi terlihat | +| 5 | Animasi Masuk (AOS) | AOS.js / CSS animation | Elemen muncul saat pertama kali di viewport | +| 6 | Counter Animasi | JavaScript | Angka statistik berjalan saat di-scroll | +| 7 | Filter Real-Time | Vanilla JavaScript | Filter kartu saat klik tab, tanpa reload | +| 8 | Pencarian Real-Time | Vanilla JavaScript | Cari beasiswa saat ketik di search bar | +| 9 | Popup Modal Detail | Vanilla JavaScript | Detail beasiswa dalam modal; tutup via ×, klik luar, atau Escape | +| 10 | Toggle Bahasa ID/EN | Vanilla JS + localStorage | Ubah teks tanpa reload, simpan preference di session | +| 11 | Carousel Testimoni | Vanilla JS / Swiper.js | Navigasi testimoni left/right; touch swipe di mobile | +| 12 | Form Kontak (Opsional) | Formspree / EmailJS / mailto | Kirim pesan tanpa backend | +| 13 | Lightbox Galeri (Opsional) | Fancybox / vanilla JS | Gambar fullscreen saat diklik | + +--- + +## 8. Layanan Pihak Ketiga + +| Layanan | Kegunaan | Gratis? | +|---|---|---| +| Google Fonts | Tipografi (Inter/Poppins) | ✅ Ya | +| Font Awesome | Ikon UI | ✅ Ya (tier dasar) | +| Google Maps Embed | Peta lokasi di seksi kontak | ✅ Ya (basic embed) | +| Formspree | Form kontak tanpa backend | ✅ Ya (tier dasar) | +| AOS.js | Animasi scroll (Animate on Scroll) | ✅ Ya (open source) | +| Swiper.js | Carousel testimoni | ✅ Ya (open source) | + +--- + +## 9. Desain Keamanan + +### 9.1 Keamanan Form Kontak +- Validasi client-side: semua field wajib diisi, format email dicek sebelum submit +- Rate limiting: Formspree/EmailJS membatasi pengiriman untuk mencegah spam +- reCAPTCHA (Opsional): Google reCAPTCHA v3 untuk mencegah bot + +### 9.2 Keamanan Konten +- **Tidak ada data sensitif** — website tidak menyimpan data pengguna (no login, no database) +- **HTTPS wajib** — sertifikat SSL/TLS pada server hosting prodi +- **Content Security Policy** — meta CSP header untuk mencegah XSS +- **External link** — semua link eksternal menggunakan `rel="noopener noreferrer"` + +--- + +## 10. Struktur File yang Direkomendasikan + +``` +project-root/ +├── index.html # File HTML utama (one-page) +├── assets/ +│ ├── css/ +│ │ └── style.css # Custom CSS (jika tidak full Tailwind) +│ ├── js/ +│ │ ├── main.js # Logika utama: scroll, navbar, AOS init +│ │ ├── filter.js # Filter & pencarian beasiswa +│ │ ├── popup.js # Modal popup detail beasiswa +│ │ ├── counter.js # Animasi counter statistik +│ │ ├── carousel.js # Carousel testimoni +│ │ └── i18n.js # Toggle bahasa ID/EN +│ └── images/ +│ ├── hero/ # Foto hero section +│ ├── beasiswa/ # Thumbnail logo beasiswa +│ └── testimoni/ # Foto penerima beasiswa +├── data/ +│ ├── beasiswa.json # Data beasiswa (diupdate oleh admin) +│ └── testimoni.json # Data testimoni +└── README.md # Panduan setup & deployment +``` + +--- + +## 11. Data Schema + +### 11.1 Schema Beasiswa (`beasiswa.json`) +```json +{ + "id": "string", + "nama": "string", + "kategori": "Pemerintah | Swasta", + "status": "Buka | Ditutup", + "thumbnail": "path/to/image.jpg", + "deskripsi_singkat": "string (max 150 char)", + "syarat_umum": ["string", "string"], + "kontak": "string", + "tanggal_buka": "YYYY-MM-DD", + "tanggal_tutup": "YYYY-MM-DD", + "url_sumber": "https://...", + "tags": ["S1", "S2", "Magang", "Luar Negeri"] +} +``` + +### 11.2 Schema Testimoni (`testimoni.json`) +```json +{ + "id": "string", + "nama": "string", + "foto": "path/to/foto.jpg", + "nama_beasiswa": "string", + "kutipan": "string (max 200 char)" +} +``` + +--- + +## 12. Referensi + +1. IEEE Standard 1016-2009 — Software Design Descriptions +2. W3C — HTML5 & CSS3 Specification (https://www.w3.org) +3. Google — Web Fundamentals: Responsive Web Design +4. MDN Web Docs — CSS Media Queries +5. Figma — Design Tool Documentation +6. Nurhikmat et al. (2024) — Optimasi Responsivitas Web dengan Mobile-First Design. JINTEKS. diff --git a/groups/ApeNameTeamE/SRS.md b/groups/ApeNameTeamE/SRS.md new file mode 100644 index 0000000..71f675f --- /dev/null +++ b/groups/ApeNameTeamE/SRS.md @@ -0,0 +1,337 @@ +# Software Requirements Specification (SRS) +## Pengembangan Website Statis Halaman Beasiswa +### Program Studi Informatika — Universitas Tanjungpura + +| Field | Detail | +|---|---| +| Nama Proyek | Pengembangan Website Statis Halaman Beasiswa | +| Kelompok | Ape Nama Team E | +| Versi | 1.1 | +| Tanggal | 01/05/2026 | +| Dosen | Izuardo Zulkarnain, S.Pd., M.T | +| Mata Kuliah | Proyek Perangkat Lunak — Semester Genap 2025/2026 | + +**Anggota Tim:** +- Djapianus Thebrianto — Project Manager +- Derangga Aray Abimanyu — Backend Developer +- Destra Aulia Faza Ananda Putra — Frontend Developer +- Dian Satrio Prayogo — UI/UX Designer +- Jonathan Geral Nababan — Quality Assurance + +--- + +## 1. Pendahuluan + +### 1.1 Tujuan Dokumen + +SRS ini memberikan spesifikasi teknis dan fungsional untuk pengembangan Website Statis Beasiswa Informatika Universitas Tanjungpura. Dokumen ini memastikan: + +- Pengembang membangun sistem dengan kode sederhana yang mudah di-maintain melalui mekanisme push-to-repo ke dedicated server prodi. +- Penyajian data beasiswa (nama & syarat umum) dilakukan melalui fitur **Pop-up** dengan akses langsung ke admin via WhatsApp dan Instagram kemahasiswaan UNTAN. +- Proyek mengalihkan alur data dari portal universitas/survei admin ke static page dengan **availability 24 jam**. + +**Ditujukan kepada:** Tim Ape Nama Team E, Product Owner (dosen), dan Administrator Prodi. + +### 1.2 Ruang Lingkup + +Website statis single-page yang menjadi pusat informasi beasiswa, riset, dan pengembangan karir — terintegrasi dengan infrastruktur server Prodi Informatika UNTAN. + +**Fitur yang dicakup:** +- Direktori beasiswa (mahasiswa aktif, alumni, S2 luar negeri, magang) +- Detail beasiswa via popup (nama + syarat umum) +- Data beasiswa dari web scraping sumber resmi +- Seksi testimoni penerima beasiswa (foto, profil, kutipan) +- Toggle bahasa Indonesia / Inggris (bilingual) +- CTA ke WhatsApp admin & Instagram kemahasiswaan UNTAN + +**Yang TIDAK dicakup:** +- Formulir pendaftaran (diarahkan ke URL asli penyedia) +- Halaman admin berbasis web (update via push-to-repo) +- Database — data bersifat statis (JSON/JS di repositori) + +### 1.3 Definisi & Akronim + +| Istilah | Definisi | +|---|---| +| Native Website | Web dengan HTML, CSS, JS murni tanpa framework kompleks | +| Scraping | Pengambilan data otomatis dari website eksternal | +| Dedicated Server | Server milik Prodi Informatika UNTAN (Dev & Production) | +| Pop-up / Modal | Jendela overlay di atas halaman tanpa reload | +| CTA | Call-to-Action — tombol ajakan ke WhatsApp/Instagram | +| Availability | Kemampuan sistem beroperasi 24 jam | +| Puify | Platform SaaS otomatisasi deployment dari repo ke server | + +### 1.4 Referensi +- IEEE Std 830-1998 — Software Requirements Specifications +- UU No. 27 Tahun 2022 tentang Perlindungan Data Pribadi (UU PDP) + +--- + +## 2. Deskripsi Umum Sistem + +### 2.1 Perspektif Produk + +Produk baru berdiri sendiri sebagai **single static landing page** — bukan pengganti sistem lama. Website ini hadir sebagai transformasi digital dari penyebaran info beasiswa yang sebelumnya manual (portal, surat kabar mahasiswa, grup medsos) ke satu platform terpusat. + +**Integrasi eksternal (satu arah):** +- Website resmi penyedia beasiswa (data via scraping) +- API Website Informatika UNTAN (konten artikel/berita) +- WhatsApp & Instagram Kemahasiswaan UNTAN (CTA) + +Tidak ada antarmuka admin berbasis web. Semua update konten via **push ke GitHub → auto-deploy ke server** melalui Puify. + +### 2.2 Fungsi Utama Sistem + +| Kode | Fungsi | Deskripsi | +|---|---|---| +| F01 | Direktori Beasiswa | Grid kartu beasiswa aktif, S2, magang, penelitian dari berbagai sumber resmi | +| F02 | Filter & Pencarian | Saring berdasarkan kategori (Semua/Buka/Ditutup/Pemerintah/Swasta) + real-time search | +| F03 | Detail via Pop-up | Modal berisi nama, syarat umum, kontak, tautan sumber resmi | +| F04 | Testimoni | Foto, nama, nama beasiswa, kutipan dari penerima beasiswa | +| F05 | CTA Hubungi Admin | Tombol cepat ke WhatsApp admin & Instagram kemahasiswaan | +| F06 | Bilingual ID/EN | Toggle bahasa Indonesia ↔ Inggris tanpa reload | +| F07 | Update via Repository | Admin edit file data + push → halaman publik auto-update | + +### 2.3 Kelas Pengguna + +| Kelas | Karakteristik | Hak Akses | +|---|---|---| +| Pengunjung Umum | Mahasiswa aktif, alumni, masyarakat — tanpa login | Lihat konten, filter, search, buka popup, akses link eksternal | +| Admin Prodi | Staf/mahasiswa dengan kemampuan Git dasar | Edit file data di GitHub → push → deploy otomatis | + +### 2.4 Lingkungan Operasional + +| Komponen | Spesifikasi | +|---|---| +| Platform | Browser modern: Chrome ≥v100, Firefox ≥v100, Edge ≥v100, Safari ≥v15 | +| Server/Hosting | Dedicated server Prodi Informatika UNTAN (Dev & Production) via Puify | +| Database | Tidak ada — data di file statis JSON/JS di repositori | +| Bahasa Pemrograman | HTML5, CSS3 + Tailwind CSS, JavaScript ES6+ | +| Version Control | Git / GitHub | +| Koneksi | Min 1 Mbps (dasar), 10 Mbps (optimal) | + +### 2.5 Asumsi & Ketergantungan + +**Asumsi:** +- Pengunjung menggunakan browser modern dengan JS ES6+ dan CSS3 aktif +- Data beasiswa sudah diverifikasi admin sebelum dipublikasikan +- Perangkat pengunjung mendukung akses WhatsApp (app atau web) + +**Ketergantungan:** +- Dedicated server Prodi UNTAN harus aktif untuk availability 24 jam +- Update data bergantung pada keaktifan admin melakukan push secara berkala +- Fitur berita bergantung pada stabilitas API Website Informatika UNTAN +- CTA bergantung pada keaktifan nomor WhatsApp & akun Instagram kemahasiswaan + +--- + +## 3. Kebutuhan Fungsional + +### 3.1 Daftar Use Case + +| UC ID | Nama Use Case | Aktor | Prioritas (MoSCoW) | +|---|---|---|---| +| UC-01 | Melihat Daftar Beasiswa | Pengunjung Umum | Must Have | +| UC-02 | Memfilter Beasiswa Berdasarkan Kategori | Pengunjung Umum | Must Have | +| UC-03 | Mencari Beasiswa | Pengunjung Umum | Must Have | +| UC-04 | Melihat Detail Beasiswa (Popup) | Pengunjung Umum | Must Have | +| UC-05 | Mengakses Sumber Informasi Beasiswa | Pengunjung Umum | Must Have | +| UC-06 | Menghubungi Admin via CTA | Pengunjung Umum | Must Have | +| UC-07 | Melihat Testimoni Penerima Beasiswa | Pengunjung Umum | Should Have | +| UC-08 | Mengganti Bahasa Tampilan (ID/EN) | Pengunjung Umum | Should Have | +| UC-09 | Memperbarui Data Beasiswa | Admin Prodi | Must Have | + +### 3.2 Detail Use Case + +#### UC-01: Melihat Daftar Beasiswa +| Field | Detail | +|---|---| +| Aktor | Pengunjung Umum | +| Precondition | Halaman berhasil dimuat di browser | +| Trigger | Pengunjung membuka URL atau scroll ke seksi Daftar Beasiswa | +| Main Flow | 1. Pengunjung buka URL halaman
2. Sistem tampilkan hero, statistik, daftar beasiswa
3. Kartu ditampilkan grid: 3 kolom desktop / 2 tablet / 1 mobile
4. Tiap kartu: thumbnail, badge status, nama, deskripsi singkat, tanggal, tombol "Selengkapnya"
5. Paginasi tampil di bawah grid jika beasiswa > 1 halaman | +| Alt Flow | 3a. Koneksi lambat → skeleton loading
3b. Tidak ada data → tampil "Belum ada beasiswa tersedia saat ini." | +| Postcondition | Pengunjung dapat melihat seluruh daftar beasiswa | + +#### UC-02: Memfilter Beasiswa Berdasarkan Kategori +| Field | Detail | +|---|---| +| Aktor | Pengunjung Umum | +| Precondition | Halaman dimuat, daftar beasiswa tampil | +| Trigger | Pengunjung klik salah satu tab filter | +| Main Flow | 1. Tampil tab: Semua \| Sedang Buka \| Ditutup \| Pemerintah \| Swasta
2. Pengunjung klik tab
3. Sistem real-time filter beasiswa sesuai kategori
4. Tab aktif ditandai bold/underline/warna
5. Jumlah hasil diperbarui | +| Alt Flow | 3a. Tidak ada hasil → "Tidak ada beasiswa pada kategori ini."
3b. Klik "Semua" → tampil semua beasiswa | +| Postcondition | Daftar beasiswa sesuai filter yang dipilih | + +#### UC-03: Mencari Beasiswa +| Field | Detail | +|---|---| +| Aktor | Pengunjung Umum | +| Precondition | Halaman dimuat, kolom pencarian tersedia | +| Trigger | Pengunjung mengetik di kolom pencarian | +| Main Flow | 1. Pengunjung klik kolom pencarian
2. Ketik kata kunci (misal: "Pertamina", "KIP", "luar negeri")
3. Sistem real-time filter kartu yang nama/deskripsinya cocok
4. Hapus kata kunci → kembali ke tampilan penuh
5. Filter dan pencarian dapat aktif bersamaan (kumulatif) | +| Alt Flow | 3a. Tidak ada hasil → "Tidak ditemukan beasiswa yang sesuai pencarian Anda." | +| Postcondition | Daftar beasiswa sesuai kata kunci | + +#### UC-04: Melihat Detail Beasiswa (Popup) +| Field | Detail | +|---|---| +| Aktor | Pengunjung Umum | +| Precondition | Kartu beasiswa tampil, pengunjung menemukan beasiswa yang diinginkan | +| Trigger | Klik tombol "Selengkapnya →" pada kartu | +| Main Flow | 1. Klik "Selengkapnya →"
2. Sistem tampilkan modal popup berisi: nama + thumbnail, badge status, syarat umum ringkasan, kontak, tombol "Info Lebih Lanjut" (→ URL sumber resmi di tab baru)
3. Background di-overlay gelap
4. Tutup via: tombol ×, klik di luar area, atau tekan Escape | +| Alt Flow | 4a. Klik "Info Lebih Lanjut" → jalankan UC-05 | +| Postcondition | Pengunjung mendapat info ringkas dan dapat lanjut ke sumber resmi | + +#### UC-05: Mengakses Sumber Informasi Beasiswa +| Field | Detail | +|---|---| +| Aktor | Pengunjung Umum | +| Precondition | Popup detail terbuka, tombol "Info Lebih Lanjut" tersedia | +| Trigger | Klik tombol "Info Lebih Lanjut" di popup | +| Main Flow | 1. Klik tombol
2. Sistem buka URL sumber resmi di tab baru
3. Popup di tab asal tetap terbuka | +| Alt Flow | 3a. URL tidak tersedia → "Tautan tidak tersedia. Silakan hubungi admin prodi." | +| Postcondition | Pengunjung diarahkan ke sumber resmi beasiswa | + +#### UC-06: Menghubungi Admin via CTA +| Field | Detail | +|---|---| +| Aktor | Pengunjung Umum | +| Precondition | Pengunjung ingin info lebih lanjut | +| Trigger | Scroll ke seksi CTA, klik salah satu tombol | +| Main Flow | 1. Scroll ke CTA ("Ingin Tahu Lebih Banyak tentang Beasiswa?")
2. Tampil dua tombol: "Hubungi Admin" (WhatsApp) + "Instagram Beasiswa" (IG kemahasiswaan)
3. Klik tombol → buka platform di tab baru | +| Alt Flow | 4a. Tanpa WhatsApp terinstall → buka WhatsApp Web | +| Postcondition | Pengunjung terhubung dengan admin atau follow Instagram | + +#### UC-07: Melihat Testimoni Penerima Beasiswa +| Field | Detail | +|---|---| +| Aktor | Pengunjung Umum | +| Precondition | Halaman dimuat, data testimoni tersedia di source code | +| Trigger | Scroll ke seksi Testimoni | +| Main Flow | 1. Scroll ke seksi Testimoni
2. Tampil kartu testimoni: foto, nama, nama beasiswa, kutipan singkat
3. Jika > 3 testimoni → navigasi carousel/tombol selanjutnya | +| Alt Flow | 2a. Belum ada data → seksi tidak ditampilkan atau tampil placeholder | +| Postcondition | Pengunjung mendapat gambaran pengalaman penerima beasiswa | + +#### UC-08: Mengganti Bahasa Tampilan (ID/EN) +| Field | Detail | +|---|---| +| Aktor | Pengunjung Umum | +| Precondition | Toggle ID\|EN tersedia di header navigasi | +| Trigger | Klik toggle bahasa di pojok kanan header | +| Main Flow | 1. Pengunjung lihat toggle ID \| EN di kanan atas
2. Klik bahasa yang diinginkan
3. Seluruh teks berubah tanpa reload
4. Pilihan tersimpan di session (tidak reset saat scroll/filter) | +| Alt Flow | 3a. Konten hanya tersedia 1 bahasa → tetap tampil bahasa aslinya | +| Postcondition | Halaman tampil dalam bahasa yang dipilih | + +#### UC-09: Memperbarui Data Beasiswa +| Field | Detail | +|---|---| +| Aktor | Admin Prodi | +| Precondition | Admin punya akses repo, ada info beasiswa baru/perubahan status | +| Trigger | Admin mendapat informasi update dari survei/portal/sumber lain | +| Main Flow | 1. Admin dapat info baru/perubahan status
2. Edit file data beasiswa (nama, kategori, status, syarat, kontak, URL)
3. Simpan dan push ke GitHub
4. Halaman publik auto-update dalam waktu singkat via Puify | +| Alt Flow | 3a. Error saat deploy → halaman publik tidak berubah, admin perbaiki dan push ulang | +| Postcondition | Info beasiswa terbaru tersedia di halaman publik 24/7 | + +--- + +## 4. Kebutuhan Antarmuka Eksternal + +### 4.1 Antarmuka Pengguna (UI) + +- Responsive design: breakpoint 320px (mobile), 768px (tablet), 1280px (desktop) +- Warna utama: Biru Informatika `#2B4590` dan Kuning `#F5A623` (branding UNTAN) +- Font: Inter atau Poppins, minimal 14px untuk body text +- Waktu respons antarmuka ≤ 3 detik pada koneksi 10 Mbps +- Aksesibilitas WCAG 2.1 level AA (kontras warna, ARIA label, navigasi keyboard) +- Semua elemen interaktif memiliki feedback visual saat hover/klik + +**Halaman / Seksi:** + +| Seksi | ID | Konten Utama | +|---|---|---| +| Header & Navigasi | — | Navbar sticky, logo UNTAN, toggle ID/EN, info ticker | +| Hero | `#hero` | Judul "Beasiswa Studi & Penelitian", deskripsi, CTA kuning, foto mahasiswa | +| Statistik Counter | `#statistics` | 3 angka animasi: Total Penerima, Pemerintah, Swasta | +| Direktori Beasiswa | `#directory` | Grid kartu, tab filter, real-time search, popup detail | +| Testimoni | `#testimonial` | Carousel foto+nama+kutipan penerima beasiswa | +| CTA | `#cta` | Banner ajakan + tombol WhatsApp & Instagram | +| Footer | `#footer` | Logo, alamat, kontak, sosial media, ilustrasi Pontianak | + +### 4.2 Antarmuka Hardware +- Browser modern: Chrome/Firefox/Edge ≥v100, Safari ≥v15 +- Koneksi minimal 1 Mbps; optimal 10 Mbps +- Resolusi minimal 320px lebar +- Tidak butuh hardware khusus (kamera, printer, sensor, dll.) + +### 4.3 Antarmuka Software + +| Layanan | Tujuan | Protokol | +|---|---|---| +| Dedicated Server + Puify | Hosting dev & production, auto-deploy dari GitHub | HTTPS | +| GitHub | Version control, kolaborasi, deliverable akhir | HTTPS/SSH | +| Sumber Resmi Beasiswa | Link eksternal di popup (dibuka tab baru) | HTTPS | +| WhatsApp / Instagram UNTAN | Tombol CTA | HTTPS / wa.me | +| Figma | Desain mockup & wireframe acuan implementasi | HTTPS | +| Web Scraper | Ambil data beasiswa dari sumber resmi | HTTPS | + +### 4.4 Antarmuka Komunikasi +- Semua file dikirim via HTTPS dengan sertifikat SSL/TLS valid +- Fitur interaktif (filter, search, toggle bahasa, popup, counter) berjalan client-side (JS) — tanpa request ke server +- Semua link eksternal: `target="_blank"` + `rel="noopener noreferrer"` +- Tidak menggunakan cookie, session storage, atau autentikasi pengguna (v1.0) + +--- + +## 5. Kebutuhan Non-Fungsional + +### NFR-01: Performa +- **P-01** Loading halaman ≤ 3 detik pada koneksi 10 Mbps +- **P-02** Filter beasiswa merespons < 0,5 detik setelah klik +- **P-03** Tetap responsif dan optimal di desktop, tablet, dan smartphone + +### NFR-02: Keamanan +- **S-01** Semua komunikasi via HTTPS dengan SSL/TLS +- **S-02** Source code bersih dari script berbahaya, bebas celah XSS +- **S-03** Semua link CTA dan pendaftaran mengarah ke sumber resmi tervalidasi + +### NFR-03: Skalabilitas +- **SC-01** Mampu menampilkan minimal 100 data beasiswa tanpa penurunan performa +- **SC-02** Struktur kode memungkinkan penambahan kategori baru tanpa perubahan besar +- **SC-03** Sistem bilingual mendukung penambahan bahasa baru di masa depan + +### NFR-04: Ketersediaan & Reliabilitas +- **R-01** Uptime minimal 99% selama masa operasional +- **R-02** Dapat diakses 24 jam selama server aktif +- **R-03** Backup source code via Git/GitHub untuk pemulihan data + +### NFR-05: Usability +- **U-01** Antarmuka bilingual ID/EN +- **U-02** Pengguna menemukan info beasiswa dalam < 2 menit via navigasi & filter +- **U-03** Tombol CTA di Hero kontras dan posisinya jelas + +### NFR-06: Maintainability +- **M-01** Tech stack: HTML5, CSS3 + Tailwind CSS, JavaScript ES6+ — kode rapi dan mudah dipelihara +- **M-02** Semua perubahan dikelola via Git/GitHub (version control) +- **M-03** Dokumentasi teknis & panduan deployment disertakan saat penyerahan akhir + +--- + +## 6. Batasan & Kendala + +### 6.1 Batasan Implementasi +- Tech stack terkunci: HTML5, CSS3, Tailwind CSS, JavaScript ES6+, Figma, Git/GitHub +- Single static landing page — tidak ada backend, database, atau login +- Harus berjalan optimal di Chrome, Firefox, Edge versi terbaru +- Wajib responsif: desktop, tablet, smartphone + +### 6.2 Batasan Proyek +- Durasi: 10 hari kerja (1 Mei – 11 Mei 2026) +- Tim: 5 orang dengan peran tetap (PM, Backend, Frontend, UI/UX, QA) +- Revisi antarmuka/konten sesuai batas yang disepakati +- Penambahan fitur baru saat development = di luar ruang lingkup utama + +### 6.3 Regulasi & Standar +- UU PDP No. 27/2022 untuk pengelolaan data testimoni mahasiswa +- Visual harus selaras branding resmi Informatika UNTAN +- Memenuhi prinsip aksesibilitas dasar (navigasi jelas, tampilan informatif) diff --git a/groups/ApeNameTeamE/assets/css/style.css b/groups/ApeNameTeamE/assets/css/style.css new file mode 100644 index 0000000..77bb698 --- /dev/null +++ b/groups/ApeNameTeamE/assets/css/style.css @@ -0,0 +1,1596 @@ +/* ===================================================== + INFORMATIKA UNTAN — Website Beasiswa + Custom CSS (Complementary to Tailwind CSS) + ===================================================== */ + +/* ===== CSS VARIABLES ===== */ +:root { + --color-primary: #003150; + --color-secondary: #feb404; + --color-bg: #FFFFFF; + --color-text: #1A1A1A; + --color-accent: #6B7280; + --color-success: #10B981; + --color-danger: #EF4444; + --color-overlay: rgba(0, 0, 0, 0.5); + --font-sans: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; + --font-serif: 'Roboto Condensed', sans-serif; + --transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1); + --shadow-sm: 0 1px 3px rgba(0, 0, 0, 0.08); + --shadow-card: 0 2px 12px rgba(0, 0, 0, 0.08); + --shadow-card-hover: 0 8px 30px rgba(43, 69, 144, 0.15); + --shadow-popup: 0 20px 60px rgba(0, 0, 0, 0.3); + --radius: 12px; + --navbar-height: 108px; + /* 60px top bar putih + 48px main nav kuning */ +} + +/* ===== BASE RESET ===== */ +*, +*::before, +*::after { + box-sizing: border-box; + margin: 0; + padding: 0; +} + +html { + scroll-behavior: smooth; + font-size: 16px; +} + +body { + font-family: var(--font-sans); + color: var(--color-text); + line-height: 1.65; + overflow-x: hidden; + background: var(--color-bg); +} + +/* ===== SCROLLBAR ===== */ +::-webkit-scrollbar { + width: 5px; +} + +::-webkit-scrollbar-track { + background: #f1f5f9; +} + +::-webkit-scrollbar-thumb { + background: var(--color-primary); + border-radius: 3px; +} + +/* ===== STICKY NAVBAR ===== */ +#navbar { + position: fixed; + top: 0; + left: 0; + right: 0; + z-index: 1000; + transition: var(--transition); +} + +/* ── Top Bar (DARK NAVY sesuai Figma) ── */ +.navbar-top { + background: #003150; + height: 60px; + display: flex; + align-items: center; +} + +/* Logo emblem */ +.navbar-logo-emblem { + flex-shrink: 0; + display: flex; + align-items: center; + justify-content: center; +} + +.navbar-logo-name { + font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; + font-size: 1.125rem; + /* text-lg = 18px */ + font-weight: 700; + color: #ffffff; + line-height: 1; + letter-spacing: 0.1em; + /* tracking-widest */ + text-transform: uppercase; + margin-bottom: 0.25rem; +} + +.navbar-logo-sub { + font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif; + font-size: 10px; + /* text-[10px] */ + font-weight: 400; + color: rgba(226, 232, 240, 0.9); + /* text-slate-200 opacity-90 */ + letter-spacing: 0.15em; + /* tracking-[0.15em] */ + margin-top: 0.125rem; + text-transform: uppercase; +} + +@media (min-width: 1024px) { + .navbar-logo-name { + font-size: 1.5rem; + } + + /* lg:text-2xl = 24px */ + .navbar-logo-sub { + font-size: 0.875rem; + letter-spacing: 0.3em; + } + + /* lg:text-sm, lg:tracking-[0.3em] */ +} + +/* "SATU UNTAN" text */ +.navbar-satu { + font-size: 11px; + font-weight: 700; + color: rgba(255, 255, 255, 0.85); + letter-spacing: 0.5px; + text-transform: uppercase; +} + +/* Icon buttons on top bar (dark bg version) */ +.navbar-icon-btn { + width: 32px; + height: 32px; + border-radius: 50%; + background: rgba(255, 255, 255, 0.12); + border: 1px solid rgba(255, 255, 255, 0.2); + display: flex; + align-items: center; + justify-content: center; + color: rgba(255, 255, 255, 0.8); + cursor: pointer; + transition: var(--transition); +} + +.navbar-icon-btn:hover { + background: rgba(255, 255, 255, 0.22); + color: #ffffff; +} + +.navbar-search-btn { + width: 32px; + height: 32px; + border-radius: 50%; + background: none; + border: none; + display: flex; + align-items: center; + justify-content: center; + color: rgba(255, 255, 255, 0.75); + cursor: pointer; + transition: var(--transition); +} + +.navbar-search-btn:hover { + color: #ffffff; +} + +/* Language Toggle — dark top bar */ +#lang-toggle { + display: flex; + align-items: center; + gap: 4px; +} + +.lang-btn { + padding: 0; + font-size: 11px; + font-weight: 500; + color: rgba(255, 255, 255, 0.6); + cursor: pointer; + border: none; + background: none; + transition: var(--transition); + letter-spacing: 0.5px; +} + +.lang-btn:hover { + color: #ffffff; +} + +.lang-btn.active { + font-weight: 800; + color: #ffffff; +} + +.lang-divider { + color: rgba(255, 255, 255, 0.4); + font-size: 10px; + margin: 0 2px; +} + +/* ── Main Nav Bar (KUNING) ── */ +.navbar-main { + background: var(--color-secondary); + height: 48px; + display: none; + align-items: center; +} + +@media (min-width: 1024px) { + .navbar-main { + display: flex; + } +} + +/* Nav links — teks gelap di atas latar kuning */ +.nav-link { + position: relative; + color: #0a1530; + text-decoration: none; + transition: color 0.2s; + white-space: nowrap; +} + +.nav-link:hover { + color: #000000; +} + +.nav-link.active { + color: #000000 !important; +} + +/* ===== INFO TICKER ===== */ +.ticker-wrapper { + background: var(--color-primary); + border-top: 1px solid rgba(255, 255, 255, 0.05); + height: 40px; + display: flex; + align-items: center; + overflow: hidden; + + /* Sticky behavior */ + position: fixed; + top: 108px; + left: 0; + right: 0; + z-index: 40; + transform: translateY(-100%); + opacity: 0; + transition: transform 0.3s ease, opacity 0.3s ease; +} + +.ticker-wrapper.show-ticker { + transform: translateY(0); + opacity: 1; +} + +/* Badge wrapper */ +.ticker-badge-block { + flex-shrink: 0; + background: rgba(0, 0, 0, 0.15); + /* Slightly darker than primary */ + height: 100%; + display: flex; + align-items: center; + padding: 0 20px; + border-right: 1px solid rgba(255, 255, 255, 0.1); + position: relative; + z-index: 2; +} + +/* Badge "INFO TERBARU" */ +.ticker-badge { + background: var(--color-secondary); + color: #1a1a1a; + font-size: 10px; + font-weight: 800; + padding: 4px 8px; + border-radius: 2px; + white-space: nowrap; + letter-spacing: 0.8px; + text-transform: uppercase; +} + +/* Area overflow ticker */ +.ticker-scroll-area { + flex: 1; + overflow: hidden; + height: 100%; + position: relative; + display: flex; + align-items: center; +} + +/* Inner wrapper: dua salinan teks side-by-side, dianimasikan */ +.ticker-inner { + display: flex; + align-items: center; + animation: ticker-scroll 40s linear infinite; + will-change: transform; +} + +.ticker-inner:hover { + animation-play-state: paused; +} + +/* Setiap salinan teks ticker */ +.ticker-track { + display: inline-flex; + align-items: center; + white-space: nowrap; + font-size: 12px; + font-weight: 500; + color: rgba(255, 255, 255, 0.85); + padding-left: 20px; +} + +@keyframes ticker-scroll { + 0% { + transform: translateX(0); + } + + 100% { + transform: translateX(-50%); + } +} + +/* ===== HERO SECTION ===== */ +.hero-section { + min-height: 500px; + position: relative; + display: flex; + align-items: center; + padding: 48px 0 60px; + overflow: hidden; +} + +/* Background — solid dark blue sesuai Figma */ +.hero-bg { + position: absolute; + inset: 0; + background: #003150; + z-index: 0; +} + +/* Subtle dot grid overlay */ +.hero-bg::before { + content: ''; + position: absolute; + inset: 0; + background-image: + radial-gradient(circle at 10% 80%, rgba(245, 166, 35, 0.08) 0%, transparent 40%), + radial-gradient(circle at 90% 20%, rgba(255, 255, 255, 0.03) 0%, transparent 35%); +} + +.hero-bg::after { + content: ''; + position: absolute; + inset: 0; + background-image: radial-gradient(rgba(255, 255, 255, 0.025) 1px, transparent 1px); + background-size: 28px 28px; +} + +.hero-content { + position: relative; + z-index: 10; +} + +/* Badge hero — outline style sesuai Figma (border kuning, bg transparan) */ +.hero-badge { + display: inline-flex; + align-items: center; + gap: 6px; + border: 1.5px solid var(--color-secondary); + color: var(--color-secondary); + background: rgba(245, 166, 35, 0.08); + font-size: 11px; + font-weight: 700; + padding: 6px 16px; + border-radius: 999px; + text-transform: uppercase; + letter-spacing: 1px; + margin-bottom: 20px; +} + +.hero-title { + font-family: var(--font-serif); + font-size: clamp(36px, 5vw, 60px); + font-weight: 800; + color: white; + line-height: 1.15; + margin-bottom: 12px; +} + +.hero-subtitle { + font-size: 15px; + color: rgba(255, 255, 255, 0.75); + font-style: italic; + margin-bottom: 16px; +} + +.hero-desc { + font-size: 14px; + color: rgba(255, 255, 255, 0.65); + line-height: 1.7; + max-width: 440px; + margin-bottom: 32px; +} + +/* CTA button — kuning solid, teks gelap (sesuai Figma) */ +.hero-cta { + display: inline-flex; + align-items: center; + gap: 8px; + background: var(--color-secondary); + color: #1a1a1a; + font-weight: 700; + font-size: 14px; + padding: 13px 26px; + border-radius: 8px; + text-decoration: none; + transition: var(--transition); + box-shadow: 0 4px 16px rgba(245, 166, 35, 0.35); +} + +.hero-cta:hover { + background: #e8960f; + transform: translateY(-2px); + box-shadow: 0 8px 24px rgba(245, 166, 35, 0.45); + color: #1a1a1a; +} + +.hero-cta i { + transition: transform 0.3s; + font-size: 13px; +} + +.hero-cta:hover i { + transform: translateX(4px); +} + +/* Hero image — foto lebih besar dan rounded sesuai Figma */ +.hero-image-wrap { + position: relative; + max-width: 480px; + margin-left: auto; +} + +.hero-image-wrap img { + width: 100%; + height: 400px; + object-fit: cover; + border-radius: 16px; + box-shadow: 0 20px 50px rgba(0, 0, 0, 0.45); + border: 2px solid rgba(255, 255, 255, 0.1); + display: block; +} + +/* Small decorative circle */ +.hero-image-wrap::before { + content: ''; + position: absolute; + bottom: -12px; + right: -12px; + width: 60px; + height: 60px; + border: 3px solid var(--color-secondary); + border-radius: 50%; + opacity: 0.3; + z-index: -1; +} + +/* ===== STATISTICS SECTION ===== */ +.stats-section { + background: var(--color-secondary); + padding: 36px 0; +} + +.stat-item { + text-align: center; + padding: 0 20px; + position: relative; +} + +.stat-item+.stat-item::before { + content: ''; + position: absolute; + left: 0; + top: 15%; + height: 70%; + width: 1px; + background: rgba(255, 255, 255, 0.35); +} + +.stat-number { + font-family: var(--font-serif); + font-size: clamp(36px, 5vw, 52px); + font-weight: 800; + color: #1a1a1a; + line-height: 1; + letter-spacing: -1px; +} + +.stat-label { + font-size: 11px; + color: #2d2d2d; + margin-top: 8px; + line-height: 1.45; + font-weight: 500; +} + +/* ===== SECTION LABEL & BADGE ===== */ +.section-badge { + display: inline-flex; + align-items: center; + border: 1px solid rgba(245, 166, 35, 0.4); + background: rgba(245, 166, 35, 0.12); + color: var(--color-secondary); + font-size: 11px; + font-weight: 700; + padding: 5px 14px; + border-radius: 999px; + text-transform: uppercase; + letter-spacing: 1px; +} + +.section-label { + font-size: 11px; + font-weight: 800; + color: var(--color-secondary); + text-transform: uppercase; + letter-spacing: 2px; + display: block; + margin-bottom: 6px; +} + +.section-title { + font-family: var(--font-serif); + font-size: clamp(32px, 4vw, 42px); + font-weight: 800; + color: #003150; + line-height: 1.2; + margin-bottom: 12px; + letter-spacing: -0.5px; +} + +.section-desc { + font-size: 14px; + color: #64748b; + line-height: 1.65; + max-width: 600px; +} + +/* Button Panduan Beasiswa */ +.btn-panduan { + display: inline-flex; + align-items: center; + gap: 8px; + background: rgba(245, 166, 35, 0.12); + border: 1px solid rgba(245, 166, 35, 0.3); + color: var(--color-secondary); + font-weight: 600; + font-size: 13px; + padding: 10px 20px; + border-radius: 6px; + text-decoration: none; + transition: var(--transition); +} + +.btn-panduan:hover { + background: rgba(245, 166, 35, 0.2); + border-color: rgba(245, 166, 35, 0.5); +} + +/* ===== FILTER TABS ===== */ +.filter-tabs { + display: flex; + flex-wrap: wrap; + gap: 8px; + align-items: center; +} + +.filter-tab { + padding: 8px 20px; + font-size: 12px; + font-weight: 600; + border-radius: 999px; + border: 1px solid #e5e7eb; + background: white; + color: #4b5563; + cursor: pointer; + transition: var(--transition); + white-space: nowrap; + letter-spacing: 0.3px; +} + +.filter-tab:hover { + border-color: #d1d5db; + color: #003150; + background: #f9fafb; +} + +.filter-tab.active { + background: #003150; + color: white; + border-color: #003150; + box-shadow: none; +} + +/* ===== SEARCH INPUT ===== */ +.search-wrapper { + position: relative; +} + +.search-input { + width: 100%; + padding: 9px 16px 9px 38px; + border: 1px solid #e5e7eb; + border-radius: 999px; + font-size: 13px; + font-family: var(--font-inter); + color: var(--color-text); + outline: none; + transition: var(--transition); + background: white; +} + +.search-input:focus { + border-color: var(--color-primary); + box-shadow: 0 0 0 3px rgba(43, 69, 144, 0.08); +} + +.search-input::placeholder { + color: #9ca3af; +} + +.search-icon { + position: absolute; + left: 14px; + top: 50%; + transform: translateY(-50%); + color: #9ca3af; + font-size: 13px; + pointer-events: none; +} + +/* ===== SORT BUTTON ===== */ +.btn-sort { + display: inline-flex; + align-items: center; + gap: 8px; + padding: 9px 20px; + background: white; + border: 1px solid #e5e7eb; + border-radius: 999px; + color: #4b5563; + font-size: 12px; + font-weight: 500; + cursor: pointer; + transition: var(--transition); + white-space: nowrap; +} + +.btn-sort:hover { + background: #f9fafb; + border-color: #d1d5db; + color: #003150; +} + +/* ===== SCHOLARSHIP CARDS — Schoters Style ===== */ +.scholarship-card { + background: white; + border-radius: 16px; + box-shadow: 0 2px 16px rgba(0,0,0,0.06); + overflow: hidden; + transition: var(--transition); + border: 1px solid #eef2f8; + display: flex; + flex-direction: column; + position: relative; + cursor: default; +} + +.scholarship-card:hover { + box-shadow: 0 8px 32px rgba(0,49,80,0.12); + transform: translateY(-4px); + border-color: rgba(0,49,80,0.08); +} + + +/* ─── Card Body ─── */ +.card-body { + padding: 20px 20px 18px; + flex: 1; + display: flex; + flex-direction: column; +} + +/* ─── Title ─── */ +.card-title { + font-size: 15px; + font-weight: 800; + color: #0f172a; + line-height: 1.4; + margin: 0 0 6px; + display: -webkit-box; + -webkit-line-clamp: 3; + -webkit-box-orient: vertical; + overflow: hidden; +} + +/* ─── Subtitle (Funding Type) ─── */ +.card-subtitle { + font-size: 12.5px; + color: #64748b; + margin: 0 0 12px; + font-weight: 400; +} + +/* ─── Pills Row ─── */ +.card-pills { + display: flex; + flex-wrap: wrap; + gap: 7px; + margin-bottom: 14px; +} + +.card-pill { + display: inline-flex; + align-items: center; + padding: 4px 12px; + border-radius: 999px; + font-size: 11.5px; + font-weight: 600; + background: #f1f5f9; + color: #475569; + letter-spacing: 0.2px; +} + +.card-pill-level { + background: #dbeafe; + color: #1e40af; +} + +/* ─── Divider ─── */ +.card-divider { + border: none; + border-top: 1px solid #f1f5f9; + margin: 0 0 14px; +} + +/* ─── Two-column Date Row ─── */ +.card-dates { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 8px; + margin-bottom: 14px; +} + +.card-date-col { + display: flex; + flex-direction: column; + gap: 3px; +} + +.card-date-label { + font-size: 11px; + font-weight: 700; + color: #0f172a; +} + +.card-date-value { + font-size: 12px; + color: #64748b; + font-weight: 400; +} + +/* ─── Status Button ─── */ +.card-status-btn { + width: 100%; + padding: 10px 16px; + border-radius: 8px; + font-size: 13px; + font-weight: 700; + border: none; + cursor: default; + text-align: center; + margin-bottom: 10px; +} + +.status-btn-buka { + background: #dcfce7; + color: #15803d; +} + +.status-btn-ditutup { + background: #fee2e2; + color: #b91c1c; +} + +.status-btn-segera { + background: #fef9c3; + color: #a16207; +} + +/* ─── Outline Selengkapnya Button ─── */ +.btn-selengkapnya { + width: 100%; + padding: 10px 16px; + border-radius: 8px; + border: 1.5px solid #e2e8f0; + background: white; + color: #0f172a; + font-size: 13px; + font-weight: 700; + cursor: pointer; + text-align: center; + transition: var(--transition); + font-family: var(--font-sans); + display: block; +} + +.btn-selengkapnya:hover { + border-color: var(--color-primary); + color: var(--color-primary); + background: #f8faff; +} + +/* Entrance animation */ +@keyframes fadeInCard { + from { opacity: 0; transform: translateY(16px); } + to { opacity: 1; transform: translateY(0); } +} + +.scholarship-card.fade-in-up { + animation: fadeInCard 0.4s ease both; +} + +/* ===== EMPTY STATE ===== */ +.empty-state { + grid-column: 1 / -1; + text-align: center; + padding: 64px 24px; + color: #94a3b8; +} + +.empty-state i { + font-size: 48px; + color: #e2e8f0; + margin-bottom: 16px; + display: block; +} + +/* ===== PAGINATION ===== */ +.pagination-container { + display: flex; + align-items: center; + gap: 6px; + justify-content: center; + margin-top: 40px; +} + +.page-btn { + width: 38px; + height: 38px; + border-radius: 8px; + border: 2px solid #e2e8f0; + background: white; + color: #64748b; + font-size: 13px; + font-weight: 600; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + transition: var(--transition); + font-family: var(--font-inter); +} + +.page-btn:hover:not(:disabled) { + border-color: var(--color-primary); + color: var(--color-primary); + background: #eff3ff; +} + +.page-btn.active { + background: var(--color-primary); + border-color: var(--color-primary); + color: white; + box-shadow: 0 4px 12px rgba(43, 69, 144, 0.3); +} + +.page-btn:disabled { + opacity: 0.38; + cursor: not-allowed; +} + +/* ===== POPUP MODAL ===== */ +#popup-overlay { + position: fixed; + inset: 0; + z-index: 9999; + display: none; + align-items: center; + justify-content: center; + padding: 16px; +} + +#popup-overlay.show { + display: flex; +} + +.popup-backdrop { + position: absolute; + inset: 0; + background: var(--color-overlay); + backdrop-filter: blur(4px); + -webkit-backdrop-filter: blur(4px); +} + +.popup-modal { + position: relative; + background: white; + border-radius: 20px; + box-shadow: var(--shadow-popup); + width: 100%; + max-width: 500px; + max-height: 90vh; + overflow-y: auto; + z-index: 10; + transition: opacity 0.25s ease, transform 0.25s ease; + opacity: 0; + transform: scale(0.92) translateY(8px); +} + +#popup-overlay.show .popup-modal { + opacity: 1; + transform: scale(1) translateY(0); +} + +.popup-close { + position: absolute; + top: 14px; + right: 14px; + z-index: 20; + width: 34px; + height: 34px; + border-radius: 50%; + background: rgba(255, 255, 255, 0.9); + backdrop-filter: blur(4px); + border: none; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + color: #374151; + font-size: 14px; + transition: var(--transition); + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.12); +} + +.popup-close:hover { + background: #f1f5f9; + transform: rotate(90deg); +} + +.popup-hero { + width: 100%; + height: 200px; + object-fit: cover; + display: block; + border-radius: 20px 20px 0 0; +} + +.popup-hero-logo { + width: 100%; + height: 200px; + background: linear-gradient(135deg, #EEF2FF 0%, #E0E7FF 100%); + display: flex; + align-items: center; + justify-content: center; + border-radius: 20px 20px 0 0; +} + +.popup-hero-logo img { + max-height: 100px; + max-width: 75%; + object-fit: contain; +} + +.popup-body { + padding: 24px; +} + +.popup-kategori-row { + display: flex; + align-items: center; + gap: 10px; + margin-bottom: 12px; +} + +.popup-kategori { + font-size: 11px; + color: var(--color-accent); + font-weight: 600; + background: #f1f5f9; + padding: 3px 10px; + border-radius: 999px; +} + +.popup-title { + font-family: var(--font-serif); + font-size: 20px; + font-weight: 700; + color: var(--color-primary); + line-height: 1.3; + margin-bottom: 10px; +} + +.popup-desc { + font-size: 13px; + color: #4b5563; + line-height: 1.65; + margin-bottom: 20px; +} + +.popup-section-title { + font-size: 12px; + font-weight: 700; + color: #374151; + display: flex; + align-items: center; + gap: 8px; + margin-bottom: 12px; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.popup-section-title i { + color: var(--color-secondary); +} + +.syarat-list { + list-style: none; + display: flex; + flex-direction: column; + gap: 8px; + margin-bottom: 20px; +} + +.syarat-list li { + display: flex; + align-items: flex-start; + gap: 8px; + font-size: 13px; + color: #4b5563; + line-height: 1.5; +} + +.syarat-list li i { + color: var(--color-success); + font-size: 11px; + margin-top: 3px; + flex-shrink: 0; +} + +.popup-periode { + display: grid; + grid-template-columns: 1fr 1fr; + gap: 12px; + background: #f8fafc; + border-radius: 10px; + padding: 14px 16px; + margin-bottom: 20px; +} + +.popup-periode-item label { + font-size: 10px; + color: #94a3b8; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.5px; + display: block; + margin-bottom: 4px; +} + +.popup-periode-item span { + font-size: 13px; + font-weight: 600; + color: #374151; +} + +.popup-kontak { + background: #fffbf0; + border: 1px solid #fde68a; + border-radius: 10px; + padding: 12px 14px; + margin-bottom: 20px; + font-size: 13px; + color: #92400e; + display: flex; + align-items: flex-start; + gap: 8px; +} + +.popup-kontak i { + color: var(--color-secondary); + margin-top: 1px; + flex-shrink: 0; +} + +.popup-cta { + display: flex; + align-items: center; + justify-content: center; + gap: 8px; + width: 100%; + background: var(--color-primary); + color: white; + font-weight: 700; + font-size: 14px; + padding: 14px 20px; + border-radius: 12px; + text-decoration: none; + transition: var(--transition); + border: none; + cursor: pointer; +} + +.popup-cta:hover { + background: #1e3272; + transform: translateY(-1px); + box-shadow: 0 6px 20px rgba(43, 69, 144, 0.3); + color: white; +} + +.popup-cta.disabled { + background: #94a3b8; + pointer-events: none; +} + +.popup-cta i { + transition: transform 0.3s; +} + +.popup-cta:hover i { + transform: translateX(4px); +} + +/* ===== TESTIMONIALS ===== */ +.testimonials-section { + background: #f8fafc; + padding: 72px 0; +} + +.testimonial-card { + background: white; + border-radius: 16px; + padding: 28px 22px; + text-align: center; + box-shadow: 0 4px 20px rgba(0, 0, 0, 0.06); + transition: var(--transition); + border: 1px solid #f0f4f8; + height: 100%; +} + +.testimonial-card:hover { + box-shadow: 0 10px 36px rgba(43, 69, 144, 0.12); + transform: translateY(-5px); +} + +.testimonial-avatar { + width: 82px; + height: 82px; + border-radius: 50%; + object-fit: cover; + margin: 0 auto 16px; + border: 3px solid var(--color-secondary); + display: block; +} + +.testimonial-name { + font-family: var(--font-serif); + font-size: 15px; + font-weight: 700; + color: var(--color-primary); + margin-bottom: 4px; +} + +.testimonial-beasiswa { + font-size: 11px; + color: var(--color-secondary); + font-weight: 600; + margin-bottom: 14px; + text-transform: uppercase; + letter-spacing: 0.5px; +} + +.testimonial-quote { + font-size: 13px; + color: #4b5563; + line-height: 1.65; + font-style: italic; + position: relative; +} + +/* Swiper custom styles */ +.swiper-pagination-bullet { + background: #cbd5e1 !important; + opacity: 1 !important; + width: 8px !important; + height: 8px !important; + transition: var(--transition); +} + +.swiper-pagination-bullet-active { + background: var(--color-secondary) !important; + width: 24px !important; + border-radius: 4px !important; +} + +/* ===== CTA SECTION ===== */ +.cta-section { + padding: 72px 0; + background: #f8fafc; +} + +.cta-card { + background: #003150; + border-radius: 24px; + padding: 64px 40px; + text-align: center; + position: relative; + overflow: hidden; +} + +.cta-card::before, +.cta-card::after { + content: ''; + position: absolute; + border-radius: 50%; + background: rgba(255, 255, 255, 0.04); +} + +.cta-card::before { + width: 300px; + height: 300px; + top: -100px; + right: -80px; +} + +.cta-card::after { + width: 200px; + height: 200px; + bottom: -60px; + left: -60px; +} + +.cta-title { + font-family: var(--font-serif); + font-size: clamp(22px, 3vw, 30px); + font-weight: 700; + color: white; + margin-bottom: 12px; + position: relative; + z-index: 1; +} + +.cta-desc { + font-size: 14px; + color: rgba(255, 255, 255, 0.68); + max-width: 420px; + margin: 0 auto 32px; + line-height: 1.65; + position: relative; + z-index: 1; +} + +.cta-buttons { + display: flex; + gap: 14px; + justify-content: center; + flex-wrap: wrap; + position: relative; + z-index: 1; +} + +.cta-btn-primary { + display: inline-flex; + align-items: center; + gap: 8px; + background: var(--color-secondary); + color: #0a1530; + font-weight: 700; + font-size: 13px; + padding: 13px 26px; + border-radius: 8px; + text-decoration: none; + transition: var(--transition); + box-shadow: 0 4px 16px rgba(245, 166, 35, 0.4); +} + +.cta-btn-primary:hover { + background: #e8960f; + transform: translateY(-2px); + box-shadow: 0 8px 24px rgba(245, 166, 35, 0.5); + color: #0a1530; +} + +.cta-btn-secondary { + display: inline-flex; + align-items: center; + gap: 8px; + background: transparent; + border: 2px solid rgba(255, 255, 255, 0.5); + color: white; + font-weight: 700; + font-size: 13px; + padding: 11px 26px; + border-radius: 10px; + text-decoration: none; + transition: var(--transition); + cursor: pointer; +} + + +.cta-btn-secondary:hover { + background: rgba(255, 255, 255, 0.12); + border-color: white; + color: white; + transform: translateY(-2px); +} + +/* ===== FOOTER ===== */ +footer { + font-family: 'Roboto', sans-serif; +} + +.site-footer { + background: var(--color-primary); + color: white; + position: relative; + overflow: hidden; +} + +.footer-top { + padding: 52px 0 32px; +} + +.footer-follow-title { + text-align: center; + color: white; + font-size: 11px; + font-weight: 700; + letter-spacing: 2px; + margin-bottom: 12px; +} + +.social-icons { + display: flex; + justify-content: center; + gap: 16px; + margin-bottom: 40px; +} + +.social-icon { + width: 32px; + height: 32px; + display: flex; + align-items: center; + justify-content: center; + color: white; + font-size: 16px; + transition: var(--transition); + text-decoration: none; +} + +.social-icon:hover { + color: var(--color-secondary); + transform: translateY(-2px); +} + +.footer-logo { + display: flex; + align-items: center; + justify-content: center; + gap: 12px; + margin-bottom: 20px; +} + +.footer-logo img { + height: 44px; + width: auto; + object-fit: contain; +} + +.footer-logo-text { + text-align: left; + margin-left: 8px; +} + +.footer-logo-text .name { + font-family: var(--font-serif); + font-size: 20px; + font-weight: 700; + color: white; + line-height: 1.2; + letter-spacing: 2px; +} + +.footer-logo-text .sub { + font-size: 10px; + color: rgba(255, 255, 255, 0.7); + margin-top: 2px; + letter-spacing: 1px; +} + +.footer-address { + text-align: center; + color: rgba(255, 255, 255, 0.6); + font-size: 12px; + line-height: 1.8; + margin-top: 32px; +} + +.footer-address i { + color: var(--color-secondary); +} + +.address-main { + margin-bottom: 16px; +} + +.address-contact { + font-size: 11px; + color: rgba(255, 255, 255, 0.5); + margin-bottom: 40px; +} + +.footer-divider { + border: none; + border-top: 1px solid rgba(255, 255, 255, 0.08); + margin: 28px 0 20px; +} + +.footer-copy { + text-align: center; + font-size: 11px; + color: rgba(255, 255, 255, 0.28); + padding-bottom: 28px; +} + +.footer-illustration { + width: 100%; + display: block; + max-height: 180px; + object-fit: cover; + object-position: top; +} + +/* ===== BREADCRUMB ===== */ +.breadcrumb { + display: flex; + align-items: center; + gap: 8px; + font-size: 11px; + color: rgba(255, 255, 255, 0.5); + margin-bottom: 24px; +} + +.breadcrumb a { + color: rgba(255, 255, 255, 0.5); + text-decoration: none; + transition: color 0.2s; +} + +.breadcrumb a:hover { + color: rgba(255, 255, 255, 0.85); +} + +.breadcrumb .sep { + font-size: 9px; +} + +.breadcrumb .current { + color: rgba(255, 255, 255, 0.85); +} + +/* ===== ANIMATIONS ===== */ +@keyframes fadeInUp { + from { + opacity: 0; + transform: translateY(18px); + } + + to { + opacity: 1; + transform: translateY(0); + } +} + +.fade-in-up { + animation: fadeInUp 0.45s ease forwards; +} + +/* Skeleton loading */ +.skeleton { + background: linear-gradient(90deg, #f1f5f9 25%, #e2e8f0 50%, #f1f5f9 75%); + background-size: 200% 100%; + animation: shimmer 1.6s infinite; + border-radius: 8px; +} + +@keyframes shimmer { + 0% { + background-position: 200% 0; + } + + 100% { + background-position: -200% 0; + } +} + +/* ===== RESPONSIVE ===== */ +@media (max-width: 767px) { + :root { + --navbar-height: 104px; + } + + .hero-section { + padding: 32px 0 48px; + min-height: auto; + } + + .hero-title { + font-size: 32px; + } + + .hero-image-wrap { + display: none; + } + + .stats-section { + padding: 24px 0; + } + + .stat-item+.stat-item::before { + display: none; + } + + .cta-card { + padding: 40px 20px; + } + + .filter-tabs { + gap: 6px; + } + + .filter-tab { + padding: 7px 12px; + font-size: 10px; + } + + .popup-modal { + border-radius: 14px; + } + + .popup-periode { + grid-template-columns: 1fr; + } + + .testimonial-card { + padding: 22px 16px; + } +} + +@media (min-width: 768px) and (max-width: 1023px) { + .hero-image-wrap img { + height: 300px; + } +} + +@media (min-width: 1024px) { + .hero-section { + min-height: 540px; + } +} \ No newline at end of file diff --git a/groups/ApeNameTeamE/assets/images/hero/mahasiswa.png b/groups/ApeNameTeamE/assets/images/hero/mahasiswa.png new file mode 100644 index 0000000..b8244c2 Binary files /dev/null and b/groups/ApeNameTeamE/assets/images/hero/mahasiswa.png differ diff --git a/groups/ApeNameTeamE/assets/images/hero/pontianak-illustration.png b/groups/ApeNameTeamE/assets/images/hero/pontianak-illustration.png new file mode 100644 index 0000000..922a0e0 Binary files /dev/null and b/groups/ApeNameTeamE/assets/images/hero/pontianak-illustration.png differ diff --git a/groups/ApeNameTeamE/assets/images/logo/logo-untan.png b/groups/ApeNameTeamE/assets/images/logo/logo-untan.png new file mode 100644 index 0000000..3d45d4e Binary files /dev/null and b/groups/ApeNameTeamE/assets/images/logo/logo-untan.png differ diff --git a/groups/ApeNameTeamE/assets/js/API.js b/groups/ApeNameTeamE/assets/js/API.js new file mode 100644 index 0000000..628da88 --- /dev/null +++ b/groups/ApeNameTeamE/assets/js/API.js @@ -0,0 +1,81 @@ +// ===================================================== +// API.js — Mekanisme Fetch Data Beasiswa (terpusat) +// ----------------------------------------------------- +// Alur: coba API remote (Directus publik) → jika gagal, +// fallback ke berkas lokal `data/beasiswa.json`. +// +// Data remote dinormalisasi ke skema UI yang sama dengan +// data lokal agar filter.js dan popup.js tidak perlu berubah. +// ===================================================== + +(function (global) { + 'use strict'; + + const CONFIG = { + baseUrl: 'https://api.ifuntanhub.dev', + collection: '/items/beasiswa', + localSource: 'data/beasiswa.json', + }; + + // Normalise status remote → nilai yang dipakai UI + function normalizeStatus(s) { + if (!s) return 'Ditutup'; + const lower = s.toLowerCase(); + if (lower === 'dibuka' || lower === 'buka') return 'Buka'; + if (lower === 'ditutup') return 'Ditutup'; + return s; // "Segera Dibuka" atau nilai lain: tampilkan apa adanya + } + + // Petakan satu item Directus ke skema yang diharapkan filter.js / popup.js + function normalizeItem(item) { + const parts = [item.jenjang, item.negara, item.tipe_pendanaan].filter(Boolean); + return { + id: String(item.id), + nama: item.nama || '', + status: normalizeStatus(item.status), + kategori: item.tipe_pendanaan || '', + thumbnail: '', + deskripsi_singkat: parts.join(' · ') || 'Info beasiswa tersedia di sumber resmi.', + tanggal_buka: item.tanggal_buka || '', + tanggal_tutup: item.tenggat_waktu || '', + url_sumber: item.url || '', + syarat_umum: [], + kontak: '', + tags: parts, + }; + } + + async function fetchRemote() { + const res = await fetch(CONFIG.baseUrl + CONFIG.collection); + if (!res.ok) throw new Error(`API merespons HTTP ${res.status}`); + const json = await res.json(); + return (json.data || []).map(normalizeItem); + } + + async function fetchLocal() { + const res = await fetch(CONFIG.localSource); + if (!res.ok) throw new Error(`Gagal memuat data lokal (HTTP ${res.status})`); + const json = await res.json(); + return Array.isArray(json) ? json : json.data || []; + } + + async function getBeasiswa() { + try { + // Prioritas: data lokal (lengkap: url_sumber, syarat_umum, kontak tersedia) + // Remote API digunakan hanya sebagai fallback jika data lokal tidak ditemukan. + const data = await fetchLocal(); + return { data, source: 'local' }; + } catch (err) { + console.warn('[BeasiswaAPI] Data lokal gagal, fallback ke API remote:', err.message); + try { + const data = await fetchRemote(); + return { data, source: 'remote' }; + } catch (remoteErr) { + console.error('[BeasiswaAPI] Semua sumber gagal:', remoteErr.message); + throw remoteErr; + } + } + } + + global.BeasiswaAPI = { config: CONFIG, getBeasiswa, fetchRemote, fetchLocal }; +})(window); diff --git a/groups/ApeNameTeamE/assets/js/carousel.js b/groups/ApeNameTeamE/assets/js/carousel.js new file mode 100644 index 0000000..3dc3286 --- /dev/null +++ b/groups/ApeNameTeamE/assets/js/carousel.js @@ -0,0 +1,140 @@ +// ===================================================== +// carousel.js — Swiper.js Carousel Testimoni +// Touch-friendly, auto-play, responsive breakpoints +// + DUKUNGAN MULTI-BAHASA (ID/EN) Terintegrasi +// ===================================================== + +let testimoniSwiper = null; +let allTestimoniData = []; // Simpan data di memori agar tidak perlu loading ulang saat ganti bahasa + +// 1. Variabel penampung bahasa yang terhubung otomatis dengan tombol ID/EN +let activeCarouselLang = localStorage.getItem('if_untan_lang') || document.documentElement.lang || 'id'; + +// 2. Tangkap event perubahan bahasa secara langsung dari localization.js +document.addEventListener('languageChanged', (e) => { + // Update bahasa + if (e.detail && e.detail.lang) { + activeCarouselLang = e.detail.lang; + } else if (typeof window.getLang === 'function') { + activeCarouselLang = window.getLang(); + } else { + activeCarouselLang = document.documentElement.lang || 'id'; + } + + // Jika data sudah ada, langsung cetak ulang testimoninya + if (allTestimoniData && allTestimoniData.length > 0) { + renderTestimoniSlides(allTestimoniData); + initSwiper(allTestimoniData.length); // Swiper harus di-restart agar animasinya tidak rusak + } +}); + +/** Render slide testimoni ke dalam swiper-wrapper */ +function renderTestimoniSlides(data) { + const wrapper = document.getElementById('testimonial-wrapper'); + if (!wrapper) return; + + const lang = activeCarouselLang; // Gunakan bahasa terbaru + + wrapper.innerHTML = data.map(t => { + // Logika Pintar: Cek mode bahasa. Jika 'en' dan teks terjemahannya ada, pakai bahasa Inggris. + // Jika tidak, tetap tampilkan teks bahasa Indonesia (sebagai cadangan). + const beasiswaName = (lang === 'en' && t.nama_beasiswa_en) ? t.nama_beasiswa_en : t.nama_beasiswa; + const quote = (lang === 'en' && t.kutipan_en) ? t.kutipan_en : t.kutipan; + + return ` +
+
+ Foto ${t.nama} +
+ ${t.nama.charAt(0).toUpperCase()} +
+ +
${t.nama}
+
${beasiswaName}
+

"${quote}"

+
+
+ `; + }).join(''); +} + +/** Inisialisasi Swiper setelah slide di-render */ +function initSwiper(count) { + // Bersihkan swiper lama jika ada (penting agar tidak menumpuk saat ganti bahasa) + if (testimoniSwiper) { + testimoniSwiper.destroy(true, true); + testimoniSwiper = null; + } + + testimoniSwiper = new Swiper('.testimonial-swiper', { + slidesPerView: 1, + spaceBetween: 24, + loop: count > 3, + centerInsufficientSlides: true, + autoplay: { + delay: 4500, + disableOnInteraction: false, + pauseOnMouseEnter: true, + }, + pagination: { + el: '.testimonial-pagination', + clickable: true, + }, + grabCursor: true, + breakpoints: { + 640: { slidesPerView: 2 }, + 1024: { slidesPerView: 3 }, + }, + // Dukungan Aksesibilitas Dinamis (VoiceOver / Screen Reader) + a11y: { + prevSlideMessage: activeCarouselLang === 'en' ? 'Previous slide' : 'Slide sebelumnya', + nextSlideMessage: activeCarouselLang === 'en' ? 'Next slide' : 'Slide berikutnya', + }, + }); +} + +/** Fetch data testimoni dan render */ +async function initCarousel() { + const section = document.getElementById('testimonial'); + + try { + const res = await fetch('data/testimoni.json'); + if (!res.ok) throw new Error(`HTTP ${res.status}`); + + const data = await res.json(); + allTestimoniData = data; // Simpan ke variabel global + + if (!data || data.length === 0) { + section?.classList.add('hidden'); + return; + } + + renderTestimoniSlides(data); + requestAnimationFrame(() => initSwiper(data.length)); + + } catch { + section?.classList.add('hidden'); + } +} + +document.addEventListener('DOMContentLoaded', initCarousel); \ No newline at end of file diff --git a/groups/ApeNameTeamE/assets/js/counter.js b/groups/ApeNameTeamE/assets/js/counter.js new file mode 100644 index 0000000..b68851a --- /dev/null +++ b/groups/ApeNameTeamE/assets/js/counter.js @@ -0,0 +1,53 @@ +// ===================================================== +// counter.js — Animasi Counter Statistik +// Menggunakan IntersectionObserver + requestAnimationFrame +// ===================================================== + +/** + * Animasi angka dari 0 ke nilai target + * @param {HTMLElement} el - Elemen yang menampilkan angka + * @param {number} target - Angka target + * @param {number} duration - Durasi animasi dalam ms + */ +function animateCounter(el, target, duration = 1800) { + const startTime = performance.now(); + + function update(currentTime) { + const elapsed = currentTime - startTime; + const progress = Math.min(elapsed / duration, 1); + + // Ease out cubic — percepat di awal, lambat di akhir + const eased = 1 - Math.pow(1 - progress, 3); + const current = Math.round(eased * target); + + el.textContent = current; + + if (progress < 1) { + requestAnimationFrame(update); + } + } + + requestAnimationFrame(update); +} + +function initCounters() { + const counters = document.querySelectorAll('[data-counter]'); + if (!counters.length) return; + + const observer = new IntersectionObserver( + (entries) => { + entries.forEach(entry => { + if (entry.isIntersecting && !entry.target.dataset.animated) { + entry.target.dataset.animated = 'true'; + const target = parseInt(entry.target.dataset.counter, 10) || 0; + animateCounter(entry.target, target); + } + }); + }, + { threshold: 0.6 } + ); + + counters.forEach(el => observer.observe(el)); +} + +document.addEventListener('DOMContentLoaded', initCounters); diff --git a/groups/ApeNameTeamE/assets/js/filter.js b/groups/ApeNameTeamE/assets/js/filter.js new file mode 100644 index 0000000..c1894c5 --- /dev/null +++ b/groups/ApeNameTeamE/assets/js/filter.js @@ -0,0 +1,288 @@ +// ===================================================== +// filter.js — Fetch JSON, Render Kartu, Filter Tab, Pencarian, Paginasi +// Filter dan search berjalan KUMULATIF +// + DUKUNGAN MULTI-BAHASA (ID/EN) Terintegrasi +// ===================================================== + +const ITEMS_PER_PAGE = 6; + +let allData = []; +let activeFilter = 'semua'; +let searchKeyword = ''; +let currentPage = 1; + +// 1. Variabel penampung bahasa yang terhubung otomatis dengan tombol ID/EN +let activeLang = localStorage.getItem('if_untan_lang') || document.documentElement.lang || 'id'; + +// 2. Tangkap event perubahan bahasa secara langsung dari localization.js +document.addEventListener('languageChanged', (e) => { + if (e.detail && e.detail.lang) { + activeLang = e.detail.lang; // Perbarui bahasa! + } else { + activeLang = document.documentElement.lang || 'id'; + } + + // Jika data sudah ada, langsung cetak ulang kartunya + if (allData.length > 0) { + renderCards(); + } +}); + +// 3. Format tanggal cerdas berdasarkan bahasa +function formatDate(str) { + if (!str) return '—'; + const d = new Date(str); + if (isNaN(d.getTime())) return str; + + return d.toLocaleDateString(activeLang === 'en' ? 'en-US' : 'id-ID', { + day: 'numeric', month: 'long', year: 'numeric' + }); +} + +// 4. Kamus mini untuk teks dinamis dari JSON (Negara & Kategori) +function translateDynamic(text, lang) { + if (!text || lang === 'id') return text; + + const dict = { + 'Amerika Serikat': 'United States', + 'Swiss': 'Switzerland', + 'Pemerintah': 'Government', + 'Swasta': 'Private', + }; + + return dict[text] || text; +} + +function sanitize(str) { + return str.replace(/[<>&"']/g, c => + ({ '<': '<', '>': '>', '&': '&', '"': '"', "'": ''' }[c]) + ); +} + +function createCard(bsw) { + const lang = activeLang; // Selalu gunakan bahasa aktif terbaru + + // Terjemahan Tombol Status + let statusClass = 'status-btn-ditutup'; + let statusLabel = lang === 'en' ? 'Closed' : 'Ditutup'; + + const statusLower = (bsw.status || '').toLowerCase(); + if (statusLower === 'buka' || statusLower === 'dibuka') { + statusClass = 'status-btn-buka'; + statusLabel = lang === 'en' ? 'Registration Open' : 'Pendaftaran Dibuka'; + } else if (statusLower.includes('segera')) { + statusClass = 'status-btn-segera'; + statusLabel = lang === 'en' ? 'Opening Soon' : 'Segera Dibuka'; + } + + // --- KAMUS MINI UNTUK KARTU --- + const textMulai = lang === 'en' ? 'Start' : 'Mulai'; + const textDeadline = lang === 'en' ? 'Deadline' : 'Tenggat'; + const textSelengkapnya = lang === 'en' ? 'Read More' : 'Selengkapnya'; + + // Ambil pills (tags) dan terjemahkan negaranya + const tags = Array.isArray(bsw.tags) ? bsw.tags : []; + const jenjang = tags[0] || ''; + const skipPatterns = /^(S1|S2|S3|D3|D4|Swasta|Pemerintah|Fully Funded|Partially Funded|Beasiswa Penuh|Beasiswa Sebagian|Prestasi)$/i; + const rawNegara = tags.slice(1).find(t => !skipPatterns.test(t)) || ''; + const negara = translateDynamic(rawNegara, lang); + + // Terjemahan Subtitle (Kategori Beasiswa) + const tipe = bsw.kategori || ''; + const rawTipe = tipe.replace(/^beasiswa\s+/i, ''); + let subtitle = ''; + if (rawTipe) { + if (lang === 'en') { + const tipeEn = translateDynamic(rawTipe, lang); + subtitle = `${tipeEn} Scholarship`; + } else { + subtitle = `Beasiswa ${rawTipe}`; + } + } + + // Ambil nama dari versi Inggris jika ada + const namaBsw = (lang === 'en' && bsw.nama_en) ? bsw.nama_en : bsw.nama; + + const pillsHtml = [jenjang, negara] + .filter(Boolean) + .map((t, i) => `${t}`) + .join(''); + + const article = document.createElement('article'); + article.className = 'scholarship-card fade-in-up'; + article.setAttribute('role', 'listitem'); + article.setAttribute('data-id', bsw.id); + + article.innerHTML = ` +
+

${namaBsw}

+ ${subtitle ? `

${subtitle}

` : ''} + ${pillsHtml ? `
${pillsHtml}
` : ''} +
+
+
+ ${textMulai} + ${formatDate(bsw.tanggal_buka)} +
+
+ ${textDeadline} + ${formatDate(bsw.tanggal_tutup)} +
+
+ + +
+ `; + + return article; +} + +function getFiltered() { + const kw = searchKeyword.toLowerCase(); + return allData.filter(bsw => { + + // Logika Filter Tab S1 & Studi Lanjut + let matchFilter = false; + const tags = bsw.tags || []; + + if (activeFilter === 'semua') { + matchFilter = true; + } else if (activeFilter === 's1') { + matchFilter = tags.some(t => t.includes('S1')); + } else if (activeFilter === 'studi_lanjut') { + matchFilter = tags.some(t => t.includes('S2') || t.includes('S3')); + } + + // Logika Pencarian Search Bar + const matchSearch = !kw || + bsw.nama.toLowerCase().includes(kw) || + bsw.deskripsi_singkat.toLowerCase().includes(kw) || + tags.some(t => t.toLowerCase().includes(kw)); + + return matchFilter && matchSearch; + }); +} + +function renderCards() { + const grid = document.getElementById('beasiswa-grid'); + const pagCont = document.getElementById('pagination'); + const filtered = getFiltered(); + const lang = activeLang; // Gunakan bahasa terbaru + + grid.innerHTML = ''; + + if (filtered.length === 0) { + const emptyTitle = lang === 'en' ? 'No scholarships found' : 'Tidak ada beasiswa ditemukan'; + const emptyDesc = lang === 'en' ? 'Try adjusting your filters or search keywords' : 'Coba ubah filter atau kata kunci pencarian Anda'; + + grid.innerHTML = ` +
+ +

${emptyTitle}

+

${emptyDesc}

+
`; + pagCont.innerHTML = ''; + return; + } + + const totalPages = Math.ceil(filtered.length / ITEMS_PER_PAGE); + if (currentPage > totalPages) currentPage = totalPages; + const start = (currentPage - 1) * ITEMS_PER_PAGE; + const items = filtered.slice(start, start + ITEMS_PER_PAGE); + + items.forEach((bsw, i) => { + const card = createCard(bsw); + card.style.animationDelay = `${i * 55}ms`; + grid.appendChild(card); + }); + + renderPagination(totalPages, pagCont); +} + +function renderPagination(total, container) { + container.innerHTML = ''; + if (total <= 1) return; + + const make = (content, page, disabled = false, isActive = false) => { + const btn = document.createElement('button'); + btn.className = `page-btn${isActive ? ' active' : ''}`; + btn.innerHTML = content; + btn.disabled = disabled; + if (!disabled) { + btn.addEventListener('click', () => { + currentPage = page; + renderCards(); + const dir = document.getElementById('directory'); + if (dir) { + const top = dir.getBoundingClientRect().top + window.scrollY - 120; + window.scrollTo({ top, behavior: 'smooth' }); + } + }); + } + return btn; + }; + + container.appendChild(make('', currentPage - 1, currentPage === 1)); + for (let i = 1; i <= total; i++) { + container.appendChild(make(i, i, false, i === currentPage)); + } + container.appendChild(make('', currentPage + 1, currentPage === total)); +} + +function initFilterTabs() { + document.querySelectorAll('.filter-tab').forEach(btn => { + btn.addEventListener('click', () => { + document.querySelectorAll('.filter-tab').forEach(b => { + b.classList.remove('active'); + b.setAttribute('aria-selected', 'false'); + }); + btn.classList.add('active'); + btn.setAttribute('aria-selected', 'true'); + activeFilter = btn.dataset.filter; + currentPage = 1; + renderCards(); + }); + }); +} + +function initSearch() { + const input = document.getElementById('search-input'); + if (!input) return; + input.addEventListener('input', () => { + searchKeyword = sanitize(input.value).trim(); + currentPage = 1; + renderCards(); + }); +} + +async function initDirectory() { + const grid = document.getElementById('beasiswa-grid'); + try { + if (!window.BeasiswaAPI) throw new Error('Modul API.js (BeasiswaAPI) belum dimuat'); + const { data, source } = await window.BeasiswaAPI.getBeasiswa(); + allData = data; + window.beasiswaData = allData; + renderCards(); + } catch (err) { + const lang = activeLang; + const errTitle = lang === 'en' ? 'Failed to load scholarship data' : 'Gagal memuat data beasiswa'; + const errDesc = lang === 'en' ? 'Could not connect to the server. Please refresh or contact admin.' : 'Tidak dapat terhubung ke server. Silakan refresh atau hubungi admin.'; + + grid.innerHTML = ` +
+ +

${errTitle}

+

${errDesc}

+
`; + } +} + +document.addEventListener('DOMContentLoaded', () => { + initFilterTabs(); + initSearch(); + initDirectory(); +}); \ No newline at end of file diff --git a/groups/ApeNameTeamE/assets/js/main.js b/groups/ApeNameTeamE/assets/js/main.js new file mode 100644 index 0000000..b5681da --- /dev/null +++ b/groups/ApeNameTeamE/assets/js/main.js @@ -0,0 +1,173 @@ +// ===================================================== +// main.js — Inisialisasi Utama +// Sticky Navbar, Hamburger Menu, Smooth Scroll, AOS, Active Nav +// ===================================================== + +document.addEventListener('DOMContentLoaded', () => { + + // ─── AOS (Animate on Scroll) ──────────────────────── + AOS.init({ + duration: 700, + easing: 'ease-out-cubic', + once: true, + offset: 50, + }); + + + // ─── Sticky Navbar ────────────────────────────────── + // Navbar sudah fixed di CSS; tidak perlu mengubah warna karena + // warna primary sudah menjadi identitas halaman ini. + // Namun kita tambahkan shadow saat scroll untuk depth effect. + + // PERBAIKAN: Menyesuaikan ID dengan yang ada di index.html (nav-wrapper) + const navbar = document.getElementById('nav-wrapper') || document.getElementById('navbar'); + + const handleScroll = () => { + if (!navbar) return; // PERBAIKAN: Mencegah error jika elemen tidak ada di halaman + + if (window.scrollY > 10) { + navbar.style.boxShadow = '0 4px 20px rgba(0,0,0,0.25)'; + } else { + navbar.style.boxShadow = 'none'; + } + }; + + window.addEventListener('scroll', handleScroll, { passive: true }); + handleScroll(); // initial call + + + // ─── Ticker Visibility (Muncul setelah Hero & Stats) ─ + const ticker = document.querySelector('.ticker-wrapper'); + const statsSection = document.getElementById('statistics'); + + const handleTickerVisibility = () => { + if (!ticker || !statsSection) return; + + // Ticker muncul setelah melewati batas bawah elemen statistik + const statsBottom = statsSection.offsetTop + statsSection.offsetHeight; + + if (window.scrollY > statsBottom) { + ticker.classList.add('show-ticker'); + } else { + ticker.classList.remove('show-ticker'); + } + }; + + window.addEventListener('scroll', handleTickerVisibility, { passive: true }); + // Call once on load with a slight delay to ensure layout is ready + setTimeout(handleTickerVisibility, 100); + + + // ─── Hamburger Menu (Mobile) ───────────────────────── + const mobileBtn = document.getElementById('mobile-menu-button'); + const mobileMenu = document.getElementById('mobile-menu'); + const closeMobileBtn = document.getElementById('close-mobile-menu'); + + const closeMobileMenu = () => { + mobileMenu?.classList.add('-translate-x-full'); + mobileBtn?.setAttribute('aria-expanded', 'false'); + }; + + // openMobileMenu handled by inline script in HTML; this covers close-on-scroll + closeMobileBtn?.addEventListener('click', closeMobileMenu); + + + // ─── Smooth Scroll untuk anchor links ────────────── + // Sesuai SDD: CSS scroll-behavior + JS fallback dengan offset + document.querySelectorAll('a[href^="#"]').forEach(anchor => { + anchor.addEventListener('click', e => { + const href = anchor.getAttribute('href'); + const target = document.querySelector(href); + if (!target) return; + + e.preventDefault(); + + // PERBAIKAN: Mencegah error saat membaca offsetHeight jika navbar null + const navHeight = navbar ? navbar.offsetHeight : 110; + const top = target.getBoundingClientRect().top + window.scrollY - navHeight - 4; + window.scrollTo({ top, behavior: 'smooth' }); + + // Tutup mobile menu jika sedang terbuka + closeMobileMenu(); + }); + }); + + + // ─── Active Nav Link via IntersectionObserver ────── + // Sesuai SDD fitur #4: highlight menu sesuai seksi yang terlihat + const sections = document.querySelectorAll('section[id]'); + const navLinks = document.querySelectorAll('a.nav-link'); + + const sectionObserver = new IntersectionObserver( + entries => { + entries.forEach(entry => { + if (entry.isIntersecting) { + navLinks.forEach(link => { + link.classList.remove('active'); + if (link.getAttribute('href') === `#${entry.target.id}`) { + link.classList.add('active'); + } + }); + } + }); + }, + { rootMargin: '-30% 0px -65% 0px' } + ); + + sections.forEach(s => sectionObserver.observe(s)); + + + // ─── Back to Top visibility ──────────────────────── + const backToTop = document.getElementById('back-to-top'); + if (backToTop) { + window.addEventListener('scroll', () => { + if (window.scrollY > 400) { + backToTop.classList.remove('opacity-0', 'pointer-events-none'); + backToTop.classList.add('opacity-100'); + } else { + backToTop.classList.add('opacity-0', 'pointer-events-none'); + backToTop.classList.remove('opacity-100'); + } + }, { passive: true }); + + backToTop.addEventListener('click', () => { + window.scrollTo({ top: 0, behavior: 'smooth' }); + }); + } + + // ─── Contact Us Modal (Hubungi Kami) ──────────────── + const btnOpenContact = document.getElementById('btn-open-contact'); + const contactOverlay = document.getElementById('contact-overlay'); + const contactModal = document.getElementById('contact-modal'); + const contactClose = document.getElementById('contact-close'); + const contactBackdrop = document.getElementById('contact-backdrop'); + + const openContactModal = () => { + if (!contactOverlay) return; + contactOverlay.classList.remove('hidden'); + contactOverlay.classList.add('flex'); + // Animasi muncul + setTimeout(() => { + contactOverlay.classList.remove('opacity-0'); + contactModal.classList.remove('scale-95'); + contactModal.classList.add('scale-100'); + }, 10); + }; + + const closeContactModal = () => { + if (!contactOverlay) return; + contactOverlay.classList.add('opacity-0'); + contactModal.classList.remove('scale-100'); + contactModal.classList.add('scale-95'); + // Tunggu animasi selesai baru di-hide + setTimeout(() => { + contactOverlay.classList.remove('flex'); + contactOverlay.classList.add('hidden'); + }, 300); + }; + + if (btnOpenContact) btnOpenContact.addEventListener('click', openContactModal); + if (contactClose) contactClose.addEventListener('click', closeContactModal); + if (contactBackdrop) contactBackdrop.addEventListener('click', closeContactModal); + +}); // end DOMContentLoaded \ No newline at end of file diff --git a/groups/ApeNameTeamE/assets/js/popup.js b/groups/ApeNameTeamE/assets/js/popup.js new file mode 100644 index 0000000..4af4072 --- /dev/null +++ b/groups/ApeNameTeamE/assets/js/popup.js @@ -0,0 +1,202 @@ +// ===================================================== +// popup.js — Modal Detail Beasiswa +// Tutup via: tombol ×, klik overlay, tekan Escape +// + DUKUNGAN MULTI-BAHASA (ID/EN) +// ===================================================== + +const overlay = document.getElementById('popup-overlay'); +const modal = document.getElementById('popup-modal'); +const closeBtn = document.getElementById('popup-close'); +const popupBody = document.getElementById('popup-content'); + +let currentOpenId = null; // Menyimpan status beasiswa mana yang sedang dibuka + +// Bertanya langsung ke mesin utama (localization.js) +function getPopupLang() { + if (typeof window.getLang === 'function') { + return window.getLang(); + } + return localStorage.getItem('if_untan_lang') || 'id'; +} + +// Format tanggal dinamis (ID / EN) +function fmtDate(str, lang) { + if (!str) return '—'; + const d = new Date(str); + if (isNaN(d.getTime())) return str; + return d.toLocaleDateString(lang === 'en' ? 'en-US' : 'id-ID', { + day: 'numeric', + month: 'long', + year: 'numeric' + }); +} + +// Kamus Teks Statis Modal +const popupDict = { + id: { + req_empty: 'Syarat belum tersedia. Kunjungi sumber resmi.', + req_title: 'Syarat Umum', + open_date: 'Tanggal Buka', + close_date: 'Tanggal Tutup', + contact: 'Kontak', + more_info: 'Info Lebih Lanjut', + no_link: 'Tautan tidak tersedia. Silakan hubungi admin prodi.', + status_open: 'Buka', + status_closed: 'Ditutup' + }, + en: { + req_empty: 'Requirements not available. Visit official source.', + req_title: 'General Requirements', + open_date: 'Open Date', + close_date: 'Closing Date', + contact: 'Contact', + more_info: 'More Information', + no_link: 'Link unavailable. Please contact department admin.', + status_open: 'Open', + status_closed: 'Closed' + } +}; + +/** + * Buka popup modal untuk beasiswa dengan ID tertentu + */ +function openPopup(id) { + currentOpenId = id; + const data = window.beasiswaData || []; + const bsw = data.find(b => b.id === id); + if (!bsw) return; + + const lang = getPopupLang(); + const d = popupDict[lang]; + + const isBuka = bsw.status === 'Buka' || bsw.status === 'Dibuka'; + const badgeClass = isBuka ? 'badge-buka' : 'badge-ditutup'; + + // Terjemahkan Status & Kategori + const statusText = isBuka ? d.status_open : (lang === 'en' && (bsw.status === 'Ditutup' || bsw.status === 'Tutup') ? d.status_closed : bsw.status); + + // Menerjemahkan Kategori (Misal: "Beasiswa Swasta" -> "Private Scholarship") + let kategoriText = bsw.kategori; + if (lang === 'en') { + if (bsw.kategori_en) { + kategoriText = bsw.kategori_en; + } else if (bsw.kategori.toLowerCase().includes('swasta')) { + kategoriText = 'Private Scholarship'; + } else if (bsw.kategori.toLowerCase().includes('pemerintah')) { + kategoriText = 'Government Scholarship'; + } + } + + // Teks Dinamis (Ambil _en dari JSON jika ada, jika tidak pakai ID) + const namaText = (lang === 'en' && bsw.nama_en) ? bsw.nama_en : bsw.nama; + const deskripsiText = (lang === 'en' && bsw.deskripsi_singkat_en) ? bsw.deskripsi_singkat_en : bsw.deskripsi_singkat; + const syaratData = (lang === 'en' && bsw.syarat_umum_en) ? bsw.syarat_umum_en : (bsw.syarat_umum || []); + + // Bangun list syarat umum + const syaratItems = syaratData + .map(s => ` +
  • + + ${s} +
  • `) + .join(''); + + const syaratHTML = syaratItems + ? `` + : `

    ${d.req_empty}

    `; + + const hasUrl = bsw.url_sumber && bsw.url_sumber !== '#'; + + // Render konten popup dengan template Anda yang dipertahankan + popupBody.innerHTML = ` + + `; + + // Tampilkan overlay + overlay.classList.add('show'); + document.body.style.overflow = 'hidden'; + + // Set focus ke modal untuk aksesibilitas + setTimeout(() => modal.focus(), 50); +} + +/** Tutup popup modal */ +function closePopup() { + currentOpenId = null; + overlay.classList.remove('show'); + document.body.style.overflow = ''; +} + +// === Event Listeners untuk menutup popup === +closeBtn?.addEventListener('click', closePopup); +document.getElementById('popup-backdrop')?.addEventListener('click', closePopup); +document.addEventListener('keydown', (e) => { + if (e.key === 'Escape' && overlay.classList.contains('show')) { + closePopup(); + } +}); + +// Jika bahasa diganti SAAT popup sedang terbuka, cetak ulang isinya! +document.addEventListener('languageChanged', () => { + if (currentOpenId && overlay.classList.contains('show')) { + openPopup(currentOpenId); + } +}); + +window.openPopup = openPopup; +window.closePopup = closePopup; \ No newline at end of file diff --git a/groups/ApeNameTeamE/data/beasiswa.json b/groups/ApeNameTeamE/data/beasiswa.json new file mode 100644 index 0000000..d15ff66 --- /dev/null +++ b/groups/ApeNameTeamE/data/beasiswa.json @@ -0,0 +1,285 @@ +[ + { + "id": "bsw-001", + "nama": "Boustany Foundation Scholarship, MBA - Harvard University", + "nama_en": "Boustany Foundation Scholarship, MBA - Harvard University", + "kategori": "Swasta", + "kategori_en": "Private", + "status": "Buka", + "thumbnail": "https://images.unsplash.com/photo-1541339907198-e08756dedf3f?w=400&q=80&auto=format&fit=crop", + "deskripsi_singkat": "Beasiswa bergengsi dari Boustany Foundation untuk program MBA di Harvard University, Amerika Serikat, bagi calon pemimpin bisnis dunia.", + "deskripsi_singkat_en": "A prestigious scholarship from the Boustany Foundation for the MBA program at Harvard University, United States, for future global business leaders.", + "syarat_umum": [ + "Diterima atau mendaftar di program MBA Harvard Business School", + "Memiliki rekam jejak prestasi akademik dan profesional yang luar biasa", + "Menunjukkan potensi kepemimpinan dan kontribusi internasional", + "Melengkapi aplikasi beasiswa secara online melalui situs resmi Boustany Foundation" + ], + "syarat_umum_en": [ + "Accepted or applying to the MBA program at Harvard Business School", + "Have an exceptional track record of academic and professional achievements", + "Demonstrate leadership potential and international contribution", + "Complete the scholarship application online through the official Boustany Foundation website" + ], + "kontak": "Boustany Foundation — boustany-foundation.com", + "tanggal_buka": "2026-05-21", + "tanggal_tutup": "2027-05-31", + "url_sumber": "https://www.schoters.com/id/beasiswa/boustany-foundation-scholarship-mba-harvard-university-1", + "tags": ["S2", "Swasta", "Amerika Serikat", "Partially Funded", "MBA"] + }, + { + "id": "bsw-002", + "nama": "La Trobe University - La Trobe High Achiever Scholarship (S1)", + "kategori": "Swasta", + "kategori_en": "Private", + "status": "Buka", + "thumbnail": "https://images.unsplash.com/photo-1523240795612-9a054b0db644?w=400&q=80&auto=format&fit=crop", + "deskripsi_singkat": "Beasiswa dari La Trobe University Australia untuk mahasiswa internasional jenjang S1 berprestasi tinggi yang ingin melanjutkan studi di Melbourne.", + "deskripsi_singkat_en": "Scholarship from La Trobe University Australia for high-achieving international undergraduate students who wish to pursue their studies in Melbourne.", + "syarat_umum": [ + "Mendaftar sebagai mahasiswa internasional jenjang S1 (Undergraduate) di La Trobe University", + "Memiliki nilai akademik yang sangat baik (High Achiever)", + "Tidak sedang menerima beasiswa penuh lainnya dari La Trobe University", + "Memenuhi persyaratan masuk dan kemampuan bahasa Inggris La Trobe University" + ], + "syarat_umum_en": [ + "Apply as an international undergraduate student at La Trobe University", + "Have an excellent academic record (High Achiever)", + "Not currently receiving any other full scholarship from La Trobe University", + "Meet La Trobe University's entry and English language requirements" + ], + "kontak": "La Trobe University Admissions — latrobe.edu.au", + "tanggal_buka": "2023-09-29", + "tanggal_tutup": "2026-12-31", + "url_sumber": "https://www.schoters.com/id/beasiswa/la-trobe-university-la-trobe-high-achiever-scholarship-2", + "tags": ["S1", "Swasta", "Australia", "Partially Funded"] + }, + { + "id": "bsw-003", + "nama": "Charles Sturt University - International Student Support Scholarship", + "kategori": "Swasta", + "kategori_en": "Private", + "status": "Buka", + "thumbnail": "https://images.unsplash.com/photo-1560472354-b33ff0c44a43?w=400&q=80&auto=format&fit=crop", + "deskripsi_singkat": "Beasiswa dukungan dari Charles Sturt University bagi mahasiswa internasional jenjang S1 yang mendaftar di kampus yang berlokasi di New South Wales, Australia.", + "deskripsi_singkat_en": "Support scholarship from Charles Sturt University for international undergraduate students enrolling at a campus located in New South Wales, Australia.", + "syarat_umum": [ + "Mendaftar sebagai mahasiswa internasional penuh waktu (full-time) jenjang S1", + "Memenuhi persyaratan penerimaan akademik Charles Sturt University", + "Memiliki kemampuan Bahasa Inggris yang memadai (IELTS/TOEFL)", + "Mendaftar melalui jalur penerimaan internasional resmi" + ], + "syarat_umum_en": [ + "Apply as a full-time international undergraduate student", + "Meet Charles Sturt University's academic admission requirements", + "Have adequate English language proficiency (IELTS/TOEFL)", + "Apply through the official international admission pathway" + ], + "kontak": "Charles Sturt University International — csu.edu.au", + "tanggal_buka": "2026-05-21", + "tanggal_tutup": "2026-12-31", + "url_sumber": "https://www.schoters.com/id/beasiswa/charles-sturt-university-international-student-support-scholarship-3", + "tags": ["S1", "Swasta", "Australia", "Partially Funded"] + }, + { + "id": "bsw-004", + "nama": "La Trobe University - La Trobe High Achiever Scholarship (S2)", + "kategori": "Swasta", + "kategori_en": "Private", + "status": "Buka", + "thumbnail": "https://images.unsplash.com/photo-1529156069898-49953e39b3ac?w=400&q=80&auto=format&fit=crop", + "deskripsi_singkat": "Beasiswa dari La Trobe University Australia untuk mahasiswa internasional jenjang S2 (Postgraduate) dengan pencapaian akademik tinggi.", + "deskripsi_singkat_en": "Scholarship from La Trobe University Australia for international postgraduate students with high academic achievements.", + "syarat_umum": [ + "Mendaftar sebagai mahasiswa internasional jenjang S2 di La Trobe University", + "Memiliki nilai akademik yang sangat baik di jenjang sarjana sebelumnya", + "Memenuhi persyaratan bahasa Inggris yang ditetapkan", + "Tidak sedang menerima beasiswa lain dari universitas yang sama" + ], + "syarat_umum_en": [ + "Apply as an international postgraduate student at La Trobe University", + "Have excellent academic grades in the previous undergraduate degree", + "Meet the specified English language requirements", + "Not currently receiving another scholarship from the same university" + ], + "kontak": "La Trobe University Admissions — latrobe.edu.au", + "tanggal_buka": "2023-09-29", + "tanggal_tutup": "2026-12-31", + "url_sumber": "https://www.schoters.com/id/beasiswa/la-trobe-university-la-trobe-high-achiever-scholarship-4", + "tags": ["S2", "Swasta", "Australia", "Partially Funded"] + }, + { + "id": "bsw-005", + "nama": "ETH Zurich - Excellence Scholarship & Opportunity Programme (ESOP)", + "kategori": "Pemerintah", + "kategori_en": "Government", + "status": "Buka", + "thumbnail": "https://images.unsplash.com/photo-1497366754035-f200968a6e72?w=400&q=80&auto=format&fit=crop", + "deskripsi_singkat": "Beasiswa bergengsi dari ETH Zurich (salah satu universitas teknik terbaik dunia) untuk mahasiswa S2 internasional yang unggul secara akademik.", + "deskripsi_singkat_en": "Prestigious scholarship from ETH Zurich (one of the world's best engineering universities) for academically outstanding international master's students.", + "syarat_umum": [ + "Mendaftar program Master (S2) di ETH Zurich", + "Lulus ujian penerimaan ETH Zurich atau memiliki setara gelar sarjana yang diakui", + "Menunjukkan prestasi akademik luar biasa (biasanya masuk 10% terbaik angkatan)", + "Melengkapi formulir aplikasi beasiswa ESOP yang terpisah dari aplikasi studi", + "Mendapatkan surat rekomendasi dari akademisi berwenang" + ], + "syarat_umum_en": [ + "Apply for a Master's program at ETH Zurich", + "Pass the ETH Zurich entrance exam or hold a recognized equivalent bachelor's degree", + "Demonstrate outstanding academic performance (usually top 10% of the cohort)", + "Complete the ESOP scholarship application form separately from the study application", + "Obtain a recommendation letter from authorized academics" + ], + "kontak": "ETH Zurich Scholarship Office — ethz.ch", + "tanggal_buka": "2026-11-01", + "tanggal_tutup": "2026-11-30", + "url_sumber": "https://www.schoters.com/id/beasiswa/eth-zurich-excellence-scholarship-opportunity-programme-esop-5", + "tags": ["S2", "Pemerintah", "Swiss", "Fully Funded", "Prestasi"] + }, + { + "id": "bsw-006", + "nama": "STUST - Scholarship for International Students (S3, Fully Funded)", + "kategori": "Swasta", + "kategori_en": "Private", + "status": "Buka", + "thumbnail": "https://images.unsplash.com/photo-1580582932707-520aed937b7b?w=400&q=80&auto=format&fit=crop", + "deskripsi_singkat": "Beasiswa penuh (fully funded) dari Southern Taiwan University of Science and Technology untuk mahasiswa internasional jenjang S3 (Doktoral).", + "deskripsi_singkat_en": "Fully funded scholarship from Southern Taiwan University of Science and Technology for international doctoral students.", + "syarat_umum": [ + "Mendaftar program Doktoral (S3) di STUST, Taiwan", + "Memiliki gelar magister (S2) yang diakui", + "Memenuhi persyaratan kemampuan bahasa Inggris atau Mandarin", + "Menyerahkan proposal penelitian yang relevan dengan bidang studi yang dipilih", + "Mendapatkan persetujuan dari calon pembimbing (supervisor) di STUST" + ], + "syarat_umum_en": [ + "Apply for a Doctoral program at STUST, Taiwan", + "Hold a recognized Master's degree", + "Meet the English or Mandarin language proficiency requirements", + "Submit a research proposal relevant to the chosen field of study", + "Obtain approval from a prospective supervisor at STUST" + ], + "kontak": "STUST International Affairs Office — stust.edu.tw", + "tanggal_buka": "2026-09-15", + "tanggal_tutup": "2026-11-30", + "url_sumber": "https://www.schoters.com/id/beasiswa/southern-taiwan-university-of-science-and-technology-the-stust-scholarship-for-international-students-6", + "tags": ["S3", "Swasta", "Taiwan", "Fully Funded"] + }, + { + "id": "bsw-007", + "nama": "STUST - Scholarship for International Students (S2, Partially Funded)", + "kategori": "Swasta", + "kategori_en": "Private", + "status": "Buka", + "thumbnail": "https://images.unsplash.com/photo-1606761568499-6d2451b23c66?w=400&q=80&auto=format&fit=crop", + "deskripsi_singkat": "Beasiswa parsial (partially funded) dari Southern Taiwan University of Science and Technology untuk mahasiswa internasional jenjang S2 (Magister).", + "deskripsi_singkat_en": "Partially funded scholarship from Southern Taiwan University of Science and Technology for international master's students.", + "syarat_umum": [ + "Mendaftar program Magister (S2) di STUST, Taiwan", + "Memiliki gelar sarjana (S1) yang diakui", + "Memenuhi persyaratan kemampuan bahasa Inggris atau Mandarin", + "Melengkapi berkas aplikasi secara online melalui portal resmi STUST", + "Menyertakan transkrip nilai dan surat motivasi" + ], + "syarat_umum_en": [ + "Apply for a Master's program at STUST, Taiwan", + "Hold a recognized Bachelor's degree", + "Meet the English or Mandarin language proficiency requirements", + "Complete the application file online through the official STUST portal", + "Include academic transcripts and a motivation letter" + ], + "kontak": "STUST International Affairs Office — stust.edu.tw", + "tanggal_buka": "2026-09-15", + "tanggal_tutup": "2026-11-30", + "url_sumber": "https://www.schoters.com/id/beasiswa/southern-taiwan-university-of-science-and-technology-the-stust-scholarship-for-international-students-7", + "tags": ["S2", "Swasta", "Taiwan", "Partially Funded"] + }, + { + "id": "bsw-008", + "nama": "University of Melbourne - Melbourne International Undergraduate Scholarship", + "kategori": "Swasta", + "kategori_en": "Private", + "status": "Buka", + "thumbnail": "https://images.unsplash.com/photo-1504711434969-e33886168f5c?w=400&q=80&auto=format&fit=crop", + "deskripsi_singkat": "Beasiswa untuk mahasiswa internasional berprestasi yang mendaftar program S1 di University of Melbourne, salah satu universitas terbaik di Australia.", + "deskripsi_singkat_en": "Scholarship for outstanding international students applying for an undergraduate program at the University of Melbourne, one of Australia's best universities.", + "syarat_umum": [ + "Merupakan mahasiswa internasional (bukan warga negara Australia atau New Zealand)", + "Mendaftar program sarjana (S1 / Undergraduate) di University of Melbourne", + "Memiliki hasil akademik yang sangat luar biasa di tingkat sekolah menengah atas", + "Memenuhi persyaratan kemampuan bahasa Inggris (IELTS minimal 6.5)", + "Beasiswa diberikan otomatis berdasarkan nilai akademik, tidak perlu aplikasi terpisah" + ], + "syarat_umum_en": [ + "Be an international student (not a citizen of Australia or New Zealand)", + "Apply for an undergraduate program at the University of Melbourne", + "Have an exceptional academic result at the high school level", + "Meet the English language proficiency requirements (minimum IELTS 6.5)", + "The scholarship is awarded automatically based on academic merit, no separate application required" + ], + "kontak": "University of Melbourne Future Students — unimelb.edu.au", + "tanggal_buka": "2026-05-21", + "tanggal_tutup": "2026-10-31", + "url_sumber": "https://www.schoters.com/id/beasiswa/university-of-melbourne-melbourne-international-undergraduate-scholarship-8", + "tags": ["S1", "Swasta", "Australia", "Partially Funded", "Prestasi"] + }, + { + "id": "bsw-009", + "nama": "Charles Darwin University - CDU Global Merit Scholarship", + "kategori": "Swasta", + "kategori_en": "Private", + "status": "Buka", + "thumbnail": "https://images.unsplash.com/photo-1434030216411-0b793f4b4173?w=400&q=80&auto=format&fit=crop", + "deskripsi_singkat": "Beasiswa merit global dari Charles Darwin University (CDU) di Darwin, Australia, untuk mahasiswa internasional S1 yang memiliki rekam jejak akademik yang kuat.", + "deskripsi_singkat_en": "Global merit scholarship from Charles Darwin University (CDU) in Darwin, Australia, for international undergraduate students with a strong academic track record.", + "syarat_umum": [ + "Mendaftar sebagai mahasiswa internasional baru (new international student) di CDU", + "Mendaftar untuk program sarjana (Undergraduate/S1) penuh waktu", + "Memiliki nilai ujian akhir sekolah yang baik (dikonversi ke skala CDU)", + "Memenuhi persyaratan bahasa Inggris (IELTS 6.0 atau setara)", + "Tidak sedang menerima potongan biaya kuliah lainnya dari CDU" + ], + "syarat_umum_en": [ + "Apply as a new international student at CDU", + "Apply for a full-time undergraduate program", + "Have a good high school final exam score (converted to CDU scale)", + "Meet the English language requirements (IELTS 6.0 or equivalent)", + "Not currently receiving any other tuition fee discount from CDU" + ], + "kontak": "CDU International — cdu.edu.au", + "tanggal_buka": "2026-05-21", + "tanggal_tutup": "2026-10-09", + "url_sumber": "https://www.schoters.com/id/beasiswa/charles-darwin-university-cdu-global-merit-scholarship-9", + "tags": ["S1", "Swasta", "Australia", "Partially Funded"] + }, + { + "id": "bsw-010", + "nama": "Deakin University - Vice-Chancellor's International Scholarship", + "kategori": "Swasta", + "kategori_en": "Private", + "status": "Buka", + "thumbnail": "https://images.unsplash.com/photo-1541339907198-e08756dedf3f?w=400&q=80&auto=format&fit=crop", + "deskripsi_singkat": "Beasiswa bergengsi dari Wakil Rektor (Vice-Chancellor) Deakin University untuk mahasiswa internasional terbaik yang akan menempuh studi S1 atau S2 di Australia.", + "deskripsi_singkat_en": "Prestigious Vice-Chancellor's scholarship from Deakin University for the best international students pursuing an undergraduate or postgraduate degree in Australia.", + "syarat_umum": [ + "Merupakan mahasiswa internasional (bukan warga negara Australia/New Zealand)", + "Mendaftar untuk program S1 (Undergraduate) atau S2 (Postgraduate Coursework) di Deakin", + "Memiliki rekam jejak akademik yang sangat baik dan konsisten", + "Memenuhi persyaratan masuk dan kemampuan bahasa Inggris Deakin University", + "Mengajukan aplikasi beasiswa sebelum tanggal penutupan yang ditetapkan" + ], + "syarat_umum_en": [ + "Be an international student (not an Australia/New Zealand citizen)", + "Apply for an undergraduate or postgraduate coursework program at Deakin", + "Have a consistent and excellent academic track record", + "Meet Deakin University's entry and English language requirements", + "Submit the scholarship application before the specified closing date" + ], + "kontak": "Deakin University International — deakin.edu.au", + "tanggal_buka": "2026-05-21", + "tanggal_tutup": "2026-09-25", + "url_sumber": "https://www.schoters.com/id/beasiswa/deakin-university-vice-chancellor-s-international-scholarship-10", + "tags": ["S1 & S2", "S2", "Swasta", "Australia", "Partially Funded", "Prestasi"] + } +] \ No newline at end of file diff --git a/groups/ApeNameTeamE/data/testimoni.json b/groups/ApeNameTeamE/data/testimoni.json new file mode 100644 index 0000000..1f71990 --- /dev/null +++ b/groups/ApeNameTeamE/data/testimoni.json @@ -0,0 +1,11 @@ +[ + { + "id": "tsm-001", + "nama": "Violaine Gunawan", + "foto": "https://ui-avatars.com/api/?name=Violaine+Gunawan&background=111a2f&color=fff&size=200&rounded=true", + "nama_beasiswa": "BEASISWA BAKTI BCA 2026", + "nama_beasiswa_en": "BAKTI BCA SCHOLARSHIP 2026", + "kutipan": "Beasiswa ini sangat berdampak besar. Tantangannya menyeimbangkan kuliah, asisten praktikum, organisasi, dan projek besar beasiswa. Namun, relasi di kampus dan masyarakat jadi bertambah luas. Tips: Jangan takut mencoba, pahami fokus beasiswa, sesuaikan visi misi, dan aktiflah berorganisasi!", + "kutipan_en": "This scholarship has a massive impact. The challenge is balancing college, practicum assistant duties, organizations, and major scholarship projects. However, connections on campus and in society have expanded. Tip: Don't be afraid to try, understand the scholarship's focus, align your vision and mission, and be active in organizations!" + } +] \ No newline at end of file diff --git a/groups/ApeNameTeamE/index.html b/groups/ApeNameTeamE/index.html index d7d58d3..b29acfb 100644 --- a/groups/ApeNameTeamE/index.html +++ b/groups/ApeNameTeamE/index.html @@ -1,15 +1,27 @@ - + + - Group 10 – Ape Name Tim E | Informatika UNTAN + Group 10 – ApeNameTeamE | Informatika UNTAN + - + - + @@ -1139,18 +1152,262 @@
    -
    -
    -
    - Tugas Halaman Statis -

    Beasiswa

    -

    Kelompok 10 — Ape Name Tim E  ·  Informatika UNTAN 2026

    +
    +
    + +
    +
    + +
    +
    + Selamat datang di antarmuka situs web Informatika terbaru! +  |  Pendaftaran + kolaborasi riset semester genap telah dibuka.  |  Pantau publikasi dosen dan + mahasiswa secara + real-time.  |  Beasiswa KIP Kuliah 2026 dibuka — Daftar sekarang! +  |  Beasiswa LPDP S2 + tersedia hingga September 2026.       + +
    +
    +
    + + +
    +
    + +
    + + + +
    + + +
    + +
    + PROGRAM BEASISWA +
    + + +

    + Beasiswa Studi &
    Penelitian +

    + + +

    + Teknik Informatika Universitas Tanjungpura +

    + + +

    + Temukan berbagai peluang beasiswa untuk mendukung perjalanan akademik dan penelitian Anda. +

    + + + + Lihat Daftar Beasiswa + + +
    + + + + +
    +
    +
    + + +
    +
    +
    + +
    +
    0
    +
    + Total Mahasiswa Penerima
    Beasiswa Semester Ini +
    +
    + +
    +
    0
    +
    + Total Penerima Beasiswa
    Khusus S1 +
    +
    + +
    +
    0
    +
    + Total Penerima Beasiswa
    Studi Lanjut +
    +
    + +
    +
    +
    + + +
    +
    + + +
    +
    + +
    + DAFTAR LENGKAP +
    +

    Daftar Beasiswa

    +

    + Temukan beragam beasiswa dari berbagai sumber resmi yang tersedia untuk mahasiswa aktif. +

    +
    +
    + + +
    + +
    + + + +
    + + +
    +
    + + +
    +
    +
    + + +
    + +
    + +

    Memuat data beasiswa...

    +
    +
    + + + + +
    +
    + + + + + +
    +
    + + +
    +

    Apa Kata Mereka?

    +

    + Cerita nyata dari mahasiswa yang telah meraih beasiswa +

    +
    + + +
    +
    + +
    +
    +
    + +
    +
    + + +
    +
    +
    +

    + Ingin Mengetahui Info Lebih Lanjut? +

    +

    + Bersama kami membangun sumber daya manusia unggul melalui program beasiswa dan + kolaborasi riset +

    + +
    +
    +
    +
    -

    Tulis konten halaman kelompok di sini.

    -

    Subjudul

    -

    Gunakan paragraf, list, tabel, gambar, dan elemen konten lainnya.

    + +
    @@ -1215,11 +1472,23 @@
    - Footer Illustration + Footer Illustration
    + + + + + + + + + + + + - + - + \ No newline at end of file diff --git a/groups/ApeNameTeamE/page1.json b/groups/ApeNameTeamE/page1.json new file mode 100644 index 0000000..3970938 --- /dev/null +++ b/groups/ApeNameTeamE/page1.json @@ -0,0 +1,203 @@ +{ + "source": "https://www.schoters.com/id/beasiswa", + "title": "Kalender Beasiswa - Schoters", + "description": "Kalender dan informasi beasiswa terlengkap dari semua jenjang S1, S2, & S3 di setiap negara dan kampus impian beserta persyaratan dan proses pendaftarannya", + "filters": { + "jenjang": [ + { "level": "D2", "count": 2 }, + { "level": "D3", "count": 6 }, + { "level": "Non-Degree", "count": 20 }, + { "level": "S1", "count": 648 }, + { "level": "S2", "count": 683 }, + { "level": "S3", "count": 362 } + ], + "tipe_pendanaan": [ + { "type": "Fully Funded", "count": 809 }, + { "type": "Partially Funded", "count": 590 } + ], + "tipe_beasiswa": [ + { "type": "Company/Institution Scholarship", "count": 237 }, + { "type": "Government Scholarship", "count": 459 }, + { "type": "University Scholarship", "count": 830 } + ], + "negara": [ + { "country": "Australia", "count": 161 }, + { "country": "Austria", "count": 19 }, + { "country": "Azerbaijan", "count": 6 }, + { "country": "Belgium", "count": 38 }, + { "country": "Brazil", "count": 2 }, + { "country": "Brunei", "count": 5 }, + { "country": "Canada", "count": 46 }, + { "country": "China", "count": 114 }, + { "country": "Czech Republic", "count": 2 }, + { "country": "Denmark", "count": 13 }, + { "country": "Egypt", "count": 3 }, + { "country": "Estonia", "count": 2 }, + { "country": "Finland", "count": 11 }, + { "country": "France", "count": 20 }, + { "country": "Germany", "count": 46 }, + { "country": "Hong Kong", "count": 24 }, + { "country": "Hungary", "count": 5 }, + { "country": "India", "count": 2 }, + { "country": "Indonesia", "count": 35 }, + { "country": "Ireland", "count": 8 }, + { "country": "Italy", "count": 19 }, + { "country": "Japan", "count": 254 }, + { "country": "Kazakhstan", "count": 3 }, + { "country": "Latvia", "count": 3 }, + { "country": "Libya", "count": 2 }, + { "country": "Luxembourg", "count": 1 }, + { "country": "Macau", "count": 6 }, + { "country": "Malaysia", "count": 12 }, + { "country": "Morocco", "count": 2 }, + { "country": "Netherlands", "count": 21 }, + { "country": "New Zealand", "count": 22 }, + { "country": "Pakistan", "count": 1 }, + { "country": "Philippines", "count": 2 }, + { "country": "Poland", "count": 9 }, + { "country": "Portugal", "count": 4 }, + { "country": "Qatar", "count": 6 }, + { "country": "Romania", "count": 9 }, + { "country": "Russia", "count": 6 }, + { "country": "Saudi Arabia", "count": 12 }, + { "country": "Scotland", "count": 2 }, + { "country": "Serbia", "count": 3 }, + { "country": "Singapore", "count": 49 }, + { "country": "Slovakia", "count": 1 }, + { "country": "South Korea", "count": 109 }, + { "country": "Spain", "count": 12 }, + { "country": "Sweden", "count": 11 }, + { "country": "Switzerland", "count": 19 }, + { "country": "Taiwan", "count": 112 }, + { "country": "Thailand", "count": 38 }, + { "country": "Turkey", "count": 11 }, + { "country": "United Arab Emirates", "count": 67 }, + { "country": "United Kingdom", "count": 76 }, + { "country": "United States", "count": 55 }, + { "country": "Universal", "count": 2 }, + { "country": "Vietnam", "count": 2 } + ] + }, + "scholarships_page_1": [ + { + "name": "Boustany Foundation Scholarship, MBA - Harvard University", + "funding_type": "Partially Funded", + "level": ["S2"], + "country": "United States", + "open_date": "2026-05-21", + "deadline": "2027-05-31", + "status": "Pendaftaran dibuka", + "url": "https://www.schoters.com/id/beasiswa/boustany-foundation-scholarship-mba-harvard-university-1" + }, + { + "name": "La Trobe University - La Trobe High Achiever Scholarship", + "funding_type": "Partially Funded", + "level": ["S1"], + "country": "Australia", + "open_date": "2023-09-29", + "deadline": "2026-12-31", + "status": "Pendaftaran dibuka", + "url": "https://www.schoters.com/id/beasiswa/la-trobe-university-la-trobe-high-achiever-scholarship-2" + }, + { + "name": "Charles Sturt University - International Student Support Scholarship", + "funding_type": "Partially Funded", + "level": ["S1"], + "country": "Australia", + "open_date": "2026-05-21", + "deadline": "2026-12-31", + "status": "Pendaftaran dibuka", + "url": "https://www.schoters.com/id/beasiswa/charles-sturt-university-international-student-support-scholarship-3" + }, + { + "name": "La Trobe University - La Trobe High Achiever Scholarship", + "funding_type": "Partially Funded", + "level": ["S2"], + "country": "Australia", + "open_date": "2023-09-29", + "deadline": "2026-12-31", + "status": "Pendaftaran dibuka", + "url": "https://www.schoters.com/id/beasiswa/la-trobe-university-la-trobe-high-achiever-scholarship-4" + }, + { + "name": "ETH Zurich - Excellence Scholarship & Opportunity Programme (ESOP)", + "funding_type": "Fully Funded", + "level": ["S2"], + "country": "Switzerland", + "open_date": "2026-11-01", + "deadline": "2026-11-30", + "status": "Pendaftaran dibuka", + "url": "https://www.schoters.com/id/beasiswa/eth-zurich-excellence-scholarship-opportunity-programme-esop-5" + }, + { + "name": "Southern Taiwan University of Science and Technology - The STUST Scholarship for International Students", + "funding_type": "Fully Funded", + "level": ["S3"], + "country": "Taiwan", + "open_date": "2026-09-15", + "deadline": "2026-11-30", + "status": "Pendaftaran dibuka", + "url": "https://www.schoters.com/id/beasiswa/southern-taiwan-university-of-science-and-technology-the-stust-scholarship-for-international-students-6" + }, + { + "name": "Southern Taiwan University of Science and Technology - The STUST Scholarship for International Students", + "funding_type": "Partially Funded", + "level": ["S2"], + "country": "Taiwan", + "open_date": "2026-09-15", + "deadline": "2026-11-30", + "status": "Pendaftaran dibuka", + "url": "https://www.schoters.com/id/beasiswa/southern-taiwan-university-of-science-and-technology-the-stust-scholarship-for-international-students-7" + }, + { + "name": "University of Melbourne - Melbourne International Undergraduate Scholarship", + "funding_type": "Partially Funded", + "level": ["S1"], + "country": "Australia", + "open_date": "2026-05-21", + "deadline": "2026-10-31", + "status": "Pendaftaran dibuka", + "url": "https://www.schoters.com/id/beasiswa/university-of-melbourne-melbourne-international-undergraduate-scholarship-8" + }, + { + "name": "Charles Darwin University - CDU Global Merit Scholarship", + "funding_type": "Partially Funded", + "level": ["S1"], + "country": "Australia", + "open_date": "2026-05-21", + "deadline": "2026-10-09", + "status": "Pendaftaran dibuka", + "url": "https://www.schoters.com/id/beasiswa/charles-darwin-university-cdu-global-merit-scholarship-9" + }, + { + "name": "Deakin University - Vice-Chancellor's International Scholarship", + "funding_type": "Partially Funded", + "level": ["S1", "S2"], + "country": "Australia", + "open_date": "2026-05-21", + "deadline": "2026-09-25", + "status": "Pendaftaran dibuka", + "url": "https://www.schoters.com/id/beasiswa/deakin-university-vice-chancellor-s-international-scholarship-10" + }, + { + + } + ], + "pagination": { + "current_page": 1, + "total_pages": 153 + }, + "contact": { + "email": "ask@schoters.com", + "phone": "0811 9424 966", + "address": "Gedung Sinarmas MSIG Tower Lt. 33, Jl. Jenderal Sudirman Kav. 21, Karet Kuningan, Setiabudi, Jakarta Selatan, Jakarta 12920" + }, + "social_media": { + "instagram": "https://www.instagram.com/schoters/", + "facebook": "https://www.facebook.com/schoters", + "youtube": "https://www.youtube.com/@Schoters", + "tiktok": "https://www.tiktok.com/@schoters.id", + "twitter_x": "https://x.com/schoters_com", + "linkedin": "https://id.linkedin.com/company/schoters" + } +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 43e70d0..451b48d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -886,9 +886,9 @@ } }, "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "version": "3.3.12", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", + "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", "dev": true, "funding": [ { @@ -925,9 +925,9 @@ } }, "node_modules/postcss": { - "version": "8.5.8", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz", - "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", + "version": "8.5.15", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", + "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", "dev": true, "funding": [ { @@ -945,7 +945,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.11", + "nanoid": "^3.3.12", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" },