dre-pmw / index.html
moisesraposo's picture
AGORA EU SO GOSTARIA QUE DEPOIS DE PUBLICADO ELE FICASSE ALINHADO E NAO DESCONFIGURASSE AS ESCCRITAS, QUE TODOS SEGUISSEM O MESMO ALINHAMENTO - Follow Up Deployment
2a195cb verified
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Painel Financeiro - PMW</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://unpkg.com/feather-icons"></script>
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
<link href="https://unpkg.com/aos@2.3.1/dist/aos.css" rel="stylesheet">
<script src="https://unpkg.com/aos@2.3.1/dist/aos.js"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#2563eb',
secondary: '#64748b',
success: '#22c55e',
danger: '#ef4444',
warning: '#f59e0b',
info: '#06b6d4',
dark: '#1e293b',
light: '#f8fafc'
}
}
}
}
</script>
<style>
.card {
transition: transform 0.3s ease, box-shadow 0.3s ease;
}
.card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1);
}
.positive { color: #22c55e; }
.negative { color: #ef4444; }
</style>
</head>
<body class="bg-gray-50 font-sans">
<div class="container mx-auto px-4 py-8">
<header class="text-center mb-8" data-aos="fade-down">
<h1 class="text-3xl md:text-4xl font-bold text-dark mb-2">Painel Financeiro PMW</h1>
<p class="text-secondary">Visão geral das finanças por fluxo e real</p>
<!-- Seletor de Período -->
<div class="mt-6 bg-white rounded-lg shadow-md p-4 inline-block">
<div class="flex items-center space-x-4">
<span class="text-sm font-medium text-gray-700">Período:</span>
<select id="periodSelect" class="border border-gray-300 rounded-md px-3 py-2 text-sm focus:outline-none focus:ring-2 focus:ring-primary">
<option value="geral">Geral</option>
<option value="01-2024">Janeiro 2024</option>
<option value="02-2024">Fevereiro 2024</option>
<option value="03-2024">Março 2024</option>
<option value="04-2024">Abril 2024</option>
<option value="05-2024">Maio 2024</option>
<option value="06-2024">Junho 2024</option>
<option value="07-2024">Julho 2024</option>
<option value="08-2024">Agosto 2024</option>
<option value="09-2024">Setembro 2024</option>
<option value="10-2024">Outubro 2024</option>
<option value="11-2024">Novembro 2024</option>
<option value="12-2024">Dezembro 2024</option>
</select>
<button onclick="loadData()" class="bg-primary text-white px-4 py-2 rounded-md hover:bg-blue-700 transition-colors text-sm">
<i data-feather="refresh-cw" class="w-4 h-4 mr-1 inline"></i>
Carregar Dados
</button>
</div>
</div>
</header>
<div id="loadingSpinner" class="hidden fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center">
<div class="bg-white rounded-lg p-6 flex items-center">
<div class="animate-spin rounded-full h-8 w-8 border-b-2 border-primary mr-3"></div>
<span>Carregando dados...</span>
</div>
</div>
<div class="grid grid-cols-1 lg:grid-cols-2 gap-8 mb-12">
<!-- Total por Fluxo -->
<div class="card bg-white rounded-xl shadow-md p-6" data-aos="fade-right">
<h2 class="text-xl font-semibold text-dark mb-6 flex items-center">
<i data-feather="trending-up" class="mr-2"></i> Total por Fluxo
</h2>
<div class="grid grid-cols-3 gap-4 text-center">
<div class="p-4 bg-blue-50 rounded-lg">
<p class="text-sm text-secondary mb-1">Receita</p>
<p class="text-2xl font-bold text-primary" data-summary="revenue">R$ 634.182,54</p>
<p class="text-sm">100%</p>
</div>
<div class="p-4 bg-red-50 rounded-lg">
<p class="text-sm text-secondary mb-1">Despesa</p>
<p class="text-2xl font-bold text-danger" data-summary="expenses">R$ 635.407,39</p>
<p class="text-sm">100,19%</p>
</div>
<div class="p-4 bg-green-50 rounded-lg">
<p class="text-sm text-secondary mb-1">Diferença</p>
<p class="text-2xl font-bold negative" data-summary="difference">R$ -1.224,85</p>
<p class="text-sm negative" data-summary="difference-percentage">-0,19%</p>
</div>
</div>
</div>
<!-- Total Real -->
<div class="card bg-white rounded-xl shadow-md p-6" data-aos="fade-left">
<h2 class="text-xl font-semibold text-dark mb-6 flex items-center">
<i data-feather="dollar-sign" class="mr-2"></i> Total Real
</h2>
<div class="grid grid-cols-3 gap-4 text-center">
<div class="p-4 bg-blue-50 rounded-lg">
<p class="text-sm text-secondary mb-1">Receita Real</p>
<p class="text-2xl font-bold text-primary" data-summary="revenue-real">R$ 633.592,54</p>
<p class="text-sm">100%</p>
</div>
<div class="p-4 bg-red-50 rounded-lg">
<p class="text-sm text-secondary mb-1">Despesa Real</p>
<p class="text-2xl font-bold text-danger" data-summary="expenses-real">R$ 509.423,64</p>
<p class="text-sm">80,39%</p>
</div>
<div class="p-4 bg-green-50 rounded-lg">
<p class="text-sm text-secondary mb-1">Diferença Real</p>
<p class="text-2xl font-bold positive" data-summary="difference-real">R$ 124.168,90</p>
<p class="text-sm positive" data-summary="difference-real-percentage">19,61%</p>
</div>
</div>
</div>
</div>
<!-- Gráfico Pizza - Despesas por Categoria -->
<div class="card bg-white rounded-xl shadow-md p-6 mb-12" data-aos="fade-up">
<h2 class="text-xl font-semibold text-dark mb-6 flex items-center">
<i data-feather="pie-chart" class="mr-2"></i> Despesas por Categoria
</h2>
<div class="h-80">
<canvas id="pieChart"></canvas>
</div>
</div>
<!-- Gráfico por Centro de Custo - Versão Simplificada -->
<div class="card bg-white rounded-xl shadow-md p-6" data-aos="fade-up">
<h2 class="text-xl font-semibold text-dark mb-6 flex items-center">
<i data-feather="bar-chart-2" class="mr-2"></i> Análise por Centro de Custo
</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<!-- Gráfico de Receitas por Centro de Custo -->
<div>
<h3 class="text-lg font-medium text-primary mb-4">Receitas</h3>
<div class="h-64">
<canvas id="revenueChart"></canvas>
</div>
</div>
<!-- Gráfico de Despesas por Centro de Custo -->
<div>
<h3 class="text-lg font-medium text-danger mb-4">Despesas</h3>
<div class="h-64">
<canvas id="expensesChart"></canvas>
</div>
</div>
<!-- Tabela de Diferenças -->
<div class="md:col-span-2">
<h3 class="text-lg font-medium text-dark mb-4">Resultado Líquido (Diferença)</h3>
<div class="overflow-x-auto">
<table class="w-full text-sm text-left">
<thead class="bg-gray-100">
<tr>
<th class="px-4 py-2">Centro de Custo</th>
<th class="px-4 py-2">Diferença</th>
<th class="px-4 py-2">Diferença Real</th>
</tr>
</thead>
<tbody>
<tr class="border-b">
<td class="px-4 py-2 font-medium">ADMINISTRATIVO</td>
<td class="px-4 py-2 negative">R$ -170.129,37<br><span class="text-xs">(-214,2%)</span></td>
<td class="px-4 py-2 negative">R$ -57.049,33<br><span class="text-xs">(-280,0%)</span></td>
</tr>
<tr class="border-b">
<td class="px-4 py-2 font-medium">CRIAÇÃO DE GADO</td>
<td class="px-4 py-2 negative">R$ -10.604,53<br><span class="text-xs">(-100%)</span></td>
<td class="px-4 py-2">R$ 0,00<br><span class="text-xs">(0%)</span></td>
</tr>
<tr class="border-b">
<td class="px-4 py-2 font-medium">FRETE</td>
<td class="px-4 py-2 positive">R$ 27.310,78<br><span class="text-xs">(15,7%)</span></td>
<td class="px-4 py-2 positive">R$ 39.624,49<br><span class="text-xs">(22,7%)</span></td>
</tr>
<tr>
<td class="px-4 py-2 font-medium">PRODUÇÃO</td>
<td class="px-4 py-2 positive">R$ 152.198,27<br><span class="text-xs">(33,2%)</span></td>
<td class="px-4 py-2 positive">R$ 152.198,27<br><span class="text-xs">(33,2%)</span></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div>
<!-- Resultado Analítico do Centro de Custo Frete -->
<div class="card bg-white rounded-xl shadow-md p-6 mt-12" data-aos="fade-up">
<h2 class="text-xl font-semibold text-dark mb-6 flex items-center">
<i data-feather="truck" class="mr-2"></i> Resultado Analítico do Centro de Custo Frete
</h2>
<div class="overflow-x-auto">
<table class="w-full text-sm text-left">
<thead class="bg-gray-100">
<tr>
<th class="px-4 py-2">Veículo</th>
<th class="px-4 py-2">Receita</th>
<th class="px-4 py-2">Despesa</th>
<th class="px-4 py-2">Diferença</th>
<th class="px-4 py-2">Ações</th>
</tr>
</thead>
<tbody>
<tr class="border-b">
<td class="px-4 py-2 font-medium">PMW CAMINHAO 9-160</td>
<td class="px-4 py-2">R$ 6.124,00</td>
<td class="px-4 py-2 negative">R$ -17.125,03</td>
<td class="px-4 py-2 negative">R$ -11.001,03</td>
<td class="px-4 py-2">
<button onclick="showDetails('9-160')" class="text-primary hover:text-blue-700 flex items-center">
<i data-feather="eye" class="w-4 h-4 mr-1"></i> Detalhes
</button>
</td>
</tr>
<tr class="border-b">
<td class="px-4 py-2 font-medium">PMW HYUNDAI</td>
<td class="px-4 py-2">R$ 7.101,14</td>
<td class="px-4 py-2 negative">R$ -10.485,46</td>
<td class="px-4 py-2 negative">R$ -3.384,32</td>
<td class="px-4 py-2">
<button onclick="showDetails('hyundai')" class="text-primary hover:text-blue-700 flex items-center">
<i data-feather="eye" class="w-4 h-4 mr-1"></i> Detalhes
</button>
</td>
</tr>
<tr class="border-b">
<td class="px-4 py-2 font-medium">PMW CARRETA ACTROS</td>
<td class="px-4 py-2">R$ 89.993,97</td>
<td class="px-4 py-2 negative">R$ -59.388,41</td>
<td class="px-4 py-2 positive">R$ 30.605,56</td>
<td class="px-4 py-2">
<button onclick="showDetails('actros')" class="text-primary hover:text-blue-700 flex items-center">
<i data-feather="eye" class="w-4 h-4 mr-1"></i> Detalhes
</button>
</td>
</tr>
<tr class="border-b">
<td class="px-4 py-2 font-medium">PMW CAMINHÃO VM</td>
<td class="px-4 py-2">R$ 0,00</td>
<td class="px-4 py-2 negative">R$ -173,99</td>
<td class="px-4 py-2 negative">R$ -173,99</td>
<td class="px-4 py-2">
<button onclick="showDetails('vm')" class="text-primary hover:text-blue-700 flex items-center">
<i data-feather="eye" class="w-4 h-4 mr-1"></i> Detalhes
</button>
</td>
</tr>
<tr>
<td class="px-4 py-2 font-medium">PMW IVECO</td>
<td class="px-4 py-2">R$ 71.206,04</td>
<td class="px-4 py-2 negative">R$ -51.324,86</td>
<td class="px-4 py-2 positive">R$ 19.881,18</td>
<td class="px-4 py-2">
<button onclick="showDetails('iveco')" class="text-primary hover:text-blue-700 flex items-center">
<i data-feather="eye" class="w-4 h-4 mr-1"></i> Detalhes
</button>
</td>
</tr>
</tbody>
</table>
</div>
<!-- Modal de Detalhes -->
<div id="detailsModal" class="fixed inset-0 bg-black bg-opacity-50 hidden items-center justify-center z-50">
<div class="bg-white rounded-xl p-6 max-w-4xl w-full mx-4 max-h-[80vh] overflow-y-auto">
<div class="flex justify-between items-center mb-4">
<h3 class="text-lg font-semibold" id="modalTitle">Detalhes do Veículo</h3>
<button onclick="hideDetails()" class="text-gray-500 hover:text-gray-700">
<i data-feather="x"></i>
</button>
</div>
<div id="modalContent"></div>
</div>
</div>
</div>
</div>
<script>
// Dados detalhados por veículo
const vehicleDetails = {
'9-160': {
title: 'PMW CAMINHAO 9-160 - Detalhamento de Despesas',
items: [
{ description: 'Alimentação (9-160)', value: -30.00 },
{ description: 'Combustivel (9-160)', value: -5533.93 },
{ description: 'PEÇAS (9-160)', value: -90.09 },
{ description: 'Pedagios (9-160)', value: -691.95 },
{ description: 'PNEU (9-160)', value: -2370.43 },
{ description: 'Manutenção de veiculo (9-160)', value: -1356.83 },
{ description: 'Seguro de Veiculo (9-160)', value: -3000.14 },
{ description: 'IMPOSTOS (9-160)', value: -187.86 },
{ description: 'Salario (9-160)', value: -1894.00 },
{ description: 'Mao de obra terceirizada (9-160)', value: -1050.00 },
{ description: 'Seguro de vida (9-160)', value: -40.00 },
{ description: 'INVESTIMENTO (9-160)', value: -879.80 }
],
total: -17125.03
},
'hyundai': {
title: 'PMW HYUNDAI - Detalhamento de Despesas',
items: [
{ description: 'Alimentação (HYUNDAI)', value: -250.00 },
{ description: 'Seguro de Veiculos (HYUNDAI)', value: -3534.08 },
{ description: 'Combustivel (HYUNDAI)', value: -2906.55 },
{ description: 'Peças (HYUNDAI)', value: -786.00 },
{ description: 'Pedagios (HYUNDAI)', value: -390.14 },
{ description: 'Pneu (HYUNDAI)', value: -774.92 },
{ description: 'Salario (HYUNDAI)', value: -1800.00 },
{ description: 'Seguro de vida (HYUNDAI)', value: -43.77 }
],
total: -10485.46
},
'actros': {
title: 'PMW CARRETA ACTROS - Detalhamento de Despesas',
items: [
{ description: 'COMBUSTIVEL ACTROS', value: -27213.57 },
{ description: 'PEDAGIOS ACTROS', value: -925.12 },
{ description: 'PEÇAS ACTROS', value: -6364.23 },
{ description: 'PNEU ACTROS', value: -2596.14 },
{ description: 'MANUTENÇÃO DE VEICULOS ACTROS', value: -7232.55 },
{ description: 'SEGURO DE VEÍCULOS ACTROS', value: -2369.89 },
{ description: 'Multas de Transito (ACTROS)', value: -104.13 },
{ description: 'IMPOSTO ACTROS', value: -1694.31 },
{ description: 'SALARIO ACTROS', value: -9974.00 },
{ description: 'MAO DE OBRA TERCERIZADA ACTROS', value: -300.00 },
{ description: 'SEGURO DE VIDA ACTROS', value: -43.50 },
{ description: 'INVESTIMENTO ACTROS', value: -570.97 }
],
total: -59388.41
},
'vm': {
title: 'PMW CAMINHÃO VM - Detalhamento de Despesas',
items: [
{ description: 'SEGURO DE VEÍCULO VM', value: -173.99 }
],
total: -173.99
},
'iveco': {
title: 'PMW IVECO - Detalhamento de Despesas',
items: [
{ description: 'COMBUSTIVEL IVECO', value: -19714.09 },
{ description: 'PEÇAS IVECO', value: -1052.98 },
{ description: 'PEDAGIOS IVECO', value: -293.40 },
{ description: 'PNEUS IVECO', value: -4242.90 },
{ description: 'SEGURO DE VEICULOS IVECO', value: -441.68 },
{ description: 'IMPOSTO IVECO', value: -756.87 },
{ description: 'SALARIO IVECO', value: -13960.00 },
{ description: 'INVESTIMENTO EVECO', value: -10862.94 }
],
total: -51324.86
}
};
function showDetails(vehicle) {
const modal = document.getElementById('detailsModal');
const title = document.getElementById('modalTitle');
const content = document.getElementById('modalContent');
const data = vehicleDetails[vehicle];
title.textContent = data.title;
// Ordenar itens por valor (decrescente)
const sortedItems = [...data.items].sort((a, b) => Math.abs(b.value) - Math.abs(a.value));
let html = `
<div class="overflow-x-auto">
<table class="w-full text-sm">
<thead class="bg-gray-100">
<tr>
<th class="px-4 py-2 text-left">Descrição</th>
<th class="px-4 py-2 text-right">Valor</th>
<th class="px-4 py-2 text-right">% do Total</th>
</tr>
</thead>
<tbody>
`;
sortedItems.forEach(item => {
const percentage = ((Math.abs(item.value) / Math.abs(data.total)) * 100).toFixed(1);
html += `
<tr class="border-b">
<td class="px-4 py-2">${item.description}</td>
<td class="px-4 py-2 text-right ${item.value < 0 ? 'negative' : 'positive'}">
R$ ${Math.abs(item.value).toLocaleString('pt-BR', {minimumFractionDigits: 2})}
</td>
<td class="px-4 py-2 text-right text-secondary">
${percentage}%
</td>
</tr>
`;
});
html += `
</tbody>
<tfoot class="bg-gray-50">
<tr>
<td class="px-4 py-2 font-semibold">Total Despesas</td>
<td class="px-4 py-2 text-right font-semibold negative">
R$ ${Math.abs(data.total).toLocaleString('pt-BR', {minimumFractionDigits: 2})}
</td>
<td class="px-4 py-2 text-right font-semibold">100%</td>
</tr>
</tfoot>
</table>
</div>
`;
content.innerHTML = html;
modal.classList.remove('hidden');
modal.classList.add('flex');
feather.replace();
}
function hideDetails() {
const modal = document.getElementById('detailsModal');
modal.classList.remove('flex');
modal.classList.add('hidden');
}
// Inicializar AOS e Feather Icons
document.addEventListener('DOMContentLoaded', function() {
AOS.init({
duration: 800,
easing: 'ease-in-out',
once: true
});
feather.replace();
// Dados para os gráficos
const pieValues = [208094.81, 99710.82, 41514.57, 17328.39, 858.65, 267900.15];
const pieLabels = [
'2.01-GASTOS ADMINISTRATIVOS',
'2.02-GASTOS COM PESSOAL',
'2.03-GASTOS FINANCEIROS',
'2.04-GASTOS TRIBUTARIOS',
'2.05-INVESTIMENTOS',
'2.08-CUSTO MATERIA PRIMA'
];
// Calcular totais e porcentagens
const totalPie = pieValues.reduce((sum, value) => sum + value, 0);
const piePercentages = pieValues.map(value => ((value / totalPie) * 100).toFixed(1));
// Ordenar dados em ordem decrescente
const pieDataSorted = pieLabels.map((label, index) => ({
label,
value: pieValues[index],
percentage: piePercentages[index]
})).sort((a, b) => b.value - a.value);
const pieData = {
labels: pieDataSorted.map(item => `${item.label} (${item.percentage}%)`),
datasets: [{
data: pieDataSorted.map(item => item.value),
backgroundColor: [
'#3b82f6', '#ef4444', '#f59e0b', '#10b981', '#8b5cf6', '#ec4899'
],
borderWidth: 2,
borderColor: '#ffffff'
}]
};
const revenueData = {
labels: ['ADMINISTRATIVO', 'CRIAÇÃO DE GADO', 'FRETE', 'PRODUÇÃO'],
datasets: [{
label: 'Receita',
data: [793.81, 0, 174425.15, 458963.58],
backgroundColor: '#3b82f6',
borderColor: '#2563eb',
borderWidth: 1
}]
};
const expensesData = {
labels: ['ADMINISTRATIVO', 'CRIAÇÃO DE GADO', 'FRETE', 'PRODUÇÃO'],
datasets: [{
label: 'Despesa',
data: [170923.18, 10604.53, 147114.37, 306765.31],
backgroundColor: '#ef4444',
borderColor: '#dc2626',
borderWidth: 1
}]
};
// Configurações dos gráficos
const pieConfig = {
type: 'pie',
data: pieData,
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
position: 'right',
labels: {
font: {
size: 12
},
padding: 20
}
},
tooltip: {
callbacks: {
label: function(context) {
return context.label + ': R$ ' + context.raw.toLocaleString('pt-BR');
}
}
}
}
}
};
const revenueConfig = {
type: 'bar',
data: revenueData,
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true,
ticks: {
callback: function(value) {
return 'R$ ' + value.toLocaleString('pt-BR');
}
}
}
},
plugins: {
legend: {
display: false
},
tooltip: {
callbacks: {
label: function(context) {
return 'Receita: R$ ' + context.raw.toLocaleString('pt-BR');
}
}
}
}
}
};
const expensesConfig = {
type: 'bar',
data: expensesData,
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
y: {
beginAtZero: true,
ticks: {
callback: function(value) {
return 'R$ ' + value.toLocaleString('pt-BR');
}
}
}
},
plugins: {
legend: {
display: false
},
tooltip: {
callbacks: {
label: function(context) {
return 'Despesa: R$ ' + context.raw.toLocaleString('pt-BR');
}
}
}
}
}
};
// Criar os gráficos
const pieChart = new Chart(document.getElementById('pieChart'), pieConfig);
const revenueChart = new Chart(document.getElementById('revenueChart'), revenueConfig);
const expensesChart = new Chart(document.getElementById('expensesChart'), expensesConfig);
// Carregar dados iniciais
loadData();
});
</script>
</body>
</html>