generated from nhcarrigan/template
fix: gold icon, story banner crop, crafted items persist, community blurb, validation error filtering
This commit is contained in:
@@ -622,11 +622,17 @@ const validateAndSanitize = (
|
|||||||
= Math.min(material.quantity, previousQuantity);
|
= Math.min(material.quantity, previousQuantity);
|
||||||
return { ...material, quantity: cappedQuantity };
|
return { ...material, quantity: cappedQuantity };
|
||||||
});
|
});
|
||||||
const craftedRecipeIds = incoming.exploration.craftedRecipeIds.filter(
|
|
||||||
(recipeId) => {
|
/*
|
||||||
return previousExploration.craftedRecipeIds.includes(recipeId);
|
* Merge crafted recipe IDs from both states so the list can only ever grow.
|
||||||
},
|
* A stale auto-save arriving after a craft must not silently un-craft items.
|
||||||
);
|
*/
|
||||||
|
const craftedRecipeIds = [
|
||||||
|
...new Set([
|
||||||
|
...previousExploration.craftedRecipeIds,
|
||||||
|
...incoming.exploration.craftedRecipeIds,
|
||||||
|
]),
|
||||||
|
];
|
||||||
explorationSpread = {
|
explorationSpread = {
|
||||||
exploration: {
|
exploration: {
|
||||||
...incoming.exploration,
|
...incoming.exploration,
|
||||||
|
|||||||
@@ -38,6 +38,26 @@ import type {
|
|||||||
|
|
||||||
const baseUrl = "/api";
|
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 => {
|
const getToken = (): string | null => {
|
||||||
return globalThis.localStorage.getItem("elysium_token");
|
return globalThis.localStorage.getItem("elysium_token");
|
||||||
};
|
};
|
||||||
@@ -72,6 +92,9 @@ const fetchJson = async <T>(
|
|||||||
= typeof errorBody.error === "string"
|
= typeof errorBody.error === "string"
|
||||||
? errorBody.error
|
? errorBody.error
|
||||||
: "Unknown error";
|
: "Unknown error";
|
||||||
|
if (response.status >= 400 && response.status < 500) {
|
||||||
|
throw new ValidationError(message, response.status);
|
||||||
|
}
|
||||||
throw new Error(message);
|
throw new Error(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,6 +349,7 @@ const updateProfile = async(
|
|||||||
};
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
ValidationError,
|
||||||
achieveApotheosis,
|
achieveApotheosis,
|
||||||
buyEchoUpgrade,
|
buyEchoUpgrade,
|
||||||
buyPrestigeUpgrade,
|
buyPrestigeUpgrade,
|
||||||
|
|||||||
@@ -277,6 +277,15 @@ const howToPlay = [
|
|||||||
+ " when you first enable them.",
|
+ " when you first enable them.",
|
||||||
title: "🔔 Sounds & Notifications",
|
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 => {
|
const formatDate = (dateString: string): string => {
|
||||||
|
|||||||
@@ -162,7 +162,7 @@ const ResourceBar = ({
|
|||||||
title="Click to see all resources"
|
title="Click to see all resources"
|
||||||
type="button"
|
type="button"
|
||||||
>
|
>
|
||||||
<span className="resource-icon">{"🪙"}</span>
|
<span className="resource-icon">{"💰"}</span>
|
||||||
<span className="resource-value">{formatNumber(gold)}</span>
|
<span className="resource-value">{formatNumber(gold)}</span>
|
||||||
<span className="resource-label">{"Gold"}</span>
|
<span className="resource-label">{"Gold"}</span>
|
||||||
{goldFull
|
{goldFull
|
||||||
|
|||||||
@@ -4586,6 +4586,7 @@ body::before {
|
|||||||
height: 220px;
|
height: 220px;
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
|
object-position: top;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,14 +5,22 @@
|
|||||||
* @author Naomi Carrigan
|
* @author Naomi Carrigan
|
||||||
*/
|
*/
|
||||||
/* eslint-disable no-console -- Errors are forwarded to backend via the overridden console.error */
|
/* 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.
|
* Logs an error to the backend telemetry service.
|
||||||
* Accepts the same arguments as console.error — conventionally a context string
|
* ValidationErrors (4xx API rejections) are downgraded to console.warn so they
|
||||||
* followed by the error value.
|
* are not forwarded to the error-email pipeline — they are expected server responses.
|
||||||
* @param logArguments - The values to log, forwarded directly to console.error.
|
* @param logArguments - The values to log, forwarded directly to console.error or console.warn.
|
||||||
*/
|
*/
|
||||||
const logError = (...logArguments: Array<unknown>): void => {
|
const logError = (...logArguments: Array<unknown>): void => {
|
||||||
|
const isValidation = logArguments.some((argument) => {
|
||||||
|
return argument instanceof ValidationError;
|
||||||
|
});
|
||||||
|
if (isValidation) {
|
||||||
|
console.warn(...logArguments);
|
||||||
|
return;
|
||||||
|
}
|
||||||
console.error(...logArguments);
|
console.error(...logArguments);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user