import { useState, useRef, useEffect } from 'react'; import { Camera, ArrowRight, Edit3, Upload, Type, Calendar, Palette, Edit, Stamp } from 'lucide-react'; import { Button } from './ui/button'; import { ImageWithFallback } from './figma/ImageWithFallback'; import { motion, useMotionValue, useSpring, useTransform, useInView } from 'motion/react'; import { HandwrittenText, useHandwrittenText } from './HandwrittenText'; import postcardImage from 'figma:asset/d3a880cf8b7f1bec6da9b3f2ce4a76e822e483cf.png'; interface EditableCardProps { isEditing: boolean; onEdit: () => void; children: React.ReactNode; className?: string; style?: React.CSSProperties; editIcon?: React.ReactNode; } export function CustomPostcards() { const [editingCard, setEditingCard] = useState(null); const [isFlipped, setIsFlipped] = useState(false); const [uploadedImage, setUploadedImage] = useState(null); const postcardRef = useRef(null); const sectionRef = useRef(null); const fileInputRef = useRef(null); // 3D tilt effect using mouse position const mouseX = useMotionValue(0); const mouseY = useMotionValue(0); // Spring animations for smooth mouse following const rotateX = useSpring(useTransform(mouseY, [-0.5, 0.5], [5, -5]), { stiffness: 100, damping: 15 }); const rotateY = useSpring(useTransform(mouseX, [-0.5, 0.5], [-5, 5]), { stiffness: 100, damping: 15 }); // Detect when section is in view to trigger handwriting const isInView = useInView(sectionRef, { once: true, margin: "-100px", amount: 0.3 }); // Handwritten text control const handwrittenControl = useHandwrittenText(false); // Handle mouse movement for 3D effect (disabled when flipped) const handleMouseMove = (event: React.MouseEvent) => { if (!postcardRef.current || isFlipped) return; const rect = postcardRef.current.getBoundingClientRect(); const centerX = rect.left + rect.width / 2; const centerY = rect.top + rect.height / 2; const x = (event.clientX - centerX) / (rect.width / 2); const y = (event.clientY - centerY) / (rect.height / 2); mouseX.set(x); mouseY.set(y); }; const handleMouseLeave = () => { if (isFlipped) return; mouseX.set(0); mouseY.set(0); }; const [postcardData, setPostcardData] = useState({ photo: "https://images.unsplash.com/photo-1506905925346-21bda4d32df4?w=400&h=600&fit=crop&crop=center", message: "Greetings from paradise!\\nThe beaches here are absolutely\\nbreathtaking. Wish you were\\nhere to enjoy this amazing\\nsunset with me.", date: "July 2024", addressLabel: "POSTCARD" }); const handleCreatePostcard = () => { console.log('Navigate to postcard creation page...'); }; // Handle image upload const handleImageUpload = (event: React.ChangeEvent) => { const file = event.target.files?.[0]; if (file) { const reader = new FileReader(); reader.onloadend = () => { setUploadedImage(reader.result as string); // Automatically flip to show the uploaded image setIsFlipped(true); }; reader.readAsDataURL(file); } }; // Trigger file input const triggerFileInput = () => { fileInputRef.current?.click(); }; // Start handwriting animation when section comes into view useEffect(() => { if (isInView && !editingCard) { // Delay the start of handwriting to let the postcard animation settle const timer = setTimeout(() => { handwrittenControl.start(); }, 1200); return () => clearTimeout(timer); } }, [isInView, editingCard, handwrittenControl]); // Reset handwriting when editing useEffect(() => { if (editingCard === 'message') { handwrittenControl.reset(); } }, [editingCard, handwrittenControl]); // Reset 3D tilt when card is flipped useEffect(() => { if (isFlipped) { mouseX.set(0); mouseY.set(0); } }, [isFlipped, mouseX, mouseY]); const EditableCard = ({ isEditing, onEdit, children, className = "", style = {}, editIcon }: EditableCardProps) => { return ( { e.stopPropagation(); onEdit(); }} whileHover={{ scale: 1.02, transition: { duration: 0.2 } }} whileTap={{ scale: 0.98 }} animate={isEditing ? { boxShadow: "0 0 0 2px rgba(249, 95, 98, 0.5), 0 8px 16px rgba(249, 95, 98, 0.3)" } : {}} > {children} {/* Animated Edit overlay */} {editIcon} {isEditing ? 'Editing...' : 'Edit'} ); }; // Ultra-realistic vintage postcard with responsive scaling and animations const PostcardFrame = () => { return ( {/* Realistic paper texture with variations */}
{/* Age spots and stains */}
{/* Corner wear and creases */}
{/* Subtle crease lines */}
{/* Animated Vintage Vector Logo - Top Right - Mobile Optimized */} {/* Subtle aging overlay for the vector */}
{/* For Correspondence Text */}

For correspondence

{/* Realistic vertical divider with ink bleeding - Responsive */}
{/* Ink bleed effect around divider - Responsive */}
{/* Right side content area - Responsive */}
{/* Editable Address Label Card - Responsive */} setEditingCard(editingCard === 'label' ? null : 'label')} style={{ position: 'absolute', top: '4.1%', left: '0%', pointerEvents: 'auto', transform: 'rotate(-0.3deg)' }} editIcon={} >
{postcardData.addressLabel}
{/* Realistic horizontal ruled lines with ink bleeding - Responsive */}
{[...Array(9)].map((_, i) => (
{/* Main line */}
{/* Ink bleed effect */}
))}
{/* Editable Message Card with Handwritten Animation - Responsive */} setEditingCard(editingCard === 'message' ? null : 'message')} style={{ position: 'absolute', top: '17.6%', left: '4.4%', width: '88.2%', pointerEvents: 'auto', transform: 'rotate(-0.7deg)' }} editIcon={} >
{editingCard === 'message' ? ( // Show static text when editing
{postcardData.message}
) : ( // Show animated handwritten text when not editing )}
{/* Editable Date Card - Responsive */} setEditingCard(editingCard === 'date' ? null : 'date')} style={{ position: 'absolute', bottom: '16.2%', right: '7.4%', pointerEvents: 'auto', transform: 'rotate(-1.5deg)' }} editIcon={} >
{postcardData.date}
{/* Ultra-realistic stamp - Responsive */} setEditingCard(editingCard === 'stamp' ? null : 'stamp')} style={{ position: 'absolute', width: '12.5%', height: '19.1%', right: '3.5%', bottom: '5.3%', transform: 'rotate(-12deg)' }} editIcon={} >
{/* Stamp aging and wear */}
{/* Stamp inner details */}
{/* Stamp text */}
TRAVEL
MEMORIES
2024
{/* Stamp perforations with realistic variations */} {[...Array(20)].map((_, i) => (
0.1 ? 1 : 0.3 // Random missing perforations }} /> ))} {/* Stamp smudge mark */}
{/* Additional realistic aging effects */}
); }; return (
{/* Background decorations */}
{/* Vintage Stamps */}
{/* Paper Textures */}
{/* Ink Splatters */}
{/* Header */}
Custom Memories

The Only Card That Sends Your Holiday {' '} Home.

Transform your travel memories into beautiful, personalized postcards that capture the essence of your adventures.

{/* Centered Postcard Preview - Enhanced with Animations */}
{/* Left Flip Button - Show when viewing back (flipped) */} setIsFlipped(false)} className={`hidden md:flex items-center justify-center w-12 h-12 rounded-full bg-white shadow-lg border-2 border-primary hover:bg-primary hover:text-white transition-all duration-300 ${isFlipped ? 'opacity-100' : 'opacity-0 pointer-events-none'}`} whileHover={{ scale: 1.1 }} whileTap={{ scale: 0.95 }} initial={{ opacity: 0, x: -20 }} animate={{ opacity: isFlipped ? 1 : 0, x: isFlipped ? 0 : -20 }} transition={{ duration: 0.3 }} > {/* Postcard Container */}
{/* Interactive 3D Container with Flip */} {/* Front Side - Postcard Design */} {/* Subtle glow effect */} {/* Back Side - Postcard Frame with Upload */} {/* Postcard frame with gradient background - matching Figma import */}
{/* Hidden file input */} {/* Animated Edit Instructions */} {editingCard && ( Click on any element to edit it
)} {/* Mobile Flip Button - Below postcard on mobile */} setIsFlipped(!isFlipped)} className="md:hidden mt-4 mx-auto flex items-center justify-center gap-2 px-6 py-3 rounded-full bg-primary text-white font-poppins font-semibold shadow-lg hover:bg-primary/90 transition-all duration-300" whileTap={{ scale: 0.95 }} > {isFlipped ? 'View Postcard' : 'View Image'}
{/* Right Flip Button - Show when viewing front (not flipped) */} setIsFlipped(true)} className={`hidden md:flex items-center justify-center w-12 h-12 rounded-full bg-white shadow-lg border-2 border-primary hover:bg-primary hover:text-white transition-all duration-300 ${!isFlipped ? 'opacity-100' : 'opacity-0 pointer-events-none'}`} whileHover={{ scale: 1.1 }} whileTap={{ scale: 0.95 }} initial={{ opacity: 0, x: 20 }} animate={{ opacity: !isFlipped ? 1 : 0, x: !isFlipped ? 0 : 20 }} transition={{ duration: 0.3 }} >
{/* Animated Editing Panel */} {editingCard && (

Edit {editingCard}

{editingCard === 'photo' && (
setPostcardData(prev => ({ ...prev, photo: e.target.value }))} className="w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-primary" placeholder="Enter image URL" />
)} {editingCard === 'message' && (