diff --git a/src/api/operations.ts b/src/api/operations.ts index fa18b0b..14561f3 100644 --- a/src/api/operations.ts +++ b/src/api/operations.ts @@ -1,6 +1,11 @@ import { AxiosResponse } from "axios"; import { apiRespBaseType, axiosInstance } from "./axiosInstance"; -import { opFetchGraphURL, opUpdateUserDataURL } from "./paths"; +import { + opCreateLinkURL, + opDeleteLinkURL, + opFetchGraphURL, + opUpdateUserDataURL, +} from "./paths"; interface fetchGraphDataType extends apiRespBaseType { playlists?: { @@ -17,6 +22,13 @@ interface updateUserDataType extends apiRespBaseType { removedLinks: boolean; } +type createLinkBodyType = { + from: string; // playlistID + to: string; // playlistID +}; + +type deleteLinkBodyType = createLinkBodyType; + export const apiFetchGraph = async (): Promise< AxiosResponse > => { @@ -38,3 +50,25 @@ export const apiUpdateUserData = async (): Promise< return error.response; } }; + +export const apiCreateLink = async ( + data: createLinkBodyType +): Promise> => { + try { + const response = await axiosInstance.post(opCreateLinkURL, data); + return response; + } catch (error: any) { + return error.response; + } +}; + +export const apiDeleteLink = async ( + data: deleteLinkBodyType +): Promise> => { + try { + const response = await axiosInstance.delete(opDeleteLinkURL, { data }); + return response; + } catch (error: any) { + return error.response; + } +}; diff --git a/src/api/paths.ts b/src/api/paths.ts index 8f6d834..38cb629 100644 --- a/src/api/paths.ts +++ b/src/api/paths.ts @@ -8,3 +8,5 @@ export const authRefreshURL = "api/auth/refresh"; export const opFetchGraphURL = "api/operations/fetch"; export const opUpdateUserDataURL = "api/operations/update"; +export const opCreateLinkURL = "api/operations/link"; +export const opDeleteLinkURL = opCreateLinkURL; diff --git a/src/components/APIWrapper/index.tsx b/src/components/APIWrapper/index.tsx index f70e69a..6ddf35c 100644 --- a/src/components/APIWrapper/index.tsx +++ b/src/components/APIWrapper/index.tsx @@ -35,7 +35,7 @@ const APIWrapper = async ({ if (apiResp === undefined) { showErrorToastNotification("Please try again after sometime"); - } else if (apiResp.status === 200) { + } else if (apiResp.status >= 200 && apiResp.status < 300) { return apiResp; } else if (apiResp.status === 401) { showWarnToastNotification("Session expired, refreshing..."); @@ -43,6 +43,9 @@ const APIWrapper = async ({ showErrorToastNotification("Session invalid."); return; } + } else if (apiResp.status >= 400 && apiResp.status < 500) { + showErrorToastNotification(apiResp.data.message); + return; // no retry on 4XX } else { showErrorToastNotification(apiResp.data.message); } diff --git a/src/pages/Graph/index.tsx b/src/pages/Graph/index.tsx index 556f455..e6e717f 100644 --- a/src/pages/Graph/index.tsx +++ b/src/pages/Graph/index.tsx @@ -35,10 +35,16 @@ import { AiFillSpotify } from "react-icons/ai"; import { showErrorToastNotification, showInfoToastNotification, + showSuccessToastNotification, showWarnToastNotification, } from "../../components/ToastNotification"; -import { apiFetchGraph, apiUpdateUserData } from "../../api/operations"; +import { + apiCreateLink, + apiDeleteLink, + apiFetchGraph, + apiUpdateUserData, +} from "../../api/operations"; import { RefreshAuthContext } from "../../App"; import Button from "../../components/Button"; @@ -125,10 +131,26 @@ const Graph = () => { [] ); - const onFlowAfterDelete: OnDelete = useCallback(({ nodes, edges }) => { - console.debug("deleted edges"); - console.debug(edges); - }, []); + const onFlowAfterDelete: OnDelete = useCallback( + async ({ nodes, edges }) => { + console.debug( + `deleted connection: ${edges[0].source} -> ${edges[0].target}` + ); + // call API to delete link + const spotifyPlaylistLinkPrefix = "https://open.spotify.com/playlist/"; + const resp = await APIWrapper({ + apiFn: apiDeleteLink, + data: { + from: spotifyPlaylistLinkPrefix + edges[0].source, + to: spotifyPlaylistLinkPrefix + edges[0].target, + }, + refreshAuth, + }); + if (resp?.status === 200) + showSuccessToastNotification(resp?.data.message); + }, + [refreshAuth] + ); // base event handling const onNodesChange: OnNodesChange = useCallback( @@ -141,14 +163,25 @@ const Graph = () => { ); const onConnect: OnConnect = useCallback( - (connection) => { + async (connection) => { setLinkEdges((eds) => addEdge(connection, eds)); console.debug( `new connection: ${connection.source} -> ${connection.target}` ); // call API to create link + const spotifyPlaylistLinkPrefix = "https://open.spotify.com/playlist/"; + const resp = await APIWrapper({ + apiFn: apiCreateLink, + data: { + from: spotifyPlaylistLinkPrefix + connection.source, + to: spotifyPlaylistLinkPrefix + connection.target, + }, + refreshAuth, + }); + if (resp?.status === 201) + showSuccessToastNotification(resp?.data.message); }, - [setLinkEdges] + [setLinkEdges, refreshAuth] ); type getLayoutedElementsOpts = {