Commit Graph

44 Commits

Author SHA1 Message Date
myron f54148dbe7 Condense footer from 5 columns to 3
Merged Company + Support into a single Help column, removed Sub
Categories section. Tightened grid gap, padding, and list spacing.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-15 17:23:32 +00:00
myron 01dc6f90fe Remove Weatherford TX location references from merchant feed 2026-06-14 23:49:11 +00:00
myron 94d19d27f1 Add Google Search Console verification meta tag 2026-06-14 23:10:07 +00:00
myron b504981b89 Add Google Merchant Center product feed and GSC meta tag placeholder
- merchant-feed.php: RSS 2.0 feed with all active products; includes
  title, description, image_link, price, availability, brand, shipping,
  google_product_category for each item; URL to submit in Merchant Center
- header.php: placeholder GSC meta tag (replace PASTE_GSC_CODE_HERE with
  verification content value from Search Console)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 23:01:53 +00:00
myron 873a0962c6 SEO overhaul: product schema, dynamic sitemap, favicon, og-image fix
- product.php: set metaTitle, metaDescription, canonicalUrl, ogImage,
  ogType=product, productSchema (JSON-LD with price/availability/reviews),
  and breadcrumbs variables for header.php to consume
- sitemap.php: dynamic XML sitemap generated from DB — includes all 30
  active products + static pages; robots.txt now points here
- header.php: fix favicon links (favicon.ico in root + icon-192.png);
  fix productSchema output (was double-encoding via json_encode)
- robots.txt: point Sitemap directive to /sitemap.php

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 22:50:25 +00:00
myron f89362528a Fix loyalty system: load tiers from DB, award points on payment
- LoyaltyProgram now loads tiers from loyalty_tiers DB table in constructor
  with fallback to hardcoded defaults if table is empty
- awardPoints() accepts order_id param with duplicate-prevention check so
  points cannot be double-awarded for the same order
- Inserts balance_after into loyalty_transactions for accurate history
- payment-status.php: award points after Stripe checkout session or
  PaymentIntent confirmed as paid
- create-checkout-session.php: award points in demo mode payment path

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 20:58:37 +00:00
myron b6d0319be7 Fix admin order page blank redirect after status/note update
Missing ob_start() meant HTML was output before POST handler ran,
so header() redirects silently failed after saving changes.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 20:50:53 +00:00
myron bdba57166d Condense shop page: merge hero + filters into one compact bar
Combined the large hero section and two-row filter section into a single
compact dark header bar. Category and type pills are inline with a divider,
search/sort sit in the header row. Reduced section top padding.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 20:48:45 +00:00
myron 6e4d2734bb Fix console warnings: remove SW registration, fix meta tag, clean manifest
- Remove service worker registration from footer (SW is already self-unregistering)
- Add mobile-web-app-capable meta to fix deprecation warning
- Remove missing icon references from manifest (only 192/512 PNGs exist)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 20:38:15 +00:00
myron 714ef13897 Fix Stripe checkout: wrong column name stripe_checkout_session → stripe_session_id
DB column is stripe_session_id but code was writing to stripe_checkout_session,
causing a 500 on checkout and breaking payment status checks.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 20:35:35 +00:00
myron ecf5a7ab67 Fix cart quantity update: reload page to reflect accurate totals
Partial DOM update was missing item row totals, shipping recalc, and
grand total. Reload ensures all numbers are always correct.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 20:29:31 +00:00
myron ca2f612421 Fix add-to-cart on home page: wrong class and data attribute
Button used add-to-cart/data-id instead of add-to-cart-btn/data-product-id.
Added inline onclick to match shop and product pages.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 20:26:47 +00:00
myron 7dfec466a1 Disable service worker and clear all caches
SW was caching shop pages and JS files, serving stale versions without
the inline onclick handler. Replacing with self-unregistering SW.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 20:23:36 +00:00
myron 935b838c8f Fix cart: start session in functions.php so API endpoints persist cart
All api/*.php files include functions.php but none called session_start(),
so $_SESSION writes were lost after each request. Cart appeared to work
(API returned cart_count:1) but nothing was ever saved.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 20:18:23 +00:00
myron 6e86031576 Fix add-to-cart: bust main.js SW cache, add inline onclick to shop buttons
Service worker was caching main.js (cache-first strategy) so event listeners
may not have been running. Added filemtime version param to main.js like CSS.
Also added inline onclick to shop page buttons so they work regardless of
whether event delegation is functional.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 20:11:35 +00:00
myron e389254a7c Auto-bust Cloudflare CSS cache using filemtime version param
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 20:04:09 +00:00
myron 5c0927af39 Fix ambiguous column error on shop page JOIN query
Prefixed is_active, category, product_type_id, name, description, and ORDER BY columns with table alias p to resolve ambiguity with the product_types JOIN.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 19:56:47 +00:00
myron e6ca96b75c Make footer Shop links dynamic from products categories
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 19:50:51 +00:00
myron 29656bd4d7 Add product count column to product types admin page
Shows how many active products are linked to each type, linked to the filtered products list.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 19:50:29 +00:00
myron 890c98d4cd Fix product images, add-to-cart, and add Sub Categories filter
- Add display:block to .product-card-image so padding-top aspect ratio works on anchor tags
- Add Cache-Control: no-transform header to disable Cloudflare Rocket Loader (was deferring main.js and breaking add-to-cart click handlers)
- Add Sub Categories filter row on shop page using product_types table
- Show category · sub-category on product cards
- Add Sub Categories section to footer
- Preserve subcat param across category/sort filter links

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-14 19:47:08 +00:00
myron 548713971d Fix pagination styling, add-to-cart class/data-attr mismatch, shop.php pagination 2026-06-14 16:24:39 +00:00
myron da60888b72 Fix CSV import — convert tags/images to valid JSON before insert (mysql json_valid constraint) 2026-06-14 16:05:42 +00:00
myron 0a6c4508d5 Rebuild product image upload section — fix broken HTML, wrong textarea name, JS quote errors 2026-06-14 15:57:33 +00:00
myron 1609dea8fb Fix product image upload — remove header.php (outputs HTML), auth check directly 2026-06-14 15:48:19 +00:00
myron 5058da704a Fix product image upload — ob_end_clean() before JSON response, fix uploads dir permissions 2026-06-14 15:44:25 +00:00
myron 602bc77cdd Fix CyberMail from field — use separate from/from_name fields (API rejects Name <email> format) 2026-06-14 15:40:35 +00:00
myron 66cbd3f0d3 Remove prefilled placeholder email from admin login 2026-06-14 15:18:27 +00:00
myron 8957cb2c28 Remove equipment link from footer
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 12:53:53 +00:00
myron 2a1ca85062 Add FAQ, shipping, returns, track order, and privacy policy pages
- faq.php: accordion FAQ with Orders, Coffee & Products, Coffee Freshness & Storage, and Account sections
- shipping.php: rates table (3-5 days after processing), processing time, delivery flow
- returns.php: three-tier policy (your/our/shared responsibility) adapted from DripShipper
- track-order.php: order lookup by order number + email, progress steps, tracking link
- privacy.php: full privacy policy adapted for Toms Java Jive
- footer.php: added Privacy Policy link to Support section

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-04 12:52:25 +00:00
myron 62dd05780a Add payment_status guard to payment_intent.succeeded handler
Mirrors the checkout.session.completed case which checks
payment_status === paid before acting. Now checks data.status
=== succeeded on the PaymentIntent object, consistent with how
Stripe structures the event and defensive against any future
edge case where the event fires in a non-final state.
2026-06-03 06:13:22 +00:00
myron 7eddf9e85d Fix remaining code review findings: email transport errors, metadata payload, from-name, pagination
- Email::send(): add curl_error() check so transport failures (timeout,
  DNS, TLS) return a diagnosable error string instead of Unknown error
- Email::send(): strip metadata key from options before array_merge so
  non-API fields are never sent to CyberMail endpoint
- Email::send() + sendEmail(): include from-name in From field using
  RFC 5322 "Name <email>" format so fromName DB setting takes effect
- email-log.php: replace unbounded page-link loop with a windowed
  paginator (first/last 2 pages + ±2 around current) with ellipsis
  gaps — prevents hundreds of anchors rendering at scale
2026-06-03 06:01:44 +00:00
myron a5b91ca0ea Fix Email class ignoring DB from-address settings
Constructor now reads cybermail_from_email and cybermail_from_name from
the settings table via getSetting(), falling back to constants. Matches
the pattern already used for cybermail_api_key and the global sendEmail()
wrapper in functions.php. Admin integrations page changes now take effect
across all email paths.
2026-06-03 03:44:10 +00:00
myron f8e9746340 Route webhook order emails through Email class for email_log visibility
Replaced local sendOrderConfirmationEmail() with emailService()->sendOrderConfirmation().
Order confirmations now log to email_log table and use the branded template
(orange header, full subtotal/tax/discount breakdown) instead of the minimal
brown-header version that was invisible to the admin Email Log.
2026-06-03 03:42:50 +00:00
myron 2550ec5695 Fix duplicate order confirmation email on Stripe Checkout
When using Stripe Checkout, both checkout.session.completed and
payment_intent.succeeded fire for the same payment. After the stripe.php
change propagated order_id into PI metadata, the PI handler also found
an order_id and sent a second confirmation email.

Fix: fetch the order first in payment_intent.succeeded and skip if
already confirmed. Also records stripe_payment_intent in this path
for direct PI flows that bypass checkout.session.completed.
2026-06-03 03:41:30 +00:00
myron 4f096047b6 Fix CyberMail payload format: use flat string for from/to fields 2026-05-29 18:58:35 +00:00
myron 76bf967bd0 Switch email to CyberMail API; integrations page manages API key via DB 2026-05-29 18:49:15 +00:00
myron 6b71828199 Fix integrations.php: handle POST before HTML output to fix blank screen on save 2026-05-29 18:31:16 +00:00
myron e39df89a95 Fix webhook: add checkout.session.completed; propagate metadata to payment intent 2026-05-29 16:32:37 +00:00
myron 0d481f8feb Simplify admin login to email/password only; remove Google OAuth 2026-05-29 15:33:16 +00:00
myron e344e52d70 Add Google OAuth admin login; fix header comment; both auth methods active 2026-05-29 15:13:38 +00:00
myron 53f9f3e4da Replace all SendGrid references with CyberMail in admin UI 2026-05-29 15:06:43 +00:00
myron 25e96a3d5f Switch sendEmail() in functions.php to CyberMail API 2026-05-29 15:02:17 +00:00
myron d30851e3ec Add DB schema (45 tables) and vhost config 2026-05-25 13:51:25 +00:00
myron 996ca0d621 Initial commit 2026-05-22 12:52:44 +00:00