Skip to content

Commit

Permalink
message screen setup
Browse files Browse the repository at this point in the history
  • Loading branch information
17coincooker committed Sep 14, 2023
1 parent ce540c6 commit df0afad
Show file tree
Hide file tree
Showing 8 changed files with 243 additions and 0 deletions.
31 changes: 31 additions & 0 deletions app/actions/getConversationById.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import prisma from '@/app/libs/prismadb';
import getCurrentUser from './getCurrentUser';

const getConversationById = async (conversationId: string) => {
try {
const currentUser = await getCurrentUser();

if (!currentUser) return null;

const conversation = await prisma.conversation.findUnique({
where: {
id: conversationId,
},
include: {
users: {
where: {
id: {
not: currentUser.id,
},
},
},
},
});

return conversation;
} catch (error: any) {
return null;
}
};

export default getConversationById;
24 changes: 24 additions & 0 deletions app/actions/getMessages.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import prisma from '@/app/libs/prismadb';

const getMessages = async (conversationId: string) => {
try {
const messages = await prisma.message.findMany({
where: {
conversationId,
},
include: {
sender: true,
seen: true,
},
orderBy: {
createdAt: 'asc',
},
});

return messages;
} catch (error: any) {
return [];
}
};

export default getMessages;
6 changes: 6 additions & 0 deletions app/conversations/[conversationId]/components/Body.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
'use client';

const Body = () => {
return <div className="flex-1 overflow-y-auto">Body</div>;
};
export default Body;
55 changes: 55 additions & 0 deletions app/conversations/[conversationId]/components/Form.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
'use client';

import useConversation from '@/app/hooks/useConversation';
import axios from 'axios';
import { FieldValues, SubmitHandler, useForm } from 'react-hook-form';
import { HiPhoto, HiPaperAirplane } from 'react-icons/hi2';
import MessageInput from './MessageInput';

const Form = () => {
const { conversationId } = useConversation();

const {
register,
handleSubmit,
setValue,
formState: { errors },
} = useForm<FieldValues>({
defaultValues: {
message: '',
},
});

const onSubmit: SubmitHandler<FieldValues> = (data) => {
setValue('message', '', { shouldValidate: false });
axios.post(`/api/messages`, {
...data,
conversationId,
});
};

return (
<div className="py-4 px-4 bg-white border-t flex items-center gap-2 lg:gap-4 w-full">
<HiPhoto size={30} className="text-sky-500" />
<form
onSubmit={handleSubmit(onSubmit)}
className="flex items-center gap-2 lg:gap-4 w-full"
>
<MessageInput
id="message"
register={register}
errors={errors}
required
placeholder="Type a message..."
/>
<button
type="submit"
className="rounded-full p-2 bg-sky-500 cursor-pointer hover:bg-sky-600 transition"
>
<HiPaperAirplane size={20} className="text-white" />
</button>
</form>
</div>
);
};
export default Form;
54 changes: 54 additions & 0 deletions app/conversations/[conversationId]/components/Header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
'use client';

import Avatar from '@/app/components/Avatar';
import useOtherUser from '@/app/hooks/useOtherUser';
import { Conversation, User } from '@prisma/client';
import Link from 'next/link';
import { useMemo } from 'react';
import { HiChevronLeft } from 'react-icons/hi';
import { HiEllipsisHorizontal } from 'react-icons/hi2';

interface HeaderProps {
conversation: Conversation & {
users: User[];
};
}

const Header: React.FC<HeaderProps> = ({ conversation }) => {
const otherUser = useOtherUser(conversation);

const statusText = useMemo(() => {
if (conversation.isGroup) {
return `${conversation.users.length} members`;
}

return 'Active';
}, []);

return (
<div className="bg-white w-full flex border-b-[1px] sm:px-4 py-3 px-4 lg:px-6 justify-between items-center shadow-sm">
<div className="flex gap-3 items-center">
<Link
className="lg:hidden block text-sky-500 hover:text-sky-600 transition cursor-pointer"
href="/conversations"
>
<HiChevronLeft size={32} />
</Link>
<Avatar user={otherUser} />
<div className="flex flex-col">
<div>{conversation.name || otherUser?.name || otherUser?.email}</div>
<div className="text-sm font-light text-neutral-500">
{statusText}
</div>
</div>
</div>

<HiEllipsisHorizontal
className="text-sky-500 cursor-pointer hover:text-sky-600 transition"
size={32}
onClick={() => {}}
/>
</div>
);
};
export default Header;
35 changes: 35 additions & 0 deletions app/conversations/[conversationId]/components/MessageInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
'use client';

import { FieldErrors, FieldValues, UseFormRegister } from 'react-hook-form';

interface MessageInputProps {
id: string;
placeholder?: string;
type?: string;
required?: boolean;
register: UseFormRegister<FieldValues>;
errors: FieldErrors;
}

const MessageInput: React.FC<MessageInputProps> = ({
id,
placeholder,
type,
required,
register,
errors,
}) => {
return (
<div className="relative w-full">
<input
id={id}
type={type}
autoComplete={id}
{...register(id, { required })}
placeholder={placeholder}
className="text-black font-light py-2 px-4 bg-neutral-100 w-full rounded-full focus:outline-none"
/>
</div>
);
};
export default MessageInput;
37 changes: 37 additions & 0 deletions app/conversations/[conversationId]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import getConversationById from '@/app/actions/getConversationById';
import getMessages from '@/app/actions/getMessages';
import EmptyState from '@/app/components/EmptyState';
import Header from './components/Header';
import Body from './components/Body';
import Form from './components/Form';

interface IParams {
conversationId: string;
}

const ConversationId = async ({ params }: { params: IParams }) => {
const conversation = await getConversationById(params.conversationId);
const messages = await getMessages(params.conversationId);

if (!conversation) {
return (
<div className="lg:pl-80 h-full">
<div className="h-full flex flex-col">
<EmptyState />
</div>
</div>
);
}

return (
<div className="lg:pl-80 h-full">
<div className="h-full flex flex-col">
<Header conversation={conversation} />
<Body />
<Form />
</div>
</div>
);
};

export default ConversationId;
1 change: 1 addition & 0 deletions notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
- `app/(site)/page.tsx` - Register/Login page
- `app/users/page.tsx` - Users page
- `app/conversations/page.tsx` - Conversations page
- `app/conversations/[id]/page.tsx` - Single Conversation page

## Bookmarks

Expand Down

0 comments on commit df0afad

Please sign in to comment.