project-standalo-note-to-app/app/components/AudioPlayer.tsx

97 lines
2.5 KiB
TypeScript

'use client';
import { useState, useRef, useEffect } from 'react';
import type { AudioPlayerProps } from '@/types/component-props';
export default function AudioPlayer({
audioUrl,
duration,
onPlayPause,
onSeek,
}: AudioPlayerProps) {
const [isPlaying, setIsPlaying] = useState(false);
const [currentTime, setCurrentTime] = useState(0);
const audioRef = useRef<HTMLAudioElement>(null);
useEffect(() => {
const audio = audioRef.current;
if (!audio) return;
const handleTimeUpdate = () => {
setCurrentTime(audio.currentTime);
};
const handleEnded = () => {
setIsPlaying(false);
onPlayPause?.(false);
};
audio.addEventListener('timeupdate', handleTimeUpdate);
audio.addEventListener('ended', handleEnded);
return () => {
audio.removeEventListener('timeupdate', handleTimeUpdate);
audio.removeEventListener('ended', handleEnded);
};
}, [onPlayPause]);
const handlePlayPause = () => {
const audio = audioRef.current;
if (!audio) return;
if (isPlaying) {
audio.pause();
} else {
audio.play();
}
setIsPlaying(!isPlaying);
onPlayPause?.(!isPlaying);
};
const handleSeek = (e: React.ChangeEvent<HTMLInputElement>) => {
const audio = audioRef.current;
if (!audio) return;
const newTime = parseFloat(e.target.value);
audio.currentTime = newTime;
setCurrentTime(newTime);
onSeek?.(newTime);
};
const formatTime = (seconds: number) => {
const mins = Math.floor(seconds / 60);
const secs = Math.floor(seconds % 60);
return `${mins}:${secs.toString().padStart(2, '0')}`;
};
return (
<div className="bg-white border rounded-lg p-4">
<audio ref={audioRef} src={audioUrl} />
<div className="flex items-center gap-4">
<button
onClick={handlePlayPause}
className="w-12 h-12 rounded-full bg-blue-500 text-white flex items-center justify-center hover:bg-blue-600 transition-colors"
>
{isPlaying ? '⏸️' : '▶️'}
</button>
<div className="flex-1">
<input
type="range"
min="0"
max={duration}
value={currentTime}
onChange={handleSeek}
className="w-full"
/>
<div className="flex justify-between text-xs text-gray-600 mt-1">
<span>{formatTime(currentTime)}</span>
<span>{formatTime(duration)}</span>
</div>
</div>
</div>
</div>
);
}