2022-07-02 15:19:41 +02:00
|
|
|
<script setup lang="ts">
|
2022-07-19 22:21:13 +02:00
|
|
|
import { $fetch } from 'ohmyfetch';
|
|
|
|
import AutoComplete from 'primevue/autocomplete';
|
|
|
|
|
|
|
|
import { SearchResult } from '~~/models/search-result';
|
2022-07-02 15:19:41 +02:00
|
|
|
|
|
|
|
const router = useRouter();
|
2022-07-19 22:21:13 +02:00
|
|
|
|
2022-07-20 21:40:17 +02:00
|
|
|
const searchHistory = useCookie<SearchResult[]>('searchHistory');
|
|
|
|
searchHistory.value = searchHistory.value || [];
|
|
|
|
|
2022-07-19 22:21:13 +02:00
|
|
|
const searchText = ref('');
|
|
|
|
const suggestions = ref([]);
|
|
|
|
|
2022-07-20 21:40:17 +02:00
|
|
|
// For some odd reason, if you don't do JSON.parse(JSON.stringify),
|
|
|
|
// suggestions ref won't get populated.
|
|
|
|
const displaySearchHistory = () =>
|
|
|
|
(suggestions.value = JSON.parse(JSON.stringify(searchHistory.value)));
|
|
|
|
|
2022-07-19 22:21:13 +02:00
|
|
|
const findPlaylists = async () => {
|
2022-07-20 21:40:17 +02:00
|
|
|
if (searchText.value.length === 0) return displaySearchHistory();
|
|
|
|
|
2022-07-19 22:21:13 +02:00
|
|
|
try {
|
|
|
|
const urlObject = new URL(searchText.value);
|
|
|
|
const [collectionName, playlistId] = urlObject.pathname
|
|
|
|
.split('/')
|
|
|
|
.filter(Boolean);
|
|
|
|
|
|
|
|
if (
|
|
|
|
urlObject.hostname === 'open.spotify.com' &&
|
|
|
|
collectionName === 'playlist' &&
|
|
|
|
playlistId
|
|
|
|
) {
|
|
|
|
const searchResults = await $fetch(
|
|
|
|
`https://raw.githubusercontent.com/mackorone/spotify-playlist-archive/main/playlists/pretty/${playlistId}.json`,
|
|
|
|
{
|
|
|
|
parseResponse: (body) =>
|
|
|
|
body === '404: Not Found'
|
|
|
|
? []
|
|
|
|
: [
|
|
|
|
{
|
|
|
|
id: playlistId,
|
|
|
|
title: JSON.parse(body).original_name
|
|
|
|
}
|
|
|
|
]
|
|
|
|
}
|
|
|
|
).catch((e) => e.data);
|
|
|
|
|
2022-07-20 21:40:17 +02:00
|
|
|
return (suggestions.value = searchResults);
|
2022-07-19 22:21:13 +02:00
|
|
|
} else {
|
|
|
|
throw new Error('This is not a valid playlist link');
|
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
if (error.message === 'This is not a valid playlist link') return [];
|
|
|
|
|
|
|
|
const searchResults = await $fetch<SearchResult[]>(
|
|
|
|
`/api/playlists/search?title=${searchText.value}`
|
|
|
|
);
|
|
|
|
|
2022-07-20 21:40:17 +02:00
|
|
|
return (suggestions.value = searchResults);
|
2022-07-02 15:19:41 +02:00
|
|
|
}
|
|
|
|
};
|
2022-07-19 22:21:13 +02:00
|
|
|
|
|
|
|
const openSnapshotsCalendar = async ({
|
|
|
|
value: entry
|
|
|
|
}: {
|
|
|
|
value: SearchResult;
|
|
|
|
}) => {
|
2022-07-20 21:40:17 +02:00
|
|
|
const existingHistoryEntry = searchHistory.value.find(
|
|
|
|
(e) => e.id === entry.id
|
|
|
|
);
|
|
|
|
|
|
|
|
if (searchHistory.value.length === 0 || !existingHistoryEntry) {
|
|
|
|
searchHistory.value.unshift(entry);
|
|
|
|
searchHistory.value = searchHistory.value.slice(0, 10);
|
|
|
|
}
|
|
|
|
|
2022-07-19 22:21:13 +02:00
|
|
|
await router.push(`/playlists/${entry.id}/snapshots`);
|
|
|
|
};
|
2022-07-02 15:19:41 +02:00
|
|
|
</script>
|
|
|
|
|
2022-06-29 09:51:44 +02:00
|
|
|
<template>
|
|
|
|
<NuxtLayout name="centered-content">
|
2022-07-20 21:40:17 +02:00
|
|
|
<h1 class="m-0 md:text-5xl text-4xl">Spotify Playlist Archive</h1>
|
2022-07-02 15:19:41 +02:00
|
|
|
<div class="flex flex-column justify-content-center text-center">
|
|
|
|
<p class="text-xl text-gray-300">
|
|
|
|
Browse past versions of thousands of playlists saved over time
|
|
|
|
</p>
|
2022-07-20 21:40:17 +02:00
|
|
|
<div class="w-full md:px-0 px-3">
|
2022-07-19 22:21:13 +02:00
|
|
|
<AutoComplete
|
|
|
|
v-model="searchText"
|
|
|
|
:suggestions="suggestions"
|
|
|
|
class="w-full"
|
|
|
|
placeholder="Type in at least 3 characters, or paste a playlist link"
|
|
|
|
field="title"
|
|
|
|
:min-length="3"
|
2022-07-20 21:40:17 +02:00
|
|
|
complete-on-focus
|
2022-07-19 22:21:13 +02:00
|
|
|
@complete="findPlaylists"
|
|
|
|
@item-select="openSnapshotsCalendar"
|
2022-07-02 15:19:41 +02:00
|
|
|
/>
|
2022-07-19 22:21:13 +02:00
|
|
|
</div>
|
2022-07-02 15:19:41 +02:00
|
|
|
</div>
|
2022-06-29 09:51:44 +02:00
|
|
|
</NuxtLayout>
|
|
|
|
</template>
|
2022-07-19 22:21:13 +02:00
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
:deep(.p-autocomplete-input) {
|
|
|
|
width: 100%;
|
|
|
|
text-align: center;
|
|
|
|
}
|
|
|
|
|
|
|
|
:deep(.p-autocomplete-input::placeholder) {
|
|
|
|
text-align: center;
|
|
|
|
}
|
|
|
|
</style>
|