diff --git a/equipment/equipment.js b/equipment/equipment.js
index 6ee542e..f3bc3bc 100644
--- a/equipment/equipment.js
+++ b/equipment/equipment.js
@@ -1,4 +1,4 @@
-window.loadHeader(function(headerContainer) {
+window.loadHeader(async function(headerContainer) {
const logoutForm = document.getElementById("logout-form");
if (logoutForm) {
logoutForm.action = "/api/v1/spfn/logout";
@@ -41,6 +41,7 @@ window.loadHeader(function(headerContainer) {
};
let combinedData = {};
+ let mappingCache = null;
const preloadImage = (url) => {
return new Promise((resolve) => {
@@ -52,7 +53,7 @@ window.loadHeader(function(headerContainer) {
});
};
- const renderData = async (newData) => {
+ const renderData = async (newData, isFinalFallback = false) => {
if (!newData) return;
let data = newData;
@@ -85,20 +86,25 @@ window.loadHeader(function(headerContainer) {
const infoBox = document.querySelector('.splat-info-box');
if (infoBox) {
- const fetchJson = url => fetch(url).then(r => r.ok ? r.json() : []);
- const [clothing, headgear, shoes, weapons, abilities] = await Promise.all([
- fetchJson('/assets/mapping/clothing.json'),
- fetchJson('/assets/mapping/headgear.json'),
- fetchJson('/assets/mapping/shoes.json'),
- fetchJson('/assets/mapping/weapons.json'),
- fetchJson('/assets/mapping/ability.json')
- ]);
+ if (!mappingCache) {
+ const fetchJson = url => fetch(url).then(r => r.ok ? r.json() : []);
+ mappingCache = await Promise.all([
+ fetchJson('/assets/mapping/clothing.json'),
+ fetchJson('/assets/mapping/headgear.json'),
+ fetchJson('/assets/mapping/shoes.json'),
+ fetchJson('/assets/mapping/weapons.json'),
+ fetchJson('/assets/mapping/ability.json')
+ ]);
+ }
+ const [clothing, headgear, shoes, weapons, abilities] = mappingCache;
const getImg = (list, id, folder, isAbility = false) => {
- const fallback = isAbility ? "../assets/ability/ParameterIcon^q.png" : "/assets/weapons/NotFound^w.png";
- if (id === undefined || id === null) return fallback;
+ if (id === undefined || id === null) {
+ return isFinalFallback ? (isAbility ? "../assets/ability/ParameterIcon^q.png" : "/assets/weapons/NotFound^w.png") : "";
+ }
const item = list.find(i => String(i.id) === String(id));
- return (item && item.image) ? `../assets/${folder}/${item.image}` : fallback;
+ if (item && item.image) return `../assets/${folder}/${item.image}`;
+ return isFinalFallback ? (isAbility ? "../assets/ability/ParameterIcon^q.png" : "/assets/weapons/NotFound^w.png") : "";
};
const weaponImg = getImg(weapons, equipped.weapon, 'weapons');
@@ -131,7 +137,10 @@ window.loadHeader(function(headerContainer) {
const rankLevel = equipped.Rank !== undefined ? equipped.Rank : (finalData.Rank || "--");
const udemaeKey = equipped.Udemae !== undefined ? String(equipped.Udemae) : String(finalData.Udemae || "");
- const rankGrade = udemaeMap[udemaeKey] || (udemaeKey !== "undefined" && udemaeKey !== "" ? udemaeKey : "C-");
+ const rankGrade = udemaeMap[udemaeKey] || (udemaeKey !== "undefined" && udemaeKey !== "" ? udemaeKey : "--");
+
+ const renderImg = (src, className) => src ? `
` : '';
+ const renderSub = (src) => src ? `
` : '';
infoBox.innerHTML = `
@@ -149,30 +158,30 @@ window.loadHeader(function(headerContainer) {
${rankGrade}
-
+ ${renderImg(weaponImg, 'weapon')}
-

-

+ ${renderImg(headMain, 'main-ability')}
+ ${renderImg(headImg, 'gear-icon')}
-



+ ${renderSub(clothesSub1)}${renderSub(clothesSub2)}${renderSub(clothesSub3)}
-

-

+ ${renderImg(clothesMain, 'main-ability')}
+ ${renderImg(clothesImg, 'gear-icon')}
-



+ ${renderSub(headSub1)}${renderSub(headSub2)}${renderSub(headSub3)}
-

-

+ ${renderImg(shoesMain, 'main-ability')}
+ ${renderImg(shoesImg, 'gear-icon')}
-



+ ${renderSub(shoesSub1)}${renderSub(shoesSub2)}${renderSub(shoesSub3)}
@@ -185,18 +194,32 @@ window.loadHeader(function(headerContainer) {
const init = async () => {
const overlay = document.getElementById("loading-overlay");
+ let cacheFound = false;
+
+ const cached = sessionStorage.getItem('user_cache');
+ if (cached) {
+ try {
+ await renderData(JSON.parse(cached), false);
+ cacheFound = true;
+ } catch (e) {}
+ }
+
try {
const [profileRes, equipRes] = await Promise.all([
fetch("/api/v1/me", { credentials: 'include' }).then(res => res.ok ? res.json() : {}),
fetch("/api/v1/me/equipment", { credentials: 'include' }).then(res => res.ok ? res.json() : {})
]);
- await renderData(profileRes);
- await renderData(equipRes);
+
+ await renderData(profileRes, false);
+ await renderData(equipRes, false);
sessionStorage.setItem('user_cache', JSON.stringify(combinedData));
} catch (err) {
- const cached = sessionStorage.getItem('user_cache');
- if (cached) await renderData(JSON.parse(cached));
- else await renderData({ user_id: "Guest" });
+ //last resort
+ if (cacheFound) {
+ await renderData(sessionStorage.getItem('user_cache'), true);
+ } else {
+ await renderData({ user_id: "Guest" }, true);
+ }
} finally {
if (overlay) overlay.style.display = "none";
}
diff --git a/stages/stages.js b/stages/stages.js
index 426e6fd..8cc7d8c 100644
--- a/stages/stages.js
+++ b/stages/stages.js
@@ -3,19 +3,17 @@ let currentIndex = 0;
const ITEMS_PER_PAGE = 5;
let observer;
-window.loadHeader(function(headerContainer) {
+window.loadHeader(async function(headerContainer) {
const stageButton = headerContainer.querySelector('.menu-item.stage');
if (stageButton) {
stageButton.classList.add('active');
}
const logoutForm = document.getElementById("logout-form");
-
if (logoutForm) {
logoutForm.action = "/api/v1/spfn/logout";
const originInput = document.getElementById("logout_frontend_origin");
if (originInput) originInput.value = window.location.origin;
-
logoutForm.addEventListener('submit', () => {
sessionStorage.removeItem('user_cache');
});
@@ -47,7 +45,8 @@ window.loadHeader(function(headerContainer) {
}
};
- const renderData = (data) => {
+ const renderData = async (data) => {
+ if (!data) return;
if (typeof data === 'string') {
try { data = JSON.parse(data); } catch (e) { console.error(e); }
}
@@ -66,24 +65,38 @@ window.loadHeader(function(headerContainer) {
}
};
- const cached = sessionStorage.getItem('user_cache');
- if (cached) renderData(JSON.parse(cached));
+ const init = async () => {
+ const overlay = document.getElementById("loading-overlay");
+ let cacheReady = false;
- fetch("/api/v1/me", { credentials: 'include' })
- .then(res => res.ok ? res.json() : Promise.reject(res))
- .then(data => {
- sessionStorage.setItem('user_cache', JSON.stringify(data));
- renderData(data);
- })
- .catch(err => {
- if (!cached) {
+ const cached = sessionStorage.getItem('user_cache');
+ if (cached) {
+ try {
+ await renderData(cached);
+ cacheReady = true;
+ } catch (e) {}
+ }
+
+ try {
+ const [profileRes, rotationsData] = await Promise.all([
+ fetch("/api/v1/me", { credentials: 'include' }).then(res => res.ok ? res.json() : {}),
+ renderStages()
+ ]);
+
+ await renderData(profileRes);
+ sessionStorage.setItem('user_cache', JSON.stringify(profileRes));
+ } catch (err) {
+ if (!cacheReady) {
const nameEl = document.getElementById('mii-name');
if (nameEl) nameEl.textContent = "Guest";
}
console.error(err);
- });
+ } finally {
+ if (overlay) overlay.style.display = "none";
+ }
+ };
- renderStages();
+ init();
});
const API_URL = "/api/v1/boss";
@@ -144,13 +157,11 @@ async function fetchRotations() {
async function renderStages() {
const container = document.getElementById("stages-container");
- const loadingOverlay = document.getElementById("loading-overlay");
try {
allRotations = await fetchRotations();
if (!allRotations.length) {
container.innerHTML = `Something went wrong! Try reloading the page.
`;
- if (loadingOverlay) loadingOverlay.style.display = 'none';
return;
}
@@ -174,7 +185,6 @@ async function renderStages() {
} catch (err) {
console.error(err);
- if (loadingOverlay) loadingOverlay.style.display = 'none';
}
}
@@ -183,7 +193,7 @@ function loadMore(isInitial) {
const loadingOverlay = document.getElementById("loading-overlay");
const trigger = document.getElementById('scroll-trigger');
- if (loadingOverlay) {
+ if (!isInitial && loadingOverlay) {
loadingOverlay.style.display = 'flex';
if (typeof window.animateLoadingCanvas === 'function') {
window.animateLoadingCanvas();
@@ -254,7 +264,7 @@ function loadMore(isInitial) {
container.insertAdjacentHTML('beforeend', html);
currentIndex += ITEMS_PER_PAGE;
- if (loadingOverlay) loadingOverlay.style.display = 'none';
+ if (!isInitial && loadingOverlay) loadingOverlay.style.display = 'none';
if (trigger) trigger.style.display = 'block';
if (currentIndex >= allRotations.length) {