Tristan Yu
Deploy complete working Transcreation Explorer
f074415
import React, { useState, useEffect } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import axios from 'axios';
import toast from 'react-hot-toast';
import ExampleCard from '../components/ExampleCard';
import { Shuffle, RefreshCw, Database } from 'lucide-react';
const Random = () => {
const [currentExample, setCurrentExample] = useState(null);
const [loading, setLoading] = useState(true);
const [refreshing, setRefreshing] = useState(false);
const [stats, setStats] = useState({ totalExamples: 0 });
const fetchRandomExample = async (showLoadingState = true) => {
if (showLoadingState) {
setRefreshing(true);
}
try {
const response = await axios.get('/api/examples/random');
setCurrentExample(response.data.data);
} catch (error) {
toast.error('Failed to load random example');
console.error('Error fetching random example:', error);
} finally {
setLoading(false);
setRefreshing(false);
}
};
const fetchStats = async () => {
try {
const response = await axios.get('/api/stats');
setStats(response.data.data);
} catch (error) {
console.error('Error fetching stats:', error);
}
};
useEffect(() => {
fetchRandomExample();
fetchStats();
}, []);
const handleNewExample = () => {
fetchRandomExample(true);
};
if (loading) {
return (
<div className="loading">
<div className="spinner"></div>
</div>
);
}
return (
<motion.div
initial={{ opacity: 0, y: 20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6 }}
>
<div className="card" style={{
marginBottom: '2rem',
textAlign: 'center',
maxWidth: '800px',
margin: '0 auto 2rem auto'
}}>
<h1 style={{
marginBottom: '1rem',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: '0.5rem'
}}>
<Shuffle size={24} />
Random Discovery
</h1>
<p style={{ color: '#666', marginBottom: '1.5rem' }}>
Discover transcreation examples through serendipitous exploration.
Each click reveals a new example to inspire and educate.
</p>
<div style={{
display: 'flex',
gap: '1rem',
justifyContent: 'center',
flexWrap: 'wrap',
marginBottom: '1rem'
}}>
<button
className="btn"
onClick={handleNewExample}
disabled={refreshing}
style={{
display: 'inline-flex',
alignItems: 'center',
gap: '0.5rem'
}}
>
{refreshing ? (
<>
<RefreshCw size={20} className="spin" />
Loading...
</>
) : (
<>
<Shuffle size={20} />
{currentExample ? 'Get Another Example' : 'Try Again'}
</>
)}
</button>
</div>
<div style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
gap: '1rem',
fontSize: '0.9rem',
color: '#666'
}}>
<div style={{ display: 'flex', alignItems: 'center', gap: '0.25rem' }}>
<Database size={14} />
<span>{stats.totalExamples} examples available</span>
</div>
</div>
</div>
{currentExample ? (
<AnimatePresence mode="wait">
<motion.div
key={currentExample.id}
initial={{ opacity: 0, scale: 0.95 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.95 }}
transition={{ duration: 0.3 }}
style={{
maxWidth: '800px',
margin: '0 auto'
}}
>
<ExampleCard example={currentExample} />
</motion.div>
</AnimatePresence>
) : (
<div className="card" style={{ textAlign: 'center', padding: '3rem' }}>
<h3 style={{ marginBottom: '1rem' }}>No examples available</h3>
<p style={{ color: '#666', marginBottom: '1.5rem' }}>
Please try again later.
</p>
<button
className="btn"
onClick={handleNewExample}
disabled={refreshing}
style={{
display: 'inline-flex',
alignItems: 'center',
gap: '0.5rem'
}}
>
{refreshing ? (
<>
<RefreshCw size={20} className="spin" />
Loading...
</>
) : (
<>
<Shuffle size={20} />
Try Again
</>
)}
</button>
</div>
)}
<style jsx>{`
.spin {
animation: spin 1s linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
`}</style>
</motion.div>
);
};
export default Random;