feat: [design-insight] AI 프롬프트 복사 버튼 추가

- 카드 상세 모달 편집 버튼 옆에 AI 프롬프트 버튼 추가
- 패턴 정보/구성요소/가이드라인을 AI 프롬프트로 변환 후 클립보드 복사
- 복사한 프롬프트를 AI에 붙여넣으면 해당 스타일로 코드 생성 가능
This commit is contained in:
김보곤
2026-03-08 11:10:54 +09:00
parent 4bc4e83340
commit 441a20a5d2

View File

@@ -1363,6 +1363,9 @@
<h3 x-text="previewCard.title || '(제목 없음)'" style="font-size: 15px;"></h3> <h3 x-text="previewCard.title || '(제목 없음)'" style="font-size: 15px;"></h3>
</div> </div>
<div style="display: flex; gap: 6px; align-items: center;"> <div style="display: flex; gap: 6px; align-items: center;">
<button class="di-btn sm" style="background: linear-gradient(135deg, #8b5cf6, #6366f1); color: #fff; border: none;" @click="copyAiPrompt(previewCard)" title="AI 프롬프트 복사">
<i class="ri-sparkling-line"></i> AI 프롬프트
</button>
<button class="di-btn sm" @click="showPreviewModal = false; openEditCardModal(previewCard)"> <button class="di-btn sm" @click="showPreviewModal = false; openEditCardModal(previewCard)">
<i class="ri-edit-line"></i> 편집 <i class="ri-edit-line"></i> 편집
</button> </button>
@@ -4688,6 +4691,92 @@ function designInsight() {
return String(d.getHours()).padStart(2,'0') + ':' + String(d.getMinutes()).padStart(2,'0') + ':' + String(d.getSeconds()).padStart(2,'0'); return String(d.getHours()).padStart(2,'0') + ':' + String(d.getMinutes()).padStart(2,'0') + ':' + String(d.getSeconds()).padStart(2,'0');
}, },
copyAiPrompt(card) {
const catLabel = (() => { const c = this.categories.find(cat => cat.code === card.category); return c ? c.label : card.category; })();
const stars = '★'.repeat(card.rating || 0) + '☆'.repeat(5 - (card.rating || 0));
let prompt = `## UI 패턴 구현 요청\n\n`;
prompt += `아래 UI/UX 패턴 레퍼런스를 참고하여, 동일한 스타일과 구조로 코드를 작성해 주세요.\n\n`;
prompt += `---\n\n`;
prompt += `### 패턴 정보\n`;
prompt += `- **패턴명**: ${card.title}\n`;
prompt += `- **카테고리**: ${catLabel}\n`;
prompt += `- **완성도 평점**: ${stars} (${card.rating || 0}/5)\n`;
if ((card.tags || []).length > 0) prompt += `- **키워드**: ${card.tags.join(', ')}\n`;
prompt += `\n`;
if (card.memo) {
prompt += `### 레퍼런스 설명\n`;
prompt += `${card.memo}\n\n`;
}
if ((card.usedIn || []).length > 0) {
prompt += `### 실제 사용처 (벤치마킹 대상)\n`;
card.usedIn.forEach(u => { prompt += `- ${u}\n`; });
prompt += `\n`;
}
if ((card.components || []).length > 0 && card.components[0]?.name) {
prompt += `### 필수 구성 요소\n`;
const required = card.components.filter(c => c.required);
const optional = card.components.filter(c => !c.required);
if (required.length > 0) {
prompt += `\n**필수 (반드시 포함)**:\n`;
required.forEach(c => { prompt += `- ✅ ${c.name}\n`; });
}
if (optional.length > 0) {
prompt += `\n**선택 (권장)**:\n`;
optional.forEach(c => { prompt += `- ○ ${c.name}\n`; });
}
prompt += `\n`;
}
if (card.guidelines) {
prompt += `### 디자인 가이드라인\n`;
prompt += `${card.guidelines}\n\n`;
}
if (card.suggestion) {
prompt += `### 개선 제안\n`;
prompt += `${card.suggestion}\n\n`;
}
if (card.effect) {
prompt += `### 기대 효과\n`;
prompt += `${card.effect}\n\n`;
}
if (card.type === 'analysis' && card.principles) {
prompt += `### UX 원칙\n`;
(card.principles || []).forEach(p => {
prompt += `- **${p.name}**: ${p.desc || ''}\n`;
});
prompt += `\n`;
}
prompt += `---\n\n`;
prompt += `### 구현 요구사항\n\n`;
prompt += `1. **기술 스택**: HTML + Tailwind CSS (또는 프로젝트에 맞는 프레임워크)\n`;
prompt += `2. **반응형**: 모바일/태블릿/데스크톱 대응\n`;
prompt += `3. **접근성**: 시맨틱 태그, ARIA 라벨, 키보드 네비게이션\n`;
prompt += `4. **인터랙션**: hover, focus, active 상태 포함\n`;
prompt += `5. **위 구성 요소를 모두 포함**하되, 실제 서비스처럼 자연스러운 더미 데이터 사용\n`;
prompt += `6. **위 가이드라인을 충실히 반영**하여 UX 완성도를 높일 것\n`;
navigator.clipboard.writeText(prompt).then(() => {
this.toast('AI 프롬프트가 클립보드에 복사되었습니다');
}).catch(() => {
// fallback
const ta = document.createElement('textarea');
ta.value = prompt;
document.body.appendChild(ta);
ta.select();
document.execCommand('copy');
document.body.removeChild(ta);
this.toast('AI 프롬프트가 클립보드에 복사되었습니다');
});
},
toast(msg) { toast(msg) {
this.toastMsg = msg; this.toastMsg = msg;
setTimeout(() => { this.toastMsg = ''; }, 2500); setTimeout(() => { this.toastMsg = ''; }, 2500);