diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..7c1ae9c Binary files /dev/null and b/.DS_Store differ diff --git a/.github/.DS_Store b/.github/.DS_Store new file mode 100644 index 0000000..f0bb8b7 Binary files /dev/null and b/.github/.DS_Store differ diff --git a/backend/.DS_Store b/backend/.DS_Store new file mode 100644 index 0000000..3cf6c5b Binary files /dev/null and b/backend/.DS_Store differ diff --git a/backend/code/src/rooms/rooms.service.ts b/backend/code/src/rooms/rooms.service.ts index 80f8f8f..d19e14a 100644 --- a/backend/code/src/rooms/rooms.service.ts +++ b/backend/code/src/rooms/rooms.service.ts @@ -14,6 +14,7 @@ import { RoomSearchDto } from './dto/room-search.dto'; import * as bcrypt from 'bcrypt'; import { UpdateRoomDto } from './dto/update-room.dto'; import { RoomDataDto } from './dto/room-data.dto'; +import { PICTURE } from 'src/profile/dto/profile.dto'; @Injectable() export class RoomsService { @@ -380,7 +381,7 @@ export class RoomsService { if (!user) throw new UnauthorizedException('You are not a member of this room'); - return await this.prisma.roomMember.findMany({ + const members = await this.prisma.roomMember.findMany({ skip: offset, take: limit, where: { @@ -398,6 +399,18 @@ export class RoomsService { }, }, }); + return members.map((member) => { + const avatar: PICTURE = { + thumbnail: `https://res.cloudinary.com/trandandan/image/upload/c_thumb,h_48,w_48/${member.user.avatar}`, + medium: `https://res.cloudinary.com/trandandan/image/upload/c_thumb,h_72,w_72/${member.user.avatar}`, + large: `https://res.cloudinary.com/trandandan/image/upload/c_thumb,h_128,w_128/${member.user.avatar}`, + }; + return { + id: member.user.userId, + name: { first: member.user.firstName, last: member.user.lastName }, + avatar, + } + }); } async banMember(memberData: ChangeOwnerDto, userId: string) { @@ -480,16 +493,18 @@ export class RoomsService { name: true, type: true, ownerId: true, - members: { + ...(joined && {members: { where: { userId: userId, }, select: { is_admin: true, }, - }, + }}) }, }); + if (!joined) + return rooms; return rooms.map((room) => { const is_owner = room.ownerId === userId; return { diff --git a/frontend/.DS_Store b/frontend/.DS_Store new file mode 100644 index 0000000..6a67441 Binary files /dev/null and b/frontend/.DS_Store differ diff --git a/frontend/code/src/Api/base.tsx b/frontend/code/src/Api/base.tsx index 6af97ec..195a861 100644 --- a/frontend/code/src/Api/base.tsx +++ b/frontend/code/src/Api/base.tsx @@ -1,4 +1,4 @@ -import axios from 'axios'; +import axios from "axios"; const api = axios.create({ baseURL: `${process.env.REACT_APP_API_ENDPOINT}`, @@ -6,32 +6,29 @@ const api = axios.create({ withCredentials: true, headers: { "Cache-Control": "no-cache", - 'Content-Type': 'application/json', + "Content-Type": "application/json", }, }); let refreshAttempted = false; -const errorHandler = async (error:any) => { - +const errorHandler = async (error: any) => { if (error.response.status === 401) { - if (!refreshAttempted ) { + if (!refreshAttempted) { try { refreshAttempted = true; await api.get("auth/refresh"); return api.request(error.config); - } catch (refreshError) { - } + } catch (refreshError) {} } else { - refreshAttempted = false + refreshAttempted = false; } } - + return Promise.reject({ ...error }); }; api.interceptors.response.use( - (response) => response, (error) => errorHandler(error) ); diff --git a/frontend/code/src/Components/Chat/Components/Conversation.tsx b/frontend/code/src/Components/Chat/Components/Conversation.tsx index 592691b..c73cd01 100644 --- a/frontend/code/src/Components/Chat/Components/Conversation.tsx +++ b/frontend/code/src/Components/Chat/Components/Conversation.tsx @@ -9,11 +9,10 @@ import users, { } from "./tools/Assets"; import { ChatType, useChatStore } from "../Controllers/ChatControllers"; -import { - ChatPlaceHolder, - ConfirmationModal, -} from "./RoomChatHelpers"; +import { ChatPlaceHolder, ConfirmationModal } from "./RoomChatHelpers"; import { KeyboardEvent } from "react"; +import { leaveRoomCall } from "../Services/ChatServices"; +import toast from "react-hot-toast"; export interface ChatPaceHolderProps { username: string; @@ -84,6 +83,7 @@ export const ConversationHeader: React.FC = ({ }) => { const [MyUsers] = useState(users); + const ChatState = useChatStore((state) => state); const SelectedChat = useChatStore((state) => state.selectedChatID); const currentUser = MyUsers.find((user) => user.id === SelectedChat); @@ -91,17 +91,11 @@ export const ConversationHeader: React.FC = ({ const currentRoom = chatRooms.find((room) => room.id === SelectedChat); - const [isModalOpen, setIsModalOpen] = useState(false); + const toggleChatRooms = useChatStore((state) => state.toggleChatRooms); - // Function to open the modal - const openModal = () => { - setIsModalOpen(true); - }; + const [isModalOpen, setIsModalOpen] = useState(false); - // Function to handle the confirmation const handleConfirmation = () => { - // Perform your action when the user confirms (e.g., delete item) - // For this example, we'll just close the modal setIsModalOpen(false); }; @@ -109,6 +103,15 @@ export const ConversationHeader: React.FC = ({ <>
+
+ +
+
= ({

{selectedChatType === ChatType.Chat ? currentUser?.name + : currentRoom?.isOwner + ? currentRoom.name + " ♚" : currentRoom?.name}

{selectedChatType === ChatType.Chat ? ( @@ -178,7 +183,8 @@ export const ConversationHeader: React.FC = ({ className="p-2 shadow menu dropdown-content z-[1] bg-base-100 rounded-box w-52 absolute right-full " > {/* check if current user is admin or owner to show the settings toast */} - {currentRoom?.isAdmin || currentRoom?.isOwner ? ( + {(currentRoom?.isAdmin === true || + currentRoom?.isOwner === true) && ( - ) : ( - <> )}
  • @@ -205,16 +209,25 @@ export const ConversationHeader: React.FC = ({ Show Room Info
  • - {currentRoom?.isOwner === false ? ( + {currentRoom?.isOwner === false && (
    -
  • - - leave The Room - +
  • { + ChatState.setIsLoading(true); + await leaveRoomCall(currentRoom?.id as string).then( + (res) => { + ChatState.setIsLoading(false); + if (res?.status === 200 || res?.status === 201) { + toast.success("Room Left Successfully"); + ChatState.selectNewChatID(chatRooms[0].id); + } + } + ); + }} + > + leave The Room
  • - ) : ( - <> )} {
    {MyUsers.length > 0 ? ( -
    +
    {MyUsers.filter((friend) => friend.messages.length > 0).map( // to change 0 to the last message here (friend) => ( @@ -140,13 +137,7 @@ export const OnlineNowUsers = () => { src={Explore} /> -
    - - - - - -
    +
    diff --git a/frontend/code/src/Components/Chat/Components/RoomChatHelpers.tsx b/frontend/code/src/Components/Chat/Components/RoomChatHelpers.tsx index 219d883..4167db9 100644 --- a/frontend/code/src/Components/Chat/Components/RoomChatHelpers.tsx +++ b/frontend/code/src/Components/Chat/Components/RoomChatHelpers.tsx @@ -7,6 +7,7 @@ import users, { Lock, More, NullImage, + RoomMember, RoomType, Unlock, chatRooms, @@ -16,14 +17,18 @@ import users, { import { SelectedUserTile } from ".."; import { + DeleteRoomCall, createNewRoomCall, fetchRoomsCall, + getRoomMembersCall, joinRoomCall, + takeActionCall, updateRoomCall, } from "../Services/ChatServices"; import toast from "react-hot-toast"; import { Logo } from "../../Layout/Assets/Logo"; import { useModalStore } from "../Controllers/ModalControllers"; +import { useUserStore } from "../../../Stores/stores"; interface NullComponentProps { message: string; @@ -40,19 +45,25 @@ export const RoomChatPlaceHolder = () => { // to make it dynamic later await fetchRoomsCall(0, 100, true).then((res) => { if (res?.status !== 200 && res?.status !== 201) { - toast.error("something went wrong, try again"); + // toast.error("something went wrong, try again"); } else { const rooms: ChatRoom[] = []; res.data.forEach( - (room: { id: string; name: string; type: string }) => { + (room: { + id: string; + is_admin: boolean; + is_owner: boolean; + name: string; + type: string; + }) => { rooms.push({ id: room.id, name: room.name, type: RoomType[room.type as keyof typeof RoomType], messages: [], usersId: [], - isOwner: true, - isAdmin: true, + isOwner: room.is_owner, + isAdmin: room.is_admin, }); } ); @@ -67,7 +78,7 @@ export const RoomChatPlaceHolder = () => { }, [ChatRoomsState.selectedChatID]); return ChatRoomsState.recentRooms.length > 0 ? ( -
    +
    {ChatRoomsState.recentRooms.map((room) => (
    { setSelectedOption(RoomType.public); }; return ( -
    +
    @@ -232,8 +243,21 @@ export const CreateNewRoomModal = () => { { - console.log(RoomType[selectedOption]); - if (RoomName !== "" && RoomName.length > 3) { + // console.log(RoomType[selectedOption]); + if ( + RoomName !== "" && + RoomName.length > 3 && + RoomName.length < 20 + ) { + if ( + RoomPassword.length < 8 && + selectedOption === RoomType.protected + ) { + console.log(selectedOption); + toast.error("password must be at least 8 characters"); + resetModalState(); + return; + } setIsLoading(true); await createNewRoomCall( RoomName, @@ -243,7 +267,7 @@ export const CreateNewRoomModal = () => { : undefined ).then((res) => { if (res?.status !== 200 && res?.status !== 201) { - // toast.error("something went wrong, try again"); + toast.error("something went wrong, try again"); resetModalState(); } else { createNewRoom(RoomName, selectedOption, res.data.id); @@ -252,7 +276,9 @@ export const CreateNewRoomModal = () => { setIsLoading(false); }); } else { - toast.error("Room name must be at least 4 characters"); + toast.error( + "Room name must be at least 4 characters and less than 20 " + ); resetModalState(); } }} @@ -271,7 +297,7 @@ export const AddUsersModal = () => { const [MyUsers] = useState(users); return ( -
    +
    @@ -311,15 +337,15 @@ export const AddUsersModal = () => { }; export const RoomSettingsModal = () => { + const [currentUsers, setUsers] = useState([]); + const currentUser = useUserStore((state) => state); const editRoom = useChatStore((state) => state.editRoom); const selectedChatID = useChatStore((state) => state.selectedChatID); + const deleteRoom = useChatStore((state) => state.deleteRoom); const currentRoom = chatRooms.find((room) => room.id === selectedChatID); - const currentRoomUsers = users.filter( - (user) => currentRoom?.usersId.includes(user.id) as boolean - ); const setIsLoading = useChatStore((state) => state.setIsLoading); - + const [skipCount, setSkipCount] = useState(true); const [RoomName, setName] = useState(""); const [RoomPassword, setPassword] = useState(""); @@ -338,7 +364,28 @@ export const RoomSettingsModal = () => { useEffect(() => { setSelectedOption(currentRoom?.type as RoomType); setName(currentRoom?.name as string); - }, [currentRoom?.type, currentRoom?.name]); + if (skipCount) setSkipCount(false); + if (!skipCount) { + const fetchData = async () => { + try { + await getRoomMembersCall(currentRoom?.id as string, 0, 30).then( + (res) => { + if (res?.status === 200 || res?.status === 201) { + const extractedData = res.data; + setUsers(extractedData); + } else { + } + } + ); + } catch (error) { + console.error("Error fetching data: ", error); + } + }; + + fetchData(); + } + // eslint-disable-next-line + }, [selectedChatID]); const resetModalState = () => { setPassword(""); @@ -347,7 +394,7 @@ export const RoomSettingsModal = () => { }; return ( -
    +
    @@ -404,7 +451,6 @@ export const RoomSettingsModal = () => {
    - {/* Conditionally render the text input */} {selectedOption === RoomType.protected && (
    @@ -421,104 +467,171 @@ export const RoomSettingsModal = () => {

    Room Members

    {/* Scrollable part */} -
    - {currentRoomUsers.map((user) => ( -
    -
    -
    - -
    +
    + {currentUsers + .filter((user) => user.id !== currentUser.id) + .map((user) => ( +
    +
    +
    + +
    -

    - {user.name} -

    -
    +

    + {user.name.first ?? "user"} +

    +
    -
    - -
      -
    • - Ban -
    • -
    • - + +
        +
      • { + await takeActionCall( + selectedChatID as string, + user.id, + "ban" + ).then((res) => { + if (res?.status === 200 || res?.status === 201) { + toast.success("User baned Successfully"); + } + }); + }} > - mute - -
      • - -
      • - Ban +
      • +
      • { + await takeActionCall( + selectedChatID as string, + user.id, + "mute" + ).then((res) => { + if (res?.status === 200 || res?.status === 201) { + toast.success("User Muted Successfully"); + } + }); + }} + > + mute +
      • + +
      • { + await takeActionCall( + selectedChatID as string, + user.id, + "kick" + ).then((res) => { + if (res?.status === 200 || res?.status === 201) { + toast.success("User Kicked Successfully"); + } + }); + }} + > + kick +
      • +
      • { + await takeActionCall( + selectedChatID as string, + user.id, + "setAdmin" + ).then((res) => { + if (res?.status === 200 || res?.status === 201) { + toast.success( + "User have been set as Admin Successfully" + ); + } + }); + }} > - kick - -
      • -
      • - Set as admin -
      • -
      + Set as admin +
    • +
    +
    -
    - ))} + ))}
    - -
    - { - // eslint-disable-next-line - } - - {"Close "} - - { - console.log(RoomType[selectedOption]); - if (RoomName !== "" && RoomName.length > 3) { - setIsLoading(true); - await updateRoomCall( - RoomName, - RoomType[selectedOption], - currentRoom?.id!, - selectedOption === RoomType.protected - ? RoomPassword - : undefined - ).then((res) => { - if (res?.status !== 200 && res?.status !== 201) { - resetModalState(); - } else { - editRoom(RoomName, selectedOption, currentRoom?.id!); - resetModalState(); - } - setIsLoading(false); - }); - } else { - toast.error("Room name must be at least 4 characters"); - resetModalState(); - } - }} - className="btn hover:bg-purple-500" - > - {"Save "} - +
    + +
    @@ -527,6 +640,7 @@ export const RoomSettingsModal = () => { }; export const ExploreRoomsModal = () => { + const [RoomPassword, setPassword] = useState(""); const [ChatRooms, SetChatRooms] = useState(chatRooms); const [selectedOption, setSelectedOption] = useState(RoomType.public); const [SelectedRoomID, setSelectedRoomID] = useState("0"); @@ -535,6 +649,7 @@ export const ExploreRoomsModal = () => { const modalState = useModalStore((state) => state); const resetModalState = () => { + setPassword(""); setSelectedOption(RoomType.public); setSelectedRoomID("0"); }; @@ -544,14 +659,18 @@ export const ExploreRoomsModal = () => { setIsLoading(true); await fetchRoomsCall(0, 30, false).then((res) => { if (res?.status !== 200 && res?.status !== 201) { - toast.error("something went wrong, try again"); + // toast.error("something went wrong, try again"); resetModalState(); } else { - console.log("my recent"); - console.log(recentRooms); const rooms: ChatRoom[] = []; res.data.forEach( - (room: { id: string; name: string; type: string }) => { + (room: { + id: string; + is_admin: boolean; + is_owner: boolean; + name: string; + type: string; + }) => { if ( recentRooms.recentRooms.find( (recentRoom) => recentRoom.id === room.id @@ -563,8 +682,8 @@ export const ExploreRoomsModal = () => { type: RoomType[room.type as keyof typeof RoomType], messages: [], usersId: [], - isOwner: true, - isAdmin: true, + isOwner: room.is_owner, + isAdmin: room.is_admin, }); } } @@ -576,11 +695,11 @@ export const ExploreRoomsModal = () => { }; fetch(); - // eslint-disable-next-line + // eslint-disable-next-line }, [modalState]); return ( -
    +
    @@ -640,6 +759,8 @@ export const ExploreRoomsModal = () => {

    Room Password

    setPassword(event.target.value)} type="Password" className="input w-full shadow-xl max-w-lg bg-[#272932] placeholder:text-gray-400 font-poppins text-base font-normal leading-normal" /> @@ -647,10 +768,6 @@ export const ExploreRoomsModal = () => {
    )}
    - { - // eslint-disable-next-line - } - { { - await joinRoomCall(SelectedRoomID, undefined).then((res) => { + recentRooms.setIsLoading(true); + + await joinRoomCall( + SelectedRoomID, + selectedOption === RoomType.protected + ? RoomPassword + : undefined + ).then((res) => { + recentRooms.setIsLoading(false); if (res?.status !== 200 && res?.status !== 201) { - // toast.error("something went wrong, try again"); - resetModalState(); } else { + toast.success("Room Joined Successfully"); recentRooms.selectNewChatID(SelectedRoomID); resetModalState(); } diff --git a/frontend/code/src/Components/Chat/Components/tools/Assets.tsx b/frontend/code/src/Components/Chat/Components/tools/Assets.tsx index 40ebced..427eece 100644 --- a/frontend/code/src/Components/Chat/Components/tools/Assets.tsx +++ b/frontend/code/src/Components/Chat/Components/tools/Assets.tsx @@ -20,7 +20,7 @@ import RoomsIcon from "../../assets/group_share.svg"; import Explore from "../../assets/explore.svg"; import Lock from "../../assets/lockIcon.svg"; import Unlock from "../../assets/UnlockIcon.svg"; -import ChatGif from "../../assets/chatGif.gif" +import ChatGif from "../../assets/chatGif.gif"; export enum RoomType { private, public, @@ -50,7 +50,7 @@ export { Explore, Lock, Unlock, - ChatGif + ChatGif, }; export interface Message { @@ -61,10 +61,16 @@ export interface Message { } export interface RoomMember { - userId : string; - firstName : string; - lastName : string; - avatar : string; + id: string; + name: { + first: string; + last: string; + }; + avatar: { + thumbnail: string; + medium: string; + large: string; + }; } export interface ChatRoom { @@ -77,10 +83,9 @@ export interface ChatRoom { type: RoomType; } - export interface User { - firstName? : string; - lastName? : string + firstName?: string; + lastName?: string; id: string; name: string; image: string; diff --git a/frontend/code/src/Components/Chat/Controllers/ChatControllers.tsx b/frontend/code/src/Components/Chat/Controllers/ChatControllers.tsx index 21e2e2f..2ea7e05 100644 --- a/frontend/code/src/Components/Chat/Controllers/ChatControllers.tsx +++ b/frontend/code/src/Components/Chat/Controllers/ChatControllers.tsx @@ -18,7 +18,10 @@ export interface ChatState { currentRoomMessages: Message[]; isLoading: boolean; + showChatRooms: boolean; + recentRooms: ChatRoom[]; + deleteRoom: (id: string) => void; fillRecentRooms: (rooms: ChatRoom[]) => void; setIsLoading: (isLoading: boolean) => void; selectNewChatID: (id: string) => void; @@ -26,6 +29,7 @@ export interface ChatState { createNewRoom: (name: string, roomType: RoomType, id: string) => void; addNewMessage: (message: Message) => void; changeChatType: (type: ChatType) => void; + toggleChatRooms: (value?: boolean) => void; } export const useChatStore = create()((set) => ({ @@ -33,11 +37,26 @@ export const useChatStore = create()((set) => ({ selectedChatType: ChatType.Chat, recentRooms: chatRooms, isLoading: false, + + // UI state + showChatRooms: false, + // to fix this currentMessages: users.find((user) => user.id === "1")?.messages as Message[], currentRoomMessages: chatRooms.find((room) => room.id === "1") ?.messages as Message[], + deleteRoom: (id: string) => + set((state) => { + const roomIndex = chatRooms.findIndex((room) => room.id === id); + if (roomIndex !== -1) { + chatRooms.splice(roomIndex, 1); + } + + state.recentRooms = [...chatRooms]; + state.selectNewChatID(state.recentRooms[0].id); + return { ...state }; + }), setIsLoading: (isLoading: boolean) => set((state) => { state.isLoading = isLoading; @@ -117,4 +136,10 @@ export const useChatStore = create()((set) => ({ return { ...state }; }), + + toggleChatRooms: (value?: boolean) => + set((state) => ({ + ...state, + showChatRooms: value === undefined ? !state.showChatRooms : value, + })), })); diff --git a/frontend/code/src/Components/Chat/Services/ChatServices.ts b/frontend/code/src/Components/Chat/Services/ChatServices.ts index 85a8f03..a0a73b0 100644 --- a/frontend/code/src/Components/Chat/Services/ChatServices.ts +++ b/frontend/code/src/Components/Chat/Services/ChatServices.ts @@ -1,114 +1,181 @@ -import api from "../../../Api/base"; - +import toast from "react-hot-toast"; +import api from "../../../Api/base"; export const createNewRoomCall = async ( - name: string, - type: string, - password?: string - ) => { - try { - - const response = await api.post("/rooms/create", { - name: name, - type: type, - password: password, - }); - console.log(response.data); - console.log(response.status); - return response; - } catch (e) { - console.log(e); - } - }; - - - export const updateRoomCall = async ( - name: string, - type: string, - roomId: string, - password? : string, - - ) => { - try { - - const response = await api.post("/rooms/update", { - name: name, - type: type, - roomId : roomId, - password : password, - }); - console.log(response.data); - console.log(response.status); - return response; - } catch (e) { - console.log(e); - } - - }; - - - export const fetchRoomsCall = async ( - offset: number, - limit : number, - joined : boolean, - - ) => { - - try { - const response = await api.get(`/rooms`, - { params: { offset: offset, limit : limit, joined : joined } }); - joined === true ? console.log("resent :") : console.log("Public :"); - console.log(response.status); - console.log(response.data); - return response; - } catch (e) { - console.log(e); - } - - - - - - - } - - - - export const getRoomMembersCall = async ( - id : string, - offset: number, - limit : number, - ) => { - try { - const response = await api.get(`/rooms/${id}/members`, - { params: {offset: offset, limit : limit } }); - console.log("room members :"); - console.log(response.status); - console.log(response.data); - return response; - } catch (e) { - console.log(e); - } - - } - - - export const joinRoomCall = async ( - roomId : string, - password? : string, - - ) => { - try { - - const response = await api.post("/rooms/join", { - roomId : roomId, - password : password, - }); - console.log("join room") - console.log(response.status); - console.log(response.data); - return response; - } catch (e : any) { - console.log(e.response.data.message); - } - } \ No newline at end of file + name: string, + type: string, + password?: string +) => { + try { + + const response = await api.post("/rooms/create", { + name: name, + type: type, + password: password, + }); + console.log(response.data); + console.log(response.status); + return response; + } catch (e: any) { + console.log(e.response.data.message); + } +}; + + +export const updateRoomCall = async ( + name: string, + type: string, + roomId: string, + password?: string, + +) => { + try { + + const response = await api.post("/rooms/update", { + name: name, + type: type, + roomId: roomId, + password: password, + }); + console.log(response.data); + console.log(response.status); + return response; + } catch (e: any) { + console.log(e.response.data.message); + } + +}; + + +export const fetchRoomsCall = async ( + offset: number, + limit: number, + joined: boolean, + +) => { + + try { + const response = await api.get(`/rooms`, + { params: { offset: offset, limit: limit, joined: joined } }); + joined === true ? console.log("resent :") : console.log("Public :"); + console.log(response.status); + console.log(response.data); + return response; + } catch (e: any) { + console.log(e.response.data.message); + } + +} + + + +export const getRoomMembersCall = async ( + id: string, + offset: number, + limit: number, +) => { + try { + const response = await api.get(`/rooms/${id}/members`, + { params: { offset: offset, limit: limit } }); + console.log("room members :"); + console.log(response.status); + console.log(response.data); + return response; + } catch (e: any) { + console.log(e.response.data.message); + } + +} + + +export const joinRoomCall = async ( + roomId: string, + password?: string, + +) => { + try { + + const response = await api.post("/rooms/join", { + roomId: roomId, + password: password, + }); + console.log("join room") + console.log(response.status); + console.log(response.data); + return response; + } catch (e: any) { + + console.log(e.response.data.message); + toast.error(e.response.data.message); + } +} + + +export const leaveRoomCall = async ( + roomId: string, + +) => { + try { + + const response = await api.post("/rooms/leave", { + roomId: roomId, + + }); + console.log("leave result :") + console.log(response.status); + console.log(response.data); + return response; + } catch (e: any) { + + console.log(e.response.data.message); + toast.error(e.response.data.message); + } + +} + +export const takeActionCall = async ( + roomId: string, + memberId: string, + action: string, +) => { + try { + const response = await api.post(`/rooms/${action}`, { + roomId: roomId, + memberId: memberId, + + }); + console.log(`${action} result :`) + console.log(response.status); + console.log(response.data); + return response; + } catch (e: any) { + + console.log(e.response.data.message); + toast.error(e.response.data.message); + } + +} + +export const DeleteRoomCall = async ( + roomId: string, + +) => { + try { + + const response = await api.post("/rooms/delete", { + roomId: roomId, + + }); + console.log("delete result :") + console.log(response.status); + console.log(response.data); + return response; + } catch (e: any) { + + console.log(e.response.data.message); + toast.error(e.response.data.message); + } + +} + + diff --git a/frontend/code/src/Components/Chat/index.tsx b/frontend/code/src/Components/Chat/index.tsx index 57ee564..94fe26e 100644 --- a/frontend/code/src/Components/Chat/index.tsx +++ b/frontend/code/src/Components/Chat/index.tsx @@ -5,7 +5,7 @@ import { chatRooms, RoomsIcon, RoomMember, - yas, + } from "./Components/tools/Assets"; import { useEffect, useState } from "react"; import { Conversation } from "./Components/Conversation"; @@ -15,10 +15,18 @@ import React from "react"; import { ChatType, useChatStore } from "./Controllers/ChatControllers"; import { RecentConversations } from "./Components/RecentChat"; -import { NullPlaceHolder } from "./Components/RoomChatHelpers"; +import { + AddUsersModal, + CreateNewRoomModal, + ExploreRoomsModal, + NullPlaceHolder, + RoomSettingsModal, + ShowLogoModal, +} from "./Components/RoomChatHelpers"; import { getRoomMembersCall } from "./Services/ChatServices"; import toast from "react-hot-toast"; +import { classNames } from "../../Utils/helpers"; export interface ConversationProps { onRemoveUserPreview: () => void; @@ -28,23 +36,45 @@ export const Chat = () => { const [showUserPreview, setShowUserPreview] = useState(false); const selectedChatType = useChatStore((state) => state.selectedChatType); + const showChatRooms = useChatStore((state) => state.showChatRooms); + const toggleChatRooms = useChatStore((state) => state.toggleChatRooms); + const chatRooms = useChatStore((state) => state.recentRooms); const handleRemoveUserPreview = () => { setShowUserPreview(!showUserPreview); }; return ( <> -
    +
    +
    + + + + + +
    - {} +
    + {showChatRooms && ( +
    toggleChatRooms()} + /> + )}
    {chatRooms.length < 1 && selectedChatType === ChatType.Room ? ( @@ -53,7 +83,11 @@ export const Chat = () => { )}
    -
    + -
    +
    {isLoading === false ? ( <> {currentUsers.map((user) => ( -
    - - - - - - - -
    -
    -
    -
    - Avatar Tailwind CSS Component -
    -
    -
    -
    - {user.firstName} -
    -
    -
    -
    +
    +
    + {" "} + {/* Center horizontally */} +
    +
    + Avatar Tailwind CSS Component +
    +
    +
    +
    + {/* "kkdccd" */} + {user.name?.first ?? "user"} +
    +
    +
    ))} @@ -204,6 +232,37 @@ export const UserPreviewCard: React.FC = ({ ); }; +// {/* +// +// +// +// +// +// +//
    +//
    +// {" "} +// {/* Center horizontally */} +//
    +//
    +// Avatar Tailwind CSS Component +//
    +//
    +//
    +//
    +// {/* "kkdccd" */} +// {user.name?.first ?? "user"} +//
    +//
    +//
    +//
    */} + export const SelectedUserTile = ({ username, userImage, diff --git a/frontend/code/src/Utils/helpers.ts b/frontend/code/src/Utils/helpers.ts new file mode 100644 index 0000000..1a08127 --- /dev/null +++ b/frontend/code/src/Utils/helpers.ts @@ -0,0 +1,4 @@ +export function classNames(...args: (string | number | boolean)[]) { + return args.filter(Boolean).map(String).join(' '); +} +