diff --git a/apps/web-client/package.json b/apps/web-client/package.json index 42494c6f..08f1adf2 100644 --- a/apps/web-client/package.json +++ b/apps/web-client/package.json @@ -71,7 +71,7 @@ "sync:type": "yarn dlx typesync", "check:type": "tsc", "check:type:watch": "yarn check:type --watch", - "codegen": "openapi -i https://dev.poolc.org/api/v2/api-docs -o src/lib/api-v2/__generated__ -c fetch --useUnionTypes --useOptions", + "codegen": "openapi -i https://dev.poolc.org/api/v2/api-docs -o src/lib/api-v2/__generated__ --useUnionTypes --useOptions -c axios", "postinstall": "yarn codegen", "lint": "eslint . && prettier . --check --ignore-path .gitignore", "format": "eslint . --fix && prettier . --write --ignore-path .gitignore" diff --git a/apps/web-client/src/App.tsx b/apps/web-client/src/App.tsx index 9cc5c17d..01e8b04d 100644 --- a/apps/web-client/src/App.tsx +++ b/apps/web-client/src/App.tsx @@ -103,9 +103,9 @@ function App() { - - - + + + diff --git a/apps/web-client/src/components/members/MemberDetail/MemberDetailContent.styles.ts b/apps/web-client/src/components/members/MemberDetail/MemberDetailContent.styles.ts index 1c622fdf..5eb1fef2 100644 --- a/apps/web-client/src/components/members/MemberDetail/MemberDetailContent.styles.ts +++ b/apps/web-client/src/components/members/MemberDetail/MemberDetailContent.styles.ts @@ -38,6 +38,7 @@ export const TextContainer = styled.div` export const NameContainer = styled.div` display: flex; align-items: center; + gap: 8px; @media (max-width: 576px) { justify-content: center; } @@ -50,7 +51,6 @@ export const Name = styled.p` export const Status = styled.span` font-weight: 300; - margin-left: 5px; `; export const DepartmentContainer = styled.div` diff --git a/apps/web-client/src/components/members/MemberDetail/MemberDetailContent.tsx b/apps/web-client/src/components/members/MemberDetail/MemberDetailContent.tsx index a8dfeb9a..ed5890f5 100644 --- a/apps/web-client/src/components/members/MemberDetail/MemberDetailContent.tsx +++ b/apps/web-client/src/components/members/MemberDetail/MemberDetailContent.tsx @@ -1,5 +1,6 @@ -import Icon from '@ant-design/icons'; -import { Avatar } from 'antd'; +import Icon, { MessageOutlined } from '@ant-design/icons'; +import { Avatar, Button, Tooltip } from 'antd'; +import { useHistory } from 'react-router'; import ActivityCard from '~/components/activity/ActivityCard/ActivityCard'; import ProjectCard from '~/components/projects/ProjectCard/ProjectCard'; import getFileUrl from '~/lib/utils/getFileUrl'; @@ -19,16 +20,45 @@ import { ActivityContainer, Activities, } from './MemberDetailContent.styles'; -import { MemberControllerService, MemberResponse, queryKey, useAppSuspenseQuery } from '~/lib/api-v2'; +import { ConversationControllerService, MemberControllerService, MemberResponse, queryKey, useAppMutation, useAppSuspeneseQueries } from '~/lib/api-v2'; +import { MENU } from '~/constants/menus'; export default function MemberDetailContent({ loginId }: { loginId: string }) { - const { data: _member } = useAppSuspenseQuery({ - queryKey: queryKey.member.id(loginId), - queryFn: () => MemberControllerService.getMemberWithProjectAndActivityUsingGet({ loginId }), + const history = useHistory(); + const [{ data: _member }, { data: me }] = useAppSuspeneseQueries({ + queries: [ + { + queryKey: queryKey.member.id(loginId), + queryFn: () => MemberControllerService.getMemberWithProjectAndActivityUsingGet({ loginId }), + }, + { + queryKey: queryKey.member.me, + queryFn: MemberControllerService.getMeUsingGet, + }, + ], }); const member = _member as unknown as Required; + const { mutate } = useAppMutation({ + mutationFn: () => + ConversationControllerService.createConversationUsingPost({ + request: { + otherLoginID: member.loginID, + }, + }), + }); + + const onMessageButtonClick = () => { + if (confirm(`${member.name}님과의 대화를 시작할까요?`)) { + mutate(undefined, { + onSuccess: (conversationId) => { + history.push(`/${MENU.MESSAGE}/${conversationId}/${MENU.MESSAGE_FORM}`); + }, + }); + } + }; + return ( <> @@ -40,6 +70,11 @@ export default function MemberDetailContent({ loginId }: { loginId: string }) { {member.name} {member.isAdmin && PoolC임원} {member.badge && } + {member.loginID !== me.loginID && ( + + + 대화목록 + + + ( + + + + 받은 쪽지 + 2023.08.15 19:20:50 + + 내용내용내용 + + + )} + /> + + ); +} diff --git a/apps/web-client/src/components/message/MessageAllListView.tsx b/apps/web-client/src/components/message/MessageAllListView.tsx new file mode 100644 index 00000000..0d70bd6f --- /dev/null +++ b/apps/web-client/src/components/message/MessageAllListView.tsx @@ -0,0 +1,25 @@ +import { createStyles } from 'antd-style'; +import { Suspense } from 'react'; +import { Block, WhiteBlock } from '~/styles/common/Block.styles'; +import MessageAllListContent from './MessageAllListContent'; +import Spinner from '../common/Spinner/Spinner'; + +const useStyles = createStyles(({ css }) => ({ + whiteBlock: css` + padding: 30px 20px; + `, +})); + +export default function MessageAllListView() { + const { styles } = useStyles(); + + return ( + + + }> + + + + + ); +} diff --git a/apps/web-client/src/components/message/MessageFormView.tsx b/apps/web-client/src/components/message/MessageFormView.tsx new file mode 100644 index 00000000..763f8a25 --- /dev/null +++ b/apps/web-client/src/components/message/MessageFormView.tsx @@ -0,0 +1,86 @@ +import { ArrowLeftOutlined } from '@ant-design/icons'; +import { Button, Input, Space, Typography } from 'antd'; +import { createStyles } from 'antd-style'; +import { FormEventHandler, useState } from 'react'; +import { useHistory, useParams } from 'react-router-dom'; +import { MENU } from '~/constants/menus'; +import { MessageControllerService, useAppMutation } from '~/lib/api-v2'; +import { Block, WhiteBlock } from '~/styles/common/Block.styles'; + +const useStyles = createStyles(({ css }) => ({ + whiteBlock: css` + padding: 30px 20px; + `, + wrapper: css` + width: 100%; + max-width: 1200px; + box-sizing: border-box; + `, + fullWidth: css` + width: 100%; + `, + topBox: css` + justify-content: space-between; + align-items: center; + width: 100%; + `, + topBoxName: css` + margin-bottom: 0; + font-weight: 700; + font-size: 20px; + `, + textarea: css` + min-height: 300px !important; + resize: none; + `, +})); + +export default function MessageFormView() { + const { styles } = useStyles(); + // TODO: react-hook-form 기반으로 변경 + const [content, setContent] = useState(''); + const history = useHistory(); + const { conversationId } = useParams<{ conversationId: string }>(); + + const { mutate: sendMessage } = useAppMutation({ + mutationFn: () => + MessageControllerService.sendMessageUsingPost({ + request: { + content, + conversationId, + }, + }), + }); + + const onFormSubmit: FormEventHandler = (e) => { + e.preventDefault(); + sendMessage(undefined, { + onSuccess: () => { + history.push(`/${MENU.MESSAGE}/${conversationId}`); + }, + }); + }; + + return ( + + +
+ + + + + 쪽지보내기 + + + setContent(e.target.value)} /> + + +
+
+
+ ); +} diff --git a/apps/web-client/src/components/message/MessageListContent.tsx b/apps/web-client/src/components/message/MessageListContent.tsx new file mode 100644 index 00000000..ea72058e --- /dev/null +++ b/apps/web-client/src/components/message/MessageListContent.tsx @@ -0,0 +1,92 @@ +import { Button, List, Space, Typography } from 'antd'; +import { createStyles } from 'antd-style'; +import { ArrowLeftOutlined } from '@ant-design/icons'; +import { Link, useHistory } from 'react-router-dom'; +import { Block, WhiteBlock } from '~/styles/common/Block.styles'; +import { MENU } from '~/constants/menus'; + +const useStyles = createStyles(({ css }) => ({ + whiteBlock: css` + padding: 30px 20px; + `, + wrapper: css` + width: 100%; + max-width: 1200px; + box-sizing: border-box; + `, + fullWidth: css` + width: 100%; + `, + metaInfo: css` + justify-content: space-between; + width: 100%; + `, + messageType: css` + font-weight: 700; + `, + topBox: css` + justify-content: space-between; + align-items: center; + width: 100%; + `, + topBoxName: css` + margin-bottom: 0; + font-weight: 700; + font-size: 20px; + `, +})); + +export default function MessageListContent() { + const { styles } = useStyles(); + const history = useHistory(); + + const data = [ + { + title: 'Ant Design Title 1', + }, + { + title: 'Ant Design Title 2', + }, + { + title: 'Ant Design Title 3', + }, + { + title: 'Ant Design Title 4', + }, + ]; + + return ( + + + + + + + 익명 + + + + + + ( + + + + 받은 쪽지 + 2023.08.15 19:20:50 + + 내용내용내용 + + + )} + /> + + + + ); +} diff --git a/apps/web-client/src/components/message/MessageListView.tsx b/apps/web-client/src/components/message/MessageListView.tsx new file mode 100644 index 00000000..3e7f0722 --- /dev/null +++ b/apps/web-client/src/components/message/MessageListView.tsx @@ -0,0 +1,25 @@ +import { createStyles } from 'antd-style'; +import { Suspense } from 'react'; +import { Block, WhiteBlock } from '~/styles/common/Block.styles'; +import Spinner from '../common/Spinner/Spinner'; +import MessageListContent from './MessageListContent'; + +const useStyles = createStyles(({ css }) => ({ + whiteBlock: css` + padding: 30px 20px; + `, +})); + +export default function MessageAllListView() { + const { styles } = useStyles(); + + return ( + + + }> + + + + + ); +} diff --git a/apps/web-client/src/constants/menus.js b/apps/web-client/src/constants/menus.js index db43b5c2..43504238 100644 --- a/apps/web-client/src/constants/menus.js +++ b/apps/web-client/src/constants/menus.js @@ -24,9 +24,8 @@ const MENU = { MY_PAGE_BADGE_LIST: 'badge-list', MY_PAGE_MY_POSTS: 'my-posts', MY_PAGE_MY_SCRAPS: 'my-scraps', - MESSAGE_LIST: 'message-list', - MESSAGE_FORM: 'message-form', - MESSAGE_ALL_LIST: 'message-all-list', + MESSAGE: 'message', + MESSAGE_FORM: 'form', ROOM_RESERVATION: 'room-reservation', }; diff --git a/apps/web-client/src/lib/api-v2/queryKey.ts b/apps/web-client/src/lib/api-v2/queryKey.ts index bee78dbd..6f3f7efa 100644 --- a/apps/web-client/src/lib/api-v2/queryKey.ts +++ b/apps/web-client/src/lib/api-v2/queryKey.ts @@ -29,4 +29,8 @@ export const queryKey = { room: { range: (start: string, end: string) => ['room.range', start, end] as const, }, + conversation: { + all: ['conversation.all'] as const, + conversation: (id: number) => ['conversation.conversation', id] as const, + }, }; diff --git a/apps/web-client/src/pages/message/MessageAllListPage.tsx b/apps/web-client/src/pages/message/MessageAllListPage.tsx index f5456990..0678463a 100644 --- a/apps/web-client/src/pages/message/MessageAllListPage.tsx +++ b/apps/web-client/src/pages/message/MessageAllListPage.tsx @@ -1,88 +1,5 @@ -import { Button, List, Space, Typography } from 'antd'; -import { createStyles } from 'antd-style'; -import { ArrowLeftOutlined } from '@ant-design/icons'; -import { useHistory } from 'react-router-dom'; -import { Block, WhiteBlock } from '~/styles/common/Block.styles'; - -const useStyles = createStyles(({ css }) => ({ - whiteBlock: css` - padding: 30px 20px; - `, - wrapper: css` - width: 100%; - max-width: 1200px; - box-sizing: border-box; - `, - fullWidth: css` - width: 100%; - `, - metaInfo: css` - justify-content: space-between; - width: 100%; - `, - messageType: css` - font-weight: 700; - `, - topBox: css` - justify-content: space-between; - align-items: center; - width: 100%; - `, - topBoxName: css` - margin-bottom: 0; - font-weight: 700; - font-size: 20px; - `, -})); +import MessageAllListView from '~/components/message/MessageAllListView'; export default function MessageAllListPage() { - const { styles } = useStyles(); - const history = useHistory(); - - const data = [ - { - title: 'Ant Design Title 1', - }, - { - title: 'Ant Design Title 2', - }, - { - title: 'Ant Design Title 3', - }, - { - title: 'Ant Design Title 4', - }, - ]; - - return ( - - - - - - - 쪽지목록 - - - ( - - - - 받은 쪽지 - 2023.08.15 19:20:50 - - 내용내용내용 - - - )} - /> - - - - ); + return ; } diff --git a/apps/web-client/src/pages/message/MessageFormPage.tsx b/apps/web-client/src/pages/message/MessageFormPage.tsx index 48edb023..abda5b57 100644 --- a/apps/web-client/src/pages/message/MessageFormPage.tsx +++ b/apps/web-client/src/pages/message/MessageFormPage.tsx @@ -1,61 +1,5 @@ -import { ArrowLeftOutlined } from '@ant-design/icons'; -import { Button, Input, Space, Typography } from 'antd'; -import { createStyles } from 'antd-style'; -import { useState } from 'react'; -import { useHistory } from 'react-router-dom'; -import { Block, WhiteBlock } from '~/styles/common/Block.styles'; +import MessageFormView from '~/components/message/MessageFormView'; -const useStyles = createStyles(({ css }) => ({ - whiteBlock: css` - padding: 30px 20px; - `, - wrapper: css` - width: 100%; - max-width: 1200px; - box-sizing: border-box; - `, - fullWidth: css` - width: 100%; - `, - topBox: css` - justify-content: space-between; - align-items: center; - width: 100%; - `, - topBoxName: css` - margin-bottom: 0; - font-weight: 700; - font-size: 20px; - `, - textarea: css` - min-height: 300px !important; - resize: none; - `, -})); - -export default function MyPageMessageFormPage() { - const { styles } = useStyles(); - const [content, setContent] = useState(''); - const history = useHistory(); - - return ( - - - - - - - 쪽지보내기 - - - setContent(e.target.value)} /> - - - - - ); +export default function MessageFormPage() { + return ; } diff --git a/apps/web-client/src/pages/message/MessageListPage.tsx b/apps/web-client/src/pages/message/MessageListPage.tsx index 14cc9343..c2738e74 100644 --- a/apps/web-client/src/pages/message/MessageListPage.tsx +++ b/apps/web-client/src/pages/message/MessageListPage.tsx @@ -1,7 +1,7 @@ import { Button, List, Space, Typography } from 'antd'; import { createStyles } from 'antd-style'; import { ArrowLeftOutlined } from '@ant-design/icons'; -import { Link, useHistory } from 'react-router-dom'; +import { Link, useHistory, useParams } from 'react-router-dom'; import { Block, WhiteBlock } from '~/styles/common/Block.styles'; import { MENU } from '~/constants/menus'; @@ -39,6 +39,7 @@ const useStyles = createStyles(({ css }) => ({ export default function MyPageMessageListPage() { const { styles } = useStyles(); const history = useHistory(); + const { conversationId } = useParams<{ conversationId: string }>(); const data = [ { @@ -66,7 +67,7 @@ export default function MyPageMessageListPage() { 익명 - +