feat: user avatar images
- added user avatars for each user - it will fetch user images from github or google and if there is no image then it will show initials
This commit is contained in:
parent
2262adca74
commit
30c9da559f
@ -15,6 +15,20 @@
|
||||
"when": 1731290863632,
|
||||
"tag": "0001_opposite_newton_destine",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 2,
|
||||
"version": "5",
|
||||
"when": 1731296235880,
|
||||
"tag": "0002_rainy_fantastic_four",
|
||||
"breakpoints": true
|
||||
},
|
||||
{
|
||||
"idx": 3,
|
||||
"version": "5",
|
||||
"when": 1731297339306,
|
||||
"tag": "0003_lying_snowbird",
|
||||
"breakpoints": true
|
||||
}
|
||||
]
|
||||
}
|
@ -169,6 +169,7 @@ export default {
|
||||
name: sb.name,
|
||||
type: sb.type,
|
||||
author: sb.author.name,
|
||||
authorAvatarUrl: sb.author.avatarUrl,
|
||||
sharedOn: r.sharedOn,
|
||||
}
|
||||
})
|
||||
|
@ -51,7 +51,7 @@ const getSharedUsers = async (usersToSandboxes: UsersToSandboxes[]) => {
|
||||
}
|
||||
)
|
||||
const userData: User = await userRes.json()
|
||||
return { id: userData.id, name: userData.name }
|
||||
return { id: userData.id, name: userData.name, avatarUrl: userData.avatarUrl }
|
||||
})
|
||||
)
|
||||
|
||||
|
@ -35,6 +35,7 @@ export default async function DashboardPage() {
|
||||
type: "react" | "node"
|
||||
author: string
|
||||
sharedOn: Date
|
||||
authorAvatarUrl: string
|
||||
}[]
|
||||
|
||||
return (
|
||||
|
@ -20,6 +20,7 @@ export default function DashboardSharedWithMe({
|
||||
name: string
|
||||
type: "react" | "node"
|
||||
author: string
|
||||
authorAvatarUrl: string
|
||||
sharedOn: Date
|
||||
}[]
|
||||
}) {
|
||||
@ -58,7 +59,11 @@ export default function DashboardSharedWithMe({
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<div className="flex items-center">
|
||||
<Avatar name={sandbox.author} className="mr-2" />
|
||||
<Avatar
|
||||
name={sandbox.author}
|
||||
avatarUrl={sandbox.authorAvatarUrl}
|
||||
className="mr-2"
|
||||
/>
|
||||
{sandbox.author}
|
||||
</div>
|
||||
</TableCell>
|
||||
|
@ -23,7 +23,7 @@ export default function Navbar({
|
||||
}: {
|
||||
userData: User
|
||||
sandboxData: Sandbox
|
||||
shared: { id: string; name: string }[]
|
||||
shared: { id: string; name: string; avatarUrl: string }[]
|
||||
}) {
|
||||
const [isEditOpen, setIsEditOpen] = useState(false)
|
||||
const [isShareOpen, setIsShareOpen] = useState(false)
|
||||
|
@ -43,6 +43,7 @@ export default function ShareSandboxModal({
|
||||
shared: {
|
||||
id: string
|
||||
name: string
|
||||
avatarUrl: string
|
||||
}[]
|
||||
}) {
|
||||
const [loading, setLoading] = useState(false)
|
||||
@ -142,7 +143,11 @@ export default function ShareSandboxModal({
|
||||
</DialogHeader>
|
||||
<div className="space-y-2">
|
||||
{shared.map((user) => (
|
||||
<SharedUser key={user.id} user={user} sandboxId={data.id} />
|
||||
<SharedUser
|
||||
key={user.id}
|
||||
user={user}
|
||||
sandboxId={data.id}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
@ -10,7 +10,7 @@ export default function SharedUser({
|
||||
user,
|
||||
sandboxId,
|
||||
}: {
|
||||
user: { id: string; name: string }
|
||||
user: { id: string; name: string; avatarUrl: string }
|
||||
sandboxId: string
|
||||
}) {
|
||||
const [loading, setLoading] = useState(false)
|
||||
@ -24,7 +24,7 @@ export default function SharedUser({
|
||||
return (
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex items-center">
|
||||
<Avatar name={user.name} className="mr-2" />
|
||||
<Avatar name={user.name} avatarUrl={user.avatarUrl} className="mr-2" />
|
||||
{user.name}
|
||||
</div>
|
||||
<Button
|
||||
|
@ -1,23 +1,42 @@
|
||||
import { cn } from "@/lib/utils"
|
||||
import Image from "next/image"
|
||||
|
||||
export default function Avatar({
|
||||
name,
|
||||
avatarUrl,
|
||||
className,
|
||||
}: {
|
||||
name: string
|
||||
avatarUrl?: string | null
|
||||
className?: string
|
||||
}) {
|
||||
// Generate initials from name if no avatarUrl is provided
|
||||
const initials = name
|
||||
? name
|
||||
.split(" ")
|
||||
.slice(0, 2)
|
||||
.map((letter) => letter[0].toUpperCase())
|
||||
.join("")
|
||||
: "?"
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(
|
||||
className,
|
||||
"w-5 h-5 font-mono rounded-full overflow-hidden bg-gradient-to-t from-neutral-800 to-neutral-600 flex items-center justify-center text-[0.5rem] font-medium"
|
||||
"w-9 h-9 font-mono rounded-full overflow-hidden bg-gradient-to-t from-neutral-800 to-neutral-600 flex items-center justify-center text-sm font-medium"
|
||||
)}
|
||||
>
|
||||
{name
|
||||
.split(" ")
|
||||
.slice(0, 2)
|
||||
.map((letter) => letter[0].toUpperCase())}
|
||||
{avatarUrl ? (
|
||||
<Image
|
||||
src={avatarUrl}
|
||||
alt={name || "User"}
|
||||
width={20}
|
||||
height={20}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
) : (
|
||||
initials
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import { User } from "@/lib/types"
|
||||
import { useClerk } from "@clerk/nextjs"
|
||||
import { LogOut, Sparkles } from "lucide-react"
|
||||
import { useRouter } from "next/navigation"
|
||||
import Avatar from "./avatar"
|
||||
|
||||
export default function UserButton({ userData }: { userData: User }) {
|
||||
if (!userData) return null
|
||||
@ -21,13 +22,7 @@ export default function UserButton({ userData }: { userData: User }) {
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger>
|
||||
<div className="w-9 h-9 font-mono rounded-full overflow-hidden bg-gradient-to-t from-neutral-800 to-neutral-600 flex items-center justify-center text-sm font-medium">
|
||||
{userData.name &&
|
||||
userData.name
|
||||
.split(" ")
|
||||
.slice(0, 2)
|
||||
.map((name) => name[0].toUpperCase())}
|
||||
</div>
|
||||
<Avatar name={userData.name} avatarUrl={userData.avatarUrl} />
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent className="w-48" align="end">
|
||||
<div className="py-1.5 px-2 w-full">
|
||||
|
@ -5,6 +5,12 @@ const nextConfig = {
|
||||
{
|
||||
hostname: "cdn.simpleicons.org",
|
||||
},
|
||||
{
|
||||
hostname: "img.clerk.com",
|
||||
},
|
||||
{
|
||||
hostname: "images.clerk.dev",
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user