Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 71 additions & 36 deletions apps/cyberstorm-remix/app/settings/user/Account/Account.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
import { faTrashCan } from "@fortawesome/pro-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useStrongForm } from "cyberstorm/utils/StrongForm/useStrongForm";
import {
NimbusErrorBoundary,
NimbusErrorBoundaryFallback,
type NimbusErrorBoundaryFallbackProps,
} from "cyberstorm/utils/errors/NimbusErrorBoundary";
import { useReducer } from "react";
import { useNavigate, useOutletContext, useRevalidator } from "react-router";
import { useHydrated } from "remix-utils/use-hydrated";
import { Loading } from "~/commonComponents/Loading/Loading";
import { NotLoggedIn } from "~/commonComponents/NotLoggedIn/NotLoggedIn";
import { type OutletContextShape } from "~/root";
import type { OutletContextShape } from "~/root";

import {
NewAlert,
Expand All @@ -15,8 +20,12 @@ import {
NewTextInput,
useToast,
} from "@thunderstore/cyberstorm";
import { UserFacingError, userDelete } from "@thunderstore/thunderstore-api";

import {
UserFacingError,
formatUserFacingError,
userDelete,
} from "../../../../../../packages/thunderstore-api/src";
import "./Account.css";

export default function Account() {
Expand All @@ -32,44 +41,70 @@ export default function Account() {
}

return (
<div className="settings-items user-account">
<div className="settings-items__item">
<div className="settings-items__meta">
<p className="settings-items__title">Delete Account</p>
<p className="settings-items__description">
Delete your Thunderstore account permanently
</p>
</div>
<div className="settings-items__content">
<div className="user-account__delete-user-form">
<NewAlert csVariant="warning">
You are about to delete your account. Once deleted, it will be
gone forever. Please be certain.
</NewAlert>
<p className="user-account__instructions">
The mods that have been uploaded on this account will remain
public on the site even after deletion. If you need them to be
taken down as well, please contact an administrator on the
community Discord server.
<br />
<span>
As a precaution, to delete your account, please input{" "}
<span className="user-account__username">
{outletContext.currentUser.username}
</span>{" "}
into the field below.
</span>
<NimbusErrorBoundary
fallback={AccountSettingsFallback}
onRetry={({ reset }) => reset()}
>
<div className="settings-items user-account">
<div className="settings-items__item">
<div className="settings-items__meta">
<p className="settings-items__title">Delete Account</p>
<p className="settings-items__description">
Delete your Thunderstore account permanently
</p>
<div className="user-account__actions">
<DeleteAccountForm
currentUser={outletContext.currentUser}
requestConfig={outletContext.requestConfig}
/>
</div>
<div className="settings-items__content">
<div className="user-account__delete-user-form">
<NewAlert csVariant="warning">
You are about to delete your account. Once deleted, it will be
gone forever. Please be certain.
</NewAlert>
<p className="user-account__instructions">
The mods that have been uploaded on this account will remain
public on the site even after deletion. If you need them to be
taken down as well, please contact an administrator on the
community Discord server.
<br />
<span>
As a precaution, to delete your account, please input{" "}
<span className="user-account__username">
{outletContext.currentUser.username}
</span>{" "}
into the field below.
</span>
</p>
<div className="user-account__actions">
<DeleteAccountForm
currentUser={outletContext.currentUser}
requestConfig={outletContext.requestConfig}
/>
</div>
</div>
</div>
</div>
</div>
</div>
</NimbusErrorBoundary>
);
}

/**
* Displays fallback messaging when the account settings view fails to render.
*/
function AccountSettingsFallback(props: NimbusErrorBoundaryFallbackProps) {
const {
title = "Account settings failed to load",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this page even fail to load when it has no loader? I guess the error boundary can catch errors from the actions, but for those errors this error message is a bit off?

description = "Reload the account tab or return to settings.",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the "return to settings" part helpful to the user if the error view doesn't provide a way to do so? If my assumption that the error message is shown only as a reaction to error when submitting an action, would something like "Reload the page to try again" be more suitable?

retryLabel = "Reload",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick: Haven't checked the rest of the PRs but I assume "Reload" will be quite common label, so it should probably be the default value instead of the current "Retry"? Would save us some boilerplate.

...rest
} = props;

return (
<NimbusErrorBoundaryFallback
{...rest}
title={title}
description={description}
retryLabel={retryLabel}
/>
);
}

Expand Down Expand Up @@ -143,7 +178,7 @@ function DeleteAccountForm(props: {
onSubmitError: (error) => {
toast.addToast({
csVariant: "danger",
children: `Error occurred: ${error.message || "Unknown error"}`,
children: formatUserFacingError(error),
duration: 8000,
});
},
Expand Down
33 changes: 31 additions & 2 deletions apps/cyberstorm-remix/app/settings/user/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@ import { NewLink, Tabs } from "@thunderstore/cyberstorm";

import { type OutletContextShape } from "../../root";
import "./Settings.css";
import {
NimbusErrorBoundary,
NimbusErrorBoundaryFallback,
} from "cyberstorm/utils/errors/NimbusErrorBoundary";
import type { NimbusErrorBoundaryFallbackProps } from "cyberstorm/utils/errors/NimbusErrorBoundary";

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

return (
<>
<NimbusErrorBoundary
fallback={UserSettingsFallback}
onRetry={({ reset }) => reset()}
>
<PageHeader headingLevel="1" headingSize="2">
Settings
</PageHeader>
Expand Down Expand Up @@ -47,6 +55,27 @@ export default function UserSettings() {
<Outlet context={context} />
</section>
</div>
</>
</NimbusErrorBoundary>
);
}

/**
* Provides fallback messaging when the user settings shell fails to render.
*/
function UserSettingsFallback(props: NimbusErrorBoundaryFallbackProps) {
const {
title = "Settings failed to load",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this page fail to load? This time there doesn't seem to be any actions either. Do we want to wrap all the things just in case?

description = "Reload the settings page or return to the dashboard.",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What dashboard?

retryLabel = "Reload",
...rest
} = props;

return (
<NimbusErrorBoundaryFallback
{...rest}
title={title}
description={description}
retryLabel={retryLabel}
/>
);
}
Loading