Skip to content

Commit 02b2112

Browse files
committed
Enhance error handling in user settings routes with user-facing error mapping
1 parent cd40580 commit 02b2112

File tree

2 files changed

+103
-38
lines changed

2 files changed

+103
-38
lines changed

apps/cyberstorm-remix/app/settings/user/Account/Account.tsx

Lines changed: 71 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,16 @@ import { NotLoggedIn } from "~/commonComponents/NotLoggedIn/NotLoggedIn";
1313
import { type OutletContextShape } from "~/root";
1414
import { useStrongForm } from "cyberstorm/utils/StrongForm/useStrongForm";
1515
import { useReducer } from "react";
16-
import { userDelete } from "@thunderstore/thunderstore-api";
16+
import {
17+
userDelete,
18+
UserFacingError,
19+
formatUserFacingError,
20+
} from "@thunderstore/thunderstore-api";
21+
import {
22+
NimbusErrorBoundary,
23+
NimbusErrorBoundaryFallback,
24+
} from "cyberstorm/utils/errors/NimbusErrorBoundary";
25+
import type { NimbusErrorBoundaryFallbackProps } from "cyberstorm/utils/errors/NimbusErrorBoundary";
1726

1827
export default function Account() {
1928
const outletContext = useOutletContext() as OutletContextShape;
@@ -22,44 +31,70 @@ export default function Account() {
2231
return <NotLoggedIn />;
2332

2433
return (
25-
<div className="settings-items user-account">
26-
<div className="settings-items__item">
27-
<div className="settings-items__meta">
28-
<p className="settings-items__title">Delete Account</p>
29-
<p className="settings-items__description">
30-
Delete your Thunderstore account permanently
31-
</p>
32-
</div>
33-
<div className="settings-items__content">
34-
<div className="user-account__delete-user-form">
35-
<NewAlert csVariant="warning">
36-
You are about to delete your account. Once deleted, it will be
37-
gone forever. Please be certain.
38-
</NewAlert>
39-
<p className="user-account__instructions">
40-
The mods that have been uploaded on this account will remain
41-
public on the site even after deletion. If you need them to be
42-
taken down as well, please contact an administrator on the
43-
community Discord server.
44-
<br />
45-
<span>
46-
As a precaution, to delete your account, please input{" "}
47-
<span className="user-account__username">
48-
{outletContext.currentUser.username}
49-
</span>{" "}
50-
into the field below.
51-
</span>
34+
<NimbusErrorBoundary
35+
fallback={AccountSettingsFallback}
36+
onRetry={({ reset }) => reset()}
37+
>
38+
<div className="settings-items user-account">
39+
<div className="settings-items__item">
40+
<div className="settings-items__meta">
41+
<p className="settings-items__title">Delete Account</p>
42+
<p className="settings-items__description">
43+
Delete your Thunderstore account permanently
5244
</p>
53-
<div className="user-account__actions">
54-
<DeleteAccountForm
55-
currentUser={outletContext.currentUser}
56-
requestConfig={outletContext.requestConfig}
57-
/>
45+
</div>
46+
<div className="settings-items__content">
47+
<div className="user-account__delete-user-form">
48+
<NewAlert csVariant="warning">
49+
You are about to delete your account. Once deleted, it will be
50+
gone forever. Please be certain.
51+
</NewAlert>
52+
<p className="user-account__instructions">
53+
The mods that have been uploaded on this account will remain
54+
public on the site even after deletion. If you need them to be
55+
taken down as well, please contact an administrator on the
56+
community Discord server.
57+
<br />
58+
<span>
59+
As a precaution, to delete your account, please input{" "}
60+
<span className="user-account__username">
61+
{outletContext.currentUser.username}
62+
</span>{" "}
63+
into the field below.
64+
</span>
65+
</p>
66+
<div className="user-account__actions">
67+
<DeleteAccountForm
68+
currentUser={outletContext.currentUser}
69+
requestConfig={outletContext.requestConfig}
70+
/>
71+
</div>
5872
</div>
5973
</div>
6074
</div>
6175
</div>
62-
</div>
76+
</NimbusErrorBoundary>
77+
);
78+
}
79+
80+
/**
81+
* Displays fallback messaging when the account settings view fails to render.
82+
*/
83+
function AccountSettingsFallback(props: NimbusErrorBoundaryFallbackProps) {
84+
const {
85+
title = "Account settings failed to load",
86+
description = "Reload the account tab or return to settings.",
87+
retryLabel = "Reload",
88+
...rest
89+
} = props;
90+
91+
return (
92+
<NimbusErrorBoundaryFallback
93+
{...rest}
94+
title={title}
95+
description={description}
96+
retryLabel={retryLabel}
97+
/>
6398
);
6499
}
65100

@@ -114,7 +149,7 @@ function DeleteAccountForm(props: {
114149
UserAccountDeleteRequestData,
115150
Error,
116151
SubmitorOutput,
117-
Error,
152+
UserFacingError,
118153
InputErrors
119154
>({
120155
inputs: formInputs,
@@ -129,7 +164,7 @@ function DeleteAccountForm(props: {
129164
onSubmitError: (error) => {
130165
toast.addToast({
131166
csVariant: "danger",
132-
children: `Error occurred: ${error.message || "Unknown error"}`,
167+
children: formatUserFacingError(error),
133168
duration: 8000,
134169
});
135170
},

apps/cyberstorm-remix/app/settings/user/Settings.tsx

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ import { Outlet, useLocation, useOutletContext } from "react-router";
33
import { NewLink, Tabs } from "@thunderstore/cyberstorm";
44
import { PageHeader } from "~/commonComponents/PageHeader/PageHeader";
55
import { type OutletContextShape } from "../../root";
6+
import "./Settings.css";
7+
import {
8+
NimbusErrorBoundary,
9+
NimbusErrorBoundaryFallback,
10+
} from "cyberstorm/utils/errors/NimbusErrorBoundary";
11+
import type { NimbusErrorBoundaryFallbackProps } from "cyberstorm/utils/errors/NimbusErrorBoundary";
612

713
export default function UserSettings() {
814
const context = useOutletContext<OutletContextShape>();
@@ -14,7 +20,10 @@ export default function UserSettings() {
1420
}
1521

1622
return (
17-
<>
23+
<NimbusErrorBoundary
24+
fallback={UserSettingsFallback}
25+
onRetry={({ reset }) => reset()}
26+
>
1827
<PageHeader headingLevel="1" headingSize="2">
1928
Settings
2029
</PageHeader>
@@ -45,6 +54,27 @@ export default function UserSettings() {
4554
<Outlet context={context} />
4655
</section>
4756
</div>
48-
</>
57+
</NimbusErrorBoundary>
58+
);
59+
}
60+
61+
/**
62+
* Provides fallback messaging when the user settings shell fails to render.
63+
*/
64+
function UserSettingsFallback(props: NimbusErrorBoundaryFallbackProps) {
65+
const {
66+
title = "Settings failed to load",
67+
description = "Reload the settings page or return to the dashboard.",
68+
retryLabel = "Reload",
69+
...rest
70+
} = props;
71+
72+
return (
73+
<NimbusErrorBoundaryFallback
74+
{...rest}
75+
title={title}
76+
description={description}
77+
retryLabel={retryLabel}
78+
/>
4979
);
5080
}

0 commit comments

Comments
 (0)