shinkan-jinkendo/frontend/src/components/ExerciseMediaThumbTile.jsx
Lars ee54f8380f
All checks were successful
Deploy Development / deploy (push) Successful in 39s
Test Suite / pytest-backend (push) Successful in 39s
Test Suite / lint-backend (push) Successful in 0s
Test Suite / build-frontend (push) Successful in 10s
Test Suite / playwright-tests (push) Successful in 57s
feat(P-11): implement legal hold functionality for media assets and update app version to 0.8.86
2026-05-11 13:34:41 +02:00

95 lines
2.7 KiB
JavaScript

/**
* Kachelvorschau: Video nutzt ersten Frame (metadata), Bild = img, Embed = Label.
*/
import React from 'react'
import { resolveExerciseMediaFileUrl } from '../utils/exerciseMediaUrl'
export default function ExerciseMediaThumbTile({ exerciseId, media, onOpenPreview, size = 72 }) {
const src = !media.embed_url ? resolveExerciseMediaFileUrl(exerciseId, media) : null
const commonStyle = {
width: '100%',
height: '100%',
objectFit: 'cover',
}
if (media.asset_legal_hold_active) {
return (
<div
style={{
width: size,
height: size,
flexShrink: 0,
borderRadius: '8px',
overflow: 'hidden',
background: 'rgba(216, 90, 48, 0.10)',
border: '1px solid rgba(216, 90, 48, 0.35)',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
title: 'Gesperrt',
}}
title="Medium gesperrt"
>
<span style={{ fontSize: '11px', color: 'var(--danger)', textAlign: 'center', padding: '4px' }}>
Gesperrt
</span>
</div>
)
}
return (
<div
role="button"
tabIndex={0}
title="Vorschau"
onClick={() => onOpenPreview(media)}
onKeyDown={(e) => {
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault()
onOpenPreview(media)
}
}}
style={{
width: size,
height: size,
flexShrink: 0,
borderRadius: '8px',
overflow: 'hidden',
background: 'var(--surface2, rgba(127,127,127,0.12))',
border: '1px solid var(--border)',
cursor: 'pointer',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
{media.embed_url ? (
<span style={{ fontSize: '11px', padding: '4px', color: 'var(--text2)', textAlign: 'center' }}>
{media.embed_platform || 'Embed'}
</span>
) : (media.mime_type?.startsWith('image/') || media.media_type === 'image') && src ? (
<img alt="" src={src} style={commonStyle} />
) : (media.mime_type?.startsWith('video/') || media.media_type === 'video') && src ? (
<video
src={src}
muted
playsInline
preload="metadata"
style={{ ...commonStyle, pointerEvents: 'none' }}
onLoadedMetadata={(e) => {
try {
const el = e.currentTarget
const d = el.duration
el.currentTime = Number.isFinite(d) && d > 0 ? Math.min(0.05, d * 0.01) : 0.05
} catch {
/* ignore */
}
}}
/>
) : (
<span style={{ fontSize: '11px', color: 'var(--text2)' }}>Datei</span>
)}
</div>
)
}