diff --git a/.gitignore b/.gitignore
index 475036a..9ee77e8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -25,3 +25,4 @@ dist-ssr
*.sw?
.vercel
+.env*.local
diff --git a/src/pages/home/HomePage.tsx b/src/pages/home/HomePage.tsx
index c2fd2eb..b6504bb 100644
--- a/src/pages/home/HomePage.tsx
+++ b/src/pages/home/HomePage.tsx
@@ -7,8 +7,6 @@ import {
useGetCompany,
usePostRecommendPostList,
} from "@/features/home";
-import { useDebounce } from "@/shared/lib/useDebounce";
-
import { ErrorBoundary } from "@/shared/ui/ErrorBoundary";
import { Loading } from "@/shared/ui/Loading";
import { SkeletonList } from "@/shared/ui/SkeletonList";
@@ -29,10 +27,11 @@ const SearchPostList = lazy(() =>
);
const HomePage = () => {
- const [selectedTab, setSelectedTab] = useState(0);
const [modal, setModal] = useState(false);
const { companies, toggleCompany, resetCompanies } = useCompanyStore();
-
+ const { user } = useUserStore();
+ const isLogin = !!user?.accessToken;
+ const navigate = useNavigate();
const { data: companyData } = useGetCompany();
const { mutate: postRecommendList, isPending: isRefreshing } =
usePostRecommendPostList();
@@ -40,25 +39,26 @@ const HomePage = () => {
const maxCompany = companyData?.companies.slice(0, 8) ?? [];
const [searchParams, setSearchParams] = useSearchParams();
- const searchQuery = searchParams.get("search");
- const debouncedInput = useDebounce(searchQuery, 200);
- const isSearching = debouncedInput && debouncedInput.trim() !== "";
- const { user } = useUserStore();
- const isLogin = !!user?.accessToken;
- const navigate = useNavigate();
+ const searchQuery = searchParams.get("search") ?? "";
+ const selectedTab = Number(searchParams.get("tab") ?? 0);
+
+ useEffect(() => {
+ if (!searchParams.get("tab") && !searchParams.get("search")) {
+ setSearchParams({ tab: "0" }, { replace: true });
+ }
+ }, []);
+
+ const isSearching = !!searchQuery.trim();
const handleTabChange = (tab: number) => {
if (tab === 1 && !isLogin) {
toast.info("로그인이 필요한 서비스입니다.", {
icon:
,
});
-
navigate("/login");
-
return;
}
- setSearchParams({});
- setSelectedTab(tab);
+ setSearchParams({ tab: String(tab) }, { replace: true });
};
useEffect(() => {
@@ -72,7 +72,7 @@ const HomePage = () => {
{isSearching
- ? `"${debouncedInput}" | TechFork`
+ ? `"${searchQuery}" | TechFork`
: `TechFork | ${TAB_MAP[selectedTab]}`}
@@ -103,7 +103,7 @@ const HomePage = () => {
<>
}>
-
+
>
diff --git a/src/pages/onboarding/Onboarding.tsx b/src/pages/onboarding/Onboarding.tsx
index 681ee07..1d23490 100644
--- a/src/pages/onboarding/Onboarding.tsx
+++ b/src/pages/onboarding/Onboarding.tsx
@@ -77,8 +77,25 @@ const Onboarding = () => {
-
이용약관
및
- 개인정보취급방침에
+
+
+ 이용약관
+
+
+ 및
+
+
+ 개인정보취급방침에
+
+
동의합니다.
diff --git a/src/widgets/header/SystemHeader.tsx b/src/widgets/header/SystemHeader.tsx
index 1c2a54d..a53a865 100644
--- a/src/widgets/header/SystemHeader.tsx
+++ b/src/widgets/header/SystemHeader.tsx
@@ -1,97 +1,51 @@
import Search from "@/assets/icons/search.svg";
import User from "@/assets/images/user.png";
import { useNavigate, useSearchParams } from "react-router-dom";
-import { useEffect, useRef, useState } from "react";
import { toast } from "react-toastify";
import Alert from "@/assets/icons/alert2.svg";
-import Logout from "@/assets/icons/confirm.svg";
import { useThemeToggle } from "@/shared/lib/useThemeToggle";
-import useUserStore from "@/shared/model/useUserStore";
import { MYPAGE_NAV } from "@/features/mypage";
import { useCompanyStore } from "@/features/home";
import { useGetMyProfile } from "@/shared/api/my";
-import { postLogout } from "@/features/Login";
import { cn } from "@/shared/lib/cn";
import { Button } from "@/shared/ui/button/Button";
+import { useUserMenu } from "./model/useUserMenu";
+import { useEffect, useState } from "react";
+import { useDebounce } from "@/shared/lib/useDebounce";
export const SystemHeader = () => {
const navigate = useNavigate();
- const [userModal, setUserModal] = useState(false);
- const modalRef = useRef(null);
const { isDark } = useThemeToggle();
-
- const { user, logout } = useUserStore();
- const { resetCompanies, companies } = useCompanyStore();
- console.log(companies);
- const isLogin = !!user?.accessToken;
-
+ const { resetCompanies } = useCompanyStore();
+ const { isLogin, userModal, setUserModal, modalRef, handleNavClick } =
+ useUserMenu();
const { data } = useGetMyProfile(isLogin);
- const [searchParams] = useSearchParams();
- const [input, setInput] = useState("");
-
- const handleLogout = async () => {
- try {
- await postLogout();
-
- toast.info(`로그아웃 되었습니다.`, {
- icon:
,
- });
- } catch (error) {
- console.error("로그아웃 실패:", error);
- } finally {
- logout();
- resetCompanies();
- setUserModal(false);
- navigate("/");
- }
- };
-
- const handleNavClick = (item: { name: string; nav?: string }) => {
- if (item.name === "로그아웃") {
- handleLogout();
- } else if (item.nav) {
- setUserModal(false);
- navigate(item.nav);
- }
- };
+ const [searchParams] = useSearchParams(); //tab
+ const [input, setInput] = useState(() => searchParams.get("search") ?? "");
+ const urlSearch = searchParams.get("search") ?? "";
useEffect(() => {
- const searchQuery = searchParams.get("search") || "";
- if (input !== searchQuery) {
- setInput(searchQuery);
- }
- }, [searchParams]);
-
+ setInput(urlSearch);
+ }, [urlSearch]);
+ const debouncedInput = useDebounce(input, 300);
useEffect(() => {
- if (input === "") {
- if (searchParams.get("search")) {
- navigate("/", { replace: true });
- }
- return;
- }
- if (input !== searchParams.get("search")) {
- navigate(`/?search=${input}`, { replace: true });
- }
- }, [input, navigate]);
+ const trimmed = debouncedInput.trim();
+ const currentSearch = searchParams.get("search") ?? "";
- useEffect(() => {
- const handleClick = (e: MouseEvent) => {
- if (!modalRef.current?.contains(e.target as Node))
- return setUserModal(false);
- };
+ if (trimmed === currentSearch) return;
- document.addEventListener("click", handleClick);
- return () => {
- //cleanup
- document.removeEventListener("click", handleClick);
- };
- }, []);
-
- useEffect(() => {
- if (userModal) {
- setInput("");
+ if (!trimmed) {
+ navigate("/?tab=0", { replace: true });
+ } else {
+ navigate(`/?search=${encodeURIComponent(trimmed)}`, { replace: true });
}
- }, [userModal]);
+ }, [debouncedInput]);
+
+ const handleLogoClick = () => {
+ resetCompanies();
+ setInput("");
+ navigate("/?tab=0");
+ };
return (