project-standalo-sonic-cloud/components/CreatePlaylistModal.tsx

173 lines
6.4 KiB
TypeScript

'use client'
import { useState } from 'react'
export interface CreatePlaylistData {
title: string
description?: string
isPublic: boolean
}
export interface CreatePlaylistModalProps {
isOpen: boolean
onClose: () => void
onSubmit: (data: CreatePlaylistData) => void | Promise<void>
isLoading?: boolean
}
export function CreatePlaylistModal({
isOpen,
onClose,
onSubmit,
isLoading = false
}: CreatePlaylistModalProps) {
const [formData, setFormData] = useState<CreatePlaylistData>({
title: '',
description: '',
isPublic: true
})
if (!isOpen) return null
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault()
if (formData.title.trim()) {
onSubmit(formData)
}
}
const handleClose = () => {
if (!isLoading) {
setFormData({ title: '', description: '', isPublic: true })
onClose()
}
}
return (
<div className="fixed inset-0 z-50 flex items-center justify-center p-4">
{/* Backdrop */}
<div
className="absolute inset-0 bg-black/80 backdrop-blur-sm"
onClick={handleClose}
/>
{/* Modal */}
<div className="relative bg-zinc-900 rounded-2xl shadow-2xl border border-zinc-800 w-full max-w-md overflow-hidden">
{/* Header */}
<div className="flex items-center justify-between p-6 border-b border-zinc-800">
<h2 className="text-2xl font-bold text-white">Create Playlist</h2>
<button
onClick={handleClose}
disabled={isLoading}
className="p-2 text-zinc-400 hover:text-white transition disabled:opacity-50"
>
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
{/* Form */}
<form onSubmit={handleSubmit} className="p-6 space-y-6">
{/* Title */}
<div>
<label htmlFor="title" className="block text-sm font-medium text-zinc-300 mb-2">
Playlist Name *
</label>
<input
type="text"
id="title"
value={formData.title}
onChange={(e) => setFormData({ ...formData, title: e.target.value })}
placeholder="My awesome playlist"
className="w-full px-4 py-3 bg-zinc-800 border border-zinc-700 rounded-lg text-white placeholder-zinc-500 focus:outline-none focus:ring-2 focus:ring-purple-500"
required
autoFocus
/>
</div>
{/* Description */}
<div>
<label htmlFor="description" className="block text-sm font-medium text-zinc-300 mb-2">
Description (Optional)
</label>
<textarea
id="description"
value={formData.description}
onChange={(e) => setFormData({ ...formData, description: e.target.value })}
placeholder="Add a description for your playlist"
rows={3}
className="w-full px-4 py-3 bg-zinc-800 border border-zinc-700 rounded-lg text-white placeholder-zinc-500 focus:outline-none focus:ring-2 focus:ring-purple-500 resize-none"
/>
</div>
{/* Privacy */}
<div>
<label className="block text-sm font-medium text-zinc-300 mb-3">
Privacy
</label>
<div className="space-y-3">
<label className="flex items-center gap-3 p-4 bg-zinc-800 rounded-lg cursor-pointer hover:bg-zinc-750 transition">
<input
type="radio"
name="privacy"
checked={formData.isPublic}
onChange={() => setFormData({ ...formData, isPublic: true })}
className="w-5 h-5 text-purple-500 focus:ring-purple-500"
/>
<div className="flex-1">
<div className="flex items-center gap-2 mb-1">
<svg className="w-5 h-5 text-zinc-400" fill="currentColor" viewBox="0 0 20 20">
<path d="M10 2a8 8 0 100 16 8 8 0 000-16zM8 9a1 1 0 000 2h4a1 1 0 100-2H8z" />
</svg>
<span className="font-medium text-white">Public</span>
</div>
<p className="text-sm text-zinc-400">Anyone can see and listen to this playlist</p>
</div>
</label>
<label className="flex items-center gap-3 p-4 bg-zinc-800 rounded-lg cursor-pointer hover:bg-zinc-750 transition">
<input
type="radio"
name="privacy"
checked={!formData.isPublic}
onChange={() => setFormData({ ...formData, isPublic: false })}
className="w-5 h-5 text-purple-500 focus:ring-purple-500"
/>
<div className="flex-1">
<div className="flex items-center gap-2 mb-1">
<svg className="w-5 h-5 text-zinc-400" fill="currentColor" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M5 9V7a5 5 0 0110 0v2a2 2 0 012 2v5a2 2 0 01-2 2H5a2 2 0 01-2-2v-5a2 2 0 012-2zm8-2v2H7V7a3 3 0 016 0z" clipRule="evenodd" />
</svg>
<span className="font-medium text-white">Private</span>
</div>
<p className="text-sm text-zinc-400">Only you can see and listen to this playlist</p>
</div>
</label>
</div>
</div>
{/* Buttons */}
<div className="flex gap-3 pt-2">
<button
type="button"
onClick={handleClose}
disabled={isLoading}
className="flex-1 px-6 py-3 bg-zinc-800 hover:bg-zinc-700 disabled:bg-zinc-800 disabled:text-zinc-500 text-white font-medium rounded-lg transition"
>
Cancel
</button>
<button
type="submit"
disabled={isLoading || !formData.title.trim()}
className="flex-1 px-6 py-3 bg-purple-500 hover:bg-purple-600 disabled:bg-zinc-700 disabled:text-zinc-500 text-white font-medium rounded-lg transition"
>
{isLoading ? 'Creating...' : 'Create'}
</button>
</div>
</form>
</div>
</div>
)
}