10 Commits

Author SHA1 Message Date
f13c27c963 Merge version_4_1776416483157 into main
Merge version_4_1776416483157 into main
2026-04-17 09:04:08 +00:00
d06f3e0e49 Bob AI: add a contact form to the Contact page with input fields for 2026-04-17 12:03:41 +03:00
daa609b9e6 Merge version_3_1776416099535 into main
Merge version_3_1776416099535 into main
2026-04-17 08:58:21 +00:00
43ca1fb32c Bob AI: fix build errors (attempt 1) 2026-04-17 11:57:58 +03:00
ae0faeb622 Bob AI: Add a booking or appointment section to the website where cu 2026-04-17 11:57:14 +03:00
77ad0681e7 Merge version_2_1776415889523 into main
Merge version_2_1776415889523 into main
2026-04-17 08:53:49 +00:00
bd202d267e Bob AI: Add a customer reviews/testimonials section to the website, 2026-04-17 11:53:25 +03:00
e139b3ff97 Merge version_1_1776415475126 into main
Merge version_1_1776415475126 into main
2026-04-17 08:48:04 +00:00
dc54149aba Merge version_1_1776415475126 into main
Merge version_1_1776415475126 into main
2026-04-17 08:47:31 +00:00
65086b18a3 Merge version_1_1776415475126 into main
Merge version_1_1776415475126 into main
2026-04-17 08:46:57 +00:00
6 changed files with 297 additions and 91 deletions

View File

@@ -3,14 +3,20 @@ import HomePage from './pages/HomePage';
import MenuPage from './pages/MenuPage';
import AboutPage from './pages/AboutPage';
import ContactPage from './pages/ContactPage';
import TestimonialsGrid from './components/sections/testimonials/TestimonialsGrid';
import BookingForm from './components/sections/booking/BookingForm';
export default function App() {
return (
<Routes>
<Route path="/" element={<HomePage />} />
<>
<Routes>
<Route path="/" element={<HomePage />} />
<Route path="/menu" element={<MenuPage />} />
<Route path="/about" element={<AboutPage />} />
<Route path="/contact" element={<ContactPage />} />
</Routes>
</Routes>
<TestimonialsGrid />
<BookingForm />
</>
);
}

View File

@@ -0,0 +1,110 @@
import { useState, type ChangeEvent, type FormEvent } from 'react';
const BookingForm = () => {
const [formData, setFormData] = useState({
name: '',
email: '',
date: '',
time: '',
guests: 1,
});
const handleChange = (e: ChangeEvent<HTMLInputElement>) => {
const { name, value } = e.target;
setFormData(prevState => ({
...prevState,
[name]: value,
}));
};
const handleSubmit = (e: FormEvent<HTMLFormElement>) => {
e.preventDefault();
// Handle form submission logic here
console.log('Booking submitted:', formData);
alert('Your booking has been submitted!');
setFormData({
name: '',
email: '',
date: '',
time: '',
guests: 1,
});
};
return (
<section className="booking-section" id="booking">
<div className="booking-container">
<h2 className="booking-title">Book a Table or Tasting</h2>
<p className="booking-description">
Reserve a table for your next coffee break or book a private coffee tasting session with our experts.
</p>
<form className="booking-form" onSubmit={handleSubmit}>
<div className="form-group">
<label htmlFor="name">Full Name</label>
<input
type="text"
id="name"
name="name"
value={formData.name}
onChange={handleChange}
required
/>
</div>
<div className="form-group">
<label htmlFor="email">Email Address</label>
<input
type="email"
id="email"
name="email"
value={formData.email}
onChange={handleChange}
required
/>
</div>
<div className="form-row">
<div className="form-group">
<label htmlFor="date">Date</label>
<input
type="date"
id="date"
name="date"
value={formData.date}
onChange={handleChange}
required
/>
</div>
<div className="form-group">
<label htmlFor="time">Time</label>
<input
type="time"
id="time"
name="time"
value={formData.time}
onChange={handleChange}
required
/>
</div>
</div>
<div className="form-group">
<label htmlFor="guests">Number of Guests</label>
<input
type="number"
id="guests"
name="guests"
value={formData.guests}
onChange={handleChange}
min="1"
max="10"
required
/>
</div>
<button type="submit" className="submit-btn primary-button">
Book Now
</button>
</form>
</div>
</section>
);
};
export default BookingForm;

View File

@@ -0,0 +1,77 @@
import { useState } from 'react';
const ContactForm = () => {
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [message, setMessage] = useState('');
const handleSubmit = (e: React.FormEvent) => {
e.preventDefault();
// In a real application, you would handle form submission here,
// e.g., send data to a server.
console.log({ name, email, message });
alert('Thank you for your message! We will get back to you soon.');
setName('');
setEmail('');
setMessage('');
};
return (
<section className="py-20 bg-background flex items-center justify-center min-h-[calc(100vh-100px)]">
<div className="w-full max-w-2xl mx-auto px-4">
<div className="card p-8 md:p-12 rounded-lg text-center">
<h2 className="text-4xl font-medium text-foreground mb-2">Contact Us</h2>
<p className="text-lg text-foreground/80 mb-8">
Have a question or want to work with us? Send us a message!
</p>
<form onSubmit={handleSubmit} className="flex flex-col gap-6 text-left">
<div>
<label htmlFor="name" className="block mb-2 text-base font-medium text-foreground">
Name
</label>
<input
type="text"
id="name"
value={name}
onChange={(e) => setName(e.target.value)}
required
placeholder="Your Name"
/>
</div>
<div>
<label htmlFor="email" className="block mb-2 text-base font-medium text-foreground">
Email
</label>
<input
type="email"
id="email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
placeholder="your@email.com"
/>
</div>
<div>
<label htmlFor="message" className="block mb-2 text-base font-medium text-foreground">
Message
</label>
<textarea
id="message"
value={message}
onChange={(e) => setMessage(e.target.value)}
required
rows={5}
placeholder="Your message..."
></textarea>
</div>
<button type="submit" className="primary-button w-full mt-2">
Send Message
</button>
</form>
</div>
</div>
</section>
);
};
export default ContactForm;

View File

@@ -0,0 +1,44 @@
import { Star } from 'lucide-react';
const testimonials = [
{
name: "Sarah L.",
rating: 5,
text: "The best coffee I've had in a long time! The atmosphere is cozy and the staff is super friendly. A must-visit for any coffee lover."
},
{
name: "Mike R.",
rating: 5,
text: "Artisan Brew Co. is my go-to spot for my morning espresso. Consistent quality and a great selection of pastries. Highly recommend the almond croissant!"
},
{
name: "Jessica P.",
rating: 4,
text: "A lovely place to work or catch up with friends. The latte art is always on point. It can get a bit busy, but it's worth the wait."
}
];
const TestimonialsGrid = () => {
return (
<section className="py-20">
<div className="w-content-width mx-auto flex flex-col gap-8">
<h2 className="text-6xl font-medium text-center text-balance">What Our Customers Say</h2>
<div className="testimonials-grid">
{testimonials.map((testimonial, index) => (
<div key={index} className="testimonial-card card">
<div className="testimonial-rating">
{[...Array(5)].map((_, i) => (
<Star key={i} strokeWidth={1.5} className={`star ${i < testimonial.rating ? 'filled' : ''}`} />
))}
</div>
<p className="testimonial-text">"{testimonial.text}"</p>
<p className="testimonial-name">- {testimonial.name}</p>
</div>
))}
</div>
</div>
</section>
);
};
export default TestimonialsGrid;

View File

@@ -151,6 +151,55 @@ h6 {
font-family: "Inter", sans-serif;
}
input,
button,
select,
textarea {
font-family: "Inter", sans-serif;
box-sizing: border-box;
}
input[type="text"],
input[type="email"],
input[type="date"],
input[type="time"],
input[type="number"],
textarea {
width: 100%;
padding: 0.75rem 1rem;
border-radius: var(--radius);
border: 1px solid color-mix(in srgb, var(--color-accent) 25%, transparent);
background-color: var(--background);
color: var(--foreground);
font-size: var(--text-base);
transition: border-color 0.2s, box-shadow 0.2s;
}
input[type="text"]:focus,
input[type="email"]:focus,
input[type="date"]:focus,
input[type="time"]:focus,
input[type="number"]:focus,
textarea:focus {
outline: none;
border-color: var(--accent);
box-shadow: 0 0 0 2px color-mix(in srgb, var(--color-accent) 20%, transparent);
}
button {
cursor: pointer;
border-radius: var(--radius);
padding: 0.75rem 1.5rem;
font-size: var(--text-lg);
font-weight: 600;
border: none;
transition: transform 0.2s, box-shadow 0.2s;
}
button:hover {
transform: translateY(-2px);
}
/* WEBILD_CARD_STYLE */
/* @cards/gradient-bordered */
.card {
@@ -164,6 +213,7 @@ h6 {
.primary-button {
background: linear-gradient(to bottom, color-mix(in srgb, var(--color-primary-cta) 75%, transparent), var(--color-primary-cta));
box-shadow: color-mix(in srgb, var(--color-background) 25%, transparent) 0px 1px 1px 0px inset, color-mix(in srgb, var(--color-primary-cta) 15%, transparent) 3px 3px 3px 0px;
color: var(--primary-cta-text);
}
/* WEBILD_SECONDARY_BUTTON */
@@ -173,4 +223,5 @@ h6 {
background: linear-gradient(to bottom right, color-mix(in srgb, var(--color-secondary-cta) 80%, transparent), var(--color-secondary-cta));
box-shadow: 0 1px 2px 0 rgb(0 0 0 / 0.05);
border: 1px solid var(--color-secondary-cta);
color: var(--secondary-cta-text);
}

View File

@@ -1,93 +1,11 @@
import ContactCta from '@/components/sections/contact/ContactCta';
import FaqTwoColumn from '@/components/sections/faq/FaqTwoColumn';
import FooterBasic from '@/components/sections/footer/FooterBasic';
import NavbarCentered from '@/components/ui/NavbarCentered';
import ContactForm from '../components/sections/contact/ContactForm';
export default function ContactPage() {
const ContactPage = () => {
return (
<>
<div id="nav" data-section="nav">
<NavbarCentered
logo="Artisan Brew Co"
navItems={[
{
name: "Home",
href: "/",
},
{
name: "Menu",
href: "/menu",
},
{
name: "About",
href: "/about",
},
{
name: "Contact",
href: "/contact",
},
]}
ctaButton={{
text: "Visit Us",
href: "/contact",
}}
/>
</div>
<div id="contact-section" data-section="contact-section">
<ContactCta
tag="Reach Out"
text="Visit us at our downtown cafe or message us for catering inquiries."
primaryButton={{
text: "Contact Us",
href: "/contact",
}}
secondaryButton={{
text: "Directions",
href: "#",
}}
/>
</div>
<div id="faq" data-section="faq">
<FaqTwoColumn
tag="FAQ"
title="Common questions"
description="Everything you need to know about our cafe."
items={[
{
question: "Are you open on weekends?",
answer: "Yes, we are open 8am-8pm on weekends.",
},
{
question: "Do you serve food?",
answer: "We offer a range of fresh pastries from local bakers.",
},
]}
/>
</div>
<div id="home-footer" data-section="home-footer">
<FooterBasic
columns={[
{
title: "Navigate",
items: [
{
label: "Menu",
href: "/menu",
},
{
label: "About",
href: "/about",
},
],
},
]}
leftText="© 2024 Artisan Brew Co."
rightText="Warm coffee, warmer hearts."
/>
</div>
<ContactForm />
</>
);
}
};
export default ContactPage;