Skip to content

Commit

Permalink
Feat: SSE 및 관리자 전용 참여 현황 열람 기능 추가 및 관련 수정 (#28)
Browse files Browse the repository at this point in the history
- SSE 핸들러 추가로 실시간 데이터 처리 기능 구현
- SSE 관련 타입 정의 및 관련 로직 수정
- 관리자 전용 참여 현황 열람 기능 추가
- 스타일 구조 수정으로 가독성 및 유지보수성 개선
- 상태 관리 로직 수정 및 최적화
  • Loading branch information
sunglitter committed Dec 9, 2024
1 parent e53ce7a commit 061937e
Show file tree
Hide file tree
Showing 14 changed files with 452 additions and 166 deletions.
2 changes: 1 addition & 1 deletion src/components/common/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const Header = () => {
const handleCommunityClick = (
e: React.MouseEvent<HTMLAnchorElement, MouseEvent>
) => {
if (!isLoggedIn || !isAdmin) {
if (!isLoggedIn && !isAdmin) {
e.preventDefault();
alert('로그인 후 이용할 수 있는 페이지입니다.');
setIsMobileMenuOpen(!isMobileMenuOpen);
Expand Down
2 changes: 1 addition & 1 deletion src/components/common/PostList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import SearchBar from './SearchBar';
import Pagination from './Pagination';
import { useNavigate } from 'react-router-dom';
import { SSEEvent, Post } from '../../types/postTypes';
import { getImageSrc } from '../../utils/GetImageSrc';
import { formatDateWithOffset } from '../../utils/formatDate';
import { getImageSrc } from '../../utils/GetImageSrc';

interface PostListProps {
selectedCategory: string;
Expand Down
13 changes: 7 additions & 6 deletions src/components/pages/admin/PostApprovalPage.tsx
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
import React, { useState, useEffect } from 'react';
import styled from 'styled-components';
import { useNavigate, useLocation } from 'react-router-dom';
import { fetchPostById } from '../community/api/postApi';
import { useNavigate, useLocation, useParams } from 'react-router-dom';
import { fetchPostById, handleSSEUpdate } from '../community/api/postApi';
import { approvePost, rejectPost } from './api/adminApi';
import { FaBackspace, FaAngleLeft, FaAngleRight } from 'react-icons/fa';
import { Post } from '../../../types/postTypes';
import { getImageSrc } from '../../../utils/GetImageSrc';
import { formatDateWithOffset } from '../../../utils/formatDate';

const PostApprovalPage = () => {
const { postId: paramPostId } = useParams<{ postId: string }>();
const location = useLocation();
const navigate = useNavigate();
const { postId } = location.state || {}; // PostList에서 전달된 postId
const postId = paramPostId || location.state?.communityPostId;
const [post, setPost] = useState<Post | null>(null);
const [currentIndex, setCurrentIndex] = useState(0);

Expand Down Expand Up @@ -53,7 +54,7 @@ const PostApprovalPage = () => {
const updatedTitle = post.title.startsWith('(수정요망)')
? post.title.replace(/^\(\)\s*/, '')
: post.title;

handleSSEUpdate(postId); // SSE 구독 시작
await approvePost(postId, updatedTitle); // 포스트 상태를 APPROVED로 변경
alert('게시물이 승인되었습니다.');
navigate('/admin/post'); // 승인 후 관리자 페이지로 리다이렉트
Expand All @@ -67,10 +68,10 @@ const PostApprovalPage = () => {
if (!post) return;
try {
// 제목에 '(수정요망)' 추가
const updatedTitle = post.title.startsWith('(수정요망)')
const updatedTitle = post.title.startsWith('(수정요망) ')
? post.title // 이미 '(수정요망)'이 있으면 그대로 유지
: `(수정요망) ${post.title}`;

handleSSEUpdate(postId); // SSE 구독 시작
await rejectPost(postId, updatedTitle); // 포스트 상태를 REJECTED로 변경
alert('게시물이 거절 처리되었습니다.');
navigate('/admin/post'); // 거절 후 관리자 페이지로 리다이렉트
Expand Down
8 changes: 4 additions & 4 deletions src/components/pages/admin/api/adminApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ export const approvePost = async (
throw new Error('Failed to approve post');
}
return response.data;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (error) {
console.error(`Error approving post with ID ${communityPostId}:`, error);
throw error;
throw new Error(`Error approving post with ID ${communityPostId}`);
}
};

Expand All @@ -63,8 +63,8 @@ export const rejectPost = async (
throw new Error('Failed to reject post');
}
return response.data;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
} catch (error) {
console.error(`Error rejecting post with ID ${communityPostId}:`, error);
throw error;
throw new Error(`Error rejecting post with ID ${communityPostId}`);
}
};
40 changes: 40 additions & 0 deletions src/components/pages/community/ParticipantList.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import React from 'react';
import { useAtom } from 'jotai';
import { sseDataAtom } from '../../../store/sseStore';
import { useAuth } from '../../../context/AuthContext';

const ParticipantList: React.FC = () => {
const [sseData] = useAtom(sseDataAtom);
const { isAdmin } = useAuth();

if (!isAdmin) {
// 관리자가 아니면 아무것도 표시하지 않음
return null;
}

if (!sseData || !sseData.participants.length) {
return <div>참여자 데이터가 없습니다.</div>;
}

return (
<div>
<h2>참여자 목록 (관리자 전용)</h2>
<ul>
{sseData.participants.map((participant) => (
<li key={participant.userId}>
<p>
닉네임: {participant.nickname} | 수량: {participant.quantity} |{' '}
{participant.isCancelled ? '취소됨' : '참여 중'} |{' '}
{participant.isPaymentCompleted ? '결제 완료' : '결제 대기'} |{' '}
</p>
</li>
))}
</ul>
<p>참여 인원: {sseData.participationCount}</p>
<p>결제 완료 인원: {sseData.paymentCount}</p>
<p>환불 완료 인원: {sseData.refundedCount}</p>
</div>
);
};

export default ParticipantList;
Loading

0 comments on commit 061937e

Please sign in to comment.