- Add Python/FastAPI backend with Celery workers - Add video generation with FFmpeg (spinning record animation) - Add API endpoints: submissions, status polling, webhook, results - Add database schema and Alembic migrations - Update frontend pages with API integration - Add project documentation and spec Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
115 lines
No EOL
4.7 KiB
PHP
115 lines
No EOL
4.7 KiB
PHP
<!DOCTYPE html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||
<link rel="apple-touch-icon" sizes="180x180" href="apple-touch-icon.png">
|
||
<link rel="icon" type="image/png" sizes="32x32" href="favicon-32x32.png">
|
||
<link rel="icon" type="image/png" sizes="16x16" href="favicon-16x16.png">
|
||
<title>Pets at Home</title>
|
||
<meta name="description" content="Create a personalized love song for your pet with our fun and easy tool.">
|
||
<link rel="stylesheet" href="assets/css/style.css">
|
||
|
||
<?php include('opengraph.php'); ?>
|
||
</head>
|
||
<body>
|
||
<div class="container">
|
||
|
||
<?php include('header.php'); ?>
|
||
|
||
<div class="body-container">
|
||
|
||
<img class="jukebox-banner-mb" src="assets/images/jukebox-banner-mb.png" alt="Jukebox" />
|
||
<img class="jukebox-banner-dt" src="assets/images/jukebox-banner-dt.png" alt="Jukebox" />
|
||
|
||
<div class="title">Your Pet Love Song <br/>is on its way.</div>
|
||
<div class="sub-title">Won’t take a minute...</div>
|
||
|
||
<img class="melody-record" src="assets/images/unleashedmelody.gif" alt="Melody Record" />
|
||
|
||
</div>
|
||
|
||
<?php include('footer.php'); ?>
|
||
|
||
</div>
|
||
|
||
<script>
|
||
(function() {
|
||
// Get session_id from URL query parameter
|
||
const urlParams = new URLSearchParams(window.location.search);
|
||
const sessionId = urlParams.get('session_id');
|
||
|
||
if (!sessionId) {
|
||
// No session_id, redirect to home
|
||
window.location.href = '/';
|
||
return;
|
||
}
|
||
|
||
const API_URL = window.location.origin;
|
||
const POLL_INTERVAL = 10000; // 10 seconds
|
||
const MAX_POLL_TIME = 300000; // 5 minutes
|
||
const startTime = Date.now();
|
||
let pollTimer = null;
|
||
|
||
async function pollStatus() {
|
||
// Check if we've exceeded max poll time
|
||
if (Date.now() - startTime > MAX_POLL_TIME) {
|
||
clearInterval(pollTimer);
|
||
showTimeoutError();
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const response = await fetch(`${API_URL}/api/submissions/${sessionId}/status`);
|
||
|
||
if (!response.ok) {
|
||
if (response.status === 404) {
|
||
// Session not found, redirect to home
|
||
window.location.href = '/';
|
||
return;
|
||
}
|
||
console.error('Status check failed:', response.status);
|
||
return;
|
||
}
|
||
|
||
const data = await response.json();
|
||
|
||
if (data.status === 'success') {
|
||
// Generation complete, redirect to result page
|
||
clearInterval(pollTimer);
|
||
window.location.href = `result.php?session_id=${sessionId}`;
|
||
} else if (data.status === 'fail') {
|
||
// Generation failed, redirect to result page (shows failure message)
|
||
clearInterval(pollTimer);
|
||
window.location.href = `result.php?session_id=${sessionId}`;
|
||
}
|
||
// For 'pending' or 'processing', continue polling
|
||
} catch (error) {
|
||
console.error('Error polling status:', error);
|
||
// Continue polling on network errors
|
||
}
|
||
}
|
||
|
||
function showTimeoutError() {
|
||
const bodyContainer = document.querySelector('.body-container');
|
||
if (bodyContainer) {
|
||
bodyContainer.innerHTML = `
|
||
<div class="title">Taking longer than expected...</div>
|
||
<div class="sub-title">Your song is still being created. Please check back in a few minutes.</div>
|
||
<button onclick="window.location.reload()" style="margin-top: 20px; padding: 10px 20px; cursor: pointer;">
|
||
Check Again
|
||
</button>
|
||
<button onclick="window.location.href='/'" style="margin-top: 10px; padding: 10px 20px; cursor: pointer;">
|
||
Create New Song
|
||
</button>
|
||
`;
|
||
}
|
||
}
|
||
|
||
// Start polling immediately and then every 10 seconds
|
||
pollStatus();
|
||
pollTimer = setInterval(pollStatus, POLL_INTERVAL);
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html>
|