import config from "@/utils/config.json";
import * as apiTypes from "@/utils/api/types";
/**
* Adds a row to the user statistics card on the profile page allowing the user to quickly view & copy another user's ID.
* @param userId The ID of the user.
*/
export async function displayId(userId: number) {
const statsCard = document.getElementById('user-stats-card');
if (!statsCard) return; // ? Incase the user is blocked, which means the stats card won't be present
const row = document.createElement('div');
row.classList.add('mb-1');
row.innerHTML = `
Player ID
${userId}
`;
const copyBtn = row.getElementsByTagName('a')[0];
copyBtn.addEventListener('click', () => {
navigator.clipboard.writeText(userId as unknown as string)
.then(() => {
const icon: HTMLElement = copyBtn.children[0] as HTMLElement;
copyBtn.classList.add('text-success');
icon.setAttribute('class', 'fa-duotone fa-circle-check');
icon.style.marginLeft = '3px';
setTimeout(() => {
copyBtn.classList.remove('text-success');
icon.setAttribute('class', 'fad fa-copy');
icon.style.marginLeft = '5px';
}, 1500);
})
.catch(() => {
alert('Failure to copy user ID to clipboard.');
});
});
statsCard.children[0].insertBefore(row, statsCard.querySelector('.mb-1:has(.fa-calendar)')!);
};
/**
* Adds a button next to the "Avatar" card heading, which, on click, adds up all the items the user who owns this profile is wearing.
* @param userId The ID of the user.
*/
export async function outfitCost(userId: number) {
const calculateBtn = document.createElement('small');
calculateBtn.classList.add('fw-normal');
calculateBtn.style.letterSpacing = '0px';
const calculate = async function() {
const outfit = {
cost: 0,
collectibles: 0,
offsale: 0,
timed: 0
};
const avatar: apiTypes.avatarApiSchema | "disabled" = await pullKVCache(
'avatars',
userId.toString(),
async () => {
if (!config.api.enabled) return "disabled";
return (await (await fetch(config.api.urls.public + "users/" + userId + "/avatar")).json());
},
30000, // 30 seconds
false
);
if (avatar == "disabled") {
calculateBtn.innerHTML = 'Outfit cost unavailable, please try again later';
throw new Error('[Poly+] API is disabled, cancelling avatar cost loading..');
};
if (avatar.isDefault) {
calculateBtn.innerHTML = 'Default avatar';
console.warn('[Poly+] User has default avatar, cancelling avatar cost loading..');
return;
};
for (const asset of avatar.assets.filter((asset) => asset.type != "profileTheme")) {
// ? API won't be disabled at this step, since there was already an API check previously
const item: apiTypes.itemApiSchema = await pullKVCache(
'items',
asset.id.toString(),
async () => {
return (await (await fetch(config.api.urls.public + "store/" + asset.id)).json());
},
600000,
false
);
if (item.isLimited) {
outfit.collectibles++;
outfit.cost += item.averagePrice!;
} else if (!item.price) {
outfit.offsale++;
} else if (item.onSaleUntil != null) {
outfit.timed++;
} else {
outfit.cost += item.price!;
};
};
console.log('[Poly+] Outfit breakdown: ', outfit);
calculateBtn.innerHTML = `${ outfit.cost.toLocaleString() }`;
};
if (config.api.enabled) {
calculateBtn.innerHTML = '$ calculate avatar cost';
calculateBtn.children[0].addEventListener('click', calculate);
} else {
calculateBtn.innerHTML = 'Outfit cost unavailable, please try again later';
console.error("[Poly+] API is disabled, outfit cost calculation is unavailable.")
}
document.querySelector('.section-title:first-child')!.appendChild(calculateBtn);
};