Fix conflict
This commit is contained in:
Araya's Project
2026-06-05 10:02:02 +07:00
9 changed files with 384 additions and 336 deletions
+8 -12
View File
@@ -579,16 +579,14 @@ const translations = {
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_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_hero_cta: 'Lihat Daftar Beasiswa',
ape_stats_total: 'Total Mahasiswa Penerima<br>Beasiswa Semester Ini', ape_stats_total: 'Total Mahasiswa Penerima<br>Beasiswa Semester Ini',
ape_stats_gov: 'Total Penerima Beasiswa<br>Pembiayaan Pemerintah', ape_stats_s1: 'Total Penerima Beasiswa<br>Khusus S1',
ape_stats_private: 'Total Penerima Beasiswa<br>Pembiayaan Swasta', ape_stats_studi: 'Total Penerima Beasiswa<br>Studi Lanjut',
ape_dir_label: 'Daftar Beasiswa', ape_dir_label: 'Daftar Beasiswa',
ape_dir_title: '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_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_dir_guide: 'Terima Bantuan Beasiswa?',
ape_filter_open: 'Sedang Buka', ape_filter_s1: 'Khusus S1',
ape_filter_closed: 'Ditutup', ape_filter_studi: 'Studi Lanjut',
ape_filter_gov: 'Pemerintah',
ape_filter_private: 'Swasta',
ape_search_placeholder: 'Cari Nama Beasiswa...', ape_search_placeholder: 'Cari Nama Beasiswa...',
ape_testimonial_title: 'Apa Kata Mereka?', ape_testimonial_title: 'Apa Kata Mereka?',
ape_testimonial_desc: 'Cerita inspiratif dari para penerima beasiswa Program Studi Informatika UNTAN', ape_testimonial_desc: 'Cerita inspiratif dari para penerima beasiswa Program Studi Informatika UNTAN',
@@ -1354,16 +1352,14 @@ const translations = {
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_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_hero_cta: 'View Scholarships',
ape_stats_total: 'Total Scholarship<br>Recipients This Semester', ape_stats_total: 'Total Scholarship<br>Recipients This Semester',
ape_stats_gov: 'Total Government<br>Scholarship Recipients', ape_stats_s1: 'Total Undergraduate<br>Scholarship Recipients',
ape_stats_private: 'Total Private<br>Scholarship Recipients', ape_stats_studi: 'Total Postgraduate<br>Scholarship Recipients',
ape_dir_label: 'Scholarship Directory', ape_dir_label: 'Scholarship Directory',
ape_dir_title: '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_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_dir_guide: 'Need Scholarship Aid?',
ape_filter_open: 'Open', ape_filter_s1: 'Undergraduate',
ape_filter_closed: 'Closed', ape_filter_studi: 'Postgraduate',
ape_filter_gov: 'Government',
ape_filter_private: 'Private',
ape_search_placeholder: 'Search Scholarship Name...', ape_search_placeholder: 'Search Scholarship Name...',
ape_testimonial_title: 'What They Say?', ape_testimonial_title: 'What They Say?',
ape_testimonial_desc: 'Inspiring stories from scholarship recipients at UNTAN Informatics Study Program', ape_testimonial_desc: 'Inspiring stories from scholarship recipients at UNTAN Informatics Study Program',
+70 -39
View File
@@ -1,53 +1,86 @@
// ===================================================== // =====================================================
// carousel.js — Swiper.js Carousel Testimoni // carousel.js — Swiper.js Carousel Testimoni
// Touch-friendly, auto-play, responsive breakpoints // Touch-friendly, auto-play, responsive breakpoints
// + DUKUNGAN MULTI-BAHASA (ID/EN) Terintegrasi
// ===================================================== // =====================================================
let testimoniSwiper = null; 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 */ /** Render slide testimoni ke dalam swiper-wrapper */
function renderTestimoniSlides(data) { function renderTestimoniSlides(data) {
const wrapper = document.getElementById('testimonial-wrapper'); const wrapper = document.getElementById('testimonial-wrapper');
if (!wrapper) return; if (!wrapper) return;
const lang = activeCarouselLang; // Gunakan bahasa terbaru
wrapper.innerHTML = data.map(t => ` wrapper.innerHTML = data.map(t => {
<div class="swiper-slide" style="height:auto;"> // Logika Pintar: Cek mode bahasa. Jika 'en' dan teks terjemahannya ada, pakai bahasa Inggris.
<div class="testimonial-card"> // Jika tidak, tetap tampilkan teks bahasa Indonesia (sebagai cadangan).
<img const beasiswaName = (lang === 'en' && t.nama_beasiswa_en) ? t.nama_beasiswa_en : t.nama_beasiswa;
src="${t.foto}" const quote = (lang === 'en' && t.kutipan_en) ? t.kutipan_en : t.kutipan;
alt="Foto ${t.nama}"
class="testimonial-avatar" return `
loading="lazy" <div class="swiper-slide" style="height:auto;">
onerror=" <div class="testimonial-card">
this.style.display='none'; <img
this.nextElementSibling.style.display='flex'; src="${t.foto}"
" alt="Foto ${t.nama}"
> class="testimonial-avatar"
<div loading="lazy"
class="testimonial-avatar" onerror="
style=" this.style.display='none';
display:none; this.nextElementSibling.style.display='flex';
background:linear-gradient(135deg,#003150,#4a6bc5); "
align-items:center; >
justify-content:center; <div
color:white; class="testimonial-avatar"
font-size:22px; style="
font-weight:700; display:none;
" background:linear-gradient(135deg,#003150,#4a6bc5);
> align-items:center;
${t.nama.charAt(0).toUpperCase()} 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>
<div class="testimonial-name">${t.nama}</div>
<div class="testimonial-beasiswa">${t.nama_beasiswa}</div>
<p class="testimonial-quote">"${t.kutipan}"</p>
</div> </div>
</div> `;
`).join(''); }).join('');
} }
/** Inisialisasi Swiper setelah slide di-render */ /** Inisialisasi Swiper setelah slide di-render */
function initSwiper(count) { function initSwiper(count) {
// Bersihkan swiper lama jika ada (penting agar tidak menumpuk saat ganti bahasa)
if (testimoniSwiper) { if (testimoniSwiper) {
testimoniSwiper.destroy(true, true); testimoniSwiper.destroy(true, true);
testimoniSwiper = null; testimoniSwiper = null;
@@ -72,9 +105,10 @@ function initSwiper(count) {
640: { slidesPerView: 2 }, 640: { slidesPerView: 2 },
1024: { slidesPerView: 3 }, 1024: { slidesPerView: 3 },
}, },
// Dukungan Aksesibilitas Dinamis (VoiceOver / Screen Reader)
a11y: { a11y: {
prevSlideMessage: 'Slide sebelumnya', prevSlideMessage: activeCarouselLang === 'en' ? 'Previous slide' : 'Slide sebelumnya',
nextSlideMessage: 'Slide berikutnya', nextSlideMessage: activeCarouselLang === 'en' ? 'Next slide' : 'Slide berikutnya',
}, },
}); });
} }
@@ -88,22 +122,19 @@ async function initCarousel() {
if (!res.ok) throw new Error(`HTTP ${res.status}`); if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json(); const data = await res.json();
allTestimoniData = data; // Simpan ke variabel global
if (!data || data.length === 0) { if (!data || data.length === 0) {
// Sembunyikan seksi testimoni jika data kosong (sesuai UC-07 Alt Flow)
section?.classList.add('hidden'); section?.classList.add('hidden');
return; return;
} }
renderTestimoniSlides(data); renderTestimoniSlides(data);
// Init Swiper setelah DOM di-render
requestAnimationFrame(() => initSwiper(data.length)); requestAnimationFrame(() => initSwiper(data.length));
} catch { } catch {
// Jika gagal fetch, sembunyikan seksi (graceful degradation)
section?.classList.add('hidden'); section?.classList.add('hidden');
} }
} }
document.addEventListener('DOMContentLoaded', initCarousel); document.addEventListener('DOMContentLoaded', initCarousel);
+103 -85
View File
@@ -1,70 +1,113 @@
// ===================================================== // =====================================================
// filter.js — Fetch JSON, Render Kartu, Filter Tab, Pencarian, Paginasi // filter.js — Fetch JSON, Render Kartu, Filter Tab, Pencarian, Paginasi
// Filter dan search berjalan KUMULATIF (sesuai PROJECT_CONTEXT rule #6) // Filter dan search berjalan KUMULATIF
// + DUKUNGAN MULTI-BAHASA (ID/EN) Terintegrasi
// ===================================================== // =====================================================
const ITEMS_PER_PAGE = 6; // 2 baris × 3 kolom desktop const ITEMS_PER_PAGE = 6;
let allData = []; // Semua data beasiswa dari JSON let allData = [];
let activeFilter = 'semua'; let activeFilter = 'semua';
let searchKeyword = ''; let searchKeyword = '';
let currentPage = 1; let currentPage = 1;
// Format tanggal // 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) { function formatDate(str) {
if (!str) return '—'; if (!str) return '—';
const d = new Date(str); const d = new Date(str);
if (isNaN(d.getTime())) return str; if (isNaN(d.getTime())) return str;
return d.toLocaleDateString('id-ID', {
return d.toLocaleDateString(activeLang === 'en' ? 'en-US' : 'id-ID', {
day: 'numeric', month: 'long', year: 'numeric' day: 'numeric', month: 'long', year: 'numeric'
}); });
} }
// Sanitasi string untuk mencegah XSS pada search // 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) { function sanitize(str) {
return str.replace(/[<>&"']/g, c => return str.replace(/[<>&"']/g, c =>
({ '<': '&lt;', '>': '&gt;', '&': '&amp;', '"': '&quot;', "'": '&#39;' }[c]) ({ '<': '&lt;', '>': '&gt;', '&': '&amp;', '"': '&quot;', "'": '&#39;' }[c])
); );
} }
/**
* Buat elemen kartu beasiswa
* Gunakan textContent/setAttribute — hindari langsung innerHTML dari user input
*/
function createCard(bsw) { function createCard(bsw) {
// Tentukan badge & warna tombol status const lang = activeLang; // Selalu gunakan bahasa aktif terbaru
// Terjemahan Tombol Status
let statusClass = 'status-btn-ditutup'; let statusClass = 'status-btn-ditutup';
let statusLabel = 'Ditutup'; let statusLabel = lang === 'en' ? 'Closed' : 'Ditutup';
const statusLower = (bsw.status || '').toLowerCase(); const statusLower = (bsw.status || '').toLowerCase();
if (statusLower === 'buka' || statusLower === 'dibuka') { if (statusLower === 'buka' || statusLower === 'dibuka') {
statusClass = 'status-btn-buka'; statusClass = 'status-btn-buka';
statusLabel = 'Pendaftaran Dibuka'; statusLabel = lang === 'en' ? 'Registration Open' : 'Pendaftaran Dibuka';
} else if (statusLower.includes('segera')) { } else if (statusLower.includes('segera')) {
statusClass = 'status-btn-segera'; statusClass = 'status-btn-segera';
statusLabel = 'Segera Dibuka'; statusLabel = lang === 'en' ? 'Opening Soon' : 'Segera Dibuka';
} }
// Ambil pills dari tags lokal: ["jenjang", "kategori/swasta/pemerintah", "negara", "tipe_pendanaan", ...] // --- 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 tags = Array.isArray(bsw.tags) ? bsw.tags : [];
const jenjang = tags[0] || ''; const jenjang = tags[0] || '';
// Negara: cari tag yang bukan jenjang (S1/S2/S3), bukan kategori sumber (Swasta/Pemerintah),
// dan bukan tipe pendanaan (Fully/Partially Funded)
const skipPatterns = /^(S1|S2|S3|D3|D4|Swasta|Pemerintah|Fully Funded|Partially Funded|Beasiswa Penuh|Beasiswa Sebagian|Prestasi)$/i; const skipPatterns = /^(S1|S2|S3|D3|D4|Swasta|Pemerintah|Fully Funded|Partially Funded|Beasiswa Penuh|Beasiswa Sebagian|Prestasi)$/i;
const negara = tags.slice(1).find(t => !skipPatterns.test(t)) || ''; const rawNegara = tags.slice(1).find(t => !skipPatterns.test(t)) || '';
const negara = translateDynamic(rawNegara, lang);
// Tipe pendanaan untuk subtitle — ambil dari kategori field atau dari deskripsi_singkat // Terjemahan Subtitle (Kategori Beasiswa)
const tipe = bsw.kategori || ''; 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] const pillsHtml = [jenjang, negara]
.filter(Boolean) .filter(Boolean)
.map((t, i) => `<span class="card-pill ${i === 0 ? 'card-pill-level' : ''}">${t}</span>`) .map((t, i) => `<span class="card-pill ${i === 0 ? 'card-pill-level' : ''}">${t}</span>`)
.join(''); .join('');
// Subtitle: hindari duplikasi "Beasiswa Beasiswa ..."
const rawTipe = tipe.replace(/^beasiswa\s+/i, '');
const subtitle = rawTipe ? `Beasiswa ${rawTipe}` : '';
const article = document.createElement('article'); const article = document.createElement('article');
article.className = 'scholarship-card fade-in-up'; article.className = 'scholarship-card fade-in-up';
article.setAttribute('role', 'listitem'); article.setAttribute('role', 'listitem');
@@ -72,17 +115,17 @@ function createCard(bsw) {
article.innerHTML = ` article.innerHTML = `
<div class="card-body"> <div class="card-body">
<h3 class="card-title">${bsw.nama}</h3> <h3 class="card-title">${namaBsw}</h3>
${subtitle ? `<p class="card-subtitle">${subtitle}</p>` : ''} ${subtitle ? `<p class="card-subtitle">${subtitle}</p>` : ''}
${pillsHtml ? `<div class="card-pills">${pillsHtml}</div>` : ''} ${pillsHtml ? `<div class="card-pills">${pillsHtml}</div>` : ''}
<hr class="card-divider"> <hr class="card-divider">
<div class="card-dates"> <div class="card-dates">
<div class="card-date-col"> <div class="card-date-col">
<span class="card-date-label">Mulai</span> <span class="card-date-label">${textMulai}</span>
<span class="card-date-value">${formatDate(bsw.tanggal_buka)}</span> <span class="card-date-value">${formatDate(bsw.tanggal_buka)}</span>
</div> </div>
<div class="card-date-col"> <div class="card-date-col">
<span class="card-date-label">Deadline</span> <span class="card-date-label">${textDeadline}</span>
<span class="card-date-value">${formatDate(bsw.tanggal_tutup)}</span> <span class="card-date-value">${formatDate(bsw.tanggal_tutup)}</span>
</div> </div>
</div> </div>
@@ -90,70 +133,67 @@ function createCard(bsw) {
<button <button
class="btn-selengkapnya" class="btn-selengkapnya"
onclick="openPopup('${bsw.id}')" onclick="openPopup('${bsw.id}')"
aria-label="Lihat detail beasiswa ${bsw.nama}" aria-label="Lihat detail beasiswa ${namaBsw}"
>Selengkapnya</button> >${textSelengkapnya}</button>
</div> </div>
`; `;
return article; return article;
} }
/**
* Filter data KUMULATIF: filter tab DAN search harus terpenuhi keduanya
*/
function getFiltered() { function getFiltered() {
const kw = searchKeyword.toLowerCase(); const kw = searchKeyword.toLowerCase();
return allData.filter(bsw => { return allData.filter(bsw => {
// Cocok dengan filter tab
const matchFilter = // Logika Filter Tab S1 & Studi Lanjut
activeFilter === 'semua' || let matchFilter = false;
bsw.status === activeFilter || const tags = bsw.tags || [];
bsw.kategori === activeFilter;
// Cocok dengan pencarian (nama atau deskripsi atau tags) if (activeFilter === 'semua') {
const matchSearch = matchFilter = true;
!kw || } else if (activeFilter === 's1') {
bsw.nama.toLowerCase().includes(kw) || matchFilter = tags.some(t => t.includes('S1'));
bsw.deskripsi_singkat.toLowerCase().includes(kw) || } else if (activeFilter === 'studi_lanjut') {
(bsw.tags || []).some(t => t.toLowerCase().includes(kw)); 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; return matchFilter && matchSearch;
}); });
} }
/** Render kartu + paginasi ke DOM */
function renderCards() { function renderCards() {
const grid = document.getElementById('beasiswa-grid'); const grid = document.getElementById('beasiswa-grid');
const pagCont = document.getElementById('pagination'); const pagCont = document.getElementById('pagination');
const filtered = getFiltered(); const filtered = getFiltered();
const lang = activeLang; // Gunakan bahasa terbaru
// Bersihkan grid
grid.innerHTML = ''; grid.innerHTML = '';
if (filtered.length === 0) { 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 = ` grid.innerHTML = `
<div class="empty-state" style="grid-column:1/-1"> <div class="empty-state" style="grid-column:1/-1">
<i class="fas fa-search-minus"></i> <i class="fas fa-search-minus"></i>
<p style="font-size:15px;font-weight:700;color:#94a3b8;margin-bottom:6px;"> <p style="font-size:15px;font-weight:700;color:#94a3b8;margin-bottom:6px;">${emptyTitle}</p>
Tidak ada beasiswa ditemukan <p style="font-size:13px;color:#cbd5e1;">${emptyDesc}</p>
</p>
<p style="font-size:13px;color:#cbd5e1;">
Coba ubah filter atau kata kunci pencarian Anda
</p>
</div>`; </div>`;
pagCont.innerHTML = ''; pagCont.innerHTML = '';
return; return;
} }
// Hitung paginasi
const totalPages = Math.ceil(filtered.length / ITEMS_PER_PAGE); const totalPages = Math.ceil(filtered.length / ITEMS_PER_PAGE);
if (currentPage > totalPages) currentPage = totalPages; if (currentPage > totalPages) currentPage = totalPages;
const start = (currentPage - 1) * ITEMS_PER_PAGE; const start = (currentPage - 1) * ITEMS_PER_PAGE;
const items = filtered.slice(start, start + ITEMS_PER_PAGE); const items = filtered.slice(start, start + ITEMS_PER_PAGE);
// Render kartu dengan delay animasi berurutan
items.forEach((bsw, i) => { items.forEach((bsw, i) => {
const card = createCard(bsw); const card = createCard(bsw);
card.style.animationDelay = `${i * 55}ms`; card.style.animationDelay = `${i * 55}ms`;
@@ -163,7 +203,6 @@ function renderCards() {
renderPagination(totalPages, pagCont); renderPagination(totalPages, pagCont);
} }
/** Render tombol-tombol paginasi */
function renderPagination(total, container) { function renderPagination(total, container) {
container.innerHTML = ''; container.innerHTML = '';
if (total <= 1) return; if (total <= 1) return;
@@ -173,12 +212,10 @@ function renderPagination(total, container) {
btn.className = `page-btn${isActive ? ' active' : ''}`; btn.className = `page-btn${isActive ? ' active' : ''}`;
btn.innerHTML = content; btn.innerHTML = content;
btn.disabled = disabled; btn.disabled = disabled;
btn.setAttribute('aria-label', typeof page === 'number' ? `Halaman ${page}` : content);
if (!disabled) { if (!disabled) {
btn.addEventListener('click', () => { btn.addEventListener('click', () => {
currentPage = page; currentPage = page;
renderCards(); renderCards();
// Scroll halus ke atas direktori
const dir = document.getElementById('directory'); const dir = document.getElementById('directory');
if (dir) { if (dir) {
const top = dir.getBoundingClientRect().top + window.scrollY - 120; const top = dir.getBoundingClientRect().top + window.scrollY - 120;
@@ -189,19 +226,13 @@ function renderPagination(total, container) {
return btn; return btn;
}; };
// Prev
container.appendChild(make('<i class="fas fa-chevron-left" style="font-size:11px;"></i>', currentPage - 1, currentPage === 1)); container.appendChild(make('<i class="fas fa-chevron-left" style="font-size:11px;"></i>', currentPage - 1, currentPage === 1));
// Halaman
for (let i = 1; i <= total; i++) { for (let i = 1; i <= total; i++) {
container.appendChild(make(i, i, false, i === currentPage)); container.appendChild(make(i, i, false, i === currentPage));
} }
// Next
container.appendChild(make('<i class="fas fa-chevron-right" style="font-size:11px;"></i>', currentPage + 1, currentPage === total)); container.appendChild(make('<i class="fas fa-chevron-right" style="font-size:11px;"></i>', currentPage + 1, currentPage === total));
} }
/** Inisialisasi tab filter */
function initFilterTabs() { function initFilterTabs() {
document.querySelectorAll('.filter-tab').forEach(btn => { document.querySelectorAll('.filter-tab').forEach(btn => {
btn.addEventListener('click', () => { btn.addEventListener('click', () => {
@@ -218,47 +249,34 @@ function initFilterTabs() {
}); });
} }
/** Inisialisasi real-time search */
function initSearch() { function initSearch() {
const input = document.getElementById('search-input'); const input = document.getElementById('search-input');
if (!input) return; if (!input) return;
input.addEventListener('input', () => { input.addEventListener('input', () => {
// Sanitasi input sebelum digunakan (cegah XSS)
searchKeyword = sanitize(input.value).trim(); searchKeyword = sanitize(input.value).trim();
currentPage = 1; currentPage = 1;
renderCards(); renderCards();
}); });
} }
/** Fetch data via API.js (BeasiswaAPI) lalu render */
async function initDirectory() { async function initDirectory() {
const grid = document.getElementById('beasiswa-grid'); const grid = document.getElementById('beasiswa-grid');
try { try {
if (!window.BeasiswaAPI) { if (!window.BeasiswaAPI) throw new Error('Modul API.js (BeasiswaAPI) belum dimuat');
throw new Error('Modul API.js (BeasiswaAPI) belum dimuat');
}
const { data, source } = await window.BeasiswaAPI.getBeasiswa(); const { data, source } = await window.BeasiswaAPI.getBeasiswa();
allData = data; allData = data;
console.info(`[items] beasiswa dimuat dari sumber: ${source} (${allData.length} item)`);
// Simpan ke window agar popup.js bisa akses
window.beasiswaData = allData; window.beasiswaData = allData;
renderCards(); renderCards();
} catch (err) { } catch (err) {
console.error('[items] gagal memuat beasiswa', 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 = ` grid.innerHTML = `
<div class="empty-state" style="grid-column:1/-1"> <div class="empty-state" style="grid-column:1/-1">
<i class="fas fa-exclamation-triangle" style="color:#fca5a5;"></i> <i class="fas fa-exclamation-triangle" style="color:#fca5a5;"></i>
<p style="font-size:15px;font-weight:700;color:#94a3b8;margin-bottom:6px;"> <p style="font-size:15px;font-weight:700;color:#94a3b8;margin-bottom:6px;">${errTitle}</p>
Gagal memuat data beasiswa <p style="font-size:13px;color:#cbd5e1;">${errDesc}</p>
</p>
<p style="font-size:13px;color:#cbd5e1;">
Tidak dapat terhubung ke server. Silakan refresh atau hubungi admin.
</p>
</div>`; </div>`;
} }
} }
@@ -267,4 +285,4 @@ document.addEventListener('DOMContentLoaded', () => {
initFilterTabs(); initFilterTabs();
initSearch(); initSearch();
initDirectory(); initDirectory();
}); });
-136
View File
@@ -1,136 +0,0 @@
// =====================================================
// i18n.js — Toggle Bahasa Indonesia / English
// Sesuai PROJECT_CONTEXT: tersimpan di sessionStorage
// =====================================================
const i18nData = {
id: {
'nav.tentang': 'TENTANG KAMI',
'nav.program': 'PROGRAM',
'nav.sdm': 'SDM',
'nav.fasilitas': 'FASILITAS',
'nav.agenda': 'KARYA & AGENDA',
'nav.kontak': 'KONTAK',
'breadcrumb.home': 'Beranda',
'breadcrumb.profile': 'Profil',
'breadcrumb.scholarship': 'Beasiswa',
'hero.badge': 'Program Beasiswa',
'hero.title': 'Beasiswa Studi &<br>Penelitian',
'hero.subtitle': 'Teknik Informatika Universitas Tanjungpura',
'hero.desc': 'Temukan berbagai peluang beasiswa untuk mendukung perjalanan akademik dan penelitian Anda. Program Studi Informatika UNTAN berkomitmen membantu mahasiswa meraih prestasi terbaik.',
'hero.cta': 'Lihat Daftar Beasiswa',
'stats.total': 'Total Mahasiswa Penerima<br>Beasiswa Semester Ini',
'stats.gov': 'Total Penerima Beasiswa<br>Pembiayaan Pemerintah',
'stats.private': 'Total Penerima Beasiswa<br>Pembiayaan Swasta',
'dir.label': 'Daftar Beasiswa',
'dir.title': 'Daftar Beasiswa',
'dir.desc': 'Temukan beragam beasiswa dari berbagai sumber resmi yang tersedia untuk mahasiswa aktif, alumni, dan calon mahasiswa Program Studi Informatika UNTAN.',
'dir.receive': 'Terima Bantuan Beasiswa?',
'filter.all': 'SEMUA',
'filter.open': 'Sedang Buka',
'filter.closed': 'Ditutup',
'filter.gov': 'Pemerintah',
'filter.private': 'Swasta',
'search.placeholder': 'Cari Nama Beasiswa...',
'testimonial.title': 'Apa Kata Mereka?',
'testimonial.desc': 'Cerita inspiratif dari para penerima beasiswa Program Studi Informatika UNTAN',
'cta.title': 'Ingin Mengetahui Info Lebih Lanjut?',
'cta.desc': 'Hubungi admin prodi atau ikuti Instagram kemahasiswaan UNTAN untuk informasi terbaru tentang beasiswa dan program akademik.',
'cta.btn1': 'DAFTAR BEASISWA',
'cta.btn2': 'Hubungi Kami',
'ticker': 'Pendaftaran Beasiswa KIP Kuliah 2026 telah dibuka! &nbsp;—&nbsp; Beasiswa Pertamina Foundation open hingga Agustus 2026 &nbsp;—&nbsp; Daftarkan diri Anda sekarang! &nbsp;—&nbsp; Info lengkap tersedia di halaman direktori beasiswa &nbsp;—&nbsp; Beasiswa LPDP S2 masih tersedia hingga September 2026 &nbsp;—&nbsp;',
},
en: {
'nav.tentang': 'ABOUT US',
'nav.program': 'PROGRAMS',
'nav.sdm': 'HUMAN RESOURCES',
'nav.fasilitas': 'FACILITIES',
'nav.agenda': 'WORKS & EVENTS',
'nav.kontak': 'CONTACT',
'breadcrumb.home': 'Home',
'breadcrumb.profile': 'Profile',
'breadcrumb.scholarship': 'Scholarship',
'hero.badge': 'Scholarship Program',
'hero.title': 'Study & Research<br>Scholarships',
'hero.subtitle': 'Informatics Engineering, Tanjungpura University',
'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.',
'hero.cta': 'View Scholarships',
'stats.total': 'Total Scholarship<br>Recipients This Semester',
'stats.gov': 'Total Government<br>Scholarship Recipients',
'stats.private': 'Total Private<br>Scholarship Recipients',
'dir.label': 'Scholarship Directory',
'dir.title': 'Scholarship Directory',
'dir.desc': 'Find various scholarships from official sources available for active students, alumni, and prospective students of the UNTAN Informatics Study Program.',
'dir.receive': 'Need Scholarship Aid?',
'filter.all': 'ALL',
'filter.open': 'Open',
'filter.closed': 'Closed',
'filter.gov': 'Government',
'filter.private': 'Private',
'search.placeholder': 'Search Scholarship Name...',
'testimonial.title': 'What They Say?',
'testimonial.desc': 'Inspiring stories from scholarship recipients at UNTAN Informatics Study Program',
'cta.title': 'Want to Know More?',
'cta.desc': 'Contact the program admin or follow UNTAN student affairs Instagram for the latest scholarship and academic program information.',
'cta.btn1': 'SCHOLARSHIP LIST',
'cta.btn2': 'Contact Us',
'ticker': 'KIP Kuliah Scholarship 2026 registration is now open! &nbsp;—&nbsp; Pertamina Foundation Scholarship open until August 2026 &nbsp;—&nbsp; Register now! &nbsp;—&nbsp; Full info available in the scholarship directory &nbsp;—&nbsp; LPDP S2 Scholarship available until September 2026 &nbsp;—&nbsp;',
}
};
// Load saved language from session storage
let currentLang = sessionStorage.getItem('lang') || 'id';
function applyTranslations(lang) {
const t = i18nData[lang];
if (!t) return;
// Apply data-i18n attributes
document.querySelectorAll('[data-i18n]').forEach(el => {
const key = el.getAttribute('data-i18n');
if (t[key] !== undefined) {
el.innerHTML = t[key];
}
});
// Apply data-i18n-placeholder attributes
document.querySelectorAll('[data-i18n-placeholder]').forEach(el => {
const key = el.getAttribute('data-i18n-placeholder');
if (t[key] !== undefined) {
el.placeholder = t[key];
}
});
// Update HTML lang attribute
document.documentElement.lang = lang === 'id' ? 'id' : 'en';
}
// Override setLanguage to delegate to localization.js when available,
// so both systems stay in sync (localization.js dispatches 'languageChanged'
// which triggers our listener below to re-apply dot-key translations).
function setLanguage(lang) {
if (lang !== 'id' && lang !== 'en') return;
if (typeof setLang === 'function') {
setLang(lang); // localization.js handles state + dispatches languageChanged
} else {
currentLang = lang;
sessionStorage.setItem('lang', lang);
applyTranslations(lang);
}
}
window.setLanguage = setLanguage;
// Re-apply dot-key translations whenever localization.js changes the language.
// This fixes the race where localization.js overwrites dot-key elements with the
// raw key string (its fallback for unknown keys).
document.addEventListener('languageChanged', (e) => {
applyTranslations(e.detail.lang);
});
// Initialize on DOM ready
document.addEventListener('DOMContentLoaded', () => {
// Use localization.js state if it's already loaded, otherwise fall back.
const initLang = (typeof getLang === 'function') ? getLang()
: (sessionStorage.getItem('lang') || 'id');
applyTranslations(initLang);
});
+8 -3
View File
@@ -18,9 +18,13 @@ document.addEventListener('DOMContentLoaded', () => {
// Navbar sudah fixed di CSS; tidak perlu mengubah warna karena // Navbar sudah fixed di CSS; tidak perlu mengubah warna karena
// warna primary sudah menjadi identitas halaman ini. // warna primary sudah menjadi identitas halaman ini.
// Namun kita tambahkan shadow saat scroll untuk depth effect. // Namun kita tambahkan shadow saat scroll untuk depth effect.
const navbar = document.getElementById('navbar');
// PERBAIKAN: Menyesuaikan ID dengan yang ada di index.html (nav-wrapper)
const navbar = document.getElementById('nav-wrapper') || document.getElementById('navbar');
const handleScroll = () => { const handleScroll = () => {
if (!navbar) return; // PERBAIKAN: Mencegah error jika elemen tidak ada di halaman
if (window.scrollY > 10) { if (window.scrollY > 10) {
navbar.style.boxShadow = '0 4px 20px rgba(0,0,0,0.25)'; navbar.style.boxShadow = '0 4px 20px rgba(0,0,0,0.25)';
} else { } else {
@@ -78,7 +82,8 @@ document.addEventListener('DOMContentLoaded', () => {
e.preventDefault(); e.preventDefault();
const navHeight = navbar.offsetHeight || 110; // PERBAIKAN: Mencegah error saat membaca offsetHeight jika navbar null
const navHeight = navbar ? navbar.offsetHeight : 110;
const top = target.getBoundingClientRect().top + window.scrollY - navHeight - 4; const top = target.getBoundingClientRect().top + window.scrollY - navHeight - 4;
window.scrollTo({ top, behavior: 'smooth' }); window.scrollTo({ top, behavior: 'smooth' });
@@ -165,4 +170,4 @@ document.addEventListener('DOMContentLoaded', () => {
if (contactClose) contactClose.addEventListener('click', closeContactModal); if (contactClose) contactClose.addEventListener('click', closeContactModal);
if (contactBackdrop) contactBackdrop.addEventListener('click', closeContactModal); if (contactBackdrop) contactBackdrop.addEventListener('click', closeContactModal);
}); // end DOMContentLoaded }); // end DOMContentLoaded
+90 -38
View File
@@ -1,6 +1,7 @@
// ===================================================== // =====================================================
// popup.js — Modal Detail Beasiswa // popup.js — Modal Detail Beasiswa
// Tutup via: tombol ×, klik overlay, tekan Escape // Tutup via: tombol ×, klik overlay, tekan Escape
// + DUKUNGAN MULTI-BAHASA (ID/EN)
// ===================================================== // =====================================================
const overlay = document.getElementById('popup-overlay'); const overlay = document.getElementById('popup-overlay');
@@ -8,32 +9,91 @@ const modal = document.getElementById('popup-modal');
const closeBtn = document.getElementById('popup-close'); const closeBtn = document.getElementById('popup-close');
const popupBody = document.getElementById('popup-content'); const popupBody = document.getElementById('popup-content');
// Format tanggal ke format Indonesia let currentOpenId = null; // Menyimpan status beasiswa mana yang sedang dibuka
function fmtDate(str) {
// 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 '—'; if (!str) return '—';
const d = new Date(str); const d = new Date(str);
if (isNaN(d.getTime())) return str; if (isNaN(d.getTime())) return str;
return d.toLocaleDateString('id-ID', { return d.toLocaleDateString(lang === 'en' ? 'en-US' : 'id-ID', {
day: 'numeric', day: 'numeric',
month: 'long', month: 'long',
year: 'numeric' 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 * Buka popup modal untuk beasiswa dengan ID tertentu
* Data diambil dari window.beasiswaData yang diset oleh filter.js
*/ */
function openPopup(id) { function openPopup(id) {
currentOpenId = id;
const data = window.beasiswaData || []; const data = window.beasiswaData || [];
const bsw = data.find(b => b.id === id); const bsw = data.find(b => b.id === id);
if (!bsw) return; if (!bsw) return;
const lang = getPopupLang();
const d = popupDict[lang];
const isBuka = bsw.status === 'Buka' || bsw.status === 'Dibuka'; const isBuka = bsw.status === 'Buka' || bsw.status === 'Dibuka';
const badgeClass = isBuka ? 'badge-buka' : 'badge-ditutup'; 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 // Bangun list syarat umum
const syaratItems = (bsw.syarat_umum || []) const syaratItems = syaratData
.map(s => ` .map(s => `
<li> <li>
<i class="fas fa-check-circle"></i> <i class="fas fa-check-circle"></i>
@@ -43,74 +103,65 @@ function openPopup(id) {
const syaratHTML = syaratItems const syaratHTML = syaratItems
? `<ul class="syarat-list">${syaratItems}</ul>` ? `<ul class="syarat-list">${syaratItems}</ul>`
: `<p style="font-size:13px;color:#94a3b8;font-style:italic;"> : `<p style="font-size:13px;color:#94a3b8;font-style:italic;">${d.req_empty}</p>`;
Syarat belum tersedia. Kunjungi sumber resmi.
</p>`;
const hasUrl = bsw.url_sumber && bsw.url_sumber !== '#'; const hasUrl = bsw.url_sumber && bsw.url_sumber !== '#';
// Render konten popup // Render konten popup dengan template Anda yang dipertahankan
popupBody.innerHTML = ` popupBody.innerHTML = `
<div class="popup-body"> <div class="popup-body">
<!-- Badge status + kategori -->
<div class="popup-kategori-row"> <div class="popup-kategori-row">
<span class="badge-status ${badgeClass}">${bsw.status}</span> <span class="badge-status ${badgeClass}">${statusText}</span>
<span class="popup-kategori">${bsw.kategori}</span> <span class="popup-kategori">${kategoriText}</span>
</div> </div>
<!-- Judul --> <h2 id="popup-title" class="popup-title">${namaText}</h2>
<h2 id="popup-title" class="popup-title">${bsw.nama}</h2>
<!-- Deskripsi singkat --> <p class="popup-desc">${deskripsiText}</p>
<p class="popup-desc">${bsw.deskripsi_singkat}</p>
<!-- Syarat Umum -->
<div class="popup-section-title"> <div class="popup-section-title">
<i class="fas fa-list-check"></i> <i class="fas fa-list-check"></i>
Syarat Umum ${d.req_title}
</div> </div>
${syaratHTML} ${syaratHTML}
<!-- Periode Pendaftaran -->
<div class="popup-periode"> <div class="popup-periode">
<div class="popup-periode-item"> <div class="popup-periode-item">
<label>Tanggal Buka</label> <label>${d.open_date}</label>
<span>${fmtDate(bsw.tanggal_buka)}</span> <span>${fmtDate(bsw.tanggal_buka, lang)}</span>
</div> </div>
<div class="popup-periode-item"> <div class="popup-periode-item">
<label>Tanggal Tutup</label> <label>${d.close_date}</label>
<span style="${!isBuka ? 'color:#EF4444;' : ''}">${fmtDate(bsw.tanggal_tutup)}</span> <span style="${!isBuka ? 'color:#EF4444;' : ''}">${fmtDate(bsw.tanggal_tutup, lang)}</span>
</div> </div>
</div> </div>
<!-- Kontak -->
${bsw.kontak ? ` ${bsw.kontak ? `
<div class="popup-kontak"> <div class="popup-kontak">
<i class="fas fa-phone-alt"></i> <i class="fas fa-phone-alt"></i>
<div> <div>
<div style="font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;margin-bottom:2px;">Kontak</div> <div style="font-size:10px;font-weight:700;text-transform:uppercase;letter-spacing:.5px;margin-bottom:2px;">${d.contact}</div>
${bsw.kontak} ${bsw.kontak}
</div> </div>
</div>` : ''} </div>` : ''}
<!-- Tombol Info Lebih Lanjut (UC-05) -->
${hasUrl ${hasUrl
? `<a ? `<a
href="${bsw.url_sumber}" href="${bsw.url_sumber}"
target="_blank" target="_blank"
rel="noopener noreferrer" rel="noopener noreferrer"
class="popup-cta" class="popup-cta"
aria-label="Info lebih lanjut tentang ${bsw.nama}" aria-label="${d.more_info} ${bsw.nama}"
> >
Info Lebih Lanjut ${d.more_info}
<i class="fas fa-external-link-alt" style="font-size:12px;"></i> <i class="fas fa-external-link-alt" style="font-size:12px;"></i>
</a>` </a>`
: `<button class="popup-cta disabled" disabled aria-disabled="true"> : `<button class="popup-cta disabled" disabled aria-disabled="true">
Info Lebih Lanjut ${d.more_info}
<i class="fas fa-external-link-alt" style="font-size:12px;"></i> <i class="fas fa-external-link-alt" style="font-size:12px;"></i>
</button> </button>
<p style="text-align:center;font-size:11px;color:#94a3b8;margin-top:8px;"> <p style="text-align:center;font-size:11px;color:#94a3b8;margin-top:8px;">
Tautan tidak tersedia. Silakan hubungi admin prodi. ${d.no_link}
</p>` </p>`
} }
</div> </div>
@@ -126,25 +177,26 @@ function openPopup(id) {
/** Tutup popup modal */ /** Tutup popup modal */
function closePopup() { function closePopup() {
currentOpenId = null;
overlay.classList.remove('show'); overlay.classList.remove('show');
document.body.style.overflow = ''; document.body.style.overflow = '';
} }
// === Event Listeners untuk menutup popup === // === Event Listeners untuk menutup popup ===
// 1. Tombol × close
closeBtn?.addEventListener('click', closePopup); closeBtn?.addEventListener('click', closePopup);
// 2. Klik di luar area modal (backdrop)
document.getElementById('popup-backdrop')?.addEventListener('click', closePopup); document.getElementById('popup-backdrop')?.addEventListener('click', closePopup);
// 3. Tekan Escape
document.addEventListener('keydown', (e) => { document.addEventListener('keydown', (e) => {
if (e.key === 'Escape' && overlay.classList.contains('show')) { if (e.key === 'Escape' && overlay.classList.contains('show')) {
closePopup(); closePopup();
} }
}); });
// Expose ke global (dipanggil dari onclick di kartu) // 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.openPopup = openPopup;
window.closePopup = closePopup; window.closePopup = closePopup;
+89 -2
View File
@@ -2,16 +2,25 @@
{ {
"id": "bsw-001", "id": "bsw-001",
"nama": "Boustany Foundation Scholarship, MBA - Harvard University", "nama": "Boustany Foundation Scholarship, MBA - Harvard University",
"nama_en": "Boustany Foundation Scholarship, MBA - Harvard University",
"kategori": "Swasta", "kategori": "Swasta",
"kategori_en": "Private",
"status": "Buka", "status": "Buka",
"thumbnail": "https://images.unsplash.com/photo-1541339907198-e08756dedf3f?w=400&q=80&auto=format&fit=crop", "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": "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": [ "syarat_umum": [
"Diterima atau mendaftar di program MBA Harvard Business School", "Diterima atau mendaftar di program MBA Harvard Business School",
"Memiliki rekam jejak prestasi akademik dan profesional yang luar biasa", "Memiliki rekam jejak prestasi akademik dan profesional yang luar biasa",
"Menunjukkan potensi kepemimpinan dan kontribusi internasional", "Menunjukkan potensi kepemimpinan dan kontribusi internasional",
"Melengkapi aplikasi beasiswa secara online melalui situs resmi Boustany Foundation" "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", "kontak": "Boustany Foundation — boustany-foundation.com",
"tanggal_buka": "2026-05-21", "tanggal_buka": "2026-05-21",
"tanggal_tutup": "2027-05-31", "tanggal_tutup": "2027-05-31",
@@ -22,15 +31,23 @@
"id": "bsw-002", "id": "bsw-002",
"nama": "La Trobe University - La Trobe High Achiever Scholarship (S1)", "nama": "La Trobe University - La Trobe High Achiever Scholarship (S1)",
"kategori": "Swasta", "kategori": "Swasta",
"kategori_en": "Private",
"status": "Buka", "status": "Buka",
"thumbnail": "https://images.unsplash.com/photo-1523240795612-9a054b0db644?w=400&q=80&auto=format&fit=crop", "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": "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": [ "syarat_umum": [
"Mendaftar sebagai mahasiswa internasional jenjang S1 (Undergraduate) di La Trobe University", "Mendaftar sebagai mahasiswa internasional jenjang S1 (Undergraduate) di La Trobe University",
"Memiliki nilai akademik yang sangat baik (High Achiever)", "Memiliki nilai akademik yang sangat baik (High Achiever)",
"Tidak sedang menerima beasiswa penuh lainnya dari La Trobe University", "Tidak sedang menerima beasiswa penuh lainnya dari La Trobe University",
"Memenuhi persyaratan masuk dan kemampuan bahasa Inggris 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", "kontak": "La Trobe University Admissions — latrobe.edu.au",
"tanggal_buka": "2023-09-29", "tanggal_buka": "2023-09-29",
"tanggal_tutup": "2026-12-31", "tanggal_tutup": "2026-12-31",
@@ -41,15 +58,23 @@
"id": "bsw-003", "id": "bsw-003",
"nama": "Charles Sturt University - International Student Support Scholarship", "nama": "Charles Sturt University - International Student Support Scholarship",
"kategori": "Swasta", "kategori": "Swasta",
"kategori_en": "Private",
"status": "Buka", "status": "Buka",
"thumbnail": "https://images.unsplash.com/photo-1560472354-b33ff0c44a43?w=400&q=80&auto=format&fit=crop", "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": "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": [ "syarat_umum": [
"Mendaftar sebagai mahasiswa internasional penuh waktu (full-time) jenjang S1", "Mendaftar sebagai mahasiswa internasional penuh waktu (full-time) jenjang S1",
"Memenuhi persyaratan penerimaan akademik Charles Sturt University", "Memenuhi persyaratan penerimaan akademik Charles Sturt University",
"Memiliki kemampuan Bahasa Inggris yang memadai (IELTS/TOEFL)", "Memiliki kemampuan Bahasa Inggris yang memadai (IELTS/TOEFL)",
"Mendaftar melalui jalur penerimaan internasional resmi" "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", "kontak": "Charles Sturt University International — csu.edu.au",
"tanggal_buka": "2026-05-21", "tanggal_buka": "2026-05-21",
"tanggal_tutup": "2026-12-31", "tanggal_tutup": "2026-12-31",
@@ -60,15 +85,23 @@
"id": "bsw-004", "id": "bsw-004",
"nama": "La Trobe University - La Trobe High Achiever Scholarship (S2)", "nama": "La Trobe University - La Trobe High Achiever Scholarship (S2)",
"kategori": "Swasta", "kategori": "Swasta",
"kategori_en": "Private",
"status": "Buka", "status": "Buka",
"thumbnail": "https://images.unsplash.com/photo-1529156069898-49953e39b3ac?w=400&q=80&auto=format&fit=crop", "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": "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": [ "syarat_umum": [
"Mendaftar sebagai mahasiswa internasional jenjang S2 di La Trobe University", "Mendaftar sebagai mahasiswa internasional jenjang S2 di La Trobe University",
"Memiliki nilai akademik yang sangat baik di jenjang sarjana sebelumnya", "Memiliki nilai akademik yang sangat baik di jenjang sarjana sebelumnya",
"Memenuhi persyaratan bahasa Inggris yang ditetapkan", "Memenuhi persyaratan bahasa Inggris yang ditetapkan",
"Tidak sedang menerima beasiswa lain dari universitas yang sama" "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", "kontak": "La Trobe University Admissions — latrobe.edu.au",
"tanggal_buka": "2023-09-29", "tanggal_buka": "2023-09-29",
"tanggal_tutup": "2026-12-31", "tanggal_tutup": "2026-12-31",
@@ -79,9 +112,11 @@
"id": "bsw-005", "id": "bsw-005",
"nama": "ETH Zurich - Excellence Scholarship & Opportunity Programme (ESOP)", "nama": "ETH Zurich - Excellence Scholarship & Opportunity Programme (ESOP)",
"kategori": "Pemerintah", "kategori": "Pemerintah",
"kategori_en": "Government",
"status": "Buka", "status": "Buka",
"thumbnail": "https://images.unsplash.com/photo-1497366754035-f200968a6e72?w=400&q=80&auto=format&fit=crop", "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": "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": [ "syarat_umum": [
"Mendaftar program Master (S2) di ETH Zurich", "Mendaftar program Master (S2) di ETH Zurich",
"Lulus ujian penerimaan ETH Zurich atau memiliki setara gelar sarjana yang diakui", "Lulus ujian penerimaan ETH Zurich atau memiliki setara gelar sarjana yang diakui",
@@ -89,6 +124,13 @@
"Melengkapi formulir aplikasi beasiswa ESOP yang terpisah dari aplikasi studi", "Melengkapi formulir aplikasi beasiswa ESOP yang terpisah dari aplikasi studi",
"Mendapatkan surat rekomendasi dari akademisi berwenang" "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", "kontak": "ETH Zurich Scholarship Office — ethz.ch",
"tanggal_buka": "2026-11-01", "tanggal_buka": "2026-11-01",
"tanggal_tutup": "2026-11-30", "tanggal_tutup": "2026-11-30",
@@ -99,9 +141,11 @@
"id": "bsw-006", "id": "bsw-006",
"nama": "STUST - Scholarship for International Students (S3, Fully Funded)", "nama": "STUST - Scholarship for International Students (S3, Fully Funded)",
"kategori": "Swasta", "kategori": "Swasta",
"kategori_en": "Private",
"status": "Buka", "status": "Buka",
"thumbnail": "https://images.unsplash.com/photo-1580582932707-520aed937b7b?w=400&q=80&auto=format&fit=crop", "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": "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": [ "syarat_umum": [
"Mendaftar program Doktoral (S3) di STUST, Taiwan", "Mendaftar program Doktoral (S3) di STUST, Taiwan",
"Memiliki gelar magister (S2) yang diakui", "Memiliki gelar magister (S2) yang diakui",
@@ -109,6 +153,13 @@
"Menyerahkan proposal penelitian yang relevan dengan bidang studi yang dipilih", "Menyerahkan proposal penelitian yang relevan dengan bidang studi yang dipilih",
"Mendapatkan persetujuan dari calon pembimbing (supervisor) di STUST" "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", "kontak": "STUST International Affairs Office — stust.edu.tw",
"tanggal_buka": "2026-09-15", "tanggal_buka": "2026-09-15",
"tanggal_tutup": "2026-11-30", "tanggal_tutup": "2026-11-30",
@@ -119,9 +170,11 @@
"id": "bsw-007", "id": "bsw-007",
"nama": "STUST - Scholarship for International Students (S2, Partially Funded)", "nama": "STUST - Scholarship for International Students (S2, Partially Funded)",
"kategori": "Swasta", "kategori": "Swasta",
"kategori_en": "Private",
"status": "Buka", "status": "Buka",
"thumbnail": "https://images.unsplash.com/photo-1606761568499-6d2451b23c66?w=400&q=80&auto=format&fit=crop", "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": "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": [ "syarat_umum": [
"Mendaftar program Magister (S2) di STUST, Taiwan", "Mendaftar program Magister (S2) di STUST, Taiwan",
"Memiliki gelar sarjana (S1) yang diakui", "Memiliki gelar sarjana (S1) yang diakui",
@@ -129,6 +182,13 @@
"Melengkapi berkas aplikasi secara online melalui portal resmi STUST", "Melengkapi berkas aplikasi secara online melalui portal resmi STUST",
"Menyertakan transkrip nilai dan surat motivasi" "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", "kontak": "STUST International Affairs Office — stust.edu.tw",
"tanggal_buka": "2026-09-15", "tanggal_buka": "2026-09-15",
"tanggal_tutup": "2026-11-30", "tanggal_tutup": "2026-11-30",
@@ -139,9 +199,11 @@
"id": "bsw-008", "id": "bsw-008",
"nama": "University of Melbourne - Melbourne International Undergraduate Scholarship", "nama": "University of Melbourne - Melbourne International Undergraduate Scholarship",
"kategori": "Swasta", "kategori": "Swasta",
"kategori_en": "Private",
"status": "Buka", "status": "Buka",
"thumbnail": "https://images.unsplash.com/photo-1504711434969-e33886168f5c?w=400&q=80&auto=format&fit=crop", "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": "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": [ "syarat_umum": [
"Merupakan mahasiswa internasional (bukan warga negara Australia atau New Zealand)", "Merupakan mahasiswa internasional (bukan warga negara Australia atau New Zealand)",
"Mendaftar program sarjana (S1 / Undergraduate) di University of Melbourne", "Mendaftar program sarjana (S1 / Undergraduate) di University of Melbourne",
@@ -149,6 +211,13 @@
"Memenuhi persyaratan kemampuan bahasa Inggris (IELTS minimal 6.5)", "Memenuhi persyaratan kemampuan bahasa Inggris (IELTS minimal 6.5)",
"Beasiswa diberikan otomatis berdasarkan nilai akademik, tidak perlu aplikasi terpisah" "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", "kontak": "University of Melbourne Future Students — unimelb.edu.au",
"tanggal_buka": "2026-05-21", "tanggal_buka": "2026-05-21",
"tanggal_tutup": "2026-10-31", "tanggal_tutup": "2026-10-31",
@@ -159,9 +228,11 @@
"id": "bsw-009", "id": "bsw-009",
"nama": "Charles Darwin University - CDU Global Merit Scholarship", "nama": "Charles Darwin University - CDU Global Merit Scholarship",
"kategori": "Swasta", "kategori": "Swasta",
"kategori_en": "Private",
"status": "Buka", "status": "Buka",
"thumbnail": "https://images.unsplash.com/photo-1434030216411-0b793f4b4173?w=400&q=80&auto=format&fit=crop", "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": "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": [ "syarat_umum": [
"Mendaftar sebagai mahasiswa internasional baru (new international student) di CDU", "Mendaftar sebagai mahasiswa internasional baru (new international student) di CDU",
"Mendaftar untuk program sarjana (Undergraduate/S1) penuh waktu", "Mendaftar untuk program sarjana (Undergraduate/S1) penuh waktu",
@@ -169,6 +240,13 @@
"Memenuhi persyaratan bahasa Inggris (IELTS 6.0 atau setara)", "Memenuhi persyaratan bahasa Inggris (IELTS 6.0 atau setara)",
"Tidak sedang menerima potongan biaya kuliah lainnya dari CDU" "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", "kontak": "CDU International — cdu.edu.au",
"tanggal_buka": "2026-05-21", "tanggal_buka": "2026-05-21",
"tanggal_tutup": "2026-10-09", "tanggal_tutup": "2026-10-09",
@@ -179,9 +257,11 @@
"id": "bsw-010", "id": "bsw-010",
"nama": "Deakin University - Vice-Chancellor's International Scholarship", "nama": "Deakin University - Vice-Chancellor's International Scholarship",
"kategori": "Swasta", "kategori": "Swasta",
"kategori_en": "Private",
"status": "Buka", "status": "Buka",
"thumbnail": "https://images.unsplash.com/photo-1541339907198-e08756dedf3f?w=400&q=80&auto=format&fit=crop", "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": "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": [ "syarat_umum": [
"Merupakan mahasiswa internasional (bukan warga negara Australia/New Zealand)", "Merupakan mahasiswa internasional (bukan warga negara Australia/New Zealand)",
"Mendaftar untuk program S1 (Undergraduate) atau S2 (Postgraduate Coursework) di Deakin", "Mendaftar untuk program S1 (Undergraduate) atau S2 (Postgraduate Coursework) di Deakin",
@@ -189,10 +269,17 @@
"Memenuhi persyaratan masuk dan kemampuan bahasa Inggris Deakin University", "Memenuhi persyaratan masuk dan kemampuan bahasa Inggris Deakin University",
"Mengajukan aplikasi beasiswa sebelum tanggal penutupan yang ditetapkan" "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", "kontak": "Deakin University International — deakin.edu.au",
"tanggal_buka": "2026-05-21", "tanggal_buka": "2026-05-21",
"tanggal_tutup": "2026-09-25", "tanggal_tutup": "2026-09-25",
"url_sumber": "https://www.schoters.com/id/beasiswa/deakin-university-vice-chancellor-s-international-scholarship-10", "url_sumber": "https://www.schoters.com/id/beasiswa/deakin-university-vice-chancellor-s-international-scholarship-10",
"tags": ["S1", "S2", "Swasta", "Australia", "Partially Funded", "Prestasi"] "tags": ["S1 & S2", "S2", "Swasta", "Australia", "Partially Funded", "Prestasi"]
} }
] ]
+5 -3
View File
@@ -3,7 +3,9 @@
"id": "tsm-001", "id": "tsm-001",
"nama": "Violaine Gunawan", "nama": "Violaine Gunawan",
"foto": "https://ui-avatars.com/api/?name=Violaine+Gunawan&background=111a2f&color=fff&size=200&rounded=true", "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": "BEASISWA BAKTI BCA 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!" "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!"
} }
] ]
+11 -18
View File
@@ -1247,7 +1247,6 @@
<div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8"> <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="grid grid-cols-3 divide-x divide-white/20">
<!-- Total Penerima -->
<div class="stat-item" data-aos="fade-up" data-aos-delay="0"> <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-number" data-counter="20" id="ctr-total">0</div>
<div class="stat-label" data-i18n-html="ape_stats_total"> <div class="stat-label" data-i18n-html="ape_stats_total">
@@ -1255,19 +1254,17 @@
</div> </div>
</div> </div>
<!-- Pemerintah -->
<div class="stat-item" data-aos="fade-up" data-aos-delay="100"> <div class="stat-item" data-aos="fade-up" data-aos-delay="100">
<div class="stat-number" data-counter="12" id="ctr-gov">0</div> <div class="stat-number" data-counter="12" id="ctr-s1">0</div>
<div class="stat-label" data-i18n-html="ape_stats_gov"> <div class="stat-label" data-i18n-html="ape_stats_s1">
Total Penerima Beasiswa<br>Pembiayaan Pemerintah Total Penerima Beasiswa<br>Khusus S1
</div> </div>
</div> </div>
<!-- Swasta -->
<div class="stat-item" data-aos="fade-up" data-aos-delay="200"> <div class="stat-item" data-aos="fade-up" data-aos-delay="200">
<div class="stat-number" data-counter="8" id="ctr-pvt">0</div> <div class="stat-number" data-counter="8" id="ctr-studi">0</div>
<div class="stat-label" data-i18n-html="ape_stats_private"> <div class="stat-label" data-i18n-html="ape_stats_studi">
Total Penerima Beasiswa<br>Pembiayaan Swasta Total Penerima Beasiswa<br>Studi Lanjut
</div> </div>
</div> </div>
@@ -1302,14 +1299,10 @@
aria-label="Filter beasiswa"> aria-label="Filter beasiswa">
<button class="filter-tab active" data-filter="semua" role="tab" aria-selected="true" <button class="filter-tab active" data-filter="semua" role="tab" aria-selected="true"
data-i18n="filter_all">Semua</button> data-i18n="filter_all">Semua</button>
<button class="filter-tab" data-filter="Buka" role="tab" aria-selected="false" <button class="filter-tab" data-filter="s1" role="tab" aria-selected="false"
data-i18n="ape_filter_open">Sedang Buka</button> data-i18n="ape_filter_s1">S1</button>
<button class="filter-tab" data-filter="Ditutup" role="tab" aria-selected="false" <button class="filter-tab" data-filter="studi_lanjut" role="tab" aria-selected="false"
data-i18n="ape_filter_closed">Ditutup</button> data-i18n="ape_filter_studi">Studi Lanjut</button>
<button class="filter-tab" data-filter="Pemerintah" role="tab" aria-selected="false"
data-i18n="ape_filter_gov">Pemerintah</button>
<button class="filter-tab" data-filter="Swasta" role="tab" aria-selected="false"
data-i18n="ape_filter_private">Swasta</button>
</div> </div>
<!-- Real-Time Search --> <!-- Real-Time Search -->
@@ -1487,6 +1480,7 @@
<script src="https://unpkg.com/aos@2.3.4/dist/aos.js"></script> <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="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 src="assets/js/counter.js"></script>
<script type="module" src="assets/js/API.js"></script> <script type="module" src="assets/js/API.js"></script>
@@ -1608,7 +1602,6 @@
})(); })();
</script> </script>
<script src="../../assets/global/localization.js"></script>
</body> </body>
</html> </html>