@su-record/vibe 2.8.19 → 2.8.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/skills/vibe-figma-analyze/SKILL.md +150 -39
package/package.json
CHANGED
|
@@ -132,25 +132,129 @@ Popup: 패턴 분류 (확인/취소, 상세 모달, 알림, 입력 폼)
|
|
|
132
132
|
- 개요 JSDoc 주석 (A-2에서 추출한 overview)
|
|
133
133
|
```
|
|
134
134
|
|
|
135
|
-
###
|
|
135
|
+
### HARD RULE: 빈 template 금지
|
|
136
136
|
|
|
137
137
|
```
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
138
|
+
브라우저에서 열었을 때 화면에 텍스트가 보여야 한다.
|
|
139
|
+
빈 컴포넌트 shell은 Step A 미완성.
|
|
140
|
+
|
|
141
|
+
<template> 안에 반드시:
|
|
142
|
+
- 스토리보드에서 추출한 실제 텍스트 (제목, 설명, 버튼 라벨)
|
|
143
|
+
- 목 데이터가 렌더링되는 리스트 (v-for / .map)
|
|
144
|
+
- 클릭 가능한 버튼/링크
|
|
145
|
+
- 조건부 렌더링 (v-if / &&)
|
|
146
|
+
```
|
|
144
147
|
|
|
145
|
-
|
|
146
|
-
|
|
148
|
+
### 섹션 컴포넌트 — 실제 코드 예시 (Vue)
|
|
149
|
+
|
|
150
|
+
```vue
|
|
151
|
+
<template>
|
|
152
|
+
<section class="dailyCheckInSection">
|
|
153
|
+
<h2 class="dailyCheckInSection__title">일일 출석 미션</h2>
|
|
154
|
+
<p class="dailyCheckInSection__description">매일 출석하고 스노우 토큰을 받으세요!</p>
|
|
155
|
+
|
|
156
|
+
<div class="dailyCheckInSection__calendar">
|
|
157
|
+
<div
|
|
158
|
+
v-for="day in checkInDays"
|
|
159
|
+
:key="day.date"
|
|
160
|
+
class="dailyCheckInSection__day"
|
|
161
|
+
:class="{ 'is-checked': day.checked, 'is-today': day.isToday }"
|
|
162
|
+
@click="handleCheckIn(day)"
|
|
163
|
+
>
|
|
164
|
+
<span class="dailyCheckInSection__dayLabel">{{ day.date }}</span>
|
|
165
|
+
<span class="dailyCheckInSection__dayReward">{{ day.reward }} 토큰</span>
|
|
166
|
+
</div>
|
|
167
|
+
</div>
|
|
168
|
+
|
|
169
|
+
<div class="dailyCheckInSection__milestones">
|
|
170
|
+
<div
|
|
171
|
+
v-for="milestone in milestones"
|
|
172
|
+
:key="milestone.days"
|
|
173
|
+
class="dailyCheckInSection__milestone"
|
|
174
|
+
:class="{ 'is-claimable': milestone.claimable, 'is-claimed': milestone.claimed }"
|
|
175
|
+
@click="handleClaimReward(milestone)"
|
|
176
|
+
>
|
|
177
|
+
<span>{{ milestone.days }}일 달성</span>
|
|
178
|
+
<span>{{ milestone.reward }}</span>
|
|
179
|
+
<button v-if="milestone.claimable && !milestone.claimed">받기</button>
|
|
180
|
+
</div>
|
|
181
|
+
</div>
|
|
182
|
+
</section>
|
|
183
|
+
</template>
|
|
184
|
+
|
|
185
|
+
<script setup lang="ts">
|
|
186
|
+
/**
|
|
187
|
+
* 일일 출석 미션 섹션
|
|
188
|
+
*
|
|
189
|
+
* [기능 정의]
|
|
190
|
+
* - 매일 출석 시 스노우 토큰 즉시 지급
|
|
191
|
+
* - 누적 3/5/7일 달성 시 추가 보상
|
|
192
|
+
*
|
|
193
|
+
* [인터랙션]
|
|
194
|
+
* ① 출석하기 클릭 → 출석 처리 → 토큰 지급 표시
|
|
195
|
+
* ② 누적 보상 클릭 → 보상 수령
|
|
196
|
+
*
|
|
197
|
+
* [상태] default, checked, reward-claimed
|
|
198
|
+
*/
|
|
199
|
+
|
|
200
|
+
interface CheckInDay {
|
|
201
|
+
date: string
|
|
202
|
+
checked: boolean
|
|
203
|
+
isToday: boolean
|
|
204
|
+
reward: number
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
interface Milestone {
|
|
208
|
+
days: number
|
|
209
|
+
claimable: boolean
|
|
210
|
+
claimed: boolean
|
|
211
|
+
reward: string
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// 목 데이터 — 빈 배열 금지!
|
|
215
|
+
const checkInDays = ref<CheckInDay[]>([
|
|
216
|
+
{ date: 'Day 1', checked: true, isToday: false, reward: 10 },
|
|
217
|
+
{ date: 'Day 2', checked: true, isToday: false, reward: 10 },
|
|
218
|
+
{ date: 'Day 3', checked: false, isToday: true, reward: 10 },
|
|
219
|
+
{ date: 'Day 4', checked: false, isToday: false, reward: 10 },
|
|
220
|
+
{ date: 'Day 5', checked: false, isToday: false, reward: 10 },
|
|
221
|
+
{ date: 'Day 6', checked: false, isToday: false, reward: 15 },
|
|
222
|
+
{ date: 'Day 7', checked: false, isToday: false, reward: 20 },
|
|
223
|
+
])
|
|
224
|
+
|
|
225
|
+
const milestones = ref<Milestone[]>([
|
|
226
|
+
{ days: 3, claimable: false, claimed: false, reward: '보상 상자 1개' },
|
|
227
|
+
{ days: 5, claimable: false, claimed: false, reward: '보상 상자 2개' },
|
|
228
|
+
{ days: 7, claimable: false, claimed: false, reward: '스페셜 보상' },
|
|
229
|
+
])
|
|
230
|
+
|
|
231
|
+
function handleCheckIn(day: CheckInDay): void {
|
|
232
|
+
// TODO: 출석 API 호출
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function handleClaimReward(milestone: Milestone): void {
|
|
236
|
+
// TODO: 누적 보상 수령 API 호출
|
|
237
|
+
}
|
|
238
|
+
</script>
|
|
239
|
+
<!-- 스타일은 외부 파일: styles/{feature}/components/_daily-checkin.scss -->
|
|
240
|
+
```
|
|
147
241
|
|
|
148
|
-
|
|
149
|
-
- 인터랙션 스펙에 맞는 함수 (body는 // TODO:)
|
|
242
|
+
### 필수 포함 사항 체크리스트
|
|
150
243
|
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
244
|
+
```
|
|
245
|
+
<template> 안에:
|
|
246
|
+
□ 섹션 제목 <h2> (스토리보드에서 추출한 실제 텍스트)
|
|
247
|
+
□ 설명 텍스트 <p> (스토리보드에서 추출)
|
|
248
|
+
□ 리스트 렌더링 (v-for + 목 데이터, 빈 배열 금지)
|
|
249
|
+
□ 버튼/CTA (실제 라벨 텍스트 + @click 핸들러)
|
|
250
|
+
□ 조건부 렌더링 (상태에 따른 v-if)
|
|
251
|
+
□ 클래스명 (Step B에서 외부 스타일과 매칭)
|
|
252
|
+
|
|
253
|
+
<script> 안에:
|
|
254
|
+
□ JSDoc: [기능 정의] + [인터랙션] + [상태]
|
|
255
|
+
□ TypeScript interface
|
|
256
|
+
□ 목 데이터 (기능 정의서에서 추출, 3~7개 아이템)
|
|
257
|
+
□ 이벤트 핸들러 함수 (body는 // TODO:)
|
|
154
258
|
```
|
|
155
259
|
|
|
156
260
|
### 스타일 분리 규칙
|
|
@@ -158,23 +262,21 @@ Popup: 패턴 분류 (확인/취소, 상세 모달, 알림, 입력 폼)
|
|
|
158
262
|
```
|
|
159
263
|
컴포넌트 파일에 <style> 블록을 작성하지 않는다.
|
|
160
264
|
스타일은 Step B에서 외부 파일로 생성.
|
|
161
|
-
컴포넌트는 template + script 만 포함.
|
|
265
|
+
컴포넌트는 <template> + <script setup> 만 포함.
|
|
162
266
|
```
|
|
163
267
|
|
|
164
|
-
###
|
|
268
|
+
### Step A 완료 기준
|
|
165
269
|
|
|
166
270
|
```
|
|
167
|
-
|
|
168
|
-
✅
|
|
169
|
-
✅ 리스트
|
|
170
|
-
✅
|
|
171
|
-
✅
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
→ Step B 완료 후 "placeholder", "Key Visual Image", 빈 dashed box가
|
|
177
|
-
코드에 남아있으면 = 미완성 (vibe-figma-frame HARD RULES 참조)
|
|
271
|
+
브라우저에서 열었을 때:
|
|
272
|
+
✅ 각 섹션의 제목/설명 텍스트가 화면에 보인다
|
|
273
|
+
✅ 리스트 아이템이 렌더링된다 (목 데이터)
|
|
274
|
+
✅ 버튼을 클릭하면 핸들러가 실행된다
|
|
275
|
+
✅ 탭/아코디언/모달이 동작한다
|
|
276
|
+
❌ 스타일은 없다 (Step B에서)
|
|
277
|
+
❌ 이미지는 없다 (Step B에서)
|
|
278
|
+
|
|
279
|
+
빈 화면 = Step A 미완성. 다음 단계로 넘어가지 않는다.
|
|
178
280
|
```
|
|
179
281
|
|
|
180
282
|
## A-6. 인터랙션 매핑 테이블
|
|
@@ -197,37 +299,46 @@ Step A에서는 이미지 자리에 빈 영역이 있을 수 있다.
|
|
|
197
299
|
### 검증 항목
|
|
198
300
|
|
|
199
301
|
```
|
|
302
|
+
0. 빈 화면 검사 (가장 중요 — 먼저 실행):
|
|
303
|
+
각 컴포넌트 파일을 Read로 열어서 <template> 안에 확인:
|
|
304
|
+
□ <h2> 또는 <h3> 섹션 제목 텍스트 존재
|
|
305
|
+
□ <p> 설명 텍스트 존재
|
|
306
|
+
□ v-for 또는 .map 렌더링 존재 (리스트 있는 섹션)
|
|
307
|
+
□ @click 또는 onClick 이벤트 존재 (인터랙션 있는 섹션)
|
|
308
|
+
<template> 안에 실제 HTML 태그가 없으면 → 빈 컴포넌트 → 재작성
|
|
309
|
+
Grep: "<template>" 다음 줄이 "</template>"이면 → 빈 template
|
|
310
|
+
|
|
200
311
|
1. 파일 존재 확인 (Glob 도구):
|
|
201
312
|
□ 루트 페이지 파일 존재
|
|
202
313
|
□ PAGE 프레임 수 = 컴포넌트 파일 수
|
|
203
314
|
□ styles 디렉토리 존재
|
|
204
|
-
□ 팝업 컴포넌트 존재 (스토리보드에 팝업이 있었으면)
|
|
205
|
-
→ 누락 시 Write로 생성
|
|
206
|
-
|
|
207
|
-
2. 기능 주석 확인 (Read 도구):
|
|
208
|
-
□ 모든 컴포넌트에 [기능 정의] + [인터랙션] + [상태] JSDoc
|
|
209
|
-
→ 누락 시 Edit으로 추가
|
|
210
315
|
|
|
211
|
-
|
|
316
|
+
2. 목 데이터 확인 (Grep 도구):
|
|
212
317
|
□ 빈 배열 (ref([]) 패턴) 검색 → 0건
|
|
213
318
|
→ 발견 시 목 데이터 채움
|
|
214
319
|
|
|
215
|
-
|
|
320
|
+
3. 스타일 분리 확인 (Grep 도구):
|
|
216
321
|
□ 컴포넌트 내 <style> 블록 0건
|
|
217
|
-
→ 발견 시 제거
|
|
218
322
|
|
|
219
|
-
|
|
323
|
+
4. 빌드 확인 (Bash 도구):
|
|
220
324
|
□ npm run build 성공
|
|
221
|
-
|
|
325
|
+
|
|
326
|
+
5. 브라우저 확인:
|
|
327
|
+
□ dev 서버 열어서 실제 화면 확인
|
|
328
|
+
□ 각 섹션에 텍스트가 보이는지
|
|
329
|
+
□ 빈 화면이면 → 해당 컴포넌트 재작성
|
|
222
330
|
```
|
|
223
331
|
|
|
224
332
|
### 완료 조건
|
|
225
333
|
|
|
226
334
|
```
|
|
335
|
+
✅ 빈 template 0개 — 모든 컴포넌트에 실제 HTML 마크업 존재
|
|
336
|
+
✅ 브라우저에서 텍스트/리스트/버튼이 보인다
|
|
227
337
|
✅ 파일 수 = PAGE 프레임 수
|
|
228
|
-
✅ 모든 JSDoc 주석 완비
|
|
229
338
|
✅ 빈 배열 0개
|
|
230
339
|
✅ <style> 블록 0개
|
|
231
340
|
✅ 빌드 성공
|
|
341
|
+
|
|
342
|
+
빈 화면 = Step A 미완성. Step B로 넘어가지 않는다.
|
|
232
343
|
→ Step B 진행 가능
|
|
233
344
|
```
|