puffin-app/components/AboutClient.tsx

160 lines
6.9 KiB
TypeScript
Raw Normal View History

Migrate from Vite to Next.js 16 with Turbopack This is a major migration from Vite to Next.js 16.0.1 for improved performance, better SEO, and modern React features. ## Next.js Migration Changes - Upgraded to Next.js 16.0.1 with Turbopack (from Vite 6) - Migrated from client-side routing to App Router architecture - Created app/ directory with Next.js page structure - Added server components and client components pattern - Configured standalone Docker builds for production ## Bug Fixes - React Hooks - Fixed infinite loop in Header.tsx scroll behavior (removed lastScrollY state dependency) - Fixed infinite loop in useCalculatorState.ts (wrapped saveState/clearState in useCallback) - Fixed infinite loop in OffsetOrder.tsx (removed savedState from useEffect dependencies) - Removed unused React imports from all client components ## Environment Variable Migration - Migrated all VITE_ variables to NEXT_PUBLIC_ prefix - Updated src/utils/config.ts to use direct static references (required for Next.js) - Updated src/api/checkoutClient.ts, emailClient.ts, aisClient.ts for Next.js env vars - Updated src/vite-env.d.ts types for Next.js environment - Maintained backward compatibility with Docker window.env ## Layout & UX Improvements - Fixed footer to always stay at bottom of viewport using flexbox - Updated app/layout.tsx with flex-1 main content area - Preserved glass morphism effects and luxury styling ## TypeScript & Build - Fixed TypeScript strict mode compilation errors - Removed unused imports and variables - Fixed Axios interceptor types in project/src/api/wrenClient.ts - Production build verified and passing ## Testing & Verification - Tested calculator end-to-end in Playwright - Verified Wren API integration working (11 portfolios fetched) - Confirmed calculation: 5000L → 13.47 tons CO₂ → $3,206 total - All navigation routes working correctly - Footer positioning verified across all pages ## Files Added - app/ directory with Next.js routes - components/ directory with client components - next.config.mjs, next-env.d.ts - ENV_MIGRATION.md, NEXTJS_MIGRATION_COMPLETE.md documentation ## Files Modified - Docker configuration for Next.js standalone builds - package.json dependencies (Next.js, React 19) - ts config.json for Next.js - All API clients for new env var pattern 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-31 22:23:45 +01:00
'use client';
import { Heart, Leaf, Scale, FileCheck, Handshake, Rocket } from 'lucide-react';
import { motion } from 'framer-motion';
import { useRouter } from 'next/navigation';
export function AboutClient() {
const router = useRouter();
const handleStartOffsetting = () => {
router.push('/calculator');
};
return (
<div className="max-w-4xl mx-auto py-12 px-4 sm:px-6 lg:px-8">
<div className="text-center mb-12">
<h1 className="text-4xl font-bold text-gray-900 mb-4">About Puffin Offset</h1>
<p className="text-xl text-gray-600">
Leading the way in maritime carbon offsetting solutions
</p>
</div>
<div className="prose prose-lg text-gray-600 mb-12">
<p className="text-justify">
Puffin Offset was founded with a clear mission: to make carbon offsetting accessible and effective for the maritime industry. We understand the unique challenges faced by yacht owners and operators in reducing their environmental impact while maintaining the highest standards of luxury and service.
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-8 mb-16">
<motion.div
className="luxury-card p-8"
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: 0.2 }}
viewport={{ once: true }}
whileHover={{ scale: 1.02 }}
>
<div className="flex items-center space-x-4 mb-6">
<div className="w-12 h-12 bg-gradient-to-br from-red-500 to-pink-500 rounded-full flex items-center justify-center">
<Heart className="text-white" size={24} />
</div>
<h2 className="text-2xl font-bold heading-luxury">Our Mission</h2>
</div>
<p className="text-slate-600 leading-relaxed text-justify">
To empower the maritime industry with effective, transparent, and accessible carbon offsetting solutions that make a real difference in the fight against climate change.
</p>
</motion.div>
<motion.div
className="luxury-card p-8"
initial={{ opacity: 0, y: 30 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.6, delay: 0.4 }}
viewport={{ once: true }}
whileHover={{ scale: 1.02 }}
>
<div className="flex items-center space-x-4 mb-6">
<div className="w-12 h-12 bg-gradient-to-br from-green-500 to-emerald-500 rounded-full flex items-center justify-center">
<Leaf className="text-white" size={24} />
</div>
<h2 className="text-2xl font-bold heading-luxury">Our Impact</h2>
</div>
<p className="text-slate-600 leading-relaxed text-justify">
Through our partnerships with verified carbon offset projects, we are able to help maritime businesses offset thousands of tons of CO emissions and support sustainable development worldwide.
</p>
</motion.div>
</div>
<motion.div
className="luxury-card p-10 mb-16"
initial={{ opacity: 0, y: 40 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.7, delay: 0.3 }}
viewport={{ once: true }}
>
<motion.h2
className="text-3xl font-bold heading-luxury mb-8 text-center"
initial={{ opacity: 0, y: -10 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: 0.5 }}
viewport={{ once: true }}
>
Our Values
</motion.h2>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
<motion.div
className="text-center"
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: 0.6 }}
viewport={{ once: true }}
whileHover={{ scale: 1.05 }}
>
<div className="w-16 h-16 bg-gradient-to-br from-blue-500 to-blue-600 rounded-full flex items-center justify-center mx-auto mb-4">
<Scale className="text-white" size={28} />
</div>
<h3 className="font-bold text-lg heading-luxury mb-3">Transparency</h3>
<p className="text-slate-600 leading-relaxed">Clear, honest reporting on the impact of every offset.</p>
</motion.div>
<motion.div
className="text-center"
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: 0.7 }}
viewport={{ once: true }}
whileHover={{ scale: 1.05 }}
>
<div className="w-16 h-16 bg-gradient-to-br from-green-500 to-green-600 rounded-full flex items-center justify-center mx-auto mb-4">
<FileCheck className="text-white" size={28} />
</div>
<h3 className="font-bold text-lg heading-luxury mb-3">Quality</h3>
<p className="text-slate-600 leading-relaxed">Only the highest standard of verified offset projects.</p>
</motion.div>
<motion.div
className="text-center"
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: 0.8 }}
viewport={{ once: true }}
whileHover={{ scale: 1.05 }}
>
<div className="w-16 h-16 bg-gradient-to-br from-purple-500 to-purple-600 rounded-full flex items-center justify-center mx-auto mb-4">
<Handshake className="text-white" size={28} />
</div>
<h3 className="font-bold text-lg heading-luxury mb-3">Partnership</h3>
<p className="text-slate-600 leading-relaxed">Working together for a sustainable future.</p>
</motion.div>
<motion.div
className="text-center"
initial={{ opacity: 0, y: 20 }}
whileInView={{ opacity: 1, y: 0 }}
transition={{ duration: 0.5, delay: 0.9 }}
viewport={{ once: true }}
whileHover={{ scale: 1.05 }}
>
<div className="w-16 h-16 bg-gradient-to-br from-orange-500 to-orange-600 rounded-full flex items-center justify-center mx-auto mb-4">
<Rocket className="text-white" size={28} />
</div>
<h3 className="font-bold text-lg heading-luxury mb-3">Future Proof</h3>
<p className="text-slate-600 leading-relaxed">Constantly improving our service and offsetting products.</p>
</motion.div>
</div>
</motion.div>
<div className="text-center">
<h2 className="text-2xl font-bold text-gray-900 mb-6">Ready to Make a Difference?</h2>
<button
onClick={handleStartOffsetting}
className="bg-blue-600 text-white px-8 py-3 rounded-lg hover:bg-blue-700 transition-colors"
>
Start Offsetting Today
</button>
</div>
</div>
);
}