forked from izu/student-web-if-development-kit
fixing data fetching from external API, spesifically in achievement and projects categories and name of team member
This commit is contained in:
@@ -3,6 +3,21 @@ 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
|
||||
*/
|
||||
@@ -53,7 +68,7 @@ function extractCompetition(title: string): string {
|
||||
* Fetch achievements from API
|
||||
*/
|
||||
export async function fetchAchievementsFromAPI(): Promise<Achievement[]> {
|
||||
const response = await fetch(`${API_BASE_URL}/items/prestasi`);
|
||||
const response = await fetch(`${API_BASE_URL}/items/prestasi?fields=*.*`);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch achievements: ${response.statusText}`);
|
||||
}
|
||||
@@ -65,24 +80,39 @@ export async function fetchAchievementsFromAPI(): Promise<Achievement[]> {
|
||||
.map((item: any) => {
|
||||
const id = String(item.id);
|
||||
const title = item.nama_prestasi || 'Untitled Achievement';
|
||||
const category = item.bidang || 'Akademik';
|
||||
|
||||
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 team = item.nama_tim || 'Mahasiswa';
|
||||
|
||||
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
|
||||
const image = item.foto
|
||||
? `${API_BASE_URL}/assets/${item.foto}`
|
||||
: `https://picsum.photos/seed/prestasi-${id}/800/600`;
|
||||
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();
|
||||
|
||||
// Create a friendly fallback description since Directus model lacks one
|
||||
const description = `${team} berhasil meraih prestasi luar biasa sebagai ${rank} dalam ajang ${competition} tahun ${year} pada bidang ${category.toLowerCase()}.`;
|
||||
const description = item.deskripsi || `${team} berhasil meraih prestasi luar biasa sebagai ${rank} dalam ajang ${competition} tahun ${year} pada bidang ${category.toLowerCase()}.`;
|
||||
|
||||
return {
|
||||
id,
|
||||
@@ -98,6 +128,7 @@ export async function fetchAchievementsFromAPI(): Promise<Achievement[]> {
|
||||
generation: item.angkatan ? `Angkatan ${item.angkatan}` : 'Informatika',
|
||||
image,
|
||||
avatar,
|
||||
members: anggota.map((m: any) => ({ nama: m.nama, angkatan: m.angkatan ? parseInt(m.angkatan) : undefined })),
|
||||
};
|
||||
});
|
||||
}
|
||||
@@ -106,7 +137,7 @@ export async function fetchAchievementsFromAPI(): Promise<Achievement[]> {
|
||||
* Fetch projects/portfolio from API
|
||||
*/
|
||||
export async function fetchProjectsFromAPI(): Promise<Project[]> {
|
||||
const response = await fetch(`${API_BASE_URL}/items/portfolio`);
|
||||
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}`);
|
||||
}
|
||||
@@ -118,18 +149,43 @@ export async function fetchProjectsFromAPI(): Promise<Project[]> {
|
||||
.map((item: any) => {
|
||||
const id = String(item.id);
|
||||
const title = item.nama_proyek || 'Untitled Project';
|
||||
const studentName = item.nama_mahasiswa || 'Mahasiswa';
|
||||
|
||||
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 category = item.bidang || 'Software Development';
|
||||
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}`;
|
||||
}
|
||||
|
||||
const image = item.foto
|
||||
? `${API_BASE_URL}/assets/${item.foto}`
|
||||
: `https://picsum.photos/seed/project-${id}/800/600`;
|
||||
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,
|
||||
@@ -137,10 +193,12 @@ export async function fetchProjectsFromAPI(): Promise<Project[]> {
|
||||
studentName,
|
||||
nim: item.nim || undefined,
|
||||
year,
|
||||
category,
|
||||
category: categories,
|
||||
description,
|
||||
image,
|
||||
link,
|
||||
catatan: item.catatan || undefined,
|
||||
members: anggota.map((m: any) => ({ nama: m.nama, nim: m.nim || undefined })),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user