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>
298 lines
14 KiB
PHP
298 lines
14 KiB
PHP
<?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 & 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&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 & 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>
|