🚀 Initial commit: Versão atual do TrackSteel APP

This commit is contained in:
2026-03-18 21:17:53 +00:00
commit bde410c9ad
633 changed files with 108150 additions and 0 deletions
@@ -0,0 +1,485 @@
import React from 'react';
import { FichaTecnicaData } from '@/hooks/useFichaTecnica';
import { useBrandSettings } from '@/hooks/useBrandSettings';
interface FichaTecnicaPDFTemplateProps {
data: FichaTecnicaData;
}
export const FichaTecnicaPDFTemplate: React.FC<FichaTecnicaPDFTemplateProps> = ({ data }) => {
const { brandSettings } = useBrandSettings();
const infoItems = [
{ key: 'info_calculo_estrutural', label: 'CÁLCULO ESTRUTURAL' },
{ key: 'info_projeto_basico', label: 'PROJETO BÁSICO' },
{ key: 'info_detalhamento', label: 'DETALHAMENTO' },
{ key: 'info_materia_prima', label: 'MATÉRIA-PRIMA' },
{ key: 'info_fabricacao', label: 'FABRICAÇÃO' },
{ key: 'info_grades_piso', label: 'GRADES DE PISO' },
{ key: 'info_jateamento', label: 'JATEAMENTO' },
{ key: 'info_pintura_base', label: 'PINTURA BASE/FUNDO' },
{ key: 'info_pintura_inter', label: 'PINTURA INTERMEDIÁRIA' },
{ key: 'info_pintura_acabamento', label: 'PINTURA DE ACABAMENTO' },
{ key: 'info_galvanizacao', label: 'GALVANIZAÇÃO' },
{ key: 'info_embalagem', label: 'EMBALAGEM ESPECIAL' },
{ key: 'info_transporte', label: 'TRANSPORTE' },
{ key: 'info_inspecao', label: 'INSPEÇÃO QUALIFICADA' },
{ key: 'info_ensaios_lab', label: 'ENSAIOS DE LABORATÓRIO' },
{ key: 'info_databook', label: 'DATABOOK' },
{ key: 'info_pre_montagem', label: 'PRÉ-MONTAGEM' },
{ key: 'info_placa_engenetal', label: 'PLACA "ENGEMETAL" NA OBRA' },
{ key: 'info_parafusos', label: 'PARAFUSOS/PORCAS/ARR' },
{ key: 'info_chumbadores', label: 'CHUMBADORES' },
{ key: 'info_stud_bolt', label: 'STUD BOLT' },
{ key: 'info_fornec_telhas', label: 'FORNECIMENTO DE TELHAS' },
{ key: 'info_montagem_telhas', label: 'MONTAGEM DE TELHAS' },
{ key: 'info_forn_calhas', label: 'FORN. CALHAS E RUFOS' },
{ key: 'info_mont_calhas', label: 'MONTAG. CALHAS E RUFOS' },
{ key: 'info_steel_deck', label: 'STEEL DECK E ACESSOR.' },
{ key: 'info_fornec_wall', label: 'FORNECIMENTO WALL' },
{ key: 'info_mont_wall', label: 'MONTAGEM WALL' },
{ key: 'info_outros_materiais', label: 'OUTROS MATERIAIS OU SERV. ADICIONAIS' }
];
const getInfoValue = (field: keyof FichaTecnicaData, type: 'e' | 'c' | 'na' | 'info') => {
const info = data[field] as any;
return info?.[type] || (type === 'info' ? '' : false);
};
const pdfStyles = {
container: {
fontFamily: 'Arial, sans-serif',
fontSize: '9px',
lineHeight: '1.2',
color: '#000',
width: '210mm',
minHeight: '297mm',
margin: '0 auto',
background: '#fff',
padding: '8mm',
boxSizing: 'border-box' as const
},
header: {
display: 'flex',
justifyContent: 'space-between',
alignItems: 'center',
border: '2px solid #000',
padding: '6px 10px',
marginBottom: '8px',
background: '#e8e8e8'
},
logo: {
fontSize: '14px',
fontWeight: 'bold',
color: '#333'
},
title: {
fontSize: '12px',
fontWeight: 'bold',
textAlign: 'center' as const,
flex: 1,
margin: '0 15px'
},
section: {
marginBottom: '6px',
border: '1px solid #000'
},
sectionHeader: {
background: '#d0d0d0',
padding: '3px 6px',
borderBottom: '1px solid #000',
fontWeight: 'bold',
fontSize: '8px',
textAlign: 'center' as const
},
sectionContent: {
padding: '4px 6px'
},
grid: {
display: 'grid',
gridTemplateColumns: 'repeat(5, 1fr)',
gap: '4px',
margin: '2px 0'
},
field: {
display: 'flex',
flexDirection: 'column' as const
},
fieldLabel: {
fontWeight: 'bold',
fontSize: '7px',
marginBottom: '1px',
color: '#444'
},
fieldValue: {
borderBottom: '1px solid #666',
minHeight: '12px',
padding: '1px 2px',
fontSize: '8px',
background: '#f8f8f8'
},
checkbox: {
display: 'inline-flex',
alignItems: 'center',
marginRight: '8px',
marginBottom: '2px'
},
checkboxBox: {
width: '8px',
height: '8px',
border: '1px solid #000',
marginRight: '3px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
fontSize: '6px',
background: '#fff'
},
contactSection: {
display: 'grid',
gridTemplateColumns: 'repeat(3, 1fr)',
gap: '6px',
margin: '4px 0'
},
contactGroup: {
border: '1px solid #666',
padding: '3px'
},
contactTitle: {
fontWeight: 'bold',
textAlign: 'center' as const,
marginBottom: '3px',
background: '#e0e0e0',
padding: '2px',
margin: '-3px -3px 3px -3px',
fontSize: '7px'
},
table: {
width: '100%',
borderCollapse: 'collapse' as const,
fontSize: '7px'
},
tableHeader: {
background: '#d0d0d0',
padding: '3px 2px',
textAlign: 'center' as const,
fontWeight: 'bold',
border: '1px solid #000',
fontSize: '7px'
},
tableCell: {
padding: '2px 3px',
verticalAlign: 'middle' as const,
border: '1px solid #666'
},
infoItem: {
fontWeight: 'bold',
background: '#f0f0f0',
fontSize: '7px'
},
infoCheckbox: {
textAlign: 'center' as const,
width: '15px'
},
infoText: {
minWidth: '120px',
fontSize: '7px'
},
compactGrid: {
display: 'grid',
gridTemplateColumns: 'repeat(4, 1fr)',
gap: '3px',
margin: '2px 0'
},
twoColumnGrid: {
display: 'grid',
gridTemplateColumns: '2fr 1fr 1fr',
gap: '4px',
margin: '2px 0'
},
fullWidth: {
gridColumn: 'span 4'
}
};
return (
<div id="pdf-template" style={pdfStyles.container}>
{/* Cabeçalho */}
<div style={pdfStyles.header}>
<div style={pdfStyles.logo}>
{brandSettings.logo_url ? (
<img src={brandSettings.logo_url} alt="Logo" style={{ height: '24px' }} />
) : (
brandSettings.company_name || 'EMPRESA'
)}
</div>
<div style={pdfStyles.title}>FICHA TÉCNICA DE CONTRATO</div>
<div style={{ width: '60px' }}></div>
</div>
{/* Informações da OF */}
<div style={pdfStyles.section}>
<div style={pdfStyles.sectionHeader}>INFORMAÇÕES GERAIS</div>
<div style={pdfStyles.sectionContent}>
<div style={pdfStyles.grid}>
<div style={pdfStyles.field}>
<div style={pdfStyles.fieldLabel}>OF Nº:</div>
<div style={pdfStyles.fieldValue}>{data.of_number || ''}</div>
</div>
<div style={pdfStyles.field}>
<div style={pdfStyles.fieldLabel}>GESTOR:</div>
<div style={pdfStyles.fieldValue}>{data.gestor || ''}</div>
</div>
<div style={pdfStyles.field}>
<div style={pdfStyles.fieldLabel}>REVISÃO:</div>
<div style={pdfStyles.fieldValue}>{data.revisao || ''}</div>
</div>
<div style={pdfStyles.field}>
<div style={pdfStyles.fieldLabel}>QTD (t):</div>
<div style={pdfStyles.fieldValue}>{data.quantidade || ''}</div>
</div>
<div style={pdfStyles.field}>
<div style={pdfStyles.fieldLabel}>DATA:</div>
<div style={pdfStyles.fieldValue}>{data.data_criacao || ''}</div>
</div>
</div>
</div>
</div>
{/* Dados do Cliente */}
<div style={pdfStyles.section}>
<div style={pdfStyles.sectionHeader}>DADOS DO CLIENTE</div>
<div style={pdfStyles.sectionContent}>
<div style={pdfStyles.twoColumnGrid}>
<div style={pdfStyles.field}>
<div style={pdfStyles.fieldLabel}>CLIENTE:</div>
<div style={pdfStyles.fieldValue}>{data.cliente || ''}</div>
</div>
<div style={pdfStyles.field}>
<div style={pdfStyles.fieldLabel}>CNPJ:</div>
<div style={pdfStyles.fieldValue}>{data.cnpj || ''}</div>
</div>
<div style={pdfStyles.field}>
<div style={pdfStyles.fieldLabel}>IE:</div>
<div style={pdfStyles.fieldValue}>{data.ie || ''}</div>
</div>
</div>
<div style={pdfStyles.twoColumnGrid}>
<div style={pdfStyles.field}>
<div style={pdfStyles.fieldLabel}>ENDEREÇO:</div>
<div style={pdfStyles.fieldValue}>{data.endereco || ''}</div>
</div>
<div style={pdfStyles.field}>
<div style={pdfStyles.fieldLabel}>CIDADE:</div>
<div style={pdfStyles.fieldValue}>{data.cidade || ''}</div>
</div>
<div style={pdfStyles.field}>
<div style={pdfStyles.fieldLabel}>ESTADO:</div>
<div style={pdfStyles.fieldValue}>{data.estado || ''}</div>
</div>
</div>
{/* Contatos compactos */}
<div style={pdfStyles.contactSection}>
<div style={pdfStyles.contactGroup}>
<div style={pdfStyles.contactTitle}>CONTRATO</div>
<div style={{ fontSize: '7px' }}>
<div>{data.contato_contrato || ''}</div>
<div>{data.fone_contrato || ''} | {data.cel_contrato || ''}</div>
<div>{data.email_contrato || ''}</div>
</div>
</div>
<div style={pdfStyles.contactGroup}>
<div style={pdfStyles.contactTitle}>OBRA</div>
<div style={{ fontSize: '7px' }}>
<div>{data.contato_obra || ''}</div>
<div>{data.fone_obra || ''} | {data.cel_obra || ''}</div>
<div>{data.email_obra || ''}</div>
</div>
</div>
<div style={pdfStyles.contactGroup}>
<div style={pdfStyles.contactTitle}>QUALIDADE</div>
<div style={{ fontSize: '7px' }}>
<div>{data.contato_qualid || ''}</div>
<div>{data.fone_qualid || ''} | {data.cel_qualid || ''}</div>
<div>{data.email_qualid || ''}</div>
</div>
</div>
</div>
</div>
</div>
{/* Dados do Projeto */}
<div style={pdfStyles.section}>
<div style={pdfStyles.sectionHeader}>DADOS DO PROJETO</div>
<div style={pdfStyles.sectionContent}>
<div style={{ ...pdfStyles.field, marginBottom: '4px' }}>
<div style={pdfStyles.fieldLabel}>DESCRIÇÃO:</div>
<div style={{ ...pdfStyles.fieldValue, minHeight: '20px' }}>{data.descricao_resumida || ''}</div>
</div>
<div style={pdfStyles.twoColumnGrid}>
<div style={pdfStyles.field}>
<div style={pdfStyles.fieldLabel}>ENDEREÇO:</div>
<div style={pdfStyles.fieldValue}>{data.endereco_projeto || ''}</div>
</div>
<div style={pdfStyles.field}>
<div style={pdfStyles.fieldLabel}>CIDADE:</div>
<div style={pdfStyles.fieldValue}>{data.cidade_projeto || ''}</div>
</div>
<div style={pdfStyles.field}>
<div style={pdfStyles.fieldLabel}>ESTADO:</div>
<div style={pdfStyles.fieldValue}>{data.estado_projeto || ''}</div>
</div>
</div>
</div>
</div>
{/* Tipo de Projeto */}
<div style={pdfStyles.section}>
<div style={pdfStyles.sectionHeader}>TIPO DE PROJETO</div>
<div style={pdfStyles.sectionContent}>
<div style={pdfStyles.compactGrid}>
{[
{ key: 'tipo_estrutural', label: 'ESTRUTURAL' },
{ key: 'tipo_residencial', label: 'RESIDENCIAL' },
{ key: 'tipo_espacial', label: 'ESPACIAL' },
{ key: 'tipo_comercial', label: 'COMERCIAL' },
{ key: 'tipo_grades', label: 'GRADES' },
{ key: 'tipo_industrial', label: 'INDUSTRIAL' },
{ key: 'tipo_cobertura', label: 'COBERTURA' },
{ key: 'tipo_com_montagem', label: 'COM MONTAGEM' }
].map(({ key, label }) => (
<div key={key} style={pdfStyles.checkbox}>
<div style={pdfStyles.checkboxBox}>
{data[key as keyof FichaTecnicaData] ? '✓' : ''}
</div>
<span style={{ fontSize: '7px' }}>{label}</span>
</div>
))}
</div>
</div>
</div>
{/* Documentos Fornecidos */}
<div style={pdfStyles.section}>
<div style={pdfStyles.sectionHeader}>DOCUMENTOS FORNECIDOS</div>
<div style={pdfStyles.sectionContent}>
<div style={pdfStyles.compactGrid}>
{[
{ key: 'doc_calculo', label: 'CÁLCULO' },
{ key: 'doc_projeto', label: 'PROJETO' },
{ key: 'doc_detalhamento', label: 'DETALHAMENTO' },
{ key: 'doc_cronograma', label: 'CRONOGRAMA' },
{ key: 'doc_normas', label: 'NORMAS' },
{ key: 'doc_especif_tecnicas', label: 'ESPECIF. TÉC.' },
{ key: 'doc_catalogo', label: 'CATÁLOGO' },
{ key: 'doc_fotos', label: 'FOTOS' }
].map(({ key, label }) => (
<div key={key} style={pdfStyles.checkbox}>
<div style={pdfStyles.checkboxBox}>
{data[key as keyof FichaTecnicaData] ? '✓' : ''}
</div>
<span style={{ fontSize: '7px' }}>{label}</span>
</div>
))}
</div>
</div>
</div>
{/* Informações do Projeto - Tabela compacta */}
<div style={pdfStyles.section}>
<div style={pdfStyles.sectionHeader}>INFORMAÇÕES DO PROJETO</div>
<div style={{ padding: '0' }}>
<table style={pdfStyles.table}>
<thead>
<tr>
<th style={{ ...pdfStyles.tableHeader, width: '45%' }}>ITEM</th>
<th style={{ ...pdfStyles.tableHeader, width: '8%' }}>E</th>
<th style={{ ...pdfStyles.tableHeader, width: '8%' }}>C</th>
<th style={{ ...pdfStyles.tableHeader, width: '8%' }}>NA</th>
<th style={{ ...pdfStyles.tableHeader, width: '31%' }}>INFO</th>
</tr>
</thead>
<tbody>
{infoItems.slice(0, 15).map(({ key, label }) => (
<tr key={key}>
<td style={{ ...pdfStyles.tableCell, ...pdfStyles.infoItem }}>{label}</td>
<td style={{ ...pdfStyles.tableCell, ...pdfStyles.infoCheckbox }}>
{getInfoValue(key as keyof FichaTecnicaData, 'e') ? '✓' : ''}
</td>
<td style={{ ...pdfStyles.tableCell, ...pdfStyles.infoCheckbox }}>
{getInfoValue(key as keyof FichaTecnicaData, 'c') ? '✓' : ''}
</td>
<td style={{ ...pdfStyles.tableCell, ...pdfStyles.infoCheckbox }}>
{getInfoValue(key as keyof FichaTecnicaData, 'na') ? '✓' : ''}
</td>
<td style={{ ...pdfStyles.tableCell, ...pdfStyles.infoText }}>
{getInfoValue(key as keyof FichaTecnicaData, 'info')}
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
{/* Validação */}
<div style={pdfStyles.section}>
<div style={pdfStyles.sectionHeader}>VALIDAÇÃO</div>
<div style={pdfStyles.sectionContent}>
<div style={{ display: 'flex', alignItems: 'center', gap: '8px', fontSize: '7px' }}>
<span>NECESSITA VALIDAÇÃO PÓS DETALHAMENTO?</span>
<div style={pdfStyles.checkbox}>
<div style={pdfStyles.checkboxBox}>
{data.necessita_validacao_pos_detalh ? '✓' : ''}
</div>
<span>SIM</span>
</div>
<div style={pdfStyles.checkbox}>
<div style={pdfStyles.checkboxBox}>
{!data.necessita_validacao_pos_detalh ? '✓' : ''}
</div>
<span>NÃO</span>
</div>
</div>
</div>
</div>
{/* Assinaturas compactas */}
<div style={pdfStyles.section}>
<div style={pdfStyles.sectionHeader}>VISTOS E APROVAÇÕES</div>
<div style={pdfStyles.sectionContent}>
<div style={pdfStyles.twoColumnGrid}>
<div style={pdfStyles.field}>
<div style={pdfStyles.fieldLabel}>GESTOR:</div>
<div style={{ ...pdfStyles.fieldValue, minHeight: '15px' }}>{data.visto_gestor || ''}</div>
</div>
<div style={pdfStyles.field}>
<div style={pdfStyles.fieldLabel}>PCP:</div>
<div style={{ ...pdfStyles.fieldValue, minHeight: '15px' }}>{data.visto_pcp || ''}</div>
</div>
<div style={pdfStyles.field}>
<div style={pdfStyles.fieldLabel}>ENG:</div>
<div style={{ ...pdfStyles.fieldValue, minHeight: '15px' }}>{data.visto_eng || ''}</div>
</div>
</div>
<div style={pdfStyles.twoColumnGrid}>
<div style={pdfStyles.field}>
<div style={pdfStyles.fieldLabel}>FABRICAÇÃO:</div>
<div style={{ ...pdfStyles.fieldValue, minHeight: '15px' }}>{data.visto_fab || ''}</div>
</div>
<div style={pdfStyles.field}>
<div style={pdfStyles.fieldLabel}>EXPEDIÇÃO:</div>
<div style={{ ...pdfStyles.fieldValue, minHeight: '15px' }}>{data.visto_exp || ''}</div>
</div>
<div style={pdfStyles.field}>
<div style={pdfStyles.fieldLabel}>QUALIDADE:</div>
<div style={{ ...pdfStyles.fieldValue, minHeight: '15px' }}>{data.visto_qual || ''}</div>
</div>
</div>
</div>
</div>
</div>
);
};