14 Commits

Author SHA1 Message Date
74fa8a41a1 Merge version_4 into main
Merge version_4 into main
2026-03-14 18:39:46 +00:00
66c6911dec Update src/app/page.tsx 2026-03-14 18:39:42 +00:00
90361a42ae Merge version_3 into main
Merge version_3 into main
2026-03-14 18:34:36 +00:00
ea79c252a3 Update src/app/page.tsx 2026-03-14 18:34:31 +00:00
0088542b7f Merge version_2 into main
Merge version_2 into main
2026-03-14 18:30:43 +00:00
df3036a14b Update src/app/admin/page.tsx 2026-03-14 18:30:39 +00:00
1e9b6b4300 Merge version_2 into main
Merge version_2 into main
2026-03-14 18:30:15 +00:00
aefd386fa9 Update src/app/admin/page.tsx 2026-03-14 18:30:10 +00:00
bb10a104d4 Merge version_2 into main
Merge version_2 into main
2026-03-14 18:29:48 +00:00
c429eefdfe Update src/app/styles/variables.css 2026-03-14 18:29:44 +00:00
57fdfdb51f Update src/app/page.tsx 2026-03-14 18:29:43 +00:00
3d497284d3 Add src/app/admin/page.tsx 2026-03-14 18:29:43 +00:00
a7fba8c266 Merge version_1 into main
Merge version_1 into main
2026-03-14 18:26:10 +00:00
37206aaf0e Merge version_1 into main
Merge version_1 into main
2026-03-14 18:20:51 +00:00
3 changed files with 434 additions and 64 deletions

332
src/app/admin/page.tsx Normal file
View File

@@ -0,0 +1,332 @@
"use client";
import { useState } from "react";
import { ThemeProvider } from "@/providers/themeProvider/ThemeProvider";
import NavbarStyleCentered from '@/components/navbar/NavbarStyleCentered/NavbarStyleCentered';
import FooterLogoEmphasis from '@/components/sections/footer/FooterLogoEmphasis';
import HeroBillboardDashboard from '@/components/sections/hero/HeroBillboardDashboard';
import { Settings, Clock, DollarSign, UtensilsCrossed, LogOut } from 'lucide-react';
export default function AdminPage() {
const [activeTab, setActiveTab] = useState<'hours' | 'prices' | 'menu'>('hours');
const [hours, setHours] = useState({
monday: { open: 'Closed', close: '' },
tuesday: { open: '11:00 AM', close: '9:00 PM' },
wednesday: { open: '11:00 AM', close: '9:00 PM' },
thursday: { open: '11:00 AM', close: '9:00 PM' },
friday: { open: '11:00 AM', close: '9:30 PM' },
saturday: { open: '9:00 AM', close: '9:00 PM' },
sunday: { open: '11:00 AM', close: '9:00 PM' },
});
const [prices, setPrices] = useState([
{ id: 'camarones-diabla', name: 'Camarones a la Diabla', price: '24.00' },
{ id: 'ceviche-pina', name: 'Ceviche en su Piña', price: '28.00' },
{ id: 'molcajete-mixto', name: 'Molcajete Mixto', price: '38.99' },
{ id: 'tacos-camarones', name: 'Tacos de Camarón', price: '20.00' },
]);
const [menuItems, setMenuItems] = useState([
{ id: '1', name: 'Camarones a la Diabla', description: 'Spicy deviled shrimp', available: true },
{ id: '2', name: 'Ceviche en su Piña', description: 'Ceviche served in pineapple', available: true },
{ id: '3', name: 'Molcajete Mixto', description: 'Mixed molcajete stone bowl', available: true },
{ id: '4', name: 'Tacos de Camarón', description: 'Fresh shrimp tacos', available: true },
]);
const [newItem, setNewItem] = useState({ name: '', description: '' });
const handleHourChange = (day: string, field: 'open' | 'close', value: string) => {
setHours(prev => ({
...prev,
[day]: { ...prev[day as keyof typeof hours], [field]: value }
}));
};
const handlePriceChange = (id: string, price: string) => {
setPrices(prev => prev.map(p => p.id === id ? { ...p, price } : p));
};
const handleToggleMenuItem = (id: string) => {
setMenuItems(prev => prev.map(item => item.id === id ? { ...item, available: !item.available } : item));
};
const handleAddMenuItem = () => {
if (newItem.name && newItem.description) {
setMenuItems(prev => [...prev, { id: Date.now().toString(), name: newItem.name, description: newItem.description, available: true }]);
setNewItem({ name: '', description: '' });
}
};
const dashboardData = {
title: 'Admin Dashboard',
stats: [
{ label: 'Active Orders', value: '12', icon: Settings },
{ label: 'Menu Items', value: String(menuItems.length), icon: UtensilsCrossed },
{ label: 'Today\'s Revenue', value: '$1,240', icon: DollarSign }
] as [any, any, any],
logoIcon: Settings,
sidebarItems: [
{ label: 'Hours', icon: Clock, active: activeTab === 'hours' },
{ label: 'Prices', icon: DollarSign, active: activeTab === 'prices' },
{ label: 'Menu', icon: UtensilsCrossed, active: activeTab === 'menu' }
],
buttons: [
{ text: 'Save Changes', onClick: () => alert('Changes saved!') },
{ text: 'Preview', onClick: () => alert('Preview mode') }
],
listItems: [
{ title: 'Settings', status: 'active', icon: Settings },
{ title: 'Logout', status: 'active', icon: LogOut }
],
imageSrc: 'https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3Am2LJhLLWUokyhthLvKyFV0QpK/uploaded-1773512918447-hg7wldhe.png',
searchPlaceholder: 'Search orders...',
chartTitle: 'Weekly Revenue',
chartData: [
{ day: 'Mon', value: 450 },
{ day: 'Tue', value: 520 },
{ day: 'Wed', value: 480 },
{ day: 'Thu', value: 610 },
{ day: 'Fri', value: 890 },
{ day: 'Sat', value: 1200 },
{ day: 'Sun', value: 950 }
],
listTitle: 'Quick Actions'
};
return (
<ThemeProvider
defaultButtonVariant="elastic-effect"
defaultTextAnimation="entrance-slide"
borderRadius="pill"
contentWidth="small"
sizing="largeSizeMediumTitles"
background="none"
cardStyle="gradient-mesh"
primaryButtonStyle="flat"
secondaryButtonStyle="solid"
headingFontWeight="extrabold"
>
<div id="nav" data-section="nav">
<NavbarStyleCentered
brandName="Mariscos Mi Tierra - Admin"
navItems={[
{ name: "Dashboard", id: "dashboard" },
{ name: "Hours", id: "admin-hours" },
{ name: "Menu", id: "admin" },
{ name: "Prices", id: "admin-prices" }
]}
button={{ text: "Logout", href: "/" }}
/>
</div>
<div id="hero" data-section="hero">
<HeroBillboardDashboard
title="Restaurant Management"
description="Manage your restaurant's hours, prices, and menu items from one centralized dashboard."
background={{ variant: "plain" }}
dashboard={dashboardData}
/>
</div>
<div className="max-w-6xl mx-auto px-4 py-16">
<div className="flex gap-8">
{/* Sidebar Navigation */}
<div className="w-48 flex flex-col gap-4">
<button
onClick={() => setActiveTab('hours')}
className={`px-6 py-3 rounded-lg font-semibold transition-all ${
activeTab === 'hours'
? 'bg-primary-cta text-white'
: 'bg-card text-foreground hover:bg-card/80'
}`}
>
<Clock className="inline mr-2 w-4 h-4" />
Operating Hours
</button>
<button
onClick={() => setActiveTab('prices')}
className={`px-6 py-3 rounded-lg font-semibold transition-all ${
activeTab === 'prices'
? 'bg-primary-cta text-white'
: 'bg-card text-foreground hover:bg-card/80'
}`}
>
<DollarSign className="inline mr-2 w-4 h-4" />
Prices
</button>
<button
onClick={() => setActiveTab('menu')}
className={`px-6 py-3 rounded-lg font-semibold transition-all ${
activeTab === 'menu'
? 'bg-primary-cta text-white'
: 'bg-card text-foreground hover:bg-card/80'
}`}
>
<UtensilsCrossed className="inline mr-2 w-4 h-4" />
Menu Items
</button>
</div>
{/* Main Content */}
<div className="flex-1">
{/* Operating Hours Tab */}
{activeTab === 'hours' && (
<div className="bg-card p-8 rounded-xl">
<h2 className="text-3xl font-extrabold text-foreground mb-6">Operating Hours</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{Object.entries(hours).map(([day, times]) => (
<div key={day} className="flex flex-col gap-3">
<label className="text-lg font-semibold text-foreground capitalize">{day}</label>
{day === 'monday' && times.open === 'Closed' ? (
<div className="text-foreground/70 font-semibold">Closed</div>
) : (
<div className="flex gap-3">
<input
type="text"
value={times.open}
onChange={(e) => handleHourChange(day, 'open', e.target.value)}
placeholder="Opening time"
className="flex-1 px-4 py-2 bg-background border border-foreground/20 rounded-lg text-foreground"
/>
<input
type="text"
value={times.close}
onChange={(e) => handleHourChange(day, 'close', e.target.value)}
placeholder="Closing time"
className="flex-1 px-4 py-2 bg-background border border-foreground/20 rounded-lg text-foreground"
/>
</div>
)}
</div>
))}
</div>
<button className="mt-8 px-8 py-3 bg-primary-cta text-white font-semibold rounded-lg hover:opacity-90 transition-all">
Save Hours
</button>
</div>
)}
{/* Prices Tab */}
{activeTab === 'prices' && (
<div className="bg-card p-8 rounded-xl">
<h2 className="text-3xl font-extrabold text-foreground mb-6">Menu Prices</h2>
<div className="space-y-4">
{prices.map((item) => (
<div key={item.id} className="flex items-center gap-4 p-4 bg-background rounded-lg">
<div className="flex-1">
<p className="font-semibold text-foreground">{item.name}</p>
</div>
<div className="flex items-center gap-2">
<span className="text-foreground/70">$</span>
<input
type="number"
step="0.01"
value={item.price}
onChange={(e) => handlePriceChange(item.id, e.target.value)}
className="w-24 px-3 py-2 bg-card border border-foreground/20 rounded-lg text-foreground"
/>
</div>
</div>
))}
</div>
<button className="mt-8 px-8 py-3 bg-primary-cta text-white font-semibold rounded-lg hover:opacity-90 transition-all">
Save Prices
</button>
</div>
)}
{/* Menu Items Tab */}
{activeTab === 'menu' && (
<div className="bg-card p-8 rounded-xl">
<h2 className="text-3xl font-extrabold text-foreground mb-6">Menu Management</h2>
{/* Add New Item */}
<div className="mb-8 p-6 bg-background rounded-lg border border-foreground/10">
<h3 className="text-xl font-semibold text-foreground mb-4">Add New Item</h3>
<div className="flex flex-col gap-4">
<input
type="text"
value={newItem.name}
onChange={(e) => setNewItem({ ...newItem, name: e.target.value })}
placeholder="Item name"
className="px-4 py-2 bg-card border border-foreground/20 rounded-lg text-foreground"
/>
<input
type="text"
value={newItem.description}
onChange={(e) => setNewItem({ ...newItem, description: e.target.value })}
placeholder="Item description"
className="px-4 py-2 bg-card border border-foreground/20 rounded-lg text-foreground"
/>
<button
onClick={handleAddMenuItem}
className="px-6 py-2 bg-primary-cta text-white font-semibold rounded-lg hover:opacity-90 transition-all"
>
Add Item
</button>
</div>
</div>
{/* Menu Items List */}
<div className="space-y-3">
{menuItems.map((item) => (
<div key={item.id} className="flex items-center justify-between p-4 bg-background rounded-lg">
<div>
<p className="font-semibold text-foreground">{item.name}</p>
<p className="text-sm text-foreground/70">{item.description}</p>
</div>
<button
onClick={() => handleToggleMenuItem(item.id)}
className={`px-4 py-2 rounded-lg font-semibold transition-all ${
item.available
? 'bg-green-500/20 text-green-600 hover:bg-green-500/30'
: 'bg-red-500/20 text-red-600 hover:bg-red-500/30'
}`}
>
{item.available ? 'Available' : 'Unavailable'}
</button>
</div>
))}
</div>
<button className="mt-8 px-8 py-3 bg-primary-cta text-white font-semibold rounded-lg hover:opacity-90 transition-all">
Save Menu Changes
</button>
</div>
)}
</div>
</div>
</div>
<div id="footer" data-section="footer">
<FooterLogoEmphasis
logoText="Mariscos Mi Tierra Admin"
columns={[
{
items: [
{ label: "Dashboard", href: "/admin" },
{ label: "Settings", href: "#" },
]
},
{
items: [
{ label: "Back to Main", href: "/" },
{ label: "Help", href: "#" },
]
},
{
items: [
{ label: "Terms", href: "#" },
{ label: "Privacy", href: "#" },
]
},
{
items: [
{ label: "Logout", href: "/" },
]
}
]}
/>
</div>
</ThemeProvider>
);
}

View File

@@ -179,15 +179,14 @@ export default function LandingPage() {
<ContactSplit
tag="Find Us"
title="Visit Our Location"
description="Located in the heart of Spokane Valley, we're easy to find and ready to serve you. Use the map below to get directions or call us ahead to place your order."
description="Located at 17005 E Sprague Ave, Spokane Valley, WA 99037, we're easy to find and ready to serve you. Come visit us for authentic Mexican seafood in a welcoming family atmosphere."
tagAnimation="slide-up"
background={{ variant: "plain" }}
useInvertedBackground={false}
imageSrc="http://img.b2bpic.net/free-vector/terrain-big-data-visualization_1217-1746.jpg"
imageAlt="Restaurant location map"
imageSrc="https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3Am2LJhLLWUokyhthLvKyFV0QpK/uploaded-1773513566288-bhpqbpbr.png"
imageAlt="Mariscos Mi Tierra restaurant exterior"
mediaAnimation="opacity"
mediaPosition="right"
inputPlaceholder="Enter your email"
buttonText="Get Directions"
containerClassName="py-16 md:py-24"
titleClassName="text-4xl md:text-5xl font-extrabold text-foreground"
@@ -197,55 +196,94 @@ export default function LandingPage() {
</div>
<div id="testimonials" data-section="testimonials">
<TestimonialCardSixteen
title="What Our Customers Say"
description="Hear from families and friends who have experienced our authentic Mexican seafood"
tag="Customer Reviews"
tagAnimation="slide-up"
testimonials={[
{
id: "testimonial-1", name: "Maria Rodriguez", role: "Family Visit", company: "Spokane Valley", rating: 5,
imageSrc: "http://img.b2bpic.net/free-photo/beautiful-woman-cafe_273609-12690.jpg", imageAlt: "Maria Rodriguez"
},
{
id: "testimonial-2", name: "Juan Martinez", role: "Regular Customer", company: "Local Business Owner", rating: 5,
imageSrc: "http://img.b2bpic.net/free-photo/life-after-covid-freedom-concept_23-2149068470.jpg", imageAlt: "Juan Martinez"
},
{
id: "testimonial-3", name: "Carmen Delgado", role: "Food Enthusiast", company: "Community Member", rating: 5,
imageSrc: "http://img.b2bpic.net/free-photo/young-woman-cafe-dines-traditional-shakshuka-ayran_169016-16512.jpg", imageAlt: "Carmen Delgado"
},
{
id: "testimonial-4", name: "Miguel Santos", role: "Weekly Visitor", company: "Spokane Valley Resident", rating: 5,
imageSrc: "http://img.b2bpic.net/free-photo/group-friends-having-lunch-together-restaurant_23-2150520106.jpg", imageAlt: "Miguel Santos"
},
{
id: "testimonial-5", name: "Rosa Hernandez", role: "Event Host", company: "Community Organizer", rating: 5,
imageSrc: "http://img.b2bpic.net/free-photo/adults-enjoying-mexican-food_23-2149663840.jpg", imageAlt: "Rosa Hernandez"
},
{
id: "testimonial-6", name: "Diego Flores", role: "Seafood Lover", company: "Restaurant Critic", rating: 5,
imageSrc: "http://img.b2bpic.net/free-photo/portrait-beautiful-afro-american-woman_23-2148332136.jpg", imageAlt: "Diego Flores"
}
]}
kpiItems={[
{ value: "4.9/5", label: "Average Rating" },
{ value: "500+", label: "Happy Customers" },
{ value: "15 Years", label: "Community Trust" }
]}
animationType="slide-up"
textboxLayout="default"
useInvertedBackground={true}
containerClassName="py-16 md:py-24"
textBoxTitleClassName="text-4xl md:text-5xl font-extrabold text-foreground"
textBoxDescriptionClassName="text-lg text-foreground/70 mt-2"
textBoxTagClassName="text-primary-cta font-semibold"
cardClassName="p-6 rounded-xl"
ratingClassName="text-primary-cta font-bold"
nameClassName="text-lg font-bold text-foreground mt-3"
roleClassName="text-sm text-foreground/70"
companyClassName="text-xs text-foreground/50 mt-1"
/>
<div className="w-full bg-background/50 py-16 md:py-24">
<div className="max-w-6xl mx-auto px-4">
<div className="mb-12">
<p className="text-primary-cta font-semibold mb-2">Menu Gallery</p>
<h2 className="text-4xl md:text-5xl font-extrabold text-foreground mb-4">Our Menu</h2>
<p className="text-lg text-foreground/70">Browse our complete menu of authentic Mexican seafood dishes</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
{[
{
id: "menu-1", src: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3Am2LJhLLWUokyhthLvKyFV0QpK/uploaded-1773513245125-nxkivr1l.jpg", alt: "Menu Page 1"
},
{
id: "menu-2", src: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3Am2LJhLLWUokyhthLvKyFV0QpK/uploaded-1773513245125-z5zcdzr7.jpg", alt: "Menu Page 2"
},
{
id: "menu-3", src: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3Am2LJhLLWUokyhthLvKyFV0QpK/uploaded-1773513245125-lmmbhlch.jpg", alt: "Menu Page 3"
},
{
id: "menu-4", src: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3Am2LJhLLWUokyhthLvKyFV0QpK/uploaded-1773513245125-gdotl1bc.jpg", alt: "Menu Page 4"
}
].map((menu) => (
<div
key={menu.id}
className="relative group cursor-pointer overflow-hidden rounded-xl shadow-lg hover:shadow-xl transition-all duration-300"
onClick={() => {
const modal = document.getElementById(`modal-${menu.id}`);
if (modal) modal.classList.remove('hidden');
}}
>
<img
src={menu.src}
alt={menu.alt}
className="w-full h-auto object-cover group-hover:scale-105 transition-transform duration-300"
/>
<div className="absolute inset-0 bg-black/0 group-hover:bg-black/30 transition-all duration-300 flex items-center justify-center">
<span className="text-white font-semibold text-lg opacity-0 group-hover:opacity-100 transition-opacity duration-300">
Click to Enlarge
</span>
</div>
</div>
))}
</div>
{/* Modal for enlarged images */}
{[
{
id: "menu-1", src: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3Am2LJhLLWUokyhthLvKyFV0QpK/uploaded-1773513245125-nxkivr1l.jpg", alt: "Menu Page 1"
},
{
id: "menu-2", src: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3Am2LJhLLWUokyhthLvKyFV0QpK/uploaded-1773513245125-z5zcdzr7.jpg", alt: "Menu Page 2"
},
{
id: "menu-3", src: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3Am2LJhLLWUokyhthLvKyFV0QpK/uploaded-1773513245125-lmmbhlch.jpg", alt: "Menu Page 3"
},
{
id: "menu-4", src: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3Am2LJhLLWUokyhthLvKyFV0QpK/uploaded-1773513245125-gdotl1bc.jpg", alt: "Menu Page 4"
}
].map((menu) => (
<div
key={`modal-${menu.id}`}
id={`modal-${menu.id}`}
className="hidden fixed inset-0 bg-black/80 z-50 flex items-center justify-center p-4"
onClick={(e) => {
if (e.target === e.currentTarget) {
e.currentTarget.classList.add('hidden');
}
}}
>
<div className="relative max-w-4xl max-h-[90vh] w-full">
<img
src={menu.src}
alt={menu.alt}
className="w-full h-auto max-h-[90vh] object-contain"
/>
<button
onClick={() => {
const modal = document.getElementById(`modal-${menu.id}`);
if (modal) modal.classList.add('hidden');
}}
className="absolute top-4 right-4 bg-white text-black rounded-full w-10 h-10 flex items-center justify-center font-bold hover:bg-foreground hover:text-white transition-all"
>
</button>
</div>
</div>
))}
</div>
</div>
</div>
<div id="footer" data-section="footer">
@@ -279,7 +317,7 @@ export default function LandingPage() {
items: [
{ label: "Privacy Policy", href: "#" },
{ label: "Terms of Service", href: "#" },
{ label: "Contact", href: "tel:(509) 928-0513" }
{ label: "Admin", href: "/admin" }
]
}
]}
@@ -291,4 +329,4 @@ export default function LandingPage() {
</div>
</ThemeProvider>
);
}
}

View File

@@ -10,15 +10,15 @@
--accent: #ffffff;
--background-accent: #ffffff; */
--background: #f7f6f7;
--card: #ffffff;
--foreground: #25190c;
--primary-cta: #ff6207;
--primary-cta-text: #f7f6f7;
--secondary-cta: #ffffff;
--secondary-cta-text: #25190c;
--accent: #ffce93;
--background-accent: #e8cfa8;
--background: #e8dcc4;
--card: #f5f0e6;
--foreground: #3d2817;
--primary-cta: #a67c52;
--primary-cta-text: #ffffff;
--secondary-cta: #f5f0e6;
--secondary-cta-text: #3d2817;
--accent: #d4b896;
--background-accent: #c9a876;
/* text sizing - set by ThemeProvider */
/* --text-2xs: clamp(0.465rem, 0.62vw, 0.62rem);