Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
Binary file added apps/client/src/assets/chippi_level1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/client/src/assets/chippi_level2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/client/src/assets/chippi_level3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/client/src/assets/chippi_level4.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added apps/client/src/assets/chippi_level5.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 0 additions & 5 deletions apps/client/src/layout/Layout.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
import { Outlet } from 'react-router-dom';
import OptionsMenuButton from '@shared/components/optionsMenuButton/OptionsMenuButton';

const Layout = () => {
return (
<>
{/* TODO: 필요시 레이아웃 추가 */}
{/* TODO: 사이드바 추가 */}
<OptionsMenuButton
onEdit={function (): void {}}
onDelete={function (): void {}}
></OptionsMenuButton>

<Outlet />
</>
Expand Down
61 changes: 57 additions & 4 deletions apps/client/src/pages/level/Level.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,58 @@
const Level = () => {
return <div className="bg-secondary flex flex-col gap-[2rem] p-[1rem]"></div>;
};
import { Icon } from '@pinback/design-system/icons';
import { cn } from '@pinback/design-system/utils';
import LevelScene from './components/LevelScene';
import LevelInfoCard from './components/LevelInfoCard';
import TreeStatusCard from './components/TreeStatusCard';
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.

절대 경로 체크!

import { getTreeLevel, type TreeLevel } from './utils/treeLevel';
import { Badge } from '@pinback/design-system/ui';

export default Level;
interface LevelPageProps {
acorns?: number;
}

export default function Level({ acorns = 3 }: LevelPageProps) {
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.

acorns가 optional인 부분과 default가 3이 맞는지 궁금합니다!

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

default 값은 테스트 해보느라 제가 임의로 넣어둔 값이었어요 이부분은 삭제하겠습니다
샌각해보니 저 acorns은 Props가 아닌 페이지에서 API 연결 후 받아오는 값이라 수정하겠습니다-!

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.

확인했습니다~

const info = getTreeLevel(acorns);

return (
<div className={cn('bg-subcolor mx-auto w-full max-w-[96rem]')}>
<div className="relative overflow-hidden rounded-[1.2rem]">
<LevelScene level={info.level as TreeLevel} />

<div className="absolute inset-0">
<div className="flex flex-col items-start gap-[2rem] px-[8rem] py-[5.2rem]">
<div className="flex flex-row items-center gap-[0.8rem]">
<h1 className="head3 text-font-black-1">치삐의 지식나무 숲</h1>

<div className="relative items-center">
<button
type="button"
className="peer flex items-center justify-center p-[0.4rem]"
aria-describedby="level-info-card"
>
<Icon name="ic_info" width={20} height={20} />
</button>
Comment on lines +28 to +30
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

아이콘 전용 버튼: 접근 가능한 이름과 ARIA 속성 정정 필요

현재 버튼은 시각적 아이콘만 있고 접근 가능한 이름이 없습니다. 또한 aria-describedby는 설명 텍스트 연결 용도라 팝오버/카드 토글에는 부적절합니다. 버튼에 이름을 부여하고 제어 대상은 aria-controls로 연결하세요.

-                <button
+                <button
                   type="button"
                   className="peer p-[0.4rem]"
-                  aria-describedby="level-info-card"
+                  aria-controls="level-info-card"
+                  aria-haspopup="dialog"
+                  aria-label="레벨 안내 보기"
                 >

팁: 완전한 접근성(포커스 트랩, ESC 닫기, aria-expanded 반영 등)을 원하시면 Radix UI Popover/디자인시스템 컴포넌트로 교체하는 것을 권장합니다. 필요하면 구현 도와드릴게요.

📝 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
<button
type="button"
className="peer p-[0.4rem]"
aria-describedby="level-info-card"
>
<Icon name="ic_info" width={20} height={20} />
</button>
<button
type="button"
className="peer p-[0.4rem]"
aria-controls="level-info-card"
aria-haspopup="dialog"
aria-label="레벨 안내 보기"
>
<Icon name="ic_info" width={20} height={20} />
</button>
🤖 Prompt for AI Agents
In apps/client/src/pages/level/Level.tsx around lines 27 to 33, the icon-only
button lacks an accessible name and uses aria-describedby incorrectly for
toggling a popover; replace aria-describedby with aria-controls pointing to the
popover/card ID, give the button an accessible label (either aria-label or
include visually-hidden text) and add aria-expanded (true/false) and
aria-haspopup="dialog" (or "menu" as appropriate) to reflect toggle state;
ensure the popover element has the matching id and update code where the popover
is opened/closed to set aria-expanded accordingly (or swap to Radix UI
Popover/design-system component if you want a full accessible implementation).

<div
id="level-info-card"
className={cn(
'pointer-events-none absolute left-0 top-[3rem] z-[20]',
'opacity-0 transition-opacity duration-150',
'peer-hover:pointer-events-auto peer-focus-visible:pointer-events-auto',
'peer-hover:opacity-100 peer-focus-visible:opacity-100'
Comment on lines +32 to +37
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.

이거 cn이 스타일값 객체들을 여러개 합칠 때 사용하는 걸로 아는데요!
이 코드 경우에, 분기나 객체 구분이 안보이는데, z-[20] opacity-0 ..처럼 쭉 이어서 나열하지않고 cn을 쓰신 이유가 궁금합니다!

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

맞습니당 이 코드에 따로 분기나 객체 구분은 없어요-! 다만 한줄로 쭉 나열해서 쓰다보면 가독성이 좋지 않아 cn으로 구분해서 사용했습니다-!

)}
>
Comment thread
coderabbitai[bot] marked this conversation as resolved.
<LevelInfoCard />
</div>
</div>
</div>
{/* TODO: 오늘 모은 도토리 개수 배지 */}
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.

badge 추가된 걸까요??

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

아직 수정 안된 부분입니다 따로 원래 있던 뱃지 사용하고있는 코드입니다

<Badge text={'오늘 모은 도토리 개수'} countNum={acorns} />

<div className="flex">
<TreeStatusCard acorns={acorns} />
</div>
</div>
</div>
</div>
</div>
);
}
40 changes: 40 additions & 0 deletions apps/client/src/pages/level/components/LevelScene.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// components/LevelScene.tsx
import * as React from 'react';
import { cn } from '@pinback/design-system/utils';
import { type TreeLevel } from '../utils/treeLevel';
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.

Level 페이지 컴포넌트에도 해당 type 쓰이던데 util에서 불러오는 것 같아서! util파일이 아닌 type으로 따로 빼고 재사용 해도 되지 않을까요?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

유틸이 아닌 타입으로 뺴는게 맞는거 같아보이네요 수정하겠습니다-!


import chippi_level1 from '../../../assets/chippi_level1.png';
import chippi_level2 from '../../../assets/chippi_level2.png';
import chippi_level3 from '../../../assets/chippi_level3.png';
import chippi_level4 from '../../../assets/chippi_level4.png';
import chippi_level5 from '../../../assets/chippi_level5.png';

const SCENE_BY_LEVEL: Record<TreeLevel, string> = {
1: chippi_level1,
2: chippi_level2,
3: chippi_level3,
4: chippi_level4,
5: chippi_level5,
} as const;

interface LevelSceneProps extends React.HTMLAttributes<HTMLDivElement> {
level: TreeLevel;
}
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.

트리셰이킹이 되긴 하겠지만 React 전체 모듈을 불러올 이유가 크게 없다면 그냥 HTMLAttributes만 불러와도 될 것 같아요!
React 전체 import 제거하고!


export default function LevelScene({
level,
className,
...rest
}: LevelSceneProps) {
const src = SCENE_BY_LEVEL[level];
return (
<div className={cn('relative w-full', className)} {...rest}>
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.

단순 궁금증으로 rest props로 들어오는 예시가 있을까요??

<img
src={src}
alt={`지식나무 숲 Lv.${level}`}
className="h-auto w-full select-none rounded-[1.2rem] object-cover"
draggable={false}
/>
</div>
);
}
2 changes: 1 addition & 1 deletion packages/tailwind-config/shared-styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@
--color-gradient-end: #33d08f;

/* Secondary Color */
--color-secondary: #f4f2ec;
--color-subcolor: #f4f2ec;
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.

👍


/* Grayscale */
Comment on lines 182 to 185
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

토큰명 리네임은 합리적이나 Biome 파서 오류로 CI 차단 가능

Tailwind v4 @theme 문법을 Biome(2.1.2)이 아직 정상 파싱하지 못해 parse 에러가 납니다. 코드 자체는 정상 CSS이므로 린터 설정/우회가 필요합니다.

권장 조치:

  • 단기: 해당 파일에서 Biome 파싱을 비활성화(override)하거나 @theme 블록만 무시하도록 설정.
  • 중기: Biome 업데이트 또는 packages/tailwind-config/**/*.css 경로를 Biome 대상에서 제외.

추가로, 점진적 마이그레이션을 위해 이전 토큰도 함께 노출해두면 레거시 클래스(bg-secondary)가 남아 있어도 안전합니다.

   /* Secondary Color */
-  --color-subcolor: #f4f2ec;
+  --color-subcolor: #f4f2ec;
+  /* temporary alias for backward-compat */
+  --color-secondary: var(--color-subcolor);

확인 스크립트:


🏁 Script executed:

#!/bin/bash
# 1) 레거시 사용처 존재 여부
rg -nP 'bg-secondary|--color-secondary'
# 2) Biome가 해당 파일에서만 실패하는지 확인
pnpm biome check packages/tailwind-config/shared-styles.css || true

Length of output: 11255


Biome 파서 오류로 CI 실패 확인 – 단기 대응 필요

  • Biome(2.1.2)가 packages/tailwind-config/shared-styles.css@theme 블록 내 CSS 변수 정의를 파싱하지 못해 207개 에러 발생 확인
  • 단기: 해당 파일에 대해 Biome 파서 무시/override 설정 추가
  • 중기: Biome 최신 버전으로 업그레이드하거나 packages/tailwind-config/**/*.css 경로를 검사 대상에서 제외
  • 레거시 토큰(--color-secondary) 사용처(packages/design-system/styles.css)가 존재하므로, 점진적 마이그레이션을 위해 alias 변수 추가 권장
   /* Secondary Color */
+  /* temporary alias for backward-compat */
+  --color-secondary: var(--color-subcolor);
📝 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
/* Secondary Color */
--color-secondary: #f4f2ec;
--color-subcolor: #f4f2ec;
/* Grayscale */
/* Secondary Color */
/* temporary alias for backward-compat */
--color-secondary: var(--color-subcolor);
--color-subcolor: #f4f2ec;
/* Grayscale */
🧰 Tools
🪛 Biome (2.1.2)

[error] 183-183: expected , but instead found --color-subcolor

Remove --color-subcolor

(parse)


[error] 183-183: Unexpected value or character.

Expected one of:

(parse)


[error] 183-183: expected , but instead found ;

Remove ;

(parse)

🤖 Prompt for AI Agents
In packages/tailwind-config/shared-styles.css around lines 182 to 185, Biome
2.1.2 fails parsing CSS variable definitions inside the @theme block causing CI
errors; as a short-term fix add a Biome parser override/ignore entry for this
file (or for packages/tailwind-config/**/*.css) in the repo's Biome config so
the file is skipped by the parser, and also add a legacy alias variable
declaration mapping --color-secondary to --color-subcolor within this CSS file
to keep compatibility with packages/design-system/styles.css; for mid-term
consider upgrading Biome or excluding the path from parsing altogether.

--color-gray0: #f7f7fb;
Expand Down
Loading