En el archivo ReplaceVideosPage.tsx hay un botón que dice “Replace all playlist items”, cuando se presiona se activa una API, quiero que en el texto de la etiqueta PRE se muestre el texto de cada video agregao correctametne a ala playlist “Added ${countIds} of ${videoIds.length}: ${videoId}” de la respuesta del archivo “src\services\addVideosToPlaylist.js”

// src\features\playlist-management\components\ReplaceVideosPage.tsx

import { useEffect, useState } from “react”;
import extractIDsFromUrls from “…/…/…/services/extractIDsFromUrls”;
import CustomButton from “./CustomButton”;
import CustomTextarea from “./CustomTextarea”;
import CustomInput from “./CustomInput”;

const ReplaceVideosPage = () => {
  const [youtubeUrls, setYoutubeUrls] = useState<string>(“”);
  const [videoIds, setVideoIds] = useState<string[]>([]);
  const [customPlaylistID, setCustomPlaylistId] = useState<string>(“”);
  const [isLoading, setIsLoading] = useState<boolean>(false);

  const replacePlaylistData = async () => {
    try {
      setIsLoading(true);
      const responseGet = await fetch(/api/playlists/${customPlaylistID});

      if (!responseGet.ok) {
        throw new Error(
          Get Playlist API request failed: ${responseGet.status}
        );
      }

      const dataGet = await responseGet.json();
      const allIDs = dataGet.allItems.map((item: { id: string }) => item.id);
      const IDsToAdd = videoIds.filter((id) => !allIDs.includes(id));
      const IDsToRemove = allIDs.filter((id: string) => !videoIds.includes(id));

      const responseCreate = await fetch(
        /api/createPlaylist?newItems=${encodeURIComponent(<br/>          JSON.stringify(IDsToAdd)<br/>        )}&customPlaylistId=${customPlaylistID}
      );

      if (!responseCreate.ok) {
        throw new Error(
          Create Playlist API request failed: ${responseCreate.status}
        );
      }

      const responseDelete = await fetch(
        /api/deleteFromPlaylist?newItems=${encodeURIComponent(<br/>          JSON.stringify(IDsToRemove)<br/>        )}&customPlaylistId=${customPlaylistID}
      );

      if (!responseDelete.ok) {
        throw new Error(
          Delete Playlist API request failed: ${responseDelete.status}
        );
      }

      setIsLoading(false);
    } catch (error) {
      console.error(“Error processing Replace Playlist API:”, error);
    }
  };

  useEffect(() => {
    setVideoIds(extractIDsFromUrls(youtubeUrls));
  }, [youtubeUrls]);

  return (
    <main className=“w-full max-w-lg mx-auto my-8 flex flex-col gap-4”>
      <CustomInput
        title=“Required Playlist ID*”
        onChangeHandler={setCustomPlaylistId}
        inputValue={customPlaylistID}
      />
      <CustomTextarea
        onChangeHandler={setYoutubeUrls}
        placeholder=“Enter youtube links…”
        textareaValue={youtubeUrls}
      />
      {videoIds.length > 0 && (
        <>
          <p># ID: {videoIds.length}</p>
          <CustomButton
            buttonText={
              isLoading ? “Cargando…” : “Replace all playlist items”
            }
            isLoading={isLoading}
            onClickHandler={replacePlaylistData}
          />
        </>
      )}
      <div className=“bg-gray-300 p-4 rounded-md”>
        <pre className=“text-sm font-mono”>
          <code className=“block”>Tu código aquí…</code>
        </pre>
      </div>
    </main>
  );
};

export default ReplaceVideosPage;

// src\pages\api\createPlaylist.ts

import { google } from “googleapis”;
import { promises as fs } from “fs”;
import {
  CLIENT_ID,
  CLIENT_SECRET,
  REDIRECTION_URI,
} from “…/…/models/credentials”;
import createPlaylist from “…/…/services/createPlaylist”;

const oAuth2Client: any = new google.auth.OAuth2(
  CLIENT_ID,
  CLIENT_SECRET,
  REDIRECTION_URI
);

export default async function handler(req: any, res: any) {
  try {
    const {
      newItems,
      customPlaylistId,
    }: { newItems: string; customPlaylistId?: string } = req.query;

    const token: any = await fs.readFile(“token.json”);
    const parsedToken = JSON.parse(token);
    oAuth2Client.setCredentials(parsedToken);

    const newPlaylistId = await createPlaylist({
      auth: oAuth2Client,
      newItems,
      customPlaylistId,
    });

    res
      .status(200)
      .json({ message: “Playlist created successfully”, newPlaylistId });
  } catch (error) {
    console.error(“Error:”, error);
    res.status(500).json({ error: “Internal Server Error” });
  }
}

// src\services\createPlaylist.ts

import { google } from “googleapis”;
import addVideosToPlaylist from “./addVideosToPlaylist”;

interface CreatePlaylistData {
  auth: any;
  newItems: string;
  customPlaylistId?: string;
}

async function createPlaylist({
  auth,
  newItems,
  customPlaylistId,
}: CreatePlaylistData): Promise<string> {
  const youtube: any = google.youtube({ version: “v3”, auth });

  try {
    let playlistId: string;
    let videoIds: string[] = JSON.parse(newItems);

    if (customPlaylistId) {
      playlistId = customPlaylistId;
      console.log(“Using custom playlist ID:”, playlistId);

      const getPlaylistData = async (): Promise<string[]> => {
        try {
          const response = await fetch(
            http://localhost:3000/api/playlists/${playlistId}
          );

          if (!response.ok) {
            throw new Error(
              API request failed with status ${response.status}
            );
          }

          const data = await response.json();
          const allIDs = data.allItems.map((item: any) => item.id);

          videoIds = videoIds.filter((videoId) => !allIDs.includes(videoId));
          return videoIds;
        } catch (error) {
          console.error(“Error fetching playlist data:”, error);
          return [];
        }
      };

      videoIds = await getPlaylistData();
    } else {
      const res = await youtube.playlists.insert({
        part: [“snippet,status”],
        resource: {
          snippet: {
            title: “Música”,
            description: “Descripción”,
            tags: [“Music”],
            defaultLanguage: “es_MX”,
          },
          status: {
            privacyStatus: “unlisted”,
          },
        },
      });

      playlistId = res.data.id;
      console.log(“Playlist created:”, playlistId);
    }

    await addVideosToPlaylist(auth, playlistId, videoIds);

    return playlistId;
  } catch (err) {
    console.error(“Error creating playlist:”, err);
    throw err;
  }
}

export default createPlaylist;


//  src\services\addVideosToPlaylist.js

const { google } = require(“googleapis”);

async function addVideosToPlaylist(auth, playlistId, videoIds) {
  const youtube = google.youtube({
    version: “v3”,
    auth,
  });

  console.log(Adding ${videoIds.length} videos to playlist.);
  let failedItems = 0;
  let countIds = 0;

  for (const videoId of videoIds) {
    countIds++;
    try {
      await youtube.playlistItems.insert({
        part: [“snippet”],
        resource: {
          snippet: {
            playlistId: playlistId,
            resourceId: {
              kind: “youtube#video”,
              videoId: videoId,
            },
          },
        },
      });
      console.log(Added ${countIds} of ${videoIds.length}: ${videoId});
    } catch (err) {
      console.error(Error ${countIds} of ${videoIds.length}: ${videoId});
      failedItems++;
    }
  }

  console.log(
    ${videoIds.length - failedItems} video(s) added to playlist successfully.
  );
  failedItems && console.log(${failedItems} video(s) failed.);
}

module.exports = addVideosToPlaylist;