feat: init premium random group selector with custom sizes and scroll prevention

This commit is contained in:
JooWangi
2026-07-22 12:27:24 +09:00
commit e910696fbe
5 changed files with 2420 additions and 0 deletions
+261
View File
@@ -0,0 +1,261 @@
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Premium Random Group Selector | 무작위 인원 그룹 추첨기</title>
<!-- Google Fonts: Inter & Outfit & Noto Sans KR -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&family=Outfit:wght@400;500;600;700;800&family=Noto+Sans+KR:wght@300;400;500;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="app-container">
<!-- Header -->
<header class="app-header">
<div class="logo-area">
<div class="logo-icon">
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round">
<rect x="3" y="3" width="7" height="7" rx="1.5"></rect>
<rect x="14" y="3" width="7" height="7" rx="1.5"></rect>
<rect x="14" y="14" width="7" height="7" rx="1.5"></rect>
<rect x="3" y="14" width="7" height="7" rx="1.5"></rect>
</svg>
</div>
<div class="logo-text">
<h1>RANDOM SELECTOR</h1>
<span class="badge">PRO GROUPING</span>
</div>
</div>
<div class="header-right">
<div class="status-summary">
<div class="stat-pill">
<span class="label">전체 인원</span>
<span class="value" id="stat-total">0</span>
</div>
<div class="stat-pill highlight-pill">
<span class="label">남은 대기</span>
<span class="value" id="stat-remaining">0</span>
</div>
<div class="stat-pill">
<span class="label">완료 그룹</span>
<span class="value" id="stat-groups">0</span>
</div>
</div>
<!-- Settings Modal Trigger Icon Button -->
<button type="button" class="btn btn-secondary btn-icon-setting" id="btn-open-modal" title="명단 및 설정 변경">
<span class="icon">⚙️</span>
<span class="btn-text">설정 & 명단</span>
</button>
</div>
</header>
<!-- Main Single Column Layout -->
<main class="main-single-layout">
<!-- Top Main Action Controls Bar -->
<section class="main-action-bar">
<div class="action-info">
<span class="mode-indicator" id="current-mode-indicator">추첨 방식: 그룹 당 4명</span>
</div>
<div class="action-buttons-group">
<button type="button" class="btn btn-outline btn-md" id="btn-open-modal-sub">
⚙️ 명단/설정 변경
</button>
<button type="button" class="btn btn-primary btn-md" id="btn-draw-group">
<span class="btn-sparkle"></span>
<span class="btn-text" id="draw-btn-text">다음 1개 그룹 추첨</span>
</button>
<button type="button" class="btn btn-accent btn-md" id="btn-draw-all">
⚡ 남은 전체 한 번에 배치
</button>
</div>
</section>
<!-- Full-Width Live Draw Stage -->
<section class="stage-section">
<div class="draw-stage" id="draw-stage">
<!-- Active Drawing / Result Display (Always Visible) -->
<div class="active-draw-display" id="active-draw-display">
<div class="drawing-header">
<span class="group-title-badge" id="drawing-group-title">READY</span>
<span class="drawing-status-text" id="drawing-status-text">추첨 대기 중</span>
</div>
<div class="cards-grid grid-size-lg" id="drawing-cards-container">
<div class="initial-placeholder">
<span class="placeholder-icon"></span>
<p>상단의 <strong>[다음 1개 그룹 추첨]</strong> 버튼을 눌러 그룹 편성을 시작하세요.</p>
</div>
</div>
</div>
</div>
<!-- Completed Groups Results Area -->
<div class="results-area">
<div class="results-header">
<h3><span class="icon">🏆</span> 생성된 그룹 목록</h3>
<div class="results-actions">
<button type="button" class="btn btn-sm btn-ghost" id="btn-copy-results">📋 결과 복사</button>
<button type="button" class="btn btn-sm btn-ghost" id="btn-reset-all">🔄 전체 리셋</button>
</div>
</div>
<div class="groups-grid" id="groups-container">
<div class="empty-results" id="empty-results">
아직 추첨된 그룹이 없습니다.
</div>
</div>
</div>
</section>
</main>
<!-- Canvas for Particle / Confetti -->
<canvas id="confetti-canvas"></canvas>
<!-- ==========================================================================
SETTINGS & MEMBER MANAGEMENT MODAL WINDOW
========================================================================== -->
<div class="modal-overlay hidden" id="settings-modal">
<div class="modal-content">
<!-- Modal Header -->
<div class="modal-header">
<div class="modal-tabs">
<button type="button" class="modal-tab-btn active" data-tab="tab-members">📊 명단 관리 (표)</button>
<button type="button" class="modal-tab-btn" data-tab="tab-settings">⚙️ 그룹 & 연출 설정</button>
</div>
<button type="button" class="modal-close-btn" id="btn-close-modal" title="닫기"></button>
</div>
<!-- Modal Body -->
<div class="modal-body">
<!-- TAB 1: Member Table Management -->
<div class="tab-pane active" id="tab-members">
<div class="panel-header-sub">
<div class="preset-group">
<span class="sub-title">빠른 49명 생성:</span>
<button type="button" class="btn btn-xs btn-outline" id="btn-preset-49num">1~49번</button>
<button type="button" class="btn btn-xs btn-outline" id="btn-preset-49names">샘플이름</button>
</div>
<div class="input-mode-toggle">
<button type="button" class="btn btn-xs btn-ghost active" id="btn-mode-table">📊 표 모드</button>
<button type="button" class="btn btn-xs btn-ghost" id="btn-mode-text">📝 텍스트 일괄입력</button>
</div>
</div>
<!-- Table View Container -->
<div class="member-view-box" id="table-view-container">
<div class="table-actions-bar">
<button type="button" class="btn btn-xs btn-secondary" id="btn-add-row"> 인원 추가</button>
<button type="button" class="btn btn-xs btn-ghost" id="btn-clear-table">🗑️ 전체 비우기</button>
<span class="table-count-badge" id="table-count-badge">총 0명</span>
</div>
<div class="member-table-wrapper">
<table class="member-table">
<thead>
<tr>
<th style="width: 55px;">#</th>
<th>이름</th>
<th style="width: 60px; text-align: center;">삭제</th>
</tr>
</thead>
<tbody id="member-table-body">
<!-- Dynamic Table Rows -->
</tbody>
</table>
</div>
</div>
<!-- Text Area View Container (Hidden by default) -->
<div class="member-view-box hidden" id="text-view-container">
<div class="input-group">
<textarea id="member-input" placeholder="이름을 줄바꿈이나 콤마로 구분하여 대량 입력하세요.&#10;예:&#10;홍길동&#10;김철수&#10;이영희..."></textarea>
</div>
</div>
</div>
<!-- TAB 2: Group & Animation Settings -->
<div class="tab-pane" id="tab-settings">
<div class="setting-group">
<label class="setting-label">추첨 방식 선택</label>
<div class="radio-toggle stacked-toggle">
<input type="radio" name="group-mode" id="mode-per-group" value="per-group" checked>
<label for="mode-per-group">그룹 당 동일 N명</label>
<input type="radio" name="group-mode" id="mode-total-groups" value="total-groups">
<label for="mode-total-groups">총 N개 그룹 균등</label>
<input type="radio" name="group-mode" id="mode-custom-groups" value="custom-groups">
<label for="mode-custom-groups">🛠️ 그룹별 명수 개별 지정 (커스텀)</label>
</div>
</div>
<!-- Uniform Mode Controls -->
<div class="setting-row inline-input" id="uniform-mode-controls">
<label for="group-size-val" id="mode-size-label">한 그룹당 인원수</label>
<div class="number-stepper">
<button type="button" id="btn-size-minus">-</button>
<input type="number" id="group-size-val" value="4" min="1" max="50">
<button type="button" id="btn-size-plus">+</button>
</div>
</div>
<!-- Custom Mode Builder Controls -->
<div class="custom-builder-container hidden" id="custom-builder-container">
<div class="custom-builder-header">
<span>개별 그룹 구성 목록</span>
<span class="total-custom-badge" id="custom-total-badge">설정: 0명</span>
</div>
<div class="custom-groups-list" id="custom-groups-list">
<!-- Dynamic Custom Group Rows -->
</div>
<button type="button" class="btn btn-xs btn-outline btn-full" id="btn-add-custom-group">
➕ 그룹 추가
</button>
</div>
<hr class="modal-divider">
<div class="setting-group">
<label class="setting-label">애니메이션 연출 속도</label>
<div class="radio-toggle speed-toggle">
<input type="radio" name="anim-speed" id="speed-fast" value="fast" checked>
<label for="speed-fast">🚀 터보 (0.6초)</label>
<input type="radio" name="anim-speed" id="speed-normal" value="normal">
<label for="speed-normal">⚡ 보통 (1.4초)</label>
<input type="radio" name="anim-speed" id="speed-instant" value="instant">
<label for="speed-instant">⚡ 즉시</label>
</div>
</div>
<div class="setting-row toggle-row">
<span>사운드 효과음</span>
<label class="switch">
<input type="checkbox" id="toggle-sound" checked>
<span class="slider"></span>
</label>
</div>
</div>
</div>
<!-- Modal Footer -->
<div class="modal-footer">
<button type="button" class="btn btn-primary btn-md btn-full" id="btn-save-modal">
✨ 저장 및 적용하기
</button>
</div>
</div>
</div>
</div>
<script src="audio.js"></script>
<script src="app.js"></script>
</body>
</html>