File size: 8,360 Bytes
a8df197
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175

import React, { useState, useRef, useEffect } from 'react';
import { Model } from '../types';

interface CreateModelModalProps {
  isOpen: boolean;
  onClose: () => void;
  onSave: (model: Model) => void;
  onDelete?: (id: string) => void;
  editingModel?: Model | null;
}

const CreateModelModal: React.FC<CreateModelModalProps> = ({ isOpen, onClose, onSave, onDelete, editingModel }) => {
  const [name, setName] = useState('');
  const [image, setImage] = useState<File | string | null>(null);
  const [audio, setAudio] = useState<File | null>(null);
  const [gender, setGender] = useState<'male' | 'female'>('male');
  
  const imgInputRef = useRef<HTMLInputElement>(null);
  const audioInputRef = useRef<HTMLInputElement>(null);

  useEffect(() => {
    if (editingModel) {
      setName(editingModel.name);
      setImage(editingModel.image);
      setAudio(null); 
      setGender(editingModel.targetGender || 'male');
    } else {
      setName('');
      setImage(null);
      setAudio(null);
      setGender('male');
    }
  }, [editingModel, isOpen]);

  if (!isOpen) return null;

  const handleImageChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    if (e.target.files && e.target.files[0]) setImage(e.target.files[0]);
  };

  const handleAudioChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    if (e.target.files && e.target.files[0]) setAudio(e.target.files[0]);
  };

  const handleSave = () => {
    if (!name || !image || (!audio && !editingModel)) return;

    const model: Model = {
      id: editingModel?.id || `user_${Date.now()}`,
      name,
      image: image as any,
      refFile: audio || (editingModel?.refFile as any),
      category: 'user_custom',
      targetGender: gender,
      isCustom: true,
      type: 'standard'
    };
    onSave(model);
  };

  const getImgPreview = () => {
    if (!image) return null;
    if (typeof image === 'string') return image;
    return URL.createObjectURL(image as Blob);
  };

  return (
    <div className="fixed inset-0 z-[100] flex items-center justify-center p-4">
      <div className="absolute inset-0 bg-black/70 backdrop-blur-md" onClick={onClose}></div>
      <div className="relative bg-white rounded-[2.5rem] w-full max-w-[380px] p-6 shadow-2xl animate-[scaleIn_0.3s_ease-out] overflow-hidden">
        
        <div className="text-center mb-6">
            <h3 className="text-xl font-black text-gray-800">{editingModel ? 'ویرایش مدل' : 'ساخت مدل صوتی جدید'}</h3>
            <p className="text-xs text-gray-400 mt-1">مدل شخصی خود را با هوش مصنوعی آلفا بسازید</p>
        </div>

        <div className="space-y-5">
            {/* Image Upload */}
            <div className="flex flex-col items-center">
                <div 
                    onClick={() => imgInputRef.current?.click()}
                    className="w-24 h-24 rounded-3xl border-2 border-dashed border-gray-200 overflow-hidden cursor-pointer hover:border-primary transition-all relative group"
                >
                    {image ? (
                        <img src={getImgPreview()!} className="w-full h-full object-cover" />
                    ) : (
                        <div className="w-full h-full flex flex-col items-center justify-center bg-gray-50">
                            <i className="fas fa-image text-gray-300 text-2xl"></i>
                            <span className="text-[10px] text-gray-400 mt-1">عکس</span>
                        </div>
                    )}
                    <div className="absolute inset-0 bg-black/40 opacity-0 group-hover:opacity-100 flex items-center justify-center transition-opacity">
                         <i className="fas fa-camera text-white"></i>
                    </div>
                </div>
                <input type="file" ref={imgInputRef} hidden accept="image/*" onChange={handleImageChange} />
            </div>

            {/* Name Input */}
            <div>
                <label className="block text-[10px] font-bold text-gray-400 mb-1 mr-2">نام مدل</label>
                <input 
                    type="text" 
                    value={name}
                    onChange={(e) => setName(e.target.value)}
                    placeholder="مثلا: صدای رادیویی من"
                    className="w-full px-4 py-3 rounded-xl border border-gray-100 bg-gray-50 focus:bg-white focus:border-primary outline-none text-sm transition-all"
                />
            </div>

            {/* Audio Upload */}
            <div 
                onClick={() => audioInputRef.current?.click()}
                className={`p-4 rounded-xl border-2 border-dashed transition-all cursor-pointer flex flex-col gap-2 text-right
                    ${audio ? 'border-green-400 bg-green-50' : 'border-gray-100 bg-gray-50 hover:border-primary'}`}
            >
                <input type="file" ref={audioInputRef} hidden accept="audio/*" onChange={handleAudioChange} />
                <div className="flex items-center gap-3">
                    <div className={`w-10 h-10 rounded-full flex items-center justify-center flex-shrink-0 ${audio ? 'bg-green-500 text-white' : 'bg-white text-gray-400 shadow-sm'}`}>
                        <i className={`fas ${audio ? 'fa-check' : 'fa-microphone'}`}></i>
                    </div>
                    <div className="flex-1">
                        <p className="text-xs font-bold text-gray-700">{audio ? 'فایل صوتی انتخاب شد' : 'آپلود فایل صوتی مرجع'}</p>
                        <p className="text-[10px] text-gray-400 truncate">{audio ? audio.name : 'انتخاب فایل مدل...'}</p>
                    </div>
                </div>
                {!audio && (
                    <p className="text-[9px] text-gray-400 leading-relaxed mt-1">
                        (بهترین حالت ۳ تا ۹ ثانیه)دقت کنید کیفیت صدای خروجی به کیفیت این فایل صوتی مدل که اضافه میکنید بستگی داره اگر فایل صوتی این مدل شما با کیفیت بالا بدون نویز باشه در حد استودیو خروجی های این مدل شما نیز با کیفیت خواهد بود
                    </p>
                )}
            </div>

            {/* Gender Selection */}
            <div className="flex gap-2">
                <button 
                    onClick={() => setGender('male')}
                    className={`flex-1 py-2 rounded-xl text-xs font-bold transition-all border
                        ${gender === 'male' ? 'bg-blue-600 text-white border-blue-600' : 'bg-white text-gray-400 border-gray-100'}`}
                >مرد</button>
                <button 
                    onClick={() => setGender('female')}
                    className={`flex-1 py-2 rounded-xl text-xs font-bold transition-all border
                        ${gender === 'female' ? 'bg-pink-600 text-white border-pink-600' : 'bg-white text-gray-400 border-gray-100'}`}
                >زن</button>
            </div>

            <div className="flex gap-2 pt-2">
                <button 
                    onClick={handleSave}
                    disabled={!name || !image || (!audio && !editingModel)}
                    className="flex-[2] py-4 bg-gradient-to-r from-primary to-secondary text-white rounded-2xl font-black text-sm shadow-xl shadow-primary/20 hover:scale-[1.02] active:scale-95 transition-all disabled:grayscale disabled:opacity-50"
                >
                    {editingModel ? 'بروزرسانی مدل' : 'ساخت و ذخیره مدل'}
                </button>
                {editingModel && onDelete && (
                    <button 
                        onClick={() => onDelete(editingModel.id)}
                        className="flex-1 bg-red-50 text-red-500 rounded-2xl flex items-center justify-center hover:bg-red-100 transition-colors"
                    >
                        <i className="fas fa-trash-alt"></i>
                    </button>
                )}
            </div>
            
            <button onClick={onClose} className="w-full py-2 text-xs text-gray-400 font-bold">انصراف</button>
        </div>
      </div>
    </div>
  );
};

export default CreateModelModal;