| 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);
|
|
|
| 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);
|
|
|
|
|
| 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;
|
|
|