shinkan-jinkendo/frontend/src/components/MediaPreviewModal.jsx
Lars 24bf3f7035
All checks were successful
Deploy Development / deploy (push) Successful in 40s
Test Suite / pytest-backend (push) Successful in 35s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 10s
Test Suite / playwright-tests (push) Successful in 1m1s
feat(P-13): update app version to 0.8.89, implement MediaPreviewModal and reporting functionality across media components
2026-05-11 18:43:05 +02:00

141 lines
5.0 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.

/**
* Gemeinsamer Medienvorschau-Dialog.
*
* Props:
* title Anzeigename des Mediums (Dateiname o.ä.)
* media Medienobjekt (mime_type, embed_url, asset_legal_hold_active, media_type)
* fileUrl Bereits aufgelöste Datei-URL (null für Embed-only-Medien)
* onClose Pflicht
* onReport optional; wenn gesetzt, erscheint "Melden"-Button
* onEdit optional; wenn gesetzt, erscheint "Bearbeiten"-Button
*/
import React from 'react'
export default function MediaPreviewModal({ title, media, fileUrl, onClose, onReport, onEdit }) {
const mlow = (media?.mime_type || '').toLowerCase()
const isHeic = mlow.includes('heic') || mlow.includes('heif')
const isImage = !isHeic && (media?.mime_type?.startsWith('image/') || media?.media_type === 'image')
const isVideo = media?.mime_type?.startsWith('video/') || media?.media_type === 'video'
const isPdf = mlow.includes('pdf')
const isLegalHold = !!media?.asset_legal_hold_active
const canReport = onReport && !isLegalHold
function handleBackdrop(e) {
if (e.target === e.currentTarget) onClose()
}
function handleKeyDown(e) {
if (e.key === 'Escape') onClose()
}
return (
<div
role="dialog"
aria-modal="true"
aria-label="Medienvorschau"
style={{
position: 'fixed',
inset: 0,
background: 'rgba(0,0,0,0.55)',
zIndex: 1100,
overflow: 'auto',
padding: '16px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
onClick={handleBackdrop}
onKeyDown={handleKeyDown}
>
<div
className="card"
style={{ maxWidth: 720, width: '100%', maxHeight: '90vh', overflow: 'auto', padding: '1.25rem' }}
onClick={(e) => e.stopPropagation()}
>
{/* Header */}
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '1rem', gap: '0.5rem' }}>
<h3 style={{ margin: 0, fontSize: '1rem', fontWeight: 600, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
{title || 'Vorschau'}
</h3>
<div style={{ display: 'flex', gap: '0.4rem', flexShrink: 0 }}>
{canReport && (
<button type="button" className="btn btn-secondary" style={{ fontSize: '0.85rem', padding: '5px 10px' }} onClick={onReport}>
Melden
</button>
)}
{onEdit && (
<button type="button" className="btn btn-secondary" style={{ fontSize: '0.85rem', padding: '5px 10px' }} onClick={onEdit}>
Bearbeiten
</button>
)}
<button
type="button"
className="btn btn-secondary"
style={{ fontSize: '0.85rem', padding: '5px 10px' }}
onClick={onClose}
aria-label="Schließen"
>
</button>
</div>
</div>
{/* Body */}
{isLegalHold ? (
<p style={{ color: 'var(--danger)', fontSize: '0.9rem' }}>
Dieses Medium ist gesperrt und steht nicht zur Verfügung.
</p>
) : media?.embed_url ? (
<p style={{ fontSize: '14px', wordBreak: 'break-all' }}>
<a href={media.embed_url} target="_blank" rel="noreferrer">{media.embed_url}</a>
</p>
) : isHeic ? (
<div>
<p style={{ color: 'var(--text2)', fontSize: '0.9rem' }}>
HEIC/HEIF in diesem Browser oft keine eingebettete Vorschau. Zum Ansehen herunterladen oder im neuen Tab öffnen.
</p>
{fileUrl && (
<a className="btn btn-secondary" href={fileUrl} target="_blank" rel="noopener noreferrer">
Datei öffnen
</a>
)}
</div>
) : isImage ? (
<img
key={media?.id}
alt=""
src={fileUrl}
style={{ maxWidth: '100%', borderRadius: '8px', maxHeight: '70vh', objectFit: 'contain', display: 'block' }}
/>
) : isVideo ? (
<video
key={media?.id}
src={fileUrl}
controls
playsInline
preload="metadata"
style={{ width: '100%', borderRadius: '8px', maxHeight: '70vh' }}
>
Wiedergabe nicht unterstützt.
</video>
) : isPdf ? (
<div>
<p style={{ color: 'var(--text2)', fontSize: '0.9rem' }}>PDF zur Ansicht im neuen Tab öffnen.</p>
{fileUrl && (
<a className="btn btn-secondary" href={fileUrl} target="_blank" rel="noopener noreferrer">
PDF öffnen
</a>
)}
</div>
) : fileUrl ? (
<p style={{ fontSize: '14px' }}>
<a href={fileUrl} target="_blank" rel="noreferrer">Datei öffnen</a>
</p>
) : (
<p style={{ color: 'var(--text2)', fontSize: '0.9rem' }}>Keine Vorschau verfügbar.</p>
)}
</div>
</div>
)
}