-
Notifications
You must be signed in to change notification settings - Fork 0
#21 feat: 배지 컴포넌트 구현 #24
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
…eat/13-student-management
|
Warning
|
| Cohort / File(s) | Summary |
|---|---|
Dependencies & Tooling package.json, commitlint.config.cjs, .prettierrc, .husky/commit-msg, .coderabbit.yaml |
Add tailwind-variants and formatting/commit tooling (prettier, prettier-plugin-tailwindcss, commitlint, Husky hook) and a project review configuration file. |
New Badge & Button src/components/common/Badge.tsx, src/components/common/Button.tsx |
New Badge component (schedule/index/submission variants); Button API reworked to variant-driven, children-based rendering using tailwind-variants (prop shape and usage changed). |
| SVG additions New: src/assets/svg/Correct.tsx, src/assets/svg/Incorrect.tsx, src/assets/svg/Unsubmitted.tsx, src/assets/svg/index.ts |
Add three SVG React components and export barrel. |
SVG removals & import style changes src/assets/svg/* (many deleted: Arrowdown/Arrowleft/Arrowright/Chat/Chevrondown/Delete/DragAndDrop/Edit/Ellipsis/File/Notification/Signout/SingleEllipsis/UserIcon), various /svg/*.svg?react imports |
Remove many legacy SVG TSX components; migrate multiple usages to Vite-style /svg/*.svg?react or new assets; update svg import paths across files. |
| Component integrations src/components/common/, src/components/admin/, src/layout/Layout.tsx |
Replace prior themed/button/icon usages with new Button/Badge; update imports, prop shapes, and some labels (e.g., 저장/등록); add new types (UserType, NavButton) and tighten typings in Layout. |
Course & Dashboard src/components/common/CourseOverview/*, src/components/common/Dashboard/* |
Replace UnitLabel/SubmissionBadge/inline badges with new Badge; update import aliases and adjust small layout/class tweaks. |
Pages & Routing src/App.tsx, src/pages/* (LandingPage, UserIdInputPage, AssignmentCreatePage, AssignmentSelectPage, Assignment pages, new studentManagementPage) |
Swap ActionButton/IconButton/HTML buttons for new Button usage; adjust routes (admin assignments/courses paths), add StudentManagementPage; remove local linked-assignments state in AssignmentSelectPage. |
Styles src/index.css, .prettierrc |
Add CSS status color variables and prettier tailwind stylesheet setting. |
Sequence Diagram(s)
(omitted)
Estimated code review effort
🎯 4 (Complex) | ⏱️ ~45 minutes
Possibly related PRs
- #13 refactor: assets 관리 구조 개선 및 라우팅 최적화 (Prettier 도입) #23 — Highly related: overlaps on tooling (package.json, commitlint/prettier/husky), SVG and Button/Badge refactor.
- #14 feat: 강의 개설 페이지, 문제 등록 및 수정 페이지 구현 #18 — Related: changes to AssignmentFormLayout and assignment-area button usage align with this PR’s Button/Badge updates.
- #9 feat: 문제 선택/관리 페이지 구현 #12 — Related: routing and Button usage changes in App/Layout/LandingPage overlap with modifications here.
Suggested labels
🎨 ui
Suggested reviewers
- JiiminHa
Poem
🐰 New badges bloom and buttons align,
Tailwind classes prance in tidy sign,
SVGs hop in, some waved goodbye,
Routes rearranged beneath the sky,
A little rabbit claps—refactor delight! 🎉
🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
| Check name | Status | Explanation | Resolution |
|---|---|---|---|
| Docstring Coverage | Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. | Write docstrings for the functions missing them to satisfy the coverage threshold. |
✅ Passed checks (2 passed)
| Check name | Status | Explanation |
|---|---|---|
| Description Check | ✅ Passed | Check skipped - CodeRabbit’s high-level summary is enabled. |
| Title check | ✅ Passed | The PR title accurately describes the main change: implementing a Badge component. It clearly summarizes the primary objective from the changeset. |
✏️ Tip: You can configure your own custom pre-merge checks in the settings.
✨ Finishing touches
- 📝 Generate docstrings
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands and usage tips.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 8
🤖 Fix all issues with AI Agents
In @src/components/admin/assignments/AssignmentPageLayout.tsx:
- Around line 40-43: The Cancel and Register buttons in AssignmentPageLayout are
missing onClick handlers; add onClick={handleCancel} and
onClick={handleRegister} (or wire to passed-in props like onCancel/onRegister)
on the two Button components, implement handleCancel to reset/close the form or
call props.onCancel, and implement handleRegister to validate and submit the
data or call props.onRegister (ensure you prevent default if inside a form and
surface errors appropriately); update the AssignmentPageLayout props and usages
if you choose to accept callbacks instead of local handlers.
- Around line 35-38: The three Button elements (the "문제 추가" Add Problem button
using AddIcon, and the "취소" Cancel and "등록" Register buttons) are missing
onClick handlers; add appropriate handler props or local functions (e.g.,
handleAddProblem, handleCancel, handleSubmit) and wire them to the Button
onClick attributes so the buttons perform actions—implement handleAddProblem to
open the add-problem modal or push a new problem to state, handleCancel to
reset/close the form or navigate away, and handleSubmit to validate and dispatch
the create assignment action; ensure handlers are correctly bound/typed and
prevent default where needed.
In @src/components/common/Badge.tsx:
- Around line 96-106: In the 'submission' switch case wrap the destructuring
"const { label, icon } = SubmissionMeta[props.status]" inside a new block to
avoid leaking variables to other cases, and remove the unsafe non-null assertion
on props.status; instead guard against undefined by checking props.status (e.g.,
early return null/placeholder or fall back to a safe default key) before reading
SubmissionMeta, then use the safe key to get label/icon and render with
submissionBadgeStyles({ status: props.status }).
- Around line 85-92: The const suffix declared in the switch case 'index' of
Badge (where props.kind and indexBadgeStyles are used) must be scoped to that
case by wrapping the case body in a block: open a { immediately after case
'index':, move the const suffix and the return(...) inside that block, and close
the } after the return so suffix is not visible to other cases.
- Around line 12-13: The Tailwind class for the "upcoming" badge uses invalid
syntax; replace the `bg-radial-[50%_50%_at_50%_50%] from-[#7D63FF] from-38%
to-[#AB9AFF] to-100%` piece with a valid Tailwind arbitrary radial-gradient,
e.g. use `bg-[radial-gradient(circle_at_50%_50%,_#7D63FF_38%,_#AB9AFF_100%)]`
and keep the rest of the utilities (e.g., `border-0 text-white`) so the
`upcoming` entry in Badge.tsx renders correctly.
In @src/components/common/Button.tsx:
- Around line 49-61: The Button component accepts a type prop but never applies
it to the rendered <button>, causing buttons inside forms to default to
"submit"; update the JSX for the Button component (function name: Button) to
pass the destructured type prop to the element (e.g., include type={type}) while
preserving existing disabled, onClick and spread props so the button uses the
intended type.
- Around line 49-61: The Button component currently passes props into the
variant helper as button(props), but tailwind-variants won't merge a consumer's
className; destructure className from ButtonProps in the Button signature (e.g.,
({ children, onClick, type='button', disabled=false, className, ...props })) and
pass it into the variant call as button({ ...props, className }) so the consumer
className is merged with the variant styles (refer to the Button component,
ButtonProps, and the button(...) variant function).
In @src/components/common/CourseOverview/CourseActionsBar.tsx:
- Around line 3-9: The CourseActionsBar component declares an unused prop
isActive; either remove it from the component signature and all call sites
(update CourseActionsBar to const CourseActionsBar = () => { ... } and remove
isActive from any parent usage), or implement it to drive conditional styling by
mapping isActive to Button color variants (e.g., set the relevant Button color
prop based on isActive inside CourseActionsBar, such as color={isActive ?
'outlinePurple' : 'outlineWhite'} for the primary action). Update the component
signature and any affected imports/usages accordingly and ensure type
definitions reflect the change (remove the prop type or keep {isActive: boolean}
if implementing).
🧹 Nitpick comments (6)
src/assets/svg/Correct.tsx (1)
1-12: Consider usingcurrentColorfor theme flexibility.The stroke color
#856CFFis hardcoded. For better theme integration and reusability, consider usingcurrentColorto allow the icon color to be controlled via the parent's text color or CSS variables.🔎 Proposed change for flexible color control
- <circle cx={6} cy={6} r={5.35} stroke='#856CFF' strokeWidth={1.3} /> + <circle cx={6} cy={6} r={5.35} stroke='currentColor' strokeWidth={1.3} />This allows consumers to control the color:
<SvgCorrect className="text-primary" />src/components/common/Button.tsx (1)
39-47: Consider addingforwardReffor DOM access.Parent components may need to access the underlying button DOM element (e.g., for focus management, measurements, or third-party library integration).
🔎 Example implementation with forwardRef
+import {forwardRef} from 'react'; import {tv, type VariantProps} from 'tailwind-variants/lite'; // ... tv definition ... interface ButtonProps extends ButtonVariants { children: React.ReactNode; className?: string; type?: 'button' | 'submit'; disabled?: boolean; onClick?: () => void; onMouseEnter?: () => void; onMouseLeave?: () => void; } -const Button = ({ +const Button = forwardRef<HTMLButtonElement, ButtonProps>(({ children, className, onClick, type = 'button', disabled = false, ...props -}: ButtonProps) => { +}, ref) => { return ( <button + ref={ref} type={type} onClick={onClick} disabled={disabled} className={button({...props, className})}> {children} </button> ); -}; +}); + +Button.displayName = 'Button'; export default Button;src/assets/svg/Unsubmitted.tsx (1)
1-19: Consider usingcurrentColorfor theme flexibility.Similar to the Correct icon, the stroke color
#7D7993is hardcoded. UsingcurrentColorwould allow better integration with your design system and enable consumers to control the icon color via CSS.🔎 Proposed change for flexible color control
<circle cx={6} cy={6} r={5.35} - stroke='#7D7993' + stroke='currentColor' strokeDasharray='3 3' strokeWidth={1.3} />This enables color control from parent components:
<SvgUnsubmitted className="text-gray-500" />src/components/common/CourseOverview/AssignmentItem.tsx (1)
40-40: Consider using nullish coalescing operator for better falsy value handling.The
||operator will replace any falsy value (including0,'',false) with'NOT_SUBMITTED'. IfsubmittedStatuscan legitimately be an empty string or other falsy value, use the??operator instead, which only checks fornullorundefined.🔎 Suggested refinement
- <Badge - variant='submission' - status={submittedStatus || 'NOT_SUBMITTED'} - /> + <Badge + variant='submission' + status={submittedStatus ?? 'NOT_SUBMITTED'} + />src/components/common/Dashboard/ScheduleCard.tsx (1)
15-19: Consider extending the Badge component to support additional schedule states.The Badge component currently supports only 'upcoming' and 'later' states. The ScheduleCard logic (
remainingDays === 1 ? 'upcoming' : 'later') correctly uses these two states, but assignments withremainingDays === 0and negative values would benefit from distinct 'today' and 'overdue' states. To improve semantic clarity, add these schedule state variants to the Badge component'sscheduleBadgeStyles.src/pages/common/UserIdInputPage.tsx (1)
79-87: Consider moving the ArrowleftIcon inside the Button for better accessibility.The ArrowleftIcon is rendered outside the Button component, which may cause screen readers to announce them separately. For better semantic HTML and accessibility, consider including the icon as a child of the Button.
🔎 Suggested refactor
- <div className='absolute top-[43px] left-[60px] flex items-center gap-4'> - <ArrowleftIcon className='w-[18px] h-[24px]' /> - <Button - color='ghost' - onClick={handleBeforeClick} - size='none' - className='leading-7 text-lg'> + <div className='absolute top-[43px] left-[60px]'> + <Button + color='ghost' + onClick={handleBeforeClick} + size='none' + className='flex items-center gap-4 leading-7 text-lg'> + <ArrowleftIcon className='w-[18px] h-[24px]' /> 이전으로 </Button> </div>
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (4)
package-lock.jsonis excluded by!**/package-lock.jsonpublic/svg/correct.svgis excluded by!**/*.svgpublic/svg/incorrect.svgis excluded by!**/*.svgpublic/svg/unsubmitted.svgis excluded by!**/*.svg
📒 Files selected for processing (19)
package.jsonsrc/assets/svg/Correct.tsxsrc/assets/svg/Incorrect.tsxsrc/assets/svg/Unsubmitted.tsxsrc/assets/svg/index.tssrc/components/admin/assignments/AssignmentFormLayout.tsxsrc/components/admin/assignments/AssignmentPageLayout.tsxsrc/components/common/Badge.tsxsrc/components/common/Button.tsxsrc/components/common/CourseOverview/AssignmentItem.tsxsrc/components/common/CourseOverview/CourseActionsBar.tsxsrc/components/common/CourseOverview/UnitHeader.tsxsrc/components/common/CourseOverview/UnitLabel.tsxsrc/components/common/Dashboard/CourseList.tsxsrc/components/common/Dashboard/ScheduleCard.tsxsrc/layout/Layout.tsxsrc/pages/admin/assignments/AssignmentCreatePage.tsxsrc/pages/common/LandingPage.tsxsrc/pages/common/UserIdInputPage.tsx
💤 Files with no reviewable changes (1)
- src/components/common/CourseOverview/UnitLabel.tsx
🧰 Additional context used
🧠 Learnings (3)
📚 Learning: 2025-07-16T13:00:01.926Z
Learnt from: suminb99
Repo: 2025-snowCode/snowCode-Client PR: 6
File: src/assets/svg/ChatIcon.tsx:14-14
Timestamp: 2025-07-16T13:00:01.926Z
Learning: This project uses svgr for automatic SVG to React component conversion. Running `npm run svgr` automatically converts all svgr files to React component format and handles camelCase conversion for SVG attributes (e.g., stroke-width → strokeWidth).
Applied to files:
src/assets/svg/Unsubmitted.tsxsrc/assets/svg/Correct.tsx
📚 Learning: 2025-07-16T13:14:38.834Z
Learnt from: suminb99
Repo: 2025-snowCode/snowCode-Client PR: 6
File: src/assets/svg/ChatIcon.tsx:14-14
Timestamp: 2025-07-16T13:14:38.834Z
Learning: In this project, the svgr workflow requires placing original SVG files in the `public/svg` folder first, then running `npm run svgr` command to generate converted TSX files in the `src/assets/svg` folder according to the root configuration.
Applied to files:
src/assets/svg/Correct.tsxsrc/assets/svg/Incorrect.tsxsrc/assets/svg/index.ts
📚 Learning: 2025-07-13T00:27:31.464Z
Learnt from: JiiminHa
Repo: 2025-snowCode/snowCode-Client PR: 2
File: src/components/Header/StudentHeader.tsx:10-10
Timestamp: 2025-07-13T00:27:31.464Z
Learning: Using TypeScript interfaces for React component props (like StudentHeaderProps) provides clear structure, improves readability, and makes components more maintainable and extensible for future development.
Applied to files:
src/components/common/CourseOverview/UnitHeader.tsx
🧬 Code graph analysis (1)
src/components/common/Dashboard/ScheduleCard.tsx (1)
src/components/common/Dashboard/types.ts (1)
Schedule(5-10)
🪛 Biome (2.1.2)
src/components/common/Badge.tsx
[error] 86-89: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
[error] 99-101: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
🔇 Additional comments (13)
src/components/common/Button.tsx (1)
3-35:flex-centeris properly defined and all utilities are compatible with Tailwind v4.The custom utility
flex-centeris defined insrc/index.cssas@utility flex-center { @apply flex items-center justify-center; }. The button styles use standard Tailwind utilities that are all compatible with Tailwind v4—no breaking changes apply here.package.json (1)
18-18: No compatibility or security issues found for tailwind-variants ^3.2.2 with Tailwind CSS v4.Verification confirms that tailwind-variants 3.2.2 is compatible with Tailwind CSS v4.1.11 (peer dependency declares
tailwindcss: "*"), and Snyk reports no known security vulnerabilities for this package as of January 2026. This dependency is safe to use.src/components/common/Dashboard/CourseList.tsx (1)
49-55: LGTM! Button component migration looks correct.The Button component is properly used with the new variant-based API. The combination of
color='ghostWhite',size='compact', and children pattern aligns with the refactored Button implementation.src/assets/svg/Incorrect.tsx (1)
1-17: LGTM! Excellent SVG component implementation.The component follows React best practices:
- Properly typed with
SVGProps<SVGSVGElement>- Accepts and spreads props for maximum flexibility
- No hardcoded width/height, allowing parent control
- Clean, idiomatic implementation
src/pages/admin/assignments/AssignmentCreatePage.tsx (1)
63-70: Thecontent='mixed'prop is properly supported and correctly used.The Button component's
contentprop is defined as a tailwind-variants variant with valid options including 'mixed', which applies flex centering with a 2-unit gap between icon and text elements. The prop is properly typed throughButtonVariantsand is correctly applied in this component.src/components/common/CourseOverview/UnitHeader.tsx (2)
1-2: LGTM on import path updates.The migration to alias-based imports (
@/assets/images/lock.svg) and the Badge component import are consistent with the project's refactoring efforts.
22-24: Badge component supports the variant and kind props, but verify the suffix text matches PR objectives.The Badge component correctly accepts
variant='index'andkind='unit'props. The suffix rendering is implemented, but it renders'단원'(section) forkind='unit', not'차시'(lesson) as mentioned in the PR objectives. Confirm whether'단원'is the intended suffix or if this needs to be changed to'차시'.src/components/admin/assignments/AssignmentFormLayout.tsx (1)
26-33: LGTM! Proper Button API migration with handlers.The action buttons correctly use the new Button API with
colorprops and pass theonClickhandlers (onCancel,onConfirm) received from props. The label change from "확인" (Confirm) to "저장" (Save) better reflects the action's intent.src/assets/svg/index.ts (1)
7-7: The three new SVG exports follow the correct implementation pattern.The source SVG files (correct.svg, incorrect.svg, unsubmitted.svg) are present in
public/svg, the generated TSX files (Correct.tsx, Incorrect.tsx, Unsubmitted.tsx) are insrc/assets/svg, and the exports inindex.tsfollow the established naming and pattern conventions. The svgr workflow has been properly applied.src/pages/common/UserIdInputPage.tsx (1)
125-132: Button component correctly supports bothcolor='secondary'andsize='wide'variants.Both variants are properly defined in the Button component's tailwind-variants configuration (lines 8-9 and 19 of src/components/common/Button.tsx). The code change is valid.
src/layout/Layout.tsx (1)
45-51: LGTM! Clean migration to the new Button component.The refactoring from
IconButtontoButtonwithcontent='icon'andsize='icon'props is well-executed. Thearia-labelis correctly preserved for accessibility, and rendering the icon as children follows React best practices.src/pages/common/LandingPage.tsx (2)
42-48: LGTM! Button integration for navigation control.The migration to the new
Buttoncomponent withcolor='ghost'andsize='none'is correct, and theonClicknavigation logic is properly preserved.
73-88: LGTM! Well-implemented user type selection.The Button components correctly implement dynamic styling based on selection state:
color='primary'when selected,color='secondary'otherwise- The
onMouseLeavelogic that checksselected === 'none'is intentional and provides good UX by preserving the hover state when an option is selected.
| <Button color='tonal' size='compact' content='mixed'> | ||
| <AddIcon width={12} height={12} /> | ||
| 문제 추가 | ||
| </Button> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
# First, let's look at the AssignmentPageLayout.tsx file to see the full context
cat -n src/components/admin/assignments/AssignmentPageLayout.tsx | sed -n '20,55p'Repository: 2025-snowCode/snowCode-Client
Length of output: 1336
🏁 Script executed:
# Check if Button component exists and examine its props
fd Button.tsx src/componentsRepository: 2025-snowCode/snowCode-Client
Length of output: 181
🏁 Script executed:
# Search for Button component definition to verify prop support
rg -l "export.*Button|const Button" src/components --type tsx --type tsRepository: 2025-snowCode/snowCode-Client
Length of output: 100
🏁 Script executed:
# Check Button component definition
cat -n src/components/common/Button.tsxRepository: 2025-snowCode/snowCode-Client
Length of output: 2243
🏁 Script executed:
# Look for onClick handlers in AssignmentPageLayout.tsx
rg "onClick|onAdd|handleAdd" src/components/admin/assignments/AssignmentPageLayout.tsx -B 2 -A 2Repository: 2025-snowCode/snowCode-Client
Length of output: 55
🏁 Script executed:
# Check for any event handlers on Button elements in the file
rg -A 3 "<Button" src/components/admin/assignments/AssignmentPageLayout.tsxRepository: 2025-snowCode/snowCode-Client
Length of output: 361
All three buttons lack onClick handlers, making them non-functional.
The "문제 추가" (Add Problem) button at lines 35-38, along with the "취소" (Cancel) and "등록" (Register) buttons at lines 41-42, are missing onClick handlers. The Button component properly supports the content='mixed' prop (it's a valid variant), so no verification is needed there. However, all three buttons require handlers to function.
🤖 Prompt for AI Agents
In @src/components/admin/assignments/AssignmentPageLayout.tsx around lines 35 -
38, The three Button elements (the "문제 추가" Add Problem button using AddIcon, and
the "취소" Cancel and "등록" Register buttons) are missing onClick handlers; add
appropriate handler props or local functions (e.g., handleAddProblem,
handleCancel, handleSubmit) and wire them to the Button onClick attributes so
the buttons perform actions—implement handleAddProblem to open the add-problem
modal or push a new problem to state, handleCancel to reset/close the form or
navigate away, and handleSubmit to validate and dispatch the create assignment
action; ensure handlers are correctly bound/typed and prevent default where
needed.
| <div className='flex justify-end gap-5 mt-3'> | ||
| <Button theme='primaryWhite' text='취소' /> | ||
| <Button theme='primaryPurple' text='저장' /> | ||
| <Button color='outlinePurple'>취소</Button> | ||
| <Button color='primary'>등록</Button> | ||
| </div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing onClick handlers for action buttons.
Both the "취소" (Cancel) and "등록" (Register) buttons lack onClick handlers, rendering them non-functional. These are critical action buttons that should trigger cancel and registration operations respectively.
🔎 Suggested fix
<div className='flex justify-end gap-5 mt-3'>
- <Button color='outlinePurple'>취소</Button>
- <Button color='primary'>등록</Button>
+ <Button color='outlinePurple' onClick={handleCancel}>취소</Button>
+ <Button color='primary' onClick={handleRegister}>등록</Button>
</div>You'll need to implement the handleCancel and handleRegister functions, or wire them to existing callbacks if this is part of a form flow.
Committable suggestion skipped: line range outside the PR's diff.
🤖 Prompt for AI Agents
In @src/components/admin/assignments/AssignmentPageLayout.tsx around lines 40 -
43, The Cancel and Register buttons in AssignmentPageLayout are missing onClick
handlers; add onClick={handleCancel} and onClick={handleRegister} (or wire to
passed-in props like onCancel/onRegister) on the two Button components,
implement handleCancel to reset/close the form or call props.onCancel, and
implement handleRegister to validate and submit the data or call
props.onRegister (ensure you prevent default if inside a form and surface errors
appropriately); update the AssignmentPageLayout props and usages if you choose
to accept callbacks instead of local handlers.
| upcoming: | ||
| 'bg-radial-[50%_50%_at_50%_50%] from-[#7D63FF] from-38% to-[#AB9AFF] to-100% border-0 text-white', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
cat -n src/components/common/Badge.tsxRepository: 2025-snowCode/snowCode-Client
Length of output: 3464
🏁 Script executed:
# Search for other instances of bg-radial in the codebase
rg "bg-radial" --type tsx --type ts --type jsx --type jsRepository: 2025-snowCode/snowCode-Client
Length of output: 100
🌐 Web query:
Tailwind CSS v4 radial gradient syntax arbitrary values
💡 Result:
Short answer — two options in Tailwind v4:
-
Use the built-in radial utilities (bg-radial, bg-radial-[at_...]) + from/via/to stops:
- Example: class="bg-radial from-pink-400 from-40% to-fuchsia-700"
- Example with position: class="bg-radial-[at_50%_75%] from-sky-200 via-blue-400 to-indigo-900 to-90%". [1]
-
For arbitrary/custom radial-gradient() CSS, use the arbitrary background-image fallback with brackets:
- Example: class="bg-[radial-gradient(169.4%_89.55%_at_94.76%_6.29%,rgba(0,0,0,0.4)_0%,transparent_100%)]"
- Gradient helpers/tools also recommend falling back to bg-[radial-gradient(...)] for complex/positioned stops. [2][3]
References:
- Tailwind docs — radial gradient utilities. [1]
- Guidance/tools recommending bg-[radial-gradient(...)] for complex/positioned radial gradients. [2][3]
Fix the radial gradient syntax—bg-radial-[...] is not valid in Tailwind v4.
The current syntax bg-radial-[50%_50%_at_50%_50%] does not match Tailwind v4's documented radial gradient patterns. Tailwind v4 supports either built-in bg-radial utilities or arbitrary custom gradients via bg-[radial-gradient(...)].
Use the proper arbitrary gradient syntax to render correctly:
🔎 Suggested fix
- upcoming:
- 'bg-radial-[50%_50%_at_50%_50%] from-[#7D63FF] from-38% to-[#AB9AFF] to-100% border-0 text-white',
+ upcoming:
+ 'bg-[radial-gradient(circle_at_50%_50%,#7D63FF_38%,#AB9AFF_100%)] border-0 text-white',📝 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.
| upcoming: | |
| 'bg-radial-[50%_50%_at_50%_50%] from-[#7D63FF] from-38% to-[#AB9AFF] to-100% border-0 text-white', | |
| upcoming: | |
| 'bg-[radial-gradient(circle_at_50%_50%,#7D63FF_38%,#AB9AFF_100%)] border-0 text-white', |
🤖 Prompt for AI Agents
In @src/components/common/Badge.tsx around lines 12 - 13, The Tailwind class for
the "upcoming" badge uses invalid syntax; replace the
`bg-radial-[50%_50%_at_50%_50%] from-[#7D63FF] from-38% to-[#AB9AFF] to-100%`
piece with a valid Tailwind arbitrary radial-gradient, e.g. use
`bg-[radial-gradient(circle_at_50%_50%,_#7D63FF_38%,_#AB9AFF_100%)]` and keep
the rest of the utilities (e.g., `border-0 text-white`) so the `upcoming` entry
in Badge.tsx renders correctly.
| case 'index': | ||
| const suffix = props.kind === 'unit' ? '단원' : ' 문제'; | ||
|
|
||
| return ( | ||
| <span className={indexBadgeStyles({kind: props.kind})}> | ||
| {props.children} | ||
| {suffix} | ||
| </span> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrap variable declarations in blocks within switch cases.
The suffix declaration at line 86 should be wrapped in a block to prevent it from being accessible to other switch cases, which violates ES6 scoping rules.
🔎 Proposed fix
// 인덱스 배지 (단원, 문제 등)
- case 'index':
+ case 'index': {
const suffix = props.kind === 'unit' ? '단원' : ' 문제';
return (
<span className={indexBadgeStyles({kind: props.kind})}>
{props.children}
{suffix}
</span>
);
+ }📝 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.
| case 'index': | |
| const suffix = props.kind === 'unit' ? '단원' : ' 문제'; | |
| return ( | |
| <span className={indexBadgeStyles({kind: props.kind})}> | |
| {props.children} | |
| {suffix} | |
| </span> | |
| case 'index': { | |
| const suffix = props.kind === 'unit' ? '단원' : ' 문제'; | |
| return ( | |
| <span className={indexBadgeStyles({kind: props.kind})}> | |
| {props.children} | |
| {suffix} | |
| </span> | |
| ); | |
| } |
🧰 Tools
🪛 Biome (2.1.2)
[error] 86-89: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
🤖 Prompt for AI Agents
In @src/components/common/Badge.tsx around lines 85 - 92, The const suffix
declared in the switch case 'index' of Badge (where props.kind and
indexBadgeStyles are used) must be scoped to that case by wrapping the case body
in a block: open a { immediately after case 'index':, move the const suffix and
the return(...) inside that block, and close the } after the return so suffix is
not visible to other cases.
| case 'submission': | ||
| const {label, icon} = SubmissionMeta[props.status!]; | ||
|
|
||
| return ( | ||
| <span | ||
| className={submissionBadgeStyles({ | ||
| status: props.status, | ||
| })}> | ||
| {icon} {label} | ||
| </span> | ||
| ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrap variable declarations in blocks and remove unsafe non-null assertion.
Two issues:
- The destructuring at line 97 should be wrapped in a block to prevent leakage to other switch cases.
- The non-null assertion
props.status!is unsafe becausestatusis optional in the type definition. Ifstatusisundefined, this will cause a runtime error.
🔎 Proposed fix
// 제출 상태 배지
- case 'submission':
- const {label, icon} = SubmissionMeta[props.status!];
+ case 'submission': {
+ if (!props.status) {
+ console.error('Badge: submission variant requires status prop');
+ return null;
+ }
+ const {label, icon} = SubmissionMeta[props.status];
return (
<span
className={submissionBadgeStyles({
status: props.status,
})}>
{icon} {label}
</span>
);
+ }Alternatively, make status required in the type definition:
type SubmissionBadgeProps = {
variant: 'submission';
+ status: keyof typeof SubmissionMeta;
} & VariantProps<typeof submissionBadgeStyles>;📝 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.
| case 'submission': | |
| const {label, icon} = SubmissionMeta[props.status!]; | |
| return ( | |
| <span | |
| className={submissionBadgeStyles({ | |
| status: props.status, | |
| })}> | |
| {icon} {label} | |
| </span> | |
| ); | |
| case 'submission': { | |
| if (!props.status) { | |
| console.error('Badge: submission variant requires status prop'); | |
| return null; | |
| } | |
| const {label, icon} = SubmissionMeta[props.status]; | |
| return ( | |
| <span | |
| className={submissionBadgeStyles({ | |
| status: props.status, | |
| })}> | |
| {icon} {label} | |
| </span> | |
| ); | |
| } |
🧰 Tools
🪛 Biome (2.1.2)
[error] 99-101: Other switch clauses can erroneously access this declaration.
Wrap the declaration in a block to restrict its access to the switch clause.
The declaration is defined in this switch clause:
Safe fix: Wrap the declaration in a block.
(lint/correctness/noSwitchDeclarations)
🤖 Prompt for AI Agents
In @src/components/common/Badge.tsx around lines 96 - 106, In the 'submission'
switch case wrap the destructuring "const { label, icon } =
SubmissionMeta[props.status]" inside a new block to avoid leaking variables to
other cases, and remove the unsafe non-null assertion on props.status; instead
guard against undefined by checking props.status (e.g., early return
null/placeholder or fall back to a safe default key) before reading
SubmissionMeta, then use the safe key to get label/icon and render with
submissionBadgeStyles({ status: props.status }).
| const Button = ({ | ||
| children, | ||
| onClick, | ||
| type = 'button', | ||
| disabled = false, | ||
| ...props | ||
| }: ButtonProps) => { | ||
| return ( | ||
| <button | ||
| className={`py-1.5 px-3 rounded-[10px] cursor-pointer ${buttonTheme[theme]}`}> | ||
| {icon} | ||
| <span className='text-btn'>{text}</span> | ||
| <button onClick={onClick} disabled={disabled} className={button(props)}> | ||
| {children} | ||
| </button> | ||
| ); | ||
| }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Apply the type prop to the button element.
The type prop is accepted in ButtonProps but not applied to the <button> element, which means all buttons default to type="submit" in forms. This can cause unexpected form submissions.
🔎 Proposed fix
return (
- <button onClick={onClick} disabled={disabled} className={button(props)}>
+ <button type={type} onClick={onClick} disabled={disabled} className={button(props)}>
{children}
</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.
| const Button = ({ | |
| children, | |
| onClick, | |
| type = 'button', | |
| disabled = false, | |
| ...props | |
| }: ButtonProps) => { | |
| return ( | |
| <button | |
| className={`py-1.5 px-3 rounded-[10px] cursor-pointer ${buttonTheme[theme]}`}> | |
| {icon} | |
| <span className='text-btn'>{text}</span> | |
| <button onClick={onClick} disabled={disabled} className={button(props)}> | |
| {children} | |
| </button> | |
| ); | |
| }; | |
| const Button = ({ | |
| children, | |
| onClick, | |
| type = 'button', | |
| disabled = false, | |
| ...props | |
| }: ButtonProps) => { | |
| return ( | |
| <button type={type} onClick={onClick} disabled={disabled} className={button(props)}> | |
| {children} | |
| </button> | |
| ); | |
| }; |
🤖 Prompt for AI Agents
In @src/components/common/Button.tsx around lines 49 - 61, The Button component
accepts a type prop but never applies it to the rendered <button>, causing
buttons inside forms to default to "submit"; update the JSX for the Button
component (function name: Button) to pass the destructured type prop to the
element (e.g., include type={type}) while preserving existing disabled, onClick
and spread props so the button uses the intended type.
🛠️ Refactor suggestion | 🟠 Major
Merge consumer className with variant styles.
The className prop from ButtonProps is passed to button(props) but tailwind-variants doesn't automatically merge it. Consumers cannot override or extend styles.
🔎 Proposed fix to enable className override
const Button = ({
children,
+ className,
onClick,
type = 'button',
disabled = false,
...props
}: ButtonProps) => {
return (
- <button onClick={onClick} disabled={disabled} className={button(props)}>
+ <button type={type} onClick={onClick} disabled={disabled} className={button({...props, className})}>
{children}
</button>
);
};This allows consumers to extend styles:
<Button color="primary" className="custom-class">Click</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.
| const Button = ({ | |
| children, | |
| onClick, | |
| type = 'button', | |
| disabled = false, | |
| ...props | |
| }: ButtonProps) => { | |
| return ( | |
| <button | |
| className={`py-1.5 px-3 rounded-[10px] cursor-pointer ${buttonTheme[theme]}`}> | |
| {icon} | |
| <span className='text-btn'>{text}</span> | |
| <button onClick={onClick} disabled={disabled} className={button(props)}> | |
| {children} | |
| </button> | |
| ); | |
| }; | |
| const Button = ({ | |
| children, | |
| className, | |
| onClick, | |
| type = 'button', | |
| disabled = false, | |
| ...props | |
| }: ButtonProps) => { | |
| return ( | |
| <button type={type} onClick={onClick} disabled={disabled} className={button({...props, className})}> | |
| {children} | |
| </button> | |
| ); | |
| }; |
🤖 Prompt for AI Agents
In @src/components/common/Button.tsx around lines 49 - 61, The Button component
currently passes props into the variant helper as button(props), but
tailwind-variants won't merge a consumer's className; destructure className from
ButtonProps in the Button signature (e.g., ({ children, onClick, type='button',
disabled=false, className, ...props })) and pass it into the variant call as
button({ ...props, className }) so the consumer className is merged with the
variant styles (refer to the Button component, ButtonProps, and the button(...)
variant function).
| const CourseActionsBar = ({isActive}: {isActive: boolean}) => { | ||
| return ( | ||
| <div className='flex gap-5'> | ||
| <Button | ||
| theme={`${isActive ? 'primaryTransparent' : 'primaryWhite'}`} | ||
| text='학생 목록' | ||
| /> | ||
| <Button | ||
| theme={`${isActive ? 'primaryWhite' : 'primaryPurple'}`} | ||
| text='단원 추가' | ||
| /> | ||
| <Button color='outlineWhite'>학생 목록</Button> | ||
| <Button color='outlinePurple'>단원 추가</Button> | ||
| </div> | ||
| ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove or implement the unused isActive prop.
The isActive prop is declared in the component signature but never used in the implementation. This appears to be leftover from the previous theming approach.
Please either:
- Remove the unused prop if it's no longer needed
- Implement conditional styling based on
isActiveusing the new Button color variants
🔎 Example implementation if isActive should control styling
const CourseActionsBar = ({isActive}: {isActive: boolean}) => {
return (
<div className='flex gap-5'>
- <Button color='outlineWhite'>학생 목록</Button>
- <Button color='outlinePurple'>단원 추가</Button>
+ <Button color={isActive ? 'primary' : 'outlineWhite'}>학생 목록</Button>
+ <Button color={isActive ? 'primary' : 'outlinePurple'}>단원 추가</Button>
</div>
);
};Or remove it entirely:
-const CourseActionsBar = ({isActive}: {isActive: boolean}) => {
+const CourseActionsBar = () => {📝 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.
| const CourseActionsBar = ({isActive}: {isActive: boolean}) => { | |
| return ( | |
| <div className='flex gap-5'> | |
| <Button | |
| theme={`${isActive ? 'primaryTransparent' : 'primaryWhite'}`} | |
| text='학생 목록' | |
| /> | |
| <Button | |
| theme={`${isActive ? 'primaryWhite' : 'primaryPurple'}`} | |
| text='단원 추가' | |
| /> | |
| <Button color='outlineWhite'>학생 목록</Button> | |
| <Button color='outlinePurple'>단원 추가</Button> | |
| </div> | |
| ); | |
| const CourseActionsBar = ({isActive}: {isActive: boolean}) => { | |
| return ( | |
| <div className='flex gap-5'> | |
| <Button color={isActive ? 'primary' : 'outlineWhite'}>학생 목록</Button> | |
| <Button color={isActive ? 'primary' : 'outlinePurple'}>단원 추가</Button> | |
| </div> | |
| ); | |
| }; |
| const CourseActionsBar = ({isActive}: {isActive: boolean}) => { | |
| return ( | |
| <div className='flex gap-5'> | |
| <Button | |
| theme={`${isActive ? 'primaryTransparent' : 'primaryWhite'}`} | |
| text='학생 목록' | |
| /> | |
| <Button | |
| theme={`${isActive ? 'primaryWhite' : 'primaryPurple'}`} | |
| text='단원 추가' | |
| /> | |
| <Button color='outlineWhite'>학생 목록</Button> | |
| <Button color='outlinePurple'>단원 추가</Button> | |
| </div> | |
| ); | |
| const CourseActionsBar = () => { | |
| return ( | |
| <div className='flex gap-5'> | |
| <Button color='outlineWhite'>학생 목록</Button> | |
| <Button color='outlinePurple'>단원 추가</Button> | |
| </div> | |
| ); |
🤖 Prompt for AI Agents
In @src/components/common/CourseOverview/CourseActionsBar.tsx around lines 3 -
9, The CourseActionsBar component declares an unused prop isActive; either
remove it from the component signature and all call sites (update
CourseActionsBar to const CourseActionsBar = () => { ... } and remove isActive
from any parent usage), or implement it to drive conditional styling by mapping
isActive to Button color variants (e.g., set the relevant Button color prop
based on isActive inside CourseActionsBar, such as color={isActive ?
'outlinePurple' : 'outlineWhite'} for the primary action). Update the component
signature and any affected imports/usages accordingly and ensure type
definitions reflect the change (remove the prop type or keep {isActive: boolean}
if implementing).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/components/common/CourseOverview/SubmissionBadge.tsx (2)
26-26: Remove trailing space in color code.The color string
'#7D7993 'contains a trailing space that could cause subtle styling inconsistencies.🎨 Proposed fix
- variant: 'border border-[#7D7993 ] text-[#7D7993]', + variant: 'border border-[#7D7993] text-[#7D7993]',
31-42: Refactor to use the unified Badge component for submission status rendering.The new
Badgecomponent insrc/components/common/Badge.tsxalready supports submission status rendering via its'submission'variant (lines 95-106) with support forCORRECT,INCORRECT, andNOT_SUBMITTEDstatuses. ThisSubmissionBadgecomponent is redundant and should be refactored to useBadgeinstead.Key differences to address during refactoring:
- Badge uses SVG components (
<Correct>,<Incorrect>,<Unsubmitted>) while SubmissionBadge uses image files—align on asset approach- Color mismatch for
CORRECTstatus (#856CFFvs Badge'sborder-primary) andNOT_SUBMITTED(#7D7993vs Badge'sborder-light-black)—verify intended colors and update Badge'ssubmissionBadgeStylesif needed- Badge renders as
<span>while SubmissionBadge renders as<div>withmr-auto—ensure the chosen structure meets layout requirements
🤖 Fix all issues with AI agents
In @.coderabbit.yaml:
- Around line 14-24: The YAML defines the key high_level_summary_placeholder
twice, causing a parsing failure; remove the duplicate occurrence that sets
high_level_summary_placeholder: '@coderabbitai summary' and keep the first, more
detailed high_level_summary_placeholder block (the one containing "@coderabbitai
summary (졸업작품 평가 기준: 구조 / 타입 안정성 / 접근성 관점 요약)"), ensuring there is only one
high_level_summary_placeholder entry so the YAML parses correctly.
- Line 11: The profile value 'educational' is invalid; update the
.coderabbit.yaml profile key to an accepted value (use 'chill' to match the
existing PR context) by replacing the current profile: educational entry with
profile: chill so the file conforms to the schema.
In @src/layout/Layout.tsx:
- Around line 3-16: Remove the locally declared UserType and instead import the
shared type by adding an import for UserType from the Dashboard types module,
then delete the local "type UserType = 'admin' | 'student';" declaration and
ensure any usages (e.g., props or state types in Layout, and related interfaces
like NavButton if they reference UserType elsewhere) refer to the imported
UserType.
In @src/pages/admin/student/studentManagementPage.tsx:
- Line 11: The button's className contains a leading double space in the string
(' text-primary...'); remove the extra leading space so the className begins
with "text-primary" (update the className on the button element in
studentManagementPage.tsx accordingly) to avoid an unintended empty class token.
In @src/pages/common/UserIdInputPage.tsx:
- Around line 3-7: The file has duplicate imports for SnowCodeEntryMini and
ArrowleftIcon causing redeclare errors; remove the redundant relative imports
(the imports from '../../assets/...') and keep the alias-based imports
(SnowCodeEntryMini from '@/assets/images/...' and ArrowleftIcon from
'/svg/arrowleftIcon.svg?react'), and if your usage expects a named vs default
export for ArrowleftIcon adjust the single remaining import to match how
ArrowleftIcon is consumed in this module.
🧹 Nitpick comments (9)
src/pages/common/UserIdInputPage.tsx (2)
81-90: Consider making the back icon part of the clickable Button (single hit-target).
Right now only the “이전으로” text is clickable; the arrow icon isn’t. Folding the icon into theButtonimproves UX and accessibility consistency.Possible refactor
<div className='absolute top-[43px] left-[60px] flex items-center gap-4'> - <ArrowleftIcon className='w-[18px] h-[24px]' /> <Button color='ghost' onClick={handleBeforeClick} size='none' - className='leading-7 text-lg'> + className='flex items-center gap-4 leading-7 text-lg'> + <ArrowleftIcon className='w-[18px] h-[24px]' /> 이전으로 </Button> </div>
114-123: Ensure active input styling also preserves the intended text color.
Non-active filled inputs explicitly settext-primary-black, but the active branch doesn’t. If the base styles don’t guarantee the same, active state may render with an unintended color.src/index.css (1)
51-53: Nice addition of status tokens; sanity-check contrast where these are used.
If these are used as backgrounds with white/black text, confirm contrast is acceptable for your UI/accessibility targets.src/components/common/CourseOverview/AssignmentList.tsx (1)
1-7: Avoid coupling “common” UI toadmin/.../dummy/types. Even though it’simport type, this creates an awkward dependency direction; consider movingAssignmentto a sharedtypesmodule used by both admin/common. Based on learnings, keeping explicit props interfaces likeAssignmentListPropsis a good call.src/utils/getSemesterLabel.ts (1)
1-12: DecouplegetSemesterLabelfromadmin/.../dummy/typesand consider an unknown-code fallback. A sharedSemesterCodetype (non-dummy) would fit better, and a defensive fallback (or explicit error) can prevent silentundefinedlabels if data ever drifts.src/components/common/CourseOverview/dummy/types.ts (1)
1-5: Consider moving these domain types out ofadmin/.../dummy/types. If these interfaces are used broadly, a sharedsrc/types(orsrc/domain) module will reduce dependency tangles and future refactors.src/components/admin/assignments/AssignmentPageLayout.tsx (1)
8-19: Remove unused onLinkAssignments prop.The
onLinkAssignmentsprop is defined in the interface (line 12) but is neither destructured in the component parameters (line 19) nor used anywhere in the component body. This is dead code.♻️ Proposed fix to remove unused prop
interface AssignmentPageLayoutProps { title: string; fullCourses: Course[]; selectMode: boolean; - onLinkAssignments?: (id: number, title: string, isSelected: boolean) => void; }src/pages/admin/student/studentManagementPage.tsx (1)
25-33: Placeholder handlers need implementation.The
onCancelandonConfirmhandlers are currently empty placeholders. Ensure these are implemented before the feature goes live, or document the expected behavior.Would you like me to open an issue to track the implementation of these handler functions?
src/layout/Layout.tsx (1)
52-71: Avoidkey={index}for nav buttons; use a stable key and consider extracting props typing.
key={index}(Line 63) can cause unnecessary remounts if the button list changes;button.labelis stable here. Also, if you want to align with the stated preference for interface-based props, extract the inline prop type forNavigationBar. Based on learnings, interfaces for props improve maintainability.Proposed diff
interface NavButton { icon: React.ReactElement; label: string; } +interface NavigationBarProps { + buttons: NavButton[]; + width: string; +} + // 네비게이션 컴포넌트 - const NavigationBar = ({ - buttons, - width, - }: { - buttons: NavButton[]; - width: string; - }) => ( + const NavigationBar = ({buttons, width}: NavigationBarProps) => ( <nav className={`flex-1 bg-gradient-to-r from-light-purple to-purple ${width} h-full px-3 py-[8px] rounded-full flex items-center justify-between gap-9`}> {buttons.map((button, index) => ( <Button - key={index} + key={button.label} content='icon' size='icon' aria-label={button.label}> {button.icon} </Button> ))} </nav> );
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (3)
package-lock.jsonis excluded by!**/package-lock.jsonpublic/svg/profileImage.svgis excluded by!**/*.svgpublic/svg/search.svgis excluded by!**/*.svg
📒 Files selected for processing (51)
.coderabbit.yaml.husky/commit-msg.prettierrccommitlint.config.cjspackage.jsonsrc/App.tsxsrc/assets/svg/ArrowdownIcon.tsxsrc/assets/svg/ArrowleftIcon.tsxsrc/assets/svg/ArrowrightIcon.tsxsrc/assets/svg/ChatIcon.tsxsrc/assets/svg/Chevrondown.tsxsrc/assets/svg/DeleteIcon.tsxsrc/assets/svg/DragAndDropIcon.tsxsrc/assets/svg/EditIcon.tsxsrc/assets/svg/EllipsisIcon.tsxsrc/assets/svg/File.tsxsrc/assets/svg/NotificationIcon.tsxsrc/assets/svg/SignoutIcon.tsxsrc/assets/svg/SingleEllipsisIcon.tsxsrc/assets/svg/UserIcon.tsxsrc/components/admin/assignments/AssignmentCard.tsxsrc/components/admin/assignments/AssignmentFormLayout.tsxsrc/components/admin/assignments/AssignmentPageLayout.tsxsrc/components/admin/assignments/CourseSelector.tsxsrc/components/admin/form/FileUpload.tsxsrc/components/admin/form/LabeledDropdown.tsxsrc/components/common/BaseHeader.tsxsrc/components/common/CourseOverview/AssignmentItem.tsxsrc/components/common/CourseOverview/AssignmentList.tsxsrc/components/common/CourseOverview/CourseActionsBar.tsxsrc/components/common/CourseOverview/CourseHero.tsxsrc/components/common/CourseOverview/CourseStat.tsxsrc/components/common/CourseOverview/EmptyCourse.tsxsrc/components/common/CourseOverview/SubmissionBadge.tsxsrc/components/common/CourseOverview/dummy/types.tssrc/components/common/Dashboard/CourseCard.tsxsrc/components/common/Dashboard/CourseList.tsxsrc/components/common/Dashboard/ScheduleList.tsxsrc/components/common/Dashboard/types.tssrc/components/common/IconButton.tsxsrc/index.csssrc/layout/Layout.tsxsrc/pages/admin/assignments/AssignmentCreatePage.tsxsrc/pages/admin/assignments/AssignmentSelectPage.tsxsrc/pages/admin/assignments/AssignmentsPage.tsxsrc/pages/admin/student/studentManagementPage.tsxsrc/pages/common/CourseOverviewPage.tsxsrc/pages/common/Dashboard.tsxsrc/pages/common/LandingPage.tsxsrc/pages/common/UserIdInputPage.tsxsrc/utils/getSemesterLabel.ts
💤 Files with no reviewable changes (14)
- src/assets/svg/DragAndDropIcon.tsx
- src/assets/svg/UserIcon.tsx
- src/assets/svg/EditIcon.tsx
- src/assets/svg/EllipsisIcon.tsx
- src/assets/svg/ArrowdownIcon.tsx
- src/assets/svg/File.tsx
- src/assets/svg/ArrowrightIcon.tsx
- src/assets/svg/DeleteIcon.tsx
- src/assets/svg/SignoutIcon.tsx
- src/assets/svg/SingleEllipsisIcon.tsx
- src/assets/svg/NotificationIcon.tsx
- src/assets/svg/Chevrondown.tsx
- src/assets/svg/ChatIcon.tsx
- src/assets/svg/ArrowleftIcon.tsx
✅ Files skipped from review due to trivial changes (4)
- src/components/common/CourseOverview/CourseStat.tsx
- src/pages/common/LandingPage.tsx
- src/components/common/IconButton.tsx
- src/pages/admin/assignments/AssignmentsPage.tsx
🚧 Files skipped from review as they are similar to previous changes (4)
- src/components/common/CourseOverview/AssignmentItem.tsx
- src/components/common/CourseOverview/CourseActionsBar.tsx
- src/components/admin/assignments/AssignmentFormLayout.tsx
- src/pages/admin/assignments/AssignmentCreatePage.tsx
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-07-13T00:27:31.464Z
Learnt from: JiiminHa
Repo: 2025-snowCode/snowCode-Client PR: 2
File: src/components/Header/StudentHeader.tsx:10-10
Timestamp: 2025-07-13T00:27:31.464Z
Learning: Using TypeScript interfaces for React component props (like StudentHeaderProps) provides clear structure, improves readability, and makes components more maintainable and extensible for future development.
Applied to files:
src/components/common/Dashboard/types.tssrc/pages/admin/student/studentManagementPage.tsxsrc/components/common/BaseHeader.tsxsrc/components/admin/assignments/CourseSelector.tsxsrc/components/common/CourseOverview/AssignmentList.tsxsrc/components/common/Dashboard/CourseCard.tsxsrc/layout/Layout.tsxsrc/components/admin/assignments/AssignmentCard.tsx
📚 Learning: 2025-07-16T12:33:43.867Z
Learnt from: JiiminHa
Repo: 2025-snowCode/snowCode-Client PR: 6
File: src/App.tsx:6-11
Timestamp: 2025-07-16T12:33:43.867Z
Learning: JiiminHa prefers hierarchical routing structure with role-based path organization: common routes at root level (/), student-specific routes under /student prefix, and admin-specific routes under /admin prefix, using nested routes with a shared Layout component for consistent UI patterns.
Applied to files:
src/App.tsx
🧬 Code graph analysis (2)
src/layout/Layout.tsx (1)
src/components/common/Dashboard/types.ts (1)
UserType(30-30)
src/App.tsx (2)
src/pages/common/UserIdInputPage.tsx (1)
UserIdInputPage(9-138)src/pages/admin/student/studentManagementPage.tsx (1)
StudentManagementPage(5-34)
🪛 Biome (2.1.2)
src/pages/common/UserIdInputPage.tsx
[error] 5-5: Shouldn't redeclare 'SnowCodeEntryMini'. Consider to delete it or rename it.
'SnowCodeEntryMini' is defined here:
(lint/suspicious/noRedeclare)
[error] 6-6: Shouldn't redeclare 'ArrowleftIcon'. Consider to delete it or rename it.
'ArrowleftIcon' is defined here:
(lint/suspicious/noRedeclare)
🪛 YAMLlint (1.37.1)
.coderabbit.yaml
[error] 24-24: duplication of key "high_level_summary_placeholder" in mapping
(key-duplicates)
🔇 Additional comments (32)
src/components/admin/form/LabeledDropdown.tsx (1)
2-2: SVG import configuration is properly set up—no changes needed.The migration to direct SVG imports with the
?reactsuffix is correctly configured:
- SVG file exists at
public/svg/chevrondown.svg- Vite has
vite-plugin-svgrconfigured with proper settings- TypeScript declarations include
vite-plugin-svgr/clienttypes invite-env.d.tsThe import will work as intended.
src/components/admin/assignments/AssignmentCard.tsx (1)
2-5: No configuration issues. The import pattern/svg/*.svg?reactis correctly configured and supported. The project usesvite-plugin-svgrwith proper TypeScript declarations (vite-plugin-svgr/client), and the SVG files exist atpublic/svg/. These imports will work as intended.src/components/common/BaseHeader.tsx (1)
1-1: LGTM! Path alias improves maintainability.The refactor from a relative import path to the
@/alias makes the codebase more maintainable and prevents issues when files are reorganized. The@/alias is properly configured in bothtsconfig.app.jsonandvite.config.ts, and the asset file exists at the resolved path.src/components/common/CourseOverview/EmptyCourse.tsx (2)
1-1: LGTM: Import path updated to absolute alias.The change to use the
@/alias improves consistency and maintainability across the project.
14-14: No action needed—empty strings are appropriate here.The
CourseActionsBarinterface explicitly requirestitleandsectionto bestringtype (not optional). Empty strings correctly satisfy this requirement and are semantically appropriate for the empty state inEmptyCourse. Usingnullorundefinedwould violate the prop type definition. The code is correct as-is.src/pages/common/UserIdInputPage.tsx (1)
127-134: CTA migration to shared Button looks consistent (disabled gating is clear).
disabled={!isComplete}combined with the early-return inhandleSubmitis a good double-guard.src/components/admin/form/FileUpload.tsx (2)
106-106: LGTM!The component usage is correctly updated to match the new import. The props and styling remain unchanged, ensuring no behavioral differences.
3-3: Revert to the established svgr-generated import pattern.This import change breaks the project's established workflow. The codebase uses svgr to generate TypeScript components from SVGs in
public/svg/and exports them fromsrc/assets/svg/index.ts. The correct approach is to importFilefrom@/assets/svg(which is already exported at line 12 of index.ts). The change to import directly from/svg/file.svg?reactbypasses the svgr workflow that other SVG components in the project follow (AddIcon, Correct, Incorrect, etc.). If renaming toFileIconis desired, that should be done in the generated component, not by switching import patterns.Likely an incorrect or invalid review comment.
src/components/admin/assignments/CourseSelector.tsx (1)
2-2: Consider adding explicit path alias for/svg/in Vite config for better clarity.The import is compatible with your build setup:
vite-plugin-svgris installed and configured withicon: true, which allows passing width/height props to SVG components. The absolute path/svg/works because Vite's defaultpublicDirispublic/, resolving it topublic/svg/arrowdownIcon.svg.However, to improve clarity and maintainability, add an explicit alias in your
vite.config.ts:resolve: { alias: { '@': path.resolve(__dirname, './src'), '/svg': path.resolve(__dirname, './public/svg'), // Add this line }, }This makes the path mapping explicit and matches the pattern already used across 16+ files in your codebase.
src/pages/common/CourseOverviewPage.tsx (1)
1-4: Import refactor to@/is fine (no behavioral change).
Just make sure this file is covered by the same alias config as the rest of the app (TS + Vite).package.json (1)
18-18: [Your rewritten review comment text here]
[Exactly ONE classification tag]src/components/common/Dashboard/ScheduleList.tsx (1)
2-3: Import alias@/is correctly configured in both TypeScript and Vite.TypeScript paths (
tsconfig.app.json):"@/*": ["./src/*"]
Vite alias (vite.config.ts):'@': path.resolve(__dirname, './src')Both configurations are consistent and point to the same directory, so the import statements will resolve correctly.
.prettierrc (1)
20-21: Configuration is correct;tailwindStylesheetis properly set up.The
prettier-plugin-tailwindcssis installed in devDependencies, andtailwindStylesheet: "src/index.css"is the correct (required) option for Tailwind CSS v4+. Prettier auto-loads the plugin from.prettierrc, so no additional configuration is needed.src/components/common/Dashboard/CourseCard.tsx (1)
2-4: LGTM! Clean import refactor.The migration to Vite's
?reactSVG import syntax and path aliases improves maintainability without affecting functionality.commitlint.config.cjs (1)
1-3: LGTM! Standard commitlint setup.The configuration correctly extends the conventional config preset, aligning with the commit message validation in the Husky hook.
.husky/commit-msg (1)
1-34: LGTM! Well-structured commit message validation.The two-stage validation approach (custom format check followed by commitlint) effectively catches common mistakes while providing clear, educational error messages. The regex correctly validates that issue numbers require spacing before text.
src/components/common/Dashboard/CourseList.tsx (2)
1-5: LGTM! Consistent import refactoring.Import updates align with the project-wide migration to SVG-as-React-component syntax and path aliases.
49-56: LGTM! Button API migration looks correct.The refactor from native button to the new Button component API (using children instead of label prop) is consistent with the Button.tsx refactor to Tailwind Variants mentioned in the PR summary. The props usage (
color,size,className) aligns with the variant-based approach..coderabbit.yaml (1)
27-90: Well-structured path-specific review guidelines.The comprehensive instructions for React components, hooks, and TypeScript code provide clear, actionable standards for the team. The Korean language guidelines are detailed and cover important aspects like naming conventions, accessibility, and performance considerations.
src/pages/common/Dashboard.tsx (1)
1-2: Alias import migration looks good. Just ensure all toolchains (Vite/TS/Jest/ESLint) resolve@/consistently so this doesn’t break in CI/build.src/components/common/CourseOverview/CourseHero.tsx (2)
2-4: Alias imports are fine; keep SVG module typing consistent. If the project relies on*.svgtyping (SVGR vs URL), ensure the alias move didn’t bypass any special import handling.
34-41: CourseActionsBar correctly acceptstitleandsectionprops; all call sites are properly updated. BothEmptyCourse.tsxandCourseHero.tsxpass the required props. No build/TS issues.The
absolute ... right-26positioning adjustment can be verified through responsive testing on different screen sizes to ensure proper alignment.src/components/common/Dashboard/types.ts (1)
1-1: LGTM! Clean import path refactor.The switch from relative to alias-based import improves maintainability and aligns with the project-wide path refactoring effort visible across this PR.
src/components/common/CourseOverview/SubmissionBadge.tsx (1)
1-4: LGTM! Import paths updated correctly.The alias-based import paths improve maintainability and are consistent with the broader refactoring in this PR.
src/pages/admin/assignments/AssignmentSelectPage.tsx (2)
1-3: LGTM! Clean import refactor.Import paths correctly updated to alias-based resolution, consistent with the project-wide refactoring.
19-25: LGTM! Simplified component logic.Removal of linked assignments state management and handler is appropriate for this select-mode page. The component now focuses solely on rendering the selection UI without managing selection state internally.
src/components/admin/assignments/AssignmentPageLayout.tsx (3)
3-5: LGTM! Import paths updated correctly.The alias-based imports for Button and AddIcon are consistent with the broader refactoring effort.
35-38: LGTM! Button API refactor looks good.The transition from prop-based configuration to a children-based content API with explicit color and size props improves flexibility and aligns with the new Button component design mentioned in the PR summary.
41-42: LGTM! Action buttons updated appropriately.The color prop updates and label change from '저장' to '등록' align well with the Button component refactor.
src/pages/admin/student/studentManagementPage.tsx (1)
14-22: Verify search icon alignment.The search icon uses hardcoded positioning (
top-3) which may not align perfectly if the input height changes or on different screen sizes. Consider using flexbox centering for more robust alignment.💡 Suggested improvement for icon positioning
- <div className='relative'> + <div className='relative flex items-center'> <input type='text' placeholder='학번을 검색하세요' className='border border-gray-300 rounded-lg px-4 py-2 pr-10 w-64' /> - <Search className='absolute right-3 top-3 w-4 h-4 text-gray-400' /> + <Search className='absolute right-3 w-4 h-4 text-gray-400 pointer-events-none' /> </div>src/App.tsx (2)
18-40: Routing structure looks consistent (root +/student+/adminwith nested child paths).Using a shared
<Layout />with nested routes under/,/student, and/adminis clean and matches the role-based organization preference. Based on learnings, this aligns with the desired hierarchy.
34-40: No stale links to old admin create routes found. All navigation references have been properly updated to use the new relative paths (assignments/createandcourses/create). The route migration is complete with no 404 risk.
| 4. 칭찬은 짧고 위트 있게 작성하세요. | ||
| reviews: | ||
| profile: educational |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical: Invalid profile value.
The profile value 'educational' is not valid according to the schema. Only 'chill' or 'assertive' are accepted values.
🔧 Proposed fix
Based on the tone instructions emphasizing educational feedback and improvement suggestions, 'chill' would be the appropriate choice:
reviews:
- profile: educational
+ profile: chill
request_changes_workflow: trueNote: The current PR already uses "Chill" mode as mentioned in the review context, so this aligns with the existing setup.
🤖 Prompt for AI Agents
In @.coderabbit.yaml at line 11, The profile value 'educational' is invalid;
update the .coderabbit.yaml profile key to an accepted value (use 'chill' to
match the existing PR context) by replacing the current profile: educational
entry with profile: chill so the file conforms to the schema.
| high_level_summary_placeholder: | | ||
| @coderabbitai summary | ||
| (졸업작품 평가 기준: 구조 / 타입 안정성 / 접근성 관점 요약) | ||
| poem: false | ||
| review_status: true | ||
| suggested_labels: true | ||
| commit_status: true | ||
| fail_commit_status: false | ||
| abort_on_close: true | ||
| high_level_summary_in_walkthrough: true | ||
| high_level_summary_placeholder: '@coderabbitai summary' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Critical: Duplicate key causes YAML parsing failure.
The high_level_summary_placeholder key is defined twice (lines 14 and 24), which will cause the YAML parser to fail. This prevents CodeRabbit from loading the configuration.
🔧 Proposed fix
Remove the duplicate key on line 24 and keep only the first definition:
abort_on_close: true
high_level_summary_in_walkthrough: true
- high_level_summary_placeholder: '@coderabbitai summary'
collapse_walkthrough: trueThe first definition (lines 14-16) already includes the detailed placeholder with graduation project criteria, which appears more comprehensive than the duplicate.
🧰 Tools
🪛 YAMLlint (1.37.1)
[error] 24-24: duplication of key "high_level_summary_placeholder" in mapping
(key-duplicates)
🤖 Prompt for AI Agents
In @.coderabbit.yaml around lines 14 - 24, The YAML defines the key
high_level_summary_placeholder twice, causing a parsing failure; remove the
duplicate occurrence that sets high_level_summary_placeholder: '@coderabbitai
summary' and keep the first, more detailed high_level_summary_placeholder block
(the one containing "@coderabbitai summary (졸업작품 평가 기준: 구조 / 타입 안정성 / 접근성 관점
요약)"), ensuring there is only one high_level_summary_placeholder entry so the
YAML parses correctly.
| import BaseHeader from '@/components/common/BaseHeader'; | ||
| import NotificationIcon from '/svg/notificationIcon.svg?react'; | ||
| import SignoutIcon from '/svg/signoutIcon.svg?react'; | ||
| import UserIcon from '/svg/userIcon.svg?react'; | ||
| import ChatIcon from '/svg/chatIcon.svg?react'; | ||
| import Button from '@/components/common/Button'; | ||
| import React from 'react'; | ||
|
|
||
| type UserType = 'admin' | 'student'; | ||
|
|
||
| interface NavButton { | ||
| icon: React.ReactElement; | ||
| label: string; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# 1) Find where the SVG files are located (source and generated)
echo "=== Locating SVG files ==="
find . -type f \( -name "notificationIcon.svg" -o -name "signoutIcon.svg" -o -name "userIcon.svg" -o -name "chatIcon.svg" \)
# 2) Check for svgr config in the repo root
echo "=== Checking SVGR configuration ==="
ls -la | grep -i svgr || echo "No svgr file found in root"
cat .svgrrc.* 2>/dev/null || echo "No .svgrrc config found"
cat svgr.config.* 2>/dev/null || echo "No svgr.config found"
# 3) Check vite config for asset handling
echo "=== Checking vite config ==="
fd -a 'vite\.config\.' . | head -5
# 4) Find all SVG imports to see the established pattern
echo "=== Existing SVG import patterns in src ==="
rg -n "import.*from.*\.svg" src --type ts --type tsx
# 5) Check if UserType exists in Dashboard/types.ts
echo "=== Checking for UserType in Dashboard types ==="
rg -n "UserType" src --type ts --type tsxRepository: 2025-snowCode/snowCode-Client
Length of output: 474
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# 1) Read vite config to understand SVG handling
echo "=== Vite config ==="
cat vite.config.ts
# 2) Check if src/assets/svg exists and what's in it
echo ""
echo "=== Content of src/assets/svg/ ==="
ls -la src/assets/svg/ 2>/dev/null || echo "Directory does not exist"
# 3) Search for SVG imports without type restrictions
echo ""
echo "=== SVG imports in codebase ==="
rg "import.*\.svg" src
# 4) Check Dashboard/types.ts for UserType
echo ""
echo "=== UserType definitions ==="
rg -n "type UserType|interface UserType" src
rg -n "UserType" src/components/common/Dashboard/types.ts 2>/dev/null || echo "File or pattern not found"
# 5) Check the actual import in Layout.tsx
echo ""
echo "=== Current imports in Layout.tsx ==="
head -20 src/layout/Layout.tsxRepository: 2025-snowCode/snowCode-Client
Length of output: 5222
Import UserType from src/components/common/Dashboard/types.ts instead of redefining it locally.
UserType is already defined and exported in src/components/common/Dashboard/types.ts. Duplicating it here creates maintenance drift risk—import the shared type instead:
import { UserType } from '@/components/common/Dashboard/types';The SVG imports using /svg/*.svg?react are correct and follow the established pattern in this codebase (vite-plugin-svgr is configured in vite.config.ts).
🤖 Prompt for AI Agents
In @src/layout/Layout.tsx around lines 3 - 16, Remove the locally declared
UserType and instead import the shared type by adding an import for UserType
from the Dashboard types module, then delete the local "type UserType = 'admin'
| 'student';" declaration and ensure any usages (e.g., props or state types in
Layout, and related interfaces like NavButton if they reference UserType
elsewhere) refer to the imported UserType.
|
|
||
| const titleExtra = ( | ||
| <div className='flex justify-between items-center flex-1'> | ||
| <button className=' text-primary px-3 py-[6px] rounded-4xl inline-flex h-8 justify-center items-center border border-primary'> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix double space in className.
The className string has an extra leading space: ' text-primary' should be 'text-primary'.
🧹 Proposed fix
- <button className=' text-primary px-3 py-[6px] rounded-4xl inline-flex h-8 justify-center items-center border border-primary'>
+ <button className='text-primary px-3 py-[6px] rounded-4xl inline-flex h-8 justify-center items-center border border-primary'>📝 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.
| <button className=' text-primary px-3 py-[6px] rounded-4xl inline-flex h-8 justify-center items-center border border-primary'> | |
| <button className='text-primary px-3 py-[6px] rounded-4xl inline-flex h-8 justify-center items-center border border-primary'> |
🤖 Prompt for AI Agents
In @src/pages/admin/student/studentManagementPage.tsx at line 11, The button's
className contains a leading double space in the string (' text-primary...');
remove the extra leading space so the className begins with "text-primary"
(update the className on the button element in studentManagementPage.tsx
accordingly) to avoid an unintended empty class token.
| import SnowCodeEntryMini from '@/assets/images/snowCode_entry_mini.svg'; | ||
| import ArrowleftIcon from '/svg/arrowleftIcon.svg?react'; | ||
| import SnowCodeEntryMini from '../../assets/images/snowCode_entry_mini.svg'; | ||
| import {ArrowleftIcon} from '../../assets/svg'; | ||
| import Button from '@/components/common/Button'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix duplicate imports (current code won’t compile due to redeclare).
SnowCodeEntryMini and ArrowleftIcon are each imported twice (Line 3 + Line 5, Line 4 + Line 6). This matches the Biome noRedeclare errors.
Proposed fix (keep the alias-based imports; adjust icon path if needed)
import {useState, useRef, useEffect} from 'react';
import {useNavigate, useLocation} from 'react-router-dom';
import SnowCodeEntryMini from '@/assets/images/snowCode_entry_mini.svg';
-import ArrowleftIcon from '/svg/arrowleftIcon.svg?react';
-import SnowCodeEntryMini from '../../assets/images/snowCode_entry_mini.svg';
-import {ArrowleftIcon} from '../../assets/svg';
+import {ArrowleftIcon} from '@/assets/svg';
import Button from '@/components/common/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.
| import SnowCodeEntryMini from '@/assets/images/snowCode_entry_mini.svg'; | |
| import ArrowleftIcon from '/svg/arrowleftIcon.svg?react'; | |
| import SnowCodeEntryMini from '../../assets/images/snowCode_entry_mini.svg'; | |
| import {ArrowleftIcon} from '../../assets/svg'; | |
| import Button from '@/components/common/Button'; | |
| import SnowCodeEntryMini from '@/assets/images/snowCode_entry_mini.svg'; | |
| import {ArrowleftIcon} from '@/assets/svg'; | |
| import Button from '@/components/common/Button'; |
🧰 Tools
🪛 Biome (2.1.2)
[error] 5-5: Shouldn't redeclare 'SnowCodeEntryMini'. Consider to delete it or rename it.
'SnowCodeEntryMini' is defined here:
(lint/suspicious/noRedeclare)
[error] 6-6: Shouldn't redeclare 'ArrowleftIcon'. Consider to delete it or rename it.
'ArrowleftIcon' is defined here:
(lint/suspicious/noRedeclare)
🤖 Prompt for AI Agents
In @src/pages/common/UserIdInputPage.tsx around lines 3 - 7, The file has
duplicate imports for SnowCodeEntryMini and ArrowleftIcon causing redeclare
errors; remove the redundant relative imports (the imports from
'../../assets/...') and keep the alias-based imports (SnowCodeEntryMini from
'@/assets/images/...' and ArrowleftIcon from '/svg/arrowleftIcon.svg?react'),
and if your usage expects a named vs default export for ArrowleftIcon adjust the
single remaining import to match how ArrowleftIcon is consumed in this module.
⚙️ Related ISSUE Number
Related #21
📄 Work Description
Badge컴포넌트 구현:schedule,submission,index세 가지 유형의 배지를 지원.CORRECT,INCORRECT,NOT_SUBMITTED상태에 따라 아이콘과 텍스트 표시.upcoming,later상태에 따라 배경 및 텍스트 스타일 변경.unit과problem에 따라 스타일 및 텍스트 접미사 추가.scheduleBadgeStyles,submissionBadgeStyles,indexBadgeStyles로 스타일 분리.📷 Screenshot
💬 To Reviewers
🔗 Reference
Summary by CodeRabbit
New Features
UI Improvements
Chores
✏️ Tip: You can customize this high-level summary in your review settings.