order detail + types + components

This commit is contained in:
hamid zarghami
2026-01-31 11:00:24 +03:30
parent 7df6d04d5f
commit b730f86b1e
11 changed files with 723 additions and 6 deletions
+74
View File
@@ -0,0 +1,74 @@
import { Pause, Play } from "iconsax-react"
import { useEffect, useRef, useState, type FC } from "react"
type VoicePlayerProps = {
url: string
}
const VoicePlayer: FC<VoicePlayerProps> = ({ url }) => {
const audioRef = useRef<HTMLAudioElement | null>(null)
const [isPlaying, setIsPlaying] = useState(false)
const [progress, setProgress] = useState(0)
useEffect(() => {
const audio = audioRef.current
if (!audio) return
const update = () => {
if (!audio.duration) return
setProgress(audio.currentTime / audio.duration)
}
audio.addEventListener('timeupdate', update)
audio.addEventListener('ended', () => {
setIsPlaying(false)
setProgress(0)
})
return () => {
audio.removeEventListener('timeupdate', update)
}
}, [])
const toggle = () => {
if (!audioRef.current) return
if (isPlaying) audioRef.current.pause()
else audioRef.current.play()
setIsPlaying(!isPlaying)
}
return (
<div className="w-full h-12 bg-white border border-border rounded-xl flex items-center px-3 gap-3 mt-2">
<button
onClick={toggle}
className="w-8 h-8 rounded-full bg-black flex items-center justify-center flex-shrink-0"
>
{isPlaying ? (
<Pause size={16} color="#fff" variant="Bold" />
) : (
<Play size={16} color="#fff" variant="Bold" />
)}
</button>
<div className="flex-1 flex items-center gap-[2px] h-8">
{Array.from({ length: 60 }).map((_, i) => {
const passed = i / 60 <= progress
return (
<div
key={i}
className="w-[2px] rounded-full transition-all"
style={{
height: `${Math.random() * 18 + 4}px`,
backgroundColor: passed ? '#0047FF' : '#E5E7EB'
}}
/>
)
})}
</div>
<audio ref={audioRef} src={url} className="hidden" />
</div>
)
}
export default VoicePlayer