Profile view #33
This commit is contained in:
+5
-11
@@ -1,6 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import ProfilePicture from "@/components/ProfilePicture";
|
||||
import ProfilePreview, { ProfileImage } from "@/components/ProfilePicture";
|
||||
import SettingsDialog from "@/components/settings/SettingsDialog";
|
||||
import AppLayout from "@/components/app/AppLayout";
|
||||
import { Button } from "@/components/ui/button";
|
||||
@@ -93,10 +93,7 @@ export default function ChatHub() {
|
||||
className="flex justify-between items-center hover:bg-accent hover:text-accent-foreground rounded p-2 transition"
|
||||
>
|
||||
<span className="flex gap-2">
|
||||
<ProfilePicture
|
||||
name={dm.display_name}
|
||||
url={dm.avatar_url}
|
||||
/>
|
||||
<ProfilePreview profile={dm} />
|
||||
<span className="truncate my-auto">
|
||||
{dm.display_name || dm.id}
|
||||
</span>
|
||||
@@ -129,7 +126,7 @@ export default function ChatHub() {
|
||||
className="flex justify-between items-center hover:bg-accent hover:text-accent-foreground rounded p-2 transition"
|
||||
>
|
||||
<span className="flex gap-2">
|
||||
<ProfilePicture
|
||||
<ProfileImage
|
||||
name={srv.name}
|
||||
url={srv.icon_url || ""}
|
||||
/>
|
||||
@@ -167,10 +164,7 @@ export default function ChatHub() {
|
||||
className="flex items-center justify-between hover:bg-accent rounded p-2 transition"
|
||||
>
|
||||
<div className="flex items-center gap-3">
|
||||
<ProfilePicture
|
||||
name={user?.display_name || ""}
|
||||
url={user?.avatar_url || ""}
|
||||
/>
|
||||
<ProfilePreview profile={user || undefined} />
|
||||
<div>
|
||||
<p className="font-medium">
|
||||
{user?.display_name || ""}
|
||||
@@ -233,7 +227,7 @@ export default function ChatHub() {
|
||||
}}
|
||||
>
|
||||
<CardContent className="p-4 flex flex-col items-center text-center gap-2">
|
||||
<ProfilePicture name={srv.name} url={srv.icon_url} />
|
||||
<ProfileImage name={srv.name} url={srv.icon_url} />
|
||||
<h3 className="font-medium truncate">{srv.name}</h3>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
@@ -1,19 +1,80 @@
|
||||
import { cn } from "@/lib/utils";
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "./ui/avatar";
|
||||
import { Popover, PopoverTrigger, PopoverContent } from "./ui/popover";
|
||||
import { Button } from "./ui/button";
|
||||
import { UserProfile } from "@/hooks/get-user";
|
||||
|
||||
export default function ProfilePicture({
|
||||
export function ProfileImage({
|
||||
name,
|
||||
url,
|
||||
className,
|
||||
}: {
|
||||
name: string;
|
||||
url: string | undefined;
|
||||
url: string;
|
||||
className?: string;
|
||||
}) {
|
||||
return (
|
||||
<Avatar className={cn("h-8 w-8", className)}>
|
||||
<Avatar className={cn("h-8 w-8 cursor-pointer", className)}>
|
||||
<AvatarImage src={url} alt={name} />
|
||||
<AvatarFallback>{name[0]}</AvatarFallback>
|
||||
</Avatar>
|
||||
);
|
||||
}
|
||||
|
||||
export default function ProfilePreview({
|
||||
className,
|
||||
profile,
|
||||
}: {
|
||||
profile?: UserProfile;
|
||||
className?: string;
|
||||
}) {
|
||||
if (!profile)
|
||||
return (
|
||||
<Avatar className={cn("h-8 w-8 cursor-pointer", className)}>
|
||||
<AvatarFallback>Loading</AvatarFallback>
|
||||
</Avatar>
|
||||
);
|
||||
|
||||
return (
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<Avatar className={cn("h-8 w-8 cursor-pointer", className)}>
|
||||
<AvatarImage src={profile.avatar_url} alt={profile.display_name} />
|
||||
<AvatarFallback>{profile.display_name[0]}</AvatarFallback>
|
||||
</Avatar>
|
||||
</PopoverTrigger>
|
||||
|
||||
<PopoverContent
|
||||
side="right"
|
||||
align="center"
|
||||
sideOffset={8}
|
||||
className="w-64 p-4"
|
||||
>
|
||||
<div className="flex items-center gap-4">
|
||||
<Avatar className={cn("h-8 w-8 cursor-pointer", className)}>
|
||||
<AvatarImage src={profile.avatar_url} alt={profile.display_name} />
|
||||
<AvatarFallback>{profile.display_name[0]}</AvatarFallback>
|
||||
</Avatar>
|
||||
|
||||
<div className="flex flex-col">
|
||||
<span className="font-medium leading-none">
|
||||
{profile.display_name}
|
||||
</span>
|
||||
<span className="text-sm text-muted-foreground">
|
||||
@{profile.username}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-4 flex gap-2">
|
||||
<Button size="sm" className="flex-1">
|
||||
Message
|
||||
</Button>
|
||||
{/* <Button size="sm" variant="outline" className="flex-1">
|
||||
Message
|
||||
</Button> */}
|
||||
</div>
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -91,9 +91,8 @@ export default function AppLayout({
|
||||
|
||||
<footer className="mt-auto pb-3 px-3">
|
||||
<DMItem
|
||||
name={app.profile?.display_name || "Loading.."}
|
||||
profile={app.profile}
|
||||
id={app.profile?.id || "me"}
|
||||
avatar={app.profile?.avatar_url || ""}
|
||||
status="online"
|
||||
app={app}
|
||||
settings
|
||||
|
||||
@@ -1,24 +1,23 @@
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
import ProfilePicture from "../ProfilePicture";
|
||||
import ProfilePreview from "../ProfilePicture";
|
||||
import SettingsDialog from "../settings/SettingsDialog";
|
||||
import App from "@/types/app";
|
||||
import { ProfileSettings } from "@/types/settings";
|
||||
import { UserProfile } from "@/hooks/get-user";
|
||||
|
||||
export default function DMItem({
|
||||
name,
|
||||
id,
|
||||
avatar,
|
||||
status,
|
||||
settings,
|
||||
app,
|
||||
profile,
|
||||
id,
|
||||
}: {
|
||||
name: string;
|
||||
id: string;
|
||||
avatar: string;
|
||||
status: string;
|
||||
profile?: UserProfile | null;
|
||||
settings?: boolean;
|
||||
id: string;
|
||||
status: string;
|
||||
app: App;
|
||||
}) {
|
||||
return (
|
||||
@@ -26,11 +25,15 @@ export default function DMItem({
|
||||
href={settings ? "" : `/chat/${id}`}
|
||||
className="p-2 flex items-center gap-2 cursor-pointer hover:bg-accent rounded-md"
|
||||
>
|
||||
<ProfilePicture name={name} url={avatar} />
|
||||
<div className="flex flex-col">
|
||||
<span className="text-sm font-medium">{name}</span>
|
||||
<span className="text-xs text-muted-foreground">{status}</span>
|
||||
</div>
|
||||
{profile && (
|
||||
<>
|
||||
<ProfilePreview profile={profile} />
|
||||
<div className="flex flex-col">
|
||||
<span className="text-sm font-medium">{profile.display_name}</span>
|
||||
<span className="text-xs text-muted-foreground">{status}</span>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
{settings && (
|
||||
<SettingsDialog
|
||||
className="ml-auto w-7 h-7 p-0 flex items-center justify-center"
|
||||
|
||||
@@ -65,9 +65,8 @@ export default function SidebarDMs({ app }: { app: App }) {
|
||||
{dms.map((user) => (
|
||||
<DMItem
|
||||
key={user.id}
|
||||
name={user.display_name}
|
||||
profile={user}
|
||||
id={user.id}
|
||||
avatar={user.avatar_url}
|
||||
status="online"
|
||||
app={app}
|
||||
/>
|
||||
|
||||
@@ -18,7 +18,7 @@ import { Label } from "../ui/label";
|
||||
import { toast } from "sonner";
|
||||
import { useState } from "react";
|
||||
import App from "@/types/app";
|
||||
import ProfilePicture from "../ProfilePicture";
|
||||
import ProfilePreview, { ProfileImage } from "../ProfilePicture";
|
||||
import SettingsDialog from "../settings/SettingsDialog";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { getServerById } from "@/actions/get-server";
|
||||
@@ -52,7 +52,7 @@ export default function SidebarServers({ app }: { app: App }) {
|
||||
(srv, i) =>
|
||||
srv && (
|
||||
<Link href={`/server/${srv.id}`} key={i}>
|
||||
<ProfilePicture name={srv.name} url={srv.icon_url} />
|
||||
<ProfileImage name={srv.name} url={srv.icon_url} />
|
||||
</Link>
|
||||
)
|
||||
)}
|
||||
|
||||
@@ -16,7 +16,7 @@ import { format, isToday, isYesterday } from "date-fns";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import remarkGfm from "remark-gfm";
|
||||
import { UserProfile } from "@/hooks/get-user";
|
||||
import ProfilePicture from "../ProfilePicture";
|
||||
import ProfilePreview, { ProfileImage } from "../ProfilePicture";
|
||||
import App, { SetState } from "@/types/app";
|
||||
import { Textarea } from "../ui/textarea";
|
||||
import {
|
||||
@@ -60,10 +60,7 @@ function MessageContainer({
|
||||
<div className="flex flex-col gap-3 rounded-lg p-4 hover:bg-accent">
|
||||
<div className="flex gap-2">
|
||||
{/* <div className="w-8 h-8 rounded-full bg-gray-400" /> */}
|
||||
<ProfilePicture
|
||||
url={profile?.avatar_url}
|
||||
name={profile?.display_name || message.from}
|
||||
/>
|
||||
<ProfilePreview profile={profile || undefined} />
|
||||
<div className="flex flex-col flex-1">
|
||||
<span className="font-bold flex gap-1 items-center select-none">
|
||||
{profile?.display_name || message.from}
|
||||
@@ -379,7 +376,7 @@ export default function MessageBox({
|
||||
<ChevronLeftIcon className="w-5 h-5 my-auto md:hidden" />
|
||||
<span className="flex items-center gap-1.5">
|
||||
{channelIcon && (
|
||||
<ProfilePicture
|
||||
<ProfileImage
|
||||
name={channelName}
|
||||
url={channelIcon}
|
||||
className="size-7"
|
||||
|
||||
@@ -42,7 +42,7 @@ export default function Settings({
|
||||
schema={CLIENT_SCHEMA}
|
||||
onSave={() => {
|
||||
setClientSettings(settings);
|
||||
router.refresh();
|
||||
setTimeout(() => router.refresh(), 300);
|
||||
}}
|
||||
/>
|
||||
</CardContent>
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import * as PopoverPrimitive from "@radix-ui/react-popover"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
|
||||
function Popover({
|
||||
...props
|
||||
}: React.ComponentProps<typeof PopoverPrimitive.Root>) {
|
||||
return <PopoverPrimitive.Root data-slot="popover" {...props} />
|
||||
}
|
||||
|
||||
function PopoverTrigger({
|
||||
...props
|
||||
}: React.ComponentProps<typeof PopoverPrimitive.Trigger>) {
|
||||
return <PopoverPrimitive.Trigger data-slot="popover-trigger" {...props} />
|
||||
}
|
||||
|
||||
function PopoverContent({
|
||||
className,
|
||||
align = "center",
|
||||
sideOffset = 4,
|
||||
...props
|
||||
}: React.ComponentProps<typeof PopoverPrimitive.Content>) {
|
||||
return (
|
||||
<PopoverPrimitive.Portal>
|
||||
<PopoverPrimitive.Content
|
||||
data-slot="popover-content"
|
||||
align={align}
|
||||
sideOffset={sideOffset}
|
||||
className={cn(
|
||||
"bg-popover text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-72 origin-(--radix-popover-content-transform-origin) rounded-md border p-4 shadow-md outline-hidden",
|
||||
className
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
</PopoverPrimitive.Portal>
|
||||
)
|
||||
}
|
||||
|
||||
function PopoverAnchor({
|
||||
...props
|
||||
}: React.ComponentProps<typeof PopoverPrimitive.Anchor>) {
|
||||
return <PopoverPrimitive.Anchor data-slot="popover-anchor" {...props} />
|
||||
}
|
||||
|
||||
export { Popover, PopoverTrigger, PopoverContent, PopoverAnchor }
|
||||
Reference in New Issue
Block a user