import { DirectusClient } from '../services/directus-client.js'; import { DocumentCardView } from '../components/document-card-view.js'; import { CustomDropdown } from '../components/custom-dropdown.js'; import { DateRangePicker } from '../components/date-range-picker.js'; import { CounterAnimation } from '../components/counter-animation.js'; export class DocumentRepository { static PAGE_SIZE = 6; constructor() { this.gridContainer = document.getElementById('document-grid'); this.filterWrapper = document.getElementById('tag-filter-wrapper'); this.mobileFilterWrapper = document.getElementById('mobile-tag-filter-wrapper'); this.searchInput = document.getElementById('doc-search'); this.sortFilterWrapper = document.getElementById('sort-filter-wrapper'); // Hero stat values (filled from real API data after fetch). this.statActiveEl = document.getElementById('stat-active-value'); this.statUpdatesEl = document.getElementById('stat-updates-value'); this.cards = []; this.paginationContainer = null; this.state = { filter: 'all', // 'all' or a specific tag string search: '', startDate: '', endDate: '', sort: 'newest', page: 1, }; } async init() { if (!this.gridContainer) return; this._bindControls(); this._initPagination(); try { const items = await DirectusClient.fetchPublished('berkas'); this._renderCards(items); this._buildCategoryFilters(items); this._renderStats(items); this._applySort(); this._applyFilters(); } catch (err) { console.error(err); this._renderError(); this._renderStatsError(); } } _initPagination() { const pag = document.createElement('div'); pag.id = 'doc-pagination'; pag.className = 'doc-pagination'; this.gridContainer.insertAdjacentElement('afterend', pag); this.paginationContainer = pag; } // Days within which an upload counts as a "recent update". static RECENT_DAYS = 30; // Populate the hero stats from real data: // Dokumen Aktif → number of published documents // Pembaruan Terbaru → uploads within the last RECENT_DAYS days _renderStats(items) { const active = items.length; const windowMs = DocumentRepository.RECENT_DAYS * 24 * 60 * 60 * 1000; const now = Date.now(); const recent = items.filter(item => { if (!item.tanggal_upload) return false; const t = new Date(item.tanggal_upload).getTime(); return !Number.isNaN(t) && now - t <= windowMs; }).length; CounterAnimation.animateValue(this.statActiveEl, active); CounterAnimation.animateValue(this.statUpdatesEl, recent); } _renderStatsError() { if (this.statActiveEl) this.statActiveEl.textContent = '—'; if (this.statUpdatesEl) this.statUpdatesEl.textContent = '—'; } /** * Fixed category definitions for the sidebar filter. * Each has a key, an i18n key for bilingual labels, and a fallback label. */ static CATEGORIES = [ { key: 'all', i18n: 'filter_all', label: 'Semua Berkas' }, { key: 'skripsi', i18n: 'filter_skripsi', label: 'Panduan Skripsi' }, { key: 'akademik', i18n: 'filter_akademik', label: 'Kalender Akademik' }, { key: 'praktik', i18n: 'filter_praktik', label: 'Kerja Praktik' }, { key: 'umum', i18n: 'filter_umum', label: 'Formulir Umum' }, ]; /** * Build category filter controls: * – Desktop: sidebar buttons (hidden on mobile via CSS) * – Mobile: a