rein0421 commited on
Commit
3d39f0b
·
verified ·
1 Parent(s): d73bff4

Update templates/userRegister.html

Browse files
Files changed (1) hide show
  1. templates/userRegister.html +317 -12
templates/userRegister.html CHANGED
@@ -20,7 +20,6 @@
20
  .animate-pulse-scale {
21
  animation: pulse-scale 1s infinite;
22
  }
23
-
24
  /* Record Button Styles */
25
  .record-button {
26
  width: 50px;
@@ -51,7 +50,6 @@
51
  height: 20px;
52
  border-radius: 50%;
53
  }
54
-
55
  /* Title */
56
  .main-title {
57
  font-size: 2.5rem;
@@ -60,7 +58,6 @@
60
  color: #fff;
61
  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
62
  }
63
-
64
  /* Buttons */
65
  .action-button {
66
  margin-top: 1rem;
@@ -70,26 +67,80 @@
70
  transition: background-color 0.2s ease;
71
  width: 100%;
72
  }
73
-
74
  .action-button:hover {
75
  background-color: rgba(55, 65, 81, 0.7);
76
  }
77
-
78
  .back-button {
79
  background-color: #607d8b; /* 落ち着いたグレー */
80
  color: white;
81
  }
82
-
83
  .add-button {
84
  background-color: #4caf50; /* 落ち着いた緑色 */
85
  color: white;
86
  }
87
-
88
  /* Disabled State */
89
  .disabled {
90
  opacity: 0.5;
91
  pointer-events: none;
92
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
93
  </style>
94
  </head>
95
  <body>
@@ -97,15 +148,12 @@
97
  <div class="main-content relative">
98
  <!-- Title -->
99
  <div class="main-title">JustTalk</div>
100
-
101
  <!-- User List -->
102
  <div id="people-list" class="space-y-4"></div>
103
-
104
  <!-- Add Button -->
105
  <button id="add-btn" class="action-button add-button">
106
  <i class="fas fa-user-plus"></i> メンバーを追加
107
  </button>
108
-
109
  <!-- 録音画面へ移動ボタン(Back Buttonから変更) -->
110
  <button
111
  id="backButton"
@@ -116,6 +164,263 @@
116
  </button>
117
  </div>
118
 
119
- <script src="{{ url_for('static', filename='register_record.js') }}"></script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
120
  </body>
121
- </html>
 
20
  .animate-pulse-scale {
21
  animation: pulse-scale 1s infinite;
22
  }
 
23
  /* Record Button Styles */
24
  .record-button {
25
  width: 50px;
 
50
  height: 20px;
51
  border-radius: 50%;
52
  }
 
53
  /* Title */
54
  .main-title {
55
  font-size: 2.5rem;
 
58
  color: #fff;
59
  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.5);
60
  }
 
61
  /* Buttons */
62
  .action-button {
63
  margin-top: 1rem;
 
67
  transition: background-color 0.2s ease;
68
  width: 100%;
69
  }
 
70
  .action-button:hover {
71
  background-color: rgba(55, 65, 81, 0.7);
72
  }
 
73
  .back-button {
74
  background-color: #607d8b; /* 落ち着いたグレー */
75
  color: white;
76
  }
 
77
  .add-button {
78
  background-color: #4caf50; /* 落ち着いた緑色 */
79
  color: white;
80
  }
 
81
  /* Disabled State */
82
  .disabled {
83
  opacity: 0.5;
84
  pointer-events: none;
85
  }
86
+
87
+ /* Modal Styles */
88
+ .modal {
89
+ display: none;
90
+ position: fixed;
91
+ top: 0;
92
+ left: 0;
93
+ width: 100%;
94
+ height: 100%;
95
+ background-color: rgba(0, 0, 0, 0.7);
96
+ z-index: 1000;
97
+ justify-content: center;
98
+ align-items: center;
99
+ }
100
+
101
+ .modal-content {
102
+ background-color: #2d3748;
103
+ color: white;
104
+ padding: 2rem;
105
+ border-radius: 1rem;
106
+ width: 90%;
107
+ max-width: 500px;
108
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
109
+ }
110
+
111
+ .input-field {
112
+ width: 100%;
113
+ padding: 0.75rem;
114
+ border-radius: 0.5rem;
115
+ background-color: #1a202c;
116
+ border: 1px solid #4a5568;
117
+ color: white;
118
+ margin-bottom: 1rem;
119
+ }
120
+
121
+ .modal-buttons {
122
+ display: flex;
123
+ justify-content: space-between;
124
+ margin-top: 1rem;
125
+ }
126
+
127
+ .modal-button {
128
+ padding: 0.75rem 1.5rem;
129
+ border-radius: 0.5rem;
130
+ cursor: pointer;
131
+ min-width: 100px;
132
+ text-align: center;
133
+ }
134
+
135
+ .record-modal-button {
136
+ background-color: #d32f2f;
137
+ color: white;
138
+ }
139
+
140
+ .cancel-button {
141
+ background-color: #64748b;
142
+ color: white;
143
+ }
144
  </style>
145
  </head>
146
  <body>
 
148
  <div class="main-content relative">
149
  <!-- Title -->
150
  <div class="main-title">JustTalk</div>
 
151
  <!-- User List -->
152
  <div id="people-list" class="space-y-4"></div>
 
153
  <!-- Add Button -->
154
  <button id="add-btn" class="action-button add-button">
155
  <i class="fas fa-user-plus"></i> メンバーを追加
156
  </button>
 
157
  <!-- 録音画面へ移動ボタン(Back Buttonから変更) -->
158
  <button
159
  id="backButton"
 
164
  </button>
165
  </div>
166
 
167
+ <!-- Modal for Adding New User -->
168
+ <div id="add-modal" class="modal">
169
+ <div class="modal-content">
170
+ <h2 class="text-xl font-bold mb-4">新しいメンバーを追加</h2>
171
+ <input id="user-name" type="text" placeholder="名前を入力" class="input-field">
172
+
173
+ <div class="flex justify-center my-4">
174
+ <div id="record-button" class="record-button">
175
+ <div class="record-icon"></div>
176
+ </div>
177
+ </div>
178
+ <div id="recording-status" class="text-center mb-4">録音をクリックして開始</div>
179
+
180
+ <div class="modal-buttons">
181
+ <button id="cancel-button" class="modal-button cancel-button">キャンセル</button>
182
+ <button id="save-button" class="modal-button record-modal-button" disabled>保存</button>
183
+ </div>
184
+ </div>
185
+ </div>
186
+
187
+ <script>
188
+ // グローバル変数
189
+ let mediaRecorder;
190
+ let audioChunks = [];
191
+ let registeredUsers = [];
192
+ let isRecording = false;
193
+
194
+ // ページ読み込み時に実行
195
+ document.addEventListener('DOMContentLoaded', () => {
196
+ loadUsers();
197
+ setupEventListeners();
198
+ });
199
+
200
+ // イベントリスナーの設定
201
+ function setupEventListeners() {
202
+ // 追加ボタン
203
+ document.getElementById('add-btn').addEventListener('click', () => {
204
+ openModal();
205
+ });
206
+
207
+ // 録音ボタン
208
+ document.getElementById('record-button').addEventListener('click', toggleRecording);
209
+
210
+ // キャンセルボタン
211
+ document.getElementById('cancel-button').addEventListener('click', closeModal);
212
+
213
+ // 保存ボタン
214
+ document.getElementById('save-button').addEventListener('click', saveRecording);
215
+ }
216
+
217
+ // ユーザーリストを読み込む
218
+ async function loadUsers() {
219
+ try {
220
+ const response = await fetch('/list_base_audio');
221
+ const data = await response.json();
222
+
223
+ if (data.status === "success" && Array.isArray(data.id)) {
224
+ registeredUsers = data.id;
225
+ displayUsers(registeredUsers);
226
+ } else {
227
+ console.error('Unexpected response format:', data);
228
+ }
229
+ } catch (error) {
230
+ console.error('Error loading users:', error);
231
+ }
232
+ }
233
+
234
+ // ユーザーリストを表示
235
+ function displayUsers(users) {
236
+ const peopleList = document.getElementById('people-list');
237
+ peopleList.innerHTML = '';
238
+
239
+ if (users.length === 0) {
240
+ peopleList.innerHTML = '<p class="text-gray-400 text-center">登録されたメンバーはいません</p>';
241
+ return;
242
+ }
243
+
244
+ users.forEach(user => {
245
+ const userDiv = document.createElement('div');
246
+ userDiv.className = 'bg-gray-700 rounded-lg p-4 flex justify-between items-center';
247
+ userDiv.innerHTML = `
248
+ <div class="flex items-center">
249
+ <i class="fas fa-user-circle text-2xl mr-3"></i>
250
+ <span>${user}</span>
251
+ </div>
252
+ <button class="delete-btn text-red-500 hover:text-red-300" data-name="${user}">
253
+ <i class="fas fa-trash"></i>
254
+ </button>
255
+ `;
256
+ peopleList.appendChild(userDiv);
257
+ });
258
+
259
+ // 削除ボタンのイベントリスナーを追加
260
+ document.querySelectorAll('.delete-btn').forEach(button => {
261
+ button.addEventListener('click', function() {
262
+ const name = this.getAttribute('data-name');
263
+ deleteUser(name);
264
+ });
265
+ });
266
+ }
267
+
268
+ // ユーザーを削除
269
+ async function deleteUser(name) {
270
+ if (!confirm(`${name}を削除してもよろしいですか?`)) return;
271
+
272
+ try {
273
+ const response = await fetch('/reset_member', {
274
+ method: 'POST',
275
+ headers: {
276
+ 'Content-Type': 'application/json'
277
+ },
278
+ body: JSON.stringify({
279
+ names: [name]
280
+ })
281
+ });
282
+
283
+ const data = await response.json();
284
+
285
+ if (data.status === "success") {
286
+ // 削除成功時、ユーザーリストを更新
287
+ loadUsers();
288
+ } else {
289
+ console.error('Error deleting user:', data.message);
290
+ alert('ユーザーの削除に失敗しました');
291
+ }
292
+ } catch (error) {
293
+ console.error('Error:', error);
294
+ alert('エラーが発生しました');
295
+ }
296
+ }
297
+
298
+ // モーダルを開く
299
+ function openModal() {
300
+ document.getElementById('add-modal').style.display = 'flex';
301
+ document.getElementById('user-name').value = '';
302
+ document.getElementById('save-button').disabled = true;
303
+ document.getElementById('recording-status').textContent = '録音をクリックして開始';
304
+
305
+ // 録音状態をリセット
306
+ isRecording = false;
307
+ audioChunks = [];
308
+ const recordButton = document.getElementById('record-button');
309
+ recordButton.classList.remove('recording');
310
+ }
311
+
312
+ // モーダルを閉じる
313
+ function closeModal() {
314
+ document.getElementById('add-modal').style.display = 'none';
315
+
316
+ // 録音中なら停止
317
+ if (mediaRecorder && isRecording) {
318
+ mediaRecorder.stop();
319
+ isRecording = false;
320
+ }
321
+ }
322
+
323
+ // 録音の開始/停止を切り替え
324
+ async function toggleRecording() {
325
+ const recordButton = document.getElementById('record-button');
326
+ const statusText = document.getElementById('recording-status');
327
+
328
+ if (!isRecording) {
329
+ // 録音開始
330
+ try {
331
+ const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
332
+ mediaRecorder = new MediaRecorder(stream);
333
+ audioChunks = [];
334
+
335
+ mediaRecorder.ondataavailable = event => {
336
+ audioChunks.push(event.data);
337
+ };
338
+
339
+ mediaRecorder.onstop = () => {
340
+ document.getElementById('save-button').disabled = false;
341
+ statusText.textContent = '録音完了!';
342
+ recordButton.classList.remove('recording');
343
+ };
344
+
345
+ mediaRecorder.start();
346
+ isRecording = true;
347
+ statusText.textContent = '録音中...';
348
+ recordButton.classList.add('recording');
349
+ } catch (error) {
350
+ console.error('録音の開始に失敗しました:', error);
351
+ statusText.textContent = '録音の開始に失敗しました';
352
+ }
353
+ } else {
354
+ // 録音停止
355
+ mediaRecorder.stop();
356
+ isRecording = false;
357
+ }
358
+ }
359
+
360
+ // 録音を保存
361
+ async function saveRecording() {
362
+ const userName = document.getElementById('user-name').value.trim();
363
+
364
+ if (!userName) {
365
+ alert('名前を入力してください');
366
+ return;
367
+ }
368
+
369
+ if (registeredUsers.includes(userName)) {
370
+ if (!confirm(`${userName}は既に登録されています。上書きしますか?`)) {
371
+ return;
372
+ }
373
+ }
374
+
375
+ if (audioChunks.length === 0) {
376
+ alert('録音データがありません');
377
+ return;
378
+ }
379
+
380
+ try {
381
+ // 録音データをBlobに変換
382
+ const audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
383
+
384
+ // Base64に変換
385
+ const reader = new FileReader();
386
+ reader.readAsDataURL(audioBlob);
387
+ reader.onloadend = async () => {
388
+ // Base64文字列から先頭の "data:audio/wav;base64," を削除
389
+ const base64Audio = reader.result.split(',')[1];
390
+
391
+ // サーバーに送信
392
+ const response = await fetch('/upload_base_audio', {
393
+ method: 'POST',
394
+ headers: {
395
+ 'Content-Type': 'application/json'
396
+ },
397
+ body: JSON.stringify({
398
+ name: userName,
399
+ audio_data: base64Audio
400
+ })
401
+ });
402
+
403
+ const data = await response.json();
404
+
405
+ if (data.state === "Registration Success!") {
406
+ closeModal();
407
+ loadUsers(); // ユーザーリストを更新
408
+ alert(`${userName}を登録しました!`);
409
+ } else {
410
+ console.error('Error saving recording:', data);
411
+ alert('録音の保存に失敗しました');
412
+ }
413
+ };
414
+ } catch (error) {
415
+ console.error('Error:', error);
416
+ alert('エラーが発生しました');
417
+ }
418
+ }
419
+
420
+ // ユーザー選択画面に戻る
421
+ function showUserSelect() {
422
+ window.location.href = "/userselect";
423
+ }
424
+ </script>
425
  </body>
426
+ </html>