release/0.1.0 #18
1 changed files with 74 additions and 39 deletions
|
|
@ -1,11 +1,18 @@
|
|||
import { useState } from "react"
|
||||
import { Link } from "wouter"
|
||||
import { motion } from "framer-motion"
|
||||
import { Crown, ExternalLink, Music } from "lucide-react"
|
||||
import type { PlayerScore, RoomSnapshot } from "@nerdware/shared"
|
||||
import { Check, ClipboardList, Crown, ExternalLink, Music, Music2 } from "lucide-react"
|
||||
import type { BlindtestTrackInfo, PlayerScore, RoomSnapshot } from "@nerdware/shared"
|
||||
import { Button } from "@workspace/ui/components/button"
|
||||
import { useRoomStore } from "@/store/room"
|
||||
import { Avatar } from "@/components/avatar"
|
||||
|
||||
/** Lien de recherche Spotify (le titre vidéo contient en général artiste + chanson). */
|
||||
function spotifySearch(track: BlindtestTrackInfo): string {
|
||||
const query = `${track.title} ${track.artist}`.trim()
|
||||
return `https://open.spotify.com/search/${encodeURIComponent(query)}`
|
||||
}
|
||||
|
||||
type Place = 1 | 2 | 3
|
||||
|
||||
// Hauteur de marche, couleurs (or / argent / bronze) et taille d'avatar par place.
|
||||
|
|
@ -198,43 +205,7 @@ export function GameEndView({ snapshot }: { snapshot: RoomSnapshot }) {
|
|||
)}
|
||||
|
||||
{gameTracks && gameTracks.length > 0 && (
|
||||
<section className="flex flex-col gap-2 text-left">
|
||||
<h3 className="text-muted-foreground flex items-center gap-1.5 text-sm font-medium">
|
||||
<Music className="size-4" /> Les musiques de la partie
|
||||
</h3>
|
||||
<ul className="flex flex-col gap-2">
|
||||
{gameTracks.map((t) => (
|
||||
<li
|
||||
key={t.youtubeId}
|
||||
className="bg-muted/40 flex items-center gap-3 rounded-lg p-2"
|
||||
>
|
||||
<img
|
||||
src={`https://img.youtube.com/vi/${t.youtubeId}/mqdefault.jpg`}
|
||||
alt=""
|
||||
className="h-10 w-16 shrink-0 rounded object-cover"
|
||||
/>
|
||||
<span className="min-w-0 flex-1">
|
||||
<span className="line-clamp-1 text-xs font-medium">
|
||||
{t.title}
|
||||
</span>
|
||||
<span className="text-muted-foreground line-clamp-1 text-[10px]">
|
||||
ajouté par {t.submittedByName}
|
||||
</span>
|
||||
</span>
|
||||
<a
|
||||
href={t.url}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
title="Ouvrir sur YouTube"
|
||||
>
|
||||
<Button size="icon-sm" variant="secondary">
|
||||
<ExternalLink />
|
||||
</Button>
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</section>
|
||||
<TracksRecap tracks={gameTracks} />
|
||||
)}
|
||||
|
||||
<div className="flex flex-col gap-2">
|
||||
|
|
@ -256,3 +227,67 @@ export function GameEndView({ snapshot }: { snapshot: RoomSnapshot }) {
|
|||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
function TracksRecap({ tracks }: { tracks: BlindtestTrackInfo[] }) {
|
||||
const [copied, setCopied] = useState(false)
|
||||
|
||||
async function copyPlaylist() {
|
||||
const text = tracks.map((t) => `${t.title} — ${t.artist}`).join("\n")
|
||||
try {
|
||||
await navigator.clipboard.writeText(text)
|
||||
setCopied(true)
|
||||
setTimeout(() => setCopied(false), 1500)
|
||||
} catch {
|
||||
// presse-papier indisponible : on ignore
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<section className="flex flex-col gap-2 text-left">
|
||||
<div className="flex items-center justify-between">
|
||||
<h3 className="text-muted-foreground flex items-center gap-1.5 text-sm font-medium">
|
||||
<Music className="size-4" /> Les musiques de la partie
|
||||
</h3>
|
||||
<Button size="sm" variant="secondary" onClick={copyPlaylist}>
|
||||
{copied ? <Check className="text-green-500" /> : <ClipboardList />}
|
||||
{copied ? "Copié" : "Playlist"}
|
||||
</Button>
|
||||
</div>
|
||||
<ul className="flex flex-col gap-2">
|
||||
{tracks.map((t) => (
|
||||
<li
|
||||
key={t.youtubeId}
|
||||
className="bg-muted/40 flex items-center gap-3 rounded-lg p-2"
|
||||
>
|
||||
<img
|
||||
src={`https://img.youtube.com/vi/${t.youtubeId}/mqdefault.jpg`}
|
||||
alt=""
|
||||
className="h-10 w-16 shrink-0 rounded object-cover"
|
||||
/>
|
||||
<span className="min-w-0 flex-1">
|
||||
<span className="line-clamp-1 text-xs font-medium">{t.title}</span>
|
||||
<span className="text-muted-foreground line-clamp-1 text-[10px]">
|
||||
ajouté par {t.submittedByName}
|
||||
</span>
|
||||
</span>
|
||||
<a
|
||||
href={spotifySearch(t)}
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
title="Chercher sur Spotify"
|
||||
>
|
||||
<Button size="icon-sm" className="bg-green-600 hover:bg-green-500">
|
||||
<Music2 />
|
||||
</Button>
|
||||
</a>
|
||||
<a href={t.url} target="_blank" rel="noreferrer" title="Ouvrir sur YouTube">
|
||||
<Button size="icon-sm" variant="secondary">
|
||||
<ExternalLink />
|
||||
</Button>
|
||||
</a>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</section>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue