Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
5 changes: 5 additions & 0 deletions apps/client/src/shared/apis/axios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,8 @@ export const deleteRemindArticle = async (id: number) => {
const response = await apiRequest.delete(`/api/v1/articles/${id}`);
return response;
};

export const getGoogleProfile = async () => {
const { data } = await apiRequest.get('/api/v2/users/me/google-profile');
return data.data;
};
9 changes: 9 additions & 0 deletions apps/client/src/shared/apis/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
getArticleDetail,
getAcorns,
deleteRemindArticle,
getGoogleProfile,
} from '@shared/apis/axios';
import { AxiosError } from 'axios';
import {
Expand Down Expand Up @@ -136,3 +137,11 @@ export const useGetPageMeta = (url: string) => {
retry: false,
});
};

export const useGetGoogleProfile = () => {
return useQuery({
queryKey: ['googleProfile'],
queryFn: getGoogleProfile,
staleTime: Infinity,
});
};
Comment on lines +142 to +148
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

이 부분은 따로 바뀌는 경우가 없어서 staleTimeInfinity로 지정하신거죠??

21 changes: 20 additions & 1 deletion apps/client/src/shared/components/sidebar/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
useGetArcons,
usePutCategory,
useDeleteCategory,
useGetGoogleProfile,
} from '@shared/apis/queries';
import { useEffect, useState } from 'react';
import { useQueryClient } from '@tanstack/react-query';
Expand All @@ -33,6 +34,9 @@ export function Sidebar() {
const { mutate: createCategory } = usePostCategory();
const { data, isPending } = useGetArcons();
const { mutate: deleteCategory } = useDeleteCategory();
const { data: googleProfileData } = useGetGoogleProfile();
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot Dec 17, 2025

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

프로필 로딩 및 에러 상태 처리 부재.

useGetGoogleProfile에서 isLoadingisError 상태를 추출하지 않아, 프로필 로딩 중이거나 요청이 실패해도 사용자에게 피드백이 없습니다. 특히 하단의 MyLevelItem은 로딩 스켈레톤을 보여주는 반면(226-228줄), 프로필 영역은 일관성 있는 로딩 처리가 없습니다.

다음과 같이 수정하세요:

-  const { data: googleProfileData } = useGetGoogleProfile();
+  const { data: googleProfileData, isLoading: isProfileLoading } = useGetGoogleProfile();

그리고 UI에서 로딩 상태를 처리하세요:

   <button
     className="h-[3.6rem] w-[3.6rem] flex-shrink-0 overflow-hidden rounded-full border border-gray-200"
     onClick={() => console.log('프로필 클릭', profileImageUrl)}
   >
-    {profileImageUrl ? (
+    {isProfileLoading ? (
+      <div className="h-full w-full animate-pulse bg-gray-200" />
+    ) : profileImageUrl ? (
       <img
         src={profileImageUrl}
         alt="프로필 이미지"
         className="h-full w-full object-cover"
       />
     ) : (
       <div className="h-full w-full bg-gray-200" />
     )}
   </button>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const { data: googleProfileData } = useGetGoogleProfile();
const { data: googleProfileData, isLoading: isProfileLoading } = useGetGoogleProfile();
🤖 Prompt for AI Agents
apps/client/src/shared/components/sidebar/Sidebar.tsx around line 37:
useGetGoogleProfile call only destructures data and omits isLoading/isError, so
the profile section lacks loading/error handling; update the hook call to
extract { data: googleProfileData, isLoading: isGoogleProfileLoading, isError:
isGoogleProfileError } (or similar names), then in the JSX conditionally render
a loading skeleton when isGoogleProfileLoading, an error fallback/message when
isGoogleProfileError, and the normal profile UI when data is present; also
ensure MyLevelItem’s existing skeleton behavior remains consistent with the new
profile-loading state so the sidebar shows a unified loading state.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

해당 API pending관련 처리는 이후에 추가될까요??

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@constantly-dev, 좋은 질문입니다!

현재 PR에서 로딩 상태 처리를 추가하실 계획인가요, 아니면 추후 별도 PR에서 진행하실 예정인가요?

만약 이후에 추가하실 계획이시라면, 추적을 위해 별도 이슈를 생성해드릴까요? 이렇게 하면 향후 UX 개선 작업 시 놓치지 않고 처리하실 수 있을 것 같습니다. 😊


🧠 Learnings used
Learnt from: constantly-dev
Repo: Pinback-Team/pinback-client PR: 2
File: pnpm-workspace.yaml:3-3
Timestamp: 2025-08-18T13:48:59.065Z
Learning: constantly-dev는 docs 디렉터리를 컨벤션 문서 추가용으로 사용할 예정이라고 명시했습니다.

Learnt from: constantly-dev
Repo: Pinback-Team/pinback-client PR: 5
File: apps/extension/src/index.css:1-1
Timestamp: 2025-08-19T17:18:57.678Z
Learning: constantly-dev는 디자인 시스템 설정 PR 머지 후 `import 'pinback/tailwind-config/shared-styles.css';`를 `app.css`나 `index.css`에서 사용하여 공유 스타일을 관리할 계획입니다.


const profileImageUrl = googleProfileData?.googleProfile || null;
Comment on lines +41 to +43
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

사이드바 프로필 클릭할때, 그때 유저정보 불러오는게 아니라,
사이드바 전체 fetch할때 한번에 팝업 내용도 받아오는 구조인거죠? 좋네용


const {
activeTab,
Expand Down Expand Up @@ -128,12 +132,27 @@ export function Sidebar() {
return (
<aside className="bg-white-bg sticky top-0 h-screen w-[24rem] border-r border-gray-300">
<div className="flex h-full flex-col px-[0.8rem]">
<header className="px-[0.8rem] py-[2.8rem]">
{/* TODO: 사이드바 프로필 클릭이벤트 추가 */}
<header className="flex items-center justify-between px-[0.8rem] py-[2.8rem]">
<Icon
name="logo"
aria-label="Pinback 로고"
className="h-[2.4rem] w-[8.7rem] cursor-pointer"
/>
<button
className="h-[3.6rem] w-[3.6rem] flex-shrink-0 overflow-hidden rounded-full border border-gray-200"
onClick={() => console.log('프로필 클릭', profileImageUrl)}
>
Comment on lines +146 to +150
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

button 태그는 항상 명시적으로 type을 지정해주세요!

{profileImageUrl ? (
<img
src={profileImageUrl}
alt="프로필 이미지"
className="h-full w-full object-cover"
/>
) : (
<div className="h-full w-full bg-gray-200" />
)}
</button>
</header>
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated

<hr className="my-[0.8rem] border-gray-100" />
Expand Down
Loading