Files
dbmaker/estrutura_visual/databook-template/app.js

512 lines
24 KiB
JavaScript

// Application State
const state = {
currentTemplate: 'cover',
settings: {
primaryColor: '#1a365d',
secondaryColor: '#2b6cb0',
projectTitle: 'BUZIOS 7 PRODUCTION SYSTEM DEVELOPMENT',
projectSubtitle: 'AR HEAD FABRICATION LONG',
clientName: 'SAIPEM',
documentNumber: 'DB-B97-01_S1_VENDOR_DATABOOK',
contractNumber: 'OC 1472739',
supplierName: 'ENGEMETAL',
language: 'both',
date: '2024'
},
indexData: [
{ number: '1', title_pt: 'Identificação', title_en: 'Identification', level: 1, page: '1' },
{ number: '2', title_pt: 'Materiais', title_en: 'Materials', level: 1, page: '5' },
{ number: '2.1', title_pt: 'Certificados das matérias-primas', title_en: 'Raw materials certificates', level: 2, page: '6' },
{ number: '2.2', title_pt: 'Consumíveis de soldagem', title_en: 'Welding consumables', level: 2, page: '15' },
{ number: '3', title_pt: 'Procedimentos de Soldagem', title_en: 'Welding Procedures', level: 1, page: '20' },
{ number: '3.1', title_pt: 'Especificação do Procedimento de Soldagem (EPS)', title_en: 'Welding Procedure Specification (WPS)', level: 2, page: '21' },
{ number: '3.2', title_pt: 'Registros de Qualificação (RQPS)', title_en: 'Procedure Qualification Records (WPQR)', level: 2, page: '35' },
{ number: '3.3', title_pt: 'Registros de Soldadores (RQS)', title_en: 'Welder Qualification Records (WQR)', level: 2, page: '50' },
{ number: '4', title_pt: 'Inspeção e Testes', title_en: 'Inspection and Testing', level: 1, page: '65' },
{ number: '4.1', title_pt: 'Plano de Inspeção e Testes (PIT)', title_en: 'Inspection and Testing Plan (ITP)', level: 2, page: '66' },
{ number: '4.2', title_pt: 'Ensaios Não Destrutivos (NDT)', title_en: 'Non-Destructive Testing (NDT)', level: 2, page: '75' },
{ number: '4.3', title_pt: 'Relatórios de Inspeção Dimensional', title_en: 'Dimensional Inspection Reports', level: 2, page: '90' },
{ number: '4.4', title_pt: 'Relatórios de Inspeção de Pintura', title_en: 'Painting Inspection Reports', level: 2, page: '105' },
{ number: '8', title_pt: 'Certificados de Conformidade do Produto', title_en: 'Product Conformity Certificates', level: 1, page: '120' },
{ number: '8.1', title_pt: 'Inspection Release Notice (IRN)', title_en: 'Inspection Release Notice (IRN)', level: 2, page: '121' }
],
sectionIcons: {
'1': '📋',
'2': '🔩',
'3': '⚡',
'4': '🔍',
'8': '✅'
}
};
// Template Generators
const templates = {
cover: () => `
<div class="template-page cover-template">
<div class="cover-logo-top">Logo Cliente</div>
<div class="cover-content">
<h1 class="cover-title">${state.settings.projectTitle}</h1>
<h2 class="cover-subtitle">${state.settings.projectSubtitle}</h2>
<div class="cover-divider"></div>
<div class="cover-document-info">
<div class="cover-document-number">${state.settings.documentNumber}</div>
<div class="cover-contract">Contrato: ${state.settings.contractNumber}</div>
<div class="cover-date">Cliente: ${state.settings.clientName}</div>
<div class="cover-date">${state.settings.date}</div>
</div>
</div>
<div class="cover-logo-bottom">Logo ${state.settings.supplierName}</div>
</div>
`,
index: () => {
const renderIndexItems = () => {
return state.indexData.map(item => {
const titleText = state.settings.language === 'en' ? item.title_en :
state.settings.language === 'pt' ? item.title_pt :
`${item.title_pt} / ${item.title_en}`;
return `
<li class="index-item level-${item.level}">
<span class="index-number">${item.number}</span>
<span class="index-title-text">${titleText}</span>
<span class="index-page">${item.page}</span>
</li>
`;
}).join('');
};
return `
<div class="template-page index-template">
<h1 class="index-title">ÍNDICE / TABLE OF CONTENTS</h1>
<div class="index-divider"></div>
<ul class="index-list">
${renderIndexItems()}
</ul>
</div>
`;
},
'divider-minimal': () => {
const sectionNumber = '2';
const titlePt = 'Materiais';
const titleEn = 'Materials';
const icon = state.sectionIcons[sectionNumber] || '📑';
const title = state.settings.language === 'en' ? titleEn :
state.settings.language === 'pt' ? titlePt :
titlePt;
const subtitle = state.settings.language === 'both' ? titleEn : '';
return `
<div class="template-page divider-minimal">
<div class="divider-watermark">${sectionNumber}</div>
<div class="divider-content">
<div class="divider-number">${icon} Seção ${sectionNumber}</div>
<h1 class="divider-title">${title}</h1>
${subtitle ? `<p class="divider-subtitle">${subtitle}</p>` : ''}
<div class="divider-line"></div>
</div>
</div>
`;
},
'divider-lateral': () => {
const sectionNumber = '3';
const titlePt = 'Procedimentos de Soldagem';
const titleEn = 'Welding Procedures';
const title = state.settings.language === 'en' ? titleEn :
state.settings.language === 'pt' ? titlePt :
titlePt;
const subtitle = state.settings.language === 'both' ? titleEn : '';
return `
<div class="template-page divider-lateral">
<div class="divider-sidebar">${sectionNumber}</div>
<div class="divider-main-content">
<h1 class="divider-main-title">${title}</h1>
${subtitle ? `<p class="divider-main-subtitle">${subtitle}</p>` : ''}
<div class="divider-footer">
<div><strong>Projeto:</strong> ${state.settings.projectTitle}</div>
<div><strong>Documento:</strong> ${state.settings.documentNumber}</div>
<div><strong>Cliente:</strong> ${state.settings.clientName}</div>
</div>
</div>
</div>
`;
},
'divider-corporate': () => {
const sectionNumber = '4';
const titlePt = 'Inspeção e Testes';
const titleEn = 'Inspection and Testing';
const icon = state.sectionIcons[sectionNumber] || '📑';
const title = state.settings.language === 'en' ? titleEn :
state.settings.language === 'pt' ? titlePt :
titlePt;
return `
<div class="template-page divider-corporate">
<div class="divider-corporate-header">
<div class="divider-corporate-logo">Logo Cliente</div>
</div>
<div class="divider-corporate-content">
<div class="divider-corporate-number">${icon} ${sectionNumber}</div>
<h1 class="divider-corporate-title">${title}</h1>
<div class="divider-info-box">
<div class="divider-info-item">
<span class="divider-info-label">Projeto:</span>
<span class="divider-info-value">${state.settings.projectTitle.substring(0, 30)}...</span>
</div>
<div class="divider-info-item">
<span class="divider-info-label">Cliente:</span>
<span class="divider-info-value">${state.settings.clientName}</span>
</div>
<div class="divider-info-item">
<span class="divider-info-label">Contrato:</span>
<span class="divider-info-value">${state.settings.contractNumber}</span>
</div>
<div class="divider-info-item">
<span class="divider-info-label">Documento:</span>
<span class="divider-info-value">${state.settings.documentNumber}</span>
</div>
</div>
</div>
</div>
`;
},
'headers-footers': () => `
<div class="template-page header-footer-showcase">
<h1 style="font-family: Roboto, sans-serif; font-size: 36px; color: var(--primary-color); margin-bottom: 2rem;">Cabeçalhos e Rodapés</h1>
<div class="hf-example">
<div class="hf-label">Cabeçalho - Opção 1</div>
<div class="page-header">
<div class="page-header-logo">Logo</div>
<div class="page-header-project">${state.settings.projectTitle.substring(0, 40)}...</div>
<div class="page-header-doc">${state.settings.documentNumber}</div>
</div>
</div>
<div class="hf-example">
<div class="hf-label">Cabeçalho - Opção 2</div>
<div class="page-header" style="border-bottom: 1px solid var(--gray-light);">
<div class="page-header-project" style="flex: 1;">${state.settings.clientName} - ${state.settings.projectTitle.substring(0, 35)}...</div>
<div class="page-header-doc" style="background-color: var(--gray-light); padding: 0.5rem 1rem; border-radius: 4px;">${state.settings.documentNumber}</div>
</div>
</div>
<div class="hf-example">
<div class="hf-label">Rodapé - Opção 1</div>
<div class="page-footer">
<div class="page-footer-left">Rev. 01 | ${state.settings.date}</div>
<div class="page-footer-center">45</div>
<div class="page-footer-right">${state.settings.supplierName}</div>
</div>
</div>
<div class="hf-example">
<div class="hf-label">Rodapé - Opção 2</div>
<div class="page-footer" style="background-color: rgba(26, 54, 93, 0.05);">
<div class="page-footer-left">${state.settings.documentNumber}</div>
<div class="page-footer-center" style="background-color: var(--primary-color); color: white; padding: 0.25rem 1rem; border-radius: 4px;">12</div>
<div class="page-footer-right">Data: ${state.settings.date}</div>
</div>
</div>
<div class="hf-example">
<div class="hf-label">Rodapé - Opção 3</div>
<div class="page-footer" style="border-top: 3px solid var(--primary-color);">
<div class="page-footer-left" style="display: flex; flex-direction: column;">
<span style="font-weight: 600;">${state.settings.clientName}</span>
<span>${state.settings.contractNumber}</span>
</div>
<div class="page-footer-center">8</div>
<div class="page-footer-right" style="text-align: right;">
<div style="font-weight: 600;">${state.settings.supplierName}</div>
<div>${state.settings.date}</div>
</div>
</div>
</div>
</div>
`,
'style-guide': () => `
<div class="template-page style-guide">
<h1 style="font-family: Roboto, sans-serif; font-size: 36px; color: var(--primary-color); margin-bottom: 2rem; text-align: center;">Guia de Estilo - Databook</h1>
<div class="sg-section">
<h2 class="sg-section-title">Paleta de Cores</h2>
<div class="color-palette">
<div class="color-swatch">
<div class="color-sample" style="background-color: ${state.settings.primaryColor};"></div>
<div class="color-name">Primária</div>
<div class="color-hex">${state.settings.primaryColor}</div>
</div>
<div class="color-swatch">
<div class="color-sample" style="background-color: ${state.settings.secondaryColor};"></div>
<div class="color-name">Secundária</div>
<div class="color-hex">${state.settings.secondaryColor}</div>
</div>
<div class="color-swatch">
<div class="color-sample" style="background-color: #4299e1;"></div>
<div class="color-name">Accent</div>
<div class="color-hex">#4299e1</div>
</div>
<div class="color-swatch">
<div class="color-sample" style="background-color: #2d3748;"></div>
<div class="color-name">Cinza Escuro</div>
<div class="color-hex">#2d3748</div>
</div>
<div class="color-swatch">
<div class="color-sample" style="background-color: #718096;"></div>
<div class="color-name">Cinza Médio</div>
<div class="color-hex">#718096</div>
</div>
<div class="color-swatch">
<div class="color-sample" style="background-color: #e2e8f0;"></div>
<div class="color-name">Cinza Claro</div>
<div class="color-hex">#e2e8f0</div>
</div>
</div>
</div>
<div class="sg-section">
<h2 class="sg-section-title">Tipografia</h2>
<div class="typography-examples">
<div class="typo-example">
<div class="typo-label">Título Principal (H1) - 60px Bold</div>
<h1 style="font-family: Roboto, sans-serif; font-size: 60px; font-weight: 700; color: var(--primary-color);">Título Principal</h1>
</div>
<div class="typo-example">
<div class="typo-label">Subtítulo (H2) - 36px Regular</div>
<h2 style="font-family: Roboto, sans-serif; font-size: 36px; font-weight: 400; color: var(--gray-dark);">Subtítulo do Documento</h2>
</div>
<div class="typo-example">
<div class="typo-label">Seção (H3) - 24px Bold</div>
<h3 style="font-family: Roboto, sans-serif; font-size: 24px; font-weight: 700; color: var(--primary-color);">Título de Seção</h3>
</div>
<div class="typo-example">
<div class="typo-label">Corpo de Texto - 14px Regular</div>
<p style="font-family: Open Sans, sans-serif; font-size: 14px; font-weight: 400; color: var(--gray-dark);">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
</div>
<div class="typo-example">
<div class="typo-label">Texto Secundário - 12px Regular</div>
<p style="font-family: Open Sans, sans-serif; font-size: 12px; font-weight: 400; color: var(--gray-medium);">Texto secundário ou informações auxiliares</p>
</div>
</div>
</div>
<div class="sg-section">
<h2 class="sg-section-title">Espaçamentos</h2>
<div class="spacing-grid">
<div class="spacing-item">
<div class="spacing-visual" style="width: 8px; height: 8px;"></div>
<div class="spacing-label">8px - XS</div>
</div>
<div class="spacing-item">
<div class="spacing-visual" style="width: 16px; height: 16px;"></div>
<div class="spacing-label">16px - SM</div>
</div>
<div class="spacing-item">
<div class="spacing-visual" style="width: 24px; height: 24px;"></div>
<div class="spacing-label">24px - MD</div>
</div>
<div class="spacing-item">
<div class="spacing-visual" style="width: 32px; height: 32px;"></div>
<div class="spacing-label">32px - LG</div>
</div>
<div class="spacing-item">
<div class="spacing-visual" style="width: 48px; height: 48px;"></div>
<div class="spacing-label">48px - XL</div>
</div>
</div>
</div>
<div class="sg-section">
<h2 class="sg-section-title">Elementos</h2>
<div style="display: flex; gap: 1rem; flex-wrap: wrap;">
<button class="btn btn-primary">Botão Primário</button>
<button class="btn btn-secondary">Botão Secundário</button>
</div>
<div style="margin-top: 1rem; padding: 1rem; background-color: rgba(26, 54, 93, 0.05); border-left: 4px solid var(--primary-color); border-radius: 8px;">
<strong>Caixa de Informação</strong><br>
Utilizada para destacar informações importantes no documento.
</div>
</div>
</div>
`
};
// DOM Elements
const navItems = document.querySelectorAll('.nav-item');
const previewContainer = document.getElementById('previewContainer');
const exportBtn = document.getElementById('exportBtn');
const exportModal = document.getElementById('exportModal');
const closeModal = document.getElementById('closeModal');
const closeModalBtn = document.getElementById('closeModalBtn');
const copyHtmlBtn = document.getElementById('copyHtmlBtn');
const applyBtn = document.getElementById('applyBtn');
const resetBtn = document.getElementById('resetBtn');
// Form inputs
const primaryColorInput = document.getElementById('primaryColor');
const secondaryColorInput = document.getElementById('secondaryColor');
const projectTitleInput = document.getElementById('projectTitle');
const projectSubtitleInput = document.getElementById('projectSubtitle');
const clientNameInput = document.getElementById('clientName');
const documentNumberInput = document.getElementById('documentNumber');
const contractNumberInput = document.getElementById('contractNumber');
const supplierNameInput = document.getElementById('supplierName');
const languageSelect = document.getElementById('language');
// Functions
function renderTemplate(templateName) {
if (templates[templateName]) {
previewContainer.innerHTML = templates[templateName]();
updateCSSVariables();
}
}
function updateCSSVariables() {
document.documentElement.style.setProperty('--primary-color', state.settings.primaryColor);
document.documentElement.style.setProperty('--secondary-color', state.settings.secondaryColor);
}
function updateColorPreviews() {
document.getElementById('primaryColorBox').style.backgroundColor = state.settings.primaryColor;
document.getElementById('primaryColorCode').textContent = state.settings.primaryColor;
document.getElementById('secondaryColorBox').style.backgroundColor = state.settings.secondaryColor;
document.getElementById('secondaryColorCode').textContent = state.settings.secondaryColor;
}
function applySettings() {
state.settings.primaryColor = primaryColorInput.value;
state.settings.secondaryColor = secondaryColorInput.value;
state.settings.projectTitle = projectTitleInput.value;
state.settings.projectSubtitle = projectSubtitleInput.value;
state.settings.clientName = clientNameInput.value;
state.settings.documentNumber = documentNumberInput.value;
state.settings.contractNumber = contractNumberInput.value;
state.settings.supplierName = supplierNameInput.value;
state.settings.language = languageSelect.value;
updateColorPreviews();
renderTemplate(state.currentTemplate);
}
function resetSettings() {
state.settings = {
primaryColor: '#1a365d',
secondaryColor: '#2b6cb0',
projectTitle: 'BUZIOS 7 PRODUCTION SYSTEM DEVELOPMENT',
projectSubtitle: 'AR HEAD FABRICATION LONG',
clientName: 'SAIPEM',
documentNumber: 'DB-B97-01_S1_VENDOR_DATABOOK',
contractNumber: 'OC 1472739',
supplierName: 'ENGEMETAL',
language: 'both',
date: '2024'
};
primaryColorInput.value = state.settings.primaryColor;
secondaryColorInput.value = state.settings.secondaryColor;
projectTitleInput.value = state.settings.projectTitle;
projectSubtitleInput.value = state.settings.projectSubtitle;
clientNameInput.value = state.settings.clientName;
documentNumberInput.value = state.settings.documentNumber;
contractNumberInput.value = state.settings.contractNumber;
supplierNameInput.value = state.settings.supplierName;
languageSelect.value = state.settings.language;
updateColorPreviews();
renderTemplate(state.currentTemplate);
}
function copyHTMLToClipboard() {
const templateContent = previewContainer.innerHTML;
const fullHTML = `<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Template Databook</title>
<style>
/* Adicione o CSS necessário aqui */
</style>
</head>
<body>
${templateContent}
</body>
</html>`;
navigator.clipboard.writeText(fullHTML).then(() => {
const originalText = copyHtmlBtn.textContent;
copyHtmlBtn.textContent = '✓ Copiado!';
copyHtmlBtn.style.backgroundColor = '#48bb78';
setTimeout(() => {
copyHtmlBtn.textContent = originalText;
copyHtmlBtn.style.backgroundColor = '';
}, 2000);
}).catch(err => {
alert('Erro ao copiar: ' + err);
});
}
// Event Listeners
navItems.forEach(item => {
item.addEventListener('click', (e) => {
const templateName = item.getAttribute('data-template');
if (templateName) {
// Update active state
navItems.forEach(nav => nav.classList.remove('active'));
item.classList.add('active');
// Render template
state.currentTemplate = templateName;
renderTemplate(templateName);
}
});
});
exportBtn.addEventListener('click', () => {
exportModal.classList.add('active');
});
closeModal.addEventListener('click', () => {
exportModal.classList.remove('active');
});
closeModalBtn.addEventListener('click', () => {
exportModal.classList.remove('active');
});
exportModal.addEventListener('click', (e) => {
if (e.target === exportModal) {
exportModal.classList.remove('active');
}
});
applyBtn.addEventListener('click', applySettings);
resetBtn.addEventListener('click', resetSettings);
copyHtmlBtn.addEventListener('click', copyHTMLToClipboard);
// Real-time color preview updates
primaryColorInput.addEventListener('input', (e) => {
document.getElementById('primaryColorBox').style.backgroundColor = e.target.value;
document.getElementById('primaryColorCode').textContent = e.target.value;
});
secondaryColorInput.addEventListener('input', (e) => {
document.getElementById('secondaryColorBox').style.backgroundColor = e.target.value;
document.getElementById('secondaryColorCode').textContent = e.target.value;
});
// Initialize
renderTemplate('cover');
updateColorPreviews();