tengo esto:

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";

// Función para formatear la duración total
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" | null>(null);

  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.sort((a, b) => a.age - b.age); // Ajusta el campo según necesites
    } else if (sortOrder === "desc") {
      sorted.sort((a, b) => b.age - a.age);
    }
    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;


y tengo esto:

// /components/Navbar.tsx

import React, { useState } from "react";
import { Search, X } from "lucide-react";
import { BiSortAZ, BiSortZA } from "react-icons/bi";
import { Input } from "./ui/input";

interface NavbarProps {
  searchValue: string;
  onSearchChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
  onClear: () => void;
  onSortAscending: () => void;
  onSortDescending: () => void;
}

const Navbar: React.FC<NavbarProps> = ({
  searchValue,
  onSearchChange,
  onClear,
  onSortAscending,
  onSortDescending,
}) => {
  const [isAscending, setIsAscending] = useState<boolean>(true);
  const [isLoading, setIsLoading] = useState<boolean>(false);

  const handleSort = async () => {
    setIsLoading(true);
    // Simular una operación de ordenación con un retraso de 500 ms
    await new Promise((resolve) => setTimeout(resolve, 500));
    if (isAscending) {
      onSortDescending();
    } else {
      onSortAscending();
    }
    setIsAscending(!isAscending);
    setIsLoading(false);
  };

  return (
    <div className="flex items-center p-4 bg-blue-800 bg-opacity-75 fixed top-0 left-0 right-0 z-50 backdrop-blur-lg transition-transform duration-300">
      {/* Buscador */}
      <div className="flex-1 mx-4">
        <div className="relative">
          <Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-5 w-5 text-gray-200" />

          <Input
            type="text"
            placeholder="Buscar"
            value={searchValue}
            onChange={onSearchChange}
            className="pl-10 pr-10 py-2 w-full bg-blue-700 bg-opacity-80 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-300 border-blue-300 border-2 text-white placeholder-gray-300"
          />

          {searchValue && (
            <button
              type="button"
              onClick={onClear}
              className="absolute right-3 top-1/2 transform -translate-y-1/2 text-gray-200 hover:text-white focus:outline-none"
              aria-label="Clear search"
            >
              <X className="h-5 w-5" />
            </button>
          )}
        </div>
      </div>

      {/* Botón de Ordenar */}
      <div className="relative mx-4">
        <button
          onClick={handleSort}
          disabled={isLoading}
          aria-label={`Sort ${isAscending ? "Descending" : "Ascending"}`}
          className="flex items-center gap-2 px-4 py-2 bg-gradient-to-r from-blue-500 to-blue-600 text-white rounded-lg
            hover:from-blue-600 hover:to-blue-700 focus:ring-4 focus:ring-blue-300 focus:outline-none
            transform transition-all duration-200 ease-in-out hover:scale-105
            disabled:opacity-50 disabled:cursor-not-allowed"
        >
          {isLoading ? (
            <div className="animate-spin rounded-full h-5 w-5 border-2 border-white border-t-transparent"></div>
          ) : (
            <>
              {isAscending ? <BiSortAZ size={20} /> : <BiSortZA size={20} />}
              <span>Ordenar</span>
            </>
          )}
        </button>
      </div>
    </div>
  );
};

export default Navbar;

lo que pasa es que tengo este error:

Property 'age' does not exist on type 'Song'.typescript(2339)
any