Skip to content
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
36 changes: 31 additions & 5 deletions apps/client/src/layout/Layout.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,36 @@
import { Outlet, useLocation } from 'react-router-dom';
import { Sidebar } from '@shared/components/sidebar/Sidebar';
import { ROUTES_CONFIG } from '@routes/routesConfig';
import { useGetHasJob } from '@shared/apis/queries';
import JobSelectionFunnel from '@shared/components/jobSelectionFunnel/JobSelectionFunnel';
import { Sidebar } from '@shared/components/sidebar/Sidebar';
import { useQueryClient } from '@tanstack/react-query';
import { Outlet, useLocation } from 'react-router-dom';

const Layout = () => {
const location = useLocation();
const queryClient = useQueryClient();

const isPolicyPage =
location.pathname === ROUTES_CONFIG.privacyPolicy.path ||
location.pathname === ROUTES_CONFIG.termsOfService.path;

const isSidebarHidden =
const isAuthPage =
location.pathname.startsWith(ROUTES_CONFIG.onboarding.path) ||
location.pathname.startsWith(ROUTES_CONFIG.login.path) ||
location.pathname.startsWith(ROUTES_CONFIG.onboardingCallback.path) ||
isPolicyPage;
location.pathname.startsWith(ROUTES_CONFIG.onboardingCallback.path);

const isSidebarHidden = isAuthPage || isPolicyPage;
const isLoggedIn = !!localStorage.getItem('token');

const { data: hasJobData, isLoading: isHasJobLoading } = useGetHasJob(
isLoggedIn && !isAuthPage
);

const shouldShowJobSelectionFunnel =
isLoggedIn &&
!isAuthPage &&
!isPolicyPage &&
!isHasJobLoading &&
hasJobData?.hasJob === false;

Comment on lines 24 to 34
Copy link

@coderabbitai coderabbitai bot Feb 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

โš ๏ธ Potential issue | ๐ŸŸ  Major

์ •์ฑ…/์•ฝ๊ด€ ํŽ˜์ด์ง€์—์„œ๋„ ํผ๋„์ด ์—ด๋ฆด ์ˆ˜ ์žˆ์–ด ๋ฒ•์  ๋ฌธ์„œ ์ ‘๊ทผ์„ ๋ง‰์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ˜„์žฌ ์กฐ๊ฑด์€ Line [29]-[32]์—์„œ !isPolicyPage๋ฅผ ์ œ์™ธํ•˜์ง€ ์•Š์•„ /policy, /terms์—์„œ๋„ ๋ชจ๋‹ฌ์ด ๋œฐ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•ด๋‹น ๊ฒฝ๋กœ๋Š” ํผ๋„์—์„œ ์ œ์™ธํ•˜๋Š” ๊ฒŒ ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ”ง ์ œ์•ˆ ์ˆ˜์ •์•ˆ
   const { data: hasJobData, isLoading: isHasJobLoading } = useGetHasJob(
-    isLoggedIn && !isAuthPage
+    isLoggedIn && !isAuthPage && !isPolicyPage
   );

   const shouldShowJobSelectionFunnel =
     isLoggedIn &&
     !isAuthPage &&
+    !isPolicyPage &&
     !isHasJobLoading &&
     hasJobData?.hasJob === false;
๐Ÿค– Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@apps/client/src/layout/Layout.tsx` around lines 24 - 33, The funnel can open
on policy/terms pages; update the shouldShowJobSelectionFunnel condition to
exclude legal pages by adding checks like && !isPolicyPage && !isTermsPage (or
use a single isLegalPage flag) so the expression becomes: isLoggedIn &&
!isAuthPage && !isPolicyPage && !isTermsPage && !isHasJobLoading &&
hasJobData?.hasJob === false; ensure isPolicyPage/isTermsPage (or derived
isLegalPage) are defined/derived in the same component before use.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

์ด๋ถ€๋ถ„๋„ ํ™•์ธํ•ด๋ณด์…จ๋‚˜์š” ?!?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jjangminii ๋„ค, ๋งž์Šต๋‹ˆ๋‹ค! CodeRabbit์ด ์ง€์ ํ•œ ๋ถ€๋ถ„์ด ํƒ€๋‹นํ•œ ์ด์Šˆ์ž…๋‹ˆ๋‹ค.

ํ˜„์žฌ ์ฝ”๋“œ๋ฅผ ๋ณด๋ฉด isPolicyPage๊ฐ€ ์ •์˜๋˜์–ด ์žˆ์ง€๋งŒ, ์ง๋ฌด ์„ ํƒ ํผ๋„์„ ํ‘œ์‹œํ•˜๋Š” ์กฐ๊ฑด์—์„œ๋Š” ์ œ์™ธ๋˜์ง€ ์•Š๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋กœ ์ธํ•ด ๋กœ๊ทธ์ธํ•œ ์‚ฌ์šฉ์ž๊ฐ€ ์ด์šฉ์•ฝ๊ด€์ด๋‚˜ ๊ฐœ์ธ์ •๋ณด์ฒ˜๋ฆฌ๋ฐฉ์นจ ํŽ˜์ด์ง€๋ฅผ ๋ณผ ๋•Œ๋„ ํผ๋„ ๋ชจ๋‹ฌ์ด ๋‚˜ํƒ€๋‚  ์ˆ˜ ์žˆ์–ด์„œ, ๋ฒ•์  ๋ฌธ์„œ ์ ‘๊ทผ์„ ๋ฐฉํ•ดํ•  ์ˆ˜ ์žˆ๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ˆ˜์ •ํ•˜๋Š” ๊ฒƒ์„ ๊ถŒ์žฅํ•ฉ๋‹ˆ๋‹ค:

const { data: hasJobData, isLoading: isHasJobLoading } = useGetHasJob(
  isLoggedIn && !isAuthPage && !isPolicyPage
);

const shouldShowJobSelectionFunnel =
  isLoggedIn &&
  !isAuthPage &&
  !isPolicyPage &&
  !isHasJobLoading &&
  hasJobData?.hasJob === false;

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด:

  1. ์ •์ฑ…/์•ฝ๊ด€ ํŽ˜์ด์ง€์—์„œ๋Š” hasJob API ์š”์ฒญ ์ž์ฒด๋ฅผ ํ•˜์ง€ ์•Š์Œ
  2. ํ•ด๋‹น ํŽ˜์ด์ง€์—์„œ๋Š” ํผ๋„์ด ์ ˆ๋Œ€ ํ‘œ์‹œ๋˜์ง€ ์•Š์Œ
  3. ์‚ฌ์šฉ์ž๊ฐ€ ๋ฒ•์  ๋ฌธ์„œ๋ฅผ ์ž์œ ๋กญ๊ฒŒ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Œ

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

์—‡ ๊ทธ๋ ‡๋„ค์š”! ํ•ด๋‹น ๋ถ€๋ถ„ ์กฐ๊ฑด ์ถ”๊ฐ€ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค ๐Ÿ‘

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like the humans are having a chat. I'll hop back into my burrow for now. If you need me again, just tag @coderabbitai in a new comment, and I'll come hopping out!

return (
<>
Expand All @@ -23,6 +40,15 @@ const Layout = () => {
<Outlet />
</main>
</div>
{shouldShowJobSelectionFunnel && (
<div className="fixed inset-0 z-[2000] flex items-center justify-center bg-black/40 p-4">
<JobSelectionFunnel
onComplete={() => {
queryClient.invalidateQueries({ queryKey: ['hasJob'] });
}}
/>
</div>
)}
</>
);
};
Expand Down
14 changes: 0 additions & 14 deletions apps/client/src/pages/remind/Remind.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import {
useGetArticleDetail,
usePutArticleReadStatus,
} from '@shared/apis/queries';
import JobSelectionFunnel from '@shared/components/jobSelectionFunnel/JobSelectionFunnel';
import TooltipCard from '@shared/components/tooltipCard/TooltipCard';
import { useInfiniteScroll } from '@shared/hooks/useInfiniteScroll';
import { useQueryClient } from '@tanstack/react-query';
Expand All @@ -35,9 +34,6 @@ const Remind = () => {
const [activeBadge, setActiveBadge] = useState<'read' | 'notRead'>('notRead');
const [isDeleteOpen, setIsDeleteOpen] = useState(false);
const [deleteTargetId, setDeleteTargetId] = useState<number | null>(null);
const [showJobSelectionFunnel, setShowJobSelectionFunnel] = useState(
() => localStorage.getItem('hasJob') !== 'true'
);
const scrollContainerRef = useRef<HTMLDivElement>(null);

const formattedDate = useMemo(() => {
Expand Down Expand Up @@ -254,16 +250,6 @@ const Remind = () => {
</div>
</div>
)}

{showJobSelectionFunnel && (
<div className="fixed inset-0 z-[2000] flex items-center justify-center bg-black/40 p-4">
<JobSelectionFunnel
onComplete={() => {
setShowJobSelectionFunnel(false);
}}
/>
</div>
)}
</div>
);
};
Expand Down
11 changes: 10 additions & 1 deletion apps/client/src/shared/apis/axios.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import apiRequest from '@shared/apis/setting/axiosInstance';
import { EditArticleRequest, JobsResponse } from '@shared/types/api';
import {
EditArticleRequest,
HasJobResponse,
JobsResponse,
} from '@shared/types/api';
import { formatLocalDateTime } from '@shared/utils/formatDateTime';

export const getDashboardCategories = async () => {
Expand Down Expand Up @@ -84,6 +88,11 @@ export const getMyProfile = async () => {
return data.data;
};

export const getHasJob = async (): Promise<HasJobResponse> => {
const { data } = await apiRequest.get('/api/v3/users/job');
return data.data;
};

export const getJobs = async (): Promise<JobsResponse> => {
const { data } = await apiRequest.get('/api/v3/enums/jobs');
return data.data;
Expand Down
19 changes: 19 additions & 0 deletions apps/client/src/shared/apis/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
getArticleDetail,
getDashboardCategories,
getGoogleProfile,
getHasJob,
getJobs,
getMyProfile,
patchUserJob,
Expand All @@ -22,6 +23,7 @@ import {
ArticleReadStatusResponse,
DashboardCategoriesResponse,
EditArticleRequest,
HasJobResponse,
JobsResponse,
} from '@shared/types/api';
import { fetchOGData } from '@shared/utils/fetchOgData';
Expand Down Expand Up @@ -182,6 +184,16 @@ export const useGetMyProfile = () => {
});
};

export const useGetHasJob = (
enabled = true
): UseQueryResult<HasJobResponse, AxiosError> => {
return useQuery({
queryKey: ['hasJob'],
queryFn: getHasJob,
enabled,
});
};

export const useGetJobs = (): UseQueryResult<JobsResponse, AxiosError> => {
return useQuery({
queryKey: ['jobs'],
Expand All @@ -199,7 +211,14 @@ export const useSuspenseGetJobs = () => {
};

export const usePatchUserJob = () => {
const queryClient = useQueryClient();

return useMutation({
mutationFn: (data: patchUserJobRequest) => patchUserJob(data),
onSuccess: () => {
queryClient.invalidateQueries({
queryKey: ['hasJob'],
});
},
});
};
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Icon } from '@pinback/design-system/icons';
import { Button } from '@pinback/design-system/ui';
import { useQueryClient } from '@tanstack/react-query';
import formatRemindTime from '@shared/utils/formatRemindTime';
import { useEffect, useRef } from 'react';
import { useNavigate } from 'react-router-dom';
Expand All @@ -22,6 +23,7 @@ export default function ProfilePopup({
remindTime,
}: ProfilePopupProps) {
const navigate = useNavigate();
const queryClient = useQueryClient();
const popupRef = useRef<HTMLDivElement>(null);

useEffect(() => {
Expand All @@ -42,6 +44,8 @@ export default function ProfilePopup({
const handleLogout = () => {
localStorage.removeItem('token');
localStorage.removeItem('email');
localStorage.removeItem('userId');
queryClient.clear();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

๋กœ๊ทธ์•„์›ƒ ์‹œ ๋‹จ์ˆœํžˆ ํ† ํฐ๋งŒ ์ œ๊ฑฐํ•˜๋ฉด ๋œ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ๋Š”๋ฐ React Query ์บ์‹œ์— ์ด์ „ ์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ๊ฐ€ ๋‚จ์•„ ์žˆ์„ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์„ ๋†“์ณค๋„ค์š”

ํ† ํฐ ์‚ญ์ œ๋ฟ ์•„๋‹ˆ๋ผ ์บ์‹œ ์ดˆ๊ธฐํ™”๊นŒ์ง€ ํ•จ๊ป˜ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์ด ์‚ฌ์šฉ์ž ์ „ํ™˜ ์‹œ ๋ฐ์ดํ„ฐ ์ผ๊ด€์„ฑ๊ณผ ๋ณด์•ˆ ์ธก๋ฉด์—์„œ ๋” ์•ˆ์ „ํ•œ ๋ฐฉ๋ฒ•์ด๋ผ๊ณ  ์ดํ•ดํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•˜๋‚˜ ๋” ๋ฐฐ์›Œ๊ฐ€์š”-!

const sendExtensionLogout = () => {
window.postMessage(
{
Expand Down
4 changes: 4 additions & 0 deletions apps/client/src/shared/types/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,7 @@ export interface JobOption {
export interface JobsResponse {
jobs: JobOption[];
}

export interface HasJobResponse {
hasJob: boolean;
}
Loading