# Exemplos de Código - Template Databook SteelBook ## 1. Estrutura HTML - Capa Frontal ```html Databook - Capa Frontal

{{project_title}}

{{project_subtitle}}

Documento: {{document_number}} Contrato: {{contract_number}} Data: {{issue_date}}
``` --- ## 2. Estrutura HTML - Índice Geral ```html

ÍNDICE / TABLE OF CONTENTS

1 Identificação 3
Identification
2 Materiais 5
Materials
2.1 Certificados das matérias-primas 6
Raw materials certificates
2.2 Consumíveis de soldagem 12
Welding consumables
``` --- ## 3. Estrutura HTML - Divisora Estilo Minimalista ```html
2

Materiais

Materials

Certificados, especificações e documentação de matérias-primas

``` --- ## 4. Estrutura HTML - Divisora Estilo Lateral ```html
3

Procedimentos de Soldagem

Welding Procedures

Projeto: BUZIOS 7

Cliente: SAIPEM

Contrato: OC 1472739

``` --- ## 5. Estrutura HTML - Cabeçalho e Rodapé ```html ``` --- ## 6. JavaScript - Sistema de Variáveis Dinâmicas ```javascript // Classe para gerenciar templates class DatabookTemplate { constructor(config) { this.config = config; this.variables = {}; } // Define variáveis do projeto setVariables(vars) { this.variables = { ...this.variables, ...vars }; } // Renderiza template substituindo variáveis render(templateHtml) { let rendered = templateHtml; // Substitui variáveis no formato {{variable_name}} for (const [key, value] of Object.entries(this.variables)) { const regex = new RegExp(`{{${key}}}`, 'g'); rendered = rendered.replace(regex, value); } return rendered; } // Gera capa frontal generateCover() { const coverTemplate = `

{{project_title}}

{{project_subtitle}}

Documento: {{document_number}}

Contrato: {{contract_number}}

Data: {{issue_date}}

`; return this.render(coverTemplate); } // Gera índice generateIndex(sections) { let indexHtml = '

ÍNDICE / TABLE OF CONTENTS

'; sections.forEach(section => { const indent = section.level > 1 ? `level-${section.level}` : ''; indexHtml += `
${section.number} ${section.title_pt} ${section.page}
${section.title_en}
`; }); indexHtml += '
'; return indexHtml; } // Gera divisora de seção generateDivider(sectionNumber, titlePt, titleEn, style = 'minimal') { const templates = { minimal: `
${sectionNumber}

${titlePt}

${titleEn}

`, lateral: `
${sectionNumber}

${titlePt}

${titleEn}

`, corporate: `
${sectionNumber}

${titlePt}

${titleEn}

` }; return this.render(templates[style] || templates.minimal); } } // Exemplo de uso const template = new DatabookTemplate({ name: 'SAIPEM Vendor Databook', version: '1.0' }); template.setVariables({ project_title: 'BUZIOS 7 PRODUCTION SYSTEM DEVELOPMENT', project_subtitle: 'AR HEAD FABRICATION LONG', client_logo: '/logos/saipem.png', supplier_logo: '/logos/engemetal.png', document_number: 'DB-B97-01_S1_VENDOR_DATABOOK', contract_number: 'OC 1472739', issue_date: '2024-11-17' }); // Gerar componentes const cover = template.generateCover(); const index = template.generateIndex([ { number: '1', title_pt: 'Identificação', title_en: 'Identification', level: 1, page: 3 }, { number: '2', title_pt: 'Materiais', title_en: 'Materials', level: 1, page: 5 } ]); const divider = template.generateDivider('2', 'Materiais', 'Materials', 'minimal'); ``` --- ## 7. CSS - Variáveis Customizáveis ```css :root { /* Cores Primárias */ --color-primary: #1a365d; --color-secondary: #2b6cb0; --color-accent: #4299e1; /* Cores Neutras */ --color-gray-dark: #2d3748; --color-gray-medium: #718096; --color-gray-light: #e2e8f0; /* Tipografia */ --font-heading: 'Roboto', Arial, sans-serif; --font-body: 'Open Sans', Arial, sans-serif; --font-mono: 'Roboto Mono', monospace; /* Tamanhos de Fonte */ --font-size-h1: 60px; --font-size-h2: 48px; --font-size-h3: 36px; --font-size-h4: 24px; --font-size-body: 16px; --font-size-small: 12px; /* Espaçamentos */ --spacing-xs: 8px; --spacing-sm: 16px; --spacing-md: 24px; --spacing-lg: 40px; --spacing-xl: 60px; /* Bordas */ --border-radius: 8px; --border-width: 2px; } /* Aplicação das variáveis */ .cover-title { color: var(--color-primary); font-family: var(--font-heading); font-size: var(--font-size-h1); } .index-item { color: var(--color-gray-dark); font-family: var(--font-body); padding: var(--spacing-sm) 0; } .divider-content { padding: var(--spacing-xl); } /* Tema alternativo - Azul Claro */ .theme-light { --color-primary: #2563eb; --color-secondary: #60a5fa; --color-accent: #93c5fd; } /* Tema alternativo - Cinza Profissional */ .theme-professional { --color-primary: #334155; --color-secondary: #64748b; --color-accent: #94a3b8; } ``` --- ## 8. Integração com Banco de Dados (Supabase) ```sql -- Tabela de Templates CREATE TABLE templates ( id UUID DEFAULT uuid_generate_v4() PRIMARY KEY, nome VARCHAR(255) NOT NULL, descricao TEXT, versao VARCHAR(20) DEFAULT '1.0', config JSONB NOT NULL, criado_por UUID REFERENCES auth.users(id), criado_em TIMESTAMP DEFAULT NOW(), atualizado_em TIMESTAMP DEFAULT NOW(), ativo BOOLEAN DEFAULT true, publico BOOLEAN DEFAULT false, organizacao_id UUID REFERENCES organizacoes(id) ); -- Exemplo de config JSONB { "capa": { "titulo": "{{project_title}}", "subtitulo": "{{project_subtitle}}", "cores": { "primaria": "#1a365d", "secundaria": "#2b6cb0" } }, "indice": { "bilingue": true, "estrutura": [ { "numero": "1", "titulo_pt": "Identificação", "titulo_en": "Identification", "nivel": 1 } ] }, "divisoras": { "estilo": "minimal" } } -- Tabela de Databooks usando Templates CREATE TABLE databooks ( id UUID DEFAULT uuid_generate_v4() PRIMARY KEY, nome VARCHAR(255) NOT NULL, template_id UUID REFERENCES templates(id), dados JSONB NOT NULL, criado_em TIMESTAMP DEFAULT NOW() ); -- Query para buscar templates SELECT t.*, u.nome as criador FROM templates t LEFT JOIN auth.users u ON t.criado_por = u.id WHERE t.ativo = true AND (t.publico = true OR t.organizacao_id = $1) ORDER BY t.criado_em DESC; -- Query para aplicar template a databook UPDATE databooks SET template_id = $1, dados = jsonb_set(dados, '{template_aplicado}', 'true'::jsonb) WHERE id = $2; ``` --- ## 9. API Endpoints (Node.js/Express) ```javascript const express = require('express'); const router = express.Router(); // GET /api/templates - Lista templates router.get('/templates', async (req, res) => { try { const { data, error } = await supabase .from('templates') .select('*') .eq('ativo', true) .order('criado_em', { ascending: false }); if (error) throw error; res.json({ success: true, data }); } catch (error) { res.status(500).json({ success: false, error: error.message }); } }); // POST /api/templates - Cria novo template router.post('/templates', async (req, res) => { try { const { nome, descricao, config } = req.body; const { data, error } = await supabase .from('templates') .insert([{ nome, descricao, config, criado_por: req.user.id }]) .select() .single(); if (error) throw error; res.json({ success: true, data }); } catch (error) { res.status(500).json({ success: false, error: error.message }); } }); // PUT /api/templates/:id - Atualiza template router.put('/templates/:id', async (req, res) => { try { const { id } = req.params; const { nome, descricao, config } = req.body; const { data, error } = await supabase .from('templates') .update({ nome, descricao, config, atualizado_em: new Date().toISOString() }) .eq('id', id) .select() .single(); if (error) throw error; res.json({ success: true, data }); } catch (error) { res.status(500).json({ success: false, error: error.message }); } }); // POST /api/databooks/:id/apply-template - Aplica template router.post('/databooks/:id/apply-template', async (req, res) => { try { const { id } = req.params; const { template_id } = req.body; // Buscar template const { data: template } = await supabase .from('templates') .select('*') .eq('id', template_id) .single(); // Buscar databook const { data: databook } = await supabase .from('databooks') .select('*') .eq('id', id) .single(); // Aplicar configurações do template const dadosAtualizados = { ...databook.dados, template_config: template.config }; // Atualizar databook const { data, error } = await supabase .from('databooks') .update({ template_id, dados: dadosAtualizados }) .eq('id', id) .select() .single(); if (error) throw error; res.json({ success: true, data }); } catch (error) { res.status(500).json({ success: false, error: error.message }); } }); module.exports = router; ``` --- ## 10. Geração de PDF com Puppeteer ```javascript const puppeteer = require('puppeteer'); const fs = require('fs'); class DatabookPDFGenerator { constructor(template, databook) { this.template = template; this.databook = databook; } async generatePDF(outputPath) { const browser = await puppeteer.launch({ headless: true, args: ['--no-sandbox'] }); const page = await browser.newPage(); // Configurar página await page.setViewport({ width: 794, // A4 width in pixels at 96 DPI height: 1123 // A4 height in pixels at 96 DPI }); // Gerar HTML completo const htmlContent = this.generateFullHTML(); // Carregar conteúdo await page.setContent(htmlContent, { waitUntil: 'networkidle0' }); // Gerar PDF await page.pdf({ path: outputPath, format: 'A4', printBackground: true, margin: { top: '20mm', right: '15mm', bottom: '20mm', left: '15mm' }, displayHeaderFooter: true, headerTemplate: this.generateHeader(), footerTemplate: this.generateFooter() }); await browser.close(); return outputPath; } generateFullHTML() { const sections = []; // Capa sections.push(this.generateCover()); // Índice sections.push(this.generateIndex()); // Seções com divisoras this.databook.sections.forEach(section => { sections.push(this.generateDivider(section)); sections.push(this.generateSectionContent(section)); }); return ` ${sections.join('\n
\n')} `; } generateHeader() { return `
${this.databook.project_name}
`; } generateFooter() { return `
/
`; } getStyles() { return fs.readFileSync('./styles/databook.css', 'utf8'); } } // Uso const generator = new DatabookPDFGenerator(template, databook); await generator.generatePDF('./output/databook.pdf'); ``` --- ## Conclusão Estes exemplos fornecem uma base sólida para implementar o sistema de templates no SteelBook. Adapte conforme necessário para sua arquitetura específica.