feat: finance page overhaul — pie charts, month nav, tab improvements

- Overview tab: 3 donut pie charts (expenses by category, sub payments, invoiced) each with independent month navigation arrows
- Expenses tab: big red total in category sidebar, left-aligned category column, white text
- Subcontractors tab: big gold total in sidebar, pending/paid breakdown with gold highlight
- Invoices tab: big green total in companies sidebar, dashboard-inline-link for invoice# and company, StatusBadge with Invoiced/Paid labels, column widths tuned
- StatusBadge: add optional label prop for custom display text
- Layout/style polish across tabs

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Krao Hasanee
2026-06-01 20:14:14 -04:00
parent ac3f08122d
commit 986d831186
13 changed files with 604 additions and 305 deletions
+4 -18
View File
@@ -109,13 +109,6 @@ function TasksPageShell({ statsTasks = [], projects = [], onAddProject = null, c
if (s === 'cancelled' || s === 'archived') return 0;
return 35;
};
const tabBtnStyle = (active) => ({
fontFamily: "Fourge, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
fontSize: 13, fontWeight: 500, letterSpacing: 0.2, padding: '2px 0 5px', margin: '0 8px',
borderRadius: 0, border: 'none', borderBottom: active ? '2px solid var(--accent)' : '2px solid transparent',
cursor: 'pointer', background: 'transparent',
color: active ? 'var(--text-primary)' : 'var(--text-secondary)', transition: 'all 160ms',
});
return (
<div style={{ minWidth: 0, flex: 1, display: 'flex', flexDirection: 'column', minHeight: 0 }}>
<TasksStatsRow tasks={statsTasks} />
@@ -126,7 +119,7 @@ function TasksPageShell({ statsTasks = [], projects = [], onAddProject = null, c
<div style={{ flex: '0 0 calc(30% - 24px)', minWidth: 0, display: 'flex', flexDirection: 'column', minHeight: 0 }}>
<div style={{ display: 'flex', alignItems: 'center', gap: 4, marginBottom: 10, flexShrink: 0 }}>
{projectTabs.map(t => (
<button key={t.id} onClick={() => setProjTab(t.id)} style={tabBtnStyle(projTab === t.id)}>{t.label}</button>
<button key={t.id} onClick={() => setProjTab(t.id)} className={`section-tab-btn${projTab === t.id ? ' is-active' : ''}`}>{t.label}</button>
))}
{onAddProject && (
<div style={{ marginLeft: 'auto' }}>
@@ -521,13 +514,6 @@ export default function RequestsPage() {
).values()];
}, [isExternal, allRows, projects]); // eslint-disable-line react-hooks/exhaustive-deps
const tabBtnStyle = (active) => ({
fontFamily: "Fourge, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif",
fontSize: 13, fontWeight: 500, letterSpacing: 0.2, padding: '2px 0 5px', margin: '0 8px',
borderRadius: 0, border: 'none', borderBottom: active ? '2px solid var(--accent)' : '2px solid transparent',
cursor: 'pointer', background: 'transparent',
color: active ? 'var(--text-primary)' : 'var(--text-secondary)', transition: 'all 160ms',
});
const renderRow = (row) => {
const project = projects.find(p => p.id === row.projectId);
@@ -639,7 +625,7 @@ export default function RequestsPage() {
{/* Controls bar: tabs left, filters + actions right */}
<div style={{ display: 'flex', alignItems: 'center', gap: 4, marginBottom: 10, flexShrink: 0 }}>
{tabs.map(t => (
<button key={t.id} onClick={() => setActiveTab(t.id)} style={tabBtnStyle(activeTab === t.id)}>
<button key={t.id} onClick={() => setActiveTab(t.id)} className={`section-tab-btn${activeTab === t.id ? ' is-active' : ''}`}>
{t.label}
</button>
))}
@@ -650,7 +636,7 @@ export default function RequestsPage() {
className="btn btn-outline"
aria-label="Filter projects" title="Filter projects"
onClick={() => setProjectFilterMenuOpen(o => !o)}
style={{ width: 30, minWidth: 30, padding: 0, display: 'inline-flex', alignItems: 'center', justifyContent: 'center' }}
style={{ display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 6 }}
>
<svg viewBox="0 0 16 16" width="13" height="13" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
<path d="M2 4h12M4 8h8M6 12h4" />
@@ -672,7 +658,7 @@ export default function RequestsPage() {
className="btn btn-outline"
aria-label="Filter companies" title="Filter companies"
onClick={() => setCompanyFilterMenuOpen(o => !o)}
style={{ width: 30, minWidth: 30, padding: 0, display: 'inline-flex', alignItems: 'center', justifyContent: 'center' }}
style={{ display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 6 }}
>
<svg viewBox="0 0 16 16" width="13" height="13" fill="none" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round">
<path d="M2 4h12M4 8h8M6 12h4" />