Skip to content

Commit f83832b

Browse files
committed
FEAT 상태 변경 관련 간단히, wip (#develop)
1 parent 77c51e5 commit f83832b

File tree

11 files changed

+209
-15
lines changed

11 files changed

+209
-15
lines changed
4.4 KB
Loading
4.4 KB
Loading

services/ahhachul.com/src/apis/request/lostFound.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import type {
1111
CommentList,
1212
WithPostId,
1313
LostFoundEditForm,
14+
LostStatus,
1415
} from '@/types';
1516

1617
export const fetchLostFoundList = async (req: LostFoundListParams) => {
@@ -100,3 +101,21 @@ export const deleteLostFound = async (articleId: number) => {
100101
// TODO: sentry에 로그 남김
101102
throw new Error('Unexpected state in Promise.allSettled');
102103
};
104+
105+
export const updateLostFoundStatus = async (articleId: number, status: LostStatus) => {
106+
const [response] = await Promise.allSettled([
107+
axiosInstance.patch<ApiResponse<WithPostId>>(`/lost-posts/${articleId}/status`, { status }),
108+
sleep(750),
109+
]);
110+
111+
if (response.status === 'rejected') {
112+
throw response.reason;
113+
}
114+
115+
if (response.status === 'fulfilled') {
116+
return response.value.data;
117+
}
118+
119+
// TODO: sentry에 로그 남김
120+
throw new Error('Unexpected state in Promise.allSettled');
121+
};

services/ahhachul.com/src/assets/icons/jsx/icons.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,15 @@ function PhraseIcon() {
203203
);
204204
}
205205

206+
function LostIcon() {
207+
return (
208+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
209+
<rect x="3" y="3" width="18" height="18" rx="2" fill="#2ACF6C" />
210+
<path d="M10 16.4L6 12.4L7.4 11L10 13.6L16.6 7L18 8.4L10 16.4Z" fill="#FBFBFB" />
211+
</svg>
212+
);
213+
}
214+
206215
function CrossIcon() {
207216
return (
208217
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
@@ -237,4 +246,5 @@ export {
237246
WarningIcon,
238247
PhraseIcon,
239248
CrossIcon,
249+
LostIcon,
240250
};

services/ahhachul.com/src/components/common/postDropEllipsis/PostDropEllipsis.component.tsx

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import useMeasure from 'react-use-measure';
33

44
import styled from '@emotion/styled';
55
import { useQueryClient } from '@tanstack/react-query';
6+
import { Check } from 'lucide-react';
67
// import { useQueryClient } from '@tanstack/react-query';
78
import { AnimatePresence, motion } from 'motion/react';
89
import { Drawer } from 'vaul';
@@ -12,20 +13,26 @@ import { sleep } from '@ahhachul/utils';
1213
import { CloseIcon, DangerIcon, PhraseIcon, WarningIcon } from '@/assets/icons/jsx/icons';
1314
import { MoreVerticalIcon } from '@/assets/icons/system';
1415
import { useUser } from '@/hooks/domain';
16+
import useUpdateLostFound from '@/hooks/domain/lostFound/useUpdateLostFound';
1517
import { communityKeys, useDeleteCommunity } from '@/services/community';
1618
import { complaintKeys, useDeleteComplaint } from '@/services/complaint';
1719
import { lostFoundKeys, useDeleteLostFound } from '@/services/lostFound';
1820
import { useFlow } from '@/stackflow';
21+
import { LostStatus } from '@/types';
1922

2023
import * as S from './PostDropEllipsis.styled';
2124

2225
export interface PostDropEllipsisProps {
26+
isLost?: boolean;
27+
status?: LostStatus;
2328
articleId: string;
2429
createdBy: number;
2530
queryKey: readonly unknown[];
2631
}
2732

2833
const PostDropEllipsis = ({
34+
isLost,
35+
status,
2936
articleId,
3037
createdBy,
3138
queryKey,
@@ -66,7 +73,14 @@ const PostDropEllipsis = ({
6673
switch (view) {
6774
case 'default':
6875
return isAuthor ? (
69-
<DefaultView setView={setView} handleEdit={handleEdit} />
76+
<DefaultView
77+
isLost={isLost}
78+
status={status}
79+
articleId={articleId}
80+
setView={setView}
81+
handleEdit={handleEdit}
82+
handleClose={handleClose}
83+
/>
7084
) : (
7185
<ReportView handleClose={handleClose} />
7286
);
@@ -165,18 +179,53 @@ function Header({
165179
}
166180

167181
function DefaultView({
182+
isLost,
183+
status,
184+
articleId,
168185
setView,
169186
handleEdit,
187+
handleClose,
170188
}: {
189+
isLost?: boolean;
190+
status?: LostStatus;
191+
articleId: string;
171192
setView: (view: string) => void;
172193
handleEdit: () => void;
194+
handleClose: () => void;
173195
}) {
196+
const queryClient = useQueryClient();
197+
const { mutate } = useUpdateLostFound();
198+
const handleLost = () => {
199+
mutate(
200+
{
201+
articleId: +articleId,
202+
status: status === 'COMPLETE' ? 'PROGRESS' : 'COMPLETE',
203+
},
204+
{
205+
onSuccess: () => {
206+
handleClose();
207+
setTimeout(() => {
208+
queryClient.invalidateQueries({
209+
queryKey: lostFoundKeys.detail(+articleId),
210+
});
211+
}, 1000);
212+
},
213+
},
214+
);
215+
};
216+
174217
return (
175218
<>
176219
<S.DefaultViewHeader>
177220
<S.DefaultViewTitle>설정</S.DefaultViewTitle>
178221
</S.DefaultViewHeader>
179222
<S.ButtonContainer>
223+
{isLost && (
224+
<S.GreenButton onClick={handleLost}>
225+
<Check size={21} color="white" />
226+
{status === 'PROGRESS' ? '습득 완료' : '상태 변경'}
227+
</S.GreenButton>
228+
)}
180229
<S.Button onClick={handleEdit}>
181230
<PhraseIcon />
182231
수정하기

services/ahhachul.com/src/components/common/postDropEllipsis/PostDropEllipsis.styled.tsx

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,6 @@ export const DefaultViewHeader = styled.header`
172172
display: flex;
173173
height: 72px;
174174
align-items: center;
175-
border-bottom: 1px solid #f7f7f7;
176175
padding-left: 8px;
177176
margin-bottom: 16px;
178177
`;
@@ -194,3 +193,10 @@ export const DangerButton = styled.button`
194193
background-color: #fff0f0;
195194
color: #ff3f40;
196195
`;
196+
197+
export const GreenButton = styled.button`
198+
${buttonBase}
199+
200+
background-color: #4ade80; /* 초록색 배경 */
201+
color: white;
202+
`;

services/ahhachul.com/src/components/domain/lostFound/postDetail/headerActions/LostFoundHeaderActions.component.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,18 @@ import { ShareIcon } from '@/assets/icons/system';
44
import { UiComponent } from '@/components';
55
import { useNativeBridge } from '@/contexts';
66
import { lostFoundKeys } from '@/services/lostFound';
7+
import type { LostStatus } from '@/types';
78
import { getSharePageURL } from '@/utils/share';
89

910
import * as S from './LostFoundHeaderActions.styled';
1011

1112
interface LostFoundHeaderActionsProps {
1213
id: number;
14+
status: LostStatus;
1315
createdBy: number;
1416
}
1517

16-
const LostFoundHeaderActions = ({ id, createdBy }: LostFoundHeaderActionsProps) => {
18+
const LostFoundHeaderActions = ({ id, status, createdBy }: LostFoundHeaderActionsProps) => {
1719
const { params, isActive } = useActivity();
1820
const { bridge, isBridgeInitialized } = useNativeBridge();
1921

@@ -34,6 +36,8 @@ const LostFoundHeaderActions = ({ id, createdBy }: LostFoundHeaderActionsProps)
3436
<ShareIcon />
3537
</S.ActionButton>
3638
<UiComponent.PostDropEllipsis
39+
isLost
40+
status={status}
3741
articleId={params.id!}
3842
createdBy={createdBy}
3943
queryKey={lostFoundKeys.detail(id)}

services/ahhachul.com/src/components/domain/lostFound/postDetail/template/LostFoundDetail.component.tsx

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { LazyLoadImage } from 'react-lazy-load-image-component';
2+
13
import { formatDateTime, getRandomNumber } from '@ahhachul/utils';
24

35
import { LostFoundComponent, UiComponent } from '@/components';
@@ -33,7 +35,11 @@ const LostFoundDetail = ({ id }: LostFoundDetailProps) => {
3335

3436
return (
3537
<>
36-
<LostFoundComponent.LostFoundDetailHeaderActions id={id} createdBy={+post.createdBy} />
38+
<LostFoundComponent.LostFoundDetailHeaderActions
39+
id={id}
40+
status={post.status}
41+
createdBy={+post.createdBy}
42+
/>
3743

3844
<S.ArticleWrapper>
3945
<UiComponent.ImageCarousel label={post.title} images={images} />
@@ -52,13 +58,42 @@ const LostFoundDetail = ({ id }: LostFoundDetailProps) => {
5258
{post.isFromLost112 && (
5359
<>
5460
<S.Lost112Wrapper>
55-
{/* <Image src="/images/lost112.png" alt="lost112-image" width={24} height={24} priority /> */}
61+
<LazyLoadImage src="/lost112.png" alt="lost112-image" width={24} height={24} />
5662
<S.Lost112Text>로스트 112에 등록된 분실물입니다.</S.Lost112Text>
5763
</S.Lost112Wrapper>
5864
<Lost112InfoTable post={post} />
5965
</>
6066
)}
6167

68+
{post.status === 'COMPLETE' && (
69+
<S.CompleteWrapper>
70+
<svg
71+
width="24"
72+
height="24"
73+
viewBox="0 0 24 24"
74+
fill="none"
75+
xmlns="http://www.w3.org/2000/svg"
76+
>
77+
<path
78+
d="M12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21Z"
79+
stroke="white"
80+
strokeWidth="2"
81+
strokeMiterlimit="10"
82+
strokeLinecap="round"
83+
strokeLinejoin="round"
84+
/>
85+
<path
86+
d="M15 10L11 14L9 12"
87+
stroke="white"
88+
strokeWidth="2"
89+
strokeLinecap="round"
90+
strokeLinejoin="round"
91+
/>
92+
</svg>
93+
<S.CompleteText>유실물 찾기 완료</S.CompleteText>
94+
</S.CompleteWrapper>
95+
)}
96+
6297
<S.ContentContainer>
6398
{post.isFromLost112 || !isLexicalContent(post.content) ? (
6499
<S.TextContent>{formatLost112Content(post.content)}</S.TextContent>
@@ -70,12 +105,12 @@ const LostFoundDetail = ({ id }: LostFoundDetailProps) => {
70105
</S.ContentContainer>
71106
</S.ArticleWrapper>
72107

73-
<LostFoundComponent.RecommendPostList posts={post.recommendPosts} />
74108
<LostFoundComponent.LostFoundCommentList
75109
id={id}
76110
commentCnt={post.commentCnt}
77111
isArticleAuthor={isArticleAuthor}
78112
/>
113+
<LostFoundComponent.RecommendPostList posts={post.recommendPosts} />
79114
<LostFoundComponent.CommentInput id={id} />
80115
<S.Padding />
81116
</>

services/ahhachul.com/src/components/domain/lostFound/postDetail/template/LostFoundDetail.styled.tsx

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import styled from '@emotion/styled';
44
export const ArticleWrapper = styled.article``;
55

66
export const ContentWrapper = styled.div`
7-
padding: 20px 20px 24px;
7+
padding: 20px 20px 0 20px;
88
`;
99

1010
export const TitleWrapper = styled.div`
@@ -73,8 +73,27 @@ export const Lost112Text = styled.span`
7373
`}
7474
`;
7575

76+
export const CompleteWrapper = styled.div`
77+
${({ theme }) => css`
78+
padding: 0 20px;
79+
display: flex;
80+
align-items: center;
81+
height: 48px;
82+
width: 100%;
83+
gap: 8px;
84+
background-color: ${theme.colors['key-color']};
85+
`}
86+
`;
87+
88+
export const CompleteText = styled.span`
89+
${({ theme }) => css`
90+
${theme.fonts.titleSmall};
91+
color: ${theme.colors.white};
92+
`}
93+
`;
94+
7695
export const ContentContainer = styled.div`
77-
padding: 0 20px;
96+
padding: 24px 20px 0;
7897
`;
7998

8099
export const TextContent = styled.div`
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { useMutation } from '@tanstack/react-query';
2+
3+
import { updateLostFoundStatus } from '@/apis/request';
4+
import { LostStatus } from '@/types';
5+
6+
const useUpdateLostFound = () => {
7+
return useMutation({
8+
mutationFn: ({ articleId, status }: { articleId: number; status: LostStatus }) =>
9+
updateLostFoundStatus(articleId, status),
10+
});
11+
};
12+
13+
export default useUpdateLostFound;

0 commit comments

Comments
 (0)