Skip to content

Commit 1d4d766

Browse files
authored
Merge pull request #2229 from danielepintore/canary
feat(dashboard): generate user fallback avatar using user email and allow user to choose default avatar
2 parents 8532cba + f9210d3 commit 1d4d766

File tree

3 files changed

+35
-2
lines changed

3 files changed

+35
-2
lines changed

apps/dokploy/components/dashboard/settings/profile/profile-form.tsx

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { Avatar, AvatarFallback } from "@/components/ui/avatar";
12
import { AlertBlock } from "@/components/shared/alert-block";
23
import { Button } from "@/components/ui/button";
34
import {
@@ -19,7 +20,7 @@ import {
1920
import { Input } from "@/components/ui/input";
2021
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
2122
import { Switch } from "@/components/ui/switch";
22-
import { generateSHA256Hash } from "@/lib/utils";
23+
import { generateSHA256Hash, getFallbackAvatarInitials } from "@/lib/utils";
2324
import { api } from "@/utils/api";
2425
import { zodResolver } from "@hookform/resolvers/zod";
2526
import { Loader2, User } from "lucide-react";
@@ -257,6 +258,24 @@ export const ProfileForm = () => {
257258
value={field.value}
258259
className="flex flex-row flex-wrap gap-2 max-xl:justify-center"
259260
>
261+
<FormItem key="no-avatar">
262+
<FormLabel className="[&:has([data-state=checked])>.default-avatar]:border-primary [&:has([data-state=checked])>.default-avatar]:border-1 [&:has([data-state=checked])>.default-avatar]:p-px cursor-pointer">
263+
<FormControl>
264+
<RadioGroupItem
265+
value=""
266+
className="sr-only"
267+
/>
268+
</FormControl>
269+
270+
<Avatar className="default-avatar h-12 w-12 rounded-full border hover:p-px hover:border-primary transition-transform">
271+
<AvatarFallback className="rounded-lg">
272+
{getFallbackAvatarInitials(
273+
data?.user?.name,
274+
)}
275+
</AvatarFallback>
276+
</Avatar>
277+
</FormLabel>
278+
</FormItem>
260279
{availableAvatars.map((image) => (
261280
<FormItem key={image}>
262281
<FormLabel className="[&:has([data-state=checked])>img]:border-primary [&:has([data-state=checked])>img]:border-1 [&:has([data-state=checked])>img]:p-px cursor-pointer">

apps/dokploy/components/layouts/user-nav.tsx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import {
1919
} from "@/components/ui/select";
2020
import { authClient } from "@/lib/auth-client";
2121
import { Languages } from "@/lib/languages";
22+
import { getFallbackAvatarInitials } from "@/lib/utils";
2223
import { api } from "@/utils/api";
2324
import useLocale from "@/utils/hooks/use-locale";
2425
import { ModeToggle } from "../ui/modeToggle";
@@ -46,7 +47,9 @@ export const UserNav = () => {
4647
src={data?.user?.image || ""}
4748
alt={data?.user?.image || ""}
4849
/>
49-
<AvatarFallback className="rounded-lg">CN</AvatarFallback>
50+
<AvatarFallback className="rounded-lg">
51+
{getFallbackAvatarInitials(data?.user?.name)}
52+
</AvatarFallback>
5053
</Avatar>
5154
<div className="grid flex-1 text-left text-sm leading-tight">
5255
<span className="truncate font-semibold">Account</span>

apps/dokploy/lib/utils.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,14 @@ export function formatTimestamp(timestamp: string | number) {
2727
return "Fecha inválida";
2828
}
2929
}
30+
31+
export function getFallbackAvatarInitials(
32+
fullName: string | undefined,
33+
): string {
34+
if (typeof fullName === "undefined" || fullName === "") return "CN";
35+
const [name = "", surname = ""] = fullName.split(" ");
36+
if (surname === "") {
37+
return name.substring(0, 2).toUpperCase();
38+
}
39+
return (name.charAt(0) + surname.charAt(0)).toUpperCase();
40+
}

0 commit comments

Comments
 (0)