fix: migrar checkboxes e tick-boxes para SVG vetorial puro no checklist PDF

This commit is contained in:
2026-08-21 16:40:01 +00:00
parent ee688b0f5d
commit c869cc2e3d
2 changed files with 140 additions and 258 deletions
@@ -57,24 +57,51 @@ export const PrioridadesPDFTemplate: React.FC<PrioridadesPDFTemplateProps> = ({
// Quadrados com "5" // Quadrados com "5"
for (let i = 0; i < numBigBoxes; i++) { for (let i = 0; i < numBigBoxes; i++) {
boxes.push( boxes.push(
<div key={`big-${i}`} className="tick-box-large"> <svg
<span>5</span> key={`big-${i}`}
</div> width="13"
height="13"
viewBox="0 0 13 13"
style={{ display: 'inline-block', verticalAlign: '-1px', marginRight: '2px' }}
>
<rect x="0.5" y="0.5" width="12" height="12" rx="1.5" fill="#f3f4f6" stroke="#4b5563" strokeWidth="1" />
<text x="6.5" y="9.5" textAnchor="middle" fontSize="8.5" fontFamily="Arial, sans-serif" fontWeight="bold" fill="#4b5563">5</text>
</svg>
); );
} }
// Quadrados unitários restantes // Quadrados unitários restantes
for (let i = 0; i < numSmallBoxes; i++) { for (let i = 0; i < numSmallBoxes; i++) {
boxes.push(<div key={`small-${i}`} className="tick-box"></div>); boxes.push(
<svg
key={`small-${i}`}
width="13"
height="13"
viewBox="0 0 13 13"
style={{ display: 'inline-block', verticalAlign: '-1px', marginRight: '2px' }}
>
<rect x="0.5" y="0.5" width="12" height="12" rx="1.5" fill="#ffffff" stroke="#4b5563" strokeWidth="1" />
</svg>
);
} }
} else { } else {
// Apenas quadrados unitários // Apenas quadrados unitários
for (let i = 0; i < quantity; i++) { for (let i = 0; i < quantity; i++) {
boxes.push(<div key={i} className="tick-box"></div>); boxes.push(
<svg
key={i}
width="13"
height="13"
viewBox="0 0 13 13"
style={{ display: 'inline-block', verticalAlign: '-1px', marginRight: '2px' }}
>
<rect x="0.5" y="0.5" width="12" height="12" rx="1.5" fill="#ffffff" stroke="#4b5563" strokeWidth="1" />
</svg>
);
} }
} }
return <div className="tick-boxes-wrapper">{boxes}</div>; return <span style={{ display: 'inline-block', verticalAlign: 'middle', marginLeft: '4px' }}>{boxes}</span>;
}; };
return ( return (
@@ -84,84 +111,6 @@ export const PrioridadesPDFTemplate: React.FC<PrioridadesPDFTemplateProps> = ({
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
color: #111827; color: #111827;
} }
.process-group {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 16px;
margin-top: 4px;
}
.process-item {
display: inline-flex;
align-items: center;
gap: 6px;
vertical-align: middle;
}
.process-checkbox {
width: 14px;
height: 14px;
min-width: 14px;
min-height: 14px;
border: 1.5px solid #4b5563;
border-radius: 2px;
display: inline-block;
vertical-align: middle;
box-sizing: border-box;
background-color: #ffffff;
}
.process-label {
font-size: 13px;
font-weight: 600;
color: #374151;
line-height: 14px;
display: inline-block;
vertical-align: middle;
}
.tick-boxes-wrapper {
display: inline-flex;
align-items: center;
flex-wrap: wrap;
gap: 3px;
vertical-align: middle;
}
.tick-box {
width: 13px;
height: 13px;
min-width: 13px;
min-height: 13px;
border: 1px solid #4b5563;
border-radius: 2px;
display: inline-block;
vertical-align: middle;
box-sizing: border-box;
background-color: #ffffff;
}
.tick-box-large {
width: 13px;
height: 13px;
min-width: 13px;
min-height: 13px;
border: 1px solid #4b5563;
border-radius: 2px;
display: inline-flex;
align-items: center;
justify-content: center;
vertical-align: middle;
box-sizing: border-box;
background-color: #f3f4f6;
text-align: center;
line-height: 1;
}
.tick-box-large span {
color: #6b7280;
font-size: 8.5px;
font-weight: 700;
line-height: 13px;
display: block;
width: 100%;
height: 100%;
text-align: center;
}
.item-card { .item-card {
border: 1px solid #e5e7eb; border: 1px solid #e5e7eb;
padding: 8px 10px; padding: 8px 10px;
@@ -169,31 +118,6 @@ export const PrioridadesPDFTemplate: React.FC<PrioridadesPDFTemplateProps> = ({
background-color: #ffffff; background-color: #ffffff;
box-sizing: border-box; box-sizing: border-box;
} }
.item-header {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 6px;
min-height: 18px;
}
.item-marca {
font-size: 13px;
font-weight: 700;
color: #111827;
line-height: 14px;
white-space: nowrap;
display: inline-block;
vertical-align: middle;
}
.item-tipo {
font-size: 11px;
font-weight: 600;
color: #6b7280;
line-height: 14px;
white-space: nowrap;
display: inline-block;
vertical-align: middle;
}
.item-signature { .item-signature {
margin-top: 6px; margin-top: 6px;
font-size: 11px; font-size: 11px;
@@ -251,12 +175,29 @@ export const PrioridadesPDFTemplate: React.FC<PrioridadesPDFTemplateProps> = ({
</div> </div>
{/* Coluna Processo */} {/* Coluna Processo */}
<div className="md:col-span-2"> <div className="md:col-span-2">
<p className="text-xs font-medium text-gray-500">PROCESSO</p> <p className="text-xs font-medium text-gray-500 mb-1">PROCESSO</p>
<div className="process-group"> <div style={{ marginTop: '2px' }}>
{['Corte', 'Solda', 'Pintura', 'Expedição'].map((processo) => ( {['Corte', 'Solda', 'Pintura', 'Expedição'].map((processo) => (
<div key={processo} className="process-item"> <div
<span className="process-checkbox"></span> key={processo}
<span className="process-label">{processo}</span> style={{
display: 'inline-block',
verticalAlign: 'middle',
marginRight: '16px',
whiteSpace: 'nowrap'
}}
>
<svg
width="14"
height="14"
viewBox="0 0 14 14"
style={{ display: 'inline-block', verticalAlign: '-2px', marginRight: '4px' }}
>
<rect x="0.75" y="0.75" width="12.5" height="12.5" rx="1.5" fill="#ffffff" stroke="#4b5563" strokeWidth="1.5" />
</svg>
<span style={{ fontSize: '13px', fontWeight: 600, color: '#374151', verticalAlign: 'middle' }}>
{processo}
</span>
</div> </div>
))} ))}
</div> </div>
@@ -265,14 +206,21 @@ export const PrioridadesPDFTemplate: React.FC<PrioridadesPDFTemplateProps> = ({
</div> </div>
{/* Legenda */} {/* Legenda */}
<div className="text-xs text-gray-600 mb-5 flex items-center flex-wrap gap-x-2.5"> <div className="text-xs text-gray-600 mb-5 flex items-center flex-wrap">
<span className="font-semibold">Legenda:</span> <span className="font-semibold" style={{ marginRight: '6px' }}>Legenda:</span>
<span>Marca (Qtd)</span> <span style={{ marginRight: '6px' }}>Marca (Qtd)</span>
<span className="font-medium text-gray-500">(S/M)</span> <span className="font-medium text-gray-500" style={{ marginRight: '4px' }}>(S/M)</span>
<span>= Sem Montagem,</span> <span style={{ marginRight: '6px' }}>= Sem Montagem,</span>
<span className="font-medium text-gray-500">(C/M)</span> <span className="font-medium text-gray-500" style={{ marginRight: '4px' }}>(C/M)</span>
<span>= Com Montagem. Os quadrados</span> <span style={{ marginRight: '4px' }}>= Com Montagem. Os quadrados</span>
<span className="tick-box"></span> <svg
width="13"
height="13"
viewBox="0 0 13 13"
style={{ display: 'inline-block', verticalAlign: '-2px', margin: '0 4px' }}
>
<rect x="0.5" y="0.5" width="12" height="12" rx="1.5" fill="#ffffff" stroke="#4b5563" strokeWidth="1" />
</svg>
<span>indicam o controle de peças fabricadas.</span> <span>indicam o controle de peças fabricadas.</span>
</div> </div>
@@ -303,11 +251,13 @@ export const PrioridadesPDFTemplate: React.FC<PrioridadesPDFTemplateProps> = ({
return ( return (
<div key={item.id} className="item-card"> <div key={item.id} className="item-card">
<div className="item-header"> <div style={{ marginBottom: '6px', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }}>
<span className="item-marca"> <span style={{ fontSize: '13px', fontWeight: 700, color: '#111827', verticalAlign: 'middle', marginRight: '4px' }}>
{marca} ({quantidade}) {marca} ({quantidade})
</span> </span>
<span className="item-tipo">{infoType}</span> <span style={{ fontSize: '11px', fontWeight: 600, color: '#6b7280', verticalAlign: 'middle' }}>
{infoType}
</span>
{generateTickBoxes(quantidade)} {generateTickBoxes(quantidade)}
</div> </div>
<div className="item-signature"> <div className="item-signature">
+65 -133
View File
@@ -58,17 +58,30 @@ const PrioridadesFabricacao = () => {
const numBigBoxes = Math.floor(quantity / 5); const numBigBoxes = Math.floor(quantity / 5);
const numSmallBoxes = quantity % 5; const numSmallBoxes = quantity % 5;
for (let i = 0; i < numBigBoxes; i++) { for (let i = 0; i < numBigBoxes; i++) {
boxesHtml += `<div class="tick-box-large"><span>5</span></div>`; boxesHtml += `
<svg width="13" height="13" viewBox="0 0 13 13" style="display: inline-block; vertical-align: -1px; margin-right: 2px;">
<rect x="0.5" y="0.5" width="12" height="12" rx="1.5" fill="#f3f4f6" stroke="#4b5563" stroke-width="1" />
<text x="6.5" y="9.5" text-anchor="middle" font-size="8.5" font-family="Arial, sans-serif" font-weight="bold" fill="#4b5563">5</text>
</svg>
`;
} }
for (let i = 0; i < numSmallBoxes; i++) { for (let i = 0; i < numSmallBoxes; i++) {
boxesHtml += `<div class="tick-box"></div>`; boxesHtml += `
<svg width="13" height="13" viewBox="0 0 13 13" style="display: inline-block; vertical-align: -1px; margin-right: 2px;">
<rect x="0.5" y="0.5" width="12" height="12" rx="1.5" fill="#ffffff" stroke="#4b5563" stroke-width="1" />
</svg>
`;
} }
} else { } else {
for (let i = 0; i < quantity; i++) { for (let i = 0; i < quantity; i++) {
boxesHtml += `<div class="tick-box"></div>`; boxesHtml += `
<svg width="13" height="13" viewBox="0 0 13 13" style="display: inline-block; vertical-align: -1px; margin-right: 2px;">
<rect x="0.5" y="0.5" width="12" height="12" rx="1.5" fill="#ffffff" stroke="#4b5563" stroke-width="1" />
</svg>
`;
} }
} }
return `<div class="tick-boxes-wrapper">${boxesHtml}</div>`; return `<span style="display: inline-block; vertical-align: middle; margin-left: 4px;">${boxesHtml}</span>`;
}; };
const handleImprimirRelatorio = async () => { const handleImprimirRelatorio = async () => {
@@ -106,11 +119,11 @@ const PrioridadesFabricacao = () => {
const getCoresPrioridade = (codigo: string) => { const getCoresPrioridade = (codigo: string) => {
switch (codigo) { switch (codigo) {
case 'P1': return 'text-red-700 bg-red-100'; case 'P1': return 'text-red-700 bg-red-100 border-red-300';
case 'P2': return 'text-orange-700 bg-orange-100'; case 'P2': return 'text-orange-700 bg-orange-100 border-orange-300';
case 'P3': return 'text-blue-700 bg-blue-100'; case 'P3': return 'text-blue-700 bg-blue-100 border-blue-300';
case 'P4': return 'text-gray-700 bg-gray-200'; case 'P4': return 'text-gray-700 bg-gray-200 border-gray-300';
default: return 'text-gray-700 bg-gray-200'; default: return 'text-gray-700 bg-gray-200 border-gray-300';
} }
}; };
@@ -119,15 +132,15 @@ const PrioridadesFabricacao = () => {
itemsContent += ` itemsContent += `
<div class="priority-group ${pageBreakClass}"> <div class="priority-group ${pageBreakClass}">
<h2 class="text-lg font-semibold ${getCoresPrioridade(codigo)} px-3 py-1 rounded-md inline-block mb-3"> <h2 class="text-base font-semibold ${getCoresPrioridade(codigo)} px-3 py-1 rounded-md inline-block mb-2.5 border">
${getPrioridadeNome(codigo)} ${getPrioridadeNome(codigo)}
</h2> </h2>
<div class="space-y-1"> <div class="space-y-1.5">
`; `;
// Gerar linhas de itens (3 por linha) // Gerar linhas de itens (3 por linha)
for (let i = 0; i < Math.ceil(itens.length / 3); i++) { for (let i = 0; i < Math.ceil(itens.length / 3); i++) {
const bgColorClass = i % 2 !== 0 ? 'bg-gray-50' : 'bg-white'; const bgColorClass = i % 2 !== 0 ? 'bg-gray-50/70' : 'bg-white';
const rowItems = itens.slice(i * 3, (i + 1) * 3); const rowItems = itens.slice(i * 3, (i + 1) * 3);
itemsContent += `<div class="grid grid-cols-3 gap-2 p-1 rounded-md ${bgColorClass}">`; itemsContent += `<div class="grid grid-cols-3 gap-2 p-1 rounded-md ${bgColorClass}">`;
@@ -141,9 +154,9 @@ const PrioridadesFabricacao = () => {
itemsContent += ` itemsContent += `
<div class="item-card"> <div class="item-card">
<div class="item-header"> <div style="margin-bottom: 6px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">
<span class="item-marca">${marca} (${quantidade})</span> <span style="font-size: 13px; font-weight: 700; color: #111827; vertical-align: middle; margin-right: 4px;">${marca} (${quantidade})</span>
<span class="item-tipo">${infoType}</span> <span style="font-size: 11px; font-weight: 600; color: #6b7280; vertical-align: middle;">${infoType}</span>
${tickBoxes} ${tickBoxes}
</div> </div>
<div class="item-signature"> <div class="item-signature">
@@ -179,88 +192,10 @@ const PrioridadesFabricacao = () => {
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet"> <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<style> <style>
body { body {
font-family: 'Inter', sans-serif; font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
-webkit-print-color-adjust: exact; -webkit-print-color-adjust: exact;
print-color-adjust: exact; print-color-adjust: exact;
} }
.process-group {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 16px;
margin-top: 4px;
}
.process-item {
display: inline-flex;
align-items: center;
gap: 6px;
vertical-align: middle;
}
.process-checkbox {
width: 14px;
height: 14px;
min-width: 14px;
min-height: 14px;
border: 1.5px solid #4b5563;
border-radius: 2px;
display: inline-block;
vertical-align: middle;
box-sizing: border-box;
background-color: #ffffff;
}
.process-label {
font-size: 13px;
font-weight: 600;
color: #374151;
line-height: 14px;
display: inline-block;
vertical-align: middle;
}
.tick-boxes-wrapper {
display: inline-flex;
align-items: center;
flex-wrap: wrap;
gap: 3px;
vertical-align: middle;
}
.tick-box {
width: 13px;
height: 13px;
min-width: 13px;
min-height: 13px;
border: 1px solid #4b5563;
border-radius: 2px;
display: inline-block;
vertical-align: middle;
box-sizing: border-box;
background-color: #ffffff;
}
.tick-box-large {
width: 13px;
height: 13px;
min-width: 13px;
min-height: 13px;
border: 1px solid #4b5563;
border-radius: 2px;
display: inline-flex;
align-items: center;
justify-content: center;
vertical-align: middle;
box-sizing: border-box;
background-color: #f3f4f6;
text-align: center;
line-height: 1;
}
.tick-box-large span {
color: #6b7280;
font-size: 8.5px;
font-weight: 700;
line-height: 13px;
display: block;
width: 100%;
height: 100%;
text-align: center;
}
.item-card { .item-card {
border: 1px solid #e5e7eb; border: 1px solid #e5e7eb;
padding: 8px 10px; padding: 8px 10px;
@@ -268,31 +203,6 @@ const PrioridadesFabricacao = () => {
background-color: #ffffff; background-color: #ffffff;
box-sizing: border-box; box-sizing: border-box;
} }
.item-header {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 6px;
min-height: 18px;
}
.item-marca {
font-size: 13px;
font-weight: 700;
color: #111827;
line-height: 14px;
white-space: nowrap;
display: inline-block;
vertical-align: middle;
}
.item-tipo {
font-size: 11px;
font-weight: 600;
color: #6b7280;
line-height: 14px;
white-space: nowrap;
display: inline-block;
vertical-align: middle;
}
.item-signature { .item-signature {
margin-top: 6px; margin-top: 6px;
font-size: 11px; font-size: 11px;
@@ -348,26 +258,48 @@ const PrioridadesFabricacao = () => {
</div> </div>
<!-- Coluna Processo --> <!-- Coluna Processo -->
<div class="md:col-span-2"> <div class="md:col-span-2">
<p class="text-xs font-medium text-gray-500">PROCESSO</p> <p class="text-xs font-medium text-gray-500 mb-1">PROCESSO</p>
<div class="process-group"> <div style="margin-top: 2px;">
<div class="process-item"><span class="process-checkbox"></span><span class="process-label">Corte</span></div> <div style="display: inline-block; vertical-align: middle; margin-right: 16px; white-space: nowrap;">
<div class="process-item"><span class="process-checkbox"></span><span class="process-label">Solda</span></div> <svg width="14" height="14" viewBox="0 0 14 14" style="display: inline-block; vertical-align: -2px; margin-right: 4px;">
<div class="process-item"><span class="process-checkbox"></span><span class="process-label">Pintura</span></div> <rect x="0.75" y="0.75" width="12.5" height="12.5" rx="1.5" fill="#ffffff" stroke="#4b5563" stroke-width="1.5" />
<div class="process-item"><span class="process-checkbox"></span><span class="process-label">Expedição</span></div> </svg>
<span style="font-size: 13px; font-weight: 600; color: #374151; vertical-align: middle;">Corte</span>
</div>
<div style="display: inline-block; vertical-align: middle; margin-right: 16px; white-space: nowrap;">
<svg width="14" height="14" viewBox="0 0 14 14" style="display: inline-block; vertical-align: -2px; margin-right: 4px;">
<rect x="0.75" y="0.75" width="12.5" height="12.5" rx="1.5" fill="#ffffff" stroke="#4b5563" stroke-width="1.5" />
</svg>
<span style="font-size: 13px; font-weight: 600; color: #374151; vertical-align: middle;">Solda</span>
</div>
<div style="display: inline-block; vertical-align: middle; margin-right: 16px; white-space: nowrap;">
<svg width="14" height="14" viewBox="0 0 14 14" style="display: inline-block; vertical-align: -2px; margin-right: 4px;">
<rect x="0.75" y="0.75" width="12.5" height="12.5" rx="1.5" fill="#ffffff" stroke="#4b5563" stroke-width="1.5" />
</svg>
<span style="font-size: 13px; font-weight: 600; color: #374151; vertical-align: middle;">Pintura</span>
</div>
<div style="display: inline-block; vertical-align: middle; margin-right: 16px; white-space: nowrap;">
<svg width="14" height="14" viewBox="0 0 14 14" style="display: inline-block; vertical-align: -2px; margin-right: 4px;">
<rect x="0.75" y="0.75" width="12.5" height="12.5" rx="1.5" fill="#ffffff" stroke="#4b5563" stroke-width="1.5" />
</svg>
<span style="font-size: 13px; font-weight: 600; color: #374151; vertical-align: middle;">Expedição</span>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<!-- Legenda --> <!-- Legenda -->
<div class="text-xs text-gray-600 mb-5 flex items-center flex-wrap gap-x-2.5"> <div class="text-xs text-gray-600 mb-5 flex items-center flex-wrap">
<span class="font-semibold">Legenda:</span> <span class="font-semibold" style="margin-right: 6px;">Legenda:</span>
<span>Marca (Qtd)</span> <span style="margin-right: 6px;">Marca (Qtd)</span>
<span class="font-medium text-gray-500">(S/M)</span> <span class="font-medium text-gray-500" style="margin-right: 4px;">(S/M)</span>
<span>= Sem Montagem,</span> <span style="margin-right: 6px;">= Sem Montagem,</span>
<span class="font-medium text-gray-500">(C/M)</span> <span class="font-medium text-gray-500" style="margin-right: 4px;">(C/M)</span>
<span>= Com Montagem. Os quadrados</span> <span style="margin-right: 4px;">= Com Montagem. Os quadrados</span>
<span class="tick-box"></span> <svg width="13" height="13" viewBox="0 0 13 13" style="display: inline-block; vertical-align: -2px; margin: 0 4px;">
<rect x="0.5" y="0.5" width="12" height="12" rx="1.5" fill="#ffffff" stroke="#4b5563" stroke-width="1" />
</svg>
<span>indicam o controle de peças fabricadas.</span> <span>indicam o controle de peças fabricadas.</span>
</div> </div>