Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/conventions/coding-style.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
- 훅: `useXxx`. 일반 함수/변수: camelCase. 상수: `UPPER_SNAKE_CASE`.
- 불리언: `is` / `has` / `should` 접두사.
- 폴더: 도메인명 소문자 또는 kebab-case.
- **도메인 이름은 임의로 번역/축약하지 않는다.** `features/<기능>/` 폴더명, 라우트 경로, 도메인 접두사가 붙는 컴포넌트/타입명은 `docs/conventions/terminology.md`(용어 사전)의 코드 용어를 그대로 쓴다 — 백엔드 API 엔드포인트 네이밍과 맞추기 위함이다. 사전에 없는 새 도메인이면 먼저 그 문서에 추가한 뒤 코드에 반영한다.

## 폴더 구조

Expand Down
38 changes: 38 additions & 0 deletions docs/conventions/terminology.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# 용어 사전 (한글 도메인명 ↔ 코드 용어)

> 코드에서 도메인 이름을 임의로 짓지 않기 위한 사전. 백엔드 API 엔드포인트 네이밍과 프론트 코드(라우트 경로, `src/features/` 폴더명, 컴포넌트/타입 접두사 등)가 같은 용어를 쓰게 맞춘다.

## 원칙

- 새 기능/화면을 만들 때 도메인 이름이 필요하면, 영어로 대충 번역하지 말고 **반드시 이 표부터 확인한다.**
- 여기 없는 새 도메인이 생기면 백엔드와 협의해서 엔드포인트 네이밍을 먼저 정하고, 그걸 이 표에 추가한 뒤 코드에 반영한다 — 프론트에서 먼저 임의로 정하지 않는다.
- 표의 "코드 용어"는 백엔드 엔드포인트 세그먼트(`/api/{코드 용어}/...`)와 동일한 문자열이다. 프론트에서는 아래 "적용 범위"에 그대로 쓴다.

## 사전

| 한글 도메인명 | 코드 용어 |
| --- | --- |
| 공통 | `auth` |
| 사용자 | `users` |
| 게시판(공지) | `notices` |
| 게시판(열린피드백) | `feedbacks` |
| 빌릴게 | `bililge` |
| 사물함 | `lockers` |
| 슬랑제 | `seulrangjes` |
| 아카이빙 | `archives` |
| 챗봇 | `chat` |
| 파일 | `files` |
| 행사(event) | `events` |
| 회비 납부 | `fee` |

## 적용 범위

- 백엔드 API 엔드포인트 경로: `/api/{코드 용어}/...`
- 프론트 라우트 경로: `/{코드 용어}`
- `src/features/{코드 용어}/` 폴더명
- 그 안의 컴포넌트/타입/상수 이름의 도메인 접두사 — 코드 용어를 PascalCase로 바꿔서 쓴다 (예: `bililge` → `Bililge...`, `bililgeItems` 같은 camelCase 변수명도 동일)
- Figma 노드/화면 이름은 그대로 한글을 쓴다(디자이너와의 소통 채널이라 번역하지 않음) — 코드 파일 최상단의 `// Figma: ...` 주석에서만 한글 화면명을 남긴다.

## 반영 사례

- "빌릴게" 기능: 처음엔 `rental`로 임의 명명했다가, 이 사전을 도입하면서 `src/features/rental/` → `src/features/bililge/`로 전체 리네이밍했다(#18).
4 changes: 2 additions & 2 deletions src/app/App.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Route, Routes } from "react-router-dom";

import ScreenLayout from "@/components/ui/ScreenLayout";
import BililgeListScreen from "@/features/bililge/BililgeListScreen";
import HomeScreen from "@/features/home/HomeScreen";
import RentalListScreen from "@/features/rental/RentalListScreen";

// 데스크톱에서 보기 좋게 아이폰 화면 크기로 가운데 정렬만 해준다.
function App() {
Expand All @@ -11,7 +11,7 @@ function App() {
<Routes>
<Route element={<ScreenLayout />}>
<Route element={<HomeScreen />} path="/" />
<Route element={<RentalListScreen />} path="/rental" />
<Route element={<BililgeListScreen />} path="/bililge" />
</Route>
</Routes>
</div>
Expand Down
8 changes: 4 additions & 4 deletions src/components/ui/BottomNav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@ import {
IconTicket,
} from "@wanteddev/wds-icon";

import bililgeSelected from "@/assets/icons/bottom-nav/bililge-selected.svg";
import boardSelected from "@/assets/icons/bottom-nav/board-selected.svg";
import eventSelected from "@/assets/icons/bottom-nav/event-selected.svg";
import homeSelected from "@/assets/icons/bottom-nav/home-selected.svg";
import rentalSelected from "@/assets/icons/bottom-nav/rental-selected.svg";

export type BottomNavValue = "home" | "event" | "board" | "rental";
export type BottomNavValue = "home" | "event" | "board" | "bililge";

interface BottomNavProps {
value: BottomNavValue;
Expand Down Expand Up @@ -47,8 +47,8 @@ const TABS: BottomNavTab[] = [
{
NormalIcon: IconStorage,
label: "빌릴게",
selectedIcon: rentalSelected,
value: "rental",
selectedIcon: bililgeSelected,
value: "bililge",
},
];

Expand Down
2 changes: 1 addition & 1 deletion src/components/ui/ScreenLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import { ScreenHeaderContext } from "@/components/ui/screenHeaderContext";

// Bottom Nav 탭 ↔ 라우트 경로 매핑. 화면이 늘어나면 여기에 추가한다.
const BOTTOM_NAV_PATHS: Record<BottomNavValue, string> = {
bililge: "/bililge",
board: "/board",
event: "/event",
home: "/",
rental: "/rental",
};

function getBottomNavValueFromPath(pathname: string): BottomNavValue {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@ import { useState } from "react";

import ScreenHeader from "@/components/ui/ScreenHeader";
import { useScreenHeader } from "@/components/ui/useScreenHeader";
import RentalCategoryFilter from "@/features/rental/components/RentalCategoryFilter";
import RentalItemCard from "@/features/rental/components/RentalItemCard";
import { RENTAL_ITEMS } from "@/features/rental/constants/rentalItems";
import BililgeCategoryFilter from "@/features/bililge/components/BililgeCategoryFilter";
import BililgeItemCard from "@/features/bililge/components/BililgeItemCard";
import { BILILGE_ITEMS } from "@/features/bililge/constants/bililgeItems";

// Figma: 빌릴게 (nodeId 1243:73331)
function RentalListScreen() {
function BililgeListScreen() {
const [tab, setTab] = useState("rent");
const [category, setCategory] = useState("전체");

Expand All @@ -26,14 +26,14 @@ function RentalListScreen() {
</div>

<div className="shrink-0 px-5 py-4">
<RentalCategoryFilter onChange={setCategory} value={category} />
<BililgeCategoryFilter onChange={setCategory} value={category} />
</div>

<div className="scrollbar-hidden flex-1 overflow-y-auto">
{tab === "rent" ? (
<div className="flex flex-col gap-2 px-5 pb-4">
{RENTAL_ITEMS.map((item) => (
<RentalItemCard
{BILILGE_ITEMS.map((item) => (
<BililgeItemCard
icon={item.icon}
itemName={item.name}
key={item.id}
Expand All @@ -51,4 +51,4 @@ function RentalListScreen() {
);
}

export default RentalListScreen;
export default BililgeListScreen;
Original file line number Diff line number Diff line change
@@ -1,22 +1,25 @@
const RENTAL_CATEGORIES = [
const BILILGE_CATEGORIES = [
"전체",
"전자기기",
"생활잡화",
"상비약",
"위생용품",
];

interface RentalCategoryFilterProps {
interface BililgeCategoryFilterProps {
value: string;
onChange: (category: string) => void;
}

// Figma: 빌릴게 Filter Row (nodeId 1243:73337) — WDS Chip이 아니라 Stream 로컬 커스텀 칩.
// 카테고리·물품 매핑 API가 아직 없어 필터링 없이 선택 상태만 표시한다.
function RentalCategoryFilter({ value, onChange }: RentalCategoryFilterProps) {
function BililgeCategoryFilter({
value,
onChange,
}: BililgeCategoryFilterProps) {
return (
<div className="flex gap-1.5 overflow-x-auto">
{RENTAL_CATEGORIES.map((category) => {
{BILILGE_CATEGORIES.map((category) => {
const active = category === value;
return (
<button
Expand All @@ -37,4 +40,4 @@ function RentalCategoryFilter({ value, onChange }: RentalCategoryFilterProps) {
);
}

export default RentalCategoryFilter;
export default BililgeCategoryFilter;
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { Button } from "@wanteddev/wds";
import circleMinusFill from "@/assets/icons/circle-minus-fill.svg";
import circlePlusFill from "@/assets/icons/circle-plus-fill.svg";

interface RentalItemCardProps {
interface BililgeItemCardProps {
icon: string;
itemName: string;
quantity: number;
Expand All @@ -19,7 +19,7 @@ interface RentalItemCardProps {
// 그 이름과 1:1 대응하는 코드 export는 없다 — 대신 WDS `Button`(size="small")이 padding(7px/14px)·
// radius(8px)·타이포(label2)까지 정확히 일치해서 그걸 쓰고, Button 공개 variant엔 없는 "연한 파랑 배경
// + 파랑 텍스트" 조합만 sx로 보정했다. 스테퍼 +/- 아이콘은 여전히 WDS 미확정이라 하드코딩 — docs/plans 참고.
function RentalItemCard({
function BililgeItemCard({
icon,
itemName,
quantity,
Expand All @@ -28,7 +28,7 @@ function RentalItemCard({
stepperValue = 1,
onStepperDecrease,
onStepperIncrease,
}: RentalItemCardProps) {
}: BililgeItemCardProps) {
const isStepper = trailingControl === "stepper";

return (
Expand Down Expand Up @@ -87,4 +87,4 @@ function RentalItemCard({
);
}

export default RentalItemCard;
export default BililgeItemCard;
Original file line number Diff line number Diff line change
@@ -1,28 +1,28 @@
import eightPinCharger from "@/assets/icons/rental-items/8pin-charger.svg";
import alcoholSwab from "@/assets/icons/rental-items/alcohol-swab.svg";
import bandAid from "@/assets/icons/rental-items/band-aid.svg";
import curlingIron from "@/assets/icons/rental-items/curling-iron.svg";
import eyeDrops from "@/assets/icons/rental-items/eye-drops.svg";
import hairDryer from "@/assets/icons/rental-items/hair-dryer.svg";
import laptopCharger from "@/assets/icons/rental-items/laptop-charger.svg";
import mask from "@/assets/icons/rental-items/mask.svg";
import ointment from "@/assets/icons/rental-items/ointment.svg";
import painReliefPatch from "@/assets/icons/rental-items/pain-relief-patch.svg";
import pill from "@/assets/icons/rental-items/pill.svg";
import powerBank from "@/assets/icons/rental-items/power-bank.svg";
import sanitaryPad from "@/assets/icons/rental-items/sanitary-pad.svg";
import umbrella from "@/assets/icons/rental-items/umbrella.svg";
import usbCCharger from "@/assets/icons/rental-items/usb-c-charger.svg";
import eightPinCharger from "@/assets/icons/bililge-items/8pin-charger.svg";
import alcoholSwab from "@/assets/icons/bililge-items/alcohol-swab.svg";
import bandAid from "@/assets/icons/bililge-items/band-aid.svg";
import curlingIron from "@/assets/icons/bililge-items/curling-iron.svg";
import eyeDrops from "@/assets/icons/bililge-items/eye-drops.svg";
import hairDryer from "@/assets/icons/bililge-items/hair-dryer.svg";
import laptopCharger from "@/assets/icons/bililge-items/laptop-charger.svg";
import mask from "@/assets/icons/bililge-items/mask.svg";
import ointment from "@/assets/icons/bililge-items/ointment.svg";
import painReliefPatch from "@/assets/icons/bililge-items/pain-relief-patch.svg";
import pill from "@/assets/icons/bililge-items/pill.svg";
import powerBank from "@/assets/icons/bililge-items/power-bank.svg";
import sanitaryPad from "@/assets/icons/bililge-items/sanitary-pad.svg";
import umbrella from "@/assets/icons/bililge-items/umbrella.svg";
import usbCCharger from "@/assets/icons/bililge-items/usb-c-charger.svg";

export interface RentalItem {
export interface BililgeItem {
id: string;
name: string;
quantity: number;
icon: string;
}

// Figma: 빌릴게 Item Grid (nodeId 1243:73343) 순서·물품명·수량을 그대로 옮긴 목데이터 — 실 API 연동 전까지 사용
export const RENTAL_ITEMS: RentalItem[] = [
export const BILILGE_ITEMS: BililgeItem[] = [
{ icon: curlingIron, id: "curling-iron", name: "고데기", quantity: 28 },
{
icon: laptopCharger,
Expand Down
2 changes: 1 addition & 1 deletion src/features/home/HomeScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ function HomeScreen() {
<p className="text-label-alternative text-sm">
홈 화면은 아직 준비 중이에요
</p>
<Link className="text-primary text-sm underline" to="/rental">
<Link className="text-primary text-sm underline" to="/bililge">
빌릴게 화면 보기
</Link>
</div>
Expand Down
Loading