Finanzen: Vorschau, Steuer und Abos ohne Karten, Container-Query auf Wrapper
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
6d015df6fa
commit
bd1eccb4e3
4 files changed
+168
-175
No files matched your search
@@ -1,6 +1,6 @@
|
||||
import { FaTriangleExclamation } from 'react-icons/fa6'
|
||||
import { Badge, Card, EmptyState } from '../ui'
|
||||
import { Badge, Card, EmptyState, Stat } from '../ui'
|
||||
import { aboView } from '../../lib/financeView'
|
||||
import { isNegText } from '../../lib/financeUi'
|
||||
|
||||
/**
|
||||
* Block 5: „Abos“. Einnahmen pro Monat (aktiv und Zahlung fehlgeschlagen), zahlende Kunden, gefährdete Einnahmen
|
||||
@@ -12,50 +12,45 @@ export default function AboCard({ abos }) {
|
||||
|
||||
if (v.error) {
|
||||
return (
|
||||
<Card title="Abos" className="fin-abo-card">
|
||||
<p className="fin-hint fin-hint-warn" role="alert">
|
||||
<FaTriangleExclamation aria-hidden="true" /> {v.error}
|
||||
</p>
|
||||
<Card title="Abos">
|
||||
<div className="fin-body">
|
||||
<p className="msg warn" role="alert">
|
||||
{v.error}
|
||||
</p>
|
||||
</div>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Card title="Abos" className="fin-abo-card" bodyStyle={{ padding: 0 }}>
|
||||
<div className="fin-stats">
|
||||
<span className="fin-amount fin-stat-value">{v.monthlyText}</span>
|
||||
<span className="fin-stat-label">Abo-Einnahmen pro Monat</span>
|
||||
<span className="fin-amount fin-stat-value">{v.payingText}</span>
|
||||
<span className="fin-stat-label">zahlende Kunden</span>
|
||||
{v.atRiskText && (
|
||||
<>
|
||||
<span className="fin-amount fin-stat-value fin-flag">{v.atRiskText}</span>
|
||||
<span className="fin-stat-label fin-flag">
|
||||
<FaTriangleExclamation aria-hidden="true" /> gefährdet
|
||||
</span>
|
||||
</>
|
||||
<Card title="Abos">
|
||||
<div className="fin-body">
|
||||
<div className="stats fin-abo-stats">
|
||||
<Stat label="Abo-Einnahmen pro Monat" value={v.monthlyText} tone={isNegText(v.monthlyText) ? 'neg' : ''} />
|
||||
<Stat label="zahlende Kunden" value={v.payingText} />
|
||||
{v.atRiskText && <Stat label="gefährdet" value={v.atRiskText} tone="neg" />}
|
||||
</div>
|
||||
|
||||
{v.rows.length === 0 ? (
|
||||
<EmptyState title="Noch keine Abos." />
|
||||
) : (
|
||||
<ul className="fin-abos">
|
||||
{v.rows.map((row) => (
|
||||
<li key={row.key} className="fin-abo">
|
||||
<div className="fin-abo-main">
|
||||
<span className="fin-abo-customer">{row.customer}</span>
|
||||
<span className="fin-abo-product muted"> · {row.product}</span>
|
||||
</div>
|
||||
<div className={`fin-amount fin-abo-amount${isNegText(row.amountText) ? ' fin-neg' : ''}`}>{row.amountText}</div>
|
||||
<div className="fin-abo-meta">
|
||||
<Badge tone={row.tone}>{row.statusLabel}</Badge>
|
||||
<span className="fin-abo-next muted">nächste Abbuchung: {row.nextText}</span>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{v.rows.length === 0 ? (
|
||||
<EmptyState title="Noch keine Abos." />
|
||||
) : (
|
||||
<ul className="fin-abos">
|
||||
{v.rows.map((row) => (
|
||||
<li key={row.key} className="fin-abo">
|
||||
<div className="fin-abo-main">
|
||||
<span className="fin-abo-customer">{row.customer}</span>
|
||||
<span className="fin-abo-product muted"> · {row.product}</span>
|
||||
</div>
|
||||
<div className="fin-amount fin-abo-amount">{row.amountText}</div>
|
||||
<div className="fin-abo-meta">
|
||||
<Badge tone={row.tone}>{row.statusLabel}</Badge>
|
||||
<span className="fin-abo-next muted">nächste Abbuchung: {row.nextText}</span>
|
||||
</div>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
)}
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
Reference in new issue
Block a user