- 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.
111 lines
3.7 KiB
JavaScript
111 lines
3.7 KiB
JavaScript
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>
|
||
)
|
||
}
|