Plan Your Visit landing page for visit.waterschurch.org

Next.js 16 static export + PHP 8 API for cPanel/Apache hosting.

- Location-aware campus finder (IP estimate, optional precise location, ZIP search)
- Three-step Plan Your Visit form with separate email/SMS consent
- PHP API: validation, anti-spam, rate limiting, SQLite lead store,
  Mailchimp and Sinch Engage adapters, idempotent retries via cron
- Attribution capture (utm_*, gclid/gbraid/wbraid, fbclid, ttclid, twclid) and
  consent-aware analytics hooks
- Vitest and PHP test suites, cPanel deployment script and docs

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Waters Church
2026-09-22 13:22:26 -04:00
co-authored by Claude Fable 5.1
commit 78cd0cc550
109 changed files with 16861 additions and 0 deletions
+67
View File
@@ -0,0 +1,67 @@
import { describe, expect, it } from "vitest";
import { campuses, getCampus, openCampuses } from "@/config/campuses";
import { FAR_AWAY_MILES, formatDistance, haversineMiles, isValidLatLng, nearestCampus, normalizeZip, rankCampuses } from "@/lib/geo";
describe("haversineMiles", () => {
it("returns 0 for identical points", () => {
expect(haversineMiles({ lat: 42, lng: -71 }, { lat: 42, lng: -71 })).toBe(0);
});
it("matches a known distance (Boston → Providence ≈ 41 mi)", () => {
const d = haversineMiles({ lat: 42.3601, lng: -71.0589 }, { lat: 41.824, lng: -71.4128 });
expect(d).toBeGreaterThan(39);
expect(d).toBeLessThan(43);
});
});
describe("nearestCampus", () => {
it("recommends North Attleboro from Attleboro Falls", () => {
const r = nearestCampus({ lat: 41.97, lng: -71.3 }, campuses)!;
expect(r.campus.id).toBe("north-attleboro");
expect(r.distanceMiles).toBeLessThan(1);
});
it("recommends Norwood from Dedham", () => {
expect(nearestCampus({ lat: 42.2436, lng: -71.166 }, campuses)!.campus.id).toBe("norwood");
});
it("recommends Woonsocket from Cumberland RI", () => {
expect(nearestCampus({ lat: 41.9668, lng: -71.4328 }, campuses)!.campus.id).toBe("woonsocket");
});
it("recommends Southcoast from Fall River", () => {
expect(nearestCampus({ lat: 41.7015, lng: -71.155 }, campuses)!.campus.id).toBe("southcoast");
});
it("recommends Apollo Beach from Tampa", () => {
expect(nearestCampus({ lat: 27.9506, lng: -82.4572 }, campuses)!.campus.id).toBe("apollo-beach");
});
it("never recommends a launching campus, even when it is closest", () => {
// Winter Park FL is 0 mi from the Orlando launch location
const r = nearestCampus({ lat: 28.59213, lng: -81.37501 }, campuses)!;
expect(getCampus("orlando")?.status).toBe("launching");
expect(r.campus.id).toBe("apollo-beach");
expect(r.distanceMiles).toBeGreaterThan(FAR_AWAY_MILES);
});
it("ranks every open campus and sorts ascending", () => {
const ranked = rankCampuses({ lat: 42.0, lng: -71.4 }, campuses);
expect(ranked).toHaveLength(openCampuses.length);
for (let i = 1; i < ranked.length; i++) expect(ranked[i].distanceMiles).toBeGreaterThanOrEqual(ranked[i - 1].distanceMiles);
});
});
describe("helpers", () => {
it("formats distances for humans", () => {
expect(formatDistance(0.4)).toBe("under a mile");
expect(formatDistance(3.26)).toBe("3.3 mi");
expect(formatDistance(47.6)).toBe("48 mi");
});
it("validates coordinates and rejects null island", () => {
expect(isValidLatLng({ lat: 41.9, lng: -71.3 })).toBe(true);
expect(isValidLatLng({ lat: 0, lng: 0 })).toBe(false);
expect(isValidLatLng({ lat: 91, lng: 0 })).toBe(false);
expect(isValidLatLng({ lat: "41", lng: -71 })).toBe(false);
expect(isValidLatLng(null)).toBe(false);
});
it("normalizes ZIP codes", () => {
expect(normalizeZip(" 02763 ")).toBe("02763");
expect(normalizeZip("02763-1234")).toBe("02763");
expect(normalizeZip("2763")).toBeNull();
expect(normalizeZip("abcde")).toBeNull();
});
});