"use client" import Image from "next/image" import Link from "next/link" import { Icons } from "../icons" import { useEffect, useState } from "react" import { LABELS } from "@/app/labels" interface VideoCardProps { videoId: string } const VideoCard = ({ videoId }: VideoCardProps) => { const [title, setTitle] = useState("") const [isLoading, setIsLoading] = useState(true) const thumbnailUrl = `https://img.youtube.com/vi/${videoId}/maxresdefault.jpg` useEffect(() => { // Use YouTube's oEmbed API to get video title (no CORS issues) fetch( `https://www.youtube.com/oembed?url=https://www.youtube.com/watch?v=${videoId}&format=json` ) .then((response) => response.json()) .then((data) => { setTitle(data.title) setIsLoading(false) }) .catch(() => { // If oEmbed fails, we'll just show "YouTube Video" setIsLoading(false) }) }, [videoId]) return (
{title { // Fallback to medium quality if maxresdefault is not available const target = e.target as HTMLImageElement target.src = `https://img.youtube.com/vi/${videoId}/mqdefault.jpg` }} />

{isLoading ? (
) : ( title || "YouTube Video" )}

) } export const ProjectYouTubeVideos = ({ youtubeLinks, }: { youtubeLinks: string[] }) => { const [videoIds, setVideoIds] = useState([]) const extractVideoId = (url: string): string => { if (url.includes("youtube.com/watch?v=")) { const urlObj = new URL(url) return urlObj.searchParams.get("v") || "" } else if (url.includes("youtu.be/")) { return url.split("youtu.be/")[1]?.split("?")[0] || "" } else if (/^[a-zA-Z0-9_-]{11}$/.test(url)) { return url } return "" } useEffect(() => { if (!youtubeLinks || youtubeLinks.length === 0) { return } // Extract valid video IDs const ids = youtubeLinks.map(extractVideoId).filter((id) => id) setVideoIds(ids) }, [youtubeLinks]) if (!youtubeLinks || youtubeLinks.length === 0 || videoIds.length === 0) { return null } return (

{LABELS.COMMON.YOUTUBE_VIDEOS}

{videoIds.map((videoId) => ( ))}
) }