forked from izu/student-web-if-development-kit
Merge pull request 'main' (#7) from Araya/student-web-if-development-kit:main into main
Reviewed-on: izu/student-web-if-development-kit#7 Approved
This commit is contained in:
@@ -1,3 +1,9 @@
|
|||||||
node_modules/
|
node_modules/
|
||||||
dist/
|
dist/
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
groups/**/.env
|
||||||
|
groups/**/.env.local
|
||||||
|
README.md
|
||||||
|
i18n.js
|
||||||
@@ -570,6 +570,30 @@ const translations = {
|
|||||||
kontrib_guideline_4: "Hindari plagiarisme. Karya harus orisinal.",
|
kontrib_guideline_4: "Hindari plagiarisme. Karya harus orisinal.",
|
||||||
kontrib_guideline_5: "Tim redaksi berhak menyunting konten untuk keperluan editorial.",
|
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 &<br>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<br>Beasiswa Semester Ini',
|
||||||
|
ape_stats_s1: 'Total Penerima Beasiswa<br>Khusus S1',
|
||||||
|
ape_stats_studi: 'Total Penerima Beasiswa<br>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 ──────────────────────────────────────────────────────────────
|
// ── Page ──────────────────────────────────────────────────────────────
|
||||||
grp_habisiniseminar_page_title: 'Penerimaan Mahasiswa Baru Informatika UNTAN | Kelompok 02',
|
grp_habisiniseminar_page_title: 'Penerimaan Mahasiswa Baru Informatika UNTAN | Kelompok 02',
|
||||||
grp_habisiniseminar_brand: 'Informatika UNTAN Penerimaan Mahasiswa Baru',
|
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_4: "Avoid plagiarism. Work must be original.",
|
||||||
kontrib_guideline_5: "The editorial team reserves the right to edit content for editorial purposes.",
|
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<br>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<br>Recipients This Semester',
|
||||||
|
ape_stats_s1: 'Total Undergraduate<br>Scholarship Recipients',
|
||||||
|
ape_stats_studi: 'Total Postgraduate<br>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 ──────────────────────────────────────────────────────────────
|
// ── Page ──────────────────────────────────────────────────────────────
|
||||||
grp_habisiniseminar_page_title: 'New Student Admission Informatics UNTAN | Group 02',
|
grp_habisiniseminar_page_title: 'New Student Admission Informatics UNTAN | Group 02',
|
||||||
grp_habisiniseminar_brand: 'Informatics UNTAN New Student Admission',
|
grp_habisiniseminar_brand: 'Informatics UNTAN New Student Admission',
|
||||||
|
|||||||
@@ -997,7 +997,7 @@
|
|||||||
|
|
||||||
<!-- Overlay for mega menu -->
|
<!-- Overlay for mega menu -->
|
||||||
<div id="mega-overlay" class="fixed inset-0 bg-black/30 backdrop-blur-sm z-30"></div>
|
<div id="mega-overlay" class="fixed inset-0 bg-black/30 backdrop-blur-sm z-30"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="mobile-menu"
|
<div id="mobile-menu"
|
||||||
class="fixed inset-0 bg-slate-900 z-[60] transform -translate-x-full lg:hidden flex flex-col transition-transform duration-300"
|
class="fixed inset-0 bg-slate-900 z-[60] transform -translate-x-full lg:hidden flex flex-col transition-transform duration-300"
|
||||||
|
|||||||
@@ -0,0 +1,273 @@
|
|||||||
|
# PROJECT CONTEXT
|
||||||
|
## Website Statis Halaman Beasiswa — Informatika UNTAN
|
||||||
|
|
||||||
|
> 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
|
||||||
@@ -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 `<<include>>` 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.
|
||||||
@@ -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<br>2. Sistem tampilkan hero, statistik, daftar beasiswa<br>3. Kartu ditampilkan grid: 3 kolom desktop / 2 tablet / 1 mobile<br>4. Tiap kartu: thumbnail, badge status, nama, deskripsi singkat, tanggal, tombol "Selengkapnya"<br>5. Paginasi tampil di bawah grid jika beasiswa > 1 halaman |
|
||||||
|
| Alt Flow | 3a. Koneksi lambat → skeleton loading<br>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<br>2. Pengunjung klik tab<br>3. Sistem real-time filter beasiswa sesuai kategori<br>4. Tab aktif ditandai bold/underline/warna<br>5. Jumlah hasil diperbarui |
|
||||||
|
| Alt Flow | 3a. Tidak ada hasil → "Tidak ada beasiswa pada kategori ini."<br>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<br>2. Ketik kata kunci (misal: "Pertamina", "KIP", "luar negeri")<br>3. Sistem real-time filter kartu yang nama/deskripsinya cocok<br>4. Hapus kata kunci → kembali ke tampilan penuh<br>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 →"<br>2. Sistem tampilkan modal popup berisi: nama + thumbnail, badge status, syarat umum ringkasan, kontak, tombol "Info Lebih Lanjut" (→ URL sumber resmi di tab baru)<br>3. Background di-overlay gelap<br>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<br>2. Sistem buka URL sumber resmi di tab baru<br>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?")<br>2. Tampil dua tombol: "Hubungi Admin" (WhatsApp) + "Instagram Beasiswa" (IG kemahasiswaan)<br>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<br>2. Tampil kartu testimoni: foto, nama, nama beasiswa, kutipan singkat<br>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<br>2. Klik bahasa yang diinginkan<br>3. Seluruh teks berubah tanpa reload<br>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<br>2. Edit file data beasiswa (nama, kategori, status, syarat, kontak, URL)<br>3. Simpan dan push ke GitHub<br>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)
|
||||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
After Width: | Height: | Size: 7.4 MiB |
Binary file not shown.
|
After Width: | Height: | Size: 848 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 755 KiB |
@@ -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);
|
||||||
@@ -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 `
|
||||||
|
<div class="swiper-slide" style="height:auto;">
|
||||||
|
<div class="testimonial-card">
|
||||||
|
<img
|
||||||
|
src="${t.foto}"
|
||||||
|
alt="Foto ${t.nama}"
|
||||||
|
class="testimonial-avatar"
|
||||||
|
loading="lazy"
|
||||||
|
onerror="
|
||||||
|
this.style.display='none';
|
||||||
|
this.nextElementSibling.style.display='flex';
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="testimonial-avatar"
|
||||||
|
style="
|
||||||
|
display:none;
|
||||||
|
background:linear-gradient(135deg,#003150,#4a6bc5);
|
||||||
|
align-items:center;
|
||||||
|
justify-content:center;
|
||||||
|
color:white;
|
||||||
|
font-size:22px;
|
||||||
|
font-weight:700;
|
||||||
|
"
|
||||||
|
>
|
||||||
|
${t.nama.charAt(0).toUpperCase()}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="testimonial-name">${t.nama}</div>
|
||||||
|
<div class="testimonial-beasiswa">${beasiswaName}</div>
|
||||||
|
<p class="testimonial-quote">"${quote}"</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}).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);
|
||||||
@@ -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);
|
||||||
@@ -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) => `<span class="card-pill ${i === 0 ? 'card-pill-level' : ''}">${t}</span>`)
|
||||||
|
.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 = `
|
||||||
|
<div class="card-body">
|
||||||
|
<h3 class="card-title">${namaBsw}</h3>
|
||||||
|
${subtitle ? `<p class="card-subtitle">${subtitle}</p>` : ''}
|
||||||
|
${pillsHtml ? `<div class="card-pills">${pillsHtml}</div>` : ''}
|
||||||
|
<hr class="card-divider">
|
||||||
|
<div class="card-dates">
|
||||||
|
<div class="card-date-col">
|
||||||
|
<span class="card-date-label">${textMulai}</span>
|
||||||
|
<span class="card-date-value">${formatDate(bsw.tanggal_buka)}</span>
|
||||||
|
</div>
|
||||||
|
<div class="card-date-col">
|
||||||
|
<span class="card-date-label">${textDeadline}</span>
|
||||||
|
<span class="card-date-value">${formatDate(bsw.tanggal_tutup)}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<button class="card-status-btn ${statusClass}" disabled>${statusLabel}</button>
|
||||||
|
<button
|
||||||
|
class="btn-selengkapnya"
|
||||||
|
onclick="openPopup('${bsw.id}')"
|
||||||
|
aria-label="Lihat detail beasiswa ${namaBsw}"
|
||||||
|
>${textSelengkapnya}</button>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
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 = `
|
||||||
|
<div class="empty-state" style="grid-column:1/-1">
|
||||||
|
<i class="fas fa-search-minus"></i>
|
||||||
|
<p style="font-size:15px;font-weight:700;color:#94a3b8;margin-bottom:6px;">${emptyTitle}</p>
|
||||||
|
<p style="font-size:13px;color:#cbd5e1;">${emptyDesc}</p>
|
||||||
|
</div>`;
|
||||||
|
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('<i class="fas fa-chevron-left" style="font-size:11px;"></i>', currentPage - 1, currentPage === 1));
|
||||||
|
for (let i = 1; i <= total; i++) {
|
||||||
|
container.appendChild(make(i, i, false, i === currentPage));
|
||||||
|
}
|
||||||
|
container.appendChild(make('<i class="fas fa-chevron-right" style="font-size:11px;"></i>', 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 = `
|
||||||
|
<div class="empty-state" style="grid-column:1/-1">
|
||||||
|
<i class="fas fa-exclamation-triangle" style="color:#fca5a5;"></i>
|
||||||
|
<p style="font-size:15px;font-weight:700;color:#94a3b8;margin-bottom:6px;">${errTitle}</p>
|
||||||
|
<p style="font-size:13px;color:#cbd5e1;">${errDesc}</p>
|
||||||
|
</div>`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
initFilterTabs();
|
||||||
|
initSearch();
|
||||||
|
initDirectory();
|
||||||
|
});
|
||||||
@@ -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
|
||||||
@@ -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 => `
|
||||||
|
<li>
|
||||||
|
<i class="fas fa-check-circle"></i>
|
||||||
|
<span>${s}</span>
|
||||||
|
</li>`)
|
||||||
|
.join('');
|
||||||
|
|
||||||
|
const syaratHTML = syaratItems
|
||||||
|
? `<ul class="syarat-list">${syaratItems}</ul>`
|
||||||
|
: `<p style="font-size:13px;color:#94a3b8;font-style:italic;">${d.req_empty}</p>`;
|
||||||
|
|
||||||
|
const hasUrl = bsw.url_sumber && bsw.url_sumber !== '#';
|
||||||
|
|
||||||
|
// Render konten popup dengan template Anda yang dipertahankan
|
||||||
|
popupBody.innerHTML = `
|
||||||
|
<div class="popup-body">
|
||||||
|
<div class="popup-kategori-row">
|
||||||
|
<span class="badge-status ${badgeClass}">${statusText}</span>
|
||||||
|
<span class="popup-kategori">${kategoriText}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 id="popup-title" class="popup-title">${namaText}</h2>
|
||||||
|
|
||||||
|
<p class="popup-desc">${deskripsiText}</p>
|
||||||
|
|
||||||
|
<div class="popup-section-title">
|
||||||
|
<i class="fas fa-list-check"></i>
|
||||||
|
${d.req_title}
|
||||||
|
</div>
|
||||||
|
${syaratHTML}
|
||||||
|
|
||||||
|
<div class="popup-periode">
|
||||||
|
<div class="popup-periode-item">
|
||||||
|
<label>${d.open_date}</label>
|
||||||
|
<span>${fmtDate(bsw.tanggal_buka, lang)}</span>
|
||||||
|
</div>
|
||||||
|
<div class="popup-periode-item">
|
||||||
|
<label>${d.close_date}</label>
|
||||||
|
<span style="${!isBuka ? 'color:#EF4444;' : ''}">${fmtDate(bsw.tanggal_tutup, lang)}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
${bsw.kontak ? `
|
||||||
|
<div class="popup-kontak">
|
||||||
|
<i class="fas fa-phone-alt"></i>
|
||||||
|
<div>
|
||||||
|
<div style="font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;margin-bottom:2px;">${d.contact}</div>
|
||||||
|
${bsw.kontak}
|
||||||
|
</div>
|
||||||
|
</div>` : ''}
|
||||||
|
|
||||||
|
${hasUrl
|
||||||
|
? `<a
|
||||||
|
href="${bsw.url_sumber}"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
class="popup-cta"
|
||||||
|
aria-label="${d.more_info} ${bsw.nama}"
|
||||||
|
>
|
||||||
|
${d.more_info}
|
||||||
|
<i class="fas fa-external-link-alt" style="font-size:12px;"></i>
|
||||||
|
</a>`
|
||||||
|
: `<button class="popup-cta disabled" disabled aria-disabled="true">
|
||||||
|
${d.more_info}
|
||||||
|
<i class="fas fa-external-link-alt" style="font-size:12px;"></i>
|
||||||
|
</button>
|
||||||
|
<p style="text-align:center;font-size:11px;color:#94a3b8;margin-top:8px;">
|
||||||
|
${d.no_link}
|
||||||
|
</p>`
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
// 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;
|
||||||
@@ -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"]
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -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!"
|
||||||
|
}
|
||||||
|
]
|
||||||
+305
-36
@@ -1,15 +1,27 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="id" class="scroll-smooth">
|
<html lang="id" class="scroll-smooth">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Group 10 – Ape Name Tim E | Informatika UNTAN</title>
|
<title>Group 10 – ApeNameTeamE | Informatika UNTAN</title>
|
||||||
<link rel="stylesheet" href="../../assets/global/output.css">
|
<link rel="stylesheet" href="../../assets/global/output.css">
|
||||||
|
<link rel="stylesheet" href="assets/css/style.css" />
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Roboto+Condensed:ital,wght@0,100..900;1,100..900&family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel="stylesheet">
|
<link
|
||||||
|
href="https://fonts.googleapis.com/css2?family=Roboto+Condensed:ital,wght@0,100..900;1,100..900&family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap"
|
||||||
|
rel="stylesheet">
|
||||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
|
||||||
<style>
|
|
||||||
|
<!-- AOS.js -->
|
||||||
|
<link href="https://unpkg.com/aos@2.3.4/dist/aos.css" rel="stylesheet" />
|
||||||
|
|
||||||
|
<!-- Swiper.js -->
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.css" />
|
||||||
|
|
||||||
|
|
||||||
|
<style>
|
||||||
/* ===== MOBILE NAV STABILITY FIX =====
|
/* ===== MOBILE NAV STABILITY FIX =====
|
||||||
Prevents logo bar from collapsing/shifting on Android when
|
Prevents logo bar from collapsing/shifting on Android when
|
||||||
address bar hides/shows and triggers viewport reflow.
|
address bar hides/shows and triggers viewport reflow.
|
||||||
@@ -293,6 +305,7 @@
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body class="text-slate-800 antialiased bg-white selection:bg-untan-yellow selection:text-black">
|
<body class="text-slate-800 antialiased bg-white selection:bg-untan-yellow selection:text-black">
|
||||||
|
|
||||||
<a href="#main-content" class="skip-link" data-i18n="skip_to_content">Langsung ke Konten Utama</a>
|
<a href="#main-content" class="skip-link" data-i18n="skip_to_content">Langsung ke Konten Utama</a>
|
||||||
@@ -1139,18 +1152,262 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<main id="main-content" class="pt-[88px] lg:pt-[160px] min-h-screen bg-white">
|
<main id="main-content" class="pt-[88px] lg:pt-[160px] min-h-screen bg-white">
|
||||||
<div class="container mx-auto px-4 lg:px-8 py-12">
|
<div class="ticker-wrapper" aria-label="Pengumuman beasiswa terbaru" role="marquee">
|
||||||
<div class="mb-8 pb-8 border-b border-slate-200">
|
<!-- Badge block -->
|
||||||
<span class="bg-untan-yellow text-slate-900 text-[10px] font-bold uppercase tracking-widest px-2 py-0.5 inline-block mb-3">Tugas Halaman Statis</span>
|
<div class="ticker-badge-block">
|
||||||
<h1 class="text-3xl lg:text-4xl font-bold text-slate-900 mb-2">Beasiswa</h1>
|
<span class="ticker-badge" aria-hidden="true">INFO TERBARU</span>
|
||||||
<p class="text-slate-500 text-sm">Kelompok 10 — Ape Name Tim E · Informatika UNTAN 2026</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
<!-- Scroll area: inner wrapper berisi 2 copy teks, dianimasikan bersamaan -->
|
||||||
|
<div class="ticker-scroll-area">
|
||||||
|
<div class="ticker-inner" aria-live="off">
|
||||||
|
<span class="ticker-track">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. </span>
|
||||||
|
<span class="ticker-track" aria-hidden="true">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. </span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ================================================
|
||||||
|
HERO SECTION (#hero)
|
||||||
|
================================================ -->
|
||||||
|
<section id="hero" class="hero-section" aria-label="Header halaman beasiswa">
|
||||||
|
<div class="hero-bg"></div>
|
||||||
|
|
||||||
|
<div class="hero-content max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 w-full">
|
||||||
|
<!-- Breadcrumb -->
|
||||||
|
<nav class="breadcrumb" aria-label="Breadcrumb">
|
||||||
|
<a href="#" data-i18n="breadcrumb_home">Beranda</a>
|
||||||
|
<span class="sep"><i class="fas fa-chevron-right" style="font-size:7px;"></i></span>
|
||||||
|
<a href="#" data-i18n="ape_breadcrumb_profile">Pendidikan</a>
|
||||||
|
<span class="sep"><i class="fas fa-chevron-right" style="font-size:7px;"></i></span>
|
||||||
|
<span class="current" data-i18n="ape_breadcrumb_scholarship">Beasiswa</span>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<div class="grid lg:grid-cols-2 gap-10 lg:gap-20 items-center">
|
||||||
|
|
||||||
|
<!-- Left: Text Content -->
|
||||||
|
<div data-aos="fade-right" data-aos-duration="700">
|
||||||
|
<!-- Badge (outline style seperti Figma) -->
|
||||||
|
<div class="hero-badge">
|
||||||
|
<span data-i18n="ape_hero_badge">PROGRAM BEASISWA</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- H1 -->
|
||||||
|
<h1 class="hero-title" data-i18n-html="ape_hero_title">
|
||||||
|
Beasiswa Studi &<br>Penelitian
|
||||||
|
</h1>
|
||||||
|
|
||||||
|
<!-- Subtitle -->
|
||||||
|
<p class="hero-subtitle" data-i18n="ape_hero_subtitle">
|
||||||
|
Teknik Informatika Universitas Tanjungpura
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- Description (sesuai teks Figma) -->
|
||||||
|
<p class="hero-desc" data-i18n="ape_hero_desc">
|
||||||
|
Temukan berbagai peluang beasiswa untuk mendukung perjalanan akademik dan penelitian Anda.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<!-- CTA Button (kuning, teks gelap — sesuai Figma) -->
|
||||||
|
<a href="#directory" class="hero-cta" aria-label="Lihat daftar beasiswa">
|
||||||
|
<span data-i18n="ape_hero_cta">Lihat Daftar Beasiswa</span>
|
||||||
|
<i class="fas fa-arrow-right"></i>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Right: Hero Image -->
|
||||||
|
<div class="hidden lg:block" data-aos="fade-left" data-aos-delay="150"
|
||||||
|
data-aos-duration="700">
|
||||||
|
<div class="hero-image-wrap">
|
||||||
|
<img src="assets/images/hero/mahasiswa.png"
|
||||||
|
alt="Mahasiswa Informatika UNTAN berprestasi" width="480" height="400"
|
||||||
|
onerror="this.src='https://images.unsplash.com/photo-1523050854058-8df90110c9f1?w=500&q=80'">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- ================================================
|
||||||
|
STATISTIK COUNTER (#statistics)
|
||||||
|
================================================ -->
|
||||||
|
<section id="statistics" class="stats-section" aria-label="Statistik penerima beasiswa">
|
||||||
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<div class="grid grid-cols-3 divide-x divide-white/20">
|
||||||
|
|
||||||
|
<div class="stat-item" data-aos="fade-up" data-aos-delay="0">
|
||||||
|
<div class="stat-number" data-counter="20" id="ctr-total">0</div>
|
||||||
|
<div class="stat-label" data-i18n-html="ape_stats_total">
|
||||||
|
Total Mahasiswa Penerima<br>Beasiswa Semester Ini
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-item" data-aos="fade-up" data-aos-delay="100">
|
||||||
|
<div class="stat-number" data-counter="12" id="ctr-s1">0</div>
|
||||||
|
<div class="stat-label" data-i18n-html="ape_stats_s1">
|
||||||
|
Total Penerima Beasiswa<br>Khusus S1
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="stat-item" data-aos="fade-up" data-aos-delay="200">
|
||||||
|
<div class="stat-number" data-counter="8" id="ctr-studi">0</div>
|
||||||
|
<div class="stat-label" data-i18n-html="ape_stats_studi">
|
||||||
|
Total Penerima Beasiswa<br>Studi Lanjut
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- ================================================
|
||||||
|
DIREKTORI BEASISWA (#directory)
|
||||||
|
================================================ -->
|
||||||
|
<section id="directory" class="py-16 bg-white" aria-label="Direktori beasiswa">
|
||||||
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
|
||||||
|
<!-- Section Header -->
|
||||||
|
<div class="flex flex-col lg:flex-row lg:items-center lg:justify-between gap-6 mb-10">
|
||||||
|
<div data-aos="fade-right">
|
||||||
|
<!-- Label Badge "DAFTAR LENGKAP" -->
|
||||||
|
<div class="section-badge mb-3">
|
||||||
|
<span data-i18n="ape_dir_label">DAFTAR LENGKAP</span>
|
||||||
|
</div>
|
||||||
|
<h2 class="section-title" data-i18n="ape_dir_title">Daftar Beasiswa</h2>
|
||||||
|
<p class="section-desc" data-i18n="ape_dir_desc">
|
||||||
|
Temukan beragam beasiswa dari berbagai sumber resmi yang tersedia untuk mahasiswa aktif.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Filter & Search Row (UC-02, UC-03) -->
|
||||||
|
<div class="flex flex-col lg:flex-row gap-4 mb-8" data-aos="fade-up" data-aos-delay="50">
|
||||||
|
<!-- Filter Tabs -->
|
||||||
|
<div class="filter-tabs flex-1" id="filter-tabs" role="tablist"
|
||||||
|
aria-label="Filter beasiswa">
|
||||||
|
<button class="filter-tab active" data-filter="semua" role="tab" aria-selected="true"
|
||||||
|
data-i18n="filter_all">Semua</button>
|
||||||
|
<button class="filter-tab" data-filter="s1" role="tab" aria-selected="false"
|
||||||
|
data-i18n="ape_filter_s1">S1</button>
|
||||||
|
<button class="filter-tab" data-filter="studi_lanjut" role="tab" aria-selected="false"
|
||||||
|
data-i18n="ape_filter_studi">Studi Lanjut</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Real-Time Search -->
|
||||||
|
<div class="flex flex-col sm:flex-row gap-3 flex-shrink-0">
|
||||||
|
<div class="search-wrapper w-full sm:w-64">
|
||||||
|
<i class="fas fa-search search-icon" aria-hidden="true"></i>
|
||||||
|
<input type="search" id="search-input" class="search-input"
|
||||||
|
placeholder="Cari beasiswa..." data-i18n-placeholder="ape_search_placeholder"
|
||||||
|
aria-label="Cari beasiswa" autocomplete="off" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Cards Grid (rendered by filter.js) -->
|
||||||
|
<div id="beasiswa-grid" class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6" role="list"
|
||||||
|
aria-label="Daftar kartu beasiswa">
|
||||||
|
<!-- Skeleton loading state -->
|
||||||
|
<div class="col-span-full flex flex-col items-center justify-center py-20 text-gray-300">
|
||||||
|
<i class="fas fa-spinner fa-spin text-4xl mb-4"></i>
|
||||||
|
<p class="text-sm font-medium">Memuat data beasiswa...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Pagination (rendered by filter.js) -->
|
||||||
|
<div id="pagination" class="pagination-container" role="navigation"
|
||||||
|
aria-label="Navigasi halaman beasiswa"></div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- ================================================
|
||||||
|
POPUP MODAL DETAIL BEASISWA (UC-04, UC-05)
|
||||||
|
================================================ -->
|
||||||
|
<div id="popup-overlay" role="dialog" aria-modal="true" aria-labelledby="popup-title">
|
||||||
|
<!-- Backdrop (klik untuk tutup - UC-04) -->
|
||||||
|
<div id="popup-backdrop" class="popup-backdrop"></div>
|
||||||
|
|
||||||
|
<!-- Modal Card -->
|
||||||
|
<div id="popup-modal" class="popup-modal" tabindex="-1">
|
||||||
|
<!-- Close Button (×) -->
|
||||||
|
<button id="popup-close" class="popup-close" aria-label="Tutup detail beasiswa">
|
||||||
|
<i class="fas fa-times"></i>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<!-- Content (rendered by popup.js) -->
|
||||||
|
<div id="popup-content"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- ================================================
|
||||||
|
TESTIMONI (#testimonial) — UC-07
|
||||||
|
================================================ -->
|
||||||
|
<section id="testimonial" class="testimonials-section" aria-label="Testimoni penerima beasiswa">
|
||||||
|
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
|
||||||
|
<!-- Header -->
|
||||||
|
<div class="text-center mb-12" data-aos="fade-up">
|
||||||
|
<h2 class="section-title text-center" data-i18n="ape_testimonial_title">Apa Kata Mereka?</h2>
|
||||||
|
<p class="section-desc mx-auto text-center" data-i18n="ape_testimonial_desc">
|
||||||
|
Cerita nyata dari mahasiswa yang telah meraih beasiswa
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Swiper Carousel -->
|
||||||
|
<div class="swiper testimonial-swiper" data-aos="fade-up" data-aos-delay="100">
|
||||||
|
<div class="swiper-wrapper pb-14" id="testimonial-wrapper">
|
||||||
|
<!-- Rendered by carousel.js -->
|
||||||
|
</div>
|
||||||
|
<div class="swiper-pagination testimonial-pagination"></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- ================================================
|
||||||
|
CTA SECTION (#cta) — UC-06
|
||||||
|
================================================ -->
|
||||||
|
<section id="cta" class="cta-section" aria-label="Hubungi admin beasiswa">
|
||||||
|
<div class="max-w-5xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||||
|
<div class="cta-card" data-aos="zoom-in" data-aos-duration="600">
|
||||||
|
<h2 class="cta-title" data-i18n="ape_cta_title">
|
||||||
|
Ingin Mengetahui Info Lebih Lanjut?
|
||||||
|
</h2>
|
||||||
|
<p class="cta-desc" data-i18n="ape_cta_desc">
|
||||||
|
Bersama kami membangun sumber daya manusia unggul melalui program beasiswa dan
|
||||||
|
kolaborasi riset
|
||||||
|
</p>
|
||||||
|
<div class="cta-buttons">
|
||||||
|
<!-- Scroll ke direktori -->
|
||||||
|
<a href="#directory" class="cta-btn-primary" aria-label="Lihat daftar beasiswa">
|
||||||
|
<span data-i18n="ape_cta_btn1">Daftar Beasiswa</span>
|
||||||
|
</a>
|
||||||
|
<!-- Kontak CTA -->
|
||||||
|
<a id="btn-open-contact" class="cta-btn-secondary" aria-label="Hubungi admin" href="https://wa.me/+6285171655161">
|
||||||
|
<span data-i18n="ape_cta_btn2">Hubungi Kami</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<div class="container mx-auto px-4 lg:px-8 py-12">
|
||||||
<div id="assignment-body" class="prose prose-slate max-w-none">
|
<div id="assignment-body" class="prose prose-slate max-w-none">
|
||||||
<!-- ================= START: BAGIAN YANG DIEDIT KELOMPOK ================= -->
|
<!-- ================= START: BAGIAN YANG DIEDIT KELOMPOK ================= -->
|
||||||
<p>Tulis konten halaman kelompok di sini.</p>
|
|
||||||
<h3>Subjudul</h3>
|
|
||||||
<p>Gunakan paragraf, list, tabel, gambar, dan elemen konten lainnya.</p>
|
|
||||||
<!-- ================= END: BAGIAN YANG DIEDIT KELOMPOK ================= -->
|
<!-- ================= END: BAGIAN YANG DIEDIT KELOMPOK ================= -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1215,11 +1472,23 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-full relative z-0 mt-4 pointer-events-none flex justify-center">
|
<div class="w-full relative z-0 mt-4 pointer-events-none flex justify-center">
|
||||||
<img src="../../assets/global/footer.png" alt="Footer Illustration" class="w-full h-auto object-cover object-bottom"
|
<img src="../../assets/global/footer.png" alt="Footer Illustration"
|
||||||
style="object-position: bottom;">
|
class="w-full h-auto object-cover object-bottom" style="object-position: bottom;">
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
|
<script src="https://unpkg.com/aos@2.3.4/dist/aos.js"></script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/swiper@11/swiper-bundle.min.js"></script>
|
||||||
|
|
||||||
|
<script src="../../assets/global/localization.js"></script>
|
||||||
|
|
||||||
|
<script src="assets/js/counter.js"></script>
|
||||||
|
<script type="module" src="assets/js/API.js"></script>
|
||||||
|
<script src="assets/js/popup.js"></script>
|
||||||
|
<script src="assets/js/filter.js"></script>
|
||||||
|
<script src="assets/js/carousel.js"></script>
|
||||||
|
<script src="assets/js/main.js"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function () {
|
(function () {
|
||||||
const menuItems = document.querySelectorAll('[data-menu]');
|
const menuItems = document.querySelectorAll('[data-menu]');
|
||||||
@@ -1312,27 +1581,27 @@
|
|||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
(function() {
|
(function () {
|
||||||
const mobileBtn = document.getElementById('mobile-menu-button');
|
const mobileBtn = document.getElementById('mobile-menu-button');
|
||||||
const mobileMenu = document.getElementById('mobile-menu');
|
const mobileMenu = document.getElementById('mobile-menu');
|
||||||
const closeMobileBtn= document.getElementById('close-mobile-menu');
|
const closeMobileBtn = document.getElementById('close-mobile-menu');
|
||||||
if (mobileBtn && mobileMenu) {
|
if (mobileBtn && mobileMenu) {
|
||||||
mobileBtn.addEventListener('click', function() {
|
mobileBtn.addEventListener('click', function () {
|
||||||
const isOpen = !mobileMenu.classList.contains('-translate-x-full');
|
const isOpen = !mobileMenu.classList.contains('-translate-x-full');
|
||||||
mobileMenu.classList.toggle('-translate-x-full');
|
mobileMenu.classList.toggle('-translate-x-full');
|
||||||
mobileBtn.setAttribute('aria-expanded', isOpen ? 'false' : 'true');
|
mobileBtn.setAttribute('aria-expanded', isOpen ? 'false' : 'true');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (closeMobileBtn && mobileMenu) {
|
if (closeMobileBtn && mobileMenu) {
|
||||||
closeMobileBtn.addEventListener('click', function() {
|
closeMobileBtn.addEventListener('click', function () {
|
||||||
mobileMenu.classList.add('-translate-x-full');
|
mobileMenu.classList.add('-translate-x-full');
|
||||||
if (mobileBtn) mobileBtn.setAttribute('aria-expanded', 'false');
|
if (mobileBtn) mobileBtn.setAttribute('aria-expanded', 'false');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script src="../../assets/global/localization.js"></script>
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
@@ -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"
|
||||||
|
}
|
||||||
|
}
|
||||||
Generated
+7
-7
@@ -886,9 +886,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/nanoid": {
|
"node_modules/nanoid": {
|
||||||
"version": "3.3.11",
|
"version": "3.3.12",
|
||||||
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
|
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz",
|
||||||
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
|
"integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -925,9 +925,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/postcss": {
|
"node_modules/postcss": {
|
||||||
"version": "8.5.8",
|
"version": "8.5.15",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz",
|
||||||
"integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==",
|
"integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"funding": [
|
"funding": [
|
||||||
{
|
{
|
||||||
@@ -945,7 +945,7 @@
|
|||||||
],
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"nanoid": "^3.3.11",
|
"nanoid": "^3.3.12",
|
||||||
"picocolors": "^1.1.1",
|
"picocolors": "^1.1.1",
|
||||||
"source-map-js": "^1.2.1"
|
"source-map-js": "^1.2.1"
|
||||||
},
|
},
|
||||||
|
|||||||
Reference in New Issue
Block a user