Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโ€™ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

๐ŸŽ‰ ๊ฑฐ๋ž˜์„ฑ์‚ฌ์š”์ฒญ ๊ธฐ๋Šฅ ๊ตฌํ˜„ ์™„๋ฃŒ #98

Merged
merged 11 commits into from
Nov 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions public/images/check-circle.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions public/images/quit-circle.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
'use client'

import Image from 'next/image'
import Button from '@/components/ui/button'
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuTrigger,
} from '@/components/ui/dropdown-menu'
import Assets from '@/config/assets'
import { toast } from '@/hooks/useToast'
import { postCompleteRequest } from '@/services/complete-request/completeRequest'

type CompleteRequestButtonProps = {
myCardId: number
otherCardId: number
}

const CompleteRequestButton = ({
myCardId,
otherCardId,
}: CompleteRequestButtonProps) => {
const handleRequestButton = async () => {
try {
await postCompleteRequest(myCardId, otherCardId)
toast({
title: '๊ฑฐ๋ž˜์„ฑ์‚ฌ๋ฅผ ์š”์ฒญํ•˜์˜€์Šต๋‹ˆ๋‹ค',
variant: 'default',
duration: 2000,
})
} catch (error) {
toast({
title: '๊ฑฐ๋ž˜์„ฑ์‚ฌ ์š”์ฒญ์ด ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.',
variant: 'destructive',
duration: 2000,
})
}
}

return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button className="ml-auto" size="icon_sm" variant={null}>
<Image src={Assets.vMoreIcon} alt="more" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="min-w-[8rem]">
<DropdownMenuGroup>
<DropdownMenuItem onClick={handleRequestButton}>
๊ฑฐ๋ž˜์„ฑ์‚ฌ ์š”์ฒญ
</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>
)
}
export default CompleteRequestButton
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
import Image from 'next/image'
import Button from '@/components/ui/button'
import { Card, CardFlex, CardImage, CardText } from '@/components/ui/card/Card'
import Assets from '@/config/assets'
import { toast } from '@/hooks/useToast'
import { putCompleteRequest } from '@/services/complete-request/completeRequest'
import { Card as CardType } from '@/types/card'

const CardItem = ({
thumbnail,
itemName,
}: Pick<CardType, 'thumbnail' | 'itemName'>) => (
<CardFlex direction={'col'} justify={'center'} align={'center'} gap={'space'}>
<div className="h-11 w-20 relative">
<CardImage
alt="card-thumbnail"
src={thumbnail}
layout="fill"
objectFit="cover"
className="rounded"
/>
</div>
<CardText className="font-bold text-[12px] whitespace-nowrap overflow-hidden overflow-ellipsis">
{itemName}
</CardText>
</CardFlex>
)

type CompleteRequestCardProps = {
myCardData: CardType
otherCardData: CardType
}

const CompleteRequestCard = ({
myCardData,
otherCardData,
}: CompleteRequestCardProps) => {
const handleCompleteRequestUpdate = async (isAccepted: boolean) => {
try {
await putCompleteRequest(
otherCardData.cardId,
myCardData.cardId,
isAccepted,
)
window.location.reload()
juyeon-park marked this conversation as resolved.
Show resolved Hide resolved
toast({
title: `๊ฑฐ๋ž˜์„ฑ์‚ฌ ์š”์ฒญ์„ ${isAccepted ? '์ˆ˜๋ฝ' : '๊ฑฐ์ ˆ'}ํ•˜์˜€์Šต๋‹ˆ๋‹ค.`,
variant: 'default',
duration: 2000,
})
} catch (error) {
toast({
title: '๊ฑฐ๋ž˜์„ฑ์‚ฌ์š”์ฒญ ์ˆ˜๋ฝ ๋˜๋Š” ๊ฑฐ์ ˆ์ด ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค.',
variant: 'destructive',
duration: 2000,
})
}
}
return (
<div>
<Card className="p-2 flex items-center border-0" size={'sm'}>
<CardFlex justify={'between'} className="gap-4">
<CardItem
thumbnail={myCardData.thumbnail}
itemName={myCardData.itemName}
/>
<CardFlex direction={'col'} align={'center'} justify={'center'}>
<CardText
type={'description'}
className="text-[12px] max-w-[125px] text-center"
>
๊ฑฐ๋ž˜์„ฑ์‚ฌ ์š”์ฒญ์ด ์™”์Šต๋‹ˆ๋‹ค. ๊ฑฐ๋ž˜๋ฅผ ํ•˜์…จ๋‚˜์š”?
</CardText>
<CardFlex direction={'row'} gap={'space'}>
<Button
className="ml-auto"
size="icon_sm"
variant={null}
onClick={() => handleCompleteRequestUpdate(true)}
>
<Image src={Assets.checkCircle} alt="accept" />
</Button>
<Button
className="ml-auto"
size="icon_sm"
variant={null}
onClick={() => handleCompleteRequestUpdate(false)}
>
<Image src={Assets.quitCircle} alt="refuse" />
</Button>
</CardFlex>
</CardFlex>
<CardItem
thumbnail={otherCardData.thumbnail}
itemName={otherCardData.itemName}
/>
</CardFlex>
</Card>
</div>
)
}

export default CompleteRequestCard
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import Badge from '@/components/ui/badge'
import { COMPLETE_REQUEST_TYPE_OBJS } from '@/constants/card'
import { Card, CompleteRequestTypeObjs } from '@/types/card'
import { User } from '@/types/user'
import { getValueByKey } from '@/utils/getValueByKey'
import CompleteRequestCard from './CompleteRequestCard'

type CompleteReqeustTemplateProps = {
currentUser: User
completeRequestData: {
fromCard: { cardInfo: Card; userInfo: User }
toCard: { cardInfo: Card; userInfo: User }
status: CompleteRequestTypeObjs['key']
}
}

const CompleteReqeustTemplate = ({
currentUser,
completeRequestData: { fromCard, toCard, status },
}: CompleteReqeustTemplateProps) => {
//NOTE - ํ˜„์žฌ ๋กœ๊ทธ์ธํ•œ ์‚ฌ๋žŒ์ด ๊ฑฐ๋ž˜์„ฑ์‚ฌ ์š”์ฒญ ๋ฐ›์€ ์‚ฌ๋žŒ์ธ๊ฒฝ์šฐ + ์š”์ฒญ ์ƒํƒœ๊ฐ€ waiting์ธ ๊ฒฝ์šฐ - ๊ฑฐ๋ž˜์„ฑ์‚ฌ์š”์ฒญ ์นด๋“œ๊ฐ€ ๋ณด์ธ๋‹ค.
const isRequestedUser =
toCard.userInfo.userId === currentUser.userId && status === 'WAITING'
return isRequestedUser ? (
<CompleteRequestCard
myCardData={fromCard.cardInfo}
otherCardData={toCard.cardInfo}
/>
) : (
<Badge variant={'gradation'} size={'lg'} className="self-end mr-4">
{getValueByKey(COMPLETE_REQUEST_TYPE_OBJS, status)}
</Badge>
)
}

export default CompleteReqeustTemplate
53 changes: 50 additions & 3 deletions src/app/(root)/(routes)/chatrooms/[chatRoomId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import ApiEndPoint from '@/config/apiEndPoint'
import apiClient from '@/services/apiClient'
import { getServerCookie } from '@/utils/getServerCookie'
import ChatRoomTemplate from './components/ChatRoomTemplate'
import CompleteRequestButton from './components/CompleteRequestButton'
import CompleteReqeustTemplate from './components/CompleteRequestTemplate'

type ChatPageProps = {
params: {
Expand Down Expand Up @@ -32,19 +34,64 @@ const getInitialChatRoom = async (chatRoomId: string) => {
Authorization: `${token}`,
},
)
return res.data.chatRoomInfo.fireStoreChatRoomId
return res.data.chatRoomInfo
}

const getCompleteRequestInfo = async (completeRequestId: number) => {
const token = getServerCookie()
const res = await apiClient.get(
ApiEndPoint.getCompleteRequest(completeRequestId),
{},
{
Authorization: `${token}`,
},
)
return res.data.completeRequestInfo
}

const ChatPage = async ({ params }: ChatPageProps) => {
const initialUserInfo = await getInitialUser()
const initialChatRoom = await getInitialChatRoom(params.chatRoomId)

//NOTE - ๋‘˜ ์ค‘ ์•„๋ฌด๋ผ๋„ ๊ฑฐ๋ž˜์„ฑ์‚ฌ ์š”์ฒญ์„ ํ–ˆ์„ ๊ฒฝ์šฐ
const isCompleteRequested = initialChatRoom.completeRequestId !== -1
const completeRequestInfo = isCompleteRequested
? await getCompleteRequestInfo(initialChatRoom.completeRequestId)
: null

const suggestionDataArray = [
initialChatRoom.fromCardInfo,
initialChatRoom.toCardInfo,
]
console.log(suggestionDataArray)
const myCardId = suggestionDataArray.find(
(obj) => obj.userInfo.userId === initialUserInfo.userId,
).cardInfo.cardId

const otherCardId = suggestionDataArray.find(
(obj) => obj.userInfo.userId !== initialUserInfo.userId,
).cardInfo.cardId

return (
<main className="relative flex flex-col items-center w-full gap-10 h-page pb-chat_input">
<PageTitle title="์ฑ„ํŒ…๋ฐฉ" />
<header className="w-full flex flex-row items-center px-4">
<PageTitle title="์ฑ„ํŒ…๋ฐฉ" />
{!isCompleteRequested && (
<CompleteRequestButton
myCardId={myCardId}
otherCardId={otherCardId}
/>
)}
</header>
{isCompleteRequested && (
<CompleteReqeustTemplate
currentUser={initialUserInfo}
completeRequestData={completeRequestInfo}
/>
)}
<ChatRoomTemplate
currentUser={initialUserInfo}
fireStoreId={initialChatRoom}
fireStoreId={initialChatRoom.fireStoreChatRoomId}
/>
<div className="w-full h-0 border border-t-background-secondary-color" />
</main>
Expand Down
4 changes: 4 additions & 0 deletions src/config/apiEndPoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ const ApiEndPoint = {
putCardStatus: (cardId: number) => `/cards/status/${cardId}`,
getPopularCardList: () => '/cards/popular',
putMySuggestionStatus: () => `/suggestions/decision`,
getCompleteRequest: (completeRequestId: number) =>
`/complete-requests/${completeRequestId}`,
postCompleteRequest: () => '/complete-requests',
putCompleteRequest: () => '/complete-requests/confirm',
getNotificationList: ({ isRead, cursorId }: GetNotificationListReq) => {
return `/notifications/?${getQueryParams({
'is-read': String(isRead),
Expand Down
7 changes: 7 additions & 0 deletions src/constants/card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,12 @@ const CATEGORY_BUTTON_LIST = [
{ key: 'ALL_CARD', value: '์ „์ฒด๋ณด๊ธฐ', image: Assets.allCardIcon },
] as const

const COMPLETE_REQUEST_TYPE_OBJS = [
{ key: 'WAITING', value: '๊ฑฐ๋ž˜์„ฑ์‚ฌ ๋Œ€๊ธฐ์ค‘' },
{ key: 'ACCEPTED', value: '๊ฑฐ๋ž˜์„ฑ์‚ฌ ํ™•์ •' },
{ key: 'REFUSED', value: '๊ฑฐ๋ž˜์„ฑ์‚ฌ ๊ฑฐ์ ˆ๋จ' },
]

export {
PRICE_RANGE,
CATEGORY,
Expand All @@ -109,4 +115,5 @@ export {
CATEGORY_OBJS,
TRADE_TYPE_OBJS,
TRADE_STATUS_OBJS,
COMPLETE_REQUEST_TYPE_OBJS,
}
32 changes: 32 additions & 0 deletions src/services/complete-request/completeRequest.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import ApiEndPoint from '@/config/apiEndPoint'
import apiClient from '../apiClient'

const postCompleteRequest = async (fromCardId: number, toCardId: number) => {
const response = await apiClient.post(
ApiEndPoint.postCompleteRequest(),
{ fromCardId, toCardId },
{},
{
'Content-Type': 'application/json',
},
)
return response
}

const putCompleteRequest = async (
fromCardId: number,
toCardId: number,
isAccepted: boolean,
) => {
const response = await apiClient.post(
ApiEndPoint.putCompleteRequest(),
{ fromCardId, toCardId, isAccepted },
{},
{
'Content-Type': 'application/json',
},
)
return response
}

export { postCompleteRequest, putCompleteRequest }
3 changes: 3 additions & 0 deletions src/types/card.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
PRICE_RANGE_OBJS,
TRADE_STATUS_OBJS,
TRADE_TYPE_OBJS,
COMPLETE_REQUEST_TYPE_OBJS,
} from '@/constants/card'

interface Card {
Expand Down Expand Up @@ -51,6 +52,7 @@ type CategoryObjs = (typeof CATEGORY_OBJS)[number]
type PriceRangeObjs = (typeof PRICE_RANGE_OBJS)[number]
type TradeStatusObjs = (typeof TRADE_STATUS_OBJS)[number]
type TradeTypeObjs = (typeof TRADE_TYPE_OBJS)[number]
type CompleteRequestTypeObjs = (typeof COMPLETE_REQUEST_TYPE_OBJS)[number]

export type {
Category,
Expand All @@ -64,4 +66,5 @@ export type {
PriceRangeObjs,
TradeStatusObjs,
TradeTypeObjs,
CompleteRequestTypeObjs,
}