Files
OpenFrontIO/src/client/Cosmetics.ts
T
evanpelle 00668dd924 Remove role based perms, fetch cosmetics.json from api (#1640)
## Description:

* Fetch cosmetics.json from api
* Remove all role based perms, we are only using flares now
* Created Priviledge refresher which periodically polls /cosmetics.json
endpoint.

## Please complete the following:

- [x] I have added screenshots for all UI updates
- [x] I process any text displayed to the user through translateText()
and I've added it to the en.json file
- [x] I have added relevant tests to the test directory
- [x] I confirm I have thoroughly tested these changes and take full
responsibility for any bugs introduced
- [x] I have read and accepted the CLA agreement (only required once).

## Please put your Discord username so you can be contacted if a bug or
regression is found:

evan
2025-08-04 16:48:41 -07:00

86 lines
2.4 KiB
TypeScript

import { UserMeResponse } from "../core/ApiSchemas";
import { Cosmetics, CosmeticsSchema, Pattern } from "../core/CosmeticSchemas";
import { getApiBase, getAuthHeader } from "./jwt";
export async function patterns(
userMe: UserMeResponse | null,
): Promise<Pattern[]> {
const cosmetics = await getCosmetics();
if (cosmetics === undefined) {
return [];
}
const patterns: Pattern[] = [];
const playerFlares = new Set(userMe?.player.flares);
for (const name in cosmetics.patterns) {
const patternData = cosmetics.patterns[name];
const hasAccess = playerFlares.has(`pattern:${name}`);
if (hasAccess) {
// Remove product info because player already has access.
patternData.product = null;
patterns.push(patternData);
} else if (patternData.product !== null) {
// Player doesn't have access, but product is available for purchase.
patterns.push(patternData);
}
// If player doesn't have access and product is null, don't show it.
}
return patterns;
}
export async function handlePurchase(priceId: string) {
const response = await fetch(
`${getApiBase()}/stripe/create-checkout-session`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
authorization: getAuthHeader(),
},
body: JSON.stringify({
priceId: priceId,
successUrl: `${window.location.href}purchase-success`,
cancelUrl: `${window.location.href}purchase-cancel`,
}),
},
);
if (!response.ok) {
console.error(
`Error purchasing pattern:${response.status} ${response.statusText}`,
);
if (response.status === 401) {
alert("You are not logged in. Please log in to purchase a pattern.");
} else {
alert("Something went wrong. Please try again later.");
}
return;
}
const { url } = await response.json();
// Redirect to Stripe checkout
window.location.href = url;
}
async function getCosmetics(): Promise<Cosmetics | undefined> {
try {
const response = await fetch(`${getApiBase()}/cosmetics.json`);
if (!response.ok) {
console.error(`HTTP error! status: ${response.status}`);
return;
}
const result = CosmeticsSchema.safeParse(await response.json());
if (!result.success) {
console.error(`Invalid cosmetics: ${result.error.message}`);
return;
}
return result.data;
} catch (error) {
console.error("Error getting cosmetics:", error);
}
}