Comprehensive admin + user dashboards (production-ready)

This commit is contained in:
Leon Serfaty
2026-06-07 17:54:30 -04:00
parent 155507f21a
commit f033f00379
122 changed files with 7878 additions and 805 deletions
+13 -25
View File
@@ -1,39 +1,27 @@
"use client";
import { Download } from "lucide-react";
import { Button } from "@/components/ui/button";
function formatDuration(sec?: number | null): string {
if (!sec) return "";
const m = Math.floor(sec / 60);
const s = sec % 60;
return `${m}:${String(s).padStart(2, "0")}`;
}
import { WaveformPlayer } from "./waveform-player";
/**
* Episode audio player — a thin wrapper around the custom WaveformPlayer so the
* authed asset route and (optional) ZIP export are wired up for the editor.
*/
export function AudioPlayer({
storageKey,
durationSec,
episodeId,
}: {
storageKey: string;
durationSec?: number | null;
episodeId?: string;
}) {
const src = `/api/assets/${storageKey}`;
return (
<div className="space-y-3">
{/* eslint-disable-next-line jsx-a11y/media-has-caption */}
<audio controls src={src} className="w-full" preload="metadata" />
<div className="flex items-center justify-between">
{durationSec ? (
<span className="text-xs text-muted-foreground">Length {formatDuration(durationSec)}</span>
) : (
<span />
)}
<Button asChild variant="outline" size="sm">
<a href={`${src}?download=1`} download>
<Download className="h-4 w-4" /> Download MP3
</a>
</Button>
</div>
</div>
<WaveformPlayer
src={src}
downloadUrl={`${src}?download=1`}
durationSec={durationSec}
exportUrl={episodeId ? `/api/episodes/${episodeId}/export` : undefined}
/>
);
}