dash-assist / index.html
dcga's picture
Update index.html
9b447f7 verified
<!DOCTYPE html>
<html lang="pt-BR">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Assistente de Bolso — Dashboard</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=DM+Serif+Display&family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
:root {
--green: #1DE199;
--green-dark: #17B87A;
--green-light: #E8FBF4;
--green-glow: rgba(29, 225, 153, 0.12);
--green-subtle: #F0FDF9;
--white: #FFFFFF;
--black: #0B0B0B;
--gray-50: #FAFAFA;
--gray-100: #F4F4F5;
--gray-200: #E4E4E7;
--gray-300: #D4D4D8;
--gray-400: #A1A1AA;
--gray-500: #71717A;
--gray-600: #52525B;
--gray-700: #3F3F46;
--gray-800: #27272A;
--red: #EF4444;
--red-light: #FEF2F2;
--blue: #3B82F6;
--blue-light: #EFF6FF;
--yellow: #F59E0B;
--yellow-light: #FFFBEB;
--purple: #8B5CF6;
--purple-light: #F5F3FF;
--font-serif: 'DM Serif Display', serif;
--font-sans: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
--shadow-xs: 0 1px 2px rgba(0,0,0,0.04);
--shadow-sm: 0 1px 3px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04);
--shadow-md: 0 4px 6px rgba(0,0,0,0.05), 0 2px 4px rgba(0,0,0,0.03);
--shadow-lg: 0 10px 15px rgba(0,0,0,0.08), 0 4px 6px rgba(0,0,0,0.04);
--radius-sm: 6px;
--radius-md: 10px;
--radius-lg: 14px;
--radius-full: 9999px;
--space-1: 4px;
--space-2: 8px;
--space-3: 12px;
--space-4: 16px;
--space-5: 20px;
--space-6: 24px;
--space-8: 32px;
--space-10: 40px;
}
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { scroll-behavior: smooth; }
body {
font-family: var(--font-sans);
background: var(--gray-50);
color: var(--black);
line-height: 1.5;
min-height: 100dvh;
-webkit-font-smoothing: antialiased;
}
/* ===== HEADER ===== */
.header {
background: var(--white);
border-bottom: 1px solid var(--gray-200);
position: sticky;
top: 0;
z-index: 100;
}
.header-inner {
max-width: 1000px;
margin: 0 auto;
padding: var(--space-3) var(--space-4);
display: flex;
align-items: center;
justify-content: space-between;
}
.logo {
display: flex;
align-items: center;
gap: var(--space-2);
}
.logo-icon {
width: 32px;
height: 32px;
background: linear-gradient(135deg, var(--green), var(--green-dark));
border-radius: var(--radius-sm);
display: flex;
align-items: center;
justify-content: center;
}
.logo-icon svg { width: 18px; height: 18px; color: var(--white); }
.logo-img { width: 28px; height: 28px; object-fit: contain; }
.logo-text { font-family: var(--font-serif); font-size: 1rem; }
.header-actions {
display: flex;
align-items: center;
gap: var(--space-2);
}
.avatar {
width: 32px;
height: 32px;
border-radius: 50%;
background: var(--gray-200);
display: flex;
align-items: center;
justify-content: center;
font-size: 0.7rem;
font-weight: 600;
color: var(--gray-600);
}
/* ===== TABS NAV ===== */
.tabs-nav {
background: var(--white);
border-bottom: 1px solid var(--gray-200);
position: sticky;
top: 56px;
z-index: 90;
}
.tabs-nav-inner {
max-width: 1000px;
margin: 0 auto;
display: flex;
padding: 0 var(--space-4);
}
.tab-btn {
font-family: var(--font-sans);
font-size: 0.8125rem;
font-weight: 500;
padding: var(--space-3) var(--space-4);
background: none;
border: none;
color: var(--gray-500);
cursor: pointer;
position: relative;
transition: color 0.15s;
}
.tab-btn:hover { color: var(--black); }
.tab-btn.active { color: var(--black); }
.tab-btn.active::after {
content: '';
position: absolute;
bottom: 0;
left: var(--space-4);
right: var(--space-4);
height: 2px;
background: var(--green);
border-radius: 2px 2px 0 0;
}
.tab-btn:focus-visible { outline: 2px solid var(--green); outline-offset: -2px; }
/* ===== FILTERS (STRIPE STYLE) ===== */
.filters-bar {
background: var(--white);
border-bottom: 1px solid var(--gray-200);
}
.filters-inner {
max-width: 1000px;
margin: 0 auto;
padding: var(--space-3) var(--space-4);
display: flex;
flex-wrap: nowrap;
gap: var(--space-2);
align-items: center;
overflow-x: auto;
-webkit-overflow-scrolling: touch;
scrollbar-width: none;
-ms-overflow-style: none;
}
.filters-inner::-webkit-scrollbar {
display: none;
}
.filter-chip {
display: inline-flex;
align-items: center;
gap: var(--space-1);
font-family: var(--font-sans);
font-size: 0.75rem;
font-weight: 500;
padding: 6px 10px;
background: var(--white);
border: 1px solid var(--gray-300);
border-radius: var(--radius-sm);
color: var(--gray-700);
cursor: pointer;
transition: all 0.15s;
white-space: nowrap;
}
.filter-chip:hover {
background: var(--gray-50);
border-color: var(--gray-400);
}
.filter-chip:focus {
outline: none;
border-color: var(--green);
box-shadow: 0 0 0 3px var(--green-glow);
}
.filter-chip svg {
width: 12px;
height: 12px;
color: var(--gray-400);
}
.filter-chip.active {
background: var(--green-light);
border-color: var(--green);
color: var(--green-dark);
}
.filter-chip.active svg { color: var(--green-dark); }
.filter-dropdown {
position: relative;
}
.filter-dropdown-content {
display: none;
position: absolute;
top: calc(100% + 4px);
left: 0;
min-width: 180px;
background: var(--white);
border: 1px solid var(--gray-200);
border-radius: var(--radius-md);
box-shadow: var(--shadow-lg);
z-index: 200;
padding: var(--space-1);
}
.filter-dropdown.open .filter-dropdown-content { display: block; }
.filter-option {
display: block;
width: 100%;
padding: var(--space-2) var(--space-3);
font-family: var(--font-sans);
font-size: 0.8125rem;
text-align: left;
background: none;
border: none;
border-radius: var(--radius-sm);
color: var(--gray-700);
cursor: pointer;
transition: background 0.1s;
}
.filter-option:hover { background: var(--gray-100); }
.filter-option.selected { background: var(--green-light); color: var(--green-dark); font-weight: 500; }
/* ===== MAIN ===== */
.main {
max-width: 1000px;
margin: 0 auto;
padding: var(--space-4);
}
.tab-content { display: none; }
.tab-content.active { display: block; animation: fadeIn 0.2s ease; }
@keyframes fadeIn {
from { opacity: 0; transform: translateY(6px); }
to { opacity: 1; transform: translateY(0); }
}
/* ===== KPI GRID ===== */
.kpi-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: var(--space-3);
margin-bottom: var(--space-4);
}
@media (min-width: 640px) {
.kpi-grid {
grid-template-columns: repeat(4, 1fr);
}
}
.kpi-card {
background: var(--white);
border-radius: var(--radius-md);
padding: var(--space-4);
border: 1px solid var(--gray-200);
position: relative;
}
.kpi-header {
display: flex;
align-items: flex-start;
justify-content: space-between;
margin-bottom: var(--space-2);
}
.kpi-label {
font-size: 0.6875rem;
font-weight: 600;
color: var(--gray-500);
text-transform: uppercase;
letter-spacing: 0.03em;
line-height: 1.3;
}
.info-btn {
width: 16px;
height: 16px;
border-radius: 50%;
background: var(--gray-100);
border: none;
color: var(--gray-400);
font-size: 0.6rem;
font-weight: 700;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
transition: all 0.15s;
}
.info-btn:hover { background: var(--gray-200); color: var(--gray-600); }
.info-btn:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }
.kpi-value {
font-family: var(--font-serif);
font-size: 1.375rem;
color: var(--black);
line-height: 1.1;
}
.kpi-value.positive { color: var(--green-dark); }
.kpi-value.negative { color: var(--red); }
.kpi-subtitle {
font-size: 0.6875rem;
color: var(--gray-400);
margin-top: 2px;
}
.connect-link {
display: inline-flex;
align-items: center;
gap: 4px;
margin-top: var(--space-2);
font-size: 0.6875rem;
font-weight: 600;
color: var(--green);
text-decoration: none;
}
.connect-link:hover { text-decoration: underline; }
/* ===== PROJECTION CARD (REDESIGNED - LIGHT VERSION) ===== */
.projection-card {
background: var(--white);
border-radius: var(--radius-lg);
border: 1px solid var(--gray-200);
margin-bottom: var(--space-4);
overflow: hidden;
}
.projection-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: var(--space-4);
border-bottom: 1px solid var(--gray-100);
}
.projection-title {
display: flex;
align-items: center;
gap: var(--space-3);
}
.projection-icon {
width: 36px;
height: 36px;
border-radius: var(--radius-md);
background: linear-gradient(135deg, var(--green-light), var(--green-subtle));
display: flex;
align-items: center;
justify-content: center;
color: var(--green-dark);
}
.projection-icon svg {
width: 18px;
height: 18px;
}
.projection-title-text h2 {
font-family: var(--font-serif);
font-size: 1rem;
font-weight: 400;
color: var(--black);
margin-bottom: 0;
line-height: 1.2;
}
.projection-title-text span {
font-size: 0.6875rem;
color: var(--gray-500);
line-height: 1.2;
}
.badge {
font-size: 0.5625rem;
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.05em;
padding: 4px 10px;
border-radius: var(--radius-full);
background: var(--green-light);
color: var(--green-dark);
border: 1px solid var(--green);
}
.projection-body {
padding: var(--space-4);
}
.projection-metrics {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: var(--space-3);
margin-bottom: var(--space-4);
}
@media (min-width: 500px) {
.projection-metrics { grid-template-columns: repeat(4, 1fr); }
}
.projection-metric {
background: var(--gray-50);
border-radius: var(--radius-md);
padding: var(--space-3);
text-align: center;
}
.projection-metric-label {
font-size: 0.625rem;
font-weight: 600;
color: var(--gray-500);
text-transform: uppercase;
letter-spacing: 0.03em;
margin-bottom: var(--space-1);
}
.projection-metric-value {
font-family: var(--font-serif);
font-size: 1.125rem;
line-height: 1.2;
color: var(--black);
}
.projection-metric-value.income { color: var(--green-dark); }
.projection-metric-value.expense { color: var(--red); }
.projection-metric-value.result { color: var(--green-dark); }
.projection-metric-value.result.negative { color: var(--red); }
.projection-divider {
display: flex;
align-items: center;
gap: var(--space-3);
margin-bottom: var(--space-3);
}
.projection-divider::before,
.projection-divider::after {
content: '';
flex: 1;
height: 1px;
background: var(--gray-200);
}
.projection-divider-text {
font-size: 0.625rem;
font-weight: 600;
color: var(--gray-400);
text-transform: uppercase;
letter-spacing: 0.05em;
}
.projection-list {
list-style: none;
display: grid;
gap: var(--space-2);
}
.projection-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: var(--space-3);
background: var(--gray-50);
border-radius: var(--radius-md);
transition: background 0.15s;
}
.projection-item:hover {
background: var(--gray-100);
}
.projection-item-info {
display: flex;
align-items: center;
gap: var(--space-3);
}
.projection-item-icon {
width: 32px;
height: 32px;
border-radius: var(--radius-sm);
display: flex;
align-items: center;
justify-content: center;
font-size: 0.875rem;
}
.projection-item-icon.expense {
background: var(--red-light);
}
.projection-item-icon.income {
background: var(--green-light);
}
.projection-item-text { display: flex; flex-direction: column; }
.projection-item-title {
font-size: 0.8125rem;
font-weight: 500;
color: var(--black);
}
.projection-item-date {
font-size: 0.6875rem;
color: var(--gray-500);
}
.projection-item-value {
font-size: 0.875rem;
font-weight: 600;
text-align: right;
}
.projection-item-value.income { color: var(--green-dark); }
.projection-item-value.expense { color: var(--red); }
.projection-footer {
padding: var(--space-3) var(--space-4);
background: var(--gray-50);
border-top: 1px solid var(--gray-100);
}
.projection-note {
font-size: 0.6875rem;
color: var(--gray-500);
line-height: 1.5;
display: flex;
align-items: flex-start;
gap: var(--space-2);
}
.projection-note svg {
width: 14px;
height: 14px;
color: var(--gray-400);
flex-shrink: 0;
margin-top: 1px;
}
/* ===== CARD ===== */
.card {
background: var(--white);
border-radius: var(--radius-md);
border: 1px solid var(--gray-200);
margin-bottom: var(--space-4);
overflow: hidden;
}
.card-header {
padding: var(--space-4);
border-bottom: 1px solid var(--gray-100);
}
.card-header h3 {
font-family: var(--font-serif);
font-size: 0.9375rem;
font-weight: 400;
}
.card-body { padding: var(--space-4); }
/* ===== CHARTS ===== */
.chart-container {
position: relative;
height: 180px;
}
.chart-row {
display: grid;
grid-template-columns: 1fr;
gap: var(--space-4);
}
@media (min-width: 640px) {
.chart-row { grid-template-columns: repeat(2, 1fr); }
}
.mini-chart-container {
position: relative;
height: 140px;
}
/* ===== CATEGORY GRID ===== */
.category-grid {
display: grid;
grid-template-columns: 1fr;
gap: var(--space-4);
}
@media (min-width: 500px) {
.category-grid { grid-template-columns: 140px 1fr; }
}
.category-chart-wrapper {
display: flex;
justify-content: center;
align-items: center;
}
.category-chart-box {
width: 120px;
height: 120px;
}
.category-table {
width: 100%;
border-collapse: collapse;
font-size: 0.75rem;
}
.category-table th {
text-align: left;
font-size: 0.625rem;
font-weight: 600;
color: var(--gray-500);
text-transform: uppercase;
letter-spacing: 0.03em;
padding: var(--space-2) 0;
border-bottom: 1px solid var(--gray-200);
}
.category-table th:last-child { text-align: right; }
.category-table td {
padding: var(--space-2) 0;
border-bottom: 1px solid var(--gray-100);
}
.category-table td:last-child { text-align: right; font-weight: 600; }
.cat-dot {
display: inline-block;
width: 8px;
height: 8px;
border-radius: 50%;
margin-right: var(--space-2);
}
.cat-percent { color: var(--gray-400); font-size: 0.6875rem; }
/* ===== BREAKDOWN MINI CARDS ===== */
.breakdown-row {
display: grid;
grid-template-columns: 1fr;
gap: var(--space-3);
margin-bottom: var(--space-4);
}
@media (min-width: 640px) {
.breakdown-row { grid-template-columns: repeat(3, 1fr); }
}
.breakdown-card {
background: var(--white);
border-radius: var(--radius-md);
border: 1px solid var(--gray-200);
padding: var(--space-3);
}
.breakdown-card h4 {
font-size: 0.6875rem;
font-weight: 600;
color: var(--gray-500);
text-transform: uppercase;
letter-spacing: 0.02em;
margin-bottom: var(--space-2);
}
.breakdown-list { list-style: none; }
.breakdown-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: var(--space-1) 0;
font-size: 0.75rem;
}
.breakdown-item-label {
display: flex;
align-items: center;
gap: var(--space-1);
color: var(--gray-700);
}
.breakdown-item-value { font-weight: 600; color: var(--black); }
/* ===== TRANSACTION LIST ===== */
.search-bar {
display: flex;
flex-wrap: wrap;
gap: var(--space-2);
margin-bottom: var(--space-3);
}
.search-input {
flex: 1;
min-width: 160px;
font-family: var(--font-sans);
font-size: 0.75rem;
padding: var(--space-2) var(--space-3);
padding-left: 32px;
border: 1px solid var(--gray-300);
border-radius: var(--radius-sm);
background: var(--white) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23A1A1AA' stroke-width='2'%3E%3Ccircle cx='11' cy='11' r='8'/%3E%3Cpath d='m21 21-4.3-4.3'/%3E%3C/svg%3E") no-repeat 10px center;
transition: border-color 0.15s, box-shadow 0.15s;
}
.search-input:focus {
outline: none;
border-color: var(--green);
box-shadow: 0 0 0 3px var(--green-glow);
}
.chip-group { display: flex; gap: var(--space-1); }
.chip {
font-family: var(--font-sans);
font-size: 0.6875rem;
font-weight: 500;
padding: var(--space-1) var(--space-2);
border: 1px solid var(--gray-300);
border-radius: var(--radius-full);
background: var(--white);
color: var(--gray-600);
cursor: pointer;
transition: all 0.15s;
}
.chip:hover { border-color: var(--green); color: var(--green-dark); }
.chip.active { background: var(--green-light); border-color: var(--green); color: var(--green-dark); }
.tx-list { list-style: none; }
.tx-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: var(--space-3) 0;
border-bottom: 1px solid var(--gray-100);
gap: var(--space-3);
}
.tx-item:last-child { border-bottom: none; }
.tx-info { flex: 1; min-width: 0; }
.tx-main {
display: flex;
align-items: center;
gap: var(--space-2);
margin-bottom: 2px;
}
.tx-title {
font-size: 0.8125rem;
font-weight: 500;
color: var(--black);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.tx-badge {
font-size: 0.5625rem;
font-weight: 700;
text-transform: uppercase;
padding: 2px 5px;
border-radius: 3px;
flex-shrink: 0;
}
.tx-badge.rec { background: var(--yellow-light); color: var(--yellow); }
.tx-badge.parc { background: var(--blue-light); color: var(--blue); }
.tx-badge.pf { background: var(--gray-100); color: var(--gray-600); }
.tx-badge.pj { background: var(--purple-light); color: var(--purple); }
.tx-meta {
font-size: 0.6875rem;
color: var(--gray-500);
display: flex;
gap: var(--space-2);
flex-wrap: wrap;
}
.tx-value {
font-size: 0.8125rem;
font-weight: 600;
text-align: right;
flex-shrink: 0;
}
.tx-value.expense { color: var(--red); }
.tx-value.income { color: var(--green-dark); }
.view-all-btn {
display: flex;
align-items: center;
justify-content: center;
width: 100%;
padding: var(--space-3);
font-family: var(--font-sans);
font-size: 0.75rem;
font-weight: 600;
color: var(--gray-600);
background: var(--gray-50);
border: none;
border-top: 1px solid var(--gray-200);
cursor: pointer;
transition: background 0.15s, color 0.15s;
}
.view-all-btn:hover { background: var(--gray-100); color: var(--black); }
/* ===== MODAL ===== */
.modal-overlay {
display: none;
position: fixed;
inset: 0;
background: rgba(0,0,0,0.4);
z-index: 1000;
align-items: center;
justify-content: center;
padding: var(--space-4);
}
.modal-overlay.visible { display: flex; animation: fadeIn 0.15s ease; }
.modal {
background: var(--white);
border-radius: var(--radius-lg);
max-width: 500px;
width: 100%;
max-height: 85vh;
overflow-y: auto;
box-shadow: var(--shadow-lg);
}
.modal-header {
display: flex;
align-items: center;
justify-content: space-between;
padding: var(--space-4);
border-bottom: 1px solid var(--gray-200);
}
.modal-header h4 {
font-family: var(--font-serif);
font-size: 1rem;
font-weight: 400;
}
.modal-close {
width: 28px;
height: 28px;
border-radius: var(--radius-sm);
background: none;
border: none;
color: var(--gray-400);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: background 0.15s;
}
.modal-close:hover { background: var(--gray-100); color: var(--black); }
.modal-body { padding: var(--space-4); }
.modal-body p { font-size: 0.875rem; color: var(--gray-600); line-height: 1.6; }
.full-table {
width: 100%;
border-collapse: collapse;
font-size: 0.75rem;
}
.full-table th {
text-align: left;
font-size: 0.625rem;
font-weight: 600;
color: var(--gray-500);
text-transform: uppercase;
padding: var(--space-2);
background: var(--gray-50);
border-bottom: 1px solid var(--gray-200);
position: sticky;
top: 0;
}
.full-table td {
padding: var(--space-2);
border-bottom: 1px solid var(--gray-100);
vertical-align: middle;
}
.full-table .val { font-weight: 600; white-space: nowrap; }
.full-table .val.expense { color: var(--red); }
.full-table .val.income { color: var(--green-dark); }
.table-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
</style>
</head>
<body>
<!-- HEADER -->
<header class="header">
<div class="header-inner">
<div class="logo">
<img src="data:image/webp;base64,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" alt="Assistente de Bolso" class="logo-img">
<span class="logo-text">Assistente de Bolso</span>
</div>
<div class="header-actions">
<div class="avatar">DS</div>
</div>
</div>
</header>
<!-- TABS NAV -->
<nav class="tabs-nav" role="tablist">
<div class="tabs-nav-inner">
<button class="tab-btn active" role="tab" data-tab="resumo">Resumo</button>
<button class="tab-btn" role="tab" data-tab="despesas">Despesas</button>
<button class="tab-btn" role="tab" data-tab="receitas">Receitas</button>
</div>
</nav>
<!-- FILTERS BAR (STRIPE STYLE) -->
<div class="filters-bar">
<div class="filters-inner">
<div class="filter-dropdown" id="filterPeriod">
<button class="filter-chip" aria-haspopup="true">
<span>Dezembro 2024</span>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="m6 9 6 6 6-6"/></svg>
</button>
<div class="filter-dropdown-content">
<button class="filter-option selected">Mês atual</button>
<button class="filter-option">Mês anterior</button>
<button class="filter-option">Últimos 3 meses</button>
<button class="filter-option">Últimos 6 meses</button>
<button class="filter-option">Últimos 12 meses</button>
<button class="filter-option">Personalizado</button>
</div>
</div>
<div class="filter-dropdown" id="filterBank">
<button class="filter-chip" aria-haspopup="true">
<span>Todos os bancos</span>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="m6 9 6 6 6-6"/></svg>
</button>
<div class="filter-dropdown-content">
<button class="filter-option selected">Todos os bancos</button>
<button class="filter-option">Inter</button>
<button class="filter-option">Nubank</button>
<button class="filter-option">Bradesco</button>
</div>
</div>
<div class="filter-dropdown" id="filterMethod">
<button class="filter-chip" aria-haspopup="true">
<span>Todos métodos</span>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="m6 9 6 6 6-6"/></svg>
</button>
<div class="filter-dropdown-content">
<button class="filter-option selected">Todos métodos</button>
<button class="filter-option">Cartão de crédito</button>
<button class="filter-option">PIX</button>
<button class="filter-option">Boleto</button>
<button class="filter-option">Cartão de débito</button>
<button class="filter-option">Não informado</button>
</div>
</div>
<div class="filter-dropdown" id="filterAccount">
<button class="filter-chip" aria-haspopup="true">
<span>PF + PJ</span>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="m6 9 6 6 6-6"/></svg>
</button>
<div class="filter-dropdown-content">
<button class="filter-option selected">Ambos</button>
<button class="filter-option">Somente PF</button>
<button class="filter-option">Somente PJ</button>
</div>
</div>
</div>
</div>
<!-- MAIN -->
<main class="main">
<!-- ===== ABA RESUMO ===== -->
<div class="tab-content active" id="tab-resumo">
<!-- KPI Grid -->
<div class="kpi-grid">
<article class="kpi-card">
<div class="kpi-header">
<span class="kpi-label">Despesas do mês</span>
<button class="info-btn" data-info="despesas">i</button>
</div>
<div class="kpi-value negative">R$ 7.284,50</div>
<span class="kpi-subtitle">até agora</span>
</article>
<article class="kpi-card">
<div class="kpi-header">
<span class="kpi-label">Receitas do mês</span>
<button class="info-btn" data-info="receitas">i</button>
</div>
<div class="kpi-value positive">R$ 11.200,00</div>
<span class="kpi-subtitle">até agora</span>
</article>
<article class="kpi-card">
<div class="kpi-header">
<span class="kpi-label">Resultado do mês</span>
<button class="info-btn" data-info="resultado">i</button>
</div>
<div class="kpi-value positive">R$ 3.915,50</div>
<span class="kpi-subtitle">receitas − despesas</span>
</article>
<article class="kpi-card">
<div class="kpi-header">
<span class="kpi-label">Saldo atual</span>
<button class="info-btn" data-info="saldo">i</button>
</div>
<div class="kpi-value">R$ 18.742,33</div>
<span class="kpi-subtitle">dinheiro na conta</span>
</article>
</div>
<!-- Projection Card (Redesigned) -->
<section class="projection-card">
<div class="projection-header">
<div class="projection-title">
<div class="projection-icon">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<path d="M12 8v4l3 3"/>
<circle cx="12" cy="12" r="10"/>
</svg>
</div>
<div class="projection-title-text">
<h2>Projeção até o fim do mês</h2>
<span>Baseado em compromissos conhecidos</span>
</div>
</div>
<div style="display: flex; align-items: center; gap: 8px;">
<span class="badge">Previsão</span>
<button class="info-btn" data-info="projecao">i</button>
</div>
</div>
<div class="projection-body">
<div class="projection-metrics">
<div class="projection-metric">
<div class="projection-metric-label">Entradas</div>
<div class="projection-metric-value income">+R$ 0</div>
</div>
<div class="projection-metric">
<div class="projection-metric-label">Saídas</div>
<div class="projection-metric-value expense">−R$ 4.120</div>
</div>
<div class="projection-metric">
<div class="projection-metric-label">Resultado</div>
<div class="projection-metric-value result negative">−R$ 204</div>
</div>
<div class="projection-metric">
<div class="projection-metric-label">Saldo previsto</div>
<div class="projection-metric-value">R$ 14.622</div>
</div>
</div>
<div class="projection-divider">
<span class="projection-divider-text">Próximos compromissos</span>
</div>
<ul class="projection-list">
<li class="projection-item">
<div class="projection-item-info">
<div class="projection-item-icon expense">📚</div>
<div class="projection-item-text">
<span class="projection-item-title">Mensalidade escola</span>
<span class="projection-item-date">Dia 20 • Recorrente</span>
</div>
</div>
<span class="projection-item-value expense">−R$ 1.850</span>
</li>
<li class="projection-item">
<div class="projection-item-info">
<div class="projection-item-icon expense">💳</div>
<div class="projection-item-text">
<span class="projection-item-title">Parcela cartão (Inter)</span>
<span class="projection-item-date">Dia 22 • Fatura</span>
</div>
</div>
<span class="projection-item-value expense">−R$ 1.340</span>
</li>
<li class="projection-item">
<div class="projection-item-info">
<div class="projection-item-icon expense">🏥</div>
<div class="projection-item-text">
<span class="projection-item-title">Plano de saúde</span>
<span class="projection-item-date">Dia 25 • Recorrente</span>
</div>
</div>
<span class="projection-item-value expense">−R$ 680</span>
</li>
<li class="projection-item">
<div class="projection-item-info">
<div class="projection-item-icon expense">📶</div>
<div class="projection-item-text">
<span class="projection-item-title">Internet + Celular</span>
<span class="projection-item-date">Dia 28 • Recorrente</span>
</div>
</div>
<span class="projection-item-value expense">−R$ 250</span>
</li>
</ul>
</div>
<div class="projection-footer">
<p class="projection-note">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="10"/>
<path d="M12 16v-4"/>
<path d="M12 8h.01"/>
</svg>
<span>Projeção baseada em despesas recorrentes, parcelas de cartão e compromissos já conhecidos que ainda não foram pagos.</span>
</p>
</div>
</section>
<!-- Charts Row -->
<div class="chart-row">
<div class="card">
<div class="card-header"><h3>Despesas vs Receitas</h3></div>
<div class="card-body">
<div class="mini-chart-container"><canvas id="summaryBarChart"></canvas></div>
</div>
</div>
<div class="card">
<div class="card-header"><h3>Movimentações no mês</h3></div>
<div class="card-body">
<div class="mini-chart-container"><canvas id="summaryLineChart"></canvas></div>
</div>
</div>
</div>
</div>
<!-- ===== ABA DESPESAS ===== -->
<div class="tab-content" id="tab-despesas">
<!-- Category Breakdown -->
<div class="card">
<div class="card-header"><h3>Despesas por categoria</h3></div>
<div class="card-body">
<div class="category-grid">
<div class="category-chart-wrapper">
<div class="category-chart-box"><canvas id="expCatChart"></canvas></div>
</div>
<div class="table-scroll">
<table class="category-table">
<thead><tr><th>Categoria</th><th>Total</th><th>%</th></tr></thead>
<tbody id="expCatTable"></tbody>
</table>
</div>
</div>
</div>
</div>
<!-- Mini Breakdowns -->
<div class="breakdown-row">
<div class="breakdown-card">
<h4>Por método de pagamento</h4>
<ul class="breakdown-list" id="expMethodList"></ul>
</div>
<div class="breakdown-card">
<h4>Por banco</h4>
<ul class="breakdown-list" id="expBankList"></ul>
</div>
<div class="breakdown-card">
<h4>Por tipo de conta</h4>
<ul class="breakdown-list" id="expAccountList"></ul>
</div>
</div>
<!-- Evolution Chart -->
<div class="card">
<div class="card-header"><h3>Evolução das despesas</h3></div>
<div class="card-body">
<div class="chart-container"><canvas id="expEvolutionChart"></canvas></div>
</div>
</div>
<!-- Transaction List -->
<div class="card">
<div class="card-header"><h3>Últimas despesas</h3></div>
<div class="card-body">
<div class="search-bar">
<input type="text" class="search-input" placeholder="Buscar...">
<div class="chip-group">
<button class="chip">Recorrentes</button>
<button class="chip">Parceladas</button>
</div>
</div>
<ul class="tx-list" id="expList"></ul>
</div>
<button class="view-all-btn" data-modal="expModal">Ver todas as despesas</button>
</div>
</div>
<!-- ===== ABA RECEITAS ===== -->
<div class="tab-content" id="tab-receitas">
<!-- Category Breakdown -->
<div class="card">
<div class="card-header"><h3>Receitas por categoria</h3></div>
<div class="card-body">
<div class="category-grid">
<div class="category-chart-wrapper">
<div class="category-chart-box"><canvas id="incCatChart"></canvas></div>
</div>
<div class="table-scroll">
<table class="category-table">
<thead><tr><th>Categoria</th><th>Total</th><th>%</th></tr></thead>
<tbody id="incCatTable"></tbody>
</table>
</div>
</div>
</div>
</div>
<!-- Evolution Chart -->
<div class="card">
<div class="card-header"><h3>Evolução das receitas</h3></div>
<div class="card-body">
<div class="chart-container"><canvas id="incEvolutionChart"></canvas></div>
</div>
</div>
<!-- Transaction List -->
<div class="card">
<div class="card-header"><h3>Últimas receitas</h3></div>
<div class="card-body">
<div class="search-bar">
<input type="text" class="search-input" placeholder="Buscar...">
<div class="chip-group">
<button class="chip">Recorrentes</button>
</div>
</div>
<ul class="tx-list" id="incList"></ul>
</div>
<button class="view-all-btn" data-modal="incModal">Ver todas as receitas</button>
</div>
</div>
</main>
<!-- INFO MODAL -->
<div class="modal-overlay" id="infoModal">
<div class="modal">
<div class="modal-header">
<h4 id="infoTitle">Info</h4>
<button class="modal-close"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg></button>
</div>
<div class="modal-body"><p id="infoText"></p></div>
</div>
</div>
<!-- FULL LIST MODAL - EXPENSES -->
<div class="modal-overlay" id="expModal">
<div class="modal" style="max-width:700px;">
<div class="modal-header">
<h4>Todas as despesas</h4>
<button class="modal-close"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg></button>
</div>
<div class="modal-body">
<div class="table-scroll">
<table class="full-table">
<thead><tr><th>Data</th><th>Descrição</th><th>Categoria</th><th>Banco</th><th>Método</th><th>Valor</th></tr></thead>
<tbody id="expFullTable"></tbody>
</table>
</div>
</div>
</div>
</div>
<!-- FULL LIST MODAL - INCOME -->
<div class="modal-overlay" id="incModal">
<div class="modal" style="max-width:600px;">
<div class="modal-header">
<h4>Todas as receitas</h4>
<button class="modal-close"><svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M18 6 6 18"/><path d="m6 6 12 12"/></svg></button>
</div>
<div class="modal-body">
<div class="table-scroll">
<table class="full-table">
<thead><tr><th>Data</th><th>Descrição</th><th>Categoria</th><th>Valor</th></tr></thead>
<tbody id="incFullTable"></tbody>
</table>
</div>
</div>
</div>
</div>
<script>
// ===== DATA =====
const infoContent = {
despesas: { title: 'Despesas do mês', text: 'Soma de todos os gastos registrados no mês atual: compras, contas, transferências de saída e qualquer valor que saiu das suas contas.' },
receitas: { title: 'Receitas do mês', text: 'Soma de todas as entradas registradas no mês atual: salários, vendas, transferências recebidas e qualquer valor que entrou nas suas contas.' },
resultado: { title: 'Resultado do mês', text: 'Receitas menos despesas. Mostra se você está gastando mais do que ganha (negativo) ou economizando (positivo). Atenção: não é o mesmo que o dinheiro que você tem na conta.' },
saldo: { title: 'Dinheiro na conta', text: 'Soma dos saldos de todas as suas contas bancárias conectadas. Esse valor pode incluir dinheiro de meses anteriores — é diferente do resultado do mês.' },
projecao: { title: 'Projeção', text: 'Estimativa de entradas e saídas até o fim do mês, baseada em: despesas recorrentes, parcelas de cartão, e compromissos já conhecidos.' }
};
const expCategories = {
labels: ['Educação', 'Casa', 'Transporte', 'Saúde', 'Mercado', 'Lazer'],
values: [1850, 1420, 1180, 980, 1120, 734.50],
colors: ['#1DE199', '#17B87A', '#0B0B0B', '#52525B', '#A1A1AA', '#D4D4D8']
};
const incCategories = {
labels: ['Salário', 'Freelance', 'Investimentos'],
values: [8500, 2200, 500],
colors: ['#1DE199', '#17B87A', '#0B0B0B']
};
const expByMethod = [
{ label: 'Crédito', value: 3840 },
{ label: 'PIX', value: 2120 },
{ label: 'Débito', value: 890 },
{ label: 'Boleto', value: 434.50 }
];
const expByBank = [
{ label: 'Inter', value: 3200 },
{ label: 'Nubank', value: 2840 },
{ label: 'Bradesco', value: 1244.50 }
];
const expByAccount = [
{ label: 'PF', value: 5420 },
{ label: 'PJ', value: 1864.50 }
];
const expenses = [
{ date: '14/12', desc: 'Compras mercado', cat: 'Mercado', bank: 'Nubank', method: 'Crédito', value: 487.32, badge: null, account: 'PF' },
{ date: '12/12', desc: 'Mensalidade escola', cat: 'Educação', bank: 'Inter', method: 'Débito', value: 1850, badge: 'rec', account: 'PF' },
{ date: '10/12', desc: 'Porta banheiro — 2/3', cat: 'Casa', bank: 'Nubank', method: 'Crédito', value: 450, badge: 'parc', account: 'PF' },
{ date: '08/12', desc: 'Combustível', cat: 'Transporte', bank: 'Inter', method: 'PIX', value: 320, badge: null, account: 'PJ' },
{ date: '05/12', desc: 'Netflix + Spotify', cat: 'Lazer', bank: 'Nubank', method: 'Crédito', value: 89.80, badge: 'rec', account: 'PF' },
{ date: '03/12', desc: 'Farmácia', cat: 'Saúde', bank: 'Bradesco', method: 'Débito', value: 156.40, badge: null, account: 'PF' },
{ date: '01/12', desc: 'Contabilidade', cat: 'Casa', bank: 'Inter', method: 'Boleto', value: 434.50, badge: 'rec', account: 'PJ' }
];
const incomes = [
{ date: '05/12', desc: 'Salário — Empresa XYZ', cat: 'Salário', value: 8500, badge: 'rec', account: 'PF' },
{ date: '10/12', desc: 'Projeto consultoria', cat: 'Freelance', value: 2200, badge: null, account: 'PJ' },
{ date: '01/12', desc: 'Dividendos FIIs', cat: 'Investimentos', value: 500, badge: 'rec', account: 'PF' }
];
const dailyExp = [420, 0, 156.40, 0, 89.80, 0, 0, 320, 0, 450, 0, 1850, 0, 487.32];
const dailyInc = [500, 0, 0, 0, 8500, 0, 0, 0, 0, 2200, 0, 0, 0, 0];
const dayLabels = ['01','02','03','04','05','06','07','08','09','10','11','12','13','14'];
// ===== UTILS =====
const fmt = v => v.toLocaleString('pt-BR', { style: 'currency', currency: 'BRL' });
// ===== TABS =====
document.querySelectorAll('.tab-btn').forEach(btn => {
btn.addEventListener('click', () => {
document.querySelectorAll('.tab-btn').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
document.querySelectorAll('.tab-content').forEach(c => c.classList.remove('active'));
document.getElementById('tab-' + btn.dataset.tab).classList.add('active');
});
});
// ===== FILTER DROPDOWNS =====
document.querySelectorAll('.filter-dropdown').forEach(dd => {
const trigger = dd.querySelector('.filter-chip');
trigger.addEventListener('click', e => {
e.stopPropagation();
document.querySelectorAll('.filter-dropdown').forEach(d => { if (d !== dd) d.classList.remove('open'); });
dd.classList.toggle('open');
});
dd.querySelectorAll('.filter-option').forEach(opt => {
opt.addEventListener('click', () => {
dd.querySelectorAll('.filter-option').forEach(o => o.classList.remove('selected'));
opt.classList.add('selected');
trigger.querySelector('span').textContent = opt.textContent;
dd.classList.remove('open');
});
});
});
document.addEventListener('click', () => {
document.querySelectorAll('.filter-dropdown').forEach(d => d.classList.remove('open'));
});
// ===== INFO MODAL =====
const infoModal = document.getElementById('infoModal');
document.querySelectorAll('.info-btn').forEach(btn => {
btn.addEventListener('click', () => {
const key = btn.dataset.info;
const data = infoContent[key] || { title: 'Info', text: '' };
document.getElementById('infoTitle').textContent = data.title;
document.getElementById('infoText').textContent = data.text;
infoModal.classList.add('visible');
});
});
// ===== FULL LIST MODALS =====
document.querySelectorAll('.view-all-btn').forEach(btn => {
btn.addEventListener('click', () => {
document.getElementById(btn.dataset.modal).classList.add('visible');
});
});
document.querySelectorAll('.modal-close').forEach(btn => {
btn.addEventListener('click', () => btn.closest('.modal-overlay').classList.remove('visible'));
});
document.querySelectorAll('.modal-overlay').forEach(ov => {
ov.addEventListener('click', e => { if (e.target === ov) ov.classList.remove('visible'); });
});
// ===== CHIP TOGGLE =====
document.querySelectorAll('.chip').forEach(c => c.addEventListener('click', () => c.classList.toggle('active')));
// ===== RENDER LISTS =====
function renderTxList(id, items, type) {
const ul = document.getElementById(id);
ul.innerHTML = items.slice(0, 5).map(i => `
<li class="tx-item">
<div class="tx-info">
<div class="tx-main">
<span class="tx-title">${i.desc}</span>
${i.badge === 'rec' ? '<span class="tx-badge rec">Rec</span>' : ''}
${i.badge === 'parc' ? '<span class="tx-badge parc">Parc</span>' : ''}
</div>
<div class="tx-meta">
<span>${i.date}</span>
<span>${i.cat}</span>
${i.bank ? `<span>${i.bank}</span>` : ''}
${i.method ? `<span>${i.method}</span>` : ''}
<span class="tx-badge ${i.account.toLowerCase()}">${i.account}</span>
</div>
</div>
<span class="tx-value ${type}">${type === 'expense' ? '−' : '+'}${fmt(i.value)}</span>
</li>
`).join('');
}
renderTxList('expList', expenses, 'expense');
renderTxList('incList', incomes, 'income');
// ===== RENDER FULL TABLES =====
function renderFullTable(id, items, type) {
const tb = document.getElementById(id);
tb.innerHTML = items.map(i => `
<tr>
<td>${i.date}</td>
<td>${i.desc}${i.badge === 'rec' ? ' <span class="tx-badge rec">Rec</span>' : ''}${i.badge === 'parc' ? ' <span class="tx-badge parc">Parc</span>' : ''}</td>
<td>${i.cat}</td>
${i.bank !== undefined ? `<td>${i.bank}</td>` : ''}
${i.method !== undefined ? `<td>${i.method}</td>` : ''}
<td class="val ${type}">${type === 'expense' ? '−' : '+'}${fmt(i.value)}</td>
</tr>
`).join('');
}
renderFullTable('expFullTable', expenses, 'expense');
renderFullTable('incFullTable', incomes, 'income');
// ===== RENDER CATEGORY TABLES =====
function renderCatTable(id, data) {
const tb = document.getElementById(id);
const total = data.values.reduce((a,b) => a + b, 0);
tb.innerHTML = data.labels.map((l, i) => {
const pct = ((data.values[i] / total) * 100).toFixed(1);
return `<tr><td><span class="cat-dot" style="background:${data.colors[i]}"></span>${l}</td><td>${fmt(data.values[i])}</td><td class="cat-percent">${pct}%</td></tr>`;
}).join('');
}
renderCatTable('expCatTable', expCategories);
renderCatTable('incCatTable', incCategories);
// ===== RENDER BREAKDOWN LISTS =====
function renderBreakdown(id, items) {
const ul = document.getElementById(id);
ul.innerHTML = items.map(i => `
<li class="breakdown-item">
<span class="breakdown-item-label">${i.label}</span>
<span class="breakdown-item-value">${fmt(i.value)}</span>
</li>
`).join('');
}
renderBreakdown('expMethodList', expByMethod);
renderBreakdown('expBankList', expByBank);
renderBreakdown('expAccountList', expByAccount);
// ===== CHARTS =====
Chart.defaults.font.family = 'Inter, sans-serif';
Chart.defaults.color = '#71717A';
// Summary Bar
new Chart(document.getElementById('summaryBarChart'), {
type: 'bar',
data: {
labels: ['Dezembro'],
datasets: [
{ label: 'Despesas', data: [7284.50], backgroundColor: '#EF4444', borderRadius: 4, barPercentage: 0.5 },
{ label: 'Receitas', data: [11200], backgroundColor: '#1DE199', borderRadius: 4, barPercentage: 0.5 }
]
},
options: {
indexAxis: 'y',
responsive: true,
maintainAspectRatio: false,
scales: { x: { grid: { color: '#E4E4E7' }, ticks: { callback: v => 'R$ ' + (v/1000).toFixed(0) + 'k' } }, y: { display: false } },
plugins: { legend: { position: 'bottom', labels: { usePointStyle: true, pointStyle: 'circle', padding: 16 } }, tooltip: { backgroundColor: '#0B0B0B', padding: 10, cornerRadius: 6, callbacks: { label: ctx => ctx.dataset.label + ': ' + fmt(ctx.parsed.x) } } }
}
});
// Summary Line
new Chart(document.getElementById('summaryLineChart'), {
type: 'line',
data: {
labels: dayLabels,
datasets: [
{ label: 'Despesas', data: dailyExp, borderColor: '#EF4444', backgroundColor: 'rgba(239,68,68,0.08)', fill: true, tension: 0.3, pointRadius: 2 },
{ label: 'Receitas', data: dailyInc, borderColor: '#1DE199', backgroundColor: 'rgba(29,225,153,0.08)', fill: true, tension: 0.3, pointRadius: 2 }
]
},
options: {
responsive: true,
maintainAspectRatio: false,
interaction: { intersect: false, mode: 'index' },
scales: { x: { grid: { display: false } }, y: { grid: { color: '#E4E4E7' }, ticks: { callback: v => 'R$ ' + (v/1000).toFixed(0) + 'k' } } },
plugins: { legend: { position: 'bottom', labels: { usePointStyle: true, pointStyle: 'circle', padding: 16 } }, tooltip: { backgroundColor: '#0B0B0B', padding: 10, cornerRadius: 6, callbacks: { label: ctx => ctx.dataset.label + ': ' + fmt(ctx.parsed.y) } } }
}
});
// Expense Category Doughnut
new Chart(document.getElementById('expCatChart'), {
type: 'doughnut',
data: { labels: expCategories.labels, datasets: [{ data: expCategories.values, backgroundColor: expCategories.colors, borderWidth: 0 }] },
options: { responsive: true, maintainAspectRatio: false, cutout: '55%', plugins: { legend: { display: false }, tooltip: { backgroundColor: '#0B0B0B', padding: 8, cornerRadius: 4, callbacks: { label: ctx => fmt(ctx.parsed) } } } }
});
// Expense Evolution
new Chart(document.getElementById('expEvolutionChart'), {
type: 'bar',
data: { labels: dayLabels, datasets: [{ label: 'Despesas', data: dailyExp, backgroundColor: '#EF4444', borderRadius: 3 }] },
options: { responsive: true, maintainAspectRatio: false, scales: { x: { grid: { display: false } }, y: { grid: { color: '#E4E4E7' }, ticks: { callback: v => 'R$ ' + v } } }, plugins: { legend: { display: false }, tooltip: { backgroundColor: '#0B0B0B', padding: 8, cornerRadius: 4, callbacks: { label: ctx => fmt(ctx.parsed.y) } } } }
});
// Income Category Doughnut
new Chart(document.getElementById('incCatChart'), {
type: 'doughnut',
data: { labels: incCategories.labels, datasets: [{ data: incCategories.values, backgroundColor: incCategories.colors, borderWidth: 0 }] },
options: { responsive: true, maintainAspectRatio: false, cutout: '55%', plugins: { legend: { display: false }, tooltip: { backgroundColor: '#0B0B0B', padding: 8, cornerRadius: 4, callbacks: { label: ctx => fmt(ctx.parsed) } } } }
});
// Income Evolution
new Chart(document.getElementById('incEvolutionChart'), {
type: 'bar',
data: { labels: dayLabels, datasets: [{ label: 'Receitas', data: dailyInc, backgroundColor: '#1DE199', borderRadius: 3 }] },
options: { responsive: true, maintainAspectRatio: false, scales: { x: { grid: { display: false } }, y: { grid: { color: '#E4E4E7' }, ticks: { callback: v => 'R$ ' + (v/1000).toFixed(0) + 'k' } } }, plugins: { legend: { display: false }, tooltip: { backgroundColor: '#0B0B0B', padding: 8, cornerRadius: 4, callbacks: { label: ctx => fmt(ctx.parsed.y) } } } }
});
</script>
</body>
</html>