Files
theoldfitz/index.php
T
David DyerandClaude Sonnet 5 f1bbf59548 Add online menu management, modernized and hardened
Adds a public menu page (menu.php) and an admin CRUD interface
(admin/menu.php + admin/menu.js) backed by new menu_categories and
menu_items tables, replacing the "menu lives on Facebook" placeholder
on the homepage.

The admin JS/PHP came out of an AI-assisted pass that used outdated
JS (var, .then() chains, string-built HTML) and had some rough edges
security-wise, so this also:

- Rewrites the admin JS to modern ES (const/let, async/await,
  template literals, dataset API) and splits it out of admin/menu.php
  into admin/menu.js for proper separation of concerns
- Adds declare(strict_types=1) and PHP 8 match-based action dispatch
  in place of an if-chain
- Validates category_id/item_id/category_id server-side before use,
  so a bad ID returns a clean JSON error instead of an uncaught
  PDOException or a null item breaking the client
- Rejects non-string POST fields instead of crashing trim() on them
- Replaces the category-save handler's full-page location.reload()
  with in-place DOM updates (panel insert/update, resort by
  sort_order, keep the item modal's category dropdown in sync), so
  every admin action is now AJAX with no reload
- Sets data-name/data-desc via dataset assignment rather than string-
  interpolating them into an HTML attribute, closing a stored-XSS
  path through the category name/description fields

Removes seed-menu.php, a leftover stub with no working code left in
it after the AI's one-time seeding run.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-30 21:35:22 -04:00

298 lines
14 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
require __DIR__ . '/config.php';
require __DIR__ . '/inc/facebook-stats.php';
require __DIR__ . '/inc/announcements.php';
$fbStats = fritz_facebook_stats();
$activeAnnouncements = get_active_announcements();
$siteUrl = rtrim(SITE_URL, '/');
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>The Old Fitz Public House</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="styles.css">
<link href="https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght@0,9..144,300;0,9..144,400;0,9..144,500;0,9..144,600;0,9..144,700;1,9..144,400;1,9..144,500&family=Karla:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500&display=swap" rel="stylesheet">
<meta name="description" content="The Old Fitz Public House — a traditional Irish pub in Marion, Indiana. Open Thursday through Saturday, 4–10pm. Family friendly, no reservations.">
<link rel="canonical" href="https://theoldfitz.daviddyer.me">
<meta name="color-scheme" content="light dark">
<!-- Social sharing (Open Graph / Twitter Card) -->
<meta property="og:type" content="website">
<meta property="og:site_name" content="The Old Fitz Public House">
<meta property="og:title" content="The Old Fitz Public House | Traditional Irish Pub in Marion, Indiana">
<meta property="og:description" content="A traditional Irish pub in Marion, Indiana. Open Thursday through Saturday, 4–10pm. Family friendly, no reservations.">
<meta property="og:url" content="<?= $siteUrl ?>/">
<meta property="og:image" content="<?= $siteUrl ?>/assets/og-image.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:image:alt" content="The Old Fitz Public House">
<meta property="og:locale" content="en_US">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="The Old Fitz Public House | Traditional Irish Pub in Marion, Indiana">
<meta name="twitter:description" content="A traditional Irish pub in Marion, Indiana. Open Thursday through Saturday, 4–10pm. Family friendly, no reservations.">
<meta name="twitter:image" content="<?= $siteUrl ?>/assets/og-image.png">
</head>
<body>
<a class="skip-link" href="#main">Skip to content</a>
<header class="site">
<div class="container nav-inner">
<a class="brand" href="./">
<img class="knot" src="./assets/knot.png" alt="">
<span>THE OLD FITZ</span>
</a>
<nav class="links" aria-label="Primary">
<a href="#about">About</a>
<a href="#visit">Hours &amp; Visit</a>
<a href="#music">Live Music</a>
<a href="menu.php">Menu</a>
<a href="#contact">Contact</a>
</nav>
<a class="nav-cta" href="https://www.google.com/maps/search/?api=1&amp;query=100+N+Washington+St+Marion+IN" target="_blank" rel="noopener">Get Directions</a>
</div>
</header>
<?php
$bannerAnnouncements = array_filter($activeAnnouncements, function ($a) {
return !empty($a['show_banner']);
});
?>
<?php if (!empty($bannerAnnouncements)): ?>
<?php foreach ($bannerAnnouncements as $banner): ?>
<div class="announcement-banner banner-<?= htmlspecialchars($banner['type']) ?>" role="region" aria-label="Important Announcement">
<div class="container announcement-inner">
<span class="announcement-tag"><?= htmlspecialchars($banner['headline']) ?></span>
<span class="announcement-sep" aria-hidden="true">·</span>
<span class="announcement-text"><?= htmlspecialchars($banner['message']) ?></span>
</div>
</div>
<?php endforeach; ?>
<?php endif; ?>
<main id="main">
<section class="hero">
<div class="hero-media" aria-hidden="true">
<div class="hero-scrim"></div>
</div>
<div class="container hero-inner">
<h1 class="hero-brand">
<img class="hero-logo" src="./assets/hero-logo.png" alt="The Old Fitz Public House">
</h1>
<p class="eyebrow">Marion, Indiana</p>
<!-- <h1>The Old Fitz</h1> -->
<!-- <p class="sub">Public House</p> -->
<div class="tagline-row">
<span>Traditional Irish Pub</span><span>Family Friendly</span><span>No Reservations</span>
</div>
<div class="hero-ctas">
<a class="btn btn-primary" href="https://www.google.com/maps/search/?api=1&query=100+N+Washington+St+Marion+IN" target="_blank" rel="noopener">Get Directions</a>
<a class="btn btn-outline" href="mailto:info@theoldfitzpub.com">Say Hello</a>
</div>
</div>
</section>
<section id="about">
<div class="container">
<div class="about-grid">
<div class="reveal">
<p class="eyebrow">About the Pub</p>
<h2>A proper Irish pub, right on Washington Street.</h2>
<p class="lede">The Old Fitz Public House pours a traditional Irish pub experience in the middle of Marion — no pretense, no reservations, just a good pint and a warm room. Walk in Thursday through Saturday evening, grab a seat at the bar or a table for the family, and settle in.</p>
<p class="lede">The kitchen runs until 9, the bar stays open later for snacks, and regulars and first-timers get treated the same.</p>
</div>
<div class="stat-card reveal">
<span class="eyebrow">As the Regulars See It</span>
<div class="stat-big"><?= (int) $fbStats['recommend_pct'] ?>%</div>
<p class="stat-label">recommend The Old Fitz</p>
<p class="stat-source">Source: Facebook reviews (<?= (int) $fbStats['review_count'] ?>)</p>
<div class="stat-row">
<div class="stat-big"><?= number_format((int) $fbStats['followers']) ?>+</div>
<p class="stat-label">people following along on Facebook</p>
<p class="stat-source">Source: Facebook followers</p>
</div>
</div>
</div>
</div>
</section>
<section id="visit" class="visit">
<div class="container">
<div class="section-head reveal">
<p class="eyebrow">Hours &amp; Visit</p>
<h2>Three nights a week, doors open.</h2>
</div>
<div class="visit-grid">
<div class="card reveal">
<h3>On Tap Thu–Sat</h3>
<?php
$hoursAnnouncements = array_filter($activeAnnouncements, function ($a) {
return !empty($a['show_in_hours']);
});
?>
<?php foreach ($hoursAnnouncements as $hoursNotice): ?>
<div class="hours-alert alert-<?= htmlspecialchars($hoursNotice['type']) ?>">
<strong><?= htmlspecialchars($hoursNotice['headline']) ?>:</strong>
<span><?= htmlspecialchars($hoursNotice['message']) ?></span>
</div>
<?php endforeach; ?>
<dl class="hours-list">
<div class="hours-row">
<dt>Thursday</dt>
<dd>4:00 – 10:00 PM</dd>
</div>
<div class="hours-row">
<dt>Friday</dt>
<dd>4:00 – 10:00 PM</dd>
</div>
<div class="hours-row">
<dt>Saturday</dt>
<dd>4:00 – 10:00 PM</dd>
</div>
<div class="hours-row">
<dt>Sun – Wed</dt>
<dd>Closed</dd>
</div>
</dl>
<p class="note"><strong>Kitchen closes at 9</strong> — bar snacks stay out later. Holiday hours may vary; check our Facebook page for the latest.</p>
</div>
<div class="card find-us reveal" id="contact">
<svg class="pin" viewBox="0 0 24 24" fill="none" aria-hidden="true">
<path d="M12 2C7.86 2 4.5 5.36 4.5 9.5c0 5.5 6.2 11.16 7.06 11.92a.7.7 0 0 0 .88 0C13.3 20.66 19.5 15 19.5 9.5 19.5 5.36 16.14 2 12 2Z" stroke="var(--gold)" stroke-width="1.4" />
<circle cx="12" cy="9.5" r="2.6" stroke="var(--gold)" stroke-width="1.4" />
</svg>
<h3>Find Us</h3>
<address>
100 N Washington Street<br>
Marion, Indiana
</address>
<div class="contact-list">
<a href="https://www.google.com/maps/search/?api=1&query=100+N+Washington+St+Marion+IN" target="_blank" rel="noopener">Get Directions →</a>
<a href="mailto:info@theoldfitzpub.com">info@theoldfitzpub.com</a>
</div>
<div class="social-row">
<a href="https://www.instagram.com/theoldfitzpub/?hl=en" target="_blank" rel="noopener" aria-label="The Old Fitz on Instagram">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6">
<rect x="3" y="3" width="18" height="18" rx="5" />
<circle cx="12" cy="12" r="4.2" />
<circle cx="17.2" cy="6.8" r="1" />
</svg>
</a>
<a href="https://www.facebook.com/profile.php?id=100086635646712" target="_blank" rel="noopener" aria-label="The Old Fitz on Facebook">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6">
<path d="M15 4h-2.2C10.7 4 9.5 5.3 9.5 7.3V10H7v3.2h2.5V21h3.3v-7.8h2.6l.4-3.2h-3V7.6c0-.8.4-1.3 1.4-1.3H15V4Z" />
</svg>
</a>
</div>
</div>
</div>
</div>
</section>
<section id="music" class="music">
<div class="container">
<div class="rule-row reveal"><span class="line"></span><img class="knot" src="./assets/knot.png" alt=""><span class="line"></span></div>
<div class="section-head reveal">
<p class="eyebrow">Live Music</p>
<h2>Some nights, there's music.</h2>
</div>
<p class="body reveal">The Old Fitz brings in local musicians for live sets on select evenings — recent nights have featured artists like Casey Morris. There's no fixed weekly lineup here, so the surest way to catch a show is to follow along on Facebook or Instagram, where new dates get posted first.</p>
<div class="hero-ctas reveal">
<a class="btn btn-outline" href="https://www.facebook.com/profile.php?id=100086635646712" target="_blank" rel="noopener">Follow on Facebook</a>
<a class="btn btn-outline" href="https://www.instagram.com/theoldfitzpub/?hl=en" target="_blank" rel="noopener">Follow on Instagram</a>
</div>
</div>
</section>
<section id="menu" class="menu-band">
<div class="container">
<div class="rule-row reveal"><span class="line"></span><img class="knot" src="./assets/knot.png" alt=""><span class="line"></span></div>
<div class="section-head reveal">
<p class="eyebrow">The Menu</p>
<h2>Pub food and a full bar, Thursday through Saturday.</h2>
</div>
<p class="body reveal">We serve traditional Irish staples, shareable plates, and hearty comfort food until 9 PM, with bar snacks staying out later. Explore our full kitchen menu or check Facebook for weekend chalkboard features.</p>
<div class="hero-ctas reveal">
<a class="btn btn-primary" href="menu.php">Explore Full Menu →</a>
<a class="btn btn-outline" href="https://www.facebook.com/profile.php?id=100086635646712" target="_blank" rel="noopener">Daily Specials on Facebook</a>
</div>
</div>
</section>
</main>
<footer>
<div class="container">
<div class="footer-grid">
<div>
<a class="footer-brand" href="#main">
<img class="knot" src="./assets/knot.png" alt="">
<span>THE OLD FITZ PUBLIC HOUSE</span>
</a>
<address>
100 N Washington Street<br>
Marion, Indiana
</address>
</div>
<div>
<p class="col-title">Hours</p>
<div class="hours-mini">
<span>Thu — Sat · 4:00–10:00 PM</span>
<span>Kitchen closes at 9 PM</span>
<span>Sun — Wed · Closed</span>
</div>
</div>
<div>
<p class="col-title">Get in Touch</p>
<a class="email" href="mailto:info@theoldfitzpub.com">info@theoldfitzpub.com</a>
<div class="social-row">
<a href="https://www.instagram.com/theoldfitzpub/?hl=en" target="_blank" rel="noopener" aria-label="Instagram">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6">
<rect x="3" y="3" width="18" height="18" rx="5" />
<circle cx="12" cy="12" r="4.2" />
<circle cx="17.2" cy="6.8" r="1" />
</svg>
</a>
<a href="https://www.facebook.com/profile.php?id=100086635646712" target="_blank" rel="noopener" aria-label="Facebook">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6">
<path d="M15 4h-2.2C10.7 4 9.5 5.3 9.5 7.3V10H7v3.2h2.5V21h3.3v-7.8h2.6l.4-3.2h-3V7.6c0-.8.4-1.3 1.4-1.3H15V4Z" />
</svg>
</a>
</div>
</div>
</div>
<div class="footer-bottom">
<span>© 2026 The Old Fitz Public House</span>
<span>A neighborhood pub in Marion, Indiana</span>
</div>
</div>
</footer>
<script>
(function() {
if (window.matchMedia('(prefers-reduced-motion: reduce)').matches) return;
var els = document.querySelectorAll('.reveal');
if (!('IntersectionObserver' in window)) { els.forEach(function(e) { e.classList.add('is-visible'); }); return; }
var io = new IntersectionObserver(function(entries) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
entry.target.classList.add('is-visible');
io.unobserve(entry.target);
}
});
}, { threshold: 0.15 });
els.forEach(function(e) { io.observe(e); });
})();
</script>
</body>
</html>