Message 채팅 웹을 만드는데 유저 검색 기능을 만들었습니다.
import { gql } from "@apollo/client";
export default {
Queries: {
searchUsers: gql`
query SearchUsers($username: String!) {
searchUsers(username: $username) {
id
username
}
}
`,
},
Mutations: {
createUsername: gql`
mutation CreateUsername($username: String!) {
createUsername(username: $username) {
success
error
}
}
`,
},
Subscriptions: {},
};
searchUsers 라는 query를 만들고
import {
Button,
Input,
Modal,
ModalBody,
ModalCloseButton,
ModalContent,
ModalHeader,
ModalOverlay,
Stack,
Text,
} from "@chakra-ui/react";
import UserOperations from "../../../../graphql/operations/user";
import ConversationOperations from "../../../../graphql/operations/conversation";
import React, { useCallback, useState } from "react";
import { Observable, useLazyQuery, useMutation } from "@apollo/client";
import {
CreateConversationData,
SearchedUser,
SearchUsersData,
SearchUsersInput,
} from "@/util/types";
import UserSearchList from "./userSearchList";
import Participants from "./Participants";
import toast from "react-hot-toast";
import { Session } from "next-auth";
interface ModalProps {
session: Session;
isOpen: boolean;
onClose: () => void;
}
const ConversationModal = ({ session, isOpen, onClose }: ModalProps) => {
const {
user: { id: userId },
} = session;
const [username, setUsername] = useState("");
const [participants, setParticipants] = useState<Array<SearchedUser>>([]);
const [searchUsers, { data, loading, error }] = useLazyQuery<any>(
UserOperations.Queries.searchUsers
);
const [createConversation, { loading: createConversationLoading }] =
useMutation<CreateConversationData>(
ConversationOperations.Mutations.createConversation
);
console.log("HERE IS SEARCH DATA", data);
console.log(participants.map((s) => s.id));
const onCreateConversation = async () => {
const participantIds = [userId, ...participants.map((p) => p.id)];
try {
// createConversation Mutation
const { data } = await createConversation({
variables: {
participantIds,
},
});
console.log("DATA", data);
} catch (err: any) {
console.log("onCreateConversation", err);
toast.error(err?.message);
}
};
const onSearch = useCallback(
async (e: React.FormEvent) => {
e.preventDefault();
// search user query
searchUsers({ variables: { username } as any });
},
[username]
);
const addParticipant = (user: SearchedUser) => {
setParticipants((prev) => [...prev, user]);
setUsername("");
};
const removeParticipant = (userId: string) => {
console.log("removeParticipant");
setParticipants((prev) => prev.filter((p) => p.id !== userId));
};
return (
<>
<Modal isOpen={isOpen} onClose={onClose}>
<ModalOverlay />
<ModalContent pb={4}>
<ModalHeader>Create a Conversations</ModalHeader>
<ModalCloseButton />
<ModalBody>
<form onSubmit={onSearch}>
<Stack spacing={4}>
<Input
placeholder="유저를 입력해주세요."
value={username}
onChange={(e) => setUsername(e.target.value)}
/>
<Button type="submit" disabled={!username} isLoading={loading}>
검색
</Button>
</Stack>
</form>
{data?.searchUsers && (
<UserSearchList
users={data?.searchUsers}
username={username}
addParticipant={addParticipant}
/>
)}
{participants.length !== 0 && (
<>
<Participants
participants={participants}
removeParticipant={removeParticipant}
/>
<Button
bg="blue.100"
width="100%"
mt={6}
_hover={{ bg: "gray.100" }}
isLoading={createConversationLoading}
onClick={onCreateConversation}
>
Create Conversation
</Button>
</>
)}
</ModalBody>
</ModalContent>
</Modal>
</>
);
};
export default ConversationModal;
검색 모달 창을 만들었습니다 CSS는 npm i @chakra-ui/react @emotion/react @emotion/styled framer-motion 라이브 러리를 사용합니다
//backend src/graphql/typeDefs/user.ts
import { gql } from "apollo-server-core";
const typeDefs = gql`
type SearchedUser {
id: String
username: String
}
type Query {
searchUsers(username: String!): [SearchedUser]
}
type Mutation {
createUsername(username: String!): CreateUsernameResponse
}
type CreateUsernameResponse {
success: Boolean
error: String
}
`;
export default typeDefs;
백엔드에서 typeDef 만들고
import { User } from "@prisma/client";
import { GraphQLError } from "graphql";
import { CreateUsernameResponse, GraphQLContext } from "../../util/types";
const resolvers = {
Query: {
searchUsers: async (
_: any,
args: { username: string },
context: GraphQLContext
): Promise<Array<User>> => {
const { username: searchedUsername } = args;
const { prisma, session } = context;
if (!session?.user) {
throw new GraphQLError("Not authorized");
}
const {
user: { username: myUsername },
} = session;
try {
const users = await prisma.user.findMany({
where: {
username: searchedUsername,
},
});
return users;
} catch (error: any) {
console.log("error", error);
throw new GraphQLError(error?.message);
}
},
},
Mutation: {},
};
export default resolvers;
리졸브를 만들었습니다
GraphQL 설명은 https://happy8131.tistory.com/113
GraphQL이란
요즘회사에서 GraphQL을 많이 사용하고 현재 project에서 저도 사용해서 찾아봤습니다. 1) GraphQL 소개 GraphQL이란 페이스북이 모바일 앱을 재구성하기 위해 노력하던 2012년 개발되어 2015년 오픈소스로
happy8131.tistory.com
몽고DB Compass 보면 username에 asd가 있는게 보입니다.
Graphql Prisma 사용하면서 찾아볼게 많아졌습니다
Prisma에 대한 설명이 없는데 이것도 따로 블로깅하겠습니다.
'Project' 카테고리의 다른 글
WebSocket/ Subscription (0) | 2023.08.29 |
---|---|
GraphQL 대화 생성 (0) | 2023.08.28 |
Graphql Query, prisma (0) | 2023.08.22 |
Graphql 리액트 연결 (0) | 2023.08.22 |
next-auth 적용하여 소셜 로그인 구현하기 (0) | 2023.08.22 |