Mycc commited on
Commit
59c87d4
·
verified ·
1 Parent(s): dcae22a

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +309 -142
index.html CHANGED
@@ -50,25 +50,64 @@
50
  transition: max-height 0.3s ease-out;
51
  }
52
  .settings-panel.open {
53
- max-height: 500px; /* Увеличено для вместимости содержимого */
54
  }
55
- /* Анимация для рулетки */
56
- .roulette-spinning .roulette-char-card {
57
- animation: spin-animation 0.1s linear infinite;
58
  }
59
- @keyframes spin-animation {
60
- 0% { transform: translateY(0) rotate(0deg); opacity: 1; }
61
- 50% { transform: translateY(-5px) rotate(2deg); opacity: 0.8; }
62
- 100% { transform: translateY(0) rotate(0deg); opacity: 1; }
63
  }
64
- .roulette-item-enter {
 
 
65
  opacity: 0;
66
- transform: scale(0.8);
 
 
67
  }
68
- .roulette-item-enter-active {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  opacity: 1;
70
- transform: scale(1);
71
- transition: opacity 0.5s ease-out, transform 0.5s ease-out;
72
  }
73
  </style>
74
  </head>
@@ -88,7 +127,7 @@
88
  </svg>
89
  </button>
90
  </div>
91
- <h1 class="text-4xl md:text-5xl font-bold text-[#4A4A4A] dark:text-[#e2e8f0] mb-2">Рулетка Отрядов Genshin Impact</h1>
92
  <p class="text-lg text-[#6B6B6B] dark:text-[#a0aec0] max-w-2xl mx-auto">
93
  Сгенерируйте случайный отряд из четырех персонажей Genshin Impact!
94
  </p>
@@ -97,7 +136,7 @@
97
  <main>
98
  <div id="settings-panel" class="settings-panel bg-[#EFEAE4] dark:bg-gray-700 p-6 rounded-2xl shadow-lg mb-6">
99
  <h3 class="text-xl font-bold mb-4 dark:text-white">Настройки рулетки</h3>
100
- <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
101
  <div>
102
  <label for="team-size" class="block text-sm font-medium mb-2 dark:text-gray-300">Количество персонажей в отряде</label>
103
  <select id="team-size" class="w-full p-2 rounded border border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-white">
@@ -116,6 +155,21 @@
116
  </select>
117
  </div>
118
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
  </div>
120
 
121
  <section id="roulette-section" class="mb-16 bg-[#EFEAE4] dark:bg-gray-700 p-6 rounded-2xl shadow-lg">
@@ -129,14 +183,30 @@
129
  <p id="roulette-placeholder" class="text-[#888] dark:text-gray-400">Ваш случайный отряд появится здесь.</p>
130
  <div id="roulette-loader" class="loader hidden"></div>
131
  </div>
 
 
 
 
 
 
 
 
 
 
 
132
  </section>
133
 
134
  <section id="history-section" class="bg-[#EFEAE4] dark:bg-gray-700 p-6 rounded-2xl shadow-lg">
135
  <div class="flex justify-between items-center mb-8">
136
  <h2 class="text-3xl font-bold text-[#4A4A4A] dark:text-white">История Отрядов</h2>
137
- <button id="clear-history-button" class="bg-[#A089D0] text-white font-bold py-2 px-4 rounded-lg text-sm shadow-md hover:bg-[#8e7abf] transition-transform duration-200 ease-in-out hover:scale-105 focus:outline-none focus:ring-4 focus:ring-[#A089D0]/50 hidden">
138
- Очистить
139
- </button>
 
 
 
 
 
140
  </div>
141
  <div id="history-content" class="flex flex-col gap-6">
142
  <p id="history-placeholder" class="text-center text-[#888] dark:text-gray-400">История ваших отрядов будет отображаться здесь.</p>
@@ -154,7 +224,7 @@
154
  <div id="confirm-modal" class="fixed inset-0 bg-black bg-opacity-70 z-50 flex justify-center items-center hidden p-4">
155
  <div class="bg-[#FDF8F0] dark:bg-gray-800 rounded-2xl w-full max-w-sm shadow-2xl relative text-center p-6 transform transition-all duration-300 scale-95 opacity-0" id="confirm-modal-content">
156
  <h3 class="text-2xl font-bold mb-4 text-[#4A4A4A] dark:text-white">Подтверждение</h3>
157
- <p id="confirm-modal-message" class="text-lg text-[#6B6B6B] dark:text-gray-300 mb-6">Вы уверены, что хотите очистить историю?</p>
158
  <div class="flex justify-around gap-4">
159
  <button id="confirm-modal-cancel" class="bg-[#A089D0] text-white font-bold py-2 px-6 rounded-lg hover:bg-[#8e7abf]">Отмена</button>
160
  <button id="confirm-modal-ok" class="bg-red-500 text-white font-bold py-2 px-6 rounded-lg hover:bg-red-600">Очистить</button>
@@ -178,10 +248,10 @@
178
  { "name": "Беннет", "icon": "https://game-cdn.appsample.com/gim/items/bennett.png" },
179
  { "name": "Кандакия", "icon": "https://game-cdn.appsample.com/gim/items/candace.png" },
180
  { "name": "Шарлотта", "icon": "https://game-cdn.appsample.com/gim/items/charlotte.png" },
181
- { "name": "Часца", "icon": "https://game-cdn.appsample.com/gim/items/chasca.png" },
182
- { "name": "Чиори", "icon": "https://game-cdn.appsample.com/gim/items/chiori.png" },
183
  { "name": "Чун Юнь", "icon": "https://game-cdn.appsample.com/gim/items/chongyun.png" },
184
- { "name": "Сителла", "icon": "https://game-cdn.appsample.com/gim/items/citlali.png" },
185
  { "name": "Клоринда", "icon": "https://game-cdn.appsample.com/gim/items/clorinde.png" },
186
  { "name": "Коллеи", "icon": "https://game-cdn.appsample.com/gim/items/collei.png" },
187
  { "name": "Сайно", "icon": "https://game-cdn.appsample.com/gim/items/cyno.png" },
@@ -216,7 +286,7 @@
216
  { "name": "Сара", "icon": "https://game-cdn.appsample.com/gim/items/kujou_sara.png" },
217
  { "name": "Шинобу", "icon": "https://game-cdn.appsample.com/gim/items/kuki_shinobu.png" },
218
  { "name": "Лань Янь", "icon": "https://game-cdn.appsample.com/gim/items/lan_yan.png" },
219
- { "name": "Лайла", "icon": "https://game-cdn.appsample.com/gim/items/layla.png" },
220
  { "name": "Лиза", "icon": "https://game-cdn.appsample.com/gim/items/lisa.png" },
221
  { "name": "Линнет", "icon": "https://game-cdn.appsample.com/gim/items/lynette.png" },
222
  { "name": "Лини", "icon": "https://game-cdn.appsample.com/gim/items/lyney.png" },
@@ -232,15 +302,15 @@
232
  { "name": "Ноэлль", "icon": "https://game-cdn.appsample.com/gim/items/noelle.png" },
233
  { "name": "Оророн", "icon": "https://game-cdn.appsample.com/gim/items/ororon.png" },
234
  { "name": "Ци Ци", "icon": "https://game-cdn.appsample.com/gim/items/qiqi.png" },
235
- { "name": "Райдэн Сёгун", "icon": "https://game-cdn.appsample.com/gim/items/raiden_shogun.png" },
236
  { "name": "Рэйзор", "icon": "https://game-cdn.appsample.com/gim/items/razor.png" },
237
- { "name": "Розария", "icon": "https://game-cdn.appsample.com/gim/items/rosaria.png" },
238
- { "name": "Сангономия Кокоми", "icon": "https://game-cdn.appsample.com/gim/items/sangonomiya_kokomi.png" },
239
  { "name": "Саю", "icon": "https://game-cdn.appsample.com/gim/items/sayu.png" },
240
- { "name": "Сетусы", "icon": "https://game-cdn.appsample.com/gim/items/sethos.png" },
241
  { "name": "Шэнь Хэ", "icon": "https://game-cdn.appsample.com/gim/items/shenhe.png" },
242
- { "name": "Сиканоин Хэйдзо", "icon": "https://game-cdn.appsample.com/gim/items/shikanoin_heizou.png" },
243
- { "name": "Сигевинн", "icon": "https://game-cdn.appsample.com/gim/items/sigewinne.png" },
244
  { "name": "Сахароза", "icon": "https://game-cdn.appsample.com/gim/items/sucrose.png" },
245
  { "name": "Тарталья", "icon": "https://game-cdn.appsample.com/gim/items/tartaglia.png" },
246
  { "name": "Тома", "icon": "https://game-cdn.appsample.com/gim/items/thoma.png" },
@@ -248,11 +318,11 @@
248
  { "name": "Вареса", "icon": "https://game-cdn.appsample.com/gim/items/varesa.png" },
249
  { "name": "Венти", "icon": "https://game-cdn.appsample.com/gim/items/venti.png" },
250
  { "name": "Странник", "icon": "https://game-cdn.appsample.com/gim/items/wanderer.png" },
251
- { "name": "Райотсли", "icon": "https://game-cdn.appsample.com/gim/items/wriothesley.png" },
252
  { "name": "Сяо", "icon": "https://game-cdn.appsample.com/gim/items/xiao.png" },
253
  { "name": "Сян Линь", "icon": "https://game-cdn.appsample.com/gim/items/xiangling.png" },
254
  { "name": "Сянь Юнь", "icon": "https://game-cdn.appsample.com/gim/items/xianyun.png" },
255
- { "name": "Силонен", "icon": "https://game-cdn.appsample.com/gim/items/xilonen.png" },
256
  { "name": "Син Цю", "icon": "https://game-cdn.appsample.com/gim/items/xingqiu.png" },
257
  { "name": "Синь Янь", "icon": "https://game-cdn.appsample.com/gim/items/xinyan.png" },
258
  { "name": "Яэ Мико", "icon": "https://game-cdn.appsample.com/gim/items/yae_miko.png" },
@@ -261,7 +331,7 @@
261
  { "name": "Е Лань", "icon": "https://game-cdn.appsample.com/gim/items/yelan.png" },
262
  { "name": "Ёимия", "icon": "https://game-cdn.appsample.com/gim/items/yoimiya.png" },
263
  { "name": "Юнь Цзинь", "icon": "https://game-cdn.appsample.com/gim/items/yun_jin.png" },
264
- { "name": "Юмемидзуки Мидзуки", "icon": "https://game-cdn.appsample.com/gim/items/yumemizuki_mizuki.png" },
265
  { "name": "Чжун Ли", "icon": "https://game-cdn.appsample.com/gim/items/zhongli.png" }
266
  ];
267
 
@@ -287,7 +357,9 @@
287
  // Состояние приложения
288
  let allCharacters = [...LOCAL_CHARACTERS];
289
  let historyTeams = JSON.parse(localStorage.getItem(`${currentUserUID}_genshinTeamsHistory`)) || [];
 
290
  let isSpinning = false;
 
291
 
292
  // Элементы DOM
293
  const spinButton = document.getElementById('spin-button');
@@ -307,6 +379,14 @@
307
  const confirmModalMessage = document.getElementById('confirm-modal-message');
308
  const confirmModalCancel = document.getElementById('confirm-modal-cancel');
309
  const confirmModalOk = document.getElementById('confirm-modal-ok');
 
 
 
 
 
 
 
 
310
 
311
  // Инициализация темы
312
  function initTheme() {
@@ -331,53 +411,10 @@
331
  settingsPanel.classList.toggle('open');
332
  }
333
 
334
- // Попытка загрузки персонажей из API
335
- async function tryFetchCharacters() {
336
- try {
337
- // Используем setTimeout для имитации задержки загрузки, чтобы показать лоадер
338
- setTimeout(async () => {
339
- rouletteLoader.classList.remove('hidden');
340
- roulettePlaceholder.classList.add('hidden');
341
- spinButton.disabled = true;
342
-
343
- // Имитация загрузки из API (реальный CORS запрос без прокси не пройдет)
344
- // В реальном приложении этот fetch будет работать, если API разрешит CORS
345
- // const response = await fetch('https://akasha.cv/api/filters/characters/?type=profile');
346
- // if (!response.ok) throw new Error('Ошибка загрузки данных');
347
- // const data = await response.json();
348
- // if (data && data.data && data.data[0] && data.data[0].options) {
349
- // allCharacters = data.data[0].options.map(char => ({
350
- // name: char.name,
351
- // icon: char.icon
352
- // }));
353
- // console.log('Загружено персонажей из API:', allCharacters.length);
354
- // } else {
355
- // throw new Error('Неверный формат данных');
356
- // }
357
-
358
- // В текущей реализации всегда используем локальные данные, т.к. CORS не позволяет
359
- allCharacters = [...LOCAL_CHARACTERS];
360
- console.log('Используем локальные данные персонажей:', allCharacters.length);
361
-
362
- rouletteLoader.classList.add('hidden');
363
- spinButton.disabled = false;
364
- roulettePlaceholder.classList.remove('hidden'); // Показываем плейсхолдер после загрузки
365
- }, 500); // Небольшая задержка для имитации загрузки
366
- } catch (error) {
367
- console.error('Ошибка загрузки персонажей:', error);
368
- allCharacters = [...LOCAL_CHARACTERS];
369
- console.log('Используем локальные данные персонажей (из-за ошибки загрузки):', allCharacters.length);
370
- rouletteLoader.classList.add('hidden');
371
- spinButton.disabled = false;
372
- roulettePlaceholder.classList.remove('hidden'); // Показываем плейсхолдер после загрузки
373
- }
374
- }
375
-
376
  // Создание карточки персонажа
377
- function createCharacterCard(character, isRoulette = false) {
378
  const card = document.createElement('div');
379
  card.className = `flex flex-col items-center p-2 rounded-lg bg-white dark:bg-gray-700 shadow-sm text-center flex-shrink-0 w-[100px] sm:w-[120px] md:w-[130px] lg:w-[140px]`;
380
- if (isRoulette) card.classList.add('roulette-char-card');
381
 
382
  card.innerHTML = `
383
  <img src="${character.icon}" alt="${character.name}"
@@ -388,40 +425,140 @@
388
  return card;
389
  }
390
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
391
  // Отображение результата рулетки с плавной анимацией
392
- function renderRouletteResult(team) {
393
  rouletteResult.innerHTML = '';
394
  roulettePlaceholder.classList.add('hidden');
395
 
396
- team.forEach((char, index) => {
397
- const card = createCharacterCard(char, true);
 
 
 
398
  rouletteResult.appendChild(card);
399
-
400
- // Анимация появления с задержкой
401
- setTimeout(() => {
402
- card.classList.add('show');
403
- }, index * 150); // Уменьшил задержку для более быстрого появления
404
- });
405
  }
406
 
407
- // Отображение истории
408
  function renderHistory() {
409
  historyContent.innerHTML = '';
410
 
411
  if (historyTeams.length === 0) {
412
  historyPlaceholder.classList.remove('hidden');
413
  clearHistoryButton.classList.add('hidden');
 
414
  } else {
415
  historyPlaceholder.classList.add('hidden');
416
  clearHistoryButton.classList.remove('hidden');
 
 
 
 
 
 
 
 
417
 
418
- historyTeams.forEach((team, index) => {
419
  const teamElement = document.createElement('div');
420
  teamElement.className = 'bg-[#FDF8F0] dark:bg-gray-800 rounded-xl p-4 shadow-sm border border-[#EFEAE4] dark:border-gray-600';
421
 
422
  const title = document.createElement('h3');
423
  title.className = 'text-lg font-semibold mb-3 dark:text-white';
424
- title.textContent = `Отряд ${historyTeams.length - index} (${new Date(team.date).toLocaleString()})`;
 
425
  teamElement.appendChild(title);
426
 
427
  const charsContainer = document.createElement('div');
@@ -437,16 +574,17 @@
437
  }
438
  }
439
 
440
- // Сохранение отряда в историю
441
- function saveTeamToHistory(team) {
442
  historyTeams.unshift({
443
  date: new Date().toISOString(),
444
- characters: team
 
445
  });
446
 
447
- // Ограничиваем историю последними 10 отрядами
448
- if (historyTeams.length > 10) {
449
- historyTeams = historyTeams.slice(0, 10);
450
  }
451
 
452
  localStorage.setItem(`${currentUserUID}_genshinTeamsHistory`, JSON.stringify(historyTeams));
@@ -463,63 +601,70 @@
463
 
464
  // Запуск рулетки
465
  async function spinRoulette() {
466
- if (isSpinning || allCharacters.length < config.teamSize) return;
 
 
 
 
 
467
 
468
  isSpinning = true;
469
  spinButton.disabled = true;
470
  spinButton.textContent = 'Крутим...';
471
- rouletteResult.innerHTML = ''; // Очищаем поле результата
472
  roulettePlaceholder.classList.add('hidden');
473
  rouletteLoader.classList.remove('hidden');
474
- rouletteResult.classList.add('roulette-spinning'); // Добавляем класс для анимации вращения
475
-
 
476
  const teamSize = parseInt(teamSizeSelect.value);
477
- let availableChars = [...allCharacters];
478
  const selectedTeam = [];
479
 
480
- let spinDurationBase; // Общая базовая продолжительность анимации
481
  switch (animationSpeedSelect.value) {
482
- case 'fast': spinDurationBase = 1000; break; // 1 секунда
483
- case 'slow': spinDurationBase = 3000; break; // 3 секунды
484
- default: spinDurationBase = 2000; // 2 секунды
485
  }
486
 
487
- const delayBetweenChars = spinDurationBase / (teamSize * 2); // Задержка между появлением каждого символа
488
- const totalSpinTimePerChar = spinDurationBase / teamSize; // Общее время "кручения" для каждого символа
489
 
490
  for (let i = 0; i < teamSize; i++) {
491
- // Анимируем "прокрутку" перед выбором каждого персонажа
492
- const tempRouletteChars = [];
493
- const numTempChars = 10; // Количество временных символов для прокрутки
494
- for (let j = 0; j < numTempChars; j++) {
495
- const randomChar = availableChars[Math.floor(Math.random() * availableChars.length)];
496
- tempRouletteChars.push(randomChar);
497
- }
498
-
499
- // Показываем временные символы с быстрой сменой
500
- for (let k = 0; k < numTempChars; k++) {
501
- setTimeout(() => {
502
- rouletteResult.innerHTML = '';
503
- const tempCard = createCharacterCard(tempRouletteChars[k], true);
504
- rouletteResult.appendChild(tempCard);
505
- tempCard.classList.add('roulette-item-enter-active'); // Применяем анимацию появления
506
- }, k * (totalSpinTimePerChar / numTempChars)); // Быстрая смена временных символов
507
- }
508
-
509
- // Выбираем окончательного персонажа после анимации прокрутки
510
- await new Promise(resolve => setTimeout(resolve, totalSpinTimePerChar)); // Задержка для анимации прокрутки
511
-
512
- const selectedIndex = Math.floor(Math.random() * availableChars.length);
513
- const selectedChar = availableChars.splice(selectedIndex, 1)[0];
514
- selectedTeam.push(selectedChar);
515
-
516
- // Очищаем и добавляем выбранного персонажа
517
- rouletteResult.innerHTML = ''; // Очищаем временные символы
518
- const finalCard = createCharacterCard(selectedChar, true);
519
- rouletteResult.appendChild(finalCard);
520
- finalCard.classList.add('show'); // Показываем выбранного персонажа с плавной анимацией
521
-
522
- await new Promise(resolve => setTimeout(resolve, delayBetweenChars)); // Задержка перед следующим персонажем
 
 
523
  }
524
 
525
  // Завершение рулетки
@@ -527,10 +672,9 @@
527
  spinButton.disabled = false;
528
  spinButton.textContent = 'Крутить ещё!';
529
  isSpinning = false;
530
- rouletteResult.classList.remove('roulette-spinning'); // Удаляем класс анимации вращения
531
 
532
- // Сохраняем отряд в историю
533
- saveTeamToHistory(selectedTeam);
534
  }
535
 
536
  // Модальное окно подтверждения
@@ -571,12 +715,35 @@
571
  themeToggle.addEventListener('click', toggleTheme);
572
  settingsToggle.addEventListener('click', toggleSettings);
573
  clearHistoryButton.addEventListener('click', () => {
574
- showConfirmModal('Вы уверены, что хотите очистить всю историю отрядов?', clearHistory);
 
 
 
575
  });
576
  confirmModal.addEventListener('click', (e) => {
577
  if (e.target === confirmModal) hideConfirmModal();
578
  });
579
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
580
  // Сохранение настроек при изменении
581
  teamSizeSelect.addEventListener('change', (e) => {
582
  config.teamSize = parseInt(e.target.value);
@@ -594,7 +761,7 @@
594
 
595
  // Инициализация приложения
596
  initTheme();
597
- tryFetchCharacters(); // Пытаемся загрузить данные с API, но используем локальные в случае ошибки
598
  renderHistory();
599
  });
600
  </script>
 
50
  transition: max-height 0.3s ease-out;
51
  }
52
  .settings-panel.open {
53
+ max-height: 1000px; /* Увеличено для вместимости содержимого, особенно для "Моих персонажей" */
54
  }
55
+ /* Улучшенная анимация для рулетки */
56
+ .roulette-item-spin {
57
+ animation: spin-in-place 0.2s ease-in-out infinite alternate;
58
  }
59
+ @keyframes spin-in-place {
60
+ 0% { transform: scale(0.9) rotate(-2deg); opacity: 0.7; }
61
+ 100% { transform: scale(1.1) rotate(2deg); opacity: 1; }
 
62
  }
63
+
64
+ /* Более объемная и живая анимация выпадения персонажа */
65
+ .roulette-item-final-enter {
66
  opacity: 0;
67
+ transform: scale(0.7) translateY(50px) rotateX(-90deg);
68
+ filter: blur(5px);
69
+ box-shadow: 0 0 0 rgba(0,0,0,0);
70
  }
71
+ .roulette-item-final-enter-active {
72
+ opacity: 1;
73
+ transform: scale(1) translateY(0) rotateX(0deg);
74
+ filter: blur(0);
75
+ transition: opacity 0.6s cubic-bezier(0.68, -0.55, 0.27, 1.55),
76
+ transform 0.6s cubic-bezier(0.68, -0.55, 0.27, 1.55),
77
+ filter 0.6s ease-out,
78
+ box-shadow 0.6s ease-out;
79
+ box-shadow: 0 10px 20px rgba(0,0,0,0.2);
80
+ }
81
+
82
+ .player-char-card {
83
+ position: relative;
84
+ cursor: pointer;
85
+ border: 2px solid transparent;
86
+ transition: border-color 0.2s;
87
+ }
88
+ .player-char-card.selected {
89
+ border-color: #DCA852;
90
+ }
91
+ .player-char-card .remove-btn {
92
+ position: absolute;
93
+ top: -5px;
94
+ right: -5px;
95
+ background-color: red;
96
+ color: white;
97
+ border-radius: 50%;
98
+ width: 20px;
99
+ height: 20px;
100
+ display: flex;
101
+ justify-content: center;
102
+ align-items: center;
103
+ font-size: 0.8rem;
104
+ font-weight: bold;
105
+ cursor: pointer;
106
+ opacity: 0;
107
+ transition: opacity 0.2s;
108
+ }
109
+ .player-char-card:hover .remove-btn {
110
  opacity: 1;
 
 
111
  }
112
  </style>
113
  </head>
 
127
  </svg>
128
  </button>
129
  </div>
130
+ <h1 class="text-4xl md:text-5xl font-bold text-[#4A4A4A] dark:text-[#e2e8f0] mb-2">Random Team</h1>
131
  <p class="text-lg text-[#6B6B6B] dark:text-[#a0aec0] max-w-2xl mx-auto">
132
  Сгенерируйте случайный отряд из четырех персонажей Genshin Impact!
133
  </p>
 
136
  <main>
137
  <div id="settings-panel" class="settings-panel bg-[#EFEAE4] dark:bg-gray-700 p-6 rounded-2xl shadow-lg mb-6">
138
  <h3 class="text-xl font-bold mb-4 dark:text-white">Настройки рулетки</h3>
139
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4 mb-6">
140
  <div>
141
  <label for="team-size" class="block text-sm font-medium mb-2 dark:text-gray-300">Количество персонажей в отряде</label>
142
  <select id="team-size" class="w-full p-2 rounded border border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-white">
 
155
  </select>
156
  </div>
157
  </div>
158
+
159
+ <h3 class="text-xl font-bold mb-4 dark:text-white">Мои персонажи</h3>
160
+ <p class="text-sm text-[#6B6B6B] dark:text-[#a0aec0] mb-4">
161
+ Выберите персонажей, которыми вы владеете, чтобы рулетка использовала только их. Если ни один не выбран, будут использоваться все персонажи.
162
+ </p>
163
+ <div class="mb-4">
164
+ <input type="text" id="character-search" placeholder="Поиск персонажей..." class="w-full p-2 rounded border border-gray-300 dark:border-gray-600 dark:bg-gray-800 dark:text-white">
165
+ </div>
166
+ <div id="player-characters-selection" class="grid grid-cols-3 sm:grid-cols-4 md:grid-cols-5 lg:grid-cols-6 gap-3 mb-6 max-h-60 overflow-y-auto pr-2">
167
+ </div>
168
+ <div class="text-center">
169
+ <button id="clear-player-characters" class="bg-red-500 text-white font-bold py-2 px-4 rounded-lg text-sm shadow-md hover:bg-red-600 transition-transform duration-200 ease-in-out hover:scale-105 focus:outline-none focus:ring-4 focus:ring-red-500/50 hidden">
170
+ Очистить выбранных персонажей
171
+ </button>
172
+ </div>
173
  </div>
174
 
175
  <section id="roulette-section" class="mb-16 bg-[#EFEAE4] dark:bg-gray-700 p-6 rounded-2xl shadow-lg">
 
183
  <p id="roulette-placeholder" class="text-[#888] dark:text-gray-400">Ваш случайный отряд появится здесь.</p>
184
  <div id="roulette-loader" class="loader hidden"></div>
185
  </div>
186
+
187
+ <div id="save-team-section" class="mt-6 p-4 bg-[#FDF8F0] dark:bg-gray-800 rounded-xl shadow-sm hidden">
188
+ <h3 class="text-lg font-semibold mb-3 dark:text-white">Сохранить этот отряд</h3>
189
+ <div class="flex flex-col sm:flex-row gap-3">
190
+ <input type="text" id="team-name-input" placeholder="Название отряда (необязательно)" class="flex-grow p-2 rounded border border-gray-300 dark:border-gray-600 dark:bg-gray-700 dark:text-white">
191
+ <button id="save-team-button" class="bg-[#A089D0] text-white font-bold py-2 px-6 rounded-lg shadow-md hover:bg-[#8e7abf] transition-transform duration-200 ease-in-out hover:scale-105">
192
+ Сохранить
193
+ </button>
194
+ </div>
195
+ </div>
196
+
197
  </section>
198
 
199
  <section id="history-section" class="bg-[#EFEAE4] dark:bg-gray-700 p-6 rounded-2xl shadow-lg">
200
  <div class="flex justify-between items-center mb-8">
201
  <h2 class="text-3xl font-bold text-[#4A4A4A] dark:text-white">История Отрядов</h2>
202
+ <div class="flex gap-2">
203
+ <button id="clear-history-button" class="bg-[#A089D0] text-white font-bold py-2 px-4 rounded-lg text-sm shadow-md hover:bg-[#8e7abf] transition-transform duration-200 ease-in-out hover:scale-105 focus:outline-none focus:ring-4 focus:ring-[#A089D0]/50 hidden">
204
+ Очистить
205
+ </button>
206
+ <button id="view-full-history-button" class="bg-[#DCA852] text-white font-bold py-2 px-4 rounded-lg text-sm shadow-md hover:bg-[#c3914a] transition-transform duration-200 ease-in-out hover:scale-105 focus:outline-none focus:ring-4 focus:ring-[#DCA852]/50 hidden">
207
+ Вся история
208
+ </button>
209
+ </div>
210
  </div>
211
  <div id="history-content" class="flex flex-col gap-6">
212
  <p id="history-placeholder" class="text-center text-[#888] dark:text-gray-400">История ваших отрядов будет отображаться здесь.</p>
 
224
  <div id="confirm-modal" class="fixed inset-0 bg-black bg-opacity-70 z-50 flex justify-center items-center hidden p-4">
225
  <div class="bg-[#FDF8F0] dark:bg-gray-800 rounded-2xl w-full max-w-sm shadow-2xl relative text-center p-6 transform transition-all duration-300 scale-95 opacity-0" id="confirm-modal-content">
226
  <h3 class="text-2xl font-bold mb-4 text-[#4A4A4A] dark:text-white">Подтверждение</h3>
227
+ <p id="confirm-modal-message" class="text-lg text-[#6B6B6B] dark:text-gray-300 mb-6"></p>
228
  <div class="flex justify-around gap-4">
229
  <button id="confirm-modal-cancel" class="bg-[#A089D0] text-white font-bold py-2 px-6 rounded-lg hover:bg-[#8e7abf]">Отмена</button>
230
  <button id="confirm-modal-ok" class="bg-red-500 text-white font-bold py-2 px-6 rounded-lg hover:bg-red-600">Очистить</button>
 
248
  { "name": "Беннет", "icon": "https://game-cdn.appsample.com/gim/items/bennett.png" },
249
  { "name": "Кандакия", "icon": "https://game-cdn.appsample.com/gim/items/candace.png" },
250
  { "name": "Шарлотта", "icon": "https://game-cdn.appsample.com/gim/items/charlotte.png" },
251
+ { "name": "Часка", "icon": "https://game-cdn.appsample.com/gim/items/chasca.png" },
252
+ { "name": "Тиори", "icon": "https://game-cdn.appsample.com/gim/items/chiori.png" },
253
  { "name": "Чун Юнь", "icon": "https://game-cdn.appsample.com/gim/items/chongyun.png" },
254
+ { "name": "Ситлали", "icon": "https://game-cdn.appsample.com/gim/items/citlali.png" },
255
  { "name": "Клоринда", "icon": "https://game-cdn.appsample.com/gim/items/clorinde.png" },
256
  { "name": "Коллеи", "icon": "https://game-cdn.appsample.com/gim/items/collei.png" },
257
  { "name": "Сайно", "icon": "https://game-cdn.appsample.com/gim/items/cyno.png" },
 
286
  { "name": "Сара", "icon": "https://game-cdn.appsample.com/gim/items/kujou_sara.png" },
287
  { "name": "Шинобу", "icon": "https://game-cdn.appsample.com/gim/items/kuki_shinobu.png" },
288
  { "name": "Лань Янь", "icon": "https://game-cdn.appsample.com/gim/items/lan_yan.png" },
289
+ { "name": "Лейла", "icon": "https://game-cdn.appsample.com/gim/items/layla.png" },
290
  { "name": "Лиза", "icon": "https://game-cdn.appsample.com/gim/items/lisa.png" },
291
  { "name": "Линнет", "icon": "https://game-cdn.appsample.com/gim/items/lynette.png" },
292
  { "name": "Лини", "icon": "https://game-cdn.appsample.com/gim/items/lyney.png" },
 
302
  { "name": "Ноэлль", "icon": "https://game-cdn.appsample.com/gim/items/noelle.png" },
303
  { "name": "Оророн", "icon": "https://game-cdn.appsample.com/gim/items/ororon.png" },
304
  { "name": "Ци Ци", "icon": "https://game-cdn.appsample.com/gim/items/qiqi.png" },
305
+ { "name": "Райдэн", "icon": "https://game-cdn.appsample.com/gim/items/raiden_shogun.png" },
306
  { "name": "Рэйзор", "icon": "https://game-cdn.appsample.com/gim/items/razor.png" },
307
+ { "name": "Розалья", "icon": "https://game-cdn.appsample.com/gim/items/rosaria.png" },
308
+ { "name": "Кокоми", "icon": "https://game-cdn.appsample.com/gim/items/sangonomiya_kokomi.png" },
309
  { "name": "Саю", "icon": "https://game-cdn.appsample.com/gim/items/sayu.png" },
310
+ { "name": "Сетус", "icon": "https://game-cdn.appsample.com/gim/items/sethos.png" },
311
  { "name": "Шэнь Хэ", "icon": "https://game-cdn.appsample.com/gim/items/shenhe.png" },
312
+ { "name": "Хэйдзо", "icon": "https://game-cdn.appsample.com/gim/items/shikanoin_heizou.png" },
313
+ { "name": "Сиджвин", "icon": "https://game-cdn.appsample.com/gim/items/sigewinne.png" },
314
  { "name": "Сахароза", "icon": "https://game-cdn.appsample.com/gim/items/sucrose.png" },
315
  { "name": "Тарталья", "icon": "https://game-cdn.appsample.com/gim/items/tartaglia.png" },
316
  { "name": "Тома", "icon": "https://game-cdn.appsample.com/gim/items/thoma.png" },
 
318
  { "name": "Вареса", "icon": "https://game-cdn.appsample.com/gim/items/varesa.png" },
319
  { "name": "Венти", "icon": "https://game-cdn.appsample.com/gim/items/venti.png" },
320
  { "name": "Странник", "icon": "https://game-cdn.appsample.com/gim/items/wanderer.png" },
321
+ { "name": "Ризли", "icon": "https://game-cdn.appsample.com/gim/items/wriothesley.png" },
322
  { "name": "Сяо", "icon": "https://game-cdn.appsample.com/gim/items/xiao.png" },
323
  { "name": "Сян Линь", "icon": "https://game-cdn.appsample.com/gim/items/xiangling.png" },
324
  { "name": "Сянь Юнь", "icon": "https://game-cdn.appsample.com/gim/items/xianyun.png" },
325
+ { "name": "Шилонен", "icon": "https://game-cdn.appsample.com/gim/items/xilonen.png" },
326
  { "name": "Син Цю", "icon": "https://game-cdn.appsample.com/gim/items/xingqiu.png" },
327
  { "name": "Синь Янь", "icon": "https://game-cdn.appsample.com/gim/items/xinyan.png" },
328
  { "name": "Яэ Мико", "icon": "https://game-cdn.appsample.com/gim/items/yae_miko.png" },
 
331
  { "name": "Е Лань", "icon": "https://game-cdn.appsample.com/gim/items/yelan.png" },
332
  { "name": "Ёимия", "icon": "https://game-cdn.appsample.com/gim/items/yoimiya.png" },
333
  { "name": "Юнь Цзинь", "icon": "https://game-cdn.appsample.com/gim/items/yun_jin.png" },
334
+ { "name": "Мидзуки", "icon": "https://game-cdn.appsample.com/gim/items/yumemizuki_mizuki.png" },
335
  { "name": "Чжун Ли", "icon": "https://game-cdn.appsample.com/gim/items/zhongli.png" }
336
  ];
337
 
 
357
  // Состояние приложения
358
  let allCharacters = [...LOCAL_CHARACTERS];
359
  let historyTeams = JSON.parse(localStorage.getItem(`${currentUserUID}_genshinTeamsHistory`)) || [];
360
+ let playerCharacters = JSON.parse(localStorage.getItem(`${currentUserUID}_playerCharacters`)) || [];
361
  let isSpinning = false;
362
+ let currentGeneratedTeam = []; // Для сохранения сгенерированного отряда перед именованием
363
 
364
  // Элементы DOM
365
  const spinButton = document.getElementById('spin-button');
 
379
  const confirmModalMessage = document.getElementById('confirm-modal-message');
380
  const confirmModalCancel = document.getElementById('confirm-modal-cancel');
381
  const confirmModalOk = document.getElementById('confirm-modal-ok');
382
+ const playerCharactersSelection = document.getElementById('player-characters-selection');
383
+ const characterSearchInput = document.getElementById('character-search');
384
+ const clearPlayerCharactersButton = document.getElementById('clear-player-characters');
385
+ const saveTeamSection = document.getElementById('save-team-section');
386
+ const teamNameInput = document.getElementById('team-name-input');
387
+ const saveTeamButton = document.getElementById('save-team-button');
388
+ const viewFullHistoryButton = document.getElementById('view-full-history-button');
389
+
390
 
391
  // Инициализация темы
392
  function initTheme() {
 
411
  settingsPanel.classList.toggle('open');
412
  }
413
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
414
  // Создание карточки персонажа
415
+ function createCharacterCard(character) {
416
  const card = document.createElement('div');
417
  card.className = `flex flex-col items-center p-2 rounded-lg bg-white dark:bg-gray-700 shadow-sm text-center flex-shrink-0 w-[100px] sm:w-[120px] md:w-[130px] lg:w-[140px]`;
 
418
 
419
  card.innerHTML = `
420
  <img src="${character.icon}" alt="${character.name}"
 
425
  return card;
426
  }
427
 
428
+ // Создание карточки персонажа для выбора (в секции "Мои персонажи")
429
+ function createPlayerCharacterSelectionCard(character) {
430
+ const card = document.createElement('div');
431
+ card.className = `player-char-card flex flex-col items-center p-1 rounded-lg bg-white dark:bg-gray-800 shadow-sm text-center cursor-pointer relative`;
432
+ card.setAttribute('data-name', character.name);
433
+
434
+ const isSelected = playerCharacters.some(c => c.name === character.name);
435
+ if (isSelected) {
436
+ card.classList.add('selected');
437
+ }
438
+
439
+ card.innerHTML = `
440
+ <img src="${character.icon}" alt="${character.name}"
441
+ class="w-12 h-12 rounded-full mb-1 object-cover border-2 border-transparent"
442
+ onerror="this.onerror=null;this.src='https://placehold.co/48x48/EFEAE4/4A4A4A?text=N/A'">
443
+ <p class="font-medium text-xs truncate w-full dark:text-white">${character.name}</p>
444
+ ${isSelected ? '<button class="remove-btn" title="Удалить">&times;</button>' : ''}
445
+ `;
446
+
447
+ const img = card.querySelector('img');
448
+ if (isSelected) {
449
+ img.classList.remove('border-transparent');
450
+ img.classList.add('border-[#DCA852]');
451
+ }
452
+
453
+ card.addEventListener('click', (event) => {
454
+ if (event.target.classList.contains('remove-btn')) {
455
+ removePlayerCharacter(character.name);
456
+ } else {
457
+ togglePlayerCharacter(character);
458
+ }
459
+ });
460
+
461
+ return card;
462
+ }
463
+
464
+ // Рендеринг списка персонажей для выбора
465
+ function renderPlayerCharactersSelection(filter = '') {
466
+ playerCharactersSelection.innerHTML = '';
467
+ const filteredCharacters = allCharacters.filter(char =>
468
+ char.name.toLowerCase().includes(filter.toLowerCase())
469
+ );
470
+
471
+ filteredCharacters.forEach(char => {
472
+ playerCharactersSelection.appendChild(createPlayerCharacterSelectionCard(char));
473
+ });
474
+ updateClearPlayerCharactersButtonVisibility();
475
+ }
476
+
477
+ // Добавление/удаление персонажа из списка игрока
478
+ function togglePlayerCharacter(character) {
479
+ const index = playerCharacters.findIndex(c => c.name === character.name);
480
+ if (index > -1) {
481
+ playerCharacters.splice(index, 1);
482
+ } else {
483
+ playerCharacters.push(character);
484
+ }
485
+ localStorage.setItem(`${currentUserUID}_playerCharacters`, JSON.stringify(playerCharacters));
486
+ renderPlayerCharactersSelection(characterSearchInput.value); // Перерисовываем с текущим фильтром
487
+ updateClearPlayerCharactersButtonVisibility();
488
+ }
489
+
490
+ // Удаление персонажа из списка игрока по имени
491
+ function removePlayerCharacter(characterName) {
492
+ playerCharacters = playerCharacters.filter(c => c.name !== characterName);
493
+ localStorage.setItem(`${currentUserUID}_playerCharacters`, JSON.stringify(playerCharacters));
494
+ renderPlayerCharactersSelection(characterSearchInput.value);
495
+ updateClearPlayerCharactersButtonVisibility();
496
+ }
497
+
498
+ // Очистка всех персонажей игрока
499
+ function clearPlayerCharacters() {
500
+ playerCharacters = [];
501
+ localStorage.removeItem(`${currentUserUID}_playerCharacters`);
502
+ renderPlayerCharactersSelection('');
503
+ hideConfirmModal();
504
+ }
505
+
506
+ // Обновление видимости кнопки "Очистить выбранных персонажей"
507
+ function updateClearPlayerCharactersButtonVisibility() {
508
+ if (playerCharacters.length > 0) {
509
+ clearPlayerCharactersButton.classList.remove('hidden');
510
+ } else {
511
+ clearPlayerCharactersButton.classList.add('hidden');
512
+ }
513
+ }
514
+
515
  // Отображение результата рулетки с плавной анимацией
516
+ async function renderRouletteResult(team) {
517
  rouletteResult.innerHTML = '';
518
  roulettePlaceholder.classList.add('hidden');
519
 
520
+ for (let i = 0; i < team.length; i++) {
521
+ const char = team[i];
522
+ const card = createCharacterCard(char);
523
+ card.classList.add('roulette-item-final-enter');
524
+
525
  rouletteResult.appendChild(card);
526
+
527
+ await new Promise(resolve => setTimeout(resolve, 50));
528
+ card.classList.add('roulette-item-final-enter-active');
529
+
530
+ await new Promise(resolve => setTimeout(resolve, 200));
531
+ }
532
  }
533
 
534
+ // Отображение истории (только последние 3)
535
  function renderHistory() {
536
  historyContent.innerHTML = '';
537
 
538
  if (historyTeams.length === 0) {
539
  historyPlaceholder.classList.remove('hidden');
540
  clearHistoryButton.classList.add('hidden');
541
+ viewFullHistoryButton.classList.add('hidden');
542
  } else {
543
  historyPlaceholder.classList.add('hidden');
544
  clearHistoryButton.classList.remove('hidden');
545
+ if (historyTeams.length > 3) { // Показываем кнопку "Вся история", если команд больше 3
546
+ viewFullHistoryButton.classList.remove('hidden');
547
+ } else {
548
+ viewFullHistoryButton.classList.add('hidden');
549
+ }
550
+
551
+ // Показываем только последние 3 отряда на главной странице
552
+ const teamsToShow = historyTeams.slice(0, 3);
553
 
554
+ teamsToShow.forEach((team, index) => {
555
  const teamElement = document.createElement('div');
556
  teamElement.className = 'bg-[#FDF8F0] dark:bg-gray-800 rounded-xl p-4 shadow-sm border border-[#EFEAE4] dark:border-gray-600';
557
 
558
  const title = document.createElement('h3');
559
  title.className = 'text-lg font-semibold mb-3 dark:text-white';
560
+ // Испол��зуем сохраненное имя, если оно есть, иначе генерируем
561
+ title.textContent = team.name ? team.name : `Отряд ${historyTeams.length - index} (${new Date(team.date).toLocaleString()})`;
562
  teamElement.appendChild(title);
563
 
564
  const charsContainer = document.createElement('div');
 
574
  }
575
  }
576
 
577
+ // Сохранение отряда в историю с возможностью добавления имени
578
+ function saveTeamToHistory(team, teamName = '') {
579
  historyTeams.unshift({
580
  date: new Date().toISOString(),
581
+ characters: team,
582
+ name: teamName // Добавляем имя
583
  });
584
 
585
+ // Ограничиваем историю последними 20 отрядами для общей истории (чтобы не было слишком много данных, но достаточно для просмотра)
586
+ if (historyTeams.length > 20) {
587
+ historyTeams = historyTeams.slice(0, 20);
588
  }
589
 
590
  localStorage.setItem(`${currentUserUID}_genshinTeamsHistory`, JSON.stringify(historyTeams));
 
601
 
602
  // Запуск рулетки
603
  async function spinRoulette() {
604
+ const availableCharsForSpin = playerCharacters.length > 0 ? playerCharacters : allCharacters;
605
+
606
+ if (isSpinning || availableCharsForSpin.length < config.teamSize) {
607
+ alert(`Недостаточно персонажей для формирования отряда из ${config.teamSize} человек. Доступно: ${availableCharsForSpin.length}`);
608
+ return;
609
+ }
610
 
611
  isSpinning = true;
612
  spinButton.disabled = true;
613
  spinButton.textContent = 'Крутим...';
614
+ rouletteResult.innerHTML = '';
615
  roulettePlaceholder.classList.add('hidden');
616
  rouletteLoader.classList.remove('hidden');
617
+ saveTeamSection.classList.add('hidden'); // Скрываем секцию сохранения при новом вращении
618
+ teamNameInput.value = ''; // Очищаем поле ввода имени
619
+
620
  const teamSize = parseInt(teamSizeSelect.value);
621
+ let charsPool = [...availableCharsForSpin];
622
  const selectedTeam = [];
623
 
624
+ let spinDurationMs;
625
  switch (animationSpeedSelect.value) {
626
+ case 'fast': spinDurationMs = 1500; break;
627
+ case 'slow': spinDurationMs = 4000; break;
628
+ default: spinDurationMs = 2500;
629
  }
630
 
631
+ const individualSpinTime = spinDurationMs / teamSize;
 
632
 
633
  for (let i = 0; i < teamSize; i++) {
634
+ const tempRouletteDiv = document.createElement('div');
635
+ tempRouletteDiv.className = 'flex flex-col items-center flex-shrink-0 w-[100px] sm:w-[120px] md:w-[130px] lg:w-[140px]';
636
+ rouletteResult.appendChild(tempRouletteDiv);
637
+
638
+ let startTime = Date.now();
639
+ let animationFrame;
640
+
641
+ const animateSpin = () => {
642
+ const elapsedTime = Date.now() - startTime;
643
+ if (elapsedTime < individualSpinTime) {
644
+ const randomChar = charsPool[Math.floor(Math.random() * charsPool.length)];
645
+ tempRouletteDiv.innerHTML = '';
646
+ const tempCard = createCharacterCard(randomChar);
647
+ tempCard.classList.add('roulette-item-spin');
648
+ tempRouletteDiv.appendChild(tempCard);
649
+ animationFrame = requestAnimationFrame(animateSpin);
650
+ } else {
651
+ cancelAnimationFrame(animationFrame);
652
+ const selectedIndex = Math.floor(Math.random() * charsPool.length);
653
+ const selectedChar = charsPool.splice(selectedIndex, 1)[0];
654
+ selectedTeam.push(selectedChar);
655
+
656
+ tempRouletteDiv.innerHTML = '';
657
+ const finalCard = createCharacterCard(selectedChar);
658
+ finalCard.classList.add('roulette-item-final-enter');
659
+ tempRouletteDiv.appendChild(finalCard);
660
+ setTimeout(() => {
661
+ finalCard.classList.add('roulette-item-final-enter-active');
662
+ }, 10);
663
+ }
664
+ };
665
+ animateSpin();
666
+
667
+ await new Promise(resolve => setTimeout(resolve, individualSpinTime + 100));
668
  }
669
 
670
  // Завершение рулетки
 
672
  spinButton.disabled = false;
673
  spinButton.textContent = 'Крутить ещё!';
674
  isSpinning = false;
 
675
 
676
+ currentGeneratedTeam = selectedTeam; // Сохраняем сгенерированный отряд
677
+ saveTeamSection.classList.remove('hidden'); // Показываем секцию сохранения
678
  }
679
 
680
  // Модальное окно подтверждения
 
715
  themeToggle.addEventListener('click', toggleTheme);
716
  settingsToggle.addEventListener('click', toggleSettings);
717
  clearHistoryButton.addEventListener('click', () => {
718
+ showConfirmModal(`UID:${currentUserUID} \r\rВы уверены, что хотите очистить всю историю отрядов?`, clearHistory);
719
+ });
720
+ clearPlayerCharactersButton.addEventListener('click', () => {
721
+ showConfirmModal('Вы уверены, что хотите очистить список ваших персонажей?', clearPlayerCharacters);
722
  });
723
  confirmModal.addEventListener('click', (e) => {
724
  if (e.target === confirmModal) hideConfirmModal();
725
  });
726
 
727
+ characterSearchInput.addEventListener('input', (e) => {
728
+ renderPlayerCharactersSelection(e.target.value);
729
+ });
730
+
731
+ saveTeamButton.addEventListener('click', () => {
732
+ const teamName = teamNameInput.value.trim();
733
+ if (currentGeneratedTeam.length > 0) {
734
+ saveTeamToHistory(currentGeneratedTeam, teamName);
735
+ saveTeamSection.classList.add('hidden'); // Скрываем секцию после сохранения
736
+ teamNameInput.value = ''; // Очищаем поле
737
+ currentGeneratedTeam = []; // Сбрасываем текущий отряд
738
+ }
739
+ });
740
+
741
+ viewFullHistoryButton.addEventListener('click', () => {
742
+ // Открываем новую вкладку для полной истории
743
+ showConfirmModal(`${currentUserUID} ${history-content}`);
744
+ });
745
+
746
+
747
  // Сохранение настроек при изменении
748
  teamSizeSelect.addEventListener('change', (e) => {
749
  config.teamSize = parseInt(e.target.value);
 
761
 
762
  // Инициализация приложения
763
  initTheme();
764
+ renderPlayerCharactersSelection();
765
  renderHistory();
766
  });
767
  </script>