fix: gold icon, story banner crop, crafted items persist, community blurb, validation error filtering
Security Scan and Upload / Security & DefectDojo Upload (pull_request) Successful in 1m4s
CI / Lint, Build & Test (pull_request) Failing after 1m11s

This commit is contained in:
2026-04-06 13:57:32 -07:00
committed by Naomi Carrigan
parent 99ca3083a1
commit c494cf9a26
6 changed files with 57 additions and 9 deletions
+24
View File
@@ -38,6 +38,26 @@ import type {
const baseUrl = "/api";
/**
* Represents a 4xx API error so callers can distinguish expected server
* rejections from unexpected failures. ValidationErrors are downgraded to
* console.warn and are not forwarded to the error-email pipeline.
*/
class ValidationError extends Error {
public readonly statusCode: number;
/**
* Creates a new ValidationError.
* @param message - The error message from the server response.
* @param statusCode - The HTTP status code (4xx) returned by the server.
*/
public constructor(message: string, statusCode: number) {
super(message);
this.name = "ValidationError";
this.statusCode = statusCode;
}
}
const getToken = (): string | null => {
return globalThis.localStorage.getItem("elysium_token");
};
@@ -72,6 +92,9 @@ const fetchJson = async <T>(
= typeof errorBody.error === "string"
? errorBody.error
: "Unknown error";
if (response.status >= 400 && response.status < 500) {
throw new ValidationError(message, response.status);
}
throw new Error(message);
}
@@ -326,6 +349,7 @@ const updateProfile = async(
};
export {
ValidationError,
achieveApotheosis,
buyEchoUpgrade,
buyPrestigeUpgrade,
@@ -277,6 +277,15 @@ const howToPlay = [
+ " when you first enable them.",
title: "🔔 Sounds & Notifications",
},
{
body:
"Have a question, found a bug, or want to suggest a feature? Join the"
+ " NHCarrigan community Discord at https://chat.nhcarrigan.com or open"
+ " a support ticket at https://support.nhcarrigan.com. You can also"
+ " report issues directly on the project repository. We'd love to hear"
+ " from you!",
title: "💬 Community & Support",
},
];
const formatDate = (dateString: string): string => {
+1 -1
View File
@@ -162,7 +162,7 @@ const ResourceBar = ({
title="Click to see all resources"
type="button"
>
<span className="resource-icon">{"🪙"}</span>
<span className="resource-icon">{"💰"}</span>
<span className="resource-value">{formatNumber(gold)}</span>
<span className="resource-label">{"Gold"}</span>
{goldFull
+1
View File
@@ -4586,6 +4586,7 @@ body::before {
height: 220px;
margin-bottom: 1rem;
object-fit: cover;
object-position: top;
width: 100%;
}
+11 -3
View File
@@ -5,14 +5,22 @@
* @author Naomi Carrigan
*/
/* eslint-disable no-console -- Errors are forwarded to backend via the overridden console.error */
import { ValidationError } from "../api/client.js";
/**
* Logs an error to the backend telemetry service.
* Accepts the same arguments as console.error — conventionally a context string
* followed by the error value.
* @param logArguments - The values to log, forwarded directly to console.error.
* ValidationErrors (4xx API rejections) are downgraded to console.warn so they
* are not forwarded to the error-email pipeline — they are expected server responses.
* @param logArguments - The values to log, forwarded directly to console.error or console.warn.
*/
const logError = (...logArguments: Array<unknown>): void => {
const isValidation = logArguments.some((argument) => {
return argument instanceof ValidationError;
});
if (isValidation) {
console.warn(...logArguments);
return;
}
console.error(...logArguments);
};