PATH:
home
/
cardxfeb
/
public_html
/
resources
/
views
/
vcard
/
Editing: processing.blade.php
<!DOCTYPE html> <html lang="{{ app()->getLocale() }}"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="csrf-token" content="{{ csrf_token() }}"> <title>{{ __("Preparando seu Carto") }} CARD AO SEGUNDO CONTROL</title> <style> * { box-sizing: border-box; margin: 0; padding: 0; } body { font-family: 'Segoe UI', Arial, sans-serif; background: linear-gradient(135deg, #0f0c29, #302b63, #24243e); min-height: 100vh; display: flex; align-items: center; justify-content: center; color: #fff; } .card { background: rgba(255,255,255,0.05); backdrop-filter: blur(10px); border: 1px solid rgba(255,255,255,0.1); border-radius: 20px; padding: 50px 40px; text-align: center; max-width: 480px; width: 90%; box-shadow: 0 25px 50px rgba(0,0,0,0.4); } .logo { font-size: 13px; letter-spacing: 3px; color: #e94560; text-transform: uppercase; margin-bottom: 30px; } .spinner { width: 70px; height: 70px; border: 3px solid rgba(233,69,96,0.2); border-top: 3px solid #e94560; border-radius: 50%; animation: spin 1s linear infinite; margin: 0 auto 30px; } @keyframes spin { to { transform: rotate(360deg); } } h1 { font-size: 22px; font-weight: 700; margin-bottom: 12px; } .subtitle { color: rgba(255,255,255,0.6); font-size: 14px; line-height: 1.6; margin-bottom: 30px; } .steps { list-style: none; text-align: left; margin-bottom: 30px; } .steps li { display: flex; align-items: center; gap: 12px; padding: 10px 0; border-bottom: 1px solid rgba(255,255,255,0.07); font-size: 14px; color: rgba(255,255,255,0.7); } .steps li .dot { width: 8px; height: 8px; border-radius: 50%; background: rgba(255,255,255,0.3); flex-shrink: 0; transition: background 0.3s; } .steps li.active .dot { background: #e94560; animation: pulse 1s infinite; } .steps li.done .dot { background: #10b981; } @keyframes pulse { 0%,100%{transform:scale(1)}50%{transform:scale(1.4)} } .progress-bar { background: rgba(255,255,255,0.1); border-radius: 10px; height: 4px; overflow: hidden; margin-bottom: 20px; } .progress-fill { height: 100%; background: #e94560; border-radius: 10px; transition: width 2s ease; width: 15%; } .status-text { font-size: 13px; color: rgba(255,255,255,0.5); } #error-box { display: none; background: rgba(239,68,68,0.15); border: 1px solid rgba(239,68,68,0.4); border-radius: 8px; padding: 15px; margin-top: 20px; font-size: 13px; color: #fca5a5; } </style> </head> <body> <div class="card"> <div class="logo">CARD AO SEGUNDO CONTROL</div> <div class="spinner" id="spinner"></div> <h1 id="main-title"> @if(config('app.country') === 'PT') A IA est a criar o seu carto @else A IA est criando seu carto @endif </h1> <p class="subtitle"> @if(config('app.country') === 'PT') Estamos a analisar o seu perfil e a configurar o melhor template para si. Aguarde alguns instantes. @else Estamos analisando seu perfil e configurando o melhor template para voc. Aguarde alguns instantes. @endif </p> <ul class="steps"> <li class="active" id="step-1"> <span class="dot"></span> @if(config('app.country') === 'PT') A analisar o seu perfil social @else Analisando seu perfil social @endif </li> <li id="step-2"> <span class="dot"></span> @if(config('app.country') === 'PT') A escolher o melhor template @else Escolhendo o melhor template @endif </li> <li id="step-3"> <span class="dot"></span> @if(config('app.country') === 'PT') A preencher bio e cores @else Preenchendo bio e cores @endif </li> <li id="step-4"> <span class="dot"></span> @if(config('app.country') === 'PT') Carto pronto! @else Carto pronto! @endif </li> </ul> <div class="progress-bar"><div class="progress-fill" id="progress"></div></div> <p class="status-text" id="status-text"> @if(config('app.country') === 'PT') A processar... @else Processando... @endif </p> <div id="error-box"> @if(config('app.country') === 'PT') Ocorreu um erro ao gerar o carto. <a href="{{ route('user.vcard.create') }}" style="color:#e94560">Tentar novamente</a> @else Ocorreu um erro ao gerar o carto. <a href="{{ route('user.vcard.create') }}" style="color:#e94560">Tentar novamente</a> @endif </div> </div> <script> const vcardId = {{ $vcard->id }}; const pollUrl = '/api/vcard/' + vcardId + '/ai-status'; const csrfToken = document.querySelector('meta[name="csrf-token"]').content; let pollCount = 0; const maxPolls = 40; // 40 3s = 2 min max const steps = ['step-1', 'step-2', 'step-3', 'step-4']; const progress = document.getElementById('progress'); function setStep(n) { steps.forEach((id, i) => { const el = document.getElementById(id); el.className = i < n ? 'done' : (i === n ? 'active' : ''); }); progress.style.width = Math.min(15 + (n * 22), 95) + '%'; } async function poll() { pollCount++; if (pollCount > maxPolls) { document.getElementById('error-box').style.display = 'block'; document.getElementById('spinner').style.borderTopColor = '#ef4444'; return; } // Simulate steps while waiting const stepSim = Math.min(Math.floor(pollCount / 4), 2); setStep(stepSim); try { const res = await fetch(pollUrl, { headers: { 'X-CSRF-TOKEN': csrfToken, 'Accept': 'application/json' } }); const data = await res.json(); if (data.ai_status === 'completed') { setStep(3); document.getElementById('main-title').textContent = 'Carto pronto! '; document.getElementById('status-text').textContent = 'A redirecionar...'; progress.style.width = '100%'; setTimeout(() => { window.location.href = data.redirect_url || '/dashboard'; }, 1500); return; } if (data.ai_status === 'failed') { document.getElementById('error-box').style.display = 'block'; document.getElementById('spinner').style.borderTopColor = '#ef4444'; return; } } catch (e) { console.warn('Poll error:', e); } setTimeout(poll, 3000); } // Start polling after 2s initial delay setTimeout(poll, 2000); </script> </body> </html>
SAVE
CANCEL