Compare commits

...

2 Commits

4 changed files with 83 additions and 17 deletions

View File

@ -30,14 +30,11 @@ function App() {
// Add to history // Add to history
const newHistoryItem = { const newHistoryItem = {
...result, // Store full result (sections, etc)
id: Date.now(), id: Date.now(),
title: result.title,
subtitle: result.subtitle,
age: data.age, age: data.age,
downloads: 0, downloads: 0,
bgColor: 'bg-primary-50', // Default color bgColor: 'bg-primary-50',
// We'll need to figure out how to preview it in the gallery.
// For now, Gallery expects 'bgColor'.
}; };
setHistory(prev => [newHistoryItem, ...prev]); setHistory(prev => [newHistoryItem, ...prev]);
@ -49,6 +46,11 @@ function App() {
} }
}; };
const handleRestore = (item) => {
setGeneratedSheet(item);
window.scrollTo({ top: 0, behavior: 'smooth' });
};
const galleryItems = history.length > 0 ? history.slice(0, 3) : popularSheets.slice(0, 3); const galleryItems = history.length > 0 ? history.slice(0, 3) : popularSheets.slice(0, 3);
const galleryTitle = history.length > 0 ? "Your Recent Creations" : "Most Popular Printables"; const galleryTitle = history.length > 0 ? "Your Recent Creations" : "Most Popular Printables";
@ -74,7 +76,7 @@ function App() {
{/* Main Content */} {/* Main Content */}
<main className="max-w-7xl mx-auto px-4"> <main className="max-w-7xl mx-auto px-4">
<Hero onGenerate={handleGenerate} generatedSheet={generatedSheet} isGenerating={isGenerating} /> <Hero onGenerate={handleGenerate} generatedSheet={generatedSheet} isGenerating={isGenerating} />
<Gallery items={galleryItems} title={galleryTitle} /> <Gallery items={galleryItems} title={galleryTitle} onRestore={handleRestore} />
</main> </main>
<HowItWorks /> <HowItWorks />

View File

@ -3,7 +3,7 @@ import { motion } from 'framer-motion';
import { Wand2, Download, Star } from 'lucide-react'; import { Wand2, Download, Star } from 'lucide-react';
import { Button } from './ui/Button'; import { Button } from './ui/Button';
export const Gallery = ({ items, title = "Most Popular Printables" }) => { export const Gallery = ({ items, title = "Most Popular Printables", onRestore }) => {
return ( return (
<section className="py-12"> <section className="py-12">
<div className="flex items-center gap-2 mb-8"> <div className="flex items-center gap-2 mb-8">
@ -21,17 +21,36 @@ export const Gallery = ({ items, title = "Most Popular Printables" }) => {
className="group bg-white rounded-3xl border-2 border-slate-100 overflow-hidden hover:border-primary-200 hover:shadow-xl hover:shadow-primary-100/50 transition-all duration-300" className="group bg-white rounded-3xl border-2 border-slate-100 overflow-hidden hover:border-primary-200 hover:shadow-xl hover:shadow-primary-100/50 transition-all duration-300"
> >
<div className={`aspect-[3/4] p-6 flex flex-col items-center justify-center relative ${item.bgColor}`}> <div className={`aspect-[3/4] p-6 flex flex-col items-center justify-center relative ${item.bgColor}`}>
{/* This would ideally be the actual sheet preview */} {item.sections && item.sections.length > 0 && item.sections[0].content_svg ? (
<div className="w-full h-full bg-white rounded-xl shadow-sm border border-black/5 overflow-hidden relative">
<div
className="w-full h-full transform scale-90 origin-center"
dangerouslySetInnerHTML={{ __html: item.sections[0].content_svg }}
/>
{/* Overlay to prevent interaction with SVG parts */}
<div className="absolute inset-0 z-10"></div>
</div>
) : (
<div className="w-full h-full bg-white rounded-xl shadow-sm border border-black/5 flex flex-col items-center justify-center p-4 text-center"> <div className="w-full h-full bg-white rounded-xl shadow-sm border border-black/5 flex flex-col items-center justify-center p-4 text-center">
{item.image ? (
<img src={item.image} alt={item.title} className="w-full h-full object-cover rounded-lg" />
) : (
<>
<h3 className="font-bold text-lg mb-2">{item.title}</h3> <h3 className="font-bold text-lg mb-2">{item.title}</h3>
<p className="text-sm text-slate-500 mb-4">{item.subtitle}</p> <p className="text-sm text-slate-500 mb-4">{item.subtitle}</p>
<div className="text-4xl font-mono opacity-20">123</div> <div className="text-4xl font-mono opacity-20">123</div>
</>
)}
</div> </div>
)}
<div className="absolute inset-0 bg-black/0 group-hover:bg-black/5 transition-colors flex items-center justify-center opacity-0 group-hover:opacity-100"> <div className="absolute inset-0 bg-black/0 group-hover:bg-black/5 transition-colors flex items-center justify-center opacity-0 group-hover:opacity-100 z-20">
<Button className="shadow-xl"> <Button
<Download className="mr-2" size={18} /> className="shadow-xl"
Download PDF onClick={() => onRestore && onRestore(item)}
>
<Wand2 className="mr-2" size={18} />
{onRestore ? "Open in Editor" : "View Sheet"}
</Button> </Button>
</div> </div>
</div> </div>

View File

@ -12,6 +12,48 @@ export const Hero = ({ onGenerate, generatedSheet, isGenerating }) => {
const [age, setAge] = useState(5); const [age, setAge] = useState(5);
const [selectedSection, setSelectedSection] = useState('coloring'); const [selectedSection, setSelectedSection] = useState('coloring');
// Sync state when a sheet is restored
React.useEffect(() => {
if (generatedSheet) {
setTheme(generatedSheet.title || '');
if (generatedSheet.age) setAge(generatedSheet.age);
// If sections exist, restore the first one's type as selected
if (generatedSheet.sections && generatedSheet.sections.length > 0) {
// Map section type back to ID if possible, or fallback
const secType = generatedSheet.sections[0].type; // e.g. "coloring"
// Our IDs match the types mostly, but let's be safe
// IDs: coloring, numbers, writing, find-the-way, counting
// Types from prompt: coloring|numbers|writing|find-the-way|counting
// So direct mapping should work.
// But wait, finding the ID that matches the type/id from result
// In App.jsx we assume result has sections.
// The prompt returns 'type' and we use that? No, prompt returns 'id' and 'type'.
// Let's use the first section's ID if valid.
const secId = generatedSheet.sections[0].id; // e.g. "coloring-123"
// This ID from AI might be "coloring-main". We need to map it to our internal IDs: 'coloring', 'writing', 'numbers', etc.
// Internal IDs in Hero are: 'coloring', 'numbers', 'writing', 'find-way' (wait, it's 'find-way' not 'find-the-way'!), 'counting'.
// Let's check mockData for IDs.
// sections: [{id: 'find-way', label: 'Find the Way', ...}]
// AI prompt was: "find-the-way" for type.
// We need to map "find-the-way" -> "find-way".
const typeToId = {
'coloring': 'coloring',
'numbers': 'numbers',
'writing': 'writing',
'find-the-way': 'find-way',
'counting': 'counting'
};
if (typeToId[secType]) {
setSelectedSection(typeToId[secType]);
}
}
}
}, [generatedSheet]);
const handleSectionChange = (id) => { const handleSectionChange = (id) => {
if (!isGenerating) { if (!isGenerating) {
setSelectedSection(id); setSelectedSection(id);

View File

@ -8,6 +8,7 @@ export const popularSheets = [
type: "Math", type: "Math",
bgColor: "bg-green-50", bgColor: "bg-green-50",
image: "https://images.unsplash.com/photo-1559810686-353c7a974b7c?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.0.3", image: "https://images.unsplash.com/photo-1559810686-353c7a974b7c?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.0.3",
sections: [{ type: "Math", content: "Dinosaur Math Content (Placeholder)" }]
}, },
{ {
id: 2, id: 2,
@ -18,6 +19,7 @@ export const popularSheets = [
type: "Maze", type: "Maze",
bgColor: "bg-pink-50", bgColor: "bg-pink-50",
image: "https://images.unsplash.com/photo-1555557760-b610c1f207d5?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.0.3", image: "https://images.unsplash.com/photo-1555557760-b610c1f207d5?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.0.3",
sections: [{ type: "Maze", content: "Princess Maze Content (Placeholder)" }]
}, },
{ {
id: 3, id: 3,
@ -28,6 +30,7 @@ export const popularSheets = [
type: "Writing", type: "Writing",
bgColor: "bg-slate-50", bgColor: "bg-slate-50",
image: "https://images.unsplash.com/photo-1451187580459-43490279c0fa?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.0.3", image: "https://images.unsplash.com/photo-1451187580459-43490279c0fa?w=500&auto=format&fit=crop&q=60&ixlib=rb-4.0.3",
sections: [{ type: "Writing", content: "Space Writing Content (Placeholder)" }]
} }
]; ];