Users can now upload an avatar from Profile settings.
This commit is contained in:
@@ -1,11 +1,15 @@
|
||||
import { Form, Head, Link, usePage } from '@inertiajs/react';
|
||||
import { ImagePlus } from 'lucide-react';
|
||||
import { useEffect, useRef, useState } from 'react';
|
||||
import ProfileController from '@/actions/App/Http/Controllers/Settings/ProfileController';
|
||||
import DeleteUser from '@/components/delete-user';
|
||||
import Heading from '@/components/heading';
|
||||
import InputError from '@/components/input-error';
|
||||
import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Label } from '@/components/ui/label';
|
||||
import { useInitials } from '@/hooks/use-initials';
|
||||
import { edit } from '@/routes/profile';
|
||||
import { send } from '@/routes/verification';
|
||||
|
||||
@@ -18,11 +22,34 @@ export default function Profile({
|
||||
}) {
|
||||
const { auth } = usePage().props;
|
||||
const user = auth.user;
|
||||
const getInitials = useInitials();
|
||||
const avatarInputRef = useRef<HTMLInputElement>(null);
|
||||
const [avatarPreviewUrl, setAvatarPreviewUrl] = useState<string | null>(
|
||||
null,
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (avatarPreviewUrl) {
|
||||
URL.revokeObjectURL(avatarPreviewUrl);
|
||||
}
|
||||
};
|
||||
}, [avatarPreviewUrl]);
|
||||
|
||||
if (!user) {
|
||||
return null;
|
||||
}
|
||||
|
||||
function previewAvatar(file: File | null) {
|
||||
setAvatarPreviewUrl((currentUrl) => {
|
||||
if (currentUrl) {
|
||||
URL.revokeObjectURL(currentUrl);
|
||||
}
|
||||
|
||||
return file ? URL.createObjectURL(file) : null;
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head title="Profile settings" />
|
||||
@@ -33,7 +60,7 @@ export default function Profile({
|
||||
<Heading
|
||||
variant="small"
|
||||
title="Profile information"
|
||||
description="Update your name and email address"
|
||||
description="Update your name, email address, and avatar"
|
||||
/>
|
||||
|
||||
<Form
|
||||
@@ -41,10 +68,66 @@ export default function Profile({
|
||||
options={{
|
||||
preserveScroll: true,
|
||||
}}
|
||||
resetOnSuccess={['avatar']}
|
||||
onSuccess={() => {
|
||||
setAvatarPreviewUrl(null);
|
||||
|
||||
if (avatarInputRef.current) {
|
||||
avatarInputRef.current.value = '';
|
||||
}
|
||||
}}
|
||||
encType="multipart/form-data"
|
||||
className="space-y-6"
|
||||
>
|
||||
{({ processing, errors }) => (
|
||||
{({ processing, progress, errors }) => (
|
||||
<>
|
||||
<div className="flex flex-col gap-4 rounded-md border bg-card p-4 sm:flex-row sm:items-center">
|
||||
<Avatar className="size-20 rounded-md">
|
||||
<AvatarImage
|
||||
src={
|
||||
avatarPreviewUrl ??
|
||||
user.avatar ??
|
||||
undefined
|
||||
}
|
||||
alt={user.name}
|
||||
className="object-cover"
|
||||
/>
|
||||
<AvatarFallback className="rounded-md bg-secondary text-lg font-semibold text-secondary-foreground">
|
||||
{getInitials(user.name)}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
|
||||
<div className="grid min-w-0 flex-1 gap-2">
|
||||
<Label htmlFor="avatar">Avatar</Label>
|
||||
<Input
|
||||
id="avatar"
|
||||
ref={avatarInputRef}
|
||||
name="avatar"
|
||||
type="file"
|
||||
accept="image/jpeg,image/png,image/webp"
|
||||
onChange={(event) =>
|
||||
previewAvatar(
|
||||
event.target.files?.[0] ?? null,
|
||||
)
|
||||
}
|
||||
/>
|
||||
<div className="flex flex-wrap items-center gap-2 text-xs text-muted-foreground">
|
||||
<ImagePlus className="size-3.5" />
|
||||
<span>
|
||||
JPG, PNG, or WebP up to 2 MB.
|
||||
</span>
|
||||
</div>
|
||||
{progress && (
|
||||
<progress
|
||||
value={progress.percentage}
|
||||
max="100"
|
||||
className="h-1.5 w-full"
|
||||
/>
|
||||
)}
|
||||
<InputError message={errors.avatar} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-2">
|
||||
<Label htmlFor="name">Name</Label>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user