- initial
This commit is contained in:
+510
@@ -0,0 +1,510 @@
|
||||
<?php
|
||||
/**
|
||||
* Keyser WV Tourism Site — Database Layer
|
||||
* SQLite via PDO; DB lives in /data/ (chmod 777)
|
||||
*/
|
||||
define('DATA_DIR', dirname(__DIR__).'/data');
|
||||
define('DB_FILE', DATA_DIR.'/keyser.db');
|
||||
|
||||
function db(): PDO {
|
||||
static $pdo = null;
|
||||
if ($pdo !== null) return $pdo;
|
||||
if (!is_dir(DATA_DIR)) mkdir(DATA_DIR, 0777, true);
|
||||
@chmod(DATA_DIR, 0777);
|
||||
$isNew = !file_exists(DB_FILE) || filesize(DB_FILE) === 0;
|
||||
$pdo = new PDO('sqlite:'.DB_FILE, null, null, [
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
||||
]);
|
||||
$pdo->exec("PRAGMA journal_mode=WAL; PRAGMA foreign_keys=ON; PRAGMA synchronous=NORMAL;");
|
||||
if ($isNew) { _schema($pdo); _seed($pdo); }
|
||||
// Always ensure the edit_requests table exists (for existing DBs)
|
||||
_ensureEditRequests($pdo);
|
||||
if (file_exists(DB_FILE)) @chmod(DB_FILE, 0666);
|
||||
return $pdo;
|
||||
}
|
||||
|
||||
/* ── Shorthand query helpers ────────────────────────────── */
|
||||
function qr(string $sql, array $p=[]): PDOStatement { $s=db()->prepare($sql); $s->execute($p); return $s; }
|
||||
function qall(string $sql, array $p=[]): array { return qr($sql,$p)->fetchAll(); }
|
||||
function qone(string $sql, array $p=[]): ?array { $r=qr($sql,$p)->fetch(); return $r?:null; }
|
||||
function qval(string $sql, array $p=[]): mixed { return qr($sql,$p)->fetchColumn(); }
|
||||
function qrun(string $sql, array $p=[]): int { $s=db()->prepare($sql); $s->execute($p); return (int)db()->lastInsertId(); }
|
||||
|
||||
/* ── Ensure edit requests table exists on old DBs ─── */
|
||||
function _ensureEditRequests(PDO $db): void {
|
||||
$db->exec("
|
||||
CREATE TABLE IF NOT EXISTS business_edit_requests (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
business_id INTEGER NOT NULL REFERENCES businesses(id) ON DELETE CASCADE,
|
||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
field TEXT NOT NULL,
|
||||
old_value TEXT NOT NULL DEFAULT '',
|
||||
new_value TEXT NOT NULL DEFAULT '',
|
||||
status TEXT NOT NULL DEFAULT 'pending',
|
||||
admin_notes TEXT NOT NULL DEFAULT '',
|
||||
created_at TEXT NOT NULL DEFAULT(datetime('now')),
|
||||
reviewed_at TEXT
|
||||
);
|
||||
");
|
||||
}
|
||||
|
||||
/* ══════════════════════════════════════════════════════
|
||||
SCHEMA
|
||||
══════════════════════════════════════════════════════ */
|
||||
function _schema(PDO $db): void {
|
||||
$db->exec("
|
||||
CREATE TABLE IF NOT EXISTS settings(
|
||||
key TEXT PRIMARY KEY, value TEXT NOT NULL DEFAULT ''
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS users(
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
username TEXT UNIQUE NOT NULL,
|
||||
email TEXT,
|
||||
password TEXT NOT NULL,
|
||||
is_admin INTEGER NOT NULL DEFAULT 0,
|
||||
is_active INTEGER NOT NULL DEFAULT 1,
|
||||
created_at TEXT NOT NULL DEFAULT(datetime('now')),
|
||||
last_login TEXT
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS categories(
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT UNIQUE NOT NULL,
|
||||
icon TEXT NOT NULL DEFAULT '🏢',
|
||||
sort_order INTEGER NOT NULL DEFAULT 0
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS businesses(
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
slug TEXT UNIQUE NOT NULL,
|
||||
category_id INTEGER REFERENCES categories(id),
|
||||
subcategory TEXT NOT NULL DEFAULT '',
|
||||
description TEXT NOT NULL DEFAULT '',
|
||||
address TEXT NOT NULL DEFAULT '',
|
||||
phone TEXT NOT NULL DEFAULT '',
|
||||
email TEXT NOT NULL DEFAULT '',
|
||||
website TEXT NOT NULL DEFAULT '',
|
||||
hours TEXT NOT NULL DEFAULT '{}',
|
||||
lat REAL NOT NULL DEFAULT 39.4364,
|
||||
lng REAL NOT NULL DEFAULT -78.9762,
|
||||
is_active INTEGER NOT NULL DEFAULT 1,
|
||||
is_featured INTEGER NOT NULL DEFAULT 0,
|
||||
created_at TEXT NOT NULL DEFAULT(datetime('now'))
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS business_owners(
|
||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
business_id INTEGER NOT NULL REFERENCES businesses(id) ON DELETE CASCADE,
|
||||
PRIMARY KEY(user_id,business_id)
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS business_edit_requests(
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
business_id INTEGER NOT NULL REFERENCES businesses(id) ON DELETE CASCADE,
|
||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
field TEXT NOT NULL,
|
||||
old_value TEXT NOT NULL DEFAULT '',
|
||||
new_value TEXT NOT NULL DEFAULT '',
|
||||
status TEXT NOT NULL DEFAULT 'pending',
|
||||
admin_notes TEXT NOT NULL DEFAULT '',
|
||||
created_at TEXT NOT NULL DEFAULT(datetime('now')),
|
||||
reviewed_at TEXT
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS reviews(
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
business_id INTEGER NOT NULL REFERENCES businesses(id) ON DELETE CASCADE,
|
||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
rating INTEGER NOT NULL CHECK(rating BETWEEN 1 AND 5),
|
||||
title TEXT NOT NULL DEFAULT '',
|
||||
body TEXT NOT NULL DEFAULT '',
|
||||
is_approved INTEGER NOT NULL DEFAULT 1,
|
||||
created_at TEXT NOT NULL DEFAULT(datetime('now'))
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS menu_sections(
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
business_id INTEGER NOT NULL REFERENCES businesses(id) ON DELETE CASCADE,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT NOT NULL DEFAULT '',
|
||||
sort_order INTEGER NOT NULL DEFAULT 0
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS menu_items(
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
section_id INTEGER NOT NULL REFERENCES menu_sections(id) ON DELETE CASCADE,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT NOT NULL DEFAULT '',
|
||||
price REAL NOT NULL DEFAULT 0,
|
||||
is_available INTEGER NOT NULL DEFAULT 1,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS alerts(
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
business_id INTEGER NOT NULL REFERENCES businesses(id) ON DELETE CASCADE,
|
||||
type TEXT NOT NULL DEFAULT 'info',
|
||||
title TEXT NOT NULL,
|
||||
body TEXT NOT NULL DEFAULT '',
|
||||
is_active INTEGER NOT NULL DEFAULT 1,
|
||||
expires_at TEXT,
|
||||
created_at TEXT NOT NULL DEFAULT(datetime('now'))
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS attractions(
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
name TEXT NOT NULL,
|
||||
category TEXT NOT NULL DEFAULT 'Sightseeing',
|
||||
description TEXT NOT NULL DEFAULT '',
|
||||
address TEXT NOT NULL DEFAULT '',
|
||||
phone TEXT NOT NULL DEFAULT '',
|
||||
website TEXT NOT NULL DEFAULT '',
|
||||
hours TEXT NOT NULL DEFAULT '',
|
||||
is_active INTEGER NOT NULL DEFAULT 1,
|
||||
sort_order INTEGER NOT NULL DEFAULT 0
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS events(
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
title TEXT NOT NULL,
|
||||
description TEXT NOT NULL DEFAULT '',
|
||||
venue TEXT NOT NULL DEFAULT '',
|
||||
address TEXT NOT NULL DEFAULT '',
|
||||
event_date TEXT NOT NULL,
|
||||
event_time TEXT NOT NULL DEFAULT '',
|
||||
end_date TEXT,
|
||||
end_time TEXT NOT NULL DEFAULT '',
|
||||
cost TEXT NOT NULL DEFAULT 'Free',
|
||||
website TEXT NOT NULL DEFAULT '',
|
||||
contact_name TEXT NOT NULL DEFAULT '',
|
||||
contact_email TEXT NOT NULL DEFAULT '',
|
||||
contact_phone TEXT NOT NULL DEFAULT '',
|
||||
submitted_by INTEGER REFERENCES users(id) ON DELETE SET NULL,
|
||||
status TEXT NOT NULL DEFAULT 'pending',
|
||||
is_featured INTEGER NOT NULL DEFAULT 0,
|
||||
created_at TEXT NOT NULL DEFAULT(datetime('now'))
|
||||
);
|
||||
CREATE TABLE IF NOT EXISTS reports(
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
business_id INTEGER NOT NULL REFERENCES businesses(id) ON DELETE CASCADE,
|
||||
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
||||
type TEXT NOT NULL DEFAULT 'correction',
|
||||
message TEXT NOT NULL,
|
||||
status TEXT NOT NULL DEFAULT 'open',
|
||||
admin_notes TEXT NOT NULL DEFAULT '',
|
||||
created_at TEXT NOT NULL DEFAULT(datetime('now'))
|
||||
);
|
||||
");
|
||||
}
|
||||
|
||||
/* ══════════════════════════════════════════════════════
|
||||
SEED DATA
|
||||
══════════════════════════════════════════════════════ */
|
||||
function _seed(PDO $db): void {
|
||||
|
||||
/* Settings */
|
||||
foreach (['registration_enabled'=>'1','site_name'=>'Discover Keyser WV',
|
||||
'site_tagline'=>'The Friendliest City in the U.S.A.',
|
||||
'contact_email'=>'info@discoverkeyser.com',
|
||||
'events_require_approval'=>'1'] as $k=>$v)
|
||||
qrun("INSERT OR IGNORE INTO settings(key,value)VALUES(?,?)",[$k,$v]);
|
||||
|
||||
/* Admin user — password "password123" */
|
||||
$hash = password_hash('password123', PASSWORD_BCRYPT);
|
||||
qrun("INSERT OR IGNORE INTO users(username,email,password,is_admin)
|
||||
VALUES('administrator','admin@discoverkeyser.com',?,1)",[$hash]);
|
||||
|
||||
/* Categories */
|
||||
foreach ([
|
||||
['Dining & Food','🍽️',1],['Shopping & Retail','🛍️',2],
|
||||
['Lodging','🏨',3],['Healthcare','🏥',4],['Education','🎓',5],
|
||||
['Financial Services','🏦',6],['Automotive','🔧',7],
|
||||
['Professional Services','💼',8],['Recreation & Fitness','⛹️',9],
|
||||
['Beauty & Personal Care','💇',10],['Government & Civic','🏛️',11],
|
||||
['Legal Services','⚖️',12],['Churches & Faith','⛪',13],
|
||||
] as $c) qrun("INSERT OR IGNORE INTO categories(name,icon,sort_order)VALUES(?,?,?)",$c);
|
||||
|
||||
$cid = fn(string $n): int => (int)qval("SELECT id FROM categories WHERE name=?",[$n]);
|
||||
$h = fn(array $d): string => json_encode($d);
|
||||
$std = $h(['Mon'=>'9am–5pm','Tue'=>'9am–5pm','Wed'=>'9am–5pm','Thu'=>'9am–5pm','Fri'=>'9am–5pm','Sat'=>'Closed','Sun'=>'Closed']);
|
||||
$always= $h(['Mon'=>'Open 24 hrs','Tue'=>'Open 24 hrs','Wed'=>'Open 24 hrs','Thu'=>'Open 24 hrs','Fri'=>'Open 24 hrs','Sat'=>'Open 24 hrs','Sun'=>'Open 24 hrs']);
|
||||
|
||||
$D=$cid('Dining & Food'); $SH=$cid('Shopping & Retail'); $LO=$cid('Lodging');
|
||||
$HC=$cid('Healthcare'); $ED=$cid('Education'); $FI=$cid('Financial Services');
|
||||
$AU=$cid('Automotive'); $PS=$cid('Professional Services'); $RF=$cid('Recreation & Fitness');
|
||||
$BP=$cid('Beauty & Personal Care'); $GV=$cid('Government & Civic');
|
||||
$LG=$cid('Legal Services'); $CH=$cid('Churches & Faith');
|
||||
|
||||
$bi = $db->prepare("INSERT INTO businesses(name,slug,category_id,subcategory,description,address,phone,email,website,hours,lat,lng,is_featured)VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?)");
|
||||
|
||||
$biz = [
|
||||
["Castiglia's Italian Eatery",'castiglia-italian',$D,'Italian Restaurant',
|
||||
"Keyser's most beloved restaurant. Family recipes passed down for generations: handmade pasta, wood-fired dishes, classic antipasti, and decadent Italian desserts. Known for huge servings and amazing food.",
|
||||
'401 S. Mineral St., Keyser, WV 26726','304-788-1300','','',
|
||||
$h(['Mon'=>'Closed','Tue'=>'Closed','Wed'=>'11am–9pm','Thu'=>'11am–9pm','Fri'=>'11am–9pm','Sat'=>'11am–9pm','Sun'=>'12pm–9pm']),39.4340,-78.9734,1],
|
||||
['The Candlewyck Inn','candlewyck-inn',$D,'Fine Dining',
|
||||
"Elegant fine dining in a beautifully restored historic setting. Upscale American cuisine with locally sourced seasonal ingredients. Award-winning wine list. Keyser's premier destination for special occasions.",
|
||||
'65 S. Mineral St., Keyser, WV 26726','304-788-6594','','',
|
||||
$h(['Mon'=>'Closed','Tue'=>'5pm–9pm','Wed'=>'5pm–9pm','Thu'=>'5pm–9pm','Fri'=>'5pm–10pm','Sat'=>'4pm–10pm','Sun'=>'Closed']),39.4370,-78.9734,1],
|
||||
["Clancy's Irish Pub",'clancys-irish-pub',$D,'Irish Pub & Bar',
|
||||
"Keyser's favorite neighborhood pub! Cold craft beers on tap, hearty pub fare, sports on every screen, trivia nights on Wednesdays, and live music on weekends.",
|
||||
'777 Armstrong St., Keyser, WV 26726','304-788-1133','','',
|
||||
$h(['Mon'=>'4pm–12am','Tue'=>'4pm–12am','Wed'=>'4pm–12am','Thu'=>'4pm–12am','Fri'=>'4pm–2am','Sat'=>'12pm–2am','Sun'=>'12pm–10pm']),39.4390,-78.9750,1],
|
||||
['North Branch Craft Pub','north-branch-craft-pub',$D,'Craft Brewery & Pub',
|
||||
"Keyser's craft beer destination. Local and regional craft beers on rotating taps, great pub fare, and stunning North Branch river views. Live entertainment regularly.",
|
||||
'101 Armstrong St., Ste. 1, Keyser, WV 26726','304-790-7125','','',
|
||||
$h(['Mon'=>'Closed','Tue'=>'4pm–11pm','Wed'=>'4pm–11pm','Thu'=>'4pm–11pm','Fri'=>'3pm–1am','Sat'=>'12pm–1am','Sun'=>'12pm–8pm']),39.4392,-78.9750,1],
|
||||
['Queens Point Coffee','queens-point-coffee',$D,'Coffee Shop',
|
||||
'"THE best coffee shop I\'ve ever been to." Named after the iconic Queens Point cliff. Iced matcha, lattes, specialty drinks, amazing food, and friendly staff.',
|
||||
'101 Armstrong St., Keyser, WV 26726','304-790-7125','','',
|
||||
$h(['Mon'=>'7am–3pm','Tue'=>'7am–5pm','Wed'=>'7am–5pm','Thu'=>'7am–5pm','Fri'=>'7am–5pm','Sat'=>'8am–5pm','Sun'=>'9am–2pm']),39.4392,-78.9750,1],
|
||||
['Royal Restaurant','royal-restaurant',$D,'American / Comfort Food',
|
||||
"A Keyser classic for generations. Hearty American comfort food for breakfast, lunch, and dinner. Known for great breakfasts, homemade pies, and friendly small-town service.",
|
||||
'88 N. Main St., Keyser, WV 26726','304-788-9825','','',
|
||||
$h(['Mon'=>'6am–8pm','Tue'=>'6am–8pm','Wed'=>'6am–8pm','Thu'=>'6am–8pm','Fri'=>'6am–9pm','Sat'=>'6am–9pm','Sun'=>'7am–3pm']),39.4378,-78.9734,0],
|
||||
['Fat Bottom Grille','fat-bottom-grille',$D,'American Bar & Grill',
|
||||
'"THE best place in town to get a burger or steak sub." Everything made fresh. The smash burger is juicy and flavored to perfection. Huge portions at excellent prices.',
|
||||
'Keyser, WV 26726','304-788-0000','','',
|
||||
$h(['Mon'=>'11am–9pm','Tue'=>'11am–9pm','Wed'=>'11am–9pm','Thu'=>'11am–9pm','Fri'=>'11am–10pm','Sat'=>'11am–10pm','Sun'=>'12pm–9pm']),39.4360,-78.9740,1],
|
||||
["Denny's",'dennys',$D,'American / Diner',
|
||||
"Open 24/7. America's diner at Route 220 South. Grand Slams, hearty burgers, and all-day breakfast.",
|
||||
'825 S. Mineral St. (US Rt. 220 S), Keyser, WV 26726','304-788-3090','','dennys.com',$always,39.4300,-78.9730,0],
|
||||
["McDonald's",'mcdonalds',$D,'Fast Food',
|
||||
"Burgers, fries, breakfast sandwiches, and McCafé beverages. Drive-through available.",
|
||||
'700 S. Mineral St., Keyser, WV 26726','304-788-0604','','mcdonalds.com',
|
||||
$h(['Mon'=>'6am–11pm','Tue'=>'6am–11pm','Wed'=>'6am–11pm','Thu'=>'6am–11pm','Fri'=>'6am–12am','Sat'=>'6am–12am','Sun'=>'7am–11pm']),39.4310,-78.9730,0],
|
||||
['Burger King','burger-king',$D,'Fast Food',
|
||||
'Home of the Whopper! Flame-grilled burgers and crispy fries. Drive-through available.',
|
||||
'RR#3 Box 3240, New Creek Hwy, Keyser, WV 26726','304-788-0000','','burgerking.com',
|
||||
$h(['Mon'=>'6am–12am','Tue'=>'6am–12am','Wed'=>'6am–12am','Thu'=>'6am–12am','Fri'=>'6am–1am','Sat'=>'6am–1am','Sun'=>'7am–12am']),39.4285,-78.9720,0],
|
||||
["Domino's Pizza",'dominos',$D,'Pizza / Delivery',
|
||||
'Hot fresh pizza fast. Carryout or delivered. Online ordering at dominos.com.',
|
||||
'590 S. Mineral St., Keyser, WV 26726','304-788-6400','','dominos.com',
|
||||
$h(['Mon'=>'10:30am–12am','Tue'=>'10:30am–12am','Wed'=>'10:30am–12am','Thu'=>'10:30am–12am','Fri'=>'10:30am–1am','Sat'=>'10:30am–1am','Sun'=>'10:30am–12am']),39.4330,-78.9730,0],
|
||||
['Dairy Queen Grill & Chill','dairy-queen',$D,'Ice Cream / Fast Food',
|
||||
"Signature Blizzard® treats, soft-serve cones, and grill burgers. A Keyser summer tradition!",
|
||||
'460 S. Mineral St., Keyser, WV 26726','304-788-1499','','dairyqueen.com',
|
||||
$h(['Mon'=>'10am–10pm','Tue'=>'10am–10pm','Wed'=>'10am–10pm','Thu'=>'10am–10pm','Fri'=>'10am–10:30pm','Sat'=>'10am–10:30pm','Sun'=>'11am–9pm']),39.4320,-78.9730,0],
|
||||
["Fox's Pizza Den",'foxs-pizza',$D,'Pizza',
|
||||
"Local pizza legend! Hand-tossed pizzas, subs, wings, and salads. A true Keyser staple.",
|
||||
'567 S. Mineral St., Keyser, WV 26726','304-788-1149','','',
|
||||
$h(['Mon'=>'11am–10pm','Tue'=>'11am–10pm','Wed'=>'11am–10pm','Thu'=>'11am–10pm','Fri'=>'11am–11pm','Sat'=>'11am–11pm','Sun'=>'12pm–9pm']),39.4315,-78.9730,0],
|
||||
['Little Caesars','little-caesars',$D,'Pizza / Fast Food',
|
||||
'Hot-N-Ready pizzas at unbeatable prices. No wait. Crazy Bread and Italian favorites.',
|
||||
'30 Armstrong St., Keyser, WV 26726','304-788-7738','','littlecaesars.com',
|
||||
$h(['Mon'=>'11am–9pm','Tue'=>'11am–9pm','Wed'=>'11am–9pm','Thu'=>'11am–9pm','Fri'=>'11am–10pm','Sat'=>'11am–10pm','Sun'=>'12pm–9pm']),39.4395,-78.9750,0],
|
||||
['Subway','subway',$D,'Sandwiches / Fast Food',
|
||||
'Fresh-built footlong subs, wraps, and salads.',
|
||||
'2 Heskiet St. (Gulf), Keyser, WV 26726','304-788-3613','','subway.com',
|
||||
$h(['Mon'=>'7am–10pm','Tue'=>'7am–10pm','Wed'=>'7am–10pm','Thu'=>'7am–10pm','Fri'=>'7am–10pm','Sat'=>'8am–10pm','Sun'=>'9am–9pm']),39.4260,-78.9720,0],
|
||||
['Taco Bell','taco-bell',$D,'Mexican Fast Food',
|
||||
'Tacos, burritos, nachos, and Crunchwrap Supremes. Drive-through available.',
|
||||
'41 Plaza Drive, Keyser, WV 26726','304-788-0000','','tacobell.com',
|
||||
$h(['Mon'=>'7am–12am','Tue'=>'7am–12am','Wed'=>'7am–12am','Thu'=>'7am–12am','Fri'=>'7am–2am','Sat'=>'7am–2am','Sun'=>'8am–12am']),39.4265,-78.9722,0],
|
||||
["Ducky's Bar & Grill",'duckys-bar-grill',$D,'American Bar & Grill',
|
||||
'"The ultimate combination of bar and grill." Famous Tennessee whiskey burger and chili cheese fries.',
|
||||
'Keyser, WV 26726','304-788-0000','','',
|
||||
$h(['Mon'=>'11am–11pm','Tue'=>'11am–11pm','Wed'=>'11am–11pm','Thu'=>'11am–11pm','Fri'=>'11am–1am','Sat'=>'11am–1am','Sun'=>'12pm–9pm']),39.4358,-78.9738,0],
|
||||
["Martie's Hot Dog Stand",'marties-hot-dogs',$D,'Hot Dogs / Street Food',
|
||||
"A beloved Keyser institution. Classic hot dogs with all the fixings for generations.",
|
||||
'96 N. Main St., Keyser, WV 26726','304-788-7690','','',
|
||||
$h(['Mon'=>'10am–6pm','Tue'=>'10am–6pm','Wed'=>'10am–6pm','Thu'=>'10am–6pm','Fri'=>'10am–7pm','Sat'=>'10am–7pm','Sun'=>'Closed']),39.4375,-78.9734,0],
|
||||
["Jin's Asian Cuisine 2",'jins-asian-cuisine',$D,'Asian / Chinese',
|
||||
"Orange chicken, bourbon chicken, lo mein, fried rice, and crab rangoon made fresh to order.",
|
||||
'196 N. Tornado Way #11, Keyser, WV 26726','304-788-2222','','',
|
||||
$h(['Mon'=>'11am–9pm','Tue'=>'11am–9pm','Wed'=>'11am–9pm','Thu'=>'11am–9pm','Fri'=>'11am–10pm','Sat'=>'11am–10pm','Sun'=>'12pm–9pm']),39.4355,-78.9730,0],
|
||||
// Shopping
|
||||
["Wayne's Country Meats",'waynes-country-meats',$SH,'Butcher / Specialty Meats',
|
||||
'Premium quality meats from local farms. Custom cuts, specialty items, fresh jerky.',
|
||||
'670 Armstrong St., Keyser, WV 26726','304-788-5956','','',
|
||||
$h(['Mon'=>'8am–6pm','Tue'=>'8am–6pm','Wed'=>'8am–6pm','Thu'=>'8am–6pm','Fri'=>'8am–6pm','Sat'=>'8am–5pm','Sun'=>'Closed']),39.4395,-78.9750,1],
|
||||
['Save-A-Lot','save-a-lot',$SH,'Grocery',
|
||||
'Affordable grocery shopping. Fresh produce, quality meats, dairy, and pantry essentials.',
|
||||
'S. Mineral St., Keyser, WV 26726','304-788-7570','','save-a-lot.com',
|
||||
$h(['Mon'=>'8am–9pm','Tue'=>'8am–9pm','Wed'=>'8am–9pm','Thu'=>'8am–9pm','Fri'=>'8am–9pm','Sat'=>'8am–9pm','Sun'=>'9am–7pm']),39.4298,-78.9728,0],
|
||||
['AutoZone','autozone',$SH,'Auto Parts',
|
||||
"America's leading auto parts retailer. Free battery testing, loaner tool program.",
|
||||
'2 W. Piedmont St., Keyser, WV 26726','304-788-9058','','autozone.com',
|
||||
$h(['Mon'=>'7:30am–9pm','Tue'=>'7:30am–9pm','Wed'=>'7:30am–9pm','Thu'=>'7:30am–9pm','Fri'=>'7:30am–9pm','Sat'=>'7:30am–9pm','Sun'=>'9am–8pm']),39.4378,-78.9734,0],
|
||||
['CVS Pharmacy','cvs',$SH,'Pharmacy / Health & Beauty',
|
||||
'Prescriptions, health products, beauty supplies, and household essentials.',
|
||||
'45 S. Mineral St., Keyser, WV 26726','304-788-3443','','cvs.com',
|
||||
$h(['Mon'=>'8am–9pm','Tue'=>'8am–9pm','Wed'=>'8am–9pm','Thu'=>'8am–9pm','Fri'=>'8am–9pm','Sat'=>'9am–6pm','Sun'=>'10am–6pm']),39.4368,-78.9734,0],
|
||||
['AT&T Store','att-store',$SH,'Telecommunications',
|
||||
'Latest smartphones, tablets, and wireless plans.',
|
||||
'862 S. Mineral St., Keyser, WV 26726','304-788-9000','','att.com',
|
||||
$h(['Mon'=>'10am–7pm','Tue'=>'10am–7pm','Wed'=>'10am–7pm','Thu'=>'10am–7pm','Fri'=>'10am–7pm','Sat'=>'10am–7pm','Sun'=>'12pm–5pm']),39.4292,-78.9728,0],
|
||||
["Christy's Florist",'christys-florist',$SH,'Florist',
|
||||
'Fresh floral arrangements for weddings, funerals, anniversaries, and celebrations.',
|
||||
'81 N. Main St., Keyser, WV 26726','304-788-3679','','',
|
||||
$h(['Mon'=>'9am–5pm','Tue'=>'9am–5pm','Wed'=>'9am–5pm','Thu'=>'9am–5pm','Fri'=>'9am–6pm','Sat'=>'9am–3pm','Sun'=>'Closed']),39.4382,-78.9734,0],
|
||||
['Southern States','southern-states',$SH,'Farm & Garden Supply',
|
||||
'Agricultural supplies, pet food, hardware, seed, fertilizer, and home and garden products.',
|
||||
'201 Patrick St., Keyser, WV 26726','304-788-2317','','southernstates.com',
|
||||
$h(['Mon'=>'7:30am–5:30pm','Tue'=>'7:30am–5:30pm','Wed'=>'7:30am–5:30pm','Thu'=>'7:30am–5:30pm','Fri'=>'7:30am–5:30pm','Sat'=>'8am–3pm','Sun'=>'Closed']),39.4410,-78.9755,0],
|
||||
['Back Alley Crafts & Tarts','back-alley-crafts',$SH,'Crafts & Gifts',
|
||||
'Unique handmade crafts, locally made artisan goods, and specialty gifts.',
|
||||
'226 S. Main St., Keyser, WV 26726','304-813-6256','','',
|
||||
$h(['Mon'=>'10am–5pm','Tue'=>'10am–5pm','Wed'=>'10am–5pm','Thu'=>'10am–5pm','Fri'=>'10am–6pm','Sat'=>'10am–4pm','Sun'=>'Closed']),39.4357,-78.9734,0],
|
||||
['Heaven Sent Creations','heaven-sent-creations',$SH,'Gifts & Crafts',
|
||||
'Inspirational gifts, custom creations, home décor, and unique finds.',
|
||||
'117 Armstrong St., Keyser, WV 26726','304-790-7402','','',
|
||||
$h(['Mon'=>'10am–5pm','Tue'=>'10am–5pm','Wed'=>'10am–5pm','Thu'=>'10am–5pm','Fri'=>'10am–5pm','Sat'=>'10am–4pm','Sun'=>'Closed']),39.4393,-78.9750,0],
|
||||
['Thunder Hill Outfitters','thunder-hill-outfitters',$SH,'Hunting & Fishing Supplies',
|
||||
"Hunting and fishing supplies, gear, licenses, and local expertise.",
|
||||
'105 Armstrong St., Keyser, WV 26726','304-790-7125','','',
|
||||
$h(['Mon'=>'9am–6pm','Tue'=>'9am–6pm','Wed'=>'9am–6pm','Thu'=>'9am–6pm','Fri'=>'9am–7pm','Sat'=>'8am–7pm','Sun'=>'10am–4pm']),39.4392,-78.9750,0],
|
||||
// Lodging
|
||||
['SureStay Plus by Best Western Keyser','surestay-best-western',$LO,'Hotel',
|
||||
'Free hot breakfast daily, free WiFi, indoor pool, and fitness center. Pet-friendly.',
|
||||
'New Creek Hwy, Keyser, WV 26726','304-788-0000','','bestwestern.com',$always,39.4298,-78.9705,1],
|
||||
['Keyser Inn','keyser-inn',$LO,'Motel',
|
||||
'Affordable, clean accommodations. Continental breakfast, free WiFi, pet-friendly.',
|
||||
'Keyser, WV 26726','304-788-0000','','',$always,39.4360,-78.9734,0],
|
||||
// Healthcare
|
||||
['WVU Medicine Potomac Valley Hospital','pvh',$HC,'Hospital / Medical Center',
|
||||
'Full-service community hospital. Emergency department, surgery, maternity care, cardiac services.',
|
||||
'100 Pin Oak Ln., Keyser, WV 26726','304-597-3500','','wvumedicine.org',$always,39.4275,-78.9725,1],
|
||||
['Med-a-Save Pharmacy','med-a-save',$HC,'Independent Pharmacy',
|
||||
'Local independent pharmacy. Prescriptions, compounding, and immunizations.',
|
||||
'818 S. Mineral St., Keyser, WV 26726','304-788-6010','','',
|
||||
$h(['Mon'=>'9am–6pm','Tue'=>'9am–6pm','Wed'=>'9am–6pm','Thu'=>'9am–6pm','Fri'=>'9am–6pm','Sat'=>'9am–1pm','Sun'=>'Closed']),39.4287,-78.9728,0],
|
||||
// Education
|
||||
['Potomac State College of WVU','potomac-state-college',$ED,'Community College / University',
|
||||
"WVU Potomac State College — founded 1901 on historic Fort Fuller. Associate and bachelor's degrees in 40+ programs. Home of the Catamounts.",
|
||||
'101 Fort Ave., Keyser, WV 26726','304-788-6800','','potomacstatecollege.edu',$std,39.4368,-78.9715,1],
|
||||
['Mineral County Public Library','mineral-county-library',$ED,'Public Library',
|
||||
'Books, digital resources, internet access, printing, and community programs for all ages.',
|
||||
'Keyser, WV 26726','304-788-3100','','',
|
||||
$h(['Mon'=>'10am–7pm','Tue'=>'10am–7pm','Wed'=>'10am–7pm','Thu'=>'10am–7pm','Fri'=>'10am–5pm','Sat'=>'10am–4pm','Sun'=>'Closed']),39.4370,-78.9734,0],
|
||||
// Financial
|
||||
["First United Bank & Trust",'first-united-bank',$FI,'Community Bank',
|
||||
'Community banking rooted in West Virginia. Personal checking, savings, mortgages.',
|
||||
'29 West Southern Dr., Keyser, WV 26726','304-788-2552','','mybank.com',
|
||||
$h(['Mon'=>'9am–5pm','Tue'=>'9am–5pm','Wed'=>'9am–5pm','Thu'=>'9am–5pm','Fri'=>'9am–5:30pm','Sat'=>'9am–12pm','Sun'=>'Closed']),39.4372,-78.9740,0],
|
||||
['M&T Bank','m-t-bank',$FI,'Bank',
|
||||
'Full-service personal, small business, and commercial banking. 24/7 ATM.',
|
||||
'67 N. Main St., Keyser, WV 26726','304-788-6782','','mtb.com',
|
||||
$h(['Mon'=>'9am–5pm','Tue'=>'9am–5pm','Wed'=>'9am–5pm','Thu'=>'9am–5pm','Fri'=>'9am–6pm','Sat'=>'9am–12pm','Sun'=>'Closed']),39.4380,-78.9734,0],
|
||||
// Automotive
|
||||
["Boddy's Automotive",'boddys-auto',$AU,'Full Service Auto Repair',
|
||||
'Trusted local auto repair for all makes and models. Honest prices.',
|
||||
'220 Armstrong St., Keyser, WV 26726','304-788-5511','','',
|
||||
$h(['Mon'=>'8am–5pm','Tue'=>'8am–5pm','Wed'=>'8am–5pm','Thu'=>'8am–5pm','Fri'=>'8am–5pm','Sat'=>'Closed','Sun'=>'Closed']),39.4392,-78.9750,0],
|
||||
['Gimme A Brake Auto','gimme-a-brake',$AU,'Brakes / Tires / Oil Changes',
|
||||
'Fast, friendly, and affordable auto care. No appointment needed for routine maintenance.',
|
||||
'375 West Piedmont St., Keyser, WV 26726','304-788-7810','','',
|
||||
$h(['Mon'=>'8am–5:30pm','Tue'=>'8am–5:30pm','Wed'=>'8am–5:30pm','Thu'=>'8am–5:30pm','Fri'=>'8am–5:30pm','Sat'=>'8am–12pm','Sun'=>'Closed']),39.4378,-78.9748,0],
|
||||
// Professional Services
|
||||
['Boggs Supply and Rental Center','boggs-supply',$PS,'Equipment Rental / Supply',
|
||||
'Tools, equipment, and supplies for rent or purchase.',
|
||||
'464 Harley O Staggers Sr. Dr., Keyser, WV 26726','304-788-1617','','',
|
||||
$h(['Mon'=>'7:30am–5pm','Tue'=>'7:30am–5pm','Wed'=>'7:30am–5pm','Thu'=>'7:30am–5pm','Fri'=>'7:30am–5pm','Sat'=>'8am–12pm','Sun'=>'Closed']),39.4382,-78.9748,0],
|
||||
['Legal Aid of WV','legal-aid',$LG,'Legal Aid',
|
||||
'Free civil legal aid for eligible low-income West Virginians.',
|
||||
'251 W. Piedmont St., Keyser, WV 26726','304-788-6770','','lawv.net',$std,39.4374,-78.9750,0],
|
||||
// Recreation
|
||||
['North Branch Ventures','north-branch-ventures',$RF,'Kayak Rental / Outdoor Recreation',
|
||||
"Kayak and river supply rentals on the beautiful North Branch Potomac. Guided river experiences.",
|
||||
'101 Armstrong St., Keyser, WV 26726','304-790-7125','','',
|
||||
$h(['Mon'=>'Closed','Tue'=>'Closed','Wed'=>'10am–6pm','Thu'=>'10am–6pm','Fri'=>'9am–7pm','Sat'=>'8am–7pm','Sun'=>'8am–5pm']),39.4392,-78.9750,1],
|
||||
['PSC Recreation Center','psc-rec-center',$RF,'Fitness Center / Pool',
|
||||
"Full-service fitness center with indoor pool, hot tub, strength and cardio, group exercise. Open to the public.",
|
||||
'J. Edward Kelley Complex, 101 Fort Ave., Keyser, WV','304-788-6800','','potomacstatecollege.edu',
|
||||
$h(['Mon'=>'6am–9pm','Tue'=>'6am–9pm','Wed'=>'6am–9pm','Thu'=>'6am–9pm','Fri'=>'6am–8pm','Sat'=>'8am–6pm','Sun'=>'12pm–6pm']),39.4368,-78.9715,0],
|
||||
['Mineral County Parks & Recreation','mineral-county-parks',$RF,'Parks & Recreation',
|
||||
"Larenim Park — 365 acres with pavilions, 600-seat amphitheater, fishing ponds, and trails.",
|
||||
'Keyser, WV 26726','304-788-3066','','mineralwv.gov',
|
||||
$h(['Mon'=>'Open Daily','Tue'=>'Open Daily','Wed'=>'Open Daily','Thu'=>'Open Daily','Fri'=>'Open Daily','Sat'=>'Open Daily','Sun'=>'Open Daily']),39.4350,-78.9720,0],
|
||||
// Beauty
|
||||
['Eclips Hair Salon','eclips',$BP,'Hair Salon',
|
||||
'Full-service hair salon. Cuts, color, styling, and treatments for men and women.',
|
||||
'153 S. Mineral St., Keyser, WV 26726','304-788-5578','','',
|
||||
$h(['Mon'=>'Closed','Tue'=>'9am–5pm','Wed'=>'9am–5pm','Thu'=>'9am–5pm','Fri'=>'9am–6pm','Sat'=>'8am–4pm','Sun'=>'Closed']),39.4352,-78.9733,0],
|
||||
['In The Skin II','in-the-skin',$BP,'Tattoo & Body Art',
|
||||
'Professional tattoo and body art studio. Custom designs, cover-ups, and piercings.',
|
||||
'129 N. Main St., Keyser, WV 26726','304-597-2070','','',
|
||||
$h(['Mon'=>'11am–7pm','Tue'=>'11am–7pm','Wed'=>'11am–7pm','Thu'=>'11am–7pm','Fri'=>'11am–8pm','Sat'=>'10am–6pm','Sun'=>'Closed']),39.4373,-78.9734,0],
|
||||
// Government
|
||||
['Mineral County Courthouse','mineral-county-courthouse',$GV,'County Government',
|
||||
"Historic 1868 courthouse listed on the National Register of Historic Places — the architectural crown jewel of downtown Keyser.",
|
||||
'Keyser, WV 26726','304-788-3003','','mineralwv.gov',
|
||||
$h(['Mon'=>'8:30am–4:30pm','Tue'=>'8:30am–4:30pm','Wed'=>'8:30am–4:30pm','Thu'=>'8:30am–4:30pm','Fri'=>'8:30am–4:30pm','Sat'=>'Closed','Sun'=>'Closed']),39.4385,-78.9738,0],
|
||||
['City of Keyser','city-of-keyser',$GV,'City Government',
|
||||
"Official offices of the City of Keyser, WV. City council, mayor's office, utilities, and municipal services.",
|
||||
'Keyser, WV 26726','304-788-0222','','cityofkeyser.com',
|
||||
$h(['Mon'=>'8:30am–4:30pm','Tue'=>'8:30am–4:30pm','Wed'=>'8:30am–4:30pm','Thu'=>'8:30am–4:30pm','Fri'=>'8:30am–4:30pm','Sat'=>'Closed','Sun'=>'Closed']),39.4375,-78.9734,0],
|
||||
['Mineral County Tourism Visitors Center','mineral-county-tourism',$GV,'Tourism / Visitors Center',
|
||||
'167 S. Mineral Street — Your starting point for exploring Mineral County! Brochures, maps, and friendly staff.',
|
||||
'167 S. Mineral St., Keyser, WV 26726','304-790-7081','mineralcocvb@gmail.com','govisitmineralwv.com',
|
||||
$h(['Mon'=>'9am–4pm','Tue'=>'9am–4pm','Wed'=>'9am–4pm','Thu'=>'9am–4pm','Fri'=>'9am–4pm','Sat'=>'Call Ahead','Sun'=>'Closed']),39.4358,-78.9734,1],
|
||||
['Mineral County Historical Society Museum','mineral-county-historical',$GV,'Museum / Historical Society',
|
||||
"Museum tracking the history of Mineral County and Keyser with engaging exhibits and artifacts. Open by appointment.",
|
||||
'Keyser, WV 26726','304-788-3066','','',
|
||||
$h(['Mon'=>'By Appt','Tue'=>'By Appt','Wed'=>'By Appt','Thu'=>'By Appt','Fri'=>'By Appt','Sat'=>'Special Events','Sun'=>'Special Events']),39.4378,-78.9734,0],
|
||||
// Churches
|
||||
['Keyser First United Methodist Church','keyser-umc',$CH,'Methodist Church',
|
||||
'Welcoming United Methodist congregation serving Keyser since the 19th century.',
|
||||
'32 N. Davis St., Keyser, WV 26726','304-788-2522','','',
|
||||
$h(['Mon'=>'Closed','Tue'=>'Closed','Wed'=>'Closed','Thu'=>'Closed','Fri'=>'Closed','Sat'=>'Closed','Sun'=>'Worship 11am']),39.4372,-78.9730,0],
|
||||
['Living Faith Fellowship','living-faith',$CH,'Non-Denominational Church',
|
||||
'Vibrant non-denominational Christian fellowship. Contemporary worship and community ministry.',
|
||||
'1 N. Main St., Keyser, WV 26726','304-788-1910','','',
|
||||
$h(['Mon'=>'Closed','Tue'=>'Closed','Wed'=>'7pm','Thu'=>'Closed','Fri'=>'Closed','Sat'=>'Closed','Sun'=>'Worship 10:30am']),39.4376,-78.9734,0],
|
||||
];
|
||||
|
||||
foreach ($biz as $r) $bi->execute($r);
|
||||
|
||||
/* ── Menus ── */
|
||||
$si = $db->prepare("INSERT INTO menu_sections(business_id,name,description,sort_order)VALUES(?,?,?,?)");
|
||||
$mi = $db->prepare("INSERT INTO menu_items(section_id,name,description,price,sort_order)VALUES(?,?,?,?,?)");
|
||||
|
||||
$castId = (int)qval("SELECT id FROM businesses WHERE slug='castiglia-italian'");
|
||||
foreach ([['Antipasti & Salads','Fresh starters',1],['Pasta','Handmade pastas',2],['Pizza','Stone-baked Italian pizzas',3],['Entrees','Secondi piatti',4],['Desserts','Dolci',5]] as $s) $si->execute(array_merge([$castId],$s));
|
||||
$cs=[]; foreach(qall("SELECT id,name FROM menu_sections WHERE business_id=$castId") as $r) $cs[$r['name']]=$r['id'];
|
||||
foreach(['Antipasti & Salads'=>[['Bruschetta al Pomodoro','Toasted rustic bread with vine-ripened tomatoes, fresh basil & extra-virgin olive oil',8.95,1],['Calamari Fritti','Lightly breaded fresh calamari, marinara sauce & lemon aioli',13.95,2],['Caprese Salad','Fresh buffalo mozzarella, heirloom tomatoes, basil & balsamic glaze',11.95,3],['Minestrone Soup','Classic Italian vegetable soup with cannellini beans',7.50,4],['Caesar Salad','Romaine, house Caesar dressing, shaved Parmigiano, croutons',9.95,5]],
|
||||
'Pasta'=>[['Spaghetti Carbonara','Classic Roman — guanciale, egg, Pecorino Romano, cracked black pepper',15.95,1],['Fettuccine Alfredo','House-made fettuccine in rich cream & Parmigiano sauce',14.95,2],['Lasagna al Forno','House-rolled pasta, Bolognese, bechamel & Parmigiano',16.95,3],['Baked Ziti','Ziti, house marinara, ricotta & melted mozzarella',13.95,4],['Penne Arrabbiata','Spicy tomato, garlic, Calabrian chiles & fresh parsley',12.95,5]],
|
||||
'Pizza'=>[['Margherita','San Marzano tomatoes, fior di latte mozzarella & fresh basil',14.95,1],['Pepperoni','House marinara, mozzarella & premium pepperoni',15.95,2],['Quattro Stagioni','Ham, mushrooms, artichoke hearts & Kalamata olives',17.95,3],['Prosciutto & Arugula','Parma prosciutto, baby arugula & shaved Parmigiano',18.95,4]],
|
||||
'Entrees'=>[['Chicken Parmigiana','Breaded chicken, house marinara & fresh mozzarella, served with pasta',18.95,1],['Osso Buco alla Milanese','Braised veal shank, saffron risotto & traditional gremolata',34.95,2],['Eggplant Parmigiana','Layered eggplant, San Marzano sauce & mozzarella',15.95,3],['Salmon Piccata','Pan-seared Atlantic salmon, lemon-caper butter & fresh herbs',24.95,4]],
|
||||
'Desserts'=>[['Tiramisu','Espresso-soaked ladyfingers, mascarpone cream & cocoa',8.95,1],['Cannoli Siciliani','Crispy shells with sweet ricotta, chocolate chips & pistachios',7.95,2],['Panna Cotta','Silky vanilla panna cotta with seasonal berry coulis',7.50,3],['Gelato del Giorno','Two scoops house-made gelato — ask your server',6.95,4]]]
|
||||
as $sec=>$items) foreach($items as $item) $mi->execute(array_merge([$cs[$sec]],$item));
|
||||
|
||||
// Queens Point Coffee menu
|
||||
$qpId = (int)qval("SELECT id FROM businesses WHERE slug='queens-point-coffee'");
|
||||
foreach ([['Espresso Drinks','Hot & cold espresso beverages',1],['Cold Drinks','Refreshing chilled options',2],['Food','Fresh baked goods & light bites',3]] as $s) $si->execute(array_merge([$qpId],$s));
|
||||
$qs=[]; foreach(qall("SELECT id,name FROM menu_sections WHERE business_id=$qpId") as $r) $qs[$r['name']]=$r['id'];
|
||||
foreach(['Espresso Drinks'=>[['Latte','Smooth espresso with steamed milk',4.50,1],['Cappuccino','Double espresso with foamed milk',4.25,2],['Americano','Espresso shots with hot water',3.50,3],['Mocha','Espresso, chocolate & steamed milk',5.00,4],['Iced Matcha Latte','Matcha with milk — our most raved drink!',5.25,5]],
|
||||
'Cold Drinks'=>[['Cold Brew','Smooth 24-hour cold brew over ice',3.75,1],['Iced Latte','Chilled espresso with cold milk',4.75,2],['Blended Frappe','Blended ice coffee drink',5.50,3]],
|
||||
'Food'=>[['Blueberry Muffin','Fresh-baked daily',3.00,1],['Avocado Toast','Multigrain with avocado & everything spice',7.50,2],['Breakfast Sandwich','Egg, cheese & choice of meat',6.50,3],['Cookie','Assorted fresh-baked cookies',2.50,4]]]
|
||||
as $sec=>$items) foreach($items as $item) $mi->execute(array_merge([$qs[$sec]],$item));
|
||||
|
||||
/* ── Alerts ── */
|
||||
foreach ([
|
||||
['castiglia-italian','news','New Menu Items This Season!',
|
||||
"Chef's new handmade gnocchi and wood-fired seasonal pizza are now available. Fresh locally-sourced summer ingredients throughout the menu."],
|
||||
['queens-point-coffee','news','Try Our Famous Iced Matcha!',
|
||||
'"THE best coffee shop I\'ve ever been to." Our iced matcha with coconut and pistachio is the most-talked-about drink in Keyser.'],
|
||||
['clancys-irish-pub','event','Live Music Every Friday & Saturday!',
|
||||
"Live music from 9pm-1am every Friday and Saturday night. No cover charge! Food and drinks served until close."],
|
||||
['pvh','info','Urgent Care Now Open 7 Days',
|
||||
'WVU Medicine Potomac Valley Hospital Urgent Care is open Mon-Fri 8am-8pm and weekends 9am-5pm. No appointment needed.'],
|
||||
['north-branch-ventures','event','Guided Kayak Tours - Book Now!',
|
||||
"Guided half-day kayak tours on the North Branch Potomac every Saturday and Sunday through October. All skill levels welcome."],
|
||||
] as [$slug,$type,$title,$body])
|
||||
qrun("INSERT INTO alerts(business_id,type,title,body,is_active)VALUES((SELECT id FROM businesses WHERE slug=?),?,?,?,1)",[$slug,$type,$title,$body]);
|
||||
|
||||
/* ── Attractions ── */
|
||||
foreach ([
|
||||
['Queens Point Overlook','Natural Landmark',"A spectacular Oriskany sandstone cliff rising ~400 feet above the North Branch Potomac River. Breathtaking panoramic views of Keyser and the river valley.",'McCoole, MD (viewable from Keyser riverfront)','','','Accessible year-round',1,1],
|
||||
['North Branch Potomac River','Outdoor Recreation',"World-class smallmouth bass fishing, kayaking, canoeing, and bird watching. Contact North Branch Ventures for rentals and guided tours.",'Armstrong St. riverfront, Keyser, WV','304-790-7125','','Open year-round',1,2],
|
||||
['Jennings Randolph Lake','Lake / Reservoir',"A stunning 952-acre reservoir on the North Branch Potomac. Boating, fishing, swimming, camping, and picnicking. Managed by U.S. Army Corps of Engineers.",'Elk Garden, WV 26717 (~20 min from Keyser)','304-355-2346','','Open year-round',1,3],
|
||||
['Larenim Park','County Park',"Mineral County's premier park at 365 acres. Pavilions, 600-seat amphitheater, fishing ponds, and 5 miles of trails.",'Keyser, WV 26726','304-788-3066','','Open daily',1,4],
|
||||
['Mineral County Courthouse','Historic Site',"The 1868 courthouse listed on the National Register of Historic Places — the architectural centerpiece of downtown Keyser.",'Keyser, WV 26726','304-788-3003','','Exterior always viewable',1,5],
|
||||
['Potomac State College Campus / Fort Fuller','Historic Site',"Fort Hill — site of Civil War Fort Fuller — commanded by future president Benjamin Harrison and Lew Wallace (author of Ben-Hur). Now the beautiful PSC campus.",'101 Fort Ave., Keyser, WV 26726','304-788-6800','potomacstatecollege.edu','Campus open daily',1,6],
|
||||
['Potomac Eagle Scenic Railroad','Train Excursion',"Scenic excursions through The Trough along the South Branch Potomac River — famous for bald eagle sightings. About 30 miles from Keyser.",'Romney, WV 26757 (~30 miles)','304-822-7400','potomaceagle.info','Seasonal spring through fall',1,7],
|
||||
['Blackwater Falls State Park','State Park',"The amber-colored Blackwater Falls plunge 57 feet into the dramatic canyon. Hiking, skiing, camping, and a beautiful lodge. About 40 minutes from Keyser.",'Davis, WV 26260 (~40 min)','304-259-5216','wvstateparks.com','Open year-round',1,8],
|
||||
['Seneca Rocks','Natural Landmark',"Massive quartzite outcroppings rising 900 feet from the valley floor. Rock climbing, hiking, and spectacular views. About 45 minutes from Keyser.",'Seneca Rocks, WV (~45 min)','304-567-2827','','Open year-round',1,9],
|
||||
['Fort Ashby Blockhouse','Historic Site',"The only remaining French and Indian War fort in West Virginia. Ordered built by young George Washington in 1755. Just 15 miles from Keyser.",'Fort Ashby, WV 26719 (~15 miles)','','','Open seasonally',1,10],
|
||||
] as $a) qrun("INSERT INTO attractions(name,category,description,address,phone,website,hours,is_active,sort_order)VALUES(?,?,?,?,?,?,?,?,?)",$a);
|
||||
|
||||
/* ── Events ── */
|
||||
$adminId=(int)qval("SELECT id FROM users WHERE username='administrator'");
|
||||
foreach ([
|
||||
['Mineral County Fair','Annual county fair featuring livestock shows, carnival rides, food vendors, live entertainment, and the best of Mineral County agriculture.','Mineral County Fairgrounds','Fort Ashby, WV','2025-08-12','9:00 AM','2025-08-16','10:00 PM','Admission varies','mineralcountyfair.org','','','304-788-0000',$adminId,'approved',1],
|
||||
['Keyser Christmas Parade & Tree Lighting','Annual holiday parade through downtown Keyser with floats, marching bands, Santa Claus, and tree lighting.','Downtown Main Street','Keyser, WV 26726','2025-12-06','5:00 PM','2025-12-06','7:00 PM','Free','cityofkeyser.com','','','304-788-0222',$adminId,'approved',1],
|
||||
['PSC Catamount Athletics','Support the WVU Potomac State Catamounts at home athletic events throughout the semester.','Potomac State College','101 Fort Ave., Keyser','2025-09-01','Varies','2025-11-30','Varies','Free–$5','potomacstatecollege.edu','','','304-788-6800',$adminId,'approved',0],
|
||||
['North Branch Kayak Adventure Series','Guided and recreational kayaking on the North Branch Potomac every Saturday through October.','North Branch Ventures','101 Armstrong St., Keyser','2025-05-01','8:00 AM','2025-10-31','4:00 PM','$25–$45','','','','304-790-7125',$adminId,'approved',0],
|
||||
] as $ev) qrun("INSERT INTO events(title,description,venue,address,event_date,event_time,end_date,end_time,cost,website,contact_name,contact_email,contact_phone,submitted_by,status,is_featured)VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)",$ev);
|
||||
}
|
||||
Reference in New Issue
Block a user