- Implemented the Lakeside Orders demo rebrand:
New licensed lake, picnic, dining, server, burger, and food photography. Rebuilt homepage gallery, logo, colors, copy, menu, specials, and exports. Added dashboard-configurable branding in [settings.php (line 18)](/Users/tyemeclifford/Documents/GH/fatbottomgrille/views/admin/settings.php:18). Added a public attribution page and full [image credits](/Users/tyemeclifford/Documents/GH/fatbottomgrille/public/assets/images/CREDITS.md). Migrated existing SQLite menu data and admin email to admin@lakesideorders.test. Verified 51 PHP files, JSON/JavaScript, storefront pages, database migration, admin settings, and menu PDF. All passed.
This commit is contained in:
@@ -7,7 +7,7 @@
|
||||
<div class="admin-panel-heading"><div><span class="eyebrow">Send an update</span><h2>New Newsletter</h2></div></div>
|
||||
<form class="form-stack" action="<?= e(url('/admin/newsletters/send')) ?>" method="post">
|
||||
<?= csrf_field() ?>
|
||||
<label>Subject line<input type="text" name="subject" maxlength="140" required placeholder="This weekend at Fat Bottom Grille"></label>
|
||||
<label>Subject line<input type="text" name="subject" maxlength="140" required placeholder="This weekend at <?= e($config->get('business.name')) ?>"></label>
|
||||
<label>Message<textarea name="content" rows="12" required placeholder="Share a new special, schedule update, or note from the kitchen..."></textarea></label>
|
||||
<div class="notice">Every email includes an unsubscribe link. Users can also opt out from My Account.</div>
|
||||
<button class="button button-large button-block" type="submit" data-confirm="Send this newsletter to every opted-in user?">Send to <?= (int) $recipientCount ?> Subscribers</button>
|
||||
|
||||
@@ -15,6 +15,27 @@
|
||||
<label class="field-wide">Announcement bar<input type="text" name="business[announcement]" value="<?= e($config->get('business.announcement')) ?>"></label>
|
||||
</div>
|
||||
</section>
|
||||
<section class="admin-panel">
|
||||
<div class="admin-panel-heading"><div><span class="eyebrow">Storefront presentation</span><h2>Branding & Homepage</h2></div></div>
|
||||
<div class="notice">Edit the demo message and active image paths here. Image files live in <code>public/assets/images</code>.</div>
|
||||
<div class="form-grid">
|
||||
<label>Location label<input type="text" name="branding[location_label]" value="<?= e($config->get('branding.location_label')) ?>"></label>
|
||||
<label>Hero eyebrow<input type="text" name="branding[hero_eyebrow]" value="<?= e($config->get('branding.hero_eyebrow')) ?>"></label>
|
||||
<label>Hero heading<input type="text" name="branding[hero_heading]" value="<?= e($config->get('branding.hero_heading')) ?>"></label>
|
||||
<label>Hero emphasized line<input type="text" name="branding[hero_emphasis]" value="<?= e($config->get('branding.hero_emphasis')) ?>"></label>
|
||||
<label class="field-wide">Search description<textarea name="branding[meta_description]" rows="2"><?= e($config->get('branding.meta_description')) ?></textarea></label>
|
||||
<label class="field-wide">Hero introduction<textarea name="branding[hero_intro]" rows="3"><?= e($config->get('branding.hero_intro')) ?></textarea></label>
|
||||
<label>Hero food image<input type="text" name="branding[hero_image]" value="<?= e($config->get('branding.hero_image')) ?>"></label>
|
||||
<label>Picnic gallery image<input type="text" name="branding[gallery_picnic_image]" value="<?= e($config->get('branding.gallery_picnic_image')) ?>"></label>
|
||||
<label>Patio gallery image<input type="text" name="branding[gallery_patio_image]" value="<?= e($config->get('branding.gallery_patio_image')) ?>"></label>
|
||||
<label>Service gallery image<input type="text" name="branding[gallery_service_image]" value="<?= e($config->get('branding.gallery_service_image')) ?>"></label>
|
||||
<label>Story image<input type="text" name="branding[story_image]" value="<?= e($config->get('branding.story_image')) ?>"></label>
|
||||
<label>Story eyebrow<input type="text" name="branding[story_eyebrow]" value="<?= e($config->get('branding.story_eyebrow')) ?>"></label>
|
||||
<label>Story heading<input type="text" name="branding[story_heading]" value="<?= e($config->get('branding.story_heading')) ?>"></label>
|
||||
<label class="field-wide">Story text<textarea name="branding[story_text]" rows="3"><?= e($config->get('branding.story_text')) ?></textarea></label>
|
||||
<label class="field-wide">Footer tagline<input type="text" name="branding[footer_tagline]" value="<?= e($config->get('branding.footer_tagline')) ?>"></label>
|
||||
</div>
|
||||
</section>
|
||||
<section class="admin-panel">
|
||||
<div class="admin-panel-heading"><div><span class="eyebrow">Kitchen controls</span><h2>Online Ordering</h2></div></div>
|
||||
<div class="settings-row">
|
||||
|
||||
@@ -30,13 +30,13 @@
|
||||
<input type="text" name="street_address" required autocomplete="street-address" value="<?= e($old['street_address'] ?? '') ?>">
|
||||
</label>
|
||||
<label>City
|
||||
<input type="text" name="city" required autocomplete="address-level2" value="<?= e($old['city'] ?? 'Keyser') ?>">
|
||||
<input type="text" name="city" required autocomplete="address-level2" value="<?= e($old['city'] ?? $config->get('business.city')) ?>">
|
||||
</label>
|
||||
<label>State
|
||||
<input type="text" name="state" required maxlength="2" autocomplete="address-level1" value="<?= e($old['state'] ?? 'WV') ?>">
|
||||
<input type="text" name="state" required maxlength="2" autocomplete="address-level1" value="<?= e($old['state'] ?? $config->get('business.state')) ?>">
|
||||
</label>
|
||||
<label>ZIP code
|
||||
<input type="text" name="postal_code" required autocomplete="postal-code" value="<?= e($old['postal_code'] ?? '26726') ?>">
|
||||
<input type="text" name="postal_code" required autocomplete="postal-code" value="<?= e($old['postal_code'] ?? $config->get('business.postal_code')) ?>">
|
||||
</label>
|
||||
</div>
|
||||
<div class="form-grid">
|
||||
@@ -53,7 +53,7 @@
|
||||
<label>Quick check: what is <?= (int) $captcha[0] ?> + <?= (int) $captcha[1] ?>?
|
||||
<input type="number" name="captcha" required inputmode="numeric" autocomplete="off">
|
||||
</label>
|
||||
<div class="notice">Creating an account opts you into occasional Fat Bottom Grille news. You can opt out from any email or My Account.</div>
|
||||
<div class="notice">Creating an account opts you into occasional <?= e($config->get('business.name')) ?> news. You can opt out from any email or My Account.</div>
|
||||
<button class="button button-large button-block" type="submit">Create My Account</button>
|
||||
<p class="auth-switch">Already have an account? <a href="<?= e(url('/login')) ?>">Sign in</a></p>
|
||||
</form>
|
||||
|
||||
+6
-6
@@ -2,7 +2,7 @@
|
||||
|
||||
use FatBottom\Core\View;
|
||||
|
||||
$businessName = (string) $config->get('business.name', 'Fat Bottom Grille');
|
||||
$businessName = (string) $config->get('business.name', 'Lakeside Orders');
|
||||
$isAdmin = isset($adminPage);
|
||||
?>
|
||||
<!doctype html>
|
||||
@@ -11,7 +11,7 @@ $isAdmin = isset($adminPage);
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="theme-color" content="#09131d">
|
||||
<meta name="description" content="Order burgers, burritos, dinner plates, sides, and drinks online from Fat Bottom Grille in Keyser, West Virginia.">
|
||||
<meta name="description" content="<?= e($config->get('branding.meta_description')) ?>">
|
||||
<title><?= e($title ?? $businessName) ?> | <?= e($businessName) ?></title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
@@ -59,11 +59,11 @@ $isAdmin = isset($adminPage);
|
||||
<div class="container nav-wrap">
|
||||
<a class="brand" href="<?= e(url('/')) ?>" aria-label="<?= e($businessName) ?> home">
|
||||
<span class="brand-mark">
|
||||
<img src="<?= e(asset('assets/images/fat-bottom-grille-logo.jpg')) ?>" alt="">
|
||||
<img src="<?= e(asset('assets/images/lakeside-orders-logo.svg')) ?>" alt="">
|
||||
</span>
|
||||
<span class="brand-copy">
|
||||
<strong><?= e($businessName) ?></strong>
|
||||
<small>Keyser, West Virginia</small>
|
||||
<small><?= e($config->get('branding.location_label')) ?></small>
|
||||
</span>
|
||||
</a>
|
||||
<button class="nav-toggle" type="button" aria-expanded="false" aria-controls="site-nav">
|
||||
@@ -97,7 +97,7 @@ $isAdmin = isset($adminPage);
|
||||
<div class="container footer-grid">
|
||||
<div>
|
||||
<div class="footer-brand"><?= e($businessName) ?></div>
|
||||
<p>Good food, generous portions, and a seat at the table in Keyser.</p>
|
||||
<p><?= e($config->get('branding.footer_tagline')) ?></p>
|
||||
</div>
|
||||
<div>
|
||||
<h2>Visit</h2>
|
||||
@@ -128,7 +128,7 @@ $isAdmin = isset($adminPage);
|
||||
</div>
|
||||
<div class="container footer-bottom">
|
||||
<span>© <?= date('Y') ?> <?= e($businessName) ?></span>
|
||||
<span>410 W Piedmont St, Keyser, WV</span>
|
||||
<a href="<?= e(url('/credits')) ?>">Image credits</a>
|
||||
</div>
|
||||
</footer>
|
||||
<?php endif; ?>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<aside class="admin-sidebar">
|
||||
<a class="admin-brand" href="<?= e(url('/admin')) ?>">
|
||||
<span class="brand-mark">
|
||||
<img src="<?= e(asset('assets/images/fat-bottom-grille-logo.jpg')) ?>" alt="">
|
||||
<img src="<?= e(asset('assets/images/lakeside-orders-logo.svg')) ?>" alt="">
|
||||
</span>
|
||||
<span>
|
||||
<strong><?= e($config->get('business.name')) ?></strong>
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
<div class="summary-total"><dt>Total</dt><dd><?= money($totals['total_cents']) ?></dd></div>
|
||||
</dl>
|
||||
<a class="button button-block button-large" href="<?= e(url('/checkout')) ?>">Continue to Checkout</a>
|
||||
<p class="summary-note">Pickup at 410 W Piedmont St, Keyser.</p>
|
||||
<p class="summary-note">Pickup at <?= e($config->get('business.street')) ?>, <?= e($config->get('business.city')) ?>.</p>
|
||||
</aside>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
$credits = [
|
||||
['Sunset at Odell Lake', 'Bonnie Moreland', 'Public domain', 'https://commons.wikimedia.org/wiki/File:Sunset_Odell_Lake,_Oregon_-_Flickr_-_Bonnie_Moreland_(free_images).jpg'],
|
||||
['Picnic at Valasht Lake', 'Gholamreza Shamsnetari', 'CC BY 4.0', 'https://commons.wikimedia.org/wiki/File:Sizdah_Be-Dar_2018,_Valasht_Lake_(13970114000329636583522676851541_54966).jpg'],
|
||||
['People eating outside a restaurant', 'Elvert Barnes', 'CC BY-SA 2.0', 'https://commons.wikimedia.org/wiki/File:People_eating_outside_restaurant_Baltimore.jpg'],
|
||||
['People dining at Zen Garden', 'Ibrahim Achiri', 'CC BY-SA 4.0', 'https://commons.wikimedia.org/wiki/File:People_dining_and_socializing_at_Zen_Garden.jpg'],
|
||||
['Hamburger with fries', 'Daderot', 'CC0', 'https://commons.wikimedia.org/wiki/File:Hamburger_with_blue_cheese,_guacamole,_and_other_toppings,_plus_French_fries_-_Massachusetts.jpg'],
|
||||
['Chicken wrap with spinach', 'Tomwsulcer', 'CC0', 'https://commons.wikimedia.org/wiki/File:Lunch_chicken_wrap_with_spinach_and_sauce.JPG'],
|
||||
['Falafel bowl', 'Andy Li', 'CC0', 'https://commons.wikimedia.org/wiki/File:Falafel_Super_Bowl_Salad_-_Leon_2025-10-27.jpg'],
|
||||
['Chicken legs', 'Vyacheslav Argenberg', 'CC BY 4.0', 'https://commons.wikimedia.org/wiki/File:Fried_chicken_legs,_Rostov-on-Don,_Russia.jpg'],
|
||||
['Iced tea', 'Renee Comet', 'Public domain', 'https://commons.wikimedia.org/wiki/File:Iced_tea.jpg'],
|
||||
['French fries', 'Thriving Vegetarian', 'CC BY 2.0', 'https://commons.wikimedia.org/wiki/File:Perfect_French_Fries_-_11457817933.jpg'],
|
||||
];
|
||||
?>
|
||||
<section class="page-hero page-hero-compact">
|
||||
<div class="container">
|
||||
<span class="eyebrow">Open media</span>
|
||||
<h1>Image Credits</h1>
|
||||
<p>The Lakeside Orders demo uses public-domain and Creative Commons photography.</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="section">
|
||||
<div class="container narrow-content">
|
||||
<div class="credits-list">
|
||||
<?php foreach ($credits as [$title, $artist, $license, $source]): ?>
|
||||
<article>
|
||||
<div>
|
||||
<h2><?= e($title) ?></h2>
|
||||
<p><?= e($artist) ?> · <?= e($license) ?></p>
|
||||
</div>
|
||||
<a class="text-link" href="<?= e($source) ?>" target="_blank" rel="license noopener">View source</a>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<p class="credits-note">Photography is displayed with CSS crops for the responsive layout. No photographer or licensor endorses this demo.</p>
|
||||
</div>
|
||||
</section>
|
||||
+44
-18
@@ -2,9 +2,9 @@
|
||||
<div class="hero-texture"></div>
|
||||
<div class="container hero-grid">
|
||||
<div class="hero-copy">
|
||||
<span class="eyebrow">Keyser made. Come hungry.</span>
|
||||
<h1>Big flavor.<br><em>No shortcuts.</em></h1>
|
||||
<p>Stacked burgers, loaded burritos, and dinner plates that eat like Sunday supper. Order ahead and we will have it hot.</p>
|
||||
<span class="eyebrow"><?= e($config->get('branding.hero_eyebrow')) ?></span>
|
||||
<h1><?= e($config->get('branding.hero_heading')) ?><br><em><?= e($config->get('branding.hero_emphasis')) ?></em></h1>
|
||||
<p><?= e($config->get('branding.hero_intro')) ?></p>
|
||||
<div class="hero-actions">
|
||||
<a class="button button-large" href="<?= e(url('/menu')) ?>">Start Your Order</a>
|
||||
<?php if ($config->get('business.phone')): ?>
|
||||
@@ -20,15 +20,15 @@
|
||||
</div>
|
||||
<div class="hero-plate">
|
||||
<div class="hero-food-photo">
|
||||
<img src="<?= e(asset('assets/images/chicken-sandwich-fries.jpg')) ?>" alt="Chicken sandwich and hand-cut fries from Fat Bottom Grille">
|
||||
<img src="<?= e(asset((string) $config->get('branding.hero_image'))) ?>" alt="Burger and fries ready for a lakeside meal">
|
||||
<div class="hero-photo-caption">
|
||||
<span>Made in Keyser</span>
|
||||
<strong>Hot. Fresh. Generous.</strong>
|
||||
<span>From grill to shoreline</span>
|
||||
<strong>Fresh pickup. Easy afternoons.</strong>
|
||||
</div>
|
||||
</div>
|
||||
<div class="hero-stamp" aria-hidden="true">
|
||||
<strong>410</strong>
|
||||
<span>W Piedmont</span>
|
||||
<strong>DEMO</strong>
|
||||
<span>Lakeside pickup</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -40,7 +40,7 @@
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<span class="eyebrow">Happening now</span>
|
||||
<h2>Today’s Specials</h2>
|
||||
<h2>Dockside Specials</h2>
|
||||
</div>
|
||||
<a class="text-link" href="<?= e(url('/menu')) ?>">See the full menu</a>
|
||||
</div>
|
||||
@@ -75,10 +75,10 @@
|
||||
<div class="container">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<span class="eyebrow">Built to satisfy</span>
|
||||
<h2>Local Favorites</h2>
|
||||
<span class="eyebrow">Packed for the day</span>
|
||||
<h2>Shoreline Favorites</h2>
|
||||
</div>
|
||||
<p>These are the orders that keep showing up at the counter.</p>
|
||||
<p>Easygoing food for docks, picnic blankets, and patio tables.</p>
|
||||
</div>
|
||||
<div class="menu-grid">
|
||||
<?php foreach ($featured as $item): ?>
|
||||
@@ -88,6 +88,32 @@
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="lakeside-gallery section">
|
||||
<div class="container">
|
||||
<div class="section-heading">
|
||||
<div>
|
||||
<span class="eyebrow">Stay awhile</span>
|
||||
<h2>Food fits the view</h2>
|
||||
</div>
|
||||
<p>Grab a picnic, settle into a sunny table, or let the evening stretch out under the lights.</p>
|
||||
</div>
|
||||
<div class="experience-grid">
|
||||
<figure class="experience-card experience-card-wide">
|
||||
<img src="<?= e(asset((string) $config->get('branding.gallery_picnic_image'))) ?>" alt="People enjoying a picnic beside a lake">
|
||||
<figcaption><span>Take it outside</span><strong>Picnic-ready</strong></figcaption>
|
||||
</figure>
|
||||
<figure class="experience-card">
|
||||
<img src="<?= e(asset((string) $config->get('branding.gallery_patio_image'))) ?>" alt="Guests sitting and eating at outdoor restaurant tables">
|
||||
<figcaption><span>Meet by the water</span><strong>Tables in the sun</strong></figcaption>
|
||||
</figure>
|
||||
<figure class="experience-card">
|
||||
<img src="<?= e(asset((string) $config->get('branding.gallery_service_image'))) ?>" alt="A lively restaurant with diners and servers moving among the tables">
|
||||
<figcaption><span>Settle in</span><strong>Friendly table service</strong></figcaption>
|
||||
</figure>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="category-band">
|
||||
<div class="container">
|
||||
<span class="eyebrow">Pick your direction</span>
|
||||
@@ -104,14 +130,14 @@
|
||||
|
||||
<section class="story-section section">
|
||||
<div class="container story-grid">
|
||||
<div class="story-art" aria-hidden="true">
|
||||
<span class="story-number">26726</span>
|
||||
<div class="mountain-lines"></div>
|
||||
<div class="story-art">
|
||||
<img src="<?= e(asset((string) $config->get('branding.story_image'))) ?>" alt="Sunset over a calm lake and dock">
|
||||
<span class="story-number">LAKE</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="eyebrow">Proudly from Keyser</span>
|
||||
<h2>Food that shows up hungry.</h2>
|
||||
<p>Fat Bottom Grille is the kind of place where the portions are honest and nobody leaves wondering what is for dinner. Find us at 410 W Piedmont Street, right here in Keyser.</p>
|
||||
<span class="eyebrow"><?= e($config->get('branding.story_eyebrow')) ?></span>
|
||||
<h2><?= e($config->get('branding.story_heading')) ?></h2>
|
||||
<p><?= e($config->get('branding.story_text')) ?></p>
|
||||
<a class="button button-outline" href="<?= e(url('/menu')) ?>">Order for Pickup</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<section class="page-hero">
|
||||
<div class="container page-hero-inner">
|
||||
<div>
|
||||
<span class="eyebrow">Hot, fresh, yours</span>
|
||||
<span class="eyebrow">From the grill to the shoreline</span>
|
||||
<h1>Order Online</h1>
|
||||
<p>Choose your favorites and we will get the kitchen moving.</p>
|
||||
<p>Choose a dockside favorite and we will get your lakeside pickup moving.</p>
|
||||
</div>
|
||||
<form class="menu-search" action="<?= e(url('/menu')) ?>" method="get">
|
||||
<label for="menu-query">Search the menu</label>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<p>Your order number is <strong><?= e($order['order_number']) ?></strong>. We sent a confirmation to <?= e($order['customer_email']) ?>.</p>
|
||||
<div class="confirmation-details">
|
||||
<div><span>Pickup</span><strong><?= e($order['pickup_time'] ?: 'About ' . $config->get('ordering.pickup_eta_minutes', 25) . ' minutes') ?></strong></div>
|
||||
<div><span>Location</span><strong>410 W Piedmont St</strong></div>
|
||||
<div><span>Location</span><strong><?= e($config->get('business.street')) ?></strong></div>
|
||||
<div><span>Total paid</span><strong><?= money($order['total_cents']) ?></strong></div>
|
||||
</div>
|
||||
<div class="confirmation-items">
|
||||
|
||||
Reference in New Issue
Block a user