Skip to content

Commit cca84a1

Browse files
committed
Enhance error handling in user settings routes with user-facing error mapping
1 parent 5ac0d36 commit cca84a1

File tree

2 files changed

+110
-37
lines changed

2 files changed

+110
-37
lines changed

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

Lines changed: 79 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,24 @@ import {
1818
import { userDelete } from "@thunderstore/thunderstore-api";
1919

2020
import "./Account.css";
21+
import { faTrashCan } from "@fortawesome/pro-solid-svg-icons";
22+
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
23+
import { NotLoggedIn } from "~/commonComponents/NotLoggedIn/NotLoggedIn";
24+
import { Loading } from "~/commonComponents/Loading/Loading";
25+
import { type OutletContextShape } from "~/root";
26+
import { useStrongForm } from "cyberstorm/utils/StrongForm/useStrongForm";
27+
import { useReducer } from "react";
28+
import { useHydrated } from "remix-utils/use-hydrated";
29+
import {
30+
userDelete,
31+
UserFacingError,
32+
formatUserFacingError,
33+
} from "@thunderstore/thunderstore-api";
34+
import {
35+
NimbusErrorBoundary,
36+
NimbusErrorBoundaryFallback,
37+
} from "cyberstorm/utils/errors/NimbusErrorBoundary";
38+
import type { NimbusErrorBoundaryFallbackProps } from "cyberstorm/utils/errors/NimbusErrorBoundary";
2139

2240
export default function Account() {
2341
const outletContext = useOutletContext() as OutletContextShape;
@@ -32,44 +50,70 @@ export default function Account() {
3250
}
3351

3452
return (
35-
<div className="settings-items user-account">
36-
<div className="settings-items__item">
37-
<div className="settings-items__meta">
38-
<p className="settings-items__title">Delete Account</p>
39-
<p className="settings-items__description">
40-
Delete your Thunderstore account permanently
41-
</p>
42-
</div>
43-
<div className="settings-items__content">
44-
<div className="user-account__delete-user-form">
45-
<NewAlert csVariant="warning">
46-
You are about to delete your account. Once deleted, it will be
47-
gone forever. Please be certain.
48-
</NewAlert>
49-
<p className="user-account__instructions">
50-
The mods that have been uploaded on this account will remain
51-
public on the site even after deletion. If you need them to be
52-
taken down as well, please contact an administrator on the
53-
community Discord server.
54-
<br />
55-
<span>
56-
As a precaution, to delete your account, please input{" "}
57-
<span className="user-account__username">
58-
{outletContext.currentUser.username}
59-
</span>{" "}
60-
into the field below.
61-
</span>
53+
<NimbusErrorBoundary
54+
fallback={AccountSettingsFallback}
55+
onRetry={({ reset }) => reset()}
56+
>
57+
<div className="settings-items user-account">
58+
<div className="settings-items__item">
59+
<div className="settings-items__meta">
60+
<p className="settings-items__title">Delete Account</p>
61+
<p className="settings-items__description">
62+
Delete your Thunderstore account permanently
6263
</p>
63-
<div className="user-account__actions">
64-
<DeleteAccountForm
65-
currentUser={outletContext.currentUser}
66-
requestConfig={outletContext.requestConfig}
67-
/>
64+
</div>
65+
<div className="settings-items__content">
66+
<div className="user-account__delete-user-form">
67+
<NewAlert csVariant="warning">
68+
You are about to delete your account. Once deleted, it will be
69+
gone forever. Please be certain.
70+
</NewAlert>
71+
<p className="user-account__instructions">
72+
The mods that have been uploaded on this account will remain
73+
public on the site even after deletion. If you need them to be
74+
taken down as well, please contact an administrator on the
75+
community Discord server.
76+
<br />
77+
<span>
78+
As a precaution, to delete your account, please input{" "}
79+
<span className="user-account__username">
80+
{outletContext.currentUser.username}
81+
</span>{" "}
82+
into the field below.
83+
</span>
84+
</p>
85+
<div className="user-account__actions">
86+
<DeleteAccountForm
87+
currentUser={outletContext.currentUser}
88+
requestConfig={outletContext.requestConfig}
89+
/>
90+
</div>
6891
</div>
6992
</div>
7093
</div>
7194
</div>
72-
</div>
95+
</NimbusErrorBoundary>
96+
);
97+
}
98+
99+
/**
100+
* Displays fallback messaging when the account settings view fails to render.
101+
*/
102+
function AccountSettingsFallback(props: NimbusErrorBoundaryFallbackProps) {
103+
const {
104+
title = "Account settings failed to load",
105+
description = "Reload the account tab or return to settings.",
106+
retryLabel = "Reload",
107+
...rest
108+
} = props;
109+
110+
return (
111+
<NimbusErrorBoundaryFallback
112+
{...rest}
113+
title={title}
114+
description={description}
115+
retryLabel={retryLabel}
116+
/>
73117
);
74118
}
75119

@@ -126,7 +170,7 @@ function DeleteAccountForm(props: {
126170
UserAccountDeleteRequestData,
127171
Error,
128172
SubmitorOutput,
129-
Error,
173+
UserFacingError,
130174
InputErrors
131175
>({
132176
inputs: formInputs,
@@ -143,7 +187,7 @@ function DeleteAccountForm(props: {
143187
onSubmitError: (error) => {
144188
toast.addToast({
145189
csVariant: "danger",
146-
children: `Error occurred: ${error.message || "Unknown error"}`,
190+
children: formatUserFacingError(error),
147191
duration: 8000,
148192
});
149193
},

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

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@ import { NewLink, Tabs } from "@thunderstore/cyberstorm";
55

66
import { type OutletContextShape } from "../../root";
77
import "./Settings.css";
8+
import {
9+
NimbusErrorBoundary,
10+
NimbusErrorBoundaryFallback,
11+
} from "cyberstorm/utils/errors/NimbusErrorBoundary";
12+
import type { NimbusErrorBoundaryFallbackProps } from "cyberstorm/utils/errors/NimbusErrorBoundary";
813

914
export default function UserSettings() {
1015
const context = useOutletContext<OutletContextShape>();
@@ -16,7 +21,10 @@ export default function UserSettings() {
1621
}
1722

1823
return (
19-
<>
24+
<NimbusErrorBoundary
25+
fallback={UserSettingsFallback}
26+
onRetry={({ reset }) => reset()}
27+
>
2028
<PageHeader headingLevel="1" headingSize="2">
2129
Settings
2230
</PageHeader>
@@ -47,6 +55,27 @@ export default function UserSettings() {
4755
<Outlet context={context} />
4856
</section>
4957
</div>
50-
</>
58+
</NimbusErrorBoundary>
59+
);
60+
}
61+
62+
/**
63+
* Provides fallback messaging when the user settings shell fails to render.
64+
*/
65+
function UserSettingsFallback(props: NimbusErrorBoundaryFallbackProps) {
66+
const {
67+
title = "Settings failed to load",
68+
description = "Reload the settings page or return to the dashboard.",
69+
retryLabel = "Reload",
70+
...rest
71+
} = props;
72+
73+
return (
74+
<NimbusErrorBoundaryFallback
75+
{...rest}
76+
title={title}
77+
description={description}
78+
retryLabel={retryLabel}
79+
/>
5180
);
5281
}

0 commit comments

Comments
 (0)