Skip to content

Commit

Permalink
Merge pull request #12 from boostcampwm-2024/refactor/code-refactor
Browse files Browse the repository at this point in the history
♻️ refactor: sonarQube에 나온 이슈 해결
  • Loading branch information
jungmyunggi authored Jan 14, 2025
2 parents 2f57894 + f2f6ca4 commit 0e36b52
Show file tree
Hide file tree
Showing 17 changed files with 106 additions and 78 deletions.
3 changes: 1 addition & 2 deletions client/src/api/services/rss.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import { BLOG } from "@/constants/endpoints";

import { axiosInstance } from "@/api/instance";
import { RegisterRss } from "@/types/rss";
import { RegisterResponse } from "@/types/rss";
import { RegisterRss, RegisterResponse } from "@/types/rss";

export const registerRss = async (data: RegisterRss): Promise<RegisterResponse> => {
const response = await axiosInstance.post<RegisterResponse>(BLOG.RSS.REGISTRER_RSS, data);
Expand Down
1 change: 0 additions & 1 deletion client/src/components/RssRegistration/RssUrlInput.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ interface RssUrlInputProps {
platform: PlatformType;
value: string;
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
placeholder?: string;
}

export const RssUrlInput = ({ platform, value, onChange }: RssUrlInputProps) => {
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/admin/layout/AdminMember.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ export default function AdminMember() {
const onError = (error: AxiosError) => {
const errorMessage =
typeof error.response?.data === "string" ? error.response.data : error.response?.data || error.message;
alert(`관리자 등록 실패: ${errorMessage}`);
alert(`관리자 등록 실패: ${JSON.stringify(errorMessage)}`);
};

const handleChange = (e: React.ChangeEvent<HTMLInputElement>, name: string) => {
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/chart/PieChartItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export default function PieChartItem({ data, title }: BarType) {
<ChartTooltip content={<ChartTooltipContent hideLabel />} />
<Pie data={data} dataKey="count" nameKey="platform">
{data.map((entry, index) => (
<Cell key={`cell-${index}`} fill={chartConfig[entry.platform]?.color || "#ccc"} />
<Cell key={`cell-${index}`} fill={chartConfig[entry.platform]?.color ?? "#ccc"} />
))}
<LabelList dataKey="platform" className="fill-background" stroke="none" fontSize={12} />
</Pie>
Expand Down
3 changes: 1 addition & 2 deletions client/src/components/chat/ChatButton.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { MessageCircleMore } from "lucide-react";
import { X } from "lucide-react";
import { MessageCircleMore, X } from "lucide-react";

import { useSidebar } from "@/components/ui/sidebar";

Expand Down
20 changes: 9 additions & 11 deletions client/src/components/chat/ChatItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,18 +18,16 @@ export default function ChatItem({ chatItem, isSameUser }: ChatItemProps) {
return (
<div className="flex flex-col ">
{!isSameUser ? (
<>
<span className="flex gap-1 items-center text-left">
<Avatar>
<Avvvatars value={chatItem.username} style="shape" />
</Avatar>
{/* 이름, 시간 */}
<span className="flex gap-2 items-center inline-block">
<span className="text-sm">{chatItem.username}</span>
<span className="text-xs">{formatTime(chatItem.timestamp)}</span>
</span>
<span className="flex gap-1 items-center text-left">
<Avatar>
<Avvvatars value={chatItem.username} style="shape" />
</Avatar>
{/* 이름, 시간 */}
<span className="flex gap-2 items-center inline-block">
<span className="text-sm">{chatItem.username}</span>
<span className="text-xs">{formatTime(chatItem.timestamp)}</span>
</span>
</>
</span>
) : (
<></>
)}
Expand Down
5 changes: 2 additions & 3 deletions client/src/components/chat/layout/ChatFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,10 @@ import { SheetFooter } from "@/components/ui/sheet";

import { useKeyboardShortcut } from "@/hooks/common/useKeyboardShortcut";

import { useChatValueStroe } from "@/store/useChatStore";
import { useChatStore } from "@/store/useChatStore";
import { useChatValueStore, useChatStore } from "@/store/useChatStore";

export default function ChatFooter() {
const { message, setMessage } = useChatValueStroe();
const { message, setMessage } = useChatValueStore();
const { sendMessage } = useChatStore();

const handleSendMessage = () => {
Expand Down
48 changes: 27 additions & 21 deletions client/src/components/chat/layout/ChatSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,43 +7,49 @@ import ChatSkeleton from "@/components/chat/layout/ChatSkeleton";
import { ScrollArea } from "@/components/ui/scroll-area";

import { useChatStore } from "@/store/useChatStore";
import { ChatType } from "@/types/chat";

const FullChatWarning = () => (
<div className="flex flex-col justify-center items-center h-full mt-[30vh]">
<CircleAlert color="red" size={200} />
<p>채팅창 인원이 500명 이상입니다</p>
<p>잠시 기다렸다가 새로고침을 해주세요</p>
</div>
);

const RenderHistory = ({ chatHistory, isFull }: { chatHistory: ChatType[]; isFull: boolean }) => {
if (chatHistory.length === 0) return <ChatSkeleton number={14} />;
return isFull ? (
<FullChatWarning />
) : (
<span className="flex flex-col gap-3 px-3">
{chatHistory.map((item, index) => {
const isSameUser = index > 0 && chatHistory[index - 1]?.username === item.username;
return <ChatItem key={item.timestamp} chatItem={item} isSameUser={isSameUser} />;
})}
</span>
);
};

export default function ChatSection({ isFull }: { isFull: boolean }) {
const scrollRef = useRef<HTMLDivElement>(null);
const { chatHistory } = useChatStore();

useEffect(() => {
if (scrollRef.current) {
const scrollContent = scrollRef.current.querySelector("[data-radix-scroll-area-viewport]");
if (scrollContent) {
if (scrollContent && chatHistory.length > 0) {
scrollContent.scrollTo({
top: scrollContent.scrollHeight,
behavior: "smooth",
});
}
}
}, [chatHistory]);

const RenderHistory = () => {
if (chatHistory.length === 0) return <ChatSkeleton number={14} />;
return isFull ? (
<div className="flex flex-col justify-center items-center h-full mt-[30vh]">
<CircleAlert color="red" size={200} />
<p>채팅창 인원이 500명 이상입니다</p>
<p>잠시 기다렸다가 새로고침을 해주세요</p>
</div>
) : (
<span className="flex flex-col gap-3 px-3">
{chatHistory.map((item, index) => {
const isSameUser = index > 0 && chatHistory[index - 1].username === item.username;
return <ChatItem key={index} chatItem={item} isSameUser={isSameUser} />;
})}
</span>
);
};
}, [chatHistory.length]);

return (
<ScrollArea ref={scrollRef} className="h-full">
{RenderHistory()}
<RenderHistory chatHistory={chatHistory} isFull={isFull} />
</ScrollArea>
);
}
6 changes: 3 additions & 3 deletions client/src/components/layout/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,9 @@ export default function Header() {
<div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div className="h-20 items-center overflow-hidden flex justify-between relative z-50">
{/* 로고 영역 */}
<div className="flex-shrink-0 relative z-50">
<img className="h-14 w-auto cursor-pointer" src={logo} alt="Logo" onClick={() => location.reload()} />
</div>
<button className="flex-shrink-0 relative z-50" onClick={() => location.reload()}>
<img className="h-14 w-auto cursor-pointer" src={logo} alt="Logo" />
</button>

{/* 중앙 검색 버튼 */}
<div className="absolute left-1/2 transform -translate-x-1/2 w-full flex justify-center z-40">
Expand Down
4 changes: 1 addition & 3 deletions client/src/components/layout/SideButton.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import { Home } from "lucide-react";
import { ArrowUp } from "lucide-react";
import { ChartArea } from "lucide-react";
import { Home, ArrowUp, ChartArea } from "lucide-react";

import { Chat } from "@/components/chat/Chat";
import { OpenChat } from "@/components/chat/ChatButton";
Expand Down
4 changes: 2 additions & 2 deletions client/src/components/search/SearchButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Search } from "lucide-react";

export default function SearchButton({ handleSearchModal }: { handleSearchModal: () => void }) {
return (
<div
<button
className="w-full px-4 py-3
bg-white
border border-primary
Expand All @@ -21,6 +21,6 @@ export default function SearchButton({ handleSearchModal }: { handleSearchModal:
>
<span className="text-sm font-medium">검색</span>
<Search size={16} className="text-primary group-hover:text-secondary transition-colors" />
</div>
</button>
);
}
4 changes: 2 additions & 2 deletions client/src/components/search/SearchFilters/FilterButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,14 @@ export default function FilterButton() {
<CommandGroup heading="필터">
<div className="flex flex-col gap-1">
{filterOptions.map(({ label, filter, icon }) => (
<div
<button
key={filter}
className={getItemClassName(currentFilter === filter)}
onClick={() => handleFilterClick(filter)}
>
{icon}
<span>{label}</span>
</div>
</button>
))}
</div>
</CommandGroup>
Expand Down
9 changes: 7 additions & 2 deletions client/src/components/search/SearchHigilight.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { useMemo } from "react";

interface SearchHighlightProps {
text: string;
highlight: string;
Expand All @@ -8,8 +10,11 @@ function escapeRegExp(string: string): string {
}

export default function SearchHighlight({ text, highlight }: SearchHighlightProps) {
const escapedHighlight = escapeRegExp(highlight);
const parts = text.split(new RegExp(`(${escapedHighlight})`, "gi"));
const parts = useMemo(() => {
if (!highlight) return [text];
const escapedHighlight = escapeRegExp(highlight);
return text.split(new RegExp(`(${escapedHighlight})`, "gi"));
}, [text, highlight]);

return (
<>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ export default function SearchResults() {
page,
pageSize: RESULT_PER_PAGE,
});
const totalItems = data?.data.totalCount || 0;
const totalPages = data?.data.totalPages || 0;
const totalItems = data?.data.totalCount ?? 0;
const totalPages = data?.data.totalPages ?? 0;
const results = data?.data.result || [];
const renderContent = {
//검색 전
Expand Down
2 changes: 1 addition & 1 deletion client/src/hooks/queries/useInfiniteScrollQuery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function useInfiniteScrollQuery<T extends Identifiable>({
queryFn: ({ pageParam = 0 }) =>
fetchFn({
limit: 12,
lastId: pageParam as number,
lastId: pageParam,
}),
getNextPageParam: (lastPage) => {
if (!lastPage.hasMore) return undefined;
Expand Down
1 change: 0 additions & 1 deletion client/src/hooks/queries/useSearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { useState, useEffect } from "react";

import { debounce } from "@/utils/debounce";

// import axios from "axios"; //mockAPI사용시
import { getSearch } from "@/api/services/search";
import { SearchRequest } from "@/types/search";
import { useQuery, useQueryClient } from "@tanstack/react-query";
Expand Down
66 changes: 46 additions & 20 deletions client/src/store/useChatStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,32 +17,47 @@ interface ChatStore {
export const useChatStore = create<ChatStore>((set) => {
let socket: Socket | null = null;

// 소켓 초기화 함수
const initializeSocket = () => {
if (socket) return socket; // 이미 존재하면 그대로 반환

socket = io(CHAT_SERVER_URL, {
path: "/chat",
transports: ["websocket"],
reconnection: true, // 자동 재연결 활성화
reconnectionAttempts: 5, // 최대 5번 재시도
reconnectionDelay: 1000, // 1초 간격으로 재시도
});

// 서버 연결 성공 시
socket.on("connect", () => {});

// 서버로부터 메시지 받기
socket.on("message", (data) => {
set((state) => ({
chatHistory: [...state.chatHistory, data],
}));
});

// 사용자 수 업데이트 받기
socket.on("updateUserCount", (data) => {
set({ userCount: data.userCount });
});

// 서버 연결 해제 시
socket.on("disconnect", () => {});

return socket;
};

return {
chatHistory: [],
userCount: 0,

// Socket 연결 함수
connect: () => {
if (socket) return; // 이미 연결된 경우 중복 방지

socket = io(CHAT_SERVER_URL, { path: "/chat", transports: ["websocket"] });

// 서버 연결 성공 시
socket.on("connect", () => {});
// 서버로부터 메시지 받기
socket.on("message", (data) => {
set((state) => ({
chatHistory: [...state.chatHistory, data],
}));
});

// 사용자 수 업데이트 받기
socket.on("updateUserCount", (data) => {
set({ userCount: data.userCount });
});

// 서버 연결 해제 시
socket.on("disconnect", () => {});
initializeSocket();
},

// Socket 연결 해제 함수
Expand All @@ -54,28 +69,39 @@ export const useChatStore = create<ChatStore>((set) => {
// 이전 채팅 기록 받아오기
getHistory: () => {
if (socket) {
socket.emit("getHistory");
socket.on("chatHistory", (data) => {
set(() => ({
chatHistory: data,
}));
});
} else {
const newSocket = initializeSocket();
newSocket.emit("getHistory");
}
},

// 메시지 전송 함수
sendMessage: (message: string) => {
if (socket) {
socket.emit("message", { message });
} else {
// 소켓이 없으면 연결 후 메시지 전송
const newSocket = initializeSocket();
newSocket.on("connect", () => {
newSocket.emit("message", { message });
});
}
},
};
});

interface ChatValue {
message: string;
setMessage: (newMessage: string) => void;
}
export const useChatValueStroe = create<ChatValue>((set) => ({

export const useChatValueStore = create<ChatValue>((set) => ({
message: "",
setMessage: (newMessage: string) => set({ message: newMessage }),
}));

0 comments on commit 0e36b52

Please sign in to comment.