diff --git a/app.js b/app.js new file mode 100644 index 0000000..2ca9501 --- /dev/null +++ b/app.js @@ -0,0 +1,197 @@ +/** + * Anvil Hosting - Main Application JavaScript + * 가격 데이터 및 Alpine.js 컴포넌트 정의 + */ + +// 단일 가격 데이터 소스 (VAT 포함, 월간 기준) +const PRICING_DATA = { + global: [ + { plan: 'Micro', vcpu: '1 Core', ram: '1 GB', ssd: '25 GB', transfer: '1 TB', price: 8500 }, + { plan: 'Starter', vcpu: '1 Core', ram: '2 GB', ssd: '50 GB', transfer: '2 TB', price: 20400 }, + { plan: 'Pro', vcpu: '2 Cores', ram: '4 GB', ssd: '80 GB', transfer: '4 TB', price: 40700, featured: true }, + { plan: 'Business', vcpu: '4 Cores', ram: '8 GB', ssd: '160 GB', transfer: '5 TB', price: 67800 } + ], + seoul: [ + { plan: 'Nano', vcpu: '1 Core', ram: '512 MB', ssd: '20 GB', transfer: '1 TB', price: 6000 }, + { plan: 'Micro', vcpu: '1 Core', ram: '1 GB', ssd: '40 GB', transfer: '2 TB', price: 8500 }, + { plan: 'Starter', vcpu: '1 Core', ram: '2 GB', ssd: '60 GB', transfer: '3 TB', price: 17000 }, + { plan: 'Pro', vcpu: '2 Cores', ram: '4 GB', ssd: '80 GB', transfer: '4 TB', price: 33900, featured: true }, + { plan: 'Business', vcpu: '2 Cores', ram: '8 GB', ssd: '160 GB', transfer: '5 TB', price: 67800 } + ] +}; + +// 런처 모달용 가격 (plan명 기준) +const LAUNCHER_PRICES = { + 'Micro': { base: 8500, seoul: 8500 }, + 'Starter': { base: 20400, seoul: 17000 }, + 'Pro': { base: 40700, seoul: 33900 }, + 'Business': { base: 67800, seoul: 67800 } +}; + +// 플랜별 스펙 정보 +const PLAN_SPECS = { + 'Micro': '1vCPU / 1GB RAM', + 'Starter': '1vCPU / 2GB RAM', + 'Pro': '2vCPU / 4GB RAM', + 'Business': '4vCPU / 8GB RAM' +}; + +/** + * 가격 포맷팅 (한국 원화) + */ +function formatPrice(price) { + return '₩' + price.toLocaleString('ko-KR'); +} + +/** + * Alpine.js 메인 앱 데이터 + */ +function anvilApp() { + return { + // 모달 상태 + launcherOpen: false, + launching: false, + step: 0, + + // 서버 구성 + config: { + region: 'Tokyo', + os: 'Debian 12', + plan: 'Pro' + }, + + // 배포 로그 + logs: [], + + // 가격 조회 + getPrice(plan) { + const prices = LAUNCHER_PRICES[plan]; + if (!prices) return '0'; + const price = this.config.region === 'Seoul' ? prices.seoul : prices.base; + return price.toLocaleString('ko-KR'); + }, + + // 플랜 스펙 조회 + getPlanSpec(plan) { + return PLAN_SPECS[plan] || ''; + }, + + // 서버 배포 시작 + startLaunch() { + this.launching = true; + this.step = 1; + this.logs = [ + '[INFO] Initializing deployment...', + '[INFO] Selecting node in ' + this.config.region + '...', + '[INFO] Pulling ' + this.config.os + ' image...' + ]; + + setTimeout(() => { + this.logs.push('[SUCCESS] Image pulled.'); + this.logs.push('[INFO] Creating container instance...'); + this.step = 2; + }, 1500); + + setTimeout(() => { + this.logs.push('[SUCCESS] Container created.'); + this.logs.push('[INFO] Configuring network & firewall...'); + this.step = 3; + }, 3000); + + setTimeout(() => { + const randomIP = Math.floor(Math.random() * 254 + 1); + this.logs.push('[SUCCESS] Network ready. IP: 45.12.89.' + randomIP); + this.logs.push('[INFO] Starting system services...'); + this.step = 4; + }, 4500); + + setTimeout(() => { + this.launching = false; + this.step = 5; + this.logs.push('[COMPLETE] Server is now live!'); + }, 6000); + }, + + // 런처 초기화 + resetLauncher() { + this.launcherOpen = false; + this.launching = false; + this.step = 0; + this.logs = []; + }, + + // ESC 키로 모달 닫기 + handleKeydown(event) { + if (event.key === 'Escape' && this.launcherOpen && !this.launching) { + this.resetLauncher(); + } + } + }; +} + +/** + * 가격표 컴포넌트 + */ +function pricingTable() { + return { + region: 'global', + + get plans() { + return PRICING_DATA[this.region] || []; + }, + + formatPrice(price) { + return formatPrice(price); + }, + + isSeoul() { + return this.region === 'seoul'; + } + }; +} + +/** + * 탭 전환 (n8n/Terraform) + */ +function switchTab(tab) { + const btnN8n = document.getElementById('btn-n8n'); + const btnTf = document.getElementById('btn-tf'); + const panelN8n = document.getElementById('panel-n8n'); + const panelTf = document.getElementById('panel-tf'); + + if (tab === 'n8n') { + btnN8n.className = 'px-4 py-2 rounded-lg bg-purple-600 text-white text-sm font-bold transition shadow-lg shadow-purple-500/20'; + btnTf.className = 'px-4 py-2 rounded-lg bg-slate-800 text-slate-400 text-sm font-bold border border-slate-700 hover:text-white transition'; + panelN8n.classList.remove('hidden'); + panelTf.classList.add('hidden'); + } else { + btnN8n.className = 'px-4 py-2 rounded-lg bg-slate-800 text-slate-400 text-sm font-bold border border-slate-700 hover:text-white transition'; + btnTf.className = 'px-4 py-2 rounded-lg bg-blue-600 text-white text-sm font-bold transition shadow-lg shadow-blue-500/20'; + panelN8n.classList.add('hidden'); + panelTf.classList.remove('hidden'); + } +} + +/** + * 실시간 Ping 시뮬레이션 + */ +function updatePing() { + const regions = [ + { id: 'ping-kr', base: 2, variance: 2 }, + { id: 'ping-jp', base: 35, variance: 5 }, + { id: 'ping-hk', base: 45, variance: 8 }, + { id: 'ping-sg', base: 65, variance: 10 } + ]; + + regions.forEach(region => { + const el = document.getElementById(region.id); + if (el) { + const jitter = Math.floor(Math.random() * region.variance) - (region.variance / 2); + let val = Math.max(1, Math.floor(region.base + jitter)); + el.innerText = val; + } + }); +} + +// Ping 업데이트 시작 +setInterval(updatePing, 2000); diff --git a/index.html b/index.html index 9bc4439..3d3b8f9 100644 --- a/index.html +++ b/index.html @@ -4,75 +4,47 @@ Anvil Hosting - 개발자를 위한 컨테이너 클라우드 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + - +