374 lines
No EOL
17 KiB
PHP
374 lines
No EOL
17 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>
|
||
|
||
<?php include('header.php'); ?>
|
||
|
||
<div class="container">
|
||
|
||
<div class="body-container">
|
||
|
||
<div class="title1">My Pet Love Song.</div>
|
||
|
||
<div class="record-container">
|
||
<img class="dog-record rotate" src="./assets/images/blank-record.png" alt="Record" id="pet-record" />
|
||
<img class="record-needle" src="./assets/images/needle.png" alt="Record Needle">
|
||
</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">Get ready to share the love in <span id="timer">3:00</span></div>
|
||
<div class="share-text">When the buttons go green your Pet Love Song is ready to share</div>
|
||
<a href="javascript:void(0);" class="copy-btn">Copy URL</a>
|
||
<a href="assets/video/song.mp4" download class="download-song-btn">Download your song</a>
|
||
<div class="share-subtext hide-desktop">For <b>Download your song</b>, you’ll find your Pet Love Song in <br/>Files (on iPhones), or Downloads (on Android)</div>
|
||
<div class="share-subtext hide-mobile">For <b>Download your song</b>, you’ll find your Pet Love Song in Files (on iPhones), or Downloads (on Android)</div>
|
||
<div class="share-subtext"><b>And remember to tag us @PetsatHomeUK with #PetLoveSongs.</b></div>
|
||
</div>
|
||
|
||
<a href="javascript:void(0);" class="make-another-song-btn">Need another song?</a>
|
||
|
||
<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" />
|
||
<a href="https://www.petsathome.com/campaigns/listing/valentines" target="_blank" class="banner1-cta" aria-label="Fall head over tails">Shop now</a>
|
||
</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" />
|
||
<a href="https://signup.petsathome.com/?_gl=1*iz9hoy*_gcl_aw*R0NMLjE3Njg1NzcyODkuQ2p3S0NBaUE0S2ZMQmhCMEVpd0FVWTdHQWZTRzBGcE1pekpZYUhWVGxxMEFxNXJaRGR6cEQtQW8zSFRPOGw2bTRDVmJualRyT3V3bVBCb0NHckVRQXZEX0J3RQ..*_gcl_dc*R0NMLjE3Njg1NzcyODkuQ2p3S0NBaUE0S2ZMQmhCMEVpd0FVWTdHQWZTRzBGcE1pekpZYUhWVGxxMEFxNXJaRGR6cEQtQW8zSFRPOGw2bTRDVmJualRyT3V3bVBCb0NHckVRQXZEX0J3RQ..*_gcl_au*NDA5MDMwNTY4LjE3NjcwMDczMTk.*_ga*MTY1MTAwOTMyNy4xNzQyNDY5Mzcz*_ga_SCDHP6GJGF*czE3NzAxMTkyMzYkbzE2NCRnMSR0MTc3MDExOTY5NSRqMTIkbDAkaDIwNTY2NTE5MzQ.*_fplc*JTJCbEhEdzFrVFZ2SmFlOGUwYXZxNXI5VEhmM2Fac01MWjhPc05PV01pSnprT0poaloxclE4QWlnZ2lDNlMlMkJWNXlKTWhXM2lWVFRjV1YxcDBYbjMwcHR3anZnYmQzeVFZTWcyUGdBTHBERXdGdmR5YmdoeHIzOUZlN3RKaE5WUSUzRCUzRA.." target="_blank" class="banner2-cta" aria-label="Fall head over tails">Join now</a>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
</div>
|
||
|
||
<?php include('footer.php'); ?>
|
||
|
||
<script>
|
||
(function() {
|
||
// Get session_id from URL query parameter
|
||
const urlParams = new URLSearchParams(window.location.search);
|
||
let sessionId = urlParams.get('session_id');
|
||
|
||
if (!sessionId) {
|
||
// No session_id in URL, check localStorage
|
||
try {
|
||
const submissionData = localStorage.getItem('submission_data');
|
||
|
||
if (submissionData) {
|
||
const data = JSON.parse(submissionData);
|
||
|
||
if (data.entries && data.entries.length > 0) {
|
||
// Sort entries by timestamp (newest first) and get the latest
|
||
const sortedEntries = data.entries.sort((a, b) => {
|
||
return new Date(b.timestamp) - new Date(a.timestamp);
|
||
});
|
||
|
||
const latestEntry = sortedEntries[0];
|
||
sessionId = latestEntry.session_id;
|
||
console.log(`Loading session from localStorage: ${sessionId} from ${latestEntry.timestamp}`);
|
||
}
|
||
}
|
||
} catch (error) {
|
||
console.error(`Error reading from localStorage: ${error}`);
|
||
}
|
||
|
||
// If still no session_id, redirect to home
|
||
if (!sessionId) {
|
||
window.location.href = '/';
|
||
return;
|
||
}
|
||
}
|
||
|
||
const API_BASE_URL = 'https://valentinesong.oliver.digital/back';
|
||
let videoPlayer = null;
|
||
let resultData = null;
|
||
|
||
async function loadResults() {
|
||
try {
|
||
const response = await fetch(`${API_BASE_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 escapeHtml(text) {
|
||
const div = document.createElement('div');
|
||
div.textContent = text;
|
||
return div.innerHTML;
|
||
}
|
||
|
||
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 disablepictureinpicture controlslist="noplaybackrate nodownload nofullscreen" style="width: 100%;">
|
||
<source src="${escapeHtml(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 = escapeHtml(data.lyrics).replace(/\n/g, '<br>');
|
||
}
|
||
|
||
// Render lyrics
|
||
renderLyrics(data.lyrics, lyricsEl);
|
||
|
||
// Setup auto-scroll functionality
|
||
setupAutoScroll(videoPlayer, lyricsEl);
|
||
|
||
// 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.href = data.video_url;
|
||
downloadBtn.download = `${data.pet_name}-love-song.mp4`;
|
||
}
|
||
|
||
// 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 ${escapeHtml(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">${escapeHtml(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');
|
||
});
|
||
}
|
||
}
|
||
|
||
function renderLyrics(lyrics, container) {
|
||
const lyricsLines = lyrics.split('\n');
|
||
const lyricsHTML = lyricsLines
|
||
.map(line => `<div class="lyrics-line">${line || ' '}</div>`)
|
||
.join('');
|
||
|
||
container.innerHTML = lyricsHTML;
|
||
}
|
||
|
||
function setupAutoScroll(audio, lyricsContainer) {
|
||
let scrollAnimationId = null;
|
||
let totalDuration = 0;
|
||
let maxScroll = 0;
|
||
|
||
// Update scroll position based on current audio time
|
||
function updateScroll() {
|
||
const progress = audio.currentTime / totalDuration;
|
||
const scrollPosition = progress * maxScroll;
|
||
lyricsContainer.scrollTop = scrollPosition;
|
||
|
||
// Continue animation if audio is playing
|
||
if (!audio.paused) {
|
||
scrollAnimationId = requestAnimationFrame(updateScroll);
|
||
}
|
||
}
|
||
|
||
// Initialize scroll parameters when metadata is loaded
|
||
audio.addEventListener('loadedmetadata', () => {
|
||
totalDuration = audio.duration;
|
||
maxScroll = lyricsContainer.scrollHeight - lyricsContainer.clientHeight;
|
||
|
||
console.log('Audio duration (seconds):', totalDuration);
|
||
console.log('Max scroll distance:', maxScroll);
|
||
console.log('Scroll speed:', (maxScroll / totalDuration).toFixed(2), 'pixels per second');
|
||
});
|
||
|
||
// Start scrolling when audio plays
|
||
audio.addEventListener('play', () => {
|
||
if (scrollAnimationId) {
|
||
cancelAnimationFrame(scrollAnimationId);
|
||
}
|
||
updateScroll();
|
||
});
|
||
|
||
// Stop scrolling when audio pauses
|
||
audio.addEventListener('pause', () => {
|
||
if (scrollAnimationId) {
|
||
cancelAnimationFrame(scrollAnimationId);
|
||
scrollAnimationId = null;
|
||
}
|
||
});
|
||
|
||
// Update scroll position when user seeks
|
||
audio.addEventListener('seeked', () => {
|
||
const progress = audio.currentTime / totalDuration;
|
||
const scrollPosition = progress * maxScroll;
|
||
lyricsContainer.scrollTop = scrollPosition;
|
||
|
||
// Restart animation if audio is playing
|
||
if (!audio.paused) {
|
||
if (scrollAnimationId) {
|
||
cancelAnimationFrame(scrollAnimationId);
|
||
}
|
||
updateScroll();
|
||
}
|
||
});
|
||
}
|
||
|
||
function startCountdown() {
|
||
let totalSeconds = 180; // logical countdown time (3 minutes)
|
||
const timerElement = document.getElementById("timer");
|
||
|
||
// Each displayed second should last 1.15 real seconds
|
||
const intervalTime = 1150; // milliseconds
|
||
|
||
const interval = setInterval(() => {
|
||
// Calculate minutes and seconds
|
||
let minutes = Math.floor(totalSeconds / 60);
|
||
let seconds = totalSeconds % 60;
|
||
|
||
// Format with leading zero for seconds
|
||
timerElement.textContent = `${minutes}:${seconds.toString().padStart(2, "0")}`;
|
||
|
||
totalSeconds--;
|
||
|
||
if (totalSeconds < 0) {
|
||
clearInterval(interval);
|
||
timerElement.textContent = "0:00";
|
||
}
|
||
}, intervalTime);
|
||
}
|
||
|
||
// 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();
|
||
startCountdown();
|
||
})();
|
||
</script>
|
||
</body>
|
||
</html>
|