📦 Initialize Geulbeot structure and merge Prompts & test projects
This commit is contained in:
189
03. Code/geulbeot_10th/static/js/template.js
Normal file
189
03. Code/geulbeot_10th/static/js/template.js
Normal file
@@ -0,0 +1,189 @@
|
||||
// ===== 템플릿 모달 =====
|
||||
function openTemplateModal() {
|
||||
document.getElementById('templateModal').classList.add('active');
|
||||
document.getElementById('templateNameInput').value = '';
|
||||
removeTemplateFile();
|
||||
}
|
||||
|
||||
function closeTemplateModal() {
|
||||
document.getElementById('templateModal').classList.remove('active');
|
||||
}
|
||||
|
||||
function handleTemplateFile(input) {
|
||||
if (input.files.length > 0) {
|
||||
const file = input.files[0];
|
||||
const validExtensions = ['.hwpx', '.hwp', '.pdf'];
|
||||
const ext = '.' + file.name.split('.').pop().toLowerCase();
|
||||
|
||||
if (!validExtensions.includes(ext)) {
|
||||
alert('지원하지 않는 파일 형식입니다.\n(HWPX, HWP, PDF만 지원)');
|
||||
return;
|
||||
}
|
||||
|
||||
selectedTemplateFile = file;
|
||||
document.getElementById('templateFileName').textContent = file.name;
|
||||
document.getElementById('templateFileInfo').classList.add('show');
|
||||
document.getElementById('templateDropzone').style.display = 'none';
|
||||
|
||||
const nameInput = document.getElementById('templateNameInput');
|
||||
if (!nameInput.value.trim()) {
|
||||
nameInput.value = file.name.replace(/\.[^/.]+$/, '');
|
||||
}
|
||||
|
||||
updateTemplateSubmitBtn();
|
||||
}
|
||||
}
|
||||
|
||||
function removeTemplateFile() {
|
||||
selectedTemplateFile = null;
|
||||
document.getElementById('templateFileInput').value = '';
|
||||
document.getElementById('templateFileInfo').classList.remove('show');
|
||||
document.getElementById('templateDropzone').style.display = 'block';
|
||||
updateTemplateSubmitBtn();
|
||||
}
|
||||
|
||||
function updateTemplateSubmitBtn() {
|
||||
const nameInput = document.getElementById('templateNameInput');
|
||||
const btn = document.getElementById('templateSubmitBtn');
|
||||
btn.disabled = !selectedTemplateFile || !nameInput.value.trim();
|
||||
}
|
||||
|
||||
async function submitTemplate() {
|
||||
const name = document.getElementById('templateNameInput').value.trim();
|
||||
if (!name || !selectedTemplateFile) return;
|
||||
|
||||
const btn = document.getElementById('templateSubmitBtn');
|
||||
const spinner = document.getElementById('templateSpinner');
|
||||
const text = document.getElementById('templateSubmitText');
|
||||
|
||||
btn.disabled = true;
|
||||
spinner.style.display = 'inline-block';
|
||||
text.textContent = '분석 중...';
|
||||
|
||||
try {
|
||||
const formData = new FormData();
|
||||
formData.append('name', name);
|
||||
formData.append('file', selectedTemplateFile);
|
||||
|
||||
const response = await fetch('/analyze-template', {
|
||||
method: 'POST',
|
||||
body: formData
|
||||
});
|
||||
|
||||
const data = await response.json();
|
||||
|
||||
if (data.error) {
|
||||
throw new Error(data.error);
|
||||
}
|
||||
|
||||
userTemplates.push(data.meta);
|
||||
renderUserTemplates();
|
||||
closeTemplateModal();
|
||||
|
||||
setStatus(`템플릿 "${name}" 추가 완료`, true);
|
||||
|
||||
} catch (error) {
|
||||
alert('템플릿 분석 오류: ' + error.message);
|
||||
} finally {
|
||||
btn.disabled = false;
|
||||
spinner.style.display = 'none';
|
||||
text.textContent = '✨ 분석 및 추가';
|
||||
}
|
||||
}
|
||||
|
||||
function selectTemplate(templateId) {
|
||||
currentTemplate = templateId;
|
||||
|
||||
document.querySelectorAll('.template-item').forEach(item => {
|
||||
item.classList.remove('selected');
|
||||
const radio = item.querySelector('input[type="radio"]');
|
||||
if (radio) radio.checked = false;
|
||||
});
|
||||
|
||||
const selectedItem = document.querySelector(`.template-item[data-template="${templateId}"]`);
|
||||
if (selectedItem) {
|
||||
selectedItem.classList.add('selected');
|
||||
const radio = selectedItem.querySelector('input[type="radio"]');
|
||||
if (radio) radio.checked = true;
|
||||
}
|
||||
|
||||
const elementsPanel = document.getElementById('templateElementOptions');
|
||||
if (templateId === 'default') {
|
||||
elementsPanel.style.display = 'none';
|
||||
} else {
|
||||
showTemplateElements(templateId);
|
||||
elementsPanel.style.display = 'block';
|
||||
}
|
||||
}
|
||||
|
||||
function showTemplateElements(templateId) {
|
||||
const template = userTemplates.find(t => t.id === templateId);
|
||||
if (!template || !template.elements) return;
|
||||
|
||||
const container = document.querySelector('#templateElementOptions .elements-list');
|
||||
container.innerHTML = template.elements.map(el => `
|
||||
<label class="element-checkbox">
|
||||
<input type="checkbox"
|
||||
data-element="${el.type}"
|
||||
${el.default ? 'checked' : ''}
|
||||
onchange="toggleTemplateElement('${templateId}', '${el.type}', this.checked)">
|
||||
<span class="element-icon">${el.icon}</span>
|
||||
<span>${el.name}</span>
|
||||
</label>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
function toggleTemplateElement(templateId, elementType, checked) {
|
||||
if (!templateElements[templateId]) {
|
||||
templateElements[templateId] = {};
|
||||
}
|
||||
templateElements[templateId][elementType] = checked;
|
||||
}
|
||||
|
||||
function renderUserTemplates() {
|
||||
const container = document.getElementById('userTemplatesListNew');
|
||||
|
||||
if (userTemplates.length === 0) {
|
||||
container.innerHTML = '';
|
||||
return;
|
||||
}
|
||||
|
||||
container.innerHTML = userTemplates.map(tpl => `
|
||||
<div class="template-item" data-template="${tpl.id}" onclick="selectTemplate('${tpl.id}')">
|
||||
<input type="radio" name="template">
|
||||
<span class="label">📑 ${tpl.name}</span>
|
||||
<button class="delete-btn" onclick="event.stopPropagation(); deleteTemplate('${tpl.id}')" title="삭제">✕</button>
|
||||
</div>
|
||||
`).join('');
|
||||
}
|
||||
|
||||
async function loadUserTemplates() {
|
||||
try {
|
||||
const response = await fetch('/api/templates');
|
||||
const data = await response.json();
|
||||
if (Array.isArray(data)) {
|
||||
userTemplates = data;
|
||||
renderUserTemplates();
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('템플릿 목록 로드 실패:', error);
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteTemplate(templateId) {
|
||||
if (!confirm('이 템플릿을 삭제하시겠습니까?')) return;
|
||||
|
||||
try {
|
||||
await fetch(`/api/templates/${templateId}`, { method: 'DELETE' });
|
||||
userTemplates = userTemplates.filter(t => t.id !== templateId);
|
||||
renderUserTemplates();
|
||||
|
||||
if (currentTemplate === templateId) {
|
||||
selectTemplate('default');
|
||||
}
|
||||
|
||||
setStatus('템플릿 삭제 완료', true);
|
||||
} catch (error) {
|
||||
alert('삭제 오류: ' + error.message);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user