Spaces:
Sleeping
Sleeping
| 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; |