form feedback consolidation
This commit is contained in:
27
src/components/ui/FormFeedback.tsx
Normal file
27
src/components/ui/FormFeedback.tsx
Normal file
@@ -0,0 +1,27 @@
|
||||
import { Show, type JSX } from "solid-js";
|
||||
|
||||
export interface FormFeedbackProps {
|
||||
type: "success" | "error";
|
||||
message: string | JSX.Element;
|
||||
show?: boolean;
|
||||
class?: string;
|
||||
}
|
||||
|
||||
export default function FormFeedback(props: FormFeedbackProps) {
|
||||
const show = () => props.show ?? true;
|
||||
|
||||
return (
|
||||
<Show when={show()}>
|
||||
<div
|
||||
class={`text-center text-sm ${
|
||||
props.type === "success" ? "text-green" : "text-red"
|
||||
} ${props.class || ""}`}
|
||||
role="alert"
|
||||
>
|
||||
{props.message}
|
||||
</div>
|
||||
</Show>
|
||||
);
|
||||
}
|
||||
|
||||
export { FormFeedback };
|
||||
@@ -15,6 +15,7 @@ import { api } from "~/lib/api";
|
||||
import Input from "~/components/ui/Input";
|
||||
import PasswordInput from "~/components/ui/PasswordInput";
|
||||
import Button from "~/components/ui/Button";
|
||||
import FormFeedback from "~/components/ui/FormFeedback";
|
||||
|
||||
import type { UserProfile } from "~/types/user";
|
||||
import PasswordStrengthMeter from "~/components/PasswordStrengthMeter";
|
||||
@@ -611,11 +612,12 @@ export default function AccountPage() {
|
||||
: "Set Image"}
|
||||
</button>
|
||||
</form>
|
||||
<Show when={showImageSuccess()}>
|
||||
<div class="text-green mt-2 text-center text-sm">
|
||||
Profile image updated!
|
||||
</div>
|
||||
</Show>
|
||||
<FormFeedback
|
||||
type="success"
|
||||
message="Profile image updated!"
|
||||
show={showImageSuccess()}
|
||||
class="mt-2"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -694,11 +696,12 @@ export default function AccountPage() {
|
||||
Submit
|
||||
</Button>
|
||||
</div>
|
||||
<Show when={showEmailSuccess()}>
|
||||
<div class="text-green mt-2 text-center text-sm">
|
||||
Email updated!
|
||||
</div>
|
||||
</Show>
|
||||
<FormFeedback
|
||||
type="success"
|
||||
message="Email updated!"
|
||||
show={showEmailSuccess()}
|
||||
class="mt-2"
|
||||
/>
|
||||
</form>
|
||||
|
||||
{/* Display Name Section */}
|
||||
@@ -741,11 +744,12 @@ export default function AccountPage() {
|
||||
Submit
|
||||
</Button>
|
||||
</div>
|
||||
<Show when={showDisplayNameSuccess()}>
|
||||
<div class="text-green mt-2 text-center text-sm">
|
||||
Display name updated!
|
||||
</div>
|
||||
</Show>
|
||||
<FormFeedback
|
||||
type="success"
|
||||
message="Display name updated!"
|
||||
show={showDisplayNameSuccess()}
|
||||
class="mt-2"
|
||||
/>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -817,9 +821,11 @@ export default function AccountPage() {
|
||||
newPasswordConfRef.value.length >= 6
|
||||
}
|
||||
>
|
||||
<div class="text-red mb-4 text-center text-sm">
|
||||
Passwords do not match!
|
||||
</div>
|
||||
<FormFeedback
|
||||
type="error"
|
||||
message="Passwords do not match!"
|
||||
class="mb-4"
|
||||
/>
|
||||
</Show>
|
||||
|
||||
<Button
|
||||
@@ -831,20 +837,21 @@ export default function AccountPage() {
|
||||
Set
|
||||
</Button>
|
||||
|
||||
<Show when={passwordError()}>
|
||||
<div class="text-red text-center text-sm">
|
||||
{userProfile().hasPassword
|
||||
<FormFeedback
|
||||
type="error"
|
||||
message={
|
||||
userProfile().hasPassword
|
||||
? "Password did not match record"
|
||||
: "Error setting password"}
|
||||
</div>
|
||||
</Show>
|
||||
: "Must have email & password provider linked or set password first"
|
||||
}
|
||||
show={passwordError()}
|
||||
/>
|
||||
|
||||
<Show when={showPasswordSuccess()}>
|
||||
<div class="text-green text-center text-sm">
|
||||
Password {userProfile().hasPassword ? "changed" : "set"}{" "}
|
||||
successfully!
|
||||
</div>
|
||||
</Show>
|
||||
<FormFeedback
|
||||
type="success"
|
||||
message={`Password ${userProfile().hasPassword ? "changed" : "set"} successfully!`}
|
||||
show={showPasswordSuccess()}
|
||||
/>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -924,11 +931,12 @@ export default function AccountPage() {
|
||||
Delete Account
|
||||
</Button>
|
||||
|
||||
<Show when={passwordDeletionError()}>
|
||||
<div class="text-red mt-2 text-center text-sm">
|
||||
Password did not match record
|
||||
</div>
|
||||
</Show>
|
||||
<FormFeedback
|
||||
type="error"
|
||||
message="Password did not match record"
|
||||
show={passwordDeletionError()}
|
||||
class="mt-2"
|
||||
/>
|
||||
</form>
|
||||
</Show>
|
||||
</div>
|
||||
|
||||
@@ -7,6 +7,7 @@ import { getClientCookie } from "~/lib/cookies.client";
|
||||
import { COUNTDOWN_CONFIG } from "~/config";
|
||||
import Input from "~/components/ui/Input";
|
||||
import { Button } from "~/components/ui/Button";
|
||||
import FormFeedback from "~/components/ui/FormFeedback";
|
||||
|
||||
export default function RequestPasswordResetPage() {
|
||||
const navigate = useNavigate();
|
||||
@@ -174,42 +175,18 @@ export default function RequestPasswordResetPage() {
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div
|
||||
class={`${
|
||||
showSuccessMessage() ? "" : "opacity-0 select-none"
|
||||
} text-green flex justify-center italic transition-opacity duration-300 ease-in-out`}
|
||||
>
|
||||
If email exists, you will receive an email shortly!
|
||||
</div>
|
||||
<FormFeedback
|
||||
type="success"
|
||||
message="If email exists, you will receive an email shortly!"
|
||||
show={showSuccessMessage()}
|
||||
/>
|
||||
|
||||
<Show when={error()}>
|
||||
<div class="mt-4 flex justify-center">
|
||||
<div
|
||||
class={`${
|
||||
error().includes("Too many attempts") ||
|
||||
error().includes("wait before requesting")
|
||||
? "border-maroon bg-red rounded-lg border px-4 py-3"
|
||||
: ""
|
||||
} max-w-md text-center`}
|
||||
>
|
||||
<Show when={error().includes("Too many attempts")}>
|
||||
<div class="mb-1 text-base font-semibold">
|
||||
⏱️ Rate Limit Exceeded
|
||||
</div>
|
||||
</Show>
|
||||
<div
|
||||
class={`${
|
||||
error().includes("Too many attempts") ||
|
||||
error().includes("wait before requesting")
|
||||
? "text-sm"
|
||||
: "text-red text-sm italic"
|
||||
}`}
|
||||
>
|
||||
{error()}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Show>
|
||||
<FormFeedback
|
||||
type="error"
|
||||
message={error()}
|
||||
show={error() !== ""}
|
||||
class="mt-4"
|
||||
/>
|
||||
|
||||
<div class="mt-6 flex justify-center">
|
||||
<A
|
||||
|
||||
Reference in New Issue
Block a user