From c91a00dc447f3f32a0165a47e0cf9f9ff11694d8 Mon Sep 17 00:00:00 2001 From: Sinan Date: Mon, 23 Sep 2024 09:24:12 +0530 Subject: [PATCH] Chat Page Design Added --- .../(landing-pages)/chats/@chat/[id]/page.tsx | 68 +++++++++++++++++++ .../(landing-pages)/chats/@chat/default.tsx | 7 ++ .../chats/@chatList/default.tsx | 4 ++ .../(landing-pages)/chats/@chatList/page.tsx | 58 ++++++++++++++++ client/app/(landing-pages)/chats/layout.tsx | 27 ++++++++ client/app/(landing-pages)/chats/page.tsx | 5 ++ client/components/layout/Footer.tsx | 2 +- client/components/ui/avatar.tsx | 50 ++++++++++++++ client/constants/index.ts | 2 +- client/package-lock.json | 27 ++++++++ client/package.json | 1 + .../icons/emoji/\342\234\217\357\270\217.svg" | 1 + client/styles/globals.css | 2 +- 13 files changed, 251 insertions(+), 3 deletions(-) create mode 100644 client/app/(landing-pages)/chats/@chat/[id]/page.tsx create mode 100644 client/app/(landing-pages)/chats/@chat/default.tsx create mode 100644 client/app/(landing-pages)/chats/@chatList/default.tsx create mode 100644 client/app/(landing-pages)/chats/@chatList/page.tsx create mode 100644 client/app/(landing-pages)/chats/layout.tsx create mode 100644 client/app/(landing-pages)/chats/page.tsx create mode 100644 client/components/ui/avatar.tsx create mode 100644 "client/public/assets/icons/emoji/\342\234\217\357\270\217.svg" diff --git a/client/app/(landing-pages)/chats/@chat/[id]/page.tsx b/client/app/(landing-pages)/chats/@chat/[id]/page.tsx new file mode 100644 index 00000000..866048a7 --- /dev/null +++ b/client/app/(landing-pages)/chats/@chat/[id]/page.tsx @@ -0,0 +1,68 @@ +'use client' + +import { ScrollArea } from "@/components/ui/scroll-area" +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" +import { useParams, useRouter } from "next/navigation" +import { ButtonV2 } from "@/components/common/ButtonV2" +import { Input } from "@/components/ui/input" +import { useState } from "react" +import { ArrowLeft } from "lucide-react" + +const ChatSection = () => { + const { id: userId } = useParams() + const [message, setMessage] = useState("") + const router = useRouter() + + if (!userId) { + return
User not found
+ } + + const handleSendMessage = () => { + console.log("Sending message:", message) + setMessage("") + } + + return ( +
+
+
+ + + + {userId} + +

Chat with User {userId}

+
+
+ +
+
+
+

Hello, how are you?

+
+
+
+
+

I'm fine, thanks for asking!

+
+
+
+
+
+
+ setMessage(e.target.value)} + /> + Send +
+
+
+ ) +} + +export default ChatSection \ No newline at end of file diff --git a/client/app/(landing-pages)/chats/@chat/default.tsx b/client/app/(landing-pages)/chats/@chat/default.tsx new file mode 100644 index 00000000..d02d62f1 --- /dev/null +++ b/client/app/(landing-pages)/chats/@chat/default.tsx @@ -0,0 +1,7 @@ +export default function ChatDefault() { + return ( +
+

Select a chat to start messaging.

+
+ ); +} diff --git a/client/app/(landing-pages)/chats/@chatList/default.tsx b/client/app/(landing-pages)/chats/@chatList/default.tsx new file mode 100644 index 00000000..edc2797d --- /dev/null +++ b/client/app/(landing-pages)/chats/@chatList/default.tsx @@ -0,0 +1,4 @@ +import ChatUserList from './page' + +export default () => + diff --git a/client/app/(landing-pages)/chats/@chatList/page.tsx b/client/app/(landing-pages)/chats/@chatList/page.tsx new file mode 100644 index 00000000..dd3e70c9 --- /dev/null +++ b/client/app/(landing-pages)/chats/@chatList/page.tsx @@ -0,0 +1,58 @@ +'use client' + +import { useState } from "react" +import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" +import { ScrollArea } from "@/components/ui/scroll-area" +import Link from "next/link" +import { MoreVertical } from "lucide-react" + +interface Contact { + id: number + name: string + lastMessage: string + avatar: string + lastSeen: string +} + +export default function ChatList() { + const [selectedId, setSelectedId] = useState(null) + + const contacts: Contact[] = [ + { id: 1, name: "Alice Johnson", lastMessage: "Hey, how are you?", avatar: "/assets/icons/circle-user.svg", lastSeen: "2m" }, + { id: 2, name: "Bob Smith", lastMessage: "Let's catch up later.", avatar: "/assets/icons/circle-user.svg", lastSeen: "1h" }, + { id: 3, name: "Charlie Brown", lastMessage: "Got the files?", avatar: "/assets/icons/circle-user.svg", lastSeen: "3h" }, + { id: 4, name: "Diana Prince", lastMessage: "Meeting at 3 PM", avatar: "/assets/icons/circle-user.svg", lastSeen: "5h" }, + { id: 5, name: "Ethan Hunt", lastMessage: "Mission accomplished!", avatar: "/assets/icons/circle-user.svg", lastSeen: "1d" }, + ] + + return ( +
+ +
+ {contacts.map(({ id, name, lastMessage, avatar, lastSeen }) => ( + +
setSelectedId(id)} + > + + + {name.charAt(0)} + +
+
+

{name}

+ {lastSeen} +
+

{lastMessage}

+
+
+ + ))} +
+
+
+ ) +} \ No newline at end of file diff --git a/client/app/(landing-pages)/chats/layout.tsx b/client/app/(landing-pages)/chats/layout.tsx new file mode 100644 index 00000000..3ff15c77 --- /dev/null +++ b/client/app/(landing-pages)/chats/layout.tsx @@ -0,0 +1,27 @@ +import { ReactNode } from 'react'; + +export default function ChatLayout({ + chatList, + chat, +}: { + chatList: ReactNode; + chat: ReactNode; +}) { + return ( +
+ +
+ {chat || ( +
+
+

Welcome to Your Messages

+

Select a chat to start messaging or create a new one.

+
+
+ )} +
+
+ ); +} \ No newline at end of file diff --git a/client/app/(landing-pages)/chats/page.tsx b/client/app/(landing-pages)/chats/page.tsx new file mode 100644 index 00000000..611891fe --- /dev/null +++ b/client/app/(landing-pages)/chats/page.tsx @@ -0,0 +1,5 @@ +import ChatUserList from './@chatList/page'; + +export default function ChatsPage() { + return ; +} \ No newline at end of file diff --git a/client/components/layout/Footer.tsx b/client/components/layout/Footer.tsx index 8b5cd0a7..8b035955 100644 --- a/client/components/layout/Footer.tsx +++ b/client/components/layout/Footer.tsx @@ -4,7 +4,7 @@ import { usePathname } from "next/navigation"; const Footer = () => { const path = usePathname(); - if (path.includes("signup") || path.includes("signin") || path.includes("admin") || path.includes("doctor")) { + if (path.includes("signup") || path.includes("signin") || path.includes("admin") || path.includes("doctor") || path.includes("chats")) { return null; } return ( diff --git a/client/components/ui/avatar.tsx b/client/components/ui/avatar.tsx new file mode 100644 index 00000000..51e507ba --- /dev/null +++ b/client/components/ui/avatar.tsx @@ -0,0 +1,50 @@ +"use client" + +import * as React from "react" +import * as AvatarPrimitive from "@radix-ui/react-avatar" + +import { cn } from "@/lib/utils" + +const Avatar = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +Avatar.displayName = AvatarPrimitive.Root.displayName + +const AvatarImage = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AvatarImage.displayName = AvatarPrimitive.Image.displayName + +const AvatarFallback = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName + +export { Avatar, AvatarImage, AvatarFallback } diff --git a/client/constants/index.ts b/client/constants/index.ts index 6755ec63..f9bfc19a 100644 --- a/client/constants/index.ts +++ b/client/constants/index.ts @@ -39,7 +39,7 @@ export const DoctorsSidebarLinks: NavLinkType[] = [ export const NavLinks: NavLinkType[] = [ { href: "/", label: "Home" }, { href: "/clinicians", label: "Clinicians" }, - { href: "/products", label: "Products" }, + { href: "/chats", label: "Chats" }, { href: "/services", label: "Services" }, { href: "/about", label: "About" }, ]; diff --git a/client/package-lock.json b/client/package-lock.json index 669fd446..9aea9ed1 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -11,6 +11,7 @@ "@hookform/resolvers": "^3.9.0", "@radix-ui/react-accordion": "^1.2.0", "@radix-ui/react-alert-dialog": "^1.1.1", + "@radix-ui/react-avatar": "^1.1.0", "@radix-ui/react-checkbox": "^1.1.1", "@radix-ui/react-dialog": "^1.1.1", "@radix-ui/react-dropdown-menu": "^2.1.1", @@ -1291,6 +1292,32 @@ } } }, + "node_modules/@radix-ui/react-avatar": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-avatar/-/react-avatar-1.1.0.tgz", + "integrity": "sha512-Q/PbuSMk/vyAd/UoIShVGZ7StHHeRFYU7wXmi5GV+8cLXflZAEpHL/F697H1klrzxKXNtZ97vWiC0q3RKUH8UA==", + "license": "MIT", + "dependencies": { + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, "node_modules/@radix-ui/react-checkbox": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-checkbox/-/react-checkbox-1.1.1.tgz", diff --git a/client/package.json b/client/package.json index 03be4973..bde2bb98 100644 --- a/client/package.json +++ b/client/package.json @@ -14,6 +14,7 @@ "@hookform/resolvers": "^3.9.0", "@radix-ui/react-accordion": "^1.2.0", "@radix-ui/react-alert-dialog": "^1.1.1", + "@radix-ui/react-avatar": "^1.1.0", "@radix-ui/react-checkbox": "^1.1.1", "@radix-ui/react-dialog": "^1.1.1", "@radix-ui/react-dropdown-menu": "^2.1.1", diff --git "a/client/public/assets/icons/emoji/\342\234\217\357\270\217.svg" "b/client/public/assets/icons/emoji/\342\234\217\357\270\217.svg" new file mode 100644 index 00000000..42a957bf --- /dev/null +++ "b/client/public/assets/icons/emoji/\342\234\217\357\270\217.svg" @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/client/styles/globals.css b/client/styles/globals.css index 4cd6ffcc..988be7ec 100644 --- a/client/styles/globals.css +++ b/client/styles/globals.css @@ -39,7 +39,7 @@ @layer utilities { /* ===== UTILITIES */ .sidebar { - @apply remove-scrollbar w-full max-w-72 flex-col overflow-auto bg-black-800 px-7 py-10; + @apply remove-scrollbar w-full max-w-72 flex-col overflow-auto px-7 py-10; } .left-sidebar {