Skip to content

Commit

Permalink
Merge pull request #8 from YubaNeupane/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
YubaNeupane authored Sep 21, 2023
2 parents c3cbd82 + 0e36175 commit dd60c20
Show file tree
Hide file tree
Showing 26 changed files with 1,704 additions and 216 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { ChatHeader } from "@/components/chat/chat-header";
import { ChatInput } from "@/components/chat/chat-input";
import { ChatMessages } from "@/components/chat/chat-messages";
import { currentProfile } from "@/lib/current-profile";
import { db } from "@/lib/db";
import { redirectToSignIn } from "@clerk/nextjs";
Expand Down Expand Up @@ -43,7 +44,20 @@ const channelIdPage = async ({ params }: channelIdPageProps) => {
serverId={channel.serverId}
type="channel"
/>
<div className="flex-1">Future Messages</div>
<ChatMessages
member={member}
name={channel.name}
chatId={channel.id}
type="channel"
apiUrl="/api/messages"
socketUrl="/api/socket/messages"
socketQuery={{
channelId: channel.id,
serverId: channel.serverId,
}}
paramKey="channelId"
paramValue={channel.id}
/>
<ChatInput
name={channel.name}
type="channel"
Expand Down
80 changes: 80 additions & 0 deletions app/api/messages/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { currentProfile } from "@/lib/current-profile";
import { db } from "@/lib/db";
import { Message } from "@prisma/client";
import { NextResponse } from "next/server";

const MESSAGE_BATCH = 10;

export async function GET(req: Request) {
try {
const profile = await currentProfile();
const { searchParams } = new URL(req.url);

const cursor = searchParams.get("cursor");
const channelId = searchParams.get("channelId");

if (!profile) {
return new NextResponse("Unauthorized", { status: 401 });
}

if (!channelId) {
return new NextResponse("Channel ID missing", { status: 400 });
}

let messages: Message[] = [];

if (cursor) {
messages = await db.message.findMany({
take: MESSAGE_BATCH,
skip: 1,
cursor: {
id: cursor,
},
where: {
channelId,
},
include: {
member: {
include: {
profile: true,
},
},
},
orderBy: {
createdAt: "desc",
},
});
} else {
messages = await db.message.findMany({
take: MESSAGE_BATCH,
where: {
channelId,
},
include: {
member: {
include: {
profile: true,
},
},
},
orderBy: {
createdAt: "desc",
},
});
}

let nextCursor = null;

if (messages.length === MESSAGE_BATCH) {
nextCursor = messages[messages.length - 1].id;
}

return NextResponse.json({
items: messages,
nextCursor,
});
} catch (error) {
console.log("[MESSAGES_GET]", error);
return new NextResponse("Internal Error", { status: 500 });
}
}
3 changes: 2 additions & 1 deletion app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { cn } from "@/lib/utils";
import { ThemeProvider } from "@/components/providers/theme-provider";
import { ModalProvider } from "@/components/providers/modal-provider";
import { SocketProvider } from "@/components/providers/socket-provider";
import { QueryProvider } from "@/components/providers/query-provider";

const font = Open_Sans({ subsets: ["latin"] });

Expand All @@ -32,7 +33,7 @@ export default function RootLayout({
>
<SocketProvider>
<ModalProvider />
{children}
<QueryProvider>{children}</QueryProvider>
</SocketProvider>
</ThemeProvider>
</body>
Expand Down
2 changes: 1 addition & 1 deletion components/action-tooltip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export const ActionTooltip = ({
label,
children,
side,
align,
align = "start",
}: ActionTooltipProps) => {
return (
<TooltipProvider>
Expand Down
39 changes: 27 additions & 12 deletions components/chat/chat-input.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,38 @@
"use client";
import { useForm } from "react-hook-form";

import * as z from "zod";
import axios from "axios";
import qs from "query-string";
import { useForm } from "react-hook-form";
import { zodResolver } from "@hookform/resolvers/zod";
import { Plus } from "lucide-react";
import { useRouter } from "next/navigation";

import { Form, FormControl, FormField, FormItem } from "@/components/ui/form";
import { Input } from "@/components/ui/input";
import { Plus, SmileIcon } from "lucide-react";
import { useModal } from "@/hooks/use-modal-store";
import { EmojiPicker } from "@/components/emoji-picker";

interface ChatInputProps {
apiUrl: string;
query: Record<string, any>;
name: string;
type: "channel" | "conversation";
type: "conversation" | "channel";
}

const formSchema = z.object({
content: z.string().min(1),
});

export const ChatInput = ({ apiUrl, query, name, type }: ChatInputProps) => {
const { onOpen } = useModal();
const router = useRouter();

const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
defaultValues: {
content: "",
},
resolver: zodResolver(formSchema),
});

const isLoading = form.formState.isSubmitting;
Expand All @@ -36,9 +43,13 @@ export const ChatInput = ({ apiUrl, query, name, type }: ChatInputProps) => {
url: apiUrl,
query,
});

await axios.post(url, values);
} catch (e) {
console.log(e);

form.reset();
router.refresh();
} catch (error) {
console.log(error);
}
};

Expand All @@ -53,22 +64,26 @@ export const ChatInput = ({ apiUrl, query, name, type }: ChatInputProps) => {
<FormControl>
<div className="relative p-4 pb-6">
<button
typeof="button"
onClick={() => {}}
type="button"
onClick={() => onOpen("messageFile", { apiUrl, query })}
className="absolute top-7 left-8 h-[24px] w-[24px] bg-zinc-500 dark:bg-zinc-400 hover:bg-zinc-600 dark:hover:bg-zinc-300 transition rounded-full p-1 flex items-center justify-center"
>
<Plus className="text-white dark:text-[#313338]" />
</button>
<Input
disabled={isLoading}
{...field}
className="py-6 border-0 border-none px-14 bg-zinc-200/90 dark:bg-zinc-700/75 focus-visible:ring-0 focus-visible:ring-offset-0 text-zinc-600 dark:text-zinc-200"
placeholder={`Message ${
type === "conversation" ? name : `#${name}`
type === "conversation" ? name : "#" + name
}`}
className="py-6 border-0 border-none px-14 bg-zinc-200/90 dark:bg-zinc-700/75 focus-visible:ring-0 focus-visible:ring-offset-0 text-zinc-600 dark:text-zinc-200"
{...field}
/>
<div className="absolute top-7 right-8">
<SmileIcon />
<EmojiPicker
onChange={(emoji: string) =>
field.onChange(`${field.value} ${emoji}`)
}
/>
</div>
</div>
</FormControl>
Expand Down
Loading

1 comment on commit dd60c20

@vercel
Copy link

@vercel vercel bot commented on dd60c20 Sep 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

discord-clone – ./

discord-clone-git-main-yubaneupane.vercel.app
discord-clone-yubaneupane.vercel.app

Please sign in to comment.