Skip to content

Commit

Permalink
Merge pull request #99 from BacPacNet/v2/message
Browse files Browse the repository at this point in the history
message-ui and api implemented
  • Loading branch information
bacpactech authored Oct 19, 2024
2 parents d84916c + 9dd6237 commit c4765a3
Show file tree
Hide file tree
Showing 19 changed files with 1,590 additions and 58 deletions.
49 changes: 49 additions & 0 deletions src/app/(withLayout)/messages/old_page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
'use client'
import MessageSideBar from '@/components/messages/MessageSideBar'
import UserMessageContainer from '@/components/messages/UserMessageContainer'
import { useUpdateMessageIsSeen } from '@/services/Messages'
import { useUniStore } from '@/store/store'
import { Chat } from '@/types/constants'
import React, { useEffect, useState } from 'react'

const ChatScreen = () => {
const [selectedChat, setSelectedChat] = useState<Chat | undefined>(undefined)

const { userData } = useUniStore()
const userName = selectedChat?.users?.find((item) => item?.userId._id !== userData.id)

const { mutate: updateIsSeen } = useUpdateMessageIsSeen()
const [isRequest, setIsRequest] = useState(true)

const updateMessageSeen = () => {
const isRead = selectedChat?.latestMessage?.readByUsers?.includes(userData.id || '')

if (!isRead && isRead !== undefined && selectedChat) {
updateIsSeen({ chatId: selectedChat?._id, messageId: selectedChat?.latestMessage?._id, data: { readByUserId: userData.id } })
}
}

useEffect(() => {
updateMessageSeen()
}, [selectedChat])

return (
<div className="p-8 flex justify-center h-[84.5vh]">
<div className="border-2 border-slate-500 w-4/5 rounded-lg flex">
<MessageSideBar setSelectedChat={setSelectedChat} selectedChat={selectedChat} isRequest={isRequest} setIsRequest={setIsRequest} />
{selectedChat?._id && (
<UserMessageContainer
chatId={selectedChat._id}
name={selectedChat.isGroupChat ? selectedChat.chatName : userName?.userId.firstName ?? 'Unknown'}
users={selectedChat?.users}
profileCover={selectedChat?.groupLogoImage ?? ''}
isRequest={isRequest}
isGroupChat={selectedChat?.isGroupChat}
/>
)}
</div>
</div>
)
}

export default ChatScreen
52 changes: 8 additions & 44 deletions src/app/(withLayout)/messages/page.tsx
Original file line number Diff line number Diff line change
@@ -1,49 +1,13 @@
'use client'
import MessageSideBar from '@/components/messages/MessageSideBar'
import UserMessageContainer from '@/components/messages/UserMessageContainer'
import { useUpdateMessageIsSeen } from '@/services/Messages'
import { useUniStore } from '@/store/store'
import { Chat } from '@/types/constants'
import React, { useEffect, useState } from 'react'

const ChatScreen = () => {
const [selectedChat, setSelectedChat] = useState<Chat | undefined>(undefined)

const { userData } = useUniStore()
const userName = selectedChat?.users?.find((item) => item?.userId._id !== userData.id)

const { mutate: updateIsSeen } = useUpdateMessageIsSeen()
const [isRequest, setIsRequest] = useState(true)

const updateMessageSeen = () => {
const isRead = selectedChat?.latestMessage?.readByUsers?.includes(userData.id || '')

if (!isRead && isRead !== undefined && selectedChat) {
updateIsSeen({ chatId: selectedChat?._id, messageId: selectedChat?.latestMessage?._id, data: { readByUserId: userData.id } })
}
}

useEffect(() => {
updateMessageSeen()
}, [selectedChat])
import MessageContainer from '@/components/organisms/MessageContainer'
import React from 'react'

const Message = () => {
return (
<div className="p-8 flex justify-center h-[84.5vh]">
<div className="border-2 border-slate-500 w-4/5 rounded-lg flex">
<MessageSideBar setSelectedChat={setSelectedChat} selectedChat={selectedChat} isRequest={isRequest} setIsRequest={setIsRequest} />
{selectedChat?._id && (
<UserMessageContainer
chatId={selectedChat._id}
name={selectedChat.isGroupChat ? selectedChat.chatName : userName?.userId.firstName ?? 'Unknown'}
users={selectedChat?.users}
profileCover={selectedChat?.groupLogoImage ?? ''}
isRequest={isRequest}
isGroupChat={selectedChat?.isGroupChat}
/>
)}
</div>
</div>
<>
{' '}
<MessageContainer />
</>
)
}

export default ChatScreen
export default Message
3 changes: 1 addition & 2 deletions src/components/atoms/LogoNavbar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ import avatar from '@assets/avatar.svg'
import { Skeleton } from '@/components/ui/Skeleton'
import { FaAngleDown, FaBell, FaRegUser } from 'react-icons/fa'
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/Popover'
import { TiMessages } from 'react-icons/ti'
import { BiSolidMessageSquareDetail } from 'react-icons/bi'

import { MdInfoOutline, MdOutlineLock, MdOutlineSettings } from 'react-icons/md'
import { PiChatsBold, PiChatTextBold, PiPaintBrushDuotone } from 'react-icons/pi'
import { HiCubeTransparent } from 'react-icons/hi'
Expand Down
2 changes: 1 addition & 1 deletion src/components/atoms/PostCardImagesGrid/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type props = {
}>
>
idx: number
type: PostType.Community | PostType.Timeline
type?: PostType.Community | PostType.Timeline
}

const DynamicImageContainer = ({ images, setImageCarasol }: props) => {
Expand Down
5 changes: 3 additions & 2 deletions src/components/atoms/PostImageSlider/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ import Image from 'next/image'
type prop = {
images: { imageUrl: string }[]
initialSlide: number | null
messageImage?: boolean
}

export default function PostImageSlider({ images, initialSlide }: prop) {
export default function PostImageSlider({ images, initialSlide, messageImage }: prop) {
return (
<div className="z-40 fixed w-[60%] top-1/4 h-3/6 ">
<div className={`z-40 fixed ${messageImage ? 'w-full h-[400px]' : 'w-[60%] h-3/6'} top-1/4 `}>
<Swiper
slidesPerView={1}
spaceBetween={30}
Expand Down
229 changes: 229 additions & 0 deletions src/components/molecules/CreateGroupChat/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,229 @@
'use client'
import InputBox from '@/components/atoms/Input/InputBox'
import SelectUsers from '@/components/communityUniversity/SelectUsers'
import { useCreateGroupChat, useGetUserFollowingAndFollowers } from '@/services/Messages'
import { replaceImage } from '@/services/uploadImage'
import Image from 'next/image'
import React, { useState } from 'react'
import { Controller, useForm } from 'react-hook-form'
import { FiCamera } from 'react-icons/fi'
import { IoClose } from 'react-icons/io5'
import { MdPersonAddAlt1 } from 'react-icons/md'
import { RxCross2 } from 'react-icons/rx'
import avatar from '@assets/avatar.svg'
import { FaUser } from 'react-icons/fa'
type Props = {
setShowCreateGroup: (value: boolean) => void
setShowOneToOne: (value: boolean) => void
}
type media = {
imageUrl: string
publicId: string
}
type User = {
_id: string
firstName: string
isOnline?: boolean
profile: {
profile_dp: media
_id: string
}
}
const CreateGroupChat = ({ setShowCreateGroup, setShowOneToOne }: Props) => {
const {
control,
handleSubmit,
getValues,
register: GroupChatRegister,
formState: { errors: GroupChatRegisterErr },
} = useForm({
defaultValues: {
inviteOption: 'public',
title: '',
description: '',
},
})

const [userPopUp, setUserPopUp] = useState(false)
const [groupLogoImage, setGroupLogoImage] = useState()
const [searchInput, setSearchInput] = useState('')
const [selectedUsers, setSelectedUsers] = useState<User[]>([])
const selectedUsersId = selectedUsers.map((item: any) => item._id)
const values = getValues()

const { mutate: createGroupChat } = useCreateGroupChat()

const onGroupChatSubmit = async (data: any) => {
let CoverImageData
if (groupLogoImage) {
const imagedata: any = await replaceImage(groupLogoImage, '')
CoverImageData = { groupLogo: { imageUrl: imagedata?.imageUrl, publicId: imagedata?.publicId } }
}
const dataTopush = {
groupLogo: CoverImageData?.groupLogo,
groupName: data.title,
groupDescription: data.description,
users: selectedUsersId,
}

createGroupChat(dataTopush)
}

const { data } = useGetUserFollowingAndFollowers(searchInput)
return (
<>
<div
onClick={() => setShowCreateGroup(false)}
className="fixed w-full h-full top-0 left-0 bg-[#f3f2ff] backdrop-blur-2xl opacity-50 z-30 "
></div>

{userPopUp && (
<>
<div className="fixed w-full h-screen top-0 left-0 bg-[#f3f2ff] backdrop-blur-xl opacity-50 z-30"></div>

<div className="fixed w-1/2 max-sm:w-11/12 z-50 min-h-[400px] top-[10%] left-1/3 bg-white flex flex-col items-center gap-6 shadow-lg px-10 py-6 rounded-lg">
<div className="flex justify-between w-full">
<h3>Add Group Members</h3>
<RxCross2 onClick={() => setUserPopUp(false)} size={24} color="#737373" />
</div>
{/* search */}
<div className="relative w-full">
<svg
xmlns="http://www.w3.org/2000/svg"
className="absolute top-0 bottom-0 w-6 h-6 my-auto text-gray-400 left-3"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" />
</svg>
<input
onChange={(e) => setSearchInput(e.target.value)}
value={searchInput}
type="text"
placeholder="Search users by name"
className="w-full pl-12 pr-3 py-2 text-gray-500 bg-transparent outline-none border border-neutral-300 rounded-2xl"
/>
</div>
<button onClick={() => setSelectedUsers(data?.user)} className="self-end bg-slate-200 p-2 text-xs rounded-xl shadow-sm">
Select All
</button>
{data?.user?.map((item: any) => (
<SelectUsers key={item._id} data={item} setSelectedUsers={setSelectedUsers} selectedUsers={selectedUsers} />
))}
</div>
</>
)}

<div className="fixed w-2/5 max-sm:w-11/12 z-40 top-[10%] left-1/3 bg-white flex flex-col items-center gap-6 shadow-lg px-6 pt-6 pb-10 rounded-lg">
<div className="flex justify-between w-full">
<h3 className="text-neutral-700 font-semibold text-[18px] font-inter">Create Chat Group</h3>
</div>
<form onSubmit={handleSubmit(onGroupChatSubmit)} className="w-full flex flex-col gap-6 relative">
<div className="flex gap-2 items-center justify-between ">
<div className={` border-2 border-neutral-200 bg-white flex items-center justify-center w-24 h-24 rounded-full`}>
{groupLogoImage && (
<Image
width={40}
height={40}
className="w-24 h-24 rounded-full absolute object-cover"
src={URL.createObjectURL(groupLogoImage)}
alt="groupLogo"
/>
)}
<input style={{ display: 'none' }} type="file" id="CreateGroupLogoImage" onChange={(e: any) => setGroupLogoImage(e.target.files[0])} />
<label htmlFor="CreateGroupLogoImage" className="flex flex-col items-center gap-2">
<FiCamera size={40} className="text-slate-400 z-30" />
</label>
</div>
<div className="relative w-8/12 flex flex-col">
<label htmlFor="name" className="font-medium text-xs">
Group Name
</label>
<InputBox
placeholder="title "
type="title"
{...GroupChatRegister('title', {
required: true,
})}
/>

{GroupChatRegisterErr.title && <span className="text-red-500 font-normal"> Please enter your Group Name!</span>}
</div>
</div>
<div className="relative w-full flex flex-col">
<label htmlFor="name" className="font-medium text-xs">
Group Description
</label>
<InputBox
placeholder="description "
type="description"
{...GroupChatRegister('description', {
required: true,
})}
/>

{GroupChatRegisterErr.description && <span className="text-red-500 font-normal"> Please enter your Group Name!</span>}
</div>
<div className="mt-5 flex flex-col gap-3">
<Controller
name="inviteOption"
control={control}
render={({ field }) => (
<>
<label className="flex items-center gap-3">
<input type="radio" {...field} value="public" checked={field.value === 'public'} className="w-[18px] h-[18px]" />
<p className="text-neutral-900 text-[12px] font-medium">Allow others to invite to the chat</p>
</label>
<label className="flex items-center gap-3">
<input type="radio" {...field} value="private" checked={field.value === 'private'} className="w-[18px] h-[18px]" />
<p className="text-neutral-900 text-[12px] font-medium">Only you can invite to the chat</p>
</label>
</>
)}
/>
</div>
<div className="relative w-full flex flex-col">
<label htmlFor="inviteFriends" className="font-medium text-xs">
Add Members
</label>
<div
onClick={() => setUserPopUp(true)}
className=" border pl-6 py-2 text-md rounded-lg border-gray-light font-normal w-full h-10 flex gap-2 items-center justify-end pe-4 drop-shadow-sm"
>
{' '}
<MdPersonAddAlt1 className="text-primary-500" />
</div>
<div className="flex flex-wrap mt-2">
{' '}
{selectedUsers.map((item: any) => (
<div
key={item._id}
className="bg-[#F3F2FF] py-[2px] px-[6px] text-[10px] text-primary-500 rounded-3xl h-5 flex items-center justify-center"
>
<p key={item.id}>{item.firstName}</p>
<button type="button" onClick={() => setSelectedUsers(selectedUsers.filter((currItem) => currItem._id !== item._id))}>
<IoClose className="w-3 h-3" />
</button>
</div>
))}
</div>
</div>
<button type="submit" className="w-64 mx-auto bg-primary-500 text-white px-4 py-2 rounded-lg">
Create New Chat
</button>
<p
className=" absolute -bottom-8 -left-4 cursor-pointer text-sm text-primary-500 bg-neutral-300 p-2 rounded-full"
onClick={() => {
setShowCreateGroup(false), setShowOneToOne(true)
}}
>
<FaUser />
</p>
</form>
</div>
</>
)
}

export default CreateGroupChat
Loading

0 comments on commit c4765a3

Please sign in to comment.