feat: [design-insight] AI 프롬프트 복사 버튼 추가
- 카드 상세 모달 편집 버튼 옆에 AI 프롬프트 버튼 추가 - 패턴 정보/구성요소/가이드라인을 AI 프롬프트로 변환 후 클립보드 복사 - 복사한 프롬프트를 AI에 붙여넣으면 해당 스타일로 코드 생성 가능
This commit is contained in:
@@ -1363,6 +1363,9 @@
|
||||
<h3 x-text="previewCard.title || '(제목 없음)'" style="font-size: 15px;"></h3>
|
||||
</div>
|
||||
<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)">
|
||||
<i class="ri-edit-line"></i> 편집
|
||||
</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');
|
||||
},
|
||||
|
||||
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) {
|
||||
this.toastMsg = msg;
|
||||
setTimeout(() => { this.toastMsg = ''; }, 2500);
|
||||
|
||||
Reference in New Issue
Block a user