Design Prot Merge #1
@@ -2,5 +2,5 @@ namespace Musify.Api.DataTransferObjects.PlayLists;
|
|||||||
|
|
||||||
public record CreatePlayListRequest(
|
public record CreatePlayListRequest(
|
||||||
string Name,
|
string Name,
|
||||||
string Description,
|
string? Description,
|
||||||
Guid? PictureIntentId);
|
Guid? PictureIntentId);
|
||||||
|
|||||||
@@ -181,12 +181,8 @@ public static class PlayListEndpoints
|
|||||||
CreatePlayListRequest request,
|
CreatePlayListRequest request,
|
||||||
CancellationToken cancellationToken)
|
CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var description = string.IsNullOrWhiteSpace(request.Description)
|
|
||||||
? "No description was provided."
|
|
||||||
: request.Description;
|
|
||||||
|
|
||||||
var result = await mediator.Send(
|
var result = await mediator.Send(
|
||||||
new CreatePlayListCommand(currentUser.RequiredId, request.Name, description, request.PictureIntentId),
|
new CreatePlayListCommand(currentUser.RequiredId, request.Name, request.Description, request.PictureIntentId),
|
||||||
cancellationToken);
|
cancellationToken);
|
||||||
|
|
||||||
return result.ToCreatedResult(playList => $"/playlists/{playList.Id}");
|
return result.ToCreatedResult(playList => $"/playlists/{playList.Id}");
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ namespace Musify.Application.PlayLists
|
|||||||
public record CreatePlayListCommand(
|
public record CreatePlayListCommand(
|
||||||
long UserId,
|
long UserId,
|
||||||
string Name,
|
string Name,
|
||||||
string Description,
|
string? Description,
|
||||||
Guid? PictureIntentId)
|
Guid? PictureIntentId)
|
||||||
: ICommand<ErrorOr<PlayListApplicationResponse>>;
|
: ICommand<ErrorOr<PlayListApplicationResponse>>;
|
||||||
|
|
||||||
@@ -58,7 +58,7 @@ namespace Musify.Application.PlayLists
|
|||||||
UserId = request.UserId,
|
UserId = request.UserId,
|
||||||
Name = request.Name,
|
Name = request.Name,
|
||||||
NormalizedName = request.Name.Trim().ToUpperInvariant(),
|
NormalizedName = request.Name.Trim().ToUpperInvariant(),
|
||||||
Description = request.Description,
|
Description = string.IsNullOrWhiteSpace(request.Description) ? null : request.Description.Trim(),
|
||||||
Pictures = pictureIntent == null ? null
|
Pictures = pictureIntent == null ? null
|
||||||
: new PlayListPictures { OriginalName = pictureIntent.ObjectName }
|
: new PlayListPictures { OriginalName = pictureIntent.ObjectName }
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
using Musify.Domain.Abstractions;
|
using Musify.Domain.Abstractions;
|
||||||
@@ -24,7 +24,6 @@ namespace Musify.Domain.Entities
|
|||||||
[MaxLength(50)]
|
[MaxLength(50)]
|
||||||
public required string NormalizedName { get; set; }
|
public required string NormalizedName { get; set; }
|
||||||
|
|
||||||
[Required]
|
|
||||||
[MaxLength(256)]
|
[MaxLength(256)]
|
||||||
public string? Description { get; set; }
|
public string? Description { get; set; }
|
||||||
|
|
||||||
|
|||||||
+1174
File diff suppressed because it is too large
Load Diff
+46
@@ -0,0 +1,46 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Musify.Infrastructure.Persistence.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class MakePlayListDescriptionOptional : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "Description",
|
||||||
|
table: "PlayLists",
|
||||||
|
type: "character varying(256)",
|
||||||
|
maxLength: 256,
|
||||||
|
nullable: true,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "character varying(256)",
|
||||||
|
oldMaxLength: 256);
|
||||||
|
|
||||||
|
migrationBuilder.Sql(
|
||||||
|
"""
|
||||||
|
UPDATE "PlayLists" SET "Description" = NULL
|
||||||
|
WHERE "Description" = 'No description was provided.';
|
||||||
|
""");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "Description",
|
||||||
|
table: "PlayLists",
|
||||||
|
type: "character varying(256)",
|
||||||
|
maxLength: 256,
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: "",
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "character varying(256)",
|
||||||
|
oldMaxLength: 256,
|
||||||
|
oldNullable: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -409,7 +409,6 @@ namespace Musify.Infrastructure.Persistence.Migrations
|
|||||||
.HasColumnType("timestamp with time zone");
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
b.Property<string>("Description")
|
b.Property<string>("Description")
|
||||||
.IsRequired()
|
|
||||||
.HasMaxLength(256)
|
.HasMaxLength(256)
|
||||||
.HasColumnType("character varying(256)");
|
.HasColumnType("character varying(256)");
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@
|
|||||||
<header
|
<header
|
||||||
class="sticky top-0 z-40 flex h-14 items-center justify-between border-b border-line bg-bg/85 page-x backdrop-blur-md md:hidden"
|
class="sticky top-0 z-40 flex h-14 items-center justify-between border-b border-line bg-bg/85 page-x backdrop-blur-md md:hidden"
|
||||||
>
|
>
|
||||||
<a href="/" class="text-lg font-extrabold tracking-wide">Musify</a>
|
<a href="/" class="text-lg font-semibold tracking-wide">Musify</a>
|
||||||
|
|
||||||
<div class="relative" bind:this={menuRef}>
|
<div class="relative" bind:this={menuRef}>
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import MediaCard from './MediaCard.svelte';
|
||||||
import PlaylistArt from './PlaylistArt.svelte';
|
import PlaylistArt from './PlaylistArt.svelte';
|
||||||
import Cover from './Cover.svelte';
|
import Cover from './Cover.svelte';
|
||||||
import { hueFor } from '$lib/theme/color';
|
import { hueFor } from '$lib/theme/color';
|
||||||
@@ -45,30 +46,25 @@
|
|||||||
);
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<a
|
<MediaCard
|
||||||
href={href ?? `/albums/${id}`}
|
href={href ?? `/albums/${id}`}
|
||||||
class="group animate-enter min-w-0 text-left"
|
{title}
|
||||||
style="animation-delay:{index * 45}ms"
|
subtitle={meta}
|
||||||
|
{index}
|
||||||
oncontextmenu={onContextMenu}
|
oncontextmenu={onContextMenu}
|
||||||
>
|
>
|
||||||
{#if coverSrc}
|
{#snippet art(artClass)}
|
||||||
<Cover
|
{#if coverSrc}
|
||||||
trackId={id}
|
<Cover
|
||||||
src={coverSrc}
|
trackId={id}
|
||||||
hue={hueFor(id)}
|
src={coverSrc}
|
||||||
size="large"
|
hue={hueFor(id)}
|
||||||
alt={title}
|
size="large"
|
||||||
class="aspect-square w-full rounded-art shadow-art transition group-hover:shadow-art-lg"
|
alt={title}
|
||||||
/>
|
class={artClass}
|
||||||
{:else}
|
/>
|
||||||
<PlaylistArt
|
{:else}
|
||||||
{trackIds}
|
<PlaylistArt {trackIds} hue={hueFor(id)} class={artClass} />
|
||||||
hue={hueFor(id)}
|
{/if}
|
||||||
class="aspect-square w-full rounded-art shadow-art transition group-hover:shadow-art-lg"
|
{/snippet}
|
||||||
/>
|
</MediaCard>
|
||||||
{/if}
|
|
||||||
<div class="mt-2.5 truncate text-fg">{title}</div>
|
|
||||||
{#if meta}
|
|
||||||
<div class="mt-0.5 truncate text-sm text-fg-3">{meta}</div>
|
|
||||||
{/if}
|
|
||||||
</a>
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
{#if title}
|
{#if title}
|
||||||
<h3 class="mt-5 text-2xl font-bold tracking-tight text-fg">{title}</h3>
|
<h3 class="mt-5 text-2xl font-semibold tracking-tight text-fg">{title}</h3>
|
||||||
{/if}
|
{/if}
|
||||||
{#if description}
|
{#if description}
|
||||||
<p class="mt-2 text-fg-2">{description}</p>
|
<p class="mt-2 text-fg-2">{description}</p>
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<script lang="ts" module>
|
||||||
|
export const mediaCardArt =
|
||||||
|
'aspect-square w-full rounded-art shadow-art transition duration-300 ease-out group-hover:-translate-y-1 group-hover:shadow-art-lg';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import type { Snippet } from 'svelte';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
href: string;
|
||||||
|
title: string;
|
||||||
|
subtitle?: string | null;
|
||||||
|
index?: number;
|
||||||
|
oncontextmenu?: (event: MouseEvent) => void;
|
||||||
|
art: Snippet<[string]>;
|
||||||
|
}
|
||||||
|
|
||||||
|
let { href, title, subtitle, index = 0, oncontextmenu, art }: Props = $props();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<a
|
||||||
|
{href}
|
||||||
|
class="group animate-enter min-w-0 text-left"
|
||||||
|
style="animation-delay:{index * 45}ms"
|
||||||
|
{oncontextmenu}
|
||||||
|
>
|
||||||
|
{@render art(mediaCardArt)}
|
||||||
|
<div class="mt-2.5 truncate text-fg transition-colors group-hover:text-accent-soft">{title}</div>
|
||||||
|
{#if subtitle}
|
||||||
|
<div class="mt-0.5 truncate text-sm text-fg-3">{subtitle}</div>
|
||||||
|
{/if}
|
||||||
|
</a>
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
let {
|
let {
|
||||||
as = 'div',
|
as = 'div',
|
||||||
min = '200px',
|
min = '165px',
|
||||||
minMobile = '150px',
|
minMobile = '150px',
|
||||||
class: klass = '',
|
class: klass = '',
|
||||||
children
|
children
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import MediaCard from './MediaCard.svelte';
|
||||||
import MixArt from './MixArt.svelte';
|
import MixArt from './MixArt.svelte';
|
||||||
import { hueFor } from '$lib/theme/color';
|
import { hueFor } from '$lib/theme/color';
|
||||||
import type { Mix } from '$lib/mixes';
|
import type { Mix } from '$lib/mixes';
|
||||||
@@ -13,19 +14,13 @@
|
|||||||
const count = $derived(Number(mix.itemCount));
|
const count = $derived(Number(mix.itemCount));
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<a
|
<MediaCard
|
||||||
href="/mixes/{mix.id}"
|
href="/mixes/{mix.id}"
|
||||||
class="group animate-enter min-w-0 text-left"
|
title={mix.title}
|
||||||
style="animation-delay:{index * 45}ms"
|
subtitle="{count} {count === 1 ? 'canción' : 'canciones'}"
|
||||||
|
{index}
|
||||||
>
|
>
|
||||||
<MixArt
|
{#snippet art(artClass)}
|
||||||
items={mix.items}
|
<MixArt items={mix.items} hue={hueFor(mix.id)} class={artClass} />
|
||||||
hue={hueFor(mix.id)}
|
{/snippet}
|
||||||
class="aspect-square w-full rounded-art shadow-art transition group-hover:shadow-art-lg"
|
</MediaCard>
|
||||||
/>
|
|
||||||
<div class="mt-2.5 truncate text-fg">{mix.title}</div>
|
|
||||||
<div class="mt-0.5 truncate text-sm text-fg-3">
|
|
||||||
{count}
|
|
||||||
{count === 1 ? 'canción' : 'canciones'}
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
|
|||||||
@@ -82,7 +82,7 @@
|
|||||||
>
|
>
|
||||||
{#if title}
|
{#if title}
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<h2 class="text-lg font-bold tracking-tight text-fg">{title}</h2>
|
<h2 class="text-lg font-semibold tracking-tight text-fg">{title}</h2>
|
||||||
<IconButton label="Cerrar" onclick={onClose}>
|
<IconButton label="Cerrar" onclick={onClose}>
|
||||||
<X class="h-4 w-4" />
|
<X class="h-4 w-4" />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
<div class="flex flex-col gap-4 sm:flex-row sm:items-end sm:justify-between {klass}">
|
<div class="flex flex-col gap-4 sm:flex-row sm:items-end sm:justify-between {klass}">
|
||||||
<div class="min-w-0">
|
<div class="min-w-0">
|
||||||
<h1 class="text-2xl font-bold tracking-tight text-fg sm:text-4xl">{title}</h1>
|
<h1 class="text-2xl font-semibold tracking-tight text-fg sm:text-4xl">{title}</h1>
|
||||||
{#if subtitle}
|
{#if subtitle}
|
||||||
<p class="mt-2 text-sm text-fg-2 sm:text-base">{subtitle}</p>
|
<p class="mt-2 text-sm text-fg-2 sm:text-base">{subtitle}</p>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import MediaCard from './MediaCard.svelte';
|
||||||
import PlaylistArt from './PlaylistArt.svelte';
|
import PlaylistArt from './PlaylistArt.svelte';
|
||||||
import { hueFor } from '$lib/theme/color';
|
import { hueFor } from '$lib/theme/color';
|
||||||
|
|
||||||
@@ -14,20 +15,8 @@
|
|||||||
let { id, name, description, trackIds, updatedAt, index = 0 }: Props = $props();
|
let { id, name, description, trackIds, updatedAt, index = 0 }: Props = $props();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<a
|
<MediaCard href="/playlists/{id}" title={name} subtitle={description} {index}>
|
||||||
href="/playlists/{id}"
|
{#snippet art(artClass)}
|
||||||
class="group animate-enter min-w-0 text-left"
|
<PlaylistArt playlistId={id} {trackIds} hue={hueFor(id)} version={updatedAt} class={artClass} />
|
||||||
style="animation-delay:{index * 45}ms"
|
{/snippet}
|
||||||
>
|
</MediaCard>
|
||||||
<PlaylistArt
|
|
||||||
playlistId={id}
|
|
||||||
{trackIds}
|
|
||||||
hue={hueFor(id)}
|
|
||||||
version={updatedAt}
|
|
||||||
class="aspect-square w-full rounded-art shadow-art transition group-hover:shadow-art-lg"
|
|
||||||
/>
|
|
||||||
<div class="mt-2.5 truncate text-fg">{name}</div>
|
|
||||||
{#if description}
|
|
||||||
<div class="mt-0.5 truncate text-sm text-fg-3">{description}</div>
|
|
||||||
{/if}
|
|
||||||
</a>
|
|
||||||
|
|||||||
@@ -11,10 +11,12 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if actions}
|
{#if actions}
|
||||||
<div class="mb-4 flex items-center justify-between gap-4 sm:mb-6 {klass}">
|
<div class="mb-3 flex items-baseline justify-between gap-4 sm:mb-4 {klass}">
|
||||||
<h2 class="text-xl font-bold text-fg sm:text-2xl">{title}</h2>
|
<h2 class="text-lg font-semibold tracking-tight text-fg sm:text-xl">{title}</h2>
|
||||||
{@render actions()}
|
{@render actions()}
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<h2 class="mb-4 text-xl font-bold text-fg sm:mb-6 sm:text-2xl {klass}">{title}</h2>
|
<h2 class="mb-3 text-lg font-semibold tracking-tight text-fg sm:mb-4 sm:text-xl {klass}">
|
||||||
|
{title}
|
||||||
|
</h2>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -77,7 +77,7 @@
|
|||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<Modal open={confirmingDelete} onClose={() => (confirmingDelete = false)} maxWidth="max-w-sm">
|
<Modal open={confirmingDelete} onClose={() => (confirmingDelete = false)} maxWidth="max-w-sm">
|
||||||
<h2 class="text-lg font-bold tracking-tight text-fg">
|
<h2 class="text-lg font-semibold tracking-tight text-fg">
|
||||||
¿Eliminar «{album.title}»?
|
¿Eliminar «{album.title}»?
|
||||||
</h2>
|
</h2>
|
||||||
<p class="mt-2 text-base text-fg-3">
|
<p class="mt-2 text-base text-fg-3">
|
||||||
|
|||||||
@@ -64,7 +64,7 @@
|
|||||||
<div class="min-w-0 flex-1">
|
<div class="min-w-0 flex-1">
|
||||||
<p class="text-sm tracking-[0.14em] text-fg-3 uppercase">Álbum</p>
|
<p class="text-sm tracking-[0.14em] text-fg-3 uppercase">Álbum</p>
|
||||||
<h1
|
<h1
|
||||||
class="mt-1.5 text-3xl font-bold tracking-tight break-words text-fg sm:text-5xl md:text-7xl"
|
class="mt-1.5 text-3xl font-semibold tracking-tight break-words text-fg sm:text-5xl md:text-7xl"
|
||||||
>
|
>
|
||||||
{title}
|
{title}
|
||||||
</h1>
|
</h1>
|
||||||
|
|||||||
@@ -103,7 +103,7 @@
|
|||||||
{album.isSingle ? 'Single' : album.isEp ? 'EP' : 'Álbum'} · YouTube Music
|
{album.isSingle ? 'Single' : album.isEp ? 'EP' : 'Álbum'} · YouTube Music
|
||||||
</p>
|
</p>
|
||||||
<h1
|
<h1
|
||||||
class="mt-1.5 text-3xl font-bold tracking-tight break-words text-fg sm:text-5xl md:text-7xl"
|
class="mt-1.5 text-3xl font-semibold tracking-tight break-words text-fg sm:text-5xl md:text-7xl"
|
||||||
>
|
>
|
||||||
{album.title}
|
{album.title}
|
||||||
</h1>
|
</h1>
|
||||||
|
|||||||
@@ -85,7 +85,7 @@
|
|||||||
<div class="min-w-0 flex-1">
|
<div class="min-w-0 flex-1">
|
||||||
<p class="text-sm tracking-[0.14em] text-fg-3 uppercase">Mezcla</p>
|
<p class="text-sm tracking-[0.14em] text-fg-3 uppercase">Mezcla</p>
|
||||||
<h1
|
<h1
|
||||||
class="mt-1.5 text-3xl font-bold tracking-tight break-words text-fg sm:text-5xl md:text-7xl"
|
class="mt-1.5 text-3xl font-semibold tracking-tight break-words text-fg sm:text-5xl md:text-7xl"
|
||||||
>
|
>
|
||||||
{mix.title}
|
{mix.title}
|
||||||
</h1>
|
</h1>
|
||||||
|
|||||||
@@ -79,7 +79,7 @@
|
|||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
<Modal open={confirmingDelete} onClose={() => (confirmingDelete = false)} maxWidth="max-w-sm">
|
<Modal open={confirmingDelete} onClose={() => (confirmingDelete = false)} maxWidth="max-w-sm">
|
||||||
<h2 class="text-lg font-bold tracking-tight text-fg">
|
<h2 class="text-lg font-semibold tracking-tight text-fg">
|
||||||
¿Eliminar «{playlist.name}»?
|
¿Eliminar «{playlist.name}»?
|
||||||
</h2>
|
</h2>
|
||||||
<p class="mt-2 text-base text-fg-3">
|
<p class="mt-2 text-base text-fg-3">
|
||||||
|
|||||||
@@ -46,7 +46,7 @@
|
|||||||
<div class="min-w-0 flex-1">
|
<div class="min-w-0 flex-1">
|
||||||
<p class="text-sm tracking-[0.14em] text-fg-3 uppercase">Lista</p>
|
<p class="text-sm tracking-[0.14em] text-fg-3 uppercase">Lista</p>
|
||||||
<h1
|
<h1
|
||||||
class="mt-1.5 text-3xl font-bold tracking-tight break-words text-fg sm:text-5xl md:text-7xl"
|
class="mt-1.5 text-3xl font-semibold tracking-tight break-words text-fg sm:text-5xl md:text-7xl"
|
||||||
>
|
>
|
||||||
{name}
|
{name}
|
||||||
</h1>
|
</h1>
|
||||||
|
|||||||
@@ -141,7 +141,7 @@
|
|||||||
>
|
>
|
||||||
<Check class="h-8 w-8" strokeWidth={2.5} />
|
<Check class="h-8 w-8" strokeWidth={2.5} />
|
||||||
</span>
|
</span>
|
||||||
<h2 class="mt-6 text-2xl font-bold tracking-tight text-fg">¡Subida!</h2>
|
<h2 class="mt-6 text-2xl font-semibold tracking-tight text-fg">¡Subida!</h2>
|
||||||
<p class="mt-3 text-fg-2">
|
<p class="mt-3 text-fg-2">
|
||||||
«{publishedTitle}» se está procesando. Aparecerá lista para reproducir en tu biblioteca en
|
«{publishedTitle}» se está procesando. Aparecerá lista para reproducir en tu biblioteca en
|
||||||
unos momentos.
|
unos momentos.
|
||||||
|
|||||||
@@ -178,14 +178,14 @@
|
|||||||
></div>
|
></div>
|
||||||
<div class="animate-enter relative flex flex-col gap-2 sm:gap-2.5">
|
<div class="animate-enter relative flex flex-col gap-2 sm:gap-2.5">
|
||||||
<p class="text-sm tracking-[0.14em] text-fg-2 uppercase sm:text-base">{data.greeting}</p>
|
<p class="text-sm tracking-[0.14em] text-fg-2 uppercase sm:text-base">{data.greeting}</p>
|
||||||
<h1 class="max-w-160 text-3xl leading-[1.05] font-extrabold text-fg sm:text-5xl">
|
<h1 class="max-w-160 text-3xl leading-[1.05] font-semibold text-fg sm:text-5xl">
|
||||||
Tu música. Sin límites.
|
Tu música. Sin límites.
|
||||||
</h1>
|
</h1>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{#if recentlyPlayed.length > 0}
|
{#if recentlyPlayed.length > 0}
|
||||||
<section class="page-x pt-5 pb-3 sm:pt-6">
|
<section class="page-x pt-10 sm:pt-14">
|
||||||
<SectionHeading title="Volver a escuchar" />
|
<SectionHeading title="Volver a escuchar" />
|
||||||
<MediaGrid min="280px" minMobile="220px">
|
<MediaGrid min="280px" minMobile="220px">
|
||||||
{#each recentlyPlayed as track, i (track.id)}
|
{#each recentlyPlayed as track, i (track.id)}
|
||||||
@@ -228,7 +228,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if mixes.length > 0 || playlists.length > 0}
|
{#if mixes.length > 0 || playlists.length > 0}
|
||||||
<section class="grid gap-x-8 gap-y-5 page-x pt-5 pb-3 sm:pt-6 lg:grid-cols-2">
|
<section class="grid gap-x-8 gap-y-10 page-x pt-10 sm:pt-14 lg:grid-cols-2">
|
||||||
{#if mixes.length > 0}
|
{#if mixes.length > 0}
|
||||||
<div class="min-w-0">
|
<div class="min-w-0">
|
||||||
<SectionHeading title="Hechas para ti" />
|
<SectionHeading title="Hechas para ti" />
|
||||||
@@ -269,7 +269,7 @@
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if albums.length > 0}
|
{#if albums.length > 0}
|
||||||
<section class="page-x pt-5 pb-3 sm:pt-6">
|
<section class="page-x pt-10 sm:pt-14">
|
||||||
<SectionHeading title="Álbumes escuchados recientemente">
|
<SectionHeading title="Álbumes escuchados recientemente">
|
||||||
{#snippet actions()}
|
{#snippet actions()}
|
||||||
<a href="/albums" class="text-sm text-fg-3 transition hover:text-accent-soft">Ver todos</a>
|
<a href="/albums" class="text-sm text-fg-3 transition hover:text-accent-soft">Ver todos</a>
|
||||||
@@ -290,7 +290,7 @@
|
|||||||
</section>
|
</section>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<section class="page-x pt-5 pb-10 sm:pt-6">
|
<section class="page-x pt-10 pb-16 sm:pt-14">
|
||||||
<SectionHeading title="Descubrir" />
|
<SectionHeading title="Descubrir" />
|
||||||
{#if latest.length > 0}
|
{#if latest.length > 0}
|
||||||
<MediaGrid as="ul">
|
<MediaGrid as="ul">
|
||||||
@@ -299,6 +299,7 @@
|
|||||||
id={targetId(item)}
|
id={targetId(item)}
|
||||||
title={targetTitle(item)}
|
title={targetTitle(item)}
|
||||||
artist={targetArtist(item)}
|
artist={targetArtist(item)}
|
||||||
|
coverShape="round"
|
||||||
coverSrc={targetCoverSrc(item)}
|
coverSrc={targetCoverSrc(item)}
|
||||||
hue={hueFor(targetId(item))}
|
hue={hueFor(targetId(item))}
|
||||||
explicit={targetExplicit(item)}
|
explicit={targetExplicit(item)}
|
||||||
|
|||||||
@@ -13,10 +13,10 @@
|
|||||||
|
|
||||||
<div class="grid min-h-screen place-items-center bg-bg px-6 text-fg">
|
<div class="grid min-h-screen place-items-center bg-bg px-6 text-fg">
|
||||||
<div class="flex w-full max-w-110 flex-col items-center gap-9 text-center">
|
<div class="flex w-full max-w-110 flex-col items-center gap-9 text-center">
|
||||||
<div class="text-3xl font-extrabold tracking-tight">Musify</div>
|
<div class="text-3xl font-semibold tracking-tight">Musify</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
<h1 class="text-4xl font-extrabold tracking-tight">Tu música. Sin límites.</h1>
|
<h1 class="text-4xl font-semibold tracking-tight">Tu música. Sin límites.</h1>
|
||||||
<p class="mt-3 text-base text-fg-2">Inicia sesión para continuar.</p>
|
<p class="mt-3 text-base text-fg-2">Inicia sesión para continuar.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user