285 lines
7.7 KiB
Plaintext
285 lines
7.7 KiB
Plaintext
<% content_for :title, "Expense Report" %>
|
|
|
|
<!-- Minimal & Clean CSS (small and tidy) -->
|
|
<style>
|
|
:root{
|
|
--card-bg: #ffffff;
|
|
--muted: #6b7280;
|
|
--accent: #2563eb; /* blue */
|
|
--radius: 10px;
|
|
--shadow: 0 6px 20px rgba(16,24,40,0.06);
|
|
--gap: 18px;
|
|
font-family: "Inter", "Poppins", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial;
|
|
}
|
|
|
|
.er-container {
|
|
max-width: 920px;
|
|
margin: 28px auto;
|
|
padding: 18px;
|
|
color: #111827;
|
|
}
|
|
|
|
.er-header {
|
|
display:flex;
|
|
align-items:center;
|
|
justify-content:space-between;
|
|
gap:12px;
|
|
margin-bottom: var(--gap);
|
|
}
|
|
|
|
.er-title {
|
|
color: #fff;
|
|
font-size:1.4rem;
|
|
font-weight:600;
|
|
margin:0;
|
|
}
|
|
|
|
.er-actions { display:flex; gap:10px; align-items:center; }
|
|
|
|
.btn-simple {
|
|
background: var(--accent);
|
|
color:#fff;
|
|
padding:8px 12px;
|
|
border-radius:8px;
|
|
text-decoration:none;
|
|
font-weight:600;
|
|
font-size:0.95rem;
|
|
box-shadow: 0 6px 16px rgba(37,99,235,0.12);
|
|
transition: transform .12s ease, box-shadow .12s ease;
|
|
}
|
|
.btn-simple:hover { transform: translateY(-3px); box-shadow: 0 10px 26px rgba(37,99,235,0.16); }
|
|
|
|
/* summary cards row */
|
|
.summary-row {
|
|
display: flex;
|
|
gap: 16px;
|
|
margin-bottom: 22px;
|
|
}
|
|
|
|
.card {
|
|
flex: 1;
|
|
padding: 16px;
|
|
border-radius: var(--radius);
|
|
background: #87ceeb; /* 🌤️ Sky Blue */
|
|
border: 1px solid var(--border);
|
|
backdrop-filter: blur(12px);
|
|
box-shadow: var(--shadowG3);
|
|
transition: .25s;
|
|
}
|
|
|
|
.card:hover {
|
|
transform: translateY(-6px) scale(1.02);
|
|
box-shadow: 0 12px 36px rgba(168,85,247,0.75);
|
|
}
|
|
|
|
.card small {
|
|
color: var(--muted);
|
|
font-weight: 500;
|
|
}
|
|
|
|
.card .value {
|
|
font-size: 1.4rem;
|
|
font-weight: 700;
|
|
margin-top: 6px;
|
|
}
|
|
|
|
/* chart wrapper */
|
|
.chart-wrap {
|
|
background: var(--card-bg);
|
|
border-radius: var(--radius);
|
|
box-shadow: var(--shadow);
|
|
padding:12px;
|
|
margin-bottom: var(--gap);
|
|
border: 1px solid rgba(15,23,42,0.04);
|
|
}
|
|
|
|
/* tables */
|
|
.table {
|
|
width:100%;
|
|
border-collapse:collapse;
|
|
margin-bottom:20px;
|
|
background: transparent;
|
|
}
|
|
.table thead th {
|
|
text-align:left; font-size:0.9rem; color:var(--muted); padding:10px 12px;
|
|
border-bottom: 1px solid rgba(15,23,42,0.06);
|
|
}
|
|
.table tbody tr {
|
|
background: #fff; border-radius:8px;
|
|
}
|
|
.table td {
|
|
padding:11px 12px;
|
|
font-size:0.95rem;
|
|
vertical-align:middle;
|
|
border-bottom: 1px solid rgba(15,23,42,0.03);
|
|
}
|
|
.table tfoot th { padding:10px 12px; text-align:left; font-weight:700; border-top:1px solid rgba(15,23,42,0.06); }
|
|
|
|
/* responsive: stack cards on small screens */
|
|
@media (max-width:720px){
|
|
.summary-row { flex-direction:column; }
|
|
.er-header { flex-direction:column; align-items:flex-start; gap:10px; }
|
|
}
|
|
</style>
|
|
|
|
<div class="er-container">
|
|
<div class="er-header">
|
|
<h1 class="er-title">EXPENSE REPORT</h1>
|
|
|
|
<div class="er-actions">
|
|
<%= link_to "New Expense", new_expense_path, class: "btn-simple" %>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Summary -->
|
|
<div class="summary-row">
|
|
<div class="card">
|
|
<small>Today's Expenses</small>
|
|
<div class="value"><%= number_to_currency(@daily_expenses || 0, unit: "₹") %></div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<small>This Week</small>
|
|
<div class="value"><%= number_to_currency(@weekly_expenses || 0, unit: "₹") %></div>
|
|
</div>
|
|
|
|
<div class="card">
|
|
<small>This Month</small>
|
|
<div class="value"><%= number_to_currency(@monthly_expenses || 0, unit: "₹") %></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Chart -->
|
|
<div class="chart-wrap">
|
|
<canvas id="expensesChart" height="120"></canvas>
|
|
</div>
|
|
|
|
<!-- Today's table -->
|
|
<section>
|
|
<h3 style="margin:0 0 8px 0; font-size:1rem; color:#374151;">Today's Expenses</h3>
|
|
<table class="table" aria-describedby="today-expenses">
|
|
<thead>
|
|
<tr><th>Amount</th><th>Date</th></tr>
|
|
</thead>
|
|
<tbody>
|
|
<% (@daily_expense_items || []).each do |expense| %>
|
|
<tr>
|
|
<td><%= number_to_currency(expense.amount, unit: "₹") %></td>
|
|
<td><%= expense.created_at.strftime("%d %b %Y") %></td>
|
|
</tr>
|
|
<% end %>
|
|
<% if (@daily_expense_items || []).empty? %>
|
|
<tr><td colspan="2" style="padding:12px;color:var(--muted)">No expenses for today.</td></tr>
|
|
<% end %>
|
|
</tbody>
|
|
<tfoot>
|
|
<tr><th>Total</th><th><%= number_to_currency(@daily_expenses || 0, unit: "₹") %></th></tr>
|
|
</tfoot>
|
|
</table>
|
|
</section>
|
|
|
|
<!-- Week table -->
|
|
<section>
|
|
<h3 style="margin:0 0 8px 0; font-size:1rem; color:#374151;">This Week's Expenses</h3>
|
|
<table class="table" aria-describedby="week-expenses">
|
|
<thead>
|
|
<tr><th>Amount</th><th>Date</th></tr>
|
|
</thead>
|
|
<tbody>
|
|
<% (@weekly_expense_items || []).each do |expense| %>
|
|
<tr>
|
|
<td><%= number_to_currency(expense.amount, unit: "₹") %></td>
|
|
<td><%= expense.created_at.strftime("%d %b %Y") %></td>
|
|
</tr>
|
|
<% end %>
|
|
<% if (@weekly_expense_items || []).empty? %>
|
|
<tr><td colspan="2" style="padding:12px;color:var(--muted)">No expenses for this week.</td></tr>
|
|
<% end %>
|
|
</tbody>
|
|
<tfoot>
|
|
<tr><th>Total</th><th><%= number_to_currency(@weekly_expenses || 0, unit: "₹") %></th></tr>
|
|
</tfoot>
|
|
</table>
|
|
</section>
|
|
|
|
<!-- Month table -->
|
|
<section>
|
|
<h3 style="margin:0 0 8px 0; font-size:1rem; color:#374151;">This Month's Expenses</h3>
|
|
<table class="table" aria-describedby="month-expenses">
|
|
<thead>
|
|
<tr><th>Amount</th><th>Date</th></tr>
|
|
</thead>
|
|
<tbody>
|
|
<% (@monthly_expense_items || []).each do |expense| %>
|
|
<tr>
|
|
<td><%= number_to_currency(expense.amount, unit: "₹") %></td>
|
|
<td><%= expense.created_at.strftime("%d %b %Y") %></td>
|
|
</tr>
|
|
<% end %>
|
|
<% if (@monthly_expense_items || []).empty? %>
|
|
<tr><td colspan="2" style="padding:12px;color:var(--muted)">No expenses for this month.</td></tr>
|
|
<% end %>
|
|
</tbody>
|
|
<tfoot>
|
|
<tr><th>Total</th><th><%= number_to_currency(@monthly_expenses || 0, unit: "₹") %></th></tr>
|
|
</tfoot>
|
|
</table>
|
|
</section>
|
|
</div>
|
|
|
|
<!-- Chart.js (rounded line + subtle gradient) -->
|
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
<script>
|
|
(function(){
|
|
const labels = <%= raw((@chart_labels || []).to_json) %>;
|
|
const data = <%= raw((@chart_data || []).to_json) %>;
|
|
|
|
const ctx = document.getElementById('expensesChart').getContext('2d');
|
|
const gradient = ctx.createLinearGradient(0,0,0,120);
|
|
gradient.addColorStop(0, 'rgba(37,99,235,0.18)');
|
|
gradient.addColorStop(1, 'rgba(37,99,235,0)');
|
|
|
|
new Chart(ctx, {
|
|
type: 'line',
|
|
data: {
|
|
labels: labels,
|
|
datasets: [{
|
|
label: 'Expenses',
|
|
data: data,
|
|
fill: true,
|
|
backgroundColor: gradient,
|
|
borderColor: 'rgba(37,99,235,1)',
|
|
tension: 0.42,
|
|
borderWidth: 2,
|
|
pointRadius: 3,
|
|
pointBackgroundColor: 'rgba(37,99,235,1)'
|
|
}]
|
|
},
|
|
options: {
|
|
maintainAspectRatio: false,
|
|
scales: {
|
|
x: { ticks: { color: '#374151' } },
|
|
y: {
|
|
beginAtZero: true,
|
|
ticks: {
|
|
callback: function(v){ return '₹' + v; },
|
|
color: '#374151'
|
|
},
|
|
grid: { color: 'rgba(15,23,42,0.04)' }
|
|
}
|
|
},
|
|
plugins: {
|
|
legend: { display: false },
|
|
tooltip: {
|
|
callbacks: {
|
|
label: function(ctx){ return '₹' + ctx.formattedValue; }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
});
|
|
})();
|
|
</script>
|
|
<% content_for :title, "Expense Report" %>
|
|
|