Skip to content

Commit

Permalink
feat: add link to url (#20)
Browse files Browse the repository at this point in the history
  • Loading branch information
Dun-sin authored Sep 3, 2024
1 parent 7e44ba9 commit 1d9eece
Show file tree
Hide file tree
Showing 22 changed files with 522 additions and 308 deletions.
6 changes: 3 additions & 3 deletions app/components/DiscoverTracks/ArtistType.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ const ArtistType = () => {
<span
className={`mt-2 flex items-center gap-2 max-w-[500px] flex-wrap`}>
{artistArray.map((value, index) => (
<div
key={index}
<button
key={value}
className={`bg-brand px-2 py-1 flex gap-2 w-fit items-center justify-center cursor-pointer rounded`}
onClick={(e) => handleArtistDelete(e, index)}>
<span className={`text-lightest text-fsm md:text-fxs`}>
Expand All @@ -77,7 +77,7 @@ const ArtistType = () => {
icon='iconoir:cancel'
className='text-lightest w-4 h-4'
/>
</div>
</button>
))}
</span>
)}
Expand Down
8 changes: 4 additions & 4 deletions app/components/DiscoverTracks/ChangeType.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,20 @@ const ChangeType = () => {
return (
<div
className={`w-5/12 max-w-[400px] min-w-[150px] flex items-center rounded p-1 dark:bg-lightest border-2 border-brand dark:border-0`}>
<p
<button
onClick={() => setType('artist')}
className={`${
type === 'artist' ? 'bg-brand text-lightest' : 'text-darkest'
} w-1/2 text-center text-fsm py-1 rounded-l cursor-pointer`}>
Artist
</p>
<p
</button>
<button
onClick={() => setType('playlist')}
className={`${
type === 'playlist' ? 'bg-brand text-lightest' : 'text-darkest'
} w-1/2 text-center text-fsm py-1 rounded-r cursor-pointer`}>
Playlist
</p>
</button>
</div>
);
};
Expand Down
20 changes: 12 additions & 8 deletions app/components/DiscoverTracks/SubmitButtion.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
'use client';

import {
addTracksToPlayList,
createPlayList,
getAllTracksInAPlaylist,
} from '@/app/lib/spotify';
import {
addToUrl,
extractPlaylistId,
getAllTracks,
getEveryAlbum,
isValidPlaylistLink,
} from '@/app/lib/utils';
import {
addTracksToPlayList,
createPlayList,
getAllTracksInAPlaylist,
} from '@/app/lib/spotify';

import { GoogleGenerativeAI } from '@google/generative-ai';
import React from 'react';
Expand Down Expand Up @@ -61,7 +62,7 @@ const SubmitButtion = () => {

setLoadingMessage(`Getting the list of new artists`);
const result = await model.generateContent(prompt);
``;

const response = await result.response;
const text = response.text();

Expand All @@ -71,7 +72,7 @@ const SubmitButtion = () => {

const finalList = lastPart ? lastPart.split(', ') : [];

finalList.length > 20 ? (finalList.length = 20) : null;
finalList.length > 20 && (finalList.length = 20);

setLoadingMessage(`Getting the albums of each artist`);
const albums = await getEveryAlbum(finalList);
Expand All @@ -97,7 +98,10 @@ const SubmitButtion = () => {

if (tracks === null) throw new Error('Track is empty');
addTracksToPlayList(tracks, playListID)
.then(() => setPlayListData({ link, name }))
.then(() => {
addToUrl('link', link.split('/').at(-1) as string);
setPlayListData({ link, name });
})
.catch((err) => {
return err;
});
Expand Down
4 changes: 2 additions & 2 deletions app/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ const Header = () => {
SignOut
</button>
)}
<div
<button
className='text-xl cursor-pointer rounded-full bg-brand p-1 text-lightest'
onClick={toggleDarkMode}>
{isDarkMode ? (
Expand All @@ -171,7 +171,7 @@ const Header = () => {
className='w-3 h-4 sm:w-6 sm:h-6'
/>
)}
</div>
</button>
<a
href='https://www.buymeacoffee.com/dunsinCodes'
target='_blank'
Expand Down
149 changes: 9 additions & 140 deletions app/components/OpenOnSpotify.tsx
Original file line number Diff line number Diff line change
@@ -1,41 +1,18 @@
import React, { useState } from 'react';

import { Icon } from '@iconify/react';
import Image from 'next/image';
import useViewPlaylist from '../hooks/useViewPlaylist';
import OpenPlaylist from './OpenOnSpotify/OpenPlaylist';
import { PlaylistViewProvider } from '../context/PlaylistViewContext';
import { useGeneralState } from '../context/generalStateContext';

function OpenOnSpotify({ link }: { link: string }) {
const {
showingTracks,
loading,
startedEditing,
tracksDeleted,
restoreSelectedTracks,
deleteTrack,
restoreAllTracks,
saveTracks,
} = useViewPlaylist(link);

const [restoreOption, setRestoreOption] = useState(false);
function OpenOnSpotify() {
const [openPlaylist, setOpenPlaylist] = useState(false);
const [selectedTracksToRestore, setSelectedTracksToRestore] = useState<
string[]
>([]);
const { playListData } = useGeneralState();

const handleClick = () => {
setOpenPlaylist(!openPlaylist);
};

const handleCheckboxChange = (id: string) => {
setSelectedTracksToRestore((prevSelectedTracks) => {
if (prevSelectedTracks.includes(id)) {
return prevSelectedTracks.filter((trackId) => trackId !== id);
} else {
return [...prevSelectedTracks, id];
}
});
};

return (
<>
<div
Expand All @@ -48,7 +25,7 @@ function OpenOnSpotify({ link }: { link: string }) {
<div className='flex gap-1 items-center'>
<Icon icon='logos:spotify-icon' width='30' height='30' />
<a
href={link}
href={playListData.link}
target='_blank'
rel='norefferer'
className='flex flex-col'>
Expand All @@ -65,118 +42,10 @@ function OpenOnSpotify({ link }: { link: string }) {
</button>
</div>
</div>
{openPlaylist && (
<section className='h-screen w-screen fixed left-0 top-0 bg-slate-500 bg-opacity-60 z-50 flex items-center justify-center'>
<div className='mt-6 relative bg-lightest dark:bg-darkest w-[90%] sm:w-3/5 rounded p-6 flex flex-col max-h-[90%] min-w-[300px]'>
<div className='flex items-center justify-between sticky top-0 w-full text-fmd pr-2 pb-2'>
<p>Edit Playlist Generated</p>

<button onClick={handleClick} className='flex gap-1 items-center'>
<Icon icon='iconoir:cancel' width='20' height='20' />
<span>Close</span>
</button>
</div>
<ul className='h-96 overflow-y-scroll px-4 list-decimal flex flex-col gap-2'>
{showingTracks.map(({ id, name, artist, image }) => {
return (
<li key={id} className='flex items-center sm:gap-4 gap-2'>
<section className='flex sm:gap-4 gap-2 w-full pr-2 hover:opacity-45'>
<div className='sm:h-10 sm:w-10 h-7 w-7 relative rounded-md overflow-hidden'>
<Image
src={image as string}
alt={name + ' track image'}
fill
/>
</div>
<div className='flex-1 max-w-[100px] sm:max-w-full'>
<p className='text-fbase truncate'>{name}</p>
<p className='truncate text-fsm opacity-75 -mt-1'>
{artist.join(', ')}
</p>
</div>
</section>
<button
className='flex items-center gap-1 hover:bg-red-500 transition-all bg-red-600 bg-opacity-65 text-lightest rounded px-2.5 py-1.5 sm:text-fbase text-fsm'
onClick={() => deleteTrack(id)}>
<Icon icon='mdi:delete' width='18' height='18' />
<span>Delete</span>
</button>
</li>
);
})}
</ul>
{startedEditing && (
<div className='pt-4 flex flex-col'>
<div className='flex items-center gap-2 ml-auto'>
<button
onClick={() => setRestoreOption(!restoreOption)}
className='flex items-center gap-1 text-fsm sm:text-fbase'>
<span>Select Songs to Restore</span>
{restoreOption ? (
<Icon icon='mingcute:up-line' />
) : (
<Icon icon='mingcute:down-line' />
)}
</button>
<button
onClick={saveTracks}
disabled={loading.isLoading}
className='bg-brand px-4 py-1 rounded text-lightest text-fsm sm:text-fbase'>
{loading.isLoading ? loading.message : 'Save'}
</button>
</div>
{restoreOption && (
<section className='overflow-y-auto'>
{tracksDeleted.length > 0 && (
<div className='flex items-center gap-5'>
<button
onClick={restoreAllTracks}
className='border-brand border-2 px-4 py-1 rounded text-fsm mb-3 transition-all hover:bg-brand hover:text-lightest'>
Restore All
</button>
{selectedTracksToRestore.length > 0 && (
<button
className='border-brand border-2 px-4 py-1 rounded text-fsm mb-3 transition-all hover:bg-brand hover:text-lightest'
onClick={() => {
restoreSelectedTracks(selectedTracksToRestore);
setSelectedTracksToRestore([]);
}}>
Restore Selected
</button>
)}
</div>
)}
<div className='grid sm:grid-cols-4 grid-cols-3 gap-y-2 pl-2'>
{tracksDeleted.map(({ name, id, artist }) => {
return (
<label
key={id}
htmlFor={name}
className='flex items-center gap-2'>
<input
type='checkbox'
name={name}
id={id}
className='rounded'
onChange={() => handleCheckboxChange(id)}
/>
<div className='flex flex-col justify-between w-full pr-2'>
<p className='text-fsm'>{name}</p>
<p className='truncate text-fxs opacity-75'>
{artist.join(', ')}
</p>
</div>
</label>
);
})}
</div>
</section>
)}
</div>
)}
</div>
</section>
)}
<PlaylistViewProvider>
{openPlaylist && <OpenPlaylist handleClick={handleClick} />}
</PlaylistViewProvider>
</>
);
};
Expand Down
37 changes: 37 additions & 0 deletions app/components/OpenOnSpotify/DeleteOptions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import { Icon } from '@iconify/react/dist/iconify.js';
import { usePlaylistView } from '@/app/context/PlaylistViewContext';

type DeleteOptionsTypes = {
restoreOption: boolean;
toggleRestoreOption: () => void;
};

const DeleteOptions = ({
restoreOption,
toggleRestoreOption,
}: DeleteOptionsTypes) => {
const { saveTracks, loading } = usePlaylistView();

return (
<div className='flex items-center gap-2 ml-auto'>
<button
onClick={toggleRestoreOption}
className='flex items-center gap-1 text-fsm sm:text-fbase'>
<span>Select Songs to Restore</span>
{restoreOption ? (
<Icon icon='mingcute:up-line' />
) : (
<Icon icon='mingcute:down-line' />
)}
</button>
<button
onClick={saveTracks}
disabled={loading.isLoading}
className='bg-brand px-4 py-1 rounded text-lightest text-fsm sm:text-fbase'>
{loading.isLoading ? loading.message : 'Save'}
</button>
</div>
);
};

export default DeleteOptions;
27 changes: 27 additions & 0 deletions app/components/OpenOnSpotify/OpenPlaylist.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Icon } from '@iconify/react/dist/iconify.js';
import { PlaylistViewProvider } from '@/app/context/PlaylistViewContext';
import StartedEditing from './StartedEditing';
import TrackList from './TrackList';

const OpenPlaylist = ({ handleClick }: { handleClick: () => void }) => {
return (
<PlaylistViewProvider>
<section className='h-screen w-screen fixed left-0 top-0 bg-slate-500 bg-opacity-60 z-50 flex items-center justify-center'>
<div className='mt-6 relative bg-lightest dark:bg-darkest w-[90%] sm:w-3/5 rounded p-6 flex flex-col max-h-[90%] min-w-[300px]'>
<div className='flex items-center justify-between sticky top-0 w-full text-fmd pr-2 pb-2'>
<p>Edit Playlist Generated</p>

<button onClick={handleClick} className='flex gap-1 items-center'>
<Icon icon='iconoir:cancel' width='20' height='20' />
<span>Close</span>
</button>
</div>
<TrackList />
<StartedEditing />
</div>
</section>
</PlaylistViewProvider>
);
};

export default OpenPlaylist;
33 changes: 33 additions & 0 deletions app/components/OpenOnSpotify/RestoreOptions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import React from 'react';
import { usePlaylistView } from '@/app/context/PlaylistViewContext';

type RestoreOptionsTypes = {
selectedTracksToRestore: string[];
handleRestoreSelected: () => void;
};

const RestoreOptions = ({
selectedTracksToRestore,
handleRestoreSelected,
}: RestoreOptionsTypes) => {
const { restoreAllTracks } = usePlaylistView();

return (
<div className='flex items-center gap-5'>
<button
onClick={restoreAllTracks}
className='border-brand border-2 px-4 py-1 rounded text-fsm mb-3 transition-all hover:bg-brand hover:text-lightest'>
Restore All
</button>
{selectedTracksToRestore.length > 0 && (
<button
className='border-brand border-2 px-4 py-1 rounded text-fsm mb-3 transition-all hover:bg-brand hover:text-lightest'
onClick={handleRestoreSelected}>
Restore Selected
</button>
)}
</div>
);
};

export default RestoreOptions;
Loading

0 comments on commit 1d9eece

Please sign in to comment.