- 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>
260 lines
No EOL
11 KiB
PHP
260 lines
No EOL
11 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">
|
||
|
||
<div class="pets-text-logo"></div>
|
||
|
||
<div class="title1">My Pet Love Song.</div>
|
||
|
||
<!--<img class="dog-record" src="assets/images/dog-record.png" alt="Dog Record" />-->
|
||
|
||
<div class="record-container">
|
||
<img class="dog-record rotate" src="assets/images/blank-record.png" alt="Dog Record" id="pet-record" />
|
||
<img class="record-needle" src="assets/images/needle.png" alt="Record Needle" />
|
||
</div>
|
||
|
||
<!--<div class="heart1-icon">
|
||
<img class="red-heart-1" src="assets/images/heart-red.png" alt="Red Heart" />
|
||
</div>
|
||
|
||
<div class="heart1-icon">
|
||
<img class="red-heart-2" src="assets/images/heart-red.png" alt="Red Heart" />
|
||
</div>-->
|
||
|
||
<div class="song-lyrics">Woke up early, 6am sharp I was whining, <br/>playing my part.</div>
|
||
|
||
<div class="song-control">
|
||
<span id="toggle-song-icon" class="song-play"></span>
|
||
</div>
|
||
|
||
<div class="share-container">
|
||
<div class="share-title">Share the love.</div>
|
||
<div class="share-icons">
|
||
<img class="tiktok" src="assets/images/tiktok.png" alt="Tiktok" />
|
||
<img class="instagram" src="assets/images/instagram.png" alt="Instagram" />
|
||
<img class="facebook" src="assets/images/facebook.png" alt="Facebook" />
|
||
</div>
|
||
<button class="download-song-btn">Download your song</button>
|
||
<button class="copy-btn">Copy URL</button>
|
||
<div class="share-text">Download, share and don’t forget to tag us @PetsatHome with #PetLoveSongs so we can celebrate your love too.</div>
|
||
</div>
|
||
|
||
<button class="make-another-song-btn">Need another song</button>
|
||
|
||
<div class="banner1-container">
|
||
<img id="banner1-mb" class="banner1" src="assets/images/head-tails-btn.png" alt="Fall head over tails" />
|
||
<img id="banner1-dt" class="banner1" src="assets/images/head-tails-btn-dt.png" alt="Fall head over tails" />
|
||
</div>
|
||
|
||
<div class="banner2-container">
|
||
<img id="banner2-mb" class="banner2" src="assets/images/club-member.png" alt="Not a Pets Club member" />
|
||
<img id="banner2-dt" class="banner2" src="assets/images/club-member-dt.png" alt="Not a Pets Club member" />
|
||
</div>
|
||
|
||
</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;
|
||
let videoPlayer = null;
|
||
let resultData = null;
|
||
|
||
async function loadResults() {
|
||
try {
|
||
const response = await fetch(`${API_URL}/api/results/${sessionId}`);
|
||
|
||
if (!response.ok) {
|
||
if (response.status === 404) {
|
||
showError('Song not found. Please create a new one.');
|
||
return;
|
||
}
|
||
throw new Error('Failed to load results');
|
||
}
|
||
|
||
resultData = await response.json();
|
||
|
||
if (resultData.success && resultData.status === 'success') {
|
||
showSuccess(resultData);
|
||
} else {
|
||
showFailure(resultData);
|
||
}
|
||
} catch (error) {
|
||
console.error('Error loading results:', error);
|
||
showError('Failed to load your song. Please try again.');
|
||
}
|
||
}
|
||
|
||
function showSuccess(data) {
|
||
// Update page title
|
||
const titleEl = document.querySelector('.title1');
|
||
if (titleEl) {
|
||
titleEl.textContent = `${data.pet_name}'s Love Song`;
|
||
}
|
||
|
||
// Replace rotating record with video player
|
||
const recordContainer = document.querySelector('.record-container');
|
||
if (recordContainer && data.video_url) {
|
||
recordContainer.innerHTML = `
|
||
<video id="video-player" controls playsinline style="width: 100%; max-width: 400px; border-radius: 50%;">
|
||
<source src="${data.video_url}" type="video/mp4">
|
||
Your browser does not support the video tag.
|
||
</video>
|
||
`;
|
||
videoPlayer = document.getElementById('video-player');
|
||
}
|
||
|
||
// Update lyrics
|
||
const lyricsEl = document.querySelector('.song-lyrics');
|
||
if (lyricsEl && data.lyrics) {
|
||
// Format lyrics with line breaks
|
||
lyricsEl.innerHTML = data.lyrics.replace(/\n/g, '<br>');
|
||
}
|
||
|
||
// Hide play/pause controls (video has its own controls)
|
||
const songControl = document.querySelector('.song-control');
|
||
if (songControl) {
|
||
songControl.style.display = 'none';
|
||
}
|
||
|
||
// Setup download button
|
||
const downloadBtn = document.querySelector('.download-song-btn');
|
||
if (downloadBtn && data.video_url) {
|
||
downloadBtn.addEventListener('click', () => {
|
||
const link = document.createElement('a');
|
||
link.href = data.video_url;
|
||
link.download = `${data.pet_name}-love-song.mp4`;
|
||
link.click();
|
||
});
|
||
}
|
||
|
||
// Setup copy URL button
|
||
const copyBtn = document.querySelector('.copy-btn');
|
||
if (copyBtn) {
|
||
copyBtn.addEventListener('click', () => {
|
||
navigator.clipboard.writeText(window.location.href).then(() => {
|
||
const originalText = copyBtn.textContent;
|
||
copyBtn.textContent = 'Copied!';
|
||
setTimeout(() => {
|
||
copyBtn.textContent = originalText;
|
||
}, 2000);
|
||
}).catch(() => {
|
||
// Fallback for older browsers
|
||
const textArea = document.createElement('textarea');
|
||
textArea.value = window.location.href;
|
||
document.body.appendChild(textArea);
|
||
textArea.select();
|
||
document.execCommand('copy');
|
||
document.body.removeChild(textArea);
|
||
copyBtn.textContent = 'Copied!';
|
||
setTimeout(() => {
|
||
copyBtn.textContent = 'Copy URL';
|
||
}, 2000);
|
||
});
|
||
});
|
||
}
|
||
|
||
// Setup share buttons
|
||
setupShareButtons(data);
|
||
}
|
||
|
||
function showFailure(data) {
|
||
const bodyContainer = document.querySelector('.body-container');
|
||
if (bodyContainer) {
|
||
bodyContainer.innerHTML = `
|
||
<div class="pets-text-logo"></div>
|
||
<div class="title1">Oops! Something went wrong</div>
|
||
<div class="song-lyrics">We couldn't generate ${data.pet_name}'s love song. Please try again.</div>
|
||
<button class="make-another-song-btn" onclick="window.location.href='/'">Create a New Song</button>
|
||
`;
|
||
}
|
||
}
|
||
|
||
function showError(message) {
|
||
const bodyContainer = document.querySelector('.body-container');
|
||
if (bodyContainer) {
|
||
bodyContainer.innerHTML = `
|
||
<div class="pets-text-logo"></div>
|
||
<div class="title1">Error</div>
|
||
<div class="song-lyrics">${message}</div>
|
||
<button class="make-another-song-btn" onclick="window.location.href='/'">Create a New Song</button>
|
||
`;
|
||
}
|
||
}
|
||
|
||
function setupShareButtons(data) {
|
||
const shareUrl = encodeURIComponent(window.location.href);
|
||
const shareText = encodeURIComponent(`Check out ${data.pet_name}'s love song! #PetLoveSongs @PetsatHome`);
|
||
|
||
// Facebook share
|
||
const fbBtn = document.querySelector('.facebook');
|
||
if (fbBtn) {
|
||
fbBtn.style.cursor = 'pointer';
|
||
fbBtn.addEventListener('click', () => {
|
||
window.open(`https://www.facebook.com/sharer/sharer.php?u=${shareUrl}`, '_blank', 'width=600,height=400');
|
||
});
|
||
}
|
||
|
||
// TikTok - link to TikTok (can't directly share, user downloads and uploads)
|
||
const tiktokBtn = document.querySelector('.tiktok');
|
||
if (tiktokBtn) {
|
||
tiktokBtn.style.cursor = 'pointer';
|
||
tiktokBtn.addEventListener('click', () => {
|
||
alert('Download your video and upload it to TikTok with #PetLoveSongs @PetsatHome');
|
||
});
|
||
}
|
||
|
||
// Instagram - similar to TikTok
|
||
const instaBtn = document.querySelector('.instagram');
|
||
if (instaBtn) {
|
||
instaBtn.style.cursor = 'pointer';
|
||
instaBtn.addEventListener('click', () => {
|
||
alert('Download your video and share it on Instagram with #PetLoveSongs @PetsatHome');
|
||
});
|
||
}
|
||
}
|
||
|
||
// Setup "Need another song" button
|
||
const anotherSongBtn = document.querySelector('.make-another-song-btn');
|
||
if (anotherSongBtn) {
|
||
anotherSongBtn.addEventListener('click', () => {
|
||
window.location.href = '/';
|
||
});
|
||
}
|
||
|
||
// Load results on page load
|
||
loadResults();
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html>
|