mitai-jinkendo/frontend/src/components/dashboard-widgets/ReportExportWidget.jsx
Lars ed2b457da3
All checks were successful
Deploy Development / deploy (push) Successful in 1m5s
Build Test / pytest-backend (push) Successful in 4s
Build Test / lint-backend (push) Successful in 0s
Build Test / build-frontend (push) Successful in 20s
feat: enhance report management and PDF generation capabilities
- Introduced new API endpoints for managing report definitions, including listing, creating, and updating reports.
- Updated the frontend to include a dedicated section for configuring reports, enhancing user navigation and experience.
- Modified existing components to link to the new report settings, ensuring seamless access to report functionalities.
- Improved the report catalog API to support multiple definitions per profile and added validation for report limits.
- Updated documentation and tests to reflect the new features and ensure proper functionality.
2026-04-29 12:11:26 +02:00

111 lines
3.7 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { Link } from 'react-router-dom'
import dayjs from 'dayjs'
import { FileDown } from 'lucide-react'
import { useAuth } from '../../context/AuthContext'
import { useProfile } from '../../context/ProfileContext'
import { exportDashboardToPdf } from '../../utils/dashboardPdfExport'
/**
* @param {{ reportExportConfig: { document_title: string, subtitle: string, capture_scale: number } }} props
*/
export default function ReportExportWidget({ reportExportConfig }) {
const { canExport } = useAuth()
const { activeProfile } = useProfile()
const [busy, setBusy] = useState(false)
const [err, setErr] = useState(null)
const profileName = activeProfile?.name?.trim() || 'Profil'
const title =
reportExportConfig.document_title || `${profileName} Übersicht`
const subtitle =
reportExportConfig.subtitle ||
`Erstellt am ${dayjs().format('DD.MM.YYYY HH:mm')} · Mitai Jinkendo`
const runExport = async () => {
setErr(null)
setBusy(true)
try {
const slug = (reportExportConfig.document_title || profileName).replace(/\s+/g, '-').slice(0, 80)
await exportDashboardToPdf({
scale: reportExportConfig.capture_scale,
filenameBase: `bericht-${slug}-${dayjs().format('YYYY-MM-DD')}`,
})
} catch (e) {
setErr(e?.message || 'PDF-Export fehlgeschlagen.')
} finally {
setBusy(false)
}
}
return (
<div className="card" style={{ marginBottom: 16 }}>
<div
className="card-title"
style={{ display: 'flex', alignItems: 'center', gap: 8 }}
data-dashboard-pdf-exclude="true"
>
<FileDown size={18} color="var(--accent)" aria-hidden />
Übersicht als Bild-PDF
</div>
<div style={{ marginTop: 12 }}>
<h2
style={{
fontSize: 17,
fontWeight: 650,
margin: '0 0 6px',
color: 'var(--text1)',
lineHeight: 1.35,
}}
>
{title}
</h2>
<p style={{ margin: 0, fontSize: 13, color: 'var(--text2)', lineHeight: 1.5 }}>{subtitle}</p>
</div>
<div data-dashboard-pdf-exclude="true">
<p style={{ fontSize: 12, color: 'var(--text3)', marginTop: 14, lineHeight: 1.55 }}>
<strong>Layout-Schnappschuss:</strong> Die sichtbare Übersicht wird im Browser gerastert (html2canvas).
Für einen <strong>datenbasierten Bericht</strong> unabhängig vom Dashboard öffne{' '}
<Link to="/settings/reports" style={{ color: 'var(--accent)', fontWeight: 600 }}>
Einstellungen PDF-Berichte
</Link>
.
</p>
<div style={{ marginTop: 14 }}>
{!canExport ? (
<p style={{ fontSize: 13, color: '#D85A30', margin: 0 }}>
PDF-Export ist für dieses Profil nicht freigeschaltet.
</p>
) : (
<>
{err && (
<p style={{ fontSize: 13, color: '#D85A30', margin: '0 0 10px' }} role="alert">
{err}
</p>
)}
<button
type="button"
className="btn btn-primary"
disabled={busy}
onClick={runExport}
style={{ display: 'inline-flex', alignItems: 'center', gap: 8 }}
>
{busy ? (
<>
<span className="spinner" style={{ width: 18, height: 18 }} aria-hidden />
PDF wird erzeugt
</>
) : (
<>
<FileDown size={18} />
PDF-Schnappschuss herunterladen
</>
)}
</button>
</>
)}
</div>
</div>
</div>
)
}