Skip to content

Commit 1c1e3db

Browse files
committed
Bring ReportPackage Nimbus component closer to how other components are done
The existing implementation is very well done, but it's not aligned to how other similar components are done in the project. This commit introduces an implementation that is a bit simpler, with the added negative effect of having to have two usage instances of the component in the same page (packageListing route). Performance effects are mostly unknown, but no noticable difference was discovered in local dev env testing.
1 parent f82edf2 commit 1c1e3db

File tree

8 files changed

+180
-192
lines changed

8 files changed

+180
-192
lines changed

apps/cyberstorm-remix/app/p/components/ReportPackage/ReportPackage.css

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
@layer nimbus-layout {
2-
.report-package--centered {
2+
.report-package__body {
3+
min-width: 600px;
4+
}
5+
6+
.report-package__body--centered {
37
align-items: center;
48
justify-content: center;
59
text-align: center;
@@ -42,4 +46,10 @@
4246
font-size: var(--font-size-body-md);
4347
line-height: var(--line-height-md);
4448
}
49+
50+
@media (width <= 650px) {
51+
.report-package__body {
52+
min-width: 95vw;
53+
}
54+
}
4555
}

apps/cyberstorm-remix/app/p/components/ReportPackage/ReportPackageButton.tsx

Lines changed: 0 additions & 20 deletions
This file was deleted.

apps/cyberstorm-remix/app/p/components/ReportPackage/ReportPackageForm.tsx

Lines changed: 118 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,47 @@
1+
import "./ReportPackage.css";
12
import { useReducer, useState } from "react";
23

34
import {
45
Modal,
56
NewAlert,
67
NewButton,
8+
NewIcon,
79
NewSelect,
810
NewTextInput,
11+
useToast,
912
type SelectOption,
1013
} from "@thunderstore/cyberstorm";
1114
import {
1215
type RequestConfig,
1316
type PackageListingReportRequestData,
1417
packageListingReport,
1518
} from "@thunderstore/thunderstore-api";
19+
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
1620

1721
import { useStrongForm } from "cyberstorm/utils/StrongForm/useStrongForm";
22+
import {
23+
faFaceSaluting,
24+
faFlagSwallowtail,
25+
} from "@fortawesome/pro-solid-svg-icons";
26+
27+
export function ReportPackageButton(
28+
props: React.HTMLAttributes<HTMLButtonElement>
29+
) {
30+
return (
31+
<NewButton
32+
tooltipText="Report Package"
33+
csVariant="secondary"
34+
csModifiers={["only-icon"]}
35+
{...props}
36+
>
37+
<NewIcon csMode="inline" noWrapper>
38+
<FontAwesomeIcon icon={faFlagSwallowtail} />
39+
</NewIcon>
40+
</NewButton>
41+
);
42+
}
43+
44+
ReportPackageButton.displayName = "ReportPackageButton";
1845

1946
const reportOptions: SelectOption<PackageListingReportRequestData["reason"]>[] =
2047
[
@@ -27,29 +54,20 @@ const reportOptions: SelectOption<PackageListingReportRequestData["reason"]>[] =
2754
{ value: "Other", label: "Other" },
2855
];
2956

30-
export interface ReportPackageFormProps {
57+
export interface ReportPackageProps {
3158
community: string;
3259
namespace: string;
3360
package: string;
3461
config: () => RequestConfig;
3562
}
3663

37-
interface ReportPackageFormFullProps extends ReportPackageFormProps {
38-
error: string | null;
39-
onOpenChange: (isOpen: boolean) => void;
40-
setError: (error: string | null) => void;
41-
setIsSubmitted: (isSubmitted: boolean) => void;
42-
}
64+
export function ReportPackage(props: ReportPackageProps) {
65+
const { config, ...requestParams } = props;
66+
67+
const [submitted, setSubmitted] = useState(false);
68+
const [modalOpen, setModalOpen] = useState(false);
4369

44-
export function ReportPackageForm(props: ReportPackageFormFullProps) {
45-
const {
46-
config,
47-
onOpenChange,
48-
setIsSubmitted,
49-
error,
50-
setError,
51-
...requestParams
52-
} = props;
70+
const toast = useToast();
5371

5472
function formFieldUpdateAction(
5573
state: PackageListingReportRequestData,
@@ -95,21 +113,24 @@ export function ReportPackageForm(props: ReportPackageFormFullProps) {
95113
inputs: formInputs,
96114
submitor,
97115
onSubmitSuccess: () => {
98-
setIsSubmitted(true);
99-
setError(null);
116+
setSubmitted(true);
100117
},
101118
onSubmitError: (error) => {
102119
let message = `Error occurred: ${error.message || "Unknown error"}`;
103120
if (error.message === "401: Unauthorized") {
104121
message = "You must be logged in to report a package.";
105122
}
106-
setError(message);
123+
toast.addToast({
124+
csVariant: "danger",
125+
children: message,
126+
duration: 8000,
127+
});
107128
},
108129
});
109130

110-
return (
131+
const form = (
111132
<>
112-
<Modal.Body>
133+
<Modal.Body className="report-package__body">
113134
<div className="report-package__block">
114135
<label htmlFor="reason" className="report-package__label">
115136
Reason
@@ -147,22 +168,91 @@ export function ReportPackageForm(props: ReportPackageFormFullProps) {
147168
rootClasses="report-package__textarea"
148169
/>
149170
</div>
150-
{error && (
171+
{strongForm.inputErrors ||
172+
strongForm.refineError ||
173+
strongForm.submitError ? (
151174
<div className="report-package__block">
152-
<NewAlert csVariant="danger">{error}</NewAlert>
175+
{strongForm.inputErrors ? (
176+
<NewAlert csVariant="danger">
177+
{Object.entries(strongForm.inputErrors).map(([key, value]) => (
178+
<div key={key}>
179+
<strong>{key}:</strong>{" "}
180+
{Array.isArray(value) ? value.join(", ") : value}
181+
</div>
182+
))}
183+
</NewAlert>
184+
) : null}
185+
{strongForm.refineError ? (
186+
<NewAlert csVariant="danger">
187+
Error while refining: {strongForm.refineError.message}
188+
</NewAlert>
189+
) : null}
190+
{strongForm.submitError ? (
191+
<NewAlert csVariant="danger">
192+
Error while submitting: {strongForm.submitError.message}
193+
</NewAlert>
194+
) : null}
153195
</div>
154-
)}
196+
) : null}
155197
</Modal.Body>
156198
<Modal.Footer>
157-
<NewButton csVariant="secondary" onClick={() => onOpenChange(false)}>
158-
Cancel
159-
</NewButton>
199+
<Modal.Close asChild>
200+
<NewButton csVariant="secondary">Cancel</NewButton>
201+
</Modal.Close>
160202
<NewButton csVariant="accent" onClick={strongForm.submit}>
161203
Send report
162204
</NewButton>
163205
</Modal.Footer>
164206
</>
165207
);
208+
209+
const done = (
210+
<>
211+
<Modal.Body className="report-package-body report-package-body--centered">
212+
<div className="report-package__block ">
213+
<NewIcon
214+
csMode="inline"
215+
noWrapper
216+
rootClasses="report-package__submitted-icon"
217+
>
218+
<FontAwesomeIcon icon={faFaceSaluting} />
219+
</NewIcon>
220+
</div>
221+
<h3 className="report-package__heading">Thank you for your report</h3>
222+
<p className="report-package__paragraph">
223+
We&apos;ve received your report and will review the content shortly.
224+
<br />
225+
Your feedback helps keep our community safe.
226+
</p>
227+
</Modal.Body>
228+
<Modal.Footer>
229+
<Modal.Close asChild>
230+
<NewButton csVariant="secondary">Close</NewButton>
231+
</Modal.Close>
232+
</Modal.Footer>
233+
</>
234+
);
235+
236+
return (
237+
<Modal
238+
titleContent="Report Package"
239+
csSize="small"
240+
disableBody
241+
onOpenChange={(isOpen) => {
242+
if (modalOpen && submitted && !isOpen) {
243+
// If the modal is being closed after a successful submission,
244+
// reset the form state.
245+
updateFormFieldState({ field: "reason", value: "Other" });
246+
updateFormFieldState({ field: "description", value: "" });
247+
setSubmitted(false);
248+
}
249+
setModalOpen(isOpen);
250+
}}
251+
trigger={<ReportPackageButton />}
252+
>
253+
{submitted ? done : form}
254+
</Modal>
255+
);
166256
}
167257

168-
ReportPackageForm.displayName = "ReportPackageForm";
258+
ReportPackage.displayName = "ReportPackage";

apps/cyberstorm-remix/app/p/components/ReportPackage/ReportPackageModal.tsx

Lines changed: 0 additions & 25 deletions
This file was deleted.

apps/cyberstorm-remix/app/p/components/ReportPackage/ReportPackageSubmitted.tsx

Lines changed: 0 additions & 35 deletions
This file was deleted.

apps/cyberstorm-remix/app/p/components/ReportPackage/useReportPackage.tsx

Lines changed: 0 additions & 53 deletions
This file was deleted.

apps/cyberstorm-remix/app/p/packageListing.css

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,13 @@
264264
width: 100%;
265265
}
266266

267+
.package-listing__narrow-other-actions {
268+
display: flex;
269+
flex-direction: row;
270+
gap: var(--gap-xs);
271+
width: 100%;
272+
}
273+
267274
@media (width < 41rem) {
268275
.package-listing__actions {
269276
position: unset;

0 commit comments

Comments
 (0)