13 Commits

Author SHA1 Message Date
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 <ContactSplit
tag="Find Us" tag="Find Us"
title="Visit Our Location" 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" tagAnimation="slide-up"
background={{ variant: "plain" }} background={{ variant: "plain" }}
useInvertedBackground={false} useInvertedBackground={false}
imageSrc="http://img.b2bpic.net/free-vector/terrain-big-data-visualization_1217-1746.jpg" imageSrc="https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3Am2LJhLLWUokyhthLvKyFV0QpK/uploaded-1773513566288-bhpqbpbr.png"
imageAlt="Restaurant location map" imageAlt="Mariscos Mi Tierra restaurant exterior"
mediaAnimation="opacity" mediaAnimation="opacity"
mediaPosition="right" mediaPosition="right"
inputPlaceholder="Enter your email"
buttonText="Get Directions" buttonText="Get Directions"
containerClassName="py-16 md:py-24" containerClassName="py-16 md:py-24"
titleClassName="text-4xl md:text-5xl font-extrabold text-foreground" titleClassName="text-4xl md:text-5xl font-extrabold text-foreground"
@@ -197,55 +196,94 @@ export default function LandingPage() {
</div> </div>
<div id="testimonials" data-section="testimonials"> <div id="testimonials" data-section="testimonials">
<TestimonialCardSixteen <div className="w-full bg-background/50 py-16 md:py-24">
title="What Our Customers Say" <div className="max-w-6xl mx-auto px-4">
description="Hear from families and friends who have experienced our authentic Mexican seafood" <div className="mb-12">
tag="Customer Reviews" <p className="text-primary-cta font-semibold mb-2">Menu Gallery</p>
tagAnimation="slide-up" <h2 className="text-4xl md:text-5xl font-extrabold text-foreground mb-4">Our Menu</h2>
testimonials={[ <p className="text-lg text-foreground/70">Browse our complete menu of authentic Mexican seafood dishes</p>
{ </div>
id: "testimonial-1", name: "Maria Rodriguez", role: "Family Visit", company: "Spokane Valley", rating: 5, <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
imageSrc: "http://img.b2bpic.net/free-photo/beautiful-woman-cafe_273609-12690.jpg", imageAlt: "Maria Rodriguez" {[
}, {
{ 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: "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: "menu-2", src: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3Am2LJhLLWUokyhthLvKyFV0QpK/uploaded-1773513245125-z5zcdzr7.jpg", alt: "Menu Page 2"
{ },
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: "menu-3", src: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3Am2LJhLLWUokyhthLvKyFV0QpK/uploaded-1773513245125-lmmbhlch.jpg", alt: "Menu Page 3"
}, },
{ {
id: "testimonial-4", name: "Miguel Santos", role: "Weekly Visitor", company: "Spokane Valley Resident", rating: 5, id: "menu-4", src: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3Am2LJhLLWUokyhthLvKyFV0QpK/uploaded-1773513245125-gdotl1bc.jpg", alt: "Menu Page 4"
imageSrc: "http://img.b2bpic.net/free-photo/group-friends-having-lunch-together-restaurant_23-2150520106.jpg", imageAlt: "Miguel Santos" }
}, ].map((menu) => (
{ <div
id: "testimonial-5", name: "Rosa Hernandez", role: "Event Host", company: "Community Organizer", rating: 5, key={menu.id}
imageSrc: "http://img.b2bpic.net/free-photo/adults-enjoying-mexican-food_23-2149663840.jpg", imageAlt: "Rosa Hernandez" 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}`);
id: "testimonial-6", name: "Diego Flores", role: "Seafood Lover", company: "Restaurant Critic", rating: 5, if (modal) modal.classList.remove('hidden');
imageSrc: "http://img.b2bpic.net/free-photo/portrait-beautiful-afro-american-woman_23-2148332136.jpg", imageAlt: "Diego Flores" }}
} >
]} <img
kpiItems={[ src={menu.src}
{ value: "4.9/5", label: "Average Rating" }, alt={menu.alt}
{ value: "500+", label: "Happy Customers" }, className="w-full h-auto object-cover group-hover:scale-105 transition-transform duration-300"
{ value: "15 Years", label: "Community Trust" } />
]} <div className="absolute inset-0 bg-black/0 group-hover:bg-black/30 transition-all duration-300 flex items-center justify-center">
animationType="slide-up" <span className="text-white font-semibold text-lg opacity-0 group-hover:opacity-100 transition-opacity duration-300">
textboxLayout="default" Click to Enlarge
useInvertedBackground={true} </span>
containerClassName="py-16 md:py-24" </div>
textBoxTitleClassName="text-4xl md:text-5xl font-extrabold text-foreground" </div>
textBoxDescriptionClassName="text-lg text-foreground/70 mt-2" ))}
textBoxTagClassName="text-primary-cta font-semibold" </div>
cardClassName="p-6 rounded-xl" {/* Modal for enlarged images */}
ratingClassName="text-primary-cta font-bold" {[
nameClassName="text-lg font-bold text-foreground mt-3" {
roleClassName="text-sm text-foreground/70" id: "menu-1", src: "https://webuild-dev.s3.eu-north-1.amazonaws.com/users/user_3Am2LJhLLWUokyhthLvKyFV0QpK/uploaded-1773513245125-nxkivr1l.jpg", alt: "Menu Page 1"
companyClassName="text-xs text-foreground/50 mt-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>
<div id="footer" data-section="footer"> <div id="footer" data-section="footer">
@@ -279,7 +317,7 @@ export default function LandingPage() {
items: [ items: [
{ label: "Privacy Policy", href: "#" }, { label: "Privacy Policy", href: "#" },
{ label: "Terms of Service", href: "#" }, { label: "Terms of Service", href: "#" },
{ label: "Contact", href: "tel:(509) 928-0513" } { label: "Admin", href: "/admin" }
] ]
} }
]} ]}

View File

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