Files
student-web-if-development-kit/groups/ACAAB/src/services/api.ts
T

205 lines
6.6 KiB
TypeScript

import { Achievement, Project } from '../data';
// Determine API Base URL dynamically from Vite env, fallback to hardcoded if not set
const API_BASE_URL = import.meta.env.VITE_API_BASE_URL || 'https://api.ifuntanhub.dev';
const BIDANG_MAP: Record<number, string> = {
1: 'Kecerdasan Buatan',
2: 'Cyber Security',
3: 'Data',
4: 'Software Engineering',
5: 'Competitive Programming',
6: 'IoT',
7: 'Smart City',
8: 'Web3',
9: 'Karya Tulis Ilmiah',
10: 'Robotik',
};
/**
* Helper to parse Rank/Juara from Achievement title
*/
function extractRank(title: string): string {
const match = title.match(/(Juara\s+\d+|Juara\s+Harapan\s*\d*|Top\s+\d+|Finalis|Peringkat\s+\d+|Medali\s+\w+)/i);
return match ? match[0] : 'Pemenang';
}
/**
* Helper to parse Level (Nasional, Internasional, Regional) from title/category
*/
function extractLevel(title: string, category: string): 'Nasional' | 'Internasional' | 'Regional' {
const text = `${title} ${category}`.toLowerCase();
if (
text.includes('internasional') ||
text.includes('international') ||
text.includes('global') ||
text.includes('world') ||
text.includes('asean') ||
text.includes('unesco')
) {
return 'Internasional';
}
if (
text.includes('regional') ||
text.includes('kalbar') ||
text.includes('kalimantan') ||
text.includes('provinsi') ||
text.includes('kota') ||
text.includes('kabupaten') ||
text.includes('lokal')
) {
return 'Regional';
}
return 'Nasional'; // Default fallback
}
/**
* Helper to extract competition name from full achievement title
*/
function extractCompetition(title: string): string {
return title
.replace(/^(Juara\s+\d+|Juara\s+Harapan\s*\d*|Top\s+\d+|Finalis|Peringkat\s+\d+|Medali\s+\w+)\s+(di\s+|pada\s+|dalam\s+)?/i, '')
.trim();
}
/**
* Fetch achievements from API
*/
export async function fetchAchievementsFromAPI(): Promise<Achievement[]> {
const response = await fetch(`${API_BASE_URL}/items/prestasi?fields=*.*`);
if (!response.ok) {
throw new Error(`Failed to fetch achievements: ${response.statusText}`);
}
const result = await response.json();
const data = result.data || [];
return data
.filter((item: any) => item.status === 'published')
.map((item: any) => {
const id = String(item.id);
const title = item.nama_prestasi || 'Untitled Achievement';
let category = 'Umum';
if (item.bidang_id) {
if (typeof item.bidang_id === 'object' && item.bidang_id.nama_bidang) {
category = item.bidang_id.nama_bidang;
} else {
category = BIDANG_MAP[item.bidang_id as number] || 'Umum';
}
}
const rank = extractRank(title);
const level = extractLevel(title, category);
const competition = extractCompetition(title);
const year = parseInt(item.tahun) || new Date().getFullYear();
const anggota = Array.isArray(item.anggota) ? item.anggota : [];
const team = item.nama_tim || (anggota.length > 0 ? anggota[0].nama : 'Mahasiswa');
// Handle image url mapping for directus assets
let image = `https://picsum.photos/seed/prestasi-${id}/800/600`;
if (item.galeri && Array.isArray(item.galeri) && item.galeri.length > 0) {
const firstImg = item.galeri[0];
const imgId = typeof firstImg === 'string' ? firstImg : (firstImg.directus_files_id || firstImg.id);
if (imgId) image = `${API_BASE_URL}/assets/${imgId}`;
} else if (item.foto) {
image = `${API_BASE_URL}/assets/${item.foto}`;
}
const avatar = (item.nama_tim || item.nama_prestasi || 'IF')
.substring(0, 2)
.toUpperCase();
const description = item.deskripsi || `${team} berhasil meraih prestasi luar biasa sebagai ${rank} dalam ajang ${competition} tahun ${year} pada bidang ${category.toLowerCase()}.`;
return {
id,
title,
category,
competition,
rank,
year,
level,
description,
team,
nim: item.nim || undefined,
generation: item.angkatan ? `Angkatan ${item.angkatan}` : 'Informatika',
image,
avatar,
members: anggota.map((m: any) => ({ nama: m.nama, angkatan: m.angkatan ? parseInt(m.angkatan) : undefined })),
};
});
}
/**
* Fetch projects/portfolio from API
*/
export async function fetchProjectsFromAPI(): Promise<Project[]> {
const response = await fetch(`${API_BASE_URL}/items/portfolio?fields=*,bidang.bidang_id.nama_bidang,galeri.*`);
if (!response.ok) {
throw new Error(`Failed to fetch portfolio: ${response.statusText}`);
}
const result = await response.json();
const data = result.data || [];
return data
.filter((item: any) => item.status === 'published')
.map((item: any) => {
const id = String(item.id);
const title = item.nama_proyek || 'Untitled Project';
const anggota = Array.isArray(item.anggota) ? item.anggota : [];
const studentName = item.nama_mahasiswa || (anggota.length > 0 ? anggota[0].nama : 'Mahasiswa');
const year = parseInt(item.tahun) || new Date().getFullYear();
const description = item.deskripsi || 'Tidak ada deskripsi.';
let categories: string[] = [];
if (item.bidang && Array.isArray(item.bidang)) {
categories = item.bidang.map((b: any) => {
if (b.bidang_id && typeof b.bidang_id === 'object' && b.bidang_id.nama_bidang) {
return b.bidang_id.nama_bidang;
}
if (typeof b.bidang_id === 'number') {
return BIDANG_MAP[b.bidang_id] || 'Umum';
}
return 'Umum';
}).filter(Boolean);
}
if (categories.length === 0) {
categories = ['Umum'];
}
let link = item.url || undefined;
if (link && !/^https?:\/\//i.test(link)) {
link = `https://${link}`;
}
let image = `https://picsum.photos/seed/project-${id}/800/600`;
if (item.galeri && Array.isArray(item.galeri) && item.galeri.length > 0) {
const firstImg = item.galeri[0];
const imgId = typeof firstImg === 'string' ? firstImg : (firstImg.directus_files_id || firstImg.id);
if (imgId) image = `${API_BASE_URL}/assets/${imgId}`;
} else if (item.foto) {
image = `${API_BASE_URL}/assets/${item.foto}`;
}
return {
id,
title,
studentName,
nim: item.nim || undefined,
year,
category: categories,
description,
image,
link,
catatan: item.catatan || undefined,
members: anggota.map((m: any) => ({ nama: m.nama, nim: m.nim || undefined })),
};
});
}