| 1 | import { useState, useEffect } from "react";
|
|---|
| 2 | import type { CreatePlaylistModalProps } from "../../utils/types";
|
|---|
| 3 |
|
|---|
| 4 | const CreatePlaylistModal = ({
|
|---|
| 5 | isOpen,
|
|---|
| 6 | onClose,
|
|---|
| 7 | onSubmit,
|
|---|
| 8 | }: CreatePlaylistModalProps) => {
|
|---|
| 9 | const [playlistName, setPlaylistName] = useState("");
|
|---|
| 10 | const [isClosing, setIsClosing] = useState(false);
|
|---|
| 11 | const [isOpening, setIsOpening] = useState(false);
|
|---|
| 12 |
|
|---|
| 13 | useEffect(() => {
|
|---|
| 14 | if (isOpen) {
|
|---|
| 15 | setIsClosing(false);
|
|---|
| 16 | setPlaylistName("");
|
|---|
| 17 | setIsOpening(true);
|
|---|
| 18 | setTimeout(() => setIsOpening(false), 10);
|
|---|
| 19 | }
|
|---|
| 20 | }, [isOpen]);
|
|---|
| 21 |
|
|---|
| 22 | const handleClose = () => {
|
|---|
| 23 | setIsClosing(true);
|
|---|
| 24 | setTimeout(() => {
|
|---|
| 25 | onClose();
|
|---|
| 26 | setIsClosing(false);
|
|---|
| 27 | }, 200);
|
|---|
| 28 | };
|
|---|
| 29 |
|
|---|
| 30 | const handleSubmit = (e: React.FormEvent) => {
|
|---|
| 31 | e.preventDefault();
|
|---|
| 32 | if (playlistName.trim()) {
|
|---|
| 33 | onSubmit(playlistName.trim());
|
|---|
| 34 | handleClose();
|
|---|
| 35 | }
|
|---|
| 36 | };
|
|---|
| 37 |
|
|---|
| 38 | if (!isOpen && !isClosing) return null;
|
|---|
| 39 |
|
|---|
| 40 | return (
|
|---|
| 41 | <div
|
|---|
| 42 | className={`fixed inset-0 bg-black/60 backdrop-blur-sm flex items-center justify-center z-50 px-4 transition-opacity duration-200 ${
|
|---|
| 43 | isClosing || isOpening ? "opacity-0" : "opacity-100"
|
|---|
| 44 | }`}
|
|---|
| 45 | onClick={handleClose}
|
|---|
| 46 | >
|
|---|
| 47 | <div
|
|---|
| 48 | className={`bg-[#181818] rounded-xl p-8 w-full max-w-md border border-white/10 transition-all duration-200 ${
|
|---|
| 49 | isClosing || isOpening
|
|---|
| 50 | ? "scale-95 opacity-0"
|
|---|
| 51 | : "scale-100 opacity-100"
|
|---|
| 52 | }`}
|
|---|
| 53 | onClick={(e) => e.stopPropagation()}
|
|---|
| 54 | >
|
|---|
| 55 | <div className="flex justify-between items-center mb-6">
|
|---|
| 56 | <h2 className="text-2xl font-bold text-white">Create Playlist</h2>
|
|---|
| 57 | <button
|
|---|
| 58 | onClick={handleClose}
|
|---|
| 59 | className="text-gray-400 hover:text-white transition-colors cursor-pointer"
|
|---|
| 60 | aria-label="Close modal"
|
|---|
| 61 | >
|
|---|
| 62 | <svg
|
|---|
| 63 | className="w-6 h-6"
|
|---|
| 64 | fill="none"
|
|---|
| 65 | stroke="currentColor"
|
|---|
| 66 | viewBox="0 0 24 24"
|
|---|
| 67 | >
|
|---|
| 68 | <path
|
|---|
| 69 | strokeLinecap="round"
|
|---|
| 70 | strokeLinejoin="round"
|
|---|
| 71 | strokeWidth={2}
|
|---|
| 72 | d="M6 18L18 6M6 6l12 12"
|
|---|
| 73 | />
|
|---|
| 74 | </svg>
|
|---|
| 75 | </button>
|
|---|
| 76 | </div>
|
|---|
| 77 |
|
|---|
| 78 | <form onSubmit={handleSubmit} className="space-y-6">
|
|---|
| 79 | <div>
|
|---|
| 80 | <label
|
|---|
| 81 | className="block text-sm font-medium text-gray-300 mb-2"
|
|---|
| 82 | htmlFor="playlistName"
|
|---|
| 83 | >
|
|---|
| 84 | Playlist Name
|
|---|
| 85 | </label>
|
|---|
| 86 | <input
|
|---|
| 87 | type="text"
|
|---|
| 88 | id="playlistName"
|
|---|
| 89 | autoFocus
|
|---|
| 90 | className="w-full bg-[#282828] border border-white/10 rounded-lg py-3 px-4 text-white placeholder-gray-500 focus:outline-none focus:border-[#1db954] focus:ring-1 focus:ring-[#1db954] transition-all"
|
|---|
| 91 | placeholder="Enter playlist name"
|
|---|
| 92 | value={playlistName}
|
|---|
| 93 | onChange={(e) => setPlaylistName(e.target.value)}
|
|---|
| 94 | />
|
|---|
| 95 | </div>
|
|---|
| 96 |
|
|---|
| 97 | <div className="flex gap-3">
|
|---|
| 98 | <button
|
|---|
| 99 | type="button"
|
|---|
| 100 | onClick={handleClose}
|
|---|
| 101 | className="flex-1 py-3 bg-[#282828] rounded-full text-white font-semibold hover:bg-[#3a3a3a] transition-colors cursor-pointer"
|
|---|
| 102 | >
|
|---|
| 103 | Cancel
|
|---|
| 104 | </button>
|
|---|
| 105 | <button
|
|---|
| 106 | type="submit"
|
|---|
| 107 | disabled={!playlistName.trim()}
|
|---|
| 108 | className="flex-1 py-3 bg-[#1db954] rounded-full text-black font-semibold hover:bg-[#1ed760] transition-colors disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-[#1db954] cursor-pointer"
|
|---|
| 109 | >
|
|---|
| 110 | Create
|
|---|
| 111 | </button>
|
|---|
| 112 | </div>
|
|---|
| 113 | </form>
|
|---|
| 114 | </div>
|
|---|
| 115 | </div>
|
|---|
| 116 | );
|
|---|
| 117 | };
|
|---|
| 118 |
|
|---|
| 119 | export default CreatePlaylistModal;
|
|---|