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
3 changes: 2 additions & 1 deletion src/app/(main)/project/[id]/_components/ProjectInfo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ const ProjectInfo = ({ id }: { id: string }) => {
<div className="prose desktop:bg-none bg-gray-0 desktop:p-10 max-w-none rounded-2xl border border-gray-300 px-5 py-6 text-gray-700">
<div dangerouslySetInnerHTML={{ __html: sanitizedContent }} />
</div>
<ProjectImage {...data} />
{/* TODO: 프로젝트 이미지 부분 복구 */}
{/* <ProjectImage {...data} /> */}
Comment thread
sunhwaaRj marked this conversation as resolved.
<Profile1 profileId={data.writerProfileId} />
</div>
</div>
Expand Down
5 changes: 3 additions & 2 deletions src/app/(main)/teampsylog/_components/BottomComment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,17 @@ const BottomComment = ({ isOpen, onClose, children }: BottomSheetProps) => {
return (
<>
<div
className={`desktop:hidden fixed inset-0 z-40 bg-black/70 ${shouldShow ? 'block' : 'hidden'}`}
className="desktop:hidden fixed inset-0 z-40 block bg-black/70"
onClick={handleClose}
style={{
opacity: isDragging ? Math.max(0, 1 - dragCurrentY / 300) : isOpen && !isClosing ? 1 : 0,
transition: isDragging ? 'none' : 'opacity 0.3s',
pointerEvents: shouldShow ? 'auto' : 'none',
}}
/>
{/* 바텀 시트 */}
<div
className={`desktop:hidden fixed inset-x-0 bottom-0 z-50 rounded-t-2xl bg-gray-200 ${shouldShow ? 'flex' : 'hidden'}`}
className="desktop:hidden fixed inset-x-0 bottom-0 z-50 flex rounded-t-2xl bg-gray-200"
style={{
height: '70vh',
maxHeight: '70vh',
Expand Down
21 changes: 17 additions & 4 deletions src/components/common/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import clsx from 'clsx';
import { useToast } from '@/contexts/ToastContext';
import { isLoggedIn as checkIsLoggedIn } from '@/utils/auth';
import Footer from './Footer';
import { logout } from '@/libs/api/auth';

const Header = () => {
const { userName, _hasHydrated } = useUserStore();
Expand Down Expand Up @@ -42,10 +43,22 @@ const Header = () => {
setIsProfileDropdownOpen((prev) => !prev);
};

const handleLogout = () => {
useUserStore.getState().clearUser();
setIsProfileDropdownOpen(false);
addToast({ message: '로그아웃 완료되었습니다.' });
const PROTECTED_PATH = [/^\/mypage/, /^\/project\/[^/]+(\/|$)/];

const handleLogout = async () => {
try {
await logout();
} catch (e) {
console.error('logout api failed', e);
} finally {
useUserStore.getState().clearUser();
setIsProfileDropdownOpen(false);
setIsMenuOpen(false);
addToast({ message: '로그아웃 완료되었습니다.' });

const isProtected = PROTECTED_PATH.some((pattern) => pattern.test(pathname));
if (isProtected) router.push('/');
}
};

return (
Expand Down
2 changes: 1 addition & 1 deletion src/components/login/LoginSocialList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export default function LoginSocialList() {
}, []);

// 고정된 순서: 네이버, 카카오, 구글
const fixedOrder: SocialType[] = ['naver', 'kakao', 'google'];
const fixedOrder: SocialType[] = ['kakao', 'google'];
Comment thread
sunhwaaRj marked this conversation as resolved.

return (
<div className="tablet:gap-4 mt-6 flex w-full flex-col items-center gap-2">
Expand Down
3 changes: 2 additions & 1 deletion src/components/recruit/editor/TextContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ const TextContent = ({ control, name = 'content', initialImages }: Props) => {
<p className={`body-8 self-end ${textLength < 50 ? 'text-red-100' : 'text-gray-600'}`}>
{textLength}
</p>
<PostImage initialImages={initialImages} />
{/* TODO: 이미지 업로드 버튼 복구 */}
{/* <PostImage initialImages={initialImages} /> */}
Comment thread
sunhwaaRj marked this conversation as resolved.
</div>
<TableBubbleMenu editor={editor} />
<TableHandles editor={editor} />
Expand Down
11 changes: 11 additions & 0 deletions src/libs/api/auth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { CommonResponse } from '@/types/common';
import api from './api';

export async function logout() {
const { data } = await api.post<CommonResponse<string>>('auth/logout');
Comment on lines +4 to +5

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

로그아웃 요청에 공용 401 재발급 인터셉터가 그대로 걸립니다.

Line 5는 src/libs/api/api.ts:43-67의 401 재시도//login 리다이렉트 경로를 그대로 타기 때문에, 액세스 토큰이 만료된 상태에서 로그아웃하면 세션을 한 번 더 연장하거나 의도치 않게 /login으로 튈 수 있습니다. 로그아웃 요청만큼은 이 인터셉터를 우회하는 별도 클라이언트나 예외 분기가 필요합니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/libs/api/auth.ts` around lines 4 - 5, The logout function triggers the
global 401 retry/login-redirect interceptor because it uses the default api
client; change logout (exported logout) to call a dedicated HTTP client that
bypasses the shared 401 interceptor (or use an existing option on the client to
disable interceptors) so the logout request does not trigger token-refresh/retry
or redirect logic. Locate the logout function and replace its use of api.post
with a no-interceptor client (e.g. apiNoRetry / apiWithoutAuthInterceptor) or
create such a client in the same module that clones the axios instance without
the 401 handler; ensure CommonResponse<string> is preserved and that other logic
in logout remains unchanged.


if (!data.isSuccess) {
throw new Error(data.message || 'Failed to logout');
}
return data.result;
}
Loading