| Server IP : 173.209.174.21 / Your IP : 216.73.216.89 Web Server : Apache/2.4.58 (Ubuntu) System : Linux wcfs-server 6.8.0-124-generic #124-Ubuntu SMP PREEMPT_DYNAMIC Tue May 26 13:00:45 UTC 2026 x86_64 User : nodor ( 1000) PHP Version : 8.3.6 Disable Function : NONE MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : OFF Directory : /var/www/grangestation/ |
Upload File : |
const siteConfigStorageKey = "grangeStationSiteConfig";
const availabilityBlocksStorageKey = "grangeStationAvailabilityBlocks";
const defaultSiteConfig = {
branding: {
venueName: "Grange Station",
tagline: "Wilson Creek, WA",
logoImage: "",
heroImage: "assets/grange-station.png",
socialImage: "assets/grange-station.png"
},
colors: {
ink: "#231f1a",
paper: "#f7f2ea",
cream: "#fffaf2",
barn: "#9b2f24",
sage: "#6d7f63",
gold: "#c49a57"
},
pricing: {
weekendLow: 1200,
weekendHigh: 1800,
weekdayLow: 850,
weekdayHigh: 1350,
over100Low: 250,
over100High: 450,
standardAddonLow: 75,
standardAddonHigh: 125,
rentalAddonLow: 150,
rentalAddonHigh: 450,
vendorIntroLow: 25,
vendorIntroHigh: 75
},
addons: [
{ value: "Setup Time & Extra Hours", label: "Setup Time & Extra Hours", priceLow: 100, priceHigh: 100, priceUnit: "per hour", enabled: true },
{ value: "Photo Session Access", label: "Photo Session Access", priceLow: 100, priceHigh: 100, priceUnit: "per hour", enabled: true },
{ value: "Vendor Walkthrough", label: "Vendor Walkthrough", priceLow: 30, priceHigh: 30, priceUnit: "", enabled: true },
{ value: "Table linens", label: "Table linens", priceLow: 10, priceHigh: 10, priceUnit: "per table", enabled: true },
{ value: "Catering introduction", label: "Catering introduction", priceLow: 0, priceHigh: 0, priceUnit: "", enabled: true },
{ value: "DJ introduction", label: "DJ introduction", priceLow: 0, priceHigh: 0, priceUnit: "", enabled: true }
],
packages: [
{
name: "Simple & Sweet",
subtitle: "Single-Day Rental",
priceLow: 1500,
priceHigh: 1800,
investmentNote: "$1,500 for Friday or Sunday. $1,800 for Saturday.",
timeBlock: "10 to 12 Hours of exclusive property access (e.g., 10:00 AM to 10:00 PM).",
description: "Perfect for budget-conscious couples, intimate gatherings, or those planning a streamlined, beautifully focused celebration. This single-day block gives you full, exclusive access to create your vision from scratch.",
included: [
"Full, exclusive use of the historic hall and open ceremony lawn.",
"On-site parking for all of your guests.",
"A completely open vendor policy--choose the insured caterer, food truck, or bartender that fits your style.",
"Standard post-event trash drop-off zone."
],
includes: "Full, exclusive use of the historic hall and open ceremony lawn.\nOn-site parking for all of your guests.\nA completely open vendor policy--choose the insured caterer, food truck, or bartender that fits your style.\nStandard post-event trash drop-off zone.",
blueprint: "Because we do not provide tables or chairs, this option is ideal for couples coordinating a swift single-day furniture drop-off and pickup window with their chosen rental company.",
enabled: true
},
{
name: "The Grange Gathering",
subtitle: "The Weekend Block",
priceLow: 2800,
priceHigh: 2800,
investmentNote: "",
timeBlock: "Friday Afternoon Setup/Rehearsal (4 hours) + Full-Day Saturday (12 hours) + Sunday Morning Clean-Up (2 hours).",
description: "Our most popular option. Logistics in rural Washington are much easier when you aren't rushing. This multi-day block removes the stress of a single-day crunch, giving your family, friends, and rental vendors a relaxed window to set up, celebrate, and clear out.",
included: [
"Everything included in our single-day rental, spread across three days.",
"Ample time on Friday for your rehearsal, layout design, and initial decor setup.",
"Elimination of the \"midnight cleanup rush\"--pack up your personal items and depart peacefully on Saturday, then return Sunday morning for final checks."
],
includes: "Everything included in our single-day rental, spread across three days.\nAmple time on Friday for your rehearsal, layout design, and initial decor setup.\nElimination of the \"midnight cleanup rush\"--pack up your personal items and depart peacefully on Saturday, then return Sunday morning for final checks.",
blueprint: "Rental delivery drivers love this package. Giving your rental company a flexible 3-day window to drop off and pick up your tables and chairs frequently saves you hundreds of dollars in strict weekend delivery surcharges.",
enabled: true
},
{
name: "The Going to the Grange Station",
subtitle: "The Upgraded Weekend Experience",
priceLow: 3500,
priceHigh: 3500,
investmentNote: "",
timeBlock: "Full Weekend Access (Friday afternoon, all-day Saturday, and Sunday morning).",
description: "You still bring in your own customized furniture to match your exact aesthetic, but we step in to handle the heavy lifting and convenience logistics so you can focus entirely on your guests.",
included: [
"Everything included in The Grange Gathering package.",
"In-House Decor Collection: Full access to our curated inventory of milk cans, vintage decor, mason jar table settings and romantic string lighting.",
"Post-Event Garbage Logistics: Don't worry about packing your trash away; our team takes care of the dumpster logistics after you leave.",
"Final Deep Clean: You remove your personal belongings and rentals, and we handle the post-wedding floor scrubbing, mopping, and porta potty details."
],
includes: "Everything included in The Grange Gathering package.\nIn-House Decor Collection: Full access to our curated inventory of milk cans, vintage decor, mason jar table settings and romantic string lighting.\nPost-Event Garbage Logistics: Don't worry about packing your trash away; our team takes care of the dumpster logistics after you leave.\nFinal Deep Clean: You remove your personal belongings and rentals, and we handle the post-wedding floor scrubbing, mopping, and porta potty details.",
blueprint: "",
enabled: true
}
],
vendors: [
{ category: "Rentals", title: "Tables, chairs, linens, and setup pieces", description: "Ask for help sourcing tables, chairs, linens, bars, decor, tents, heaters, or other event rental needs.", enabled: true },
{ category: "Catering", title: "Preferred food and beverage companies", description: "Request introductions to caterers, dessert providers, bar service, coffee service, or food trucks that fit the event style.", enabled: true },
{ category: "Music", title: "DJs, live music, and sound support", description: "Let us know if you need music recommendations, ceremony audio, reception sound, or vendor walkthrough time.", enabled: true }
],
faqs: [
{ question: "Where is Grange Station?", answer: "Grange Station is in Wilson Creek, Washington, with a rustic restored building and outdoor grounds suited for gatherings and photos.", enabled: true },
{ question: "How many guests can the venue hold?", answer: "The venue has comfortable room for 100 guests, with the possibility of more inside depending on event layout and setup needs.", enabled: true },
{ question: "Can we schedule a viewing?", answer: "Yes. Use the booking form and select Private Viewing to request a tour date and time.", enabled: true },
{ question: "What photo backdrops are available?", answer: "The restored building, porch, train tracks, railroad buildings, trees, lawn, and rock outcroppings all create strong photo settings.", enabled: true },
{ question: "Are tables and chairs included?", answer: "Not by default. Tables, chairs, linens, and related setup pieces can be requested as add-ons through available rental partners.", enabled: true },
{ question: "Do you have preferred vendors?", answer: "Yes. Guests can request preferred catering, rental, music, DJ, and sound recommendations when they submit a reservation or viewing request.", enabled: true },
{ question: "What areas do you serve?", answer: "Grange Station is based in Wilson Creek and serves Central Washington events from Moses Lake, Ephrata, Soap Lake, Grand Coulee, Quincy, Ritzville, Spokane, Wenatchee, Leavenworth, Omak, Grant County, Lincoln County, Adams County, and surrounding Washington communities.", enabled: true }
],
gallery: [
{ src: "assets/gallery/gallery-01.jpg", caption: "Grange Station venue gallery image.", enabled: true },
{ src: "assets/gallery/gallery-02.jpg", caption: "Grange Station venue gallery image.", enabled: true },
{ src: "assets/gallery/gallery-03.jpg", caption: "Grange Station venue gallery image.", enabled: true },
{ src: "assets/gallery/gallery-04.jpg", caption: "Grange Station venue gallery image.", enabled: true },
{ src: "assets/gallery/gallery-05.jpg", caption: "Grange Station venue gallery image.", enabled: true },
{ src: "assets/gallery/gallery-06.jpg", caption: "Grange Station venue gallery image.", enabled: true },
{ src: "assets/gallery/gallery-07.jpg", caption: "Grange Station venue gallery image.", enabled: true },
{ src: "assets/gallery/gallery-08.jpg", caption: "Grange Station venue gallery image.", enabled: true },
{ src: "assets/gallery/gallery-09.jpg", caption: "Grange Station venue gallery image.", enabled: true },
{ src: "assets/gallery/gallery-10.jpg", caption: "Grange Station venue gallery image.", enabled: true },
{ src: "assets/gallery/gallery-11.jpg", caption: "Grange Station venue gallery image.", enabled: true },
{ src: "assets/gallery/gallery-12.jpg", caption: "Grange Station venue gallery image.", enabled: true },
{ src: "assets/gallery/gallery-13.jpg", caption: "Grange Station venue gallery image.", enabled: true },
{ src: "assets/gallery/gallery-14.jpg", caption: "Grange Station venue gallery image.", enabled: true },
{ src: "assets/gallery/gallery-15.jpg", caption: "Grange Station venue gallery image.", enabled: true },
{ src: "assets/gallery/gallery-16.jpg", caption: "Grange Station venue gallery image.", enabled: true },
{ src: "assets/gallery/gallery-17.jpg", caption: "Grange Station venue gallery image.", enabled: true },
{ src: "assets/gallery/gallery-19.jpg", caption: "Grange Station venue gallery image.", enabled: true },
{ src: "assets/gallery/gallery-20.jpg", caption: "Grange Station venue gallery image.", enabled: true },
{ src: "assets/gallery/gallery-21.jpg", caption: "Grange Station venue gallery image.", enabled: true },
{ src: "assets/gallery/gallery-22.jpg", caption: "Grange Station venue gallery image.", enabled: true },
{ src: "assets/gallery/gallery-23.jpg", caption: "Grange Station venue gallery image.", enabled: true }
]
};
function hydrateConfigArrays(config) {
const defaultAddons = defaultSiteConfig.addons || [];
const deprecatedAddons = new Set(["Outdoor seating plan", "Table rentals", "Chair rentals"]);
const addonAliases = {
"Setup time": "Setup Time & Extra Hours",
"Photo session access": "Photo Session Access",
"Vendor walkthrough": "Vendor Walkthrough",
"Linens or table settings": "Table linens",
"Catering introductions": "Catering introduction",
"Music or DJ introductions": "DJ introduction"
};
config.addons = (config.addons || []).map((addon) => {
const rawValue = addon.value || addon.label || "";
if (deprecatedAddons.has(rawValue)) return null;
const migratedValue = addonAliases[rawValue];
const normalizedValue = migratedValue || rawValue;
const fallback = defaultAddons.find((item) => (item.value || item.label) === normalizedValue) || {};
const oldDefaultLabel = addon.label === rawValue || Object.prototype.hasOwnProperty.call(addonAliases, addon.label || "");
return {
...fallback,
...addon,
...(migratedValue ? {
priceLow: fallback.priceLow,
priceHigh: fallback.priceHigh,
priceUnit: fallback.priceUnit
} : {}),
value: normalizedValue,
label: oldDefaultLabel ? (fallback.label || normalizedValue) : addon.label
};
}).filter(Boolean);
const officialPackages = defaultSiteConfig.packages || [];
config.packages = (config.packages || []).map((pkg) => {
const official = officialPackages.find((item) => item.name === pkg.name);
if (!official) return pkg;
const legacyText = !Array.isArray(pkg.included) || String(pkg.includes || "").includes(";") || String(pkg.description || "").length < 170;
const oldPricingNote = !pkg.investmentNote || /Ask about/i.test(String(pkg.investmentNote || ""));
const oldPackagePrice =
(pkg.name === "The Grange Gathering" && Number(pkg.priceLow) === 2500 && Number(pkg.priceHigh) === 2800) ||
(pkg.name === "The Going to the Grange Station" && Number(pkg.priceLow) === 3200 && Number(pkg.priceHigh) === 3500) ||
(pkg.name === "Simple & Sweet" && Number(pkg.priceLow) === 1500 && Number(pkg.priceHigh) === 1800);
if (!legacyText) {
return {
...official,
...pkg,
...(oldPackagePrice ? { priceLow: official.priceLow, priceHigh: official.priceHigh } : {}),
investmentNote: oldPricingNote ? official.investmentNote : pkg.investmentNote
};
}
return {
...pkg,
investmentNote: official.investmentNote,
timeBlock: official.timeBlock,
description: official.description,
included: official.included,
includes: official.includes,
blueprint: official.blueprint
};
});
return config;
}
function mergeConfig(saved, defaults = defaultSiteConfig) {
if (!saved || typeof saved !== "object") return hydrateConfigArrays(JSON.parse(JSON.stringify(defaults)));
const merged = JSON.parse(JSON.stringify(defaults));
Object.keys(saved).forEach((key) => {
if (Array.isArray(saved[key])) {
merged[key] = saved[key];
} else if (saved[key] && typeof saved[key] === "object") {
merged[key] = { ...(merged[key] || {}), ...saved[key] };
} else {
merged[key] = saved[key];
}
});
return hydrateConfigArrays(merged);
}
function getSiteConfig() {
return mergeConfig(JSON.parse(localStorage.getItem(siteConfigStorageKey) || "null"));
}
function saveSiteConfig(config) {
localStorage.setItem(siteConfigStorageKey, JSON.stringify(config));
}
function getAvailabilityBlocks() {
return JSON.parse(localStorage.getItem(availabilityBlocksStorageKey) || "[]");
}
function saveAvailabilityBlocks(blocks) {
localStorage.setItem(availabilityBlocksStorageKey, JSON.stringify(blocks));
}
function activeGalleryPhotos() {
return getSiteConfig().gallery.filter((photo) => photo.enabled !== false);
}