Merge branch 'main' of https://gitlab.com/hanifsalafi/mediahub_redesign into prod
This commit is contained in:
commit
ed5adaced3
|
|
@ -47,6 +47,7 @@ import {
|
|||
|
||||
// Swiper
|
||||
import { Swiper, SwiperSlide } from "swiper/react";
|
||||
import { Swiper as SwiperType } from "swiper";
|
||||
import "swiper/css";
|
||||
import "swiper/css/free-mode";
|
||||
import "swiper/css/navigation";
|
||||
|
|
@ -206,7 +207,7 @@ export default function FormConvertSPIT() {
|
|||
|
||||
// <-- changed: detailThumb is now FileType[] (objects from API) -->
|
||||
const [detailThumb, setDetailThumb] = useState<FileType[]>([]);
|
||||
const [thumbsSwiper, setThumbsSwiper] = useState<any>(null);
|
||||
const [thumbsSwiper, setThumbsSwiper] = useState<SwiperType | null>(null);
|
||||
const [files, setFiles] = useState<FileType[]>([]);
|
||||
const [filePlacements, setFilePlacements] = useState<string[][]>([]);
|
||||
const [articleIds, setArticleIds] = useState<string[]>([]);
|
||||
|
|
@ -229,6 +230,13 @@ export default function FormConvertSPIT() {
|
|||
checkUserPermissions();
|
||||
}, [userLevelId, roleId]);
|
||||
|
||||
// Handle Swiper re-initialization when detailThumb changes
|
||||
useEffect(() => {
|
||||
if (thumbsSwiper && detailThumb.length > 0) {
|
||||
thumbsSwiper.update();
|
||||
}
|
||||
}, [detailThumb, thumbsSwiper]);
|
||||
|
||||
const initializeComponent = async () => {
|
||||
try {
|
||||
setIsLoading(true);
|
||||
|
|
@ -952,68 +960,114 @@ export default function FormConvertSPIT() {
|
|||
</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div className="space-y-4">
|
||||
<div className="space-y-4 overflow-hidden">
|
||||
<Swiper
|
||||
key={`main-swiper-${detailThumb.length}`}
|
||||
thumbs={{ swiper: thumbsSwiper }}
|
||||
modules={[FreeMode, Navigation, Thumbs]}
|
||||
navigation={true}
|
||||
className="w-full h-96"
|
||||
spaceBetween={10}
|
||||
loop={false}
|
||||
watchSlidesProgress={true}
|
||||
allowTouchMove={true}
|
||||
resistance={true}
|
||||
resistanceRatio={0.85}
|
||||
preventClicks={false}
|
||||
preventClicksPropagation={false}
|
||||
slidesPerView={1}
|
||||
centeredSlides={true}
|
||||
>
|
||||
{detailThumb.map((item) => (
|
||||
<SwiperSlide key={item.contentId}>
|
||||
<SwiperSlide key={item.contentId} className="!w-full">
|
||||
{item.contentType === "VIDEO" ? (
|
||||
<div className="relative max-h-screen overflow-hidden">
|
||||
<div className="w-full max-h-screen aspect-video">
|
||||
<div className="w-full h-full object-contain">
|
||||
{/* main video player */}
|
||||
<video
|
||||
className="object-contain h-full w-full rounded-lg"
|
||||
src={item.contentFile}
|
||||
controls
|
||||
// playsInline to better on mobile
|
||||
playsInline
|
||||
// you can set poster if available: poster={item.thumbnailFileUrl}
|
||||
title={`Video ${item.contentId}`}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative w-full h-96 overflow-hidden rounded-lg">
|
||||
<video
|
||||
className="w-full h-full object-contain rounded-lg"
|
||||
src={item.contentFile}
|
||||
controls
|
||||
playsInline
|
||||
poster={item.thumbnailFileUrl || undefined}
|
||||
title={`Video ${item.contentId}`}
|
||||
onError={(e) => {
|
||||
console.error('Video load error:', e);
|
||||
e.currentTarget.style.display = 'none';
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<img
|
||||
src={item.contentFile}
|
||||
alt={`Media ${item.contentId}`}
|
||||
className="w-full h-full object-cover rounded-lg"
|
||||
/>
|
||||
<div className="w-full h-96 flex items-center justify-center overflow-hidden rounded-lg">
|
||||
<img
|
||||
src={item.contentFile}
|
||||
alt={`Media ${item.contentId}`}
|
||||
className="max-w-full max-h-full object-contain rounded-lg"
|
||||
style={{ maxWidth: '100%', maxHeight: '100%' }}
|
||||
onError={(e) => {
|
||||
console.error('Image load error:', e);
|
||||
e.currentTarget.style.display = 'none';
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</SwiperSlide>
|
||||
))}
|
||||
</Swiper>
|
||||
|
||||
<Swiper
|
||||
key={`thumbs-swiper-${detailThumb.length}`}
|
||||
onSwiper={setThumbsSwiper}
|
||||
slidesPerView={8}
|
||||
spaceBetween={8}
|
||||
modules={[Pagination, Thumbs]}
|
||||
freeMode={true}
|
||||
watchSlidesProgress={true}
|
||||
modules={[FreeMode, Thumbs]}
|
||||
breakpoints={{
|
||||
320: {
|
||||
slidesPerView: 3,
|
||||
spaceBetween: 4,
|
||||
},
|
||||
640: {
|
||||
slidesPerView: 5,
|
||||
spaceBetween: 6,
|
||||
},
|
||||
768: {
|
||||
slidesPerView: 6,
|
||||
spaceBetween: 8,
|
||||
},
|
||||
1024: {
|
||||
slidesPerView: 8,
|
||||
spaceBetween: 8,
|
||||
},
|
||||
}}
|
||||
className="w-full"
|
||||
loop={false}
|
||||
allowTouchMove={true}
|
||||
resistance={true}
|
||||
resistanceRatio={0.85}
|
||||
preventClicks={false}
|
||||
preventClicksPropagation={false}
|
||||
>
|
||||
{detailThumb.map((item) => (
|
||||
<SwiperSlide key={`thumb-${item.contentId}`}>
|
||||
<SwiperSlide key={`thumb-${item.contentId}`} className="!w-auto flex-shrink-0">
|
||||
{item.contentType === "VIDEO" ? (
|
||||
<div className="relative w-full h-16 rounded cursor-pointer overflow-hidden">
|
||||
<div className="relative w-20 h-16 rounded cursor-pointer overflow-hidden flex-shrink-0">
|
||||
{/* use preload metadata so browser doesn't download full video */}
|
||||
<video
|
||||
src={item.contentFile}
|
||||
className="w-full h-16 object-cover"
|
||||
className="w-full h-full object-cover"
|
||||
muted
|
||||
preload="metadata"
|
||||
playsInline
|
||||
// no controls in thumbnail
|
||||
tabIndex={-1}
|
||||
onError={(e) => {
|
||||
console.error('Thumbnail video load error:', e);
|
||||
e.currentTarget.style.display = 'none';
|
||||
}}
|
||||
/>
|
||||
<div className="absolute inset-0 flex items-center justify-center bg-black/30 pointer-events-none">
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
className="w-6 h-6 text-white"
|
||||
className="w-4 h-4 text-white"
|
||||
fill="currentColor"
|
||||
viewBox="0 0 24 24"
|
||||
>
|
||||
|
|
@ -1022,11 +1076,17 @@ export default function FormConvertSPIT() {
|
|||
</div>
|
||||
</div>
|
||||
) : (
|
||||
<img
|
||||
src={item.contentFile}
|
||||
alt={`Thumbnail ${item.contentId}`}
|
||||
className="w-full h-16 object-cover rounded cursor-pointer"
|
||||
/>
|
||||
<div className="w-20 h-16 rounded cursor-pointer overflow-hidden flex-shrink-0">
|
||||
<img
|
||||
src={item.contentFile}
|
||||
alt={`Thumbnail ${item.contentId}`}
|
||||
className="w-full h-full object-cover"
|
||||
onError={(e) => {
|
||||
console.error('Thumbnail image load error:', e);
|
||||
e.currentTarget.style.display = 'none';
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</SwiperSlide>
|
||||
))}
|
||||
|
|
|
|||
Loading…
Reference in New Issue