mirror of
https://github.com/felipegcoutinho/openmonetis.git
synced 2026-05-09 11:01:45 +00:00
feat(payers): upload de avatar via arquivo com redimensionamento client-side
- círculo de upload no final da grade de avatares abre seletor de arquivo - imagem redimensionada para 200×200px via Canvas e salva como base64 - suporte a data URLs em next/image com prop unoptimized - object-cover adicionado ao componente base Avatar Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -17,11 +17,6 @@ import { version } from "@/package.json";
|
||||
import { FeedbackDialogBody } from "@/shared/components/navigation/navbar/feedback-dialog";
|
||||
import { Badge } from "@/shared/components/ui/badge";
|
||||
import { Dialog, DialogTrigger } from "@/shared/components/ui/dialog";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "@/shared/components/ui/tooltip";
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
@@ -30,6 +25,11 @@ import {
|
||||
DropdownMenuTrigger,
|
||||
} from "@/shared/components/ui/dropdown-menu";
|
||||
import { Spinner } from "@/shared/components/ui/spinner";
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "@/shared/components/ui/tooltip";
|
||||
import { authClient } from "@/shared/lib/auth/client";
|
||||
import { getAvatarSrc } from "@/shared/lib/payers/utils";
|
||||
import type { UpdateCheckResult } from "@/shared/lib/version/check-update";
|
||||
@@ -68,6 +68,7 @@ export function NavbarUser({
|
||||
const avatarSrc = pagadorAvatarUrl
|
||||
? getAvatarSrc(pagadorAvatarUrl)
|
||||
: user.image || getAvatarSrc(null);
|
||||
const isDataUrl = avatarSrc.startsWith("data:");
|
||||
|
||||
async function handleLogout() {
|
||||
await authClient.signOut({
|
||||
@@ -91,6 +92,7 @@ export function NavbarUser({
|
||||
<div className="relative size-10 overflow-hidden rounded-full">
|
||||
<Image
|
||||
src={avatarSrc}
|
||||
unoptimized={isDataUrl}
|
||||
alt={`Avatar de ${user.name}`}
|
||||
fill
|
||||
sizes="40px"
|
||||
@@ -112,6 +114,7 @@ export function NavbarUser({
|
||||
<div className="relative size-9 shrink-0 overflow-hidden rounded-full">
|
||||
<Image
|
||||
src={avatarSrc}
|
||||
unoptimized={isDataUrl}
|
||||
alt={user.name}
|
||||
fill
|
||||
sizes="36px"
|
||||
@@ -120,7 +123,9 @@ export function NavbarUser({
|
||||
</div>
|
||||
<div className="flex flex-col min-w-0">
|
||||
<div className="flex items-center gap-1 min-w-0">
|
||||
<span className="text-sm font-medium truncate">{user.name}</span>
|
||||
<span className="text-sm font-medium truncate">
|
||||
{user.name}
|
||||
</span>
|
||||
<Tooltip>
|
||||
<TooltipTrigger asChild>
|
||||
<button
|
||||
|
||||
@@ -22,6 +22,7 @@ export function NavUser({ user, pagadorAvatarUrl }: NavUserProps) {
|
||||
const avatarSrc = pagadorAvatarUrl
|
||||
? getAvatarSrc(pagadorAvatarUrl)
|
||||
: user.image || getAvatarSrc(null);
|
||||
const isDataUrl = avatarSrc.startsWith("data:");
|
||||
|
||||
return (
|
||||
<SidebarMenu>
|
||||
@@ -33,6 +34,7 @@ export function NavUser({ user, pagadorAvatarUrl }: NavUserProps) {
|
||||
<div className="relative size-8 shrink-0 overflow-hidden rounded-full">
|
||||
<Image
|
||||
src={avatarSrc}
|
||||
unoptimized={isDataUrl}
|
||||
alt={user.name}
|
||||
fill
|
||||
sizes="32px"
|
||||
|
||||
@@ -28,7 +28,7 @@ function AvatarImage({
|
||||
return (
|
||||
<AvatarPrimitive.Image
|
||||
data-slot="avatar-image"
|
||||
className={cn("aspect-square size-full", className)}
|
||||
className={cn("aspect-square size-full object-cover", className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user