Skip to content

Commit 9f14641

Browse files
committed
Enhance error handling in user settings routes with user-facing error mapping
1 parent de2572f commit 9f14641

File tree

2 files changed

+102
-38
lines changed

2 files changed

+102
-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
@@ -1,12 +1,17 @@
11
import { faTrashCan } from "@fortawesome/pro-solid-svg-icons";
22
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
33
import { useStrongForm } from "cyberstorm/utils/StrongForm/useStrongForm";
4+
import {
5+
NimbusErrorBoundary,
6+
NimbusErrorBoundaryFallback,
7+
type NimbusErrorBoundaryFallbackProps,
8+
} from "cyberstorm/utils/errors/NimbusErrorBoundary";
49
import { useReducer } from "react";
510
import { useNavigate, useOutletContext, useRevalidator } from "react-router";
611
import { useHydrated } from "remix-utils/use-hydrated";
712
import { Loading } from "~/commonComponents/Loading/Loading";
813
import { NotLoggedIn } from "~/commonComponents/NotLoggedIn/NotLoggedIn";
9-
import { type OutletContextShape } from "~/root";
14+
import type { OutletContextShape } from "~/root";
1015

1116
import {
1217
NewAlert,
@@ -15,8 +20,12 @@ import {
1520
NewTextInput,
1621
useToast,
1722
} from "@thunderstore/cyberstorm";
18-
import { UserFacingError, userDelete } from "@thunderstore/thunderstore-api";
1923

24+
import {
25+
UserFacingError,
26+
formatUserFacingError,
27+
userDelete,
28+
} from "../../../../../../packages/thunderstore-api/src";
2029
import "./Account.css";
2130

2231
export default function Account() {
@@ -32,44 +41,70 @@ export default function Account() {
3241
}
3342

3443
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>
44+
<NimbusErrorBoundary
45+
fallback={AccountSettingsFallback}
46+
onRetry={({ reset }) => reset()}
47+
>
48+
<div className="settings-items user-account">
49+
<div className="settings-items__item">
50+
<div className="settings-items__meta">
51+
<p className="settings-items__title">Delete Account</p>
52+
<p className="settings-items__description">
53+
Delete your Thunderstore account permanently
6254
</p>
63-
<div className="user-account__actions">
64-
<DeleteAccountForm
65-
currentUser={outletContext.currentUser}
66-
requestConfig={outletContext.requestConfig}
67-
/>
55+
</div>
56+
<div className="settings-items__content">
57+
<div className="user-account__delete-user-form">
58+
<NewAlert csVariant="warning">
59+
You are about to delete your account. Once deleted, it will be
60+
gone forever. Please be certain.
61+
</NewAlert>
62+
<p className="user-account__instructions">
63+
The mods that have been uploaded on this account will remain
64+
public on the site even after deletion. If you need them to be
65+
taken down as well, please contact an administrator on the
66+
community Discord server.
67+
<br />
68+
<span>
69+
As a precaution, to delete your account, please input{" "}
70+
<span className="user-account__username">
71+
{outletContext.currentUser.username}
72+
</span>{" "}
73+
into the field below.
74+
</span>
75+
</p>
76+
<div className="user-account__actions">
77+
<DeleteAccountForm
78+
currentUser={outletContext.currentUser}
79+
requestConfig={outletContext.requestConfig}
80+
/>
81+
</div>
6882
</div>
6983
</div>
7084
</div>
7185
</div>
72-
</div>
86+
</NimbusErrorBoundary>
87+
);
88+
}
89+
90+
/**
91+
* Displays fallback messaging when the account settings view fails to render.
92+
*/
93+
function AccountSettingsFallback(props: NimbusErrorBoundaryFallbackProps) {
94+
const {
95+
title = "Account settings failed to load",
96+
description = "Reload the account tab or return to settings.",
97+
retryLabel = "Reload",
98+
...rest
99+
} = props;
100+
101+
return (
102+
<NimbusErrorBoundaryFallback
103+
{...rest}
104+
title={title}
105+
description={description}
106+
retryLabel={retryLabel}
107+
/>
73108
);
74109
}
75110

@@ -143,7 +178,7 @@ function DeleteAccountForm(props: {
143178
onSubmitError: (error) => {
144179
toast.addToast({
145180
csVariant: "danger",
146-
children: `Error occurred: ${error.message || "Unknown error"}`,
181+
children: formatUserFacingError(error),
147182
duration: 8000,
148183
});
149184
},

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)