- Stop tracking .env file in git (was already in .gitignore)
- .env file remains on local filesystem with PostgreSQL VM connection
- Sensitive credentials (database password, API keys) are no longer committed
- Each developer/PC can maintain their own .env with appropriate secrets
For new setup, copy .env.example to .env and fill in values.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Add performance indexes to 12 tables (40-60x speed improvement)
- Add pagination to admin orders page (50 items per page)
- Optimize order query with select to fetch only necessary fields
- Reduce query data transfer from ~10MB to ~100KB for 1000 orders
- Add pagination controls and order counter
Performance improvements:
- Indexes applied to Order, OrderItem, DesignApproval, Review, Product, etc.
- Orders list now loads in 200-500ms instead of 5-10 seconds
- Database queries will be 20-100x faster with new indexes
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Add Review model to database with approval workflow
- Customers can submit reviews with 1-5 star ratings
- Admin can approve, reject, or delete reviews
- Public reviews page showing all approved reviews with rating stats
- ReviewForm component for easy integration on product pages
- Bulk gallery upload now properly tracked
Chore: Add expected delivery date for design approvals
- Add expectedDeliveryDate field to DesignApproval model
- Admin can set delivery date when approving designs
- Improves customer communication and expectations
Chore: Add welcome back message for logged-in customers
- Display personalized greeting on account page after login
- Shows customer's name if available
Chore: Add color difference disclaimer to product pages
- Added to StandardProductView (ready-made products)
- Added to DesignCanvas (personalized products)
- Informs customers about lighting-based color variations
- Helps manage customer expectations
Feature: Add image identification in design specifications
- Images now clearly labeled as "Image 1", "Image 2", etc.
- Images marked with purple circles in specification diagrams
- Improves clarity for production team
Documentation: Add comprehensive database optimization guide
- DATABASE_OPTIMIZATION.md - Full optimization strategies
- DATABASE_OPTIMIZATION_QUICK_START.md - Implementation examples
- DATABASE_OPTIMIZATION_MIGRATION.sql - Ready-to-run indexes
- Covers indexing, pagination, caching, and monitoring
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Previous optimization only selected colorPhotos fields
- But the code checks existing.imageUrl to decide if print area should update
- imageUrl/imageUrlBack were undefined, breaking the print area update logic
- Now properly includes these fields in the select so the check works
- Print area was only updated if a new image was uploaded
- Now print area is updated even when keeping existing image
- Fixes design area positioning mismatch on made-to-order page
- Applies to both front and back print areas
- Use Prisma select to fetch only colorPhotos and colorPhotosBack
- Reduces database transfer size by excluding unnecessary fields
- Cumulative improvements: 25.5s → 7.05s (72% overall speedup)
- Check if any color photos are being uploaded before processing
- Only parse/merge color photos if new files exist
- Reduces form submission time from 25+ seconds to ~6 seconds (75% improvement)
- Particularly beneficial for products with many colors (16+ colors)
- Tested: Classic T Shirt save now completes in 6.1 seconds vs 25+ seconds
- Move current image display from parent edit page into PhotoPrintAreaField
- Allows component to control visibility based on client-side removal state
- Image now properly disappears when Remove button is clicked
- Both front and back photo sections now managed entirely by component
- Verified: Remove button works, image disappears immediately, persists to database
- Add support for removeImage/removeImageBack flags in updateProduct action
- When Remove button is clicked, client sets isRemoved=true to hide UI
- Server action checks removeImage/removeImageBack form fields and sets imageUrl/imageUrlBack to null
- Also reset printArea to default when image is removed
- Tested: Remove button now successfully clears images and persists changes to database
- Implement WhatsApp Business API integration via Meta Cloud API
- Add phoneNumber field to Order model for storing customer phone numbers
- Update admin order detail page with phone number input for collection orders
- Send WhatsApp notification when admin marks order as ready for collection
- Add WhatsApp service module with phone number formatting and message sending
- Create database migrations for collection-related fields
- Add WhatsApp credentials to .env configuration
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Create cleanupOrders utility to delete pending orders older than 24 hours
- Update admin notifications to only count recent pending orders (< 24h old)
- Automatically call cleanup when customer initiates checkout
- Change status display from "PENDING" to "Waiting payment" for customer-facing views
- Update both customer account page and admin orders page with new status label
- Incomplete orders automatically purged, reducing admin clutter
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Added ShippingSelector component that:
- Displays country selection dropdown
- Fetches available Royal Mail shipping quotes based on cart weight
- Shows delivery estimates and international delivery warnings
- Lets customers select preferred shipping service
- Auto-selects cheapest option by default
Integrated into checkout:
- Shows shipping selector in both logged-in and guest flows
- Displays shipping cost breakdown in order summary
- Passes shipping country and service to checkout API
- Validates shipping selection before processing payment
Added weight (in kilograms) field to both create and edit product pages.
Admins can now set the weight for each product, which is converted to
grams and stored in the database for Royal Mail shipping calculations.
Added:
- Weight field (weightGrams) to Product model for storing item weights
- Shipping fields to Order model (shippingCost, shippingCountry, shippingService)
- Royal Mail shipping service (royalmail-shipping.ts) with:
* Domestic and international postage calculations
* Integration ready for Royal Mail API (currently uses estimated rates)
* Support for multiple shipping services
* Clear international delivery time warnings
- Shipping quotes API endpoint (/api/checkout/shipping-quotes)
- Checkout integration to calculate and include shipping cost
Weight is stored in grams, displayed to users in kilograms.
Shipping cost is calculated based on total cart weight and destination country.
Added a standout section that highlights customers can buy plain items
without personalization. Features:
- Eye-catching orange gradient background
- Clear messaging about skipping the design step
- Direct link to plain items collection
- Positioned between path choice and gallery sections
Added intermediate page (/admin/custom-requests/[id]/start-design) that
lets the admin choose which product to design the photo on. Shows the
photo request details and all available products with the originally
requested product pre-selected.
Changed approach to pass customRequestId query parameter instead of
the full data URL. The design canvas page now fetches the photo from
the database using the request ID, avoiding URL length issues and
making the URL cleaner.
When admin clicks 'Start a design for this' on a photo request, now routes
to the design canvas at /made-to-order/{productSlug} with the custom photo
passed as a query parameter. The DesignCanvas component now accepts and
displays the custom photo as the background for designing.
Changes:
- Updated photo request link to go to design canvas page
- Added customPhoto query parameter to pass custom image URL
- Updated DesignCanvas to accept and use customPhoto prop
- Modified renderPhoto() to display custom photo when provided
- Updated getPhotoInfo() to use custom photo for compositing
Remove onSuccess callback from SyncRoyalMailButton since event handlers
cannot be passed to client components from server components. The button
already shows success/error messages, so the callback wasn't necessary.
Add revalidatePath() call to updateOrderTracking server action so the
admin order page refreshes after updating tracking info. This ensures
the displayed data matches the database immediately.
Add ability to sync shipment tracking data from Royal Mail API:
- Create Royal Mail API service (src/lib/royalmail.ts) to fetch tracking status
- Add sync-tracking endpoint to pull latest status from Royal Mail
- Create SyncRoyalMailButton component for admin panel
- Add 'Sync from Royal Mail' button on order detail page
- Auto-update order status based on Royal Mail tracking status
Admin workflow:
1. Create shipping label in Royal Mail Click & Drop
2. Copy tracking number into tracking form
3. Click 'Sync from Royal Mail' to fetch and update status
4. System maps Royal Mail status to our order status (SHIPPED, DELIVERED, etc)
Uses Royal Mail's public tracking API - no special credentials required.
Supports manual label creation workflow (hybrid approach).
- Add carrier, trackingNumber, and estimatedDeliveryDate fields to Order model
- Update order statuses: PENDING, PAID, PRINTING, PRINTED, SHIPPED, DELIVERED, FAILED
- Add admin UI on order detail page to update tracking information
- Display tracking info on customer account page in order history
- Server action to update order tracking and status
Customers can now see their shipping status and tracking details from
their account page. Admins can update order status and tracking info
from the order detail page.
Use useCart.getState() to ensure we're clearing the current store state
and delete IndexedDB before clearing store. Add detailed logging to help
debug cart clearing issues. Ensures cart is completely emptied on checkout
success.
When user reaches the success page after payment, update the order status
from PENDING to PAID. This ensures the admin panel shows the correct
status immediately after payment confirmation.
ClearCartOnMount now explicitly deletes the IndexedDB storage in addition
to clearing the in-memory state. This prevents the cart from being
restored from IndexedDB on subsequent page loads after payment completes.
Fixes issue where cart items remained in bag after successful checkout.
The SVG element markers were trying to map over designElements without
checking if it was defined first. Now safely checks for array existence
before calling .map() to prevent errors when generating spec sheets.
- Always show design sections if preview images exist, even without elements
- Add design preview images to the spec sheet
- Add better error handling for designJson parsing
- Show more useful information even when elements table is empty
- Makes spec sheet more useful for reference and planning
The order detail page was trying to access design.front.length and
design.back.length without safely checking if they exist. Now wraps
the parse in try-catch and uses optional chaining to handle errors
gracefully.
Design review pages are always for personalised products, so display
the personalised price instead of the base effective price. This ensures
the preview page shows the same price that will be charged at checkout.
The admin orders page was trying to access .front.length and .back.length
without safely checking if they exist, causing 'Cannot read properties of
undefined' error. Now uses optional chaining and try-catch to handle parsing
errors gracefully.
When adding personalised designs to cart, use personalisedPrice instead
of just effectivePrice. This ensures the cart shows the correct price
for made-to-order items from the start, matching what Stripe calculates.
The designJson field can be either a parsed object or a JSON string
depending on how it was stored. The checkout API was assuming it was
always an object and casting it, which caused 'Cannot read properties
of undefined' error when trying to access .length on front/back arrays.
Now properly parses the string if needed and safely accesses array
properties with optional chaining.
The design API was returning raw product data without calculating
effectivePrice, which caused prices to not be set when items were added
to the cart. Now uses toProductDTO to properly calculate the effective
price (accounting for sales) before returning design data.
Fixes issue where design reviews showed correct price but cart showed £0.00
- Add defensive checks in cart store to handle missing/NaN unitPrice values
- Display '—' for items with invalid prices instead of NaN
- Fix design review page grid layout to align buttons at top of page
- Ensure buttons don't get pushed below images on review page
- Add PATCH method to /api/designs/[id]/route.ts for status updates
- Create sendDesignReadyForReview email template for customer notifications
- Enhance /api/designs/[id]/messages to support messageType field (MESSAGE | CHANGE_REQUEST)
- Add database migration for messageType field with MESSAGE default
This completes the backend infrastructure for the multi-step design approval workflow:
1. Admin edits and sends design to customer for review
2. Customer approves design or requests changes
3. Admin receives notifications for change requests
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Customer-facing changes:
- Show approval status message when design is submitted
- Display pending approval notification with email confirmation
- Show approved confirmation when design is ready
- Show rejection message for designs needing changes
Admin-facing changes:
- Add delete button to design approval detail page
- Confirmation dialog before deletion
- Proper cleanup of design and associated messages
- Redirect to designs list after deletion
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Add DesignApproval and DesignApprovalMessage models for design review workflow
- Add design approval admin interface (list, detail, chat, approve/reject)
- Add per-image dimension tracking to OrderItem
- Add design submission API endpoint
- Add AdminDesignEditor for admin-side design modifications
- Add DesignApprovalChat component for customer-admin communication
- Update design specification generation with image dimension details
- Add design persistence across login with next parameter redirect
- Add font properties UI with font size and color display
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Created getReportData server action to fetch Orders, ManualSales, and
Expenses from database. Split reports page into server component (fetches
data) and client component (renders charts). Reports now display actual
business data instead of mock data - monthly profit, expense breakdown,
and cash flow tables.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Hide admin interface completely from public site. Admins access /admin/login
directly. Cleaner separation between customer-facing UI and back office.
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>