Remove dead code: unused components, duplicate logic, orphaned route

- Delete Hero, ReviewsSection, TrustedBrands components (never imported)
- Delete /api/admin/orders/[orderId]/complete route (never called; order
  state transitions go through /status instead)
- Extract maxColorsFor() from ProductCard and CartDrawer into
  src/lib/colors.ts to eliminate the duplicated implementation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
chris 2026-06-10 08:01:39 -04:00
parent f0b60f123d
commit 9dd4aff35e
7 changed files with 10 additions and 256 deletions

View File

@ -1,43 +0,0 @@
import { NextRequest, NextResponse } from 'next/server'
import { Client, Environment } from 'square'
function getClient() {
return new Client({
accessToken: process.env.SQUARE_ACCESS_TOKEN!,
environment: process.env.SQUARE_ENVIRONMENT === 'production'
? Environment.Production
: Environment.Sandbox,
})
}
export async function POST(
_req: NextRequest,
{ params }: { params: { orderId: string } }
) {
try {
const client = getClient()
const { orderId } = params
// Retrieve current order to get version (required for optimistic concurrency)
const { result: { order } } = await client.ordersApi.retrieveOrder(orderId)
if (!order) return NextResponse.json({ error: 'Order not found' }, { status: 404 })
await client.ordersApi.updateOrder(orderId, {
order: {
locationId: order.locationId!,
state: 'COMPLETED',
version: order.version,
fulfillments: (order.fulfillments ?? []).map((f) => ({
uid: f.uid,
state: 'COMPLETED',
})),
},
idempotencyKey: `complete-${orderId}`,
})
return NextResponse.json({ ok: true })
} catch (err) {
console.error('[admin/orders/complete]', err)
return NextResponse.json({ error: 'Failed to complete order' }, { status: 500 })
}
}

View File

@ -15,6 +15,7 @@ import ColorPicker from './ColorPicker'
import BookingRequestPanel from './BookingRequestPanel' import BookingRequestPanel from './BookingRequestPanel'
import CalendarPicker from './CalendarPicker' import CalendarPicker from './CalendarPicker'
import type { CartEntry } from '@/context/CartContext' import type { CartEntry } from '@/context/CartContext'
import { maxColorsFor } from '@/lib/colors'
/** Syncs a string state value to localStorage. Hydrates after mount. */ /** Syncs a string state value to localStorage. Hydrates after mount. */
function useStoredString(key: string, initial: string): [string, (v: string) => void] { function useStoredString(key: string, initial: string): [string, (v: string) => void] {
@ -32,15 +33,6 @@ function useStoredString(key: string, initial: string): [string, (v: string) =>
return [value, set] return [value, set]
} }
function maxColorsFor(name: string): number | null {
const n = name.toLowerCase()
if (/arch|column/.test(n)) return 4
if (/\b11["''″]|\b11[- ]?inch/.test(n)) return 1
if (/number.{0,10}sculpt|sculpt.{0,10}number/.test(n)) return 4
if (/ultimate/.test(n)) return 4
return null
}
type Step = 'cart' | 'delivery' | 'info' | 'payment' type Step = 'cart' | 'delivery' | 'info' | 'payment'
const STEP_TITLES: Record<Step, string> = { const STEP_TITLES: Record<Step, string> = {

View File

@ -1,87 +0,0 @@
/**
* Hero section matches the layout of beachpartyballoons.com's index.html:
* full-width image with the logo overlaid, then centered address + CTA.
*/
export default function Hero() {
return (
<>
{/* Scrolling announcement bar */}
<div className="update">
<div id="message">
🎈 Walk-ins welcome! · Delivery available across CT · Over 70 latex colors in stock · Custom arrangements made while you wait · 203.283.5626
</div>
</div>
{/* Hero image with logo overlay */}
<div className="container is-justify-content-center padding">
<figure className="image" style={{ position: 'relative' }}>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img src="/images/classic/hero.webp" alt="Beach Party Balloons" />
{/* eslint-disable-next-line @next/next/no-img-element */}
<img
className="is-overlay"
src="/images/logo/BeachPartyBalloons-logo.webp"
alt="Beach Party Balloons logo"
style={{ width: '50%', height: 'auto', margin: 'auto' }}
/>
</figure>
</div>
{/* Address + contact */}
<div className="is-flex-direction-column is-dark">
<h1 className="is-size-3" style={{ textAlign: 'center' }}>
Shop Online
</h1>
<h2 className="is-size-4" style={{ textAlign: 'center' }}>
<a
target="_blank"
rel="noopener noreferrer"
href="https://maps.app.goo.gl/gRk6NztgMRUsSVJf9"
>
554 Boston Post Road, Milford, CT 06460
</a>
</h2>
<h2 className="is-size-4" style={{ textAlign: 'center' }}>
<a href="tel:203.283.5626">203.283.5626</a>
</h2>
<div className="py-2 has-text-centered">
<a href="https://beachpartyballoons.com/contact/">
<button className="button is-info">Contact Us</button>
</a>
</div>
</div>
{/* Intro image + copy */}
<div className="container is-justify-content-center padding">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img src="/images/organic/img1.webp" alt="Organic balloon arrangement" />
</div>
<p className="is-size-5 has-text-centered">Walk-ins welcome!</p>
<p className="is-size-6 has-text-centered">
Pick up a balloon arrangement for birthdays or any occasion. We will make
it while you wait!
</p>
<p className="is-size-6 has-text-centered">
We have hundreds of foil balloon choices in stock and over 70 latex colors!
</p>
<p className="is-size-5 has-text-centered">
...Or consult with one of our designers about your balloon decorating needs.
</p>
<div className="container is-justify-content-center padding">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img src="/images/organic/img2.webp" alt="Delivery balloon arrangement" />
</div>
<p className="is-size-5 has-text-centered">Delivery available!</p>
<p className="is-size-5 has-text-centered">
Have your balloons delivered! Our delivery staff will make sure your order
arrives safe and sound!
</p>
<hr className="section-divider" />
</>
)
}

View File

@ -4,20 +4,12 @@ import { useState } from 'react'
import type { CatalogItem } from '@/data/mock-catalog' import type { CatalogItem } from '@/data/mock-catalog'
import ColorPicker from './ColorPicker' import ColorPicker from './ColorPicker'
import { fmt } from '@/lib/format' import { fmt } from '@/lib/format'
import { maxColorsFor } from '@/lib/colors'
interface Props { interface Props {
item: CatalogItem item: CatalogItem
} }
function maxColorsFor(name: string): number | null {
const n = name.toLowerCase()
if (/arch|column/.test(n)) return 4
if (/\b11["''″]|\b11[- ]?inch/.test(n)) return 1
if (/number.{0,10}sculpt|sculpt.{0,10}number/.test(n)) return 4
if (/ultimate/.test(n)) return 4
return null
}
/** Lowest stock count across tracked variations. null = nothing tracked. */ /** Lowest stock count across tracked variations. null = nothing tracked. */
function lowestTrackedInventory(item: CatalogItem): number | null { function lowestTrackedInventory(item: CatalogItem): number | null {
const tracked = item.variations.filter((v) => v.inventory !== null) const tracked = item.variations.filter((v) => v.inventory !== null)

View File

@ -1,68 +0,0 @@
const REVIEWS = [
{
text: '"Stunning balloon arch and super easy to work with. Our guests loved it!"',
author: '— Jordan M., Corporate Event',
},
{
text: '"Professional setup and gorgeous colors. Made our celebration unforgettable."',
author: '— Maria L., Birthday Party',
},
{
text: '"Fast, friendly, and beautiful designs. Will book again for our next event."',
author: '— Alex T., School Event',
},
]
export default function ReviewsSection() {
return (
<>
<hr className="section-divider" />
<section className="section reviews-section">
<div className="container has-text-centered">
<h2 className="is-size-3">Google Reviews</h2>
<p className="is-size-6 has-text-grey">
See what clients are saying, or leave a review after your event.
</p>
<div className="reviews-summary mt-4">
<div className="reviews-stars" aria-label="Average rating: 4.9 out of 5">
<span></span><span></span><span></span><span></span><span></span>
</div>
<p className="is-size-5 has-text-weight-semibold">
Rated 4.9 on Google
</p>
<p className="is-size-7 has-text-grey">Based on 100+ reviews</p>
</div>
<div className="reviews-grid mt-5">
{REVIEWS.map((r, i) => (
<article key={i} className="review-card">
<p>{r.text}</p>
<p className="review-author">{r.author}</p>
</article>
))}
</div>
<div className="buttons is-centered mt-4">
<a
className="button is-info"
target="_blank"
rel="noopener noreferrer"
href="https://www.google.com/maps/place/Beach+Party+Balloons/@41.2305385,-73.0657635,17z"
>
Read reviews
</a>
<a
className="button is-light"
target="_blank"
rel="noopener noreferrer"
href="https://g.page/r/CUEOXUF1nSDQEBE/review"
>
Leave a review
</a>
</div>
</div>
</section>
</>
)
}

View File

@ -1,40 +0,0 @@
const LOGOS = [
{ src: '/images/trusted/512px-Subway_icon.svg.webp', alt: 'Subway', dark: false },
{ src: '/images/trusted/Yale_press_logo.webp', alt: 'Yale', dark: false },
{ src: '/images/trusted/256px-Quinnipiac_University_logo_(2017).svg.webp', alt: 'Quinnipiac University', dark: false },
{ src: '/images/trusted/512px-University_of_New_Haven_logo.webp', alt: 'University of New Haven', dark: false },
{ src: '/images/trusted/Planet_Fitness_(2).webp', alt: 'Planet Fitness', dark: false },
{ src: '/images/trusted/Mohegan-Sun-Logo.webp', alt: 'Mohegan Sun', dark: false },
{ src: '/images/trusted/Post_university_of_conn_logo.webp', alt: 'Post University', dark: false },
{ src: '/images/trusted/logo-full-color.webp', alt: 'Edge Fitness', dark: false },
{ src: '/images/trusted/lincoln-culinary.webp', alt: 'Lincoln Culinary Institute', dark: false },
{ src: '/images/trusted/amazon.webp', alt: 'Amazon', dark: false },
{ src: '/images/trusted/woodwinds-2024-logo-white.webp', alt: 'The Woodwinds', dark: true },
{ src: '/images/trusted/sallys-apizza.webp', alt: "Sally's Apizza", dark: false },
]
export default function TrustedBrands() {
return (
<section className="section trusted-section">
<div className="container">
<div className="has-text-centered mb-5">
<h2 className="is-size-3">Trusted by</h2>
<p className="is-size-6 has-text-grey">
Brands and organizations we have had the joy of celebrating with.
</p>
</div>
<div className="trusted-logos">
{LOGOS.map((logo) => (
<figure
key={logo.alt}
className={`trusted-logo ${logo.dark ? 'trusted-logo--dark' : ''}`}
>
{/* eslint-disable-next-line @next/next/no-img-element */}
<img src={logo.src} alt={`${logo.alt} logo`} loading="lazy" />
</figure>
))}
</div>
</div>
</section>
)
}

8
estore/src/lib/colors.ts Normal file
View File

@ -0,0 +1,8 @@
export function maxColorsFor(name: string): number | null {
const n = name.toLowerCase()
if (/arch|column/.test(n)) return 4
if (/\b11["''″]|\b11[- ]?inch/.test(n)) return 1
if (/number.{0,10}sculpt|sculpt.{0,10}number/.test(n)) return 4
if (/ultimate/.test(n)) return 4
return null
}