mira, tengo esto:

import React from "react";

interface Playlist {
  name: string;
  description: string;
  owner: string;
  songsCount: number;
  totalDuration: string;
  coverImage: string;
}

interface PlaylistInfoProps {
  playlist: Playlist;
}

const PlaylistInfo: React.FC<PlaylistInfoProps> = ({ playlist }) => {
  const bullet = "\u2022";
  const isMobile = window.innerWidth < 768;

  return (
    <div className="px-6 mb-6 lg:flex lg:items-center">
      <div className={`${isMobile ? "mb-4" : ""}`}>
        <img
          src={playlist.coverImage || "/placeholder.svg"}
          alt="Playlist cover"
          className={`w-40 h-40 object-cover rounded-md ${
            isMobile ? "mx-auto" : "mr-0 lg:mr-6 mb-4 lg:mb-0"
          }`}
        />
      </div>
      <div className="lg:flex-grow">
        <div>
          {" "}
          {!isMobile && (
            <p className="text-xs uppercase mb-1">Playlist pública</p>
          )}
          <h1 className="text-3xl lg:text-6xl font-bold mb-1">
            {playlist.name}
          </h1>
          <p className="text-sm mb-2">{playlist.description}</p>
          <p className="text-sm flex items-center">
            <img
              src="https://i.postimg.cc/PJPVDPZW/boyaca-yo.webp"
              alt="Propietario"
              className="w-6 h-6 rounded-full mr-2"
            />
            {playlist.owner} {bullet} 2M veces guardada {bullet}{" "}
            {playlist.songsCount} canciones {bullet} {playlist.totalDuration}
          </p>
        </div>
      </div>
    </div>
  );
};

export default PlaylistInfo;


tambien esto:

// App.tsx

import React, {
  useState,
  useEffect,
  useRef,
  useMemo,
  useCallback,
} from "react";
import YouTube, { YouTubeProps, YouTubePlayer } from "react-youtube";
import Navbar from "./components/Navbar";
import PlaylistInfo from "./components/PlaylistInfo";
import PlaybackControls from "./components/PlaybackControls";
import SongList from "./components/SongList";
import NowPlayingBar from "./components/NowPlayingBar";
import FullScreenPlayer from "./components/FullScreenPlayer";
import PlaybackBar from "./components/PlaybackBar";
import { songs as initialSongs, Song } from "./songs";
import SpotifyLink from "./components/spotify/SpotifyLink";

const formatTotalDuration = (totalSeconds: number): string => {
  const hours = Math.floor(totalSeconds / 3600);
  const minutes = Math.floor((totalSeconds % 3600) / 60);
  return `${hours} h ${minutes} min`;
};

const App: React.FC = () => {
  const [currentSong, setCurrentSong] = useState<Song | null>(null);
  const [isPlaying, setIsPlaying] = useState<boolean>(false);
  const [isMobile, setIsMobile] = useState<boolean>(window.innerWidth < 1024);
  const [showNavbar, setShowNavbar] = useState<boolean>(true);
  const [isFullScreenPlayer, setIsFullScreenPlayer] = useState<boolean>(false);

  const playerRef = useRef<YouTubePlayer | null>(null);

  const [currentTime, setCurrentTime] = useState<number>(0);
  const [duration, setDuration] = useState<number>(0);

  const [volume, setVolume] = useState<number>(100);

  const lastScrollY = useRef<number>(0);

  const [searchValue, setSearchValue] = useState<string>("");

  const [currentPage, setCurrentPage] = useState<number>(1);
  const songsPerPage = 100;

  const handleSearchChange = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      setSearchValue(e.target.value);
      setCurrentPage(1);
    },
    []
  );

  const handleClearSearch = useCallback(() => {
    setSearchValue("");
    setCurrentPage(1);
  }, []);

  const [sortOrder, setSortOrder] = useState<"asc" | "desc">("asc");

  const sortAscending = useCallback(() => {
    setSortOrder("asc");
  }, []);

  const sortDescending = useCallback(() => {
    setSortOrder("desc");
  }, []);

  const [isShuffle, setIsShuffle] = useState<boolean>(false);

  const filteredSongs = useMemo(() => {
    return searchValue
      ? initialSongs.filter(
          (song) =>
            song.title.toLowerCase().includes(searchValue.toLowerCase()) ||
            song.artist.toLowerCase().includes(searchValue.toLowerCase())
        )
      : initialSongs;
  }, [searchValue]);

  const sortedSongs = useMemo(() => {
    const sorted = [...filteredSongs];
    if (sortOrder === "asc") {
      sorted.reverse();
    }
    return sorted;
  }, [filteredSongs, sortOrder]);

  const totalDurationInSeconds = useMemo(
    () => sortedSongs.reduce((sum, song) => sum + (song.duration || 0), 0),
    [sortedSongs]
  );
  const totalDuration = useMemo(
    () => formatTotalDuration(totalDurationInSeconds),
    [totalDurationInSeconds]
  );

  const playlist = useMemo(
    () => ({
      name: "Time Free",
      description: "Relajao",
      owner: "Johan Morales",
      songsCount: sortedSongs.length,
      totalDuration: totalDuration,
      coverImage: "https://i.postimg.cc/BQ8t88fC/imagen-blessd-azul.jpg",
      spotifyUrl: "https://open.spotify.com/playlist/39fLwIyFpofxhYSCyyYKpC",
    }),
    [sortedSongs.length, totalDuration]
  );

  useEffect(() => {
    const handleResize = () => {
      setIsMobile(window.innerWidth < 1024);
    };

    window.addEventListener("resize", handleResize);
    return () => window.removeEventListener("resize", handleResize);
  }, []);

  useEffect(() => {
    const handleScroll = () => {
      if (!isFullScreenPlayer) {
        if (window.scrollY > lastScrollY.current && window.scrollY > 100) {
          setShowNavbar(false);
        } else {
          setShowNavbar(true);
        }
        lastScrollY.current = window.scrollY;
      }
    };

    window.addEventListener("scroll", handleScroll);
    return () => window.removeEventListener("scroll", handleScroll);
  }, [isFullScreenPlayer]);

  const getCurrentIndex = useCallback((): number => {
    if (!currentSong?.youtubeId) return -1;
    return sortedSongs.findIndex(
      (song) => song.youtubeId === currentSong.youtubeId
    );
  }, [currentSong, sortedSongs]);

  useEffect(() => {
    if (playerRef.current && currentSong?.youtubeId) {
      try {
        playerRef.current.loadVideoById(currentSong.youtubeId);
        setCurrentTime(0);
        setDuration(0);
      } catch (error) {
        console.error("Error al cargar el video:", error);
      }
    }
  }, [currentSong]);

  // Controlar la reproducción/pausa del video
  useEffect(() => {
    if (playerRef.current) {
      if (isPlaying) {
        try {
          playerRef.current.playVideo();
        } catch (error) {
          console.error("Error intentando reproducir el video:", error);
        }
      } else {
        playerRef.current.pauseVideo();
      }
    }
  }, [isPlaying]);

  useEffect(() => {
    let intervalId: number | null = null;

    if (playerRef.current && isPlaying) {
      intervalId = window.setInterval(() => {
        if (playerRef.current) {
          const current = playerRef.current.getCurrentTime();
          const dura = playerRef.current.getDuration();
          setCurrentTime(current);
          setDuration(dura);
        }
      }, 1000);
    }

    return () => {
      if (intervalId !== null) {
        window.clearInterval(intervalId);
      }
    };
  }, [isPlaying]);

  const handlePlayPause = useCallback(() => {
    if (isPlaying) {
      playerRef.current?.pauseVideo();
      setIsPlaying(false);
    } else {
      if (currentSong?.youtubeId) {
        try {
          playerRef.current?.playVideo();
          setIsPlaying(true);
        } catch (error) {
          console.error("Error intentando reproducir el video:", error);
        }
      }
    }
  }, [isPlaying, currentSong]);

  const handleNextSong = useCallback(() => {
    if (!currentSong) return;
    let nextIndex: number;

    if (isShuffle) {
      do {
        nextIndex = Math.floor(Math.random() * sortedSongs.length);
      } while (nextIndex === getCurrentIndex());
    } else {
      const currentIndex = getCurrentIndex();
      nextIndex = (currentIndex + 1) % sortedSongs.length;
    }

    const nextSong = sortedSongs[nextIndex];
    setCurrentSong(nextSong);
    setIsPlaying(true);
  }, [currentSong, isShuffle, sortedSongs, getCurrentIndex]);

  const handlePreviousSong = useCallback(() => {
    if (!currentSong) return;
    let previousIndex: number;

    if (isShuffle) {
      do {
        previousIndex = Math.floor(Math.random() * sortedSongs.length);
      } while (previousIndex === getCurrentIndex());
    } else {
      const currentIndex = getCurrentIndex();
      previousIndex =
        (currentIndex - 1 + sortedSongs.length) % sortedSongs.length;
    }

    const previousSong = sortedSongs[previousIndex];
    setCurrentSong(previousSong);
    setIsPlaying(true);
  }, [currentSong, isShuffle, sortedSongs, getCurrentIndex]);

  const onPlayerReady: YouTubeProps["onReady"] = useCallback(
    (event: YT.PlayerEvent) => {
      playerRef.current = event.target;
      setDuration(event.target.getDuration());

      event.target.setVolume(volume);

      if (isPlaying) {
        try {
          event.target.playVideo();
        } catch (error) {
          console.error("Error intentando reproducir el video:", error);
        }
      }
    },
    [isPlaying, volume]
  );

  const onPlayerEnd: YouTubeProps["onEnd"] = useCallback(() => {
    handleNextSong();
  }, [handleNextSong]);

  const onPlayerError: YouTubeProps["onError"] = useCallback(
    (event: YT.OnErrorEvent) => {
      console.error("Error del reproductor de YouTube:", event.data);
    },
    []
  );

  const onPlayerStateChange: YouTubeProps["onStateChange"] = useCallback(
    (event: YT.OnStateChangeEvent) => {
      if (window.YT && event.data === YT.PlayerState.ENDED) {
        handleNextSong();
      } else if (
        window.YT &&
        (event.data === YT.PlayerState.CUED ||
          event.data === YT.PlayerState.BUFFERING) &&
        isPlaying
      ) {
        try {
          playerRef.current?.playVideo();
        } catch (error) {
          console.error("Error intentando reproducir el video:", error);
        }
      }
    },
    [handleNextSong, isPlaying]
  );

  const opts: YouTubeProps["opts"] = useMemo(
    () => ({
      height: "0",
      width: "0",
      playerVars: {
        autoplay: 0,
        controls: 0,
        disablekb: 1,
        fs: 0,
        modestbranding: 1,
        rel: 0,
      },
    }),
    []
  );

  const handleProgressChange = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      const newTime = Number(e.target.value);
      if (playerRef.current) {
        try {
          playerRef.current.seekTo(newTime, true);
          setCurrentTime(newTime);
        } catch (error) {
          console.error("Error al cambiar el progreso del video:", error);
        }
      }
    },
    []
  );

  const handleVolumeChange = useCallback(
    (e: React.ChangeEvent<HTMLInputElement>) => {
      const newVolume = Number(e.target.value);
      setVolume(newVolume);
      if (playerRef.current) {
        try {
          playerRef.current.setVolume(newVolume);
        } catch (error) {
          console.error("Error al cambiar el volumen:", error);
        }
      }
    },
    []
  );

  const toggleMute = useCallback(() => {
    if (playerRef.current) {
      try {
        if (playerRef.current.isMuted()) {
          playerRef.current.unMute();
          setVolume(playerRef.current.getVolume());
        } else {
          playerRef.current.mute();
          setVolume(0);
        }
      } catch (error) {
        console.error("Error al alternar mute/unmute:", error);
      }
    }
  }, []);

  const toggleFullScreenPlayer = useCallback(() => {
    setIsFullScreenPlayer((prev) => !prev);
    if (!isFullScreenPlayer) {
      setShowNavbar(false);
    } else {
      setShowNavbar(true);
    }
  }, [isFullScreenPlayer]);

  const ensurePlayback = useCallback(() => {
    if (isPlaying && playerRef.current) {
      try {
        playerRef.current.playVideo();
        console.log("Reproducción iniciada automáticamente.");
      } catch (error) {
        console.error("Error al intentar reproducir automáticamente:", error);
      }
    }
  }, [isPlaying]);

  useEffect(() => {
    if (currentSong && isPlaying) {
      const timeoutId = setTimeout(() => {
        ensurePlayback();
      }, 1000);

      return () => clearTimeout(timeoutId);
    }
  }, [currentSong, isPlaying, ensurePlayback]);

  const handleSongSelect = useCallback((song: Song) => {
    setCurrentSong(song);
    setIsPlaying(true);
  }, []);

  const handleShuffle = useCallback(() => {
    setIsShuffle((prev) => !prev);
  }, []);

  const handleRepeat = useCallback(() => {
    if (currentSong) {
      setIsPlaying(false);
      setCurrentSong(currentSong);
      setIsPlaying(true);
    }
  }, [currentSong]);

  const indexOfLastSong = currentPage * songsPerPage;
  const indexOfFirstSong = indexOfLastSong - songsPerPage;
  const currentSongs = useMemo(
    () => sortedSongs.slice(indexOfFirstSong, indexOfLastSong),
    [sortedSongs, indexOfFirstSong, indexOfLastSong]
  );

  const totalPages = useMemo(
    () => Math.ceil(sortedSongs.length / songsPerPage),
    [sortedSongs.length, songsPerPage]
  );

  const handleNextPage = useCallback(() => {
    setCurrentPage((prev) => Math.min(prev + 1, totalPages));
  }, [totalPages]);

  const handlePrevPage = useCallback(() => {
    setCurrentPage((prev) => Math.max(prev - 1, 1));
  }, []);

  return (
    <div className="flex flex-col h-screen text-gray-300 bg-black">
      {currentSong?.youtubeId && (
        <YouTube
          videoId={currentSong.youtubeId}
          opts={opts}
          onReady={onPlayerReady}
          onEnd={onPlayerEnd}
          onStateChange={onPlayerStateChange}
          onError={onPlayerError}
        />
      )}

      {showNavbar && (
        <Navbar
          searchValue={searchValue}
          onSearchChange={handleSearchChange}
          onClear={handleClearSearch}
          onSortAscending={sortAscending}
          onSortDescending={sortDescending}
        />
      )}

      <div
        className={`pt-20 flex-1 overflow-y-auto bg-gradient-to-b from-blue-900 to-gray-900 ${
          isFullScreenPlayer ? "hidden" : ""
        } pb-24`}
      >
        <PlaylistInfo playlist={playlist} />

        <SpotifyLink
          url={playlist.spotifyUrl}
          text="Esta es mi playlist original"
          size={24}
        />

        {currentSong && (
          <div className="mt-6 px-4 sm:px-6 lg:px-8">
            <PlaybackControls
              isPlaying={isPlaying}
              onPlayPause={handlePlayPause}
              onAddToQueue={() => {
                console.log("Agregar a la cola");
              }}
              onMoreOptions={() => {
                console.log("Más opciones");
              }}
            />
          </div>
        )}

        <div className="mt-4 px-4 sm:px-6 lg:px-8">
          <SongList
            songs={currentSongs}
            currentSong={currentSong}
            onSongSelect={handleSongSelect}
          />
        </div>

        <div className="flex justify-between items-center mt-6 px-4 sm:px-6 lg:px-8">
          <button
            onClick={handlePrevPage}
            disabled={currentPage === 1}
            className={`px-4 py-2 bg-gray-700 text-white rounded ${
              currentPage === 1
                ? "opacity-50 cursor-not-allowed"
                : "hover:bg-gray-600"
            }`}
          >
            Anterior
          </button>
          <span className="text-sm text-gray-400">
            Página {currentPage} de {totalPages}
          </span>
          <button
            onClick={handleNextPage}
            disabled={currentPage === totalPages}
            className={`px-4 py-2 bg-blue-700 text-white rounded ${
              currentPage === totalPages
                ? "opacity-50 cursor-not-allowed"
                : "hover:bg-gray-600"
            }`}
          >
            Siguiente
          </button>
        </div>
      </div>

      {isMobile && currentSong && !isFullScreenPlayer && (
        <NowPlayingBar
          currentSong={currentSong}
          isPlaying={isPlaying}
          onPlayPause={(e) => {
            e.preventDefault();
            handlePlayPause();
          }}
          onToggleFullScreen={toggleFullScreenPlayer}
        />
      )}

      {isMobile && isFullScreenPlayer && currentSong && (
        <FullScreenPlayer
          currentSong={currentSong}
          isPlaying={isPlaying}
          onPlayPause={handlePlayPause}
          onNextSong={handleNextSong}
          onPreviousSong={handlePreviousSong}
          onShuffle={handleShuffle}
          onRepeat={handleRepeat}
          onVolumeChange={handleVolumeChange}
          volume={volume}
          onProgressChange={(values) => {
            const newTime = (values[0] / 100) * duration;
            if (playerRef.current) {
              try {
                playerRef.current.seekTo(newTime, true);
                setCurrentTime(newTime);
              } catch (error) {
                console.error("Error al cambiar el progreso del video:", error);
              }
            }
          }}
          currentTime={currentTime}
          duration={duration}
          onClose={toggleFullScreenPlayer}
          isShuffle={isShuffle}
        />
      )}

      {!isMobile && currentSong && (
        <PlaybackBar
          currentSong={currentSong}
          isPlaying={isPlaying}
          onPlayPause={handlePlayPause}
          onNextSong={handleNextSong}
          onPreviousSong={handlePreviousSong}
          onShuffle={handleShuffle}
          onRepeat={handleRepeat}
          onVolumeChange={handleVolumeChange}
          volume={volume}
          onFullScreen={toggleFullScreenPlayer}
          currentTime={currentTime}
          duration={duration}
          onProgressChange={handleProgressChange}
          isShuffle={isShuffle}
        />
      )}
    </div>
  );
};

export default App;


necesito que para mobile, la imagen arriba de time free, se vea un poco más grande