28 Commits

Author SHA1 Message Date
Matt
e21756d7f0 Fix custom amount tons calculation and payment link failure
All checks were successful
Build and Push Docker Images / docker (push) Successful in 47s
Root Cause:
When users entered a custom monetary amount, the tons calculation was broken:
- actualOffsetTons was calculated as (tons * offsetPercentage) / 100
- When monetaryAmount was provided, tons was 0, so actualOffsetTons = 0
- This caused tons display to show 0 and payment link to fail (0 tons invalid)

Fix Applied:
1. Moved roundedPricePerTon calculation earlier in component lifecycle
2. Calculate baseTons from monetaryAmount when provided:
   baseTons = monetaryAmount / roundedPricePerTon
3. Then apply offset percentage: actualOffsetTons = (baseTons * offsetPercentage) / 100

Example:
- User enters $1,000 custom amount
- Portfolio price = $238/ton (rounded up)
- baseTons = 1000 / 238 = 4.20 tons
- With 100% offset: actualOffsetTons = 4.20 tons
- Payment link now passes 4.20 tons to Stripe ✓

Files Modified:
- src/components/OffsetOrder.tsx
- src/components/MobileOffsetOrder.tsx

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 15:40:49 +01:00
Matt
e8d47f0fb3 Fix pricing discrepancy: use rounded-up price in Stripe checkout
All checks were successful
Build and Push Docker Images / docker (push) Successful in 48s
## Problem
- Calculator displayed rounded-up price per ton (e.g., $238/ton)
- Stripe checkout used exact Wren API price (e.g., $237.20/ton)
- This caused confusion when checkout amount differed from calculator

Example with 20,000 liters (53.9 tons):
- Calculator showed: 53.9 × $238 = $12,819
- Stripe charged: 53.9 × $237.20 = $12,775.35

## Solution
Modified both OffsetOrder.tsx and MobileOffsetOrder.tsx to:
- Keep displaying rounded-up price (Math.ceil) to users
- Pass roundedPricePerTon to Stripe checkout session
- Ensures calculator and Stripe always match exactly

## Changes
- OffsetOrder.tsx (line 170): Pass roundedPricePerTon to createCheckoutSession
- MobileOffsetOrder.tsx (lines 207-218): Add rounding to price display and calculations

Now the price users see is exactly what they pay.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 14:17:14 +01:00
Matt
deb4351e21 Enhance UX: Remove calculator comparisons and redesign receipt page
All checks were successful
Build and Push Docker Images / docker (push) Successful in 51s
## Changes Made:

### 1. Remove Carbon Impact Comparisons from Calculator Pages
- Removed from OffsetOrder.tsx (lines 532-542)
- Removed from MobileOffsetOrder.tsx (lines 429-432)
- Keep comparisons ONLY on CheckoutSuccess receipt page per user request

### 2. Comprehensive CheckoutSuccess Page Redesign
- Add Puffin logo prominently at top of receipt
- Implement status mapping: paid/fulfilled → "Confirmed", pending → "Processing"
- Add comprehensive print CSS (@media print rules)
- Hide interactive elements (buttons) when printing
- Optimize layout and spacing for printed receipt
- Professional receipt aesthetics with enhanced design:
  * Beautiful gradient header with logo
  * Highlighted carbon offset display with icon
  * Enhanced pricing breakdown section
  * Better typography and spacing throughout
  * Professional metadata section with date
  * Improved button styling with gradients and hover effects
  * Email confirmation notice with icon
  * Footer with contact information

### Benefits:
- Cleaner calculator UX (comparisons only on success)
- Professional printable receipt
- Clear "Confirmed" status (not "PENDING")
- Beautiful modern design that matches brand

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 14:09:00 +01:00
Matt
5e642794d8 Implement calculator state persistence and fix checkout navigation
All checks were successful
Build and Push Docker Images / docker (push) Successful in 49s
Features:
- Add useCalculatorState hook with localStorage persistence and 1-hour expiry
- State persists through page reloads and Stripe checkout redirects
- Automatically clears state on successful payment (paid/fulfilled status)

Navigation fixes:
- Fix white page issues on checkout success/cancel pages
- Replace <a> links with button handlers for proper state-based routing
- Pass navigation handlers from App.tsx to checkout pages

State persistence integration:
- TripCalculator: Save/restore calculator inputs (fuel, distance, custom)
- MobileCalculator: Full state persistence for mobile app route
- OffsetOrder: Persist offset percentage and portfolio selection
- MobileOffsetOrder: Persist offset percentage for mobile flow

Carbon impact comparisons:
- Add varied carbon impact comparisons with random selection
- Display 3 comparisons in preview mode, 5 in success mode
- Categories: cars, flights, trees, streaming, homes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 13:55:51 +01:00
Matt
9c7e65b894 Round prices UP and change portfolio name to "Puffin Portfolio"
All checks were successful
Build and Push Docker Images / docker (push) Successful in 49s
Changes:
- Changed portfolio description from "Portfolio {ID}" to "Puffin Portfolio"
- Round pricePerTon UP using Math.ceil() instead of exact decimals
- Round total cost UP using Math.ceil()

Example: $237.19 per ton → $238 per ton

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 13:05:52 +01:00
Matt
09e3c13eaf Fix pricing calculation by passing pricePerTon from frontend to backend
All checks were successful
Build and Push Docker Images / docker (push) Successful in 51s
The backend was using a hardcoded PORTFOLIO_PRICING map that only had prices
for portfolios 1, 2, 3 (defaulting to $18/ton for others). When Wren API
returns Portfolio ID 37 at $237/ton, the backend was calculating with $18/ton
instead, causing massive pricing discrepancies.

Changes:
- Frontend now passes pricePerTon (from Wren API) in checkout request
- Backend uses the received pricePerTon instead of lookup table
- Removed dependency on hardcoded PORTFOLIO_PRICING map
- Added validation for pricePerTon parameter

Example fix:
- Before: 0.03 tons × $18/ton = $0.54 (wrong!)
- After: 0.03 tons × $237/ton = $7.11 (correct!)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-30 13:00:13 +01:00
Matt
06733cb2cb Integrate Stripe Checkout and add comprehensive UI enhancements
All checks were successful
Build and Push Docker Image / docker (push) Successful in 42s
## Stripe Payment Integration
- Add Express.js backend server with Stripe Checkout Sessions
- Create SQLite database for order tracking
- Implement Stripe webhook handlers for payment events
- Integrate with Wren Climate API for carbon offset fulfillment
- Add CheckoutSuccess and CheckoutCancel pages
- Create checkout API client for frontend
- Update OffsetOrder component to redirect to Stripe Checkout
- Add processing fee calculation (3% of base amount)
- Implement order status tracking (pending → paid → fulfilled)

Backend (server/):
- Express server with CORS and middleware
- SQLite database with Order schema
- Stripe configuration and client
- Order CRUD operations model
- Checkout session creation endpoint
- Webhook handler for payment confirmation
- Wren API client for offset fulfillment

Frontend:
- CheckoutSuccess page with order details display
- CheckoutCancel page with retry encouragement
- Updated OffsetOrder to use Stripe checkout flow
- Added checkout routes to App.tsx
- TypeScript interfaces for checkout flow

## Visual & UX Enhancements
- Add CertificationBadge component for project verification status
- Create PortfolioDonutChart for visual portfolio allocation
- Implement RadialProgress for percentage displays
- Add reusable form components (FormInput, FormTextarea, FormSelect, FormFieldWrapper)
- Refactor OffsetOrder with improved layout and animations
- Add offset percentage slider with visual feedback
- Enhance MobileOffsetOrder with better responsive design
- Improve TripCalculator with cleaner UI structure
- Update CurrencySelect with better styling
- Add portfolio distribution visualization
- Enhance project cards with hover effects and animations
- Improve color palette and gradient usage throughout

## Configuration
- Add VITE_API_BASE_URL environment variable
- Create backend .env.example template
- Update frontend .env.example with API URL
- Add Stripe documentation references

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-29 21:45:14 +01:00
Matt
3a33221130 Hide debug logs in production
All checks were successful
Build and Push Docker Image / docker (push) Successful in 48s
- Create logger utility that only logs in development mode
- Update wrenClient.ts to use logger instead of console.log/warn
- Update OffsetOrder.tsx to use logger for debug messages
- Update config.ts to only log environment loading in dev mode
- Keeps console.error for actual errors (always shown)

Fixes: Console clutter in production deployment

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-29 14:58:22 +01:00
Matt
01b232f909 Enhance UX with number formatting and improve offset workflow
- Add comma-separated number formatting for better readability in all calculator inputs
- Move offset percentage selection from calculator to offset order page for clearer workflow
- Improve project card layout with consistent height alignment in OffsetOrder
- Change number inputs to text inputs to support formatted display
- Update form messages to reflect chosen offset percentage
- Add CLAUDE.md documentation for repository guidance

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-29 12:51:43 +01:00
Matt
fe801c1542 Improve responsive layout and clean up interaction handling
- Increase max widths and improve responsive spacing across components
- Add responsive grid columns (xl:grid-cols-4) for better large screen layout
- Remove redundant click area overlay and hover effects for cleaner code
- Consolidate padding management to main container level
2025-06-03 18:29:34 +02:00
Matt
8ff0ba44f8 updates 2025-06-03 18:18:42 +02:00
Matt
1f2e0e8222 updates 2025-06-03 17:07:59 +02:00
Matt
df2e11f600 updates 2025-06-03 15:25:13 +02:00
Matt
bf38357c74 updates 2025-06-03 15:21:29 +02:00
Matt
e816ea48d2 updates 2025-06-03 15:09:20 +02:00
Matt
5308cb61d1 updates 2025-06-03 15:02:29 +02:00
Matt
f9e4bc0149 Add framer-motion animations to enhance UI interactions
- Install framer-motion dependency (v12.15.0)
- Add smooth transitions to forms and buttons in TripCalculator
- Implement hover and tap animations for interactive elements
- Add entrance/exit animations for component state changes
- Enhance user experience with motion effects in Home and OffsetOrder components
2025-06-03 14:26:22 +02:00
Matt
bf0f362ab7 Merge branch 'main' of https://code.puffinoffset.com/matt/puffin-app 2025-06-03 14:08:35 +02:00
Matt
2376205371 Added lightboxes 2025-06-03 14:07:33 +02:00
Matt
96496350ee Updated with Lightboxes 2025-06-02 20:36:04 +02:00
Matt
5d0cfdef47 more fixes 2025-05-13 21:05:12 +02:00
Matt
43fca42b7f more fixes 2025-05-13 20:58:17 +02:00
Matt
444ab364a4 better connections 2025-05-13 20:48:28 +02:00
Matt
c29b15cd0b more fixes 2025-05-13 20:42:16 +02:00
Matt
7be9fc3722 more fixes 2025-05-13 20:21:05 +02:00
Matt
279098e9fa more fixes 2025-05-13 20:12:41 +02:00
Matt
2f7f26e4fd updates 2025-05-13 20:09:23 +02:00
Matt
121b1264b7 initial push 2025-05-13 18:50:30 +02:00