added UploadAvatar to login and account page

This commit is contained in:
Oliver Bryan
2026-01-01 07:09:47 +00:00
parent 442ef7a18e
commit 1f217e1338
3 changed files with 48 additions and 24 deletions

View File

@@ -4,11 +4,13 @@ import { SettingsPageLayout } from "@/components/settings-page-layout";
import { Button } from "@/components/ui/button";
import { Field } from "@/components/ui/field";
import { Label } from "@/components/ui/label";
import { UploadAvatar } from "@/components/upload-avatar";
import { user } from "@/lib/server";
function Account() {
const [name, setName] = useState("");
const [password, setPassword] = useState("");
const [avatarURL, setAvatarUrl] = useState<string | null>(null);
const [error, setError] = useState("");
const [submitAttempted, setSubmitAttempted] = useState(false);
const [userId, setUserId] = useState<number | null>(null);
@@ -19,6 +21,7 @@ function Account() {
const user = JSON.parse(userStr) as UserRecord;
setName(user.name);
setUserId(user.id);
setAvatarUrl(user.avatarURL || null);
}
}, []);
@@ -39,6 +42,7 @@ function Account() {
id: userId,
name: name.trim(),
password: password.trim(),
avatarURL: avatarURL || undefined,
onSuccess: (data) => {
setError("");
localStorage.setItem("user", JSON.stringify(data));
@@ -52,7 +56,11 @@ function Account() {
return (
<SettingsPageLayout title="Account">
<form onSubmit={handleSubmit} className="flex flex-col max-w-sm">
<form onSubmit={handleSubmit} className="flex flex-col gap-6 max-w-sm">
<div>
<Label className="mb-4 block">Avatar</Label>
<UploadAvatar avatarURL={avatarURL} onAvatarUploaded={setAvatarUrl} />
</div>
<Field
label="Full Name"
value={name}

View File

@@ -4,6 +4,7 @@ import { ServerConfigurationDialog } from "@/components/server-configuration-dia
import { Button } from "@/components/ui/button";
import { Field } from "@/components/ui/field";
import { Label } from "@/components/ui/label";
import { UploadAvatar } from "@/components/upload-avatar";
import { capitalise, cn, getServerURL } from "@/lib/utils";
export default function LogInForm() {
@@ -12,6 +13,7 @@ export default function LogInForm() {
const [name, setName] = useState("");
const [username, setUsername] = useState("");
const [password, setPassword] = useState("");
const [avatarURL, setAvatarUrl] = useState<string | null>(null);
const [error, setError] = useState("");
const [submitAttempted, setSubmitAttempted] = useState(false);
@@ -59,6 +61,7 @@ export default function LogInForm() {
name,
username,
password,
avatarURL,
}),
})
.then(async (res) => {
@@ -83,7 +86,7 @@ export default function LogInForm() {
};
const focusFirstInput = () => {
const firstInput = document.querySelector("input");
const firstInput = document.querySelector('input[type="text"]');
if (firstInput) {
(firstInput as HTMLInputElement).focus();
}
@@ -96,6 +99,7 @@ export default function LogInForm() {
const resetForm = () => {
setError("");
setSubmitAttempted(false);
setAvatarUrl(null);
requestAnimationFrame(() => focusFirstInput());
};
@@ -119,9 +123,16 @@ export default function LogInForm() {
)}
>
<ServerConfigurationDialog />
<span className="text-xl mb-2">{capitalise(mode)}</span>
<span className="text-xl ">{capitalise(mode)}</span>
<div className={"flex flex-col items-center mb-0"}>
{mode === "register" && (
<>
<UploadAvatar
avatarURL={avatarURL}
onAvatarUploaded={setAvatarUrl}
className={"mt-2 mb-4"}
/>
<Field
label="Full Name"
value={name}
@@ -129,6 +140,7 @@ export default function LogInForm() {
validate={(v) => (v.trim() === "" ? "Cannot be empty" : undefined)}
submitAttempted={submitAttempted}
/>
</>
)}
<Field
label="Username"
@@ -145,6 +157,7 @@ export default function LogInForm() {
hidden={true}
submitAttempted={submitAttempted}
/>
</div>
{mode === "login" ? (
<>

View File

@@ -2,15 +2,18 @@ import { useRef, useState } from "react";
import { Button } from "@/components/ui/button";
import { Label } from "@/components/ui/label";
import { user } from "@/lib/server";
import { cn } from "@/lib/utils";
export function UploadAvatar({
avatarURL,
onAvatarUploaded,
label,
className,
}: {
avatarURL?: string | null;
onAvatarUploaded: (avatarURL: string) => void;
label?: string;
className?: string;
}) {
const [uploading, setUploading] = useState(false);
const [error, setError] = useState<string | null>(null);
@@ -37,7 +40,7 @@ export function UploadAvatar({
};
return (
<div className="flex items-center gap-4">
<div className={cn("flex items-center gap-4", className)}>
{avatarURL && (
<img src={avatarURL} alt="Avatar" className="w-16 h-16 rounded-full border object-cover" />
)}