Spaces:
Running
Running
| <html lang="en"> | |
| <head> | |
| <meta charset="utf-8"/> | |
| <meta name="viewport" content="width=device-width, initial-scale=1"/> | |
| <title>Create Contact Session | VCF Session</title> | |
| <style> | |
| :root { | |
| --primary: #2563eb; | |
| --primary-hover: #1d4ed8; | |
| --success: #059669; | |
| --error: #dc2626; | |
| --bg-primary: #ffffff; | |
| --bg-secondary: #f8fafc; | |
| --bg-card: #ffffff; | |
| --text-primary: #0f172a; | |
| --text-secondary: #64748b; | |
| --text-muted: #94a3b8; | |
| --border: #e2e8f0; | |
| --radius: 8px; | |
| --radius-lg: 12px; | |
| --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; | |
| --transition: all .2s cubic-bezier(.4,0,.2,1); | |
| } | |
| @media (prefers-color-scheme: dark) { | |
| :root { | |
| --primary: #3b82f6; | |
| --primary-hover: #2563eb; | |
| --bg-primary: #0f172a; | |
| --bg-secondary: #1e293b; | |
| --bg-card: #1e293b; | |
| --text-primary: #f1f5f9; | |
| --text-secondary: #cbd5e1; | |
| --text-muted: #64748b; | |
| --border: #334155; | |
| } | |
| } | |
| * { box-sizing: border-box; margin: 0; padding: 0; } | |
| body { | |
| font-family: var(--font-sans); | |
| background: var(--bg-secondary); | |
| color: var(--text-primary); | |
| display: flex; | |
| flex-direction: column; | |
| min-height: 100vh; | |
| } | |
| .container { | |
| width: 90%; | |
| max-width: 480px; | |
| margin: auto; | |
| padding: 2rem 0; | |
| } | |
| .card { | |
| background: var(--bg-card); | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius-lg); | |
| box-shadow: 0 10px 15px -3px rgb(0 0 0 / .07), 0 4px 6px -4px rgb(0 0 0 / .07); | |
| padding: 2rem; | |
| } | |
| .logo { | |
| height: 48px; | |
| margin: 0 auto 1.5rem; | |
| display: block; | |
| } | |
| .header { | |
| text-align: center; | |
| margin-bottom: 1.5rem; | |
| } | |
| .header h1 { | |
| font-size: 1.75rem; | |
| font-weight: 700; | |
| letter-spacing: -.025em; | |
| } | |
| .header p { | |
| color: var(--text-secondary); | |
| font-size: .9rem; | |
| } | |
| .form-group { | |
| margin-bottom: 1.5rem; | |
| } | |
| .form-label { | |
| display: block; | |
| font-size: .875rem; | |
| font-weight: 600; | |
| margin-bottom: .5rem; | |
| } | |
| .form-input { | |
| width: 100%; | |
| padding: .75rem 1rem; | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius); | |
| font-size: 1rem; | |
| background: var(--bg-primary); | |
| color: var(--text-primary); | |
| transition: border-color .2s, box-shadow .2s; | |
| } | |
| .form-input:focus { | |
| outline: none; | |
| border-color: var(--primary); | |
| box-shadow: 0 0 0 3px rgb(37 99 235 / .2); | |
| } | |
| .duration-grid { | |
| display: grid; | |
| grid-template-columns: repeat(2, 1fr); | |
| gap: .75rem; | |
| } | |
| .duration-option { | |
| position: relative; | |
| } | |
| .duration-radio { | |
| position: absolute; | |
| opacity: 0; | |
| pointer-events: none; | |
| } | |
| .duration-label { | |
| display: flex; | |
| align-items: center; | |
| justify-content: center; | |
| padding: .75rem 1rem; | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius); | |
| cursor: pointer; | |
| font-size: .875rem; | |
| font-weight: 500; | |
| background: var(--bg-primary); | |
| color: var(--text-secondary); | |
| transition: all .2s; | |
| } | |
| .duration-radio:checked + .duration-label { | |
| background: var(--primary); | |
| border-color: var(--primary); | |
| color: #fff; | |
| } | |
| .duration-label:hover { | |
| border-color: var(--primary); | |
| color: var(--primary); | |
| } | |
| .btn { | |
| width: 100%; | |
| padding: .875rem 1.5rem; | |
| font-size: 1rem; | |
| font-weight: 600; | |
| border: none; | |
| border-radius: var(--radius); | |
| cursor: pointer; | |
| transition: background .2s, transform .2s; | |
| position: relative; | |
| overflow: hidden; | |
| } | |
| .btn-primary { | |
| background: var(--primary); | |
| color: #fff; | |
| } | |
| .btn-primary:hover:not(:disabled) { | |
| background: var(--primary-hover); | |
| transform: translateY(-2px); | |
| } | |
| .btn:disabled { | |
| background: var(--text-muted); | |
| cursor: not-allowed; | |
| } | |
| .ripple { | |
| position: absolute; | |
| border-radius: 50%; | |
| transform: scale(0); | |
| background: rgba(255, 255, 255, .6); | |
| opacity: .6; | |
| animation: ripple .6s linear; | |
| } | |
| @keyframes ripple { | |
| to { | |
| transform: scale(4); | |
| opacity: 0; | |
| } | |
| } | |
| .success-box { | |
| display: none; | |
| text-align: center; | |
| } | |
| .success-box.show { | |
| display: block; | |
| } | |
| .url-box { | |
| background: var(--bg-secondary); | |
| border: 1px solid var(--border); | |
| border-radius: var(--radius); | |
| padding: 1rem; | |
| margin: 1rem 0; | |
| display: flex; | |
| gap: .75rem; | |
| } | |
| .url-input { | |
| flex: 1; | |
| border: none; | |
| background: transparent; | |
| color: var(--text-primary); | |
| font-family: ui-monospace, SFMono-Regular, "SF Mono", Consolas, "Liberation Mono", Menlo, monospace; | |
| font-size: .875rem; | |
| outline: none; | |
| } | |
| .copy-btn { | |
| padding: .5rem 1rem; | |
| background: var(--primary); | |
| color: #fff; | |
| border: none; | |
| border-radius: var(--radius); | |
| cursor: pointer; | |
| font-size: .875rem; | |
| transition: background .2s; | |
| } | |
| .copy-btn:hover { | |
| background: var(--primary-hover); | |
| } | |
| .copy-btn.copied { | |
| background: var(--success); | |
| } | |
| .footer { | |
| position: fixed; | |
| bottom: 1rem; | |
| left: 50%; | |
| transform: translateX(-50%); | |
| font-size: .875rem; | |
| color: var(--text-muted); | |
| } | |
| .footer a { | |
| color: var(--primary); | |
| text-decoration: none; | |
| } | |
| .footer a:hover { | |
| text-decoration: underline; | |
| } | |
| @media (max-width: 640px) { | |
| .duration-grid { | |
| grid-template-columns: 1fr; | |
| } | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <div class="container"> | |
| <div class="card"> | |
| <img src="http://165.227.176.133:2137/media/logo.svg" alt="VCF Session" class="logo"> | |
| <div id="createBox"> | |
| <div class="header"> | |
| <h1>Create Contact Session</h1> | |
| <p>Share contacts securely with automatic expiration</p> | |
| </div> | |
| <form id="createForm"> | |
| <div class="form-group"> | |
| <label for="sessionName" class="form-label">Session Name</label> | |
| <input id="sessionName" type="text" class="form-input" placeholder="e.g. Team Meeting Contacts" maxlength="60" required autocomplete="off"> | |
| </div> | |
| <div class="form-group"> | |
| <label class="form-label">Session Duration</label> | |
| <div class="duration-grid"> | |
| <div class="duration-option"> | |
| <input type="radio" id="dur5" name="duration" value="5" class="duration-radio"> | |
| <label for="dur5" class="duration-label">5 min</label> | |
| </div> | |
| <div class="duration-option"> | |
| <input type="radio" id="dur15" name="duration" value="15" class="duration-radio"> | |
| <label for="dur15" class="duration-label">15 min</label> | |
| </div> | |
| <div class="duration-option"> | |
| <input type="radio" id="dur30" name="duration" value="30" class="duration-radio" checked> | |
| <label for="dur30" class="duration-label">30 min</label> | |
| </div> | |
| <div class="duration-option"> | |
| <input type="radio" id="dur60" name="duration" value="60" class="duration-radio"> | |
| <label for="dur60" class="duration-label">1 hr</label> | |
| </div> | |
| <div class="duration-option"> | |
| <input type="radio" id="dur300" name="duration" value="300" class="duration-radio"> | |
| <label for="dur300" class="duration-label">5 hrs</label> | |
| </div> | |
| <div class="duration-option"> | |
| <input type="radio" id="dur420" name="duration" value="420" class="duration-radio"> | |
| <label for="dur420" class="duration-label">7 hrs</label> | |
| </div> | |
| </div> | |
| </div> | |
| <button type="submit" class="btn btn-primary">Create Session</button> | |
| </form> | |
| </div> | |
| <div id="successBox" class="success-box"> | |
| <div class="header"> | |
| <div class="success-icon">✓</div> | |
| <h2>Session Created!</h2> | |
| <p>Share this link with participants to collect contacts</p> | |
| </div> | |
| <div class="url-box"> | |
| <input id="urlInput" type="text" class="url-input" readonly> | |
| <button id="copyBtn" class="copy-btn">Copy</button> | |
| </div> | |
| <button id="newBtn" class="btn btn-primary">Create Another Session</button> | |
| </div> | |
| </div> | |
| <div class="footer"> | |
| Join our WhatsApp group: | |
| <a href="https://chat.whatsapp.com/JRe69IJCINM3qYX3gM8MI9?mode=ems_copy_c" target="_blank" rel="noopener">VCF GROUP</a> | |
| </div> | |
| </div> | |
| <script> | |
| const createForm = document.getElementById('createForm'); | |
| const createBox = document.getElementById('createBox'); | |
| const successBox = document.getElementById('successBox'); | |
| const urlInput = document.getElementById('urlInput'); | |
| const copyBtn = document.getElementById('copyBtn'); | |
| const newBtn = document.getElementById('newBtn'); | |
| createForm.addEventListener('submit', async e => { | |
| e.preventDefault(); | |
| const name = createForm.sessionName.value.trim(); | |
| const mins = createForm.duration.value; | |
| if (!name) return; | |
| const res = await fetch('/api/create', { | |
| method: 'POST', | |
| headers: { 'Content-Type': 'application/json' }, | |
| body: JSON.stringify({ sessionName: name, minutes: parseInt(mins) }) | |
| }); | |
| const data = await res.json(); | |
| if (!res.ok) return alert(data.error || 'Creation failed'); | |
| const url = `http://165.227.176.133:2137/session/${data.id}`; | |
| urlInput.value = url; | |
| createBox.style.display = 'none'; | |
| successBox.classList.add('show'); | |
| }); | |
| copyBtn.onclick = async () => { | |
| await navigator.clipboard.writeText(urlInput.value); | |
| copyBtn.textContent = 'Copied'; | |
| copyBtn.classList.add('copied'); | |
| setTimeout(() => { | |
| copyBtn.textContent = 'Copy'; | |
| copyBtn.classList.remove('copied'); | |
| }, 2000); | |
| }; | |
| newBtn.onclick = () => location.reload(); | |
| </script> | |
| </body> | |
| </html> | |