Vertical.ai / frontend /src /components /AudioPlayerModal.jsx
Abhisingh-18's picture
Mirror of github.com/Abhisingh18/Vertical.ai
1f7ead8 verified
Raw
History Blame Contribute Delete
5.91 kB
import React, { useState } from 'react';
import { X, Play, Square, Download, Clock, Loader2 } from 'lucide-react';
import { generateAudio } from '../api';
const AudioPlayerModal = ({ isOpen, onClose, script }) => {
const [generating, setGenerating] = useState(false);
const [audioUrl, setAudioUrl] = useState(null);
const [error, setError] = useState(null);
// Backend URL might be needed if audioUrl is relative
const BACKEND_URL = import.meta.env.VITE_BACKEND_URL || 'http://localhost:8000';
if (!isOpen) return null;
const handleGenerate = async () => {
setGenerating(true);
setError(null);
try {
const result = await generateAudio(script);
// Result.audio_url should be relative like /static/audio/...
// We prepend backend URL if it's not absolute (or use it directly if simple img tag, but audio src needs full path often if cross-origin or proxy issues, though simple string concat is safest for localhost)
setAudioUrl(`${BACKEND_URL}${result.audio_url}`);
} catch (err) {
console.error(err);
setError("Failed to generate audio. Please try again.");
} finally {
setGenerating(false);
}
};
return (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-sm p-4">
<div className="bg-white rounded-2xl shadow-2xl w-full max-w-2xl flex flex-col max-h-[90vh] animate-in fade-in zoom-in duration-200">
{/* Header */}
<div className="p-4 border-b border-slate-100 flex items-center justify-between">
<div className="flex items-center gap-3">
<div className="w-10 h-10 rounded-full bg-purple-100 flex items-center justify-center text-purple-600">
<Play size={20} fill="currentColor" />
</div>
<div>
<h2 className="text-lg font-bold text-slate-900">Audio Overview</h2>
<p className="text-sm text-slate-500">Listen to an AI-generated summary</p>
</div>
</div>
<button onClick={onClose} className="p-2 hover:bg-slate-100 rounded-full text-slate-400 transition-colors">
<X size={20} />
</button>
</div>
{/* Content */}
<div className="p-6 overflow-y-auto flex-1">
{/* Script Review */}
<div className="mb-6">
<h3 className="text-sm font-bold text-slate-700 uppercase tracking-wide mb-2 flex items-center gap-2">
<Clock size={14} /> Narration Script
</h3>
<div className="bg-slate-50 rounded-xl p-4 border border-slate-200 text-slate-700 leading-relaxed font-serif text-lg">
{script}
</div>
</div>
{/* Error Message */}
{error && (
<div className="mb-4 p-4 bg-red-50 text-red-600 rounded-xl text-sm">
{error}
</div>
)}
{/* Audio Player */}
{audioUrl && (
<div className="bg-purple-50 rounded-xl p-6 border border-purple-100 flex flex-col items-center justify-center text-center">
<h3 className="font-semibold text-purple-900 mb-4">Your Audio is Ready</h3>
<audio controls autoPlay className="w-full max-w-md shadow-md rounded-full">
<source src={audioUrl} type="audio/wav" />
Your browser does not support the audio element.
</audio>
<a href={audioUrl} download="overview.wav" className="mt-4 text-sm text-purple-600 hover:text-purple-800 flex items-center gap-1 font-medium">
<Download size={14} /> Download Audio
</a>
</div>
)}
</div>
{/* Footer Controls */}
<div className="p-4 border-t border-slate-100 bg-slate-50 rounded-b-2xl flex justify-end gap-3">
<button
onClick={onClose}
className="px-4 py-2 text-slate-600 font-medium hover:bg-slate-200 rounded-lg transition-colors"
>
Close
</button>
{!audioUrl && (
<button
onClick={handleGenerate}
disabled={generating}
className="px-6 py-2 bg-purple-600 hover:bg-purple-700 text-white font-medium rounded-lg shadow-lg shadow-purple-200 disabled:opacity-70 disabled:cursor-not-allowed flex items-center gap-2 transition-all"
>
{generating ? (
<>
<Loader2 size={18} className="animate-spin" /> Generating Voice...
</>
) : (
<>
<Play size={18} fill="currentColor" /> Generate Audio
</>
)}
</button>
)}
</div>
</div>
</div>
);
};
export default AudioPlayerModal;