Skip to content

Commit

Permalink
Merge pull request #6 from YubaNeupane/dev
Browse files Browse the repository at this point in the history
Added chat with user UI
  • Loading branch information
YubaNeupane authored Sep 18, 2023
2 parents f6b99a1 + c146aa1 commit 5cd6a54
Show file tree
Hide file tree
Showing 14 changed files with 533 additions and 31 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { ChatHeader } from "@/components/chat/chat-header";
import { currentProfile } from "@/lib/current-profile";
import { db } from "@/lib/db";
import { redirectToSignIn } from "@clerk/nextjs";
import { redirect } from "next/navigation";

interface channelIdPageProps {
params: {
serverId: string;
channelId: string;
};
}

const channelIdPage = async ({ params }: channelIdPageProps) => {
const profile = await currentProfile();

if (!profile) {
return redirectToSignIn();
}

const channel = await db.channel.findUnique({
where: {
id: params.channelId,
},
});

const member = await db.member.findFirst({
where: {
serverId: params.serverId,
profileId: profile.id,
},
});

if (!channel || !member) {
return redirect("/");
}

return (
<div className="bg-white dark:bg-[#313338] flex flex-col h-full">
<ChatHeader
name={channel.name}
serverId={channel.serverId}
type="channel"
/>
</div>
);
};

export default channelIdPage;
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { ChatHeader } from "@/components/chat/chat-header";
import { getOrCreateConversation } from "@/lib/conversation";
import { currentProfile } from "@/lib/current-profile";
import { db } from "@/lib/db";
import { redirectToSignIn } from "@clerk/nextjs";
import { redirect } from "next/navigation";

interface MemberIdPageProps {
params: {
memberId: string;
serverId: string;
};
}

const MemberIdPage = async ({ params }: MemberIdPageProps) => {
const profile = await currentProfile();

if (!profile) {
return redirectToSignIn();
}

const currentMember = await db.member.findFirst({
where: {
serverId: params.serverId,
profileId: profile.id,
},
include: {
profile: true,
},
});

if (!currentMember) {
return redirect("/");
}

const conversation = await getOrCreateConversation(
currentMember.id,
params.memberId
);

if (!conversation) {
return redirect(`/server/${params.serverId}`);
}

const { memberOne, memberTwo } = conversation;

const otherMember =
memberOne.profileId === profile.id ? memberTwo : memberOne;

return (
<div className="bg-white dark:bg-[#313338] flex flex-col h-full drop-shadow-sm">
<ChatHeader
imageUrl={otherMember?.profile.imageUrl}
name={otherMember?.profile.name}
serverId={params.serverId}
type="conversation"
/>
Memeber id page
</div>
);
};

export default MemberIdPage;
46 changes: 44 additions & 2 deletions app/(main)/(routes)/server/[serverId]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,47 @@
const ServerIdPage = () => {
return <div>Server ID Page</div>;
import { currentProfile } from "@/lib/current-profile";
import { db } from "@/lib/db";
import { redirectToSignIn } from "@clerk/nextjs";
import { redirect } from "next/navigation";

interface ServerIdPageProps {
params: {
serverId: string;
};
}

const ServerIdPage = async ({ params }: ServerIdPageProps) => {
const profile = await currentProfile();

if (!profile) return redirectToSignIn();

const server = await db.server.findUnique({
where: {
id: params.serverId,
members: {
some: {
profileId: profile.id,
},
},
},
include: {
channels: {
where: {
name: "general",
},
orderBy: {
createdAt: "asc",
},
},
},
});

const initialChannel = server?.channels[0];

if (initialChannel?.name !== "general") {
return null;
}

return redirect(`/server/${params.serverId}/channels/${initialChannel?.id}`);
};

export default ServerIdPage;
30 changes: 30 additions & 0 deletions components/chat/chat-header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Hash, Menu } from "lucide-react";
import { MobileToggle } from "@/components/mobile-toggle";
import { UserAvatar } from "@/components/user-avatar";

interface ChatHeaderProps {
serverId: string;
name: string;
type: "channel" | "conversation";
imageUrl?: string;
}

export const ChatHeader = ({
serverId,
name,
type,
imageUrl,
}: ChatHeaderProps) => {
return (
<div className="flex items-center h-12 px-3 font-semibold border-b-2 text-md border-neutral-200 dark:border-neutral-800 drop-shadow-sm">
<MobileToggle serverId={serverId} />
{type === "channel" && (
<Hash className="w-5 h-5 mr-2 text-zinc-500 dark:text-zinc-400" />
)}
{type === "conversation" && (
<UserAvatar src={imageUrl} className="w-8 h-8 mr-2 md:h-8 md:w-8" />
)}
<p className="font-semibold text-black text-md dark:text-white">{name}</p>
</div>
);
};
24 changes: 24 additions & 0 deletions components/mobile-toggle.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { MenuIcon } from "lucide-react";

import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet";
import { Button } from "@/components/ui/button";
import NavigationSideBar from "@/components/navigation/navigation-sidebar";
import { ServerSidebar } from "@/components/server/server-sidebar";

export const MobileToggle = ({ serverId }: { serverId: string }) => {
return (
<Sheet>
<SheetTrigger asChild>
<Button variant="ghost" size="icon" className="md:hidden">
<MenuIcon />
</Button>
</SheetTrigger>
<SheetContent side="left" className="flex gap-0 p-0">
<div className="w=[72px]">
<NavigationSideBar />
</div>
<ServerSidebar serverId={serverId} />
</SheetContent>
</Sheet>
);
};
4 changes: 1 addition & 3 deletions components/navigation/navigation-action.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Plus } from "lucide-react";
import { ActionTooltip } from "@/components/action-tooltip";
import { useModal } from "@/hooks/use-modal-store";

const NavigationAction = () => {
export const NavigationAction = () => {
const { onOpen } = useModal();

return (
Expand All @@ -25,5 +25,3 @@ const NavigationAction = () => {
</div>
);
};

export default NavigationAction;
3 changes: 2 additions & 1 deletion components/navigation/navigation-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import Image from "next/image";
import { useParams, useRouter } from "next/navigation";

import { cn } from "@/lib/utils";
import { ActionTooltip } from "@/components/action-tooltip";

Expand Down Expand Up @@ -36,7 +37,7 @@ export const NavigationItem = ({ id, imageUrl, name }: NavigationItemProps) => {
"bg-primary/10 text-primary rounded-[16px]"
)}
>
<Image fill src={imageUrl} alt="Server" />
<Image fill src={imageUrl} alt="Channel" />
</div>
</button>
</ActionTooltip>
Expand Down
4 changes: 2 additions & 2 deletions components/navigation/navigation-sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { UserButton } from "@clerk/nextjs";

import { currentProfile } from "@/lib/current-profile";
import { db } from "@/lib/db";
import NavigationAction from "./navigation-action";
import { NavigationAction } from "./navigation-action";
import { Separator } from "@/components/ui/separator";
import { ScrollArea } from "@/components/ui/scroll-area";
import { NavigationItem } from "@/components/navigation/navigation-item";
Expand All @@ -25,7 +25,7 @@ const NavigationSideBar = async () => {
});

return (
<div className="flex flex-col items-center h-full space-y-4 text-primary w-full dark:bg-[#1E1F22] py-3 bg-[#E3E5E8]">
<div className="flex flex-col items-center h-full space-y-4 text-primary w-full dark:bg-[#1E1F22] py-3">
<NavigationAction />
<Separator className="h-[2px] bg-zinc-300 dark:bg-zine-700 rounded-md w-10 mx-auto" />
<ScrollArea className="flex-1 w-full">
Expand Down
28 changes: 19 additions & 9 deletions components/server/server-channel.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
"use client";

import { cn } from "@/lib/utils";
import { Channel, ChannelType, MemberRole, Server } from "@prisma/client";
import { Edit, Hash, Lock, Mic, Trash, Video } from "lucide-react";
import { useParams, useRouter } from "next/navigation";
import { ActionTooltip } from "../action-tooltip";
import { useModal } from "@/hooks/use-modal-store";

import { cn } from "@/lib/utils";
import { ActionTooltip } from "@/components/action-tooltip";
import { ModalType, useModal } from "@/hooks/use-modal-store";

interface ServerChannelProps {
channel: Channel;
Expand All @@ -30,11 +31,20 @@ export const ServerChannel = ({

const Icon = iconMap[channel.type];

const onClick = () => {
router.push(`/server/${params?.serverId}/channels/${channel.id}`);
};

const onAction = (e: React.MouseEvent, action: ModalType) => {
e.stopPropagation();
onOpen(action, { channel, server });
};

return (
<button
onClick={() => {}}
onClick={onClick}
className={cn(
"group px-2 py-2 rounded-md flex items-center gap-2 w-full hover:bg-zinc-700/10 dark:hover:bg-zinc-700/50 transition mb-1",
"group px-2 py-2 rounded-md flex items-center gap-x-2 w-full hover:bg-zinc-700/10 dark:hover:bg-zinc-700/50 transition mb-1",
params?.channelId === channel.id && "bg-zinc-700/20 dark:bg-zinc-700"
)}
>
Expand All @@ -50,15 +60,15 @@ export const ServerChannel = ({
</p>
{channel.name !== "general" && role !== MemberRole.GUEST && (
<div className="flex items-center ml-auto gap-x-2">
<ActionTooltip label="Edit" align="center">
<ActionTooltip label="Edit">
<Edit
onClick={() => onOpen("editChannel", { server, channel })}
onClick={(e) => onAction(e, "editChannel")}
className="hidden w-4 h-4 transition group-hover:block text-zinc-500 hover:text-zinc-600 dark:text-zinc-400 dark:hover:text-zinc-300"
/>
</ActionTooltip>
<ActionTooltip label="Delete" align="center">
<ActionTooltip label="Delete">
<Trash
onClick={() => onOpen("deleteChannel", { server, channel })}
onClick={(e) => onAction(e, "deleteChannel")}
className="hidden w-4 h-4 transition group-hover:block text-zinc-500 hover:text-zinc-600 dark:text-zinc-400 dark:hover:text-zinc-300"
/>
</ActionTooltip>
Expand Down
6 changes: 5 additions & 1 deletion components/server/server-member.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,13 @@ export const ServerMember = ({ member, server }: ServerMemberProps) => {

const icon = roleIconMap[member.role];

const onClick = () => {
router.push(`/server/${params?.serverId}/conversations/${member.id}`);
};

return (
<button
onClick={() => {}}
onClick={onClick}
className={cn(
"group px-2 py-2 rounded-md flex items-center gap-x-2 w-full hover:bg-zinc-700/10 dark:hover:bg-zinc-700/50 transition mb-1",
params?.memberId === member.id && "bg-zinc-700/20 dark:bg-zinc-700"
Expand Down
Loading

0 comments on commit 5cd6a54

Please sign in to comment.