Displays albums in a new Recently played section on the homepage

This commit is contained in:
Justin Edmund 2024-07-30 23:04:58 -07:00
parent 00a9691363
commit 98ee4e810e
3 changed files with 187 additions and 0 deletions

View file

@ -0,0 +1,99 @@
<script lang="ts">
import { spring } from 'svelte/motion'
import type { Album } from '$lib/types/lastfm'
interface AlbumProps {
album?: Album
}
let { album = undefined }: AlbumProps = $props()
let isHovering = $state(false)
const scale = spring(1, {
stiffness: 0.2,
damping: 0.145
})
$effect(() => {
if (isHovering) {
scale.set(1.1)
} else {
scale.set(1)
}
})
</script>
<div class="album">
{#if album}
<a
href={album.url}
target="_blank"
rel="noopener noreferrer"
onmouseenter={() => (isHovering = true)}
onmouseleave={() => (isHovering = false)}
>
<img
src={album.images.itunes ? album.images.itunes : album.images.mega}
alt={album.name}
style="transform: scale({$scale})"
/>
<div class="info">
<span class="album-name">
{album.name}
</span>
<p class="artist-name">
{album.artist.name}
</p>
</div>
</a>
{:else}
<p>No album provided</p>
{/if}
</div>
<style lang="scss">
.album {
flex-basis: 100%;
a {
display: flex;
flex-direction: column;
gap: $unit * 1.5;
text-decoration: none;
transition: gap 0.125s ease-in-out;
img {
border: 1px solid rgba(0, 0, 0, 0.1);
border-radius: $unit;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.1);
width: 100%;
height: auto;
}
.info {
display: flex;
flex-direction: column;
gap: $unit-fourth;
p {
padding: 0;
margin: 0;
}
.album-name {
font-size: $font-size;
font-weight: $font-weight-med;
color: $accent-color;
}
.artist-name {
font-size: $font-size-small;
font-weight: $font-weight-med;
color: $grey-40;
}
}
}
}
</style>

View file

@ -1,9 +1,16 @@
<script lang="ts">
import Album from '$components/Album.svelte'
import Avatar from '$components/Avatar.svelte'
import MentionList from '$components/MentionList.svelte'
import Page from '$components/Page.svelte'
import ProjectList from '$components/ProjectList.svelte'
import Squiggly from '$components/Squiggly.svelte'
import type { PageData } from './$types'
export let data: PageData
$: ({ albums, error } = data)
</script>
<Page>
@ -44,6 +51,23 @@
<MentionList />
</Page>
<Page>
<svelte:fragment slot="header">
<Squiggly text="Now playing" />
</svelte:fragment>
<section class="weekly-albums">
{#if albums.length > 0}
<ul>
{#each albums.slice(0, 5) as album}
<Album {album} />
{/each}
</ul>
{:else}
<p>Loading albums...</p>
{/if}
</section>
</Page>
<footer>
<p>&copy; 2024 Justin Edmund</p>
@ -64,12 +88,62 @@
text-decoration-style: wavy;
}
header {
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: $unit-2x;
}
ul {
list-style: none;
margin: 0;
padding: 0;
}
.weekly-albums ul {
display: flex;
flex-direction: row;
gap: $unit-4x;
width: 100%;
li {
display: flex;
flex-basis: 100%;
flex-direction: column;
gap: $unit;
.info {
display: flex;
flex-direction: column;
gap: $unit-fourth;
p {
padding: 0;
margin: 0;
}
.album-name {
font-size: $font-size;
font-weight: $font-weight-med;
}
.artist-name {
font-size: $font-size-small;
font-weight: $font-weight-med;
color: $grey-40;
}
}
img {
border: 1px solid rgba(0, 0, 0, 0.1);
border-radius: $unit;
box-shadow: 0 0 8px rgba(0, 0, 0, 0.1);
width: 100%;
}
}
}
footer {
font-size: 0.85rem;
color: $grey-40;

14
src/routes/+page.ts Normal file
View file

@ -0,0 +1,14 @@
import type { PageLoad } from './$types'
import type { Album } from '$lib/types/lastfm'
export const load: PageLoad = async ({ fetch }) => {
try {
const response = await fetch('/api/lastfm')
if (!response.ok) throw new Error(`Failed to fetch albums: ${response.status}`)
const data: { albums: Album[] } = await response.json()
return { albums: data.albums }
} catch (err) {
console.error('Error fetching albums:', err)
return { albums: [], error: err instanceof Error ? err.message : 'An unknown error occurred' }
}
}