fix: correct image paths for Cloudflare Pages
Update all image references to full public paths. #VERCEL_SKIP Co-authored-by: Jeff Emmett <46964190+Jeff-Emmett@users.noreply.github.com>
This commit is contained in:
parent
3ccf13739a
commit
7277c3d462
|
|
@ -1,27 +1,9 @@
|
|||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
|
||||
# Wrangler
|
||||
.wrangler/
|
||||
|
||||
# dependencies
|
||||
/node_modules
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# next.js
|
||||
/.next/
|
||||
/out/
|
||||
|
||||
# production
|
||||
/build
|
||||
|
||||
# debug
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# env files
|
||||
.env*
|
||||
|
||||
# vercel
|
||||
.vercel
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
next-env.d.ts
|
||||
# Logs
|
||||
*.log
|
||||
|
|
|
|||
165
README.md
165
README.md
|
|
@ -1,30 +1,159 @@
|
|||
# Ebb n Flow website
|
||||
# Ebb'nFlow Therapeutics Website
|
||||
|
||||
*Automatically synced with your [v0.app](https://v0.app) deployments*
|
||||
A static HTML/CSS/JavaScript website for Ebb'nFlow Therapeutics massage therapy practice.
|
||||
|
||||
[](https://vercel.com/jeff-emmetts-projects/v0-ebb-n-flow-website)
|
||||
[](https://v0.app/chat/projects/9u6iKhKeMvy)
|
||||
## 🚨 Current Issue & Fix
|
||||
|
||||
## Overview
|
||||
Your site at https://ebb-n-flow-website.pages.dev/ isn't working because Cloudflare is looking for Next.js files.
|
||||
|
||||
This repository will stay in sync with your deployed chats on [v0.app](https://v0.app).
|
||||
Any changes you make to your deployed app will be automatically pushed to this repository from [v0.app](https://v0.app).
|
||||
### **Quick Fix:**
|
||||
|
||||
## Deployment
|
||||
1. **Delete the current Cloudflare Pages project:**
|
||||
- Go to [Cloudflare Dashboard](https://dash.cloudflare.com/)
|
||||
- Navigate to Pages → ebb-n-flow-website
|
||||
- Settings → Delete project
|
||||
|
||||
Your project is live at:
|
||||
2. **Create a new deployment with ONLY these files:**
|
||||
- `index.html`
|
||||
- `about.html`
|
||||
- `contact.html`
|
||||
- `movement.html`
|
||||
- `what-to-expect.html`
|
||||
- `styles.css`
|
||||
- `script.js`
|
||||
- `_routes.json`
|
||||
- `_headers`
|
||||
- `images/` folder
|
||||
|
||||
**[https://vercel.com/jeff-emmetts-projects/v0-ebb-n-flow-website](https://vercel.com/jeff-emmetts-projects/v0-ebb-n-flow-website)**
|
||||
3. **Upload Method:**
|
||||
- Choose "Upload assets" (not Git integration)
|
||||
- Drag and drop the files listed above
|
||||
- Deploy!
|
||||
|
||||
## Build your app
|
||||
## 📁 Files to Deploy
|
||||
|
||||
Continue building your app on:
|
||||
**Root files:**
|
||||
\`\`\`
|
||||
index.html
|
||||
about.html
|
||||
contact.html
|
||||
movement.html
|
||||
what-to-expect.html
|
||||
styles.css
|
||||
script.js
|
||||
_routes.json
|
||||
_headers
|
||||
\`\`\`
|
||||
|
||||
**[https://v0.app/chat/projects/9u6iKhKeMvy](https://v0.app/chat/projects/9u6iKhKeMvy)**
|
||||
**Images folder:**
|
||||
\`\`\`
|
||||
images/
|
||||
├── logo.jpg
|
||||
├── dahlia-portrait.jpg
|
||||
├── treatment-room.jpg
|
||||
├── reception-area.jpg
|
||||
├── clinic-exterior.jpg
|
||||
├── clinic-entrance.jpg
|
||||
├── yellow-door.jpg
|
||||
├── bioflex-laser.png
|
||||
├── movement-class.png
|
||||
├── olivia-cat.png
|
||||
└── rmt-certification.png
|
||||
\`\`\`
|
||||
|
||||
## How It Works
|
||||
## 🚀 Deployment Options
|
||||
|
||||
1. Create and modify your project using [v0.app](https://v0.app)
|
||||
2. Deploy your chats from the v0 interface
|
||||
3. Changes are automatically pushed to this repository
|
||||
4. Vercel deploys the latest version from this repository
|
||||
### Option 1: Cloudflare Pages (Direct Upload) ⭐ RECOMMENDED
|
||||
|
||||
1. Go to [Cloudflare Pages](https://dash.cloudflare.com/)
|
||||
2. Click "Create a project"
|
||||
3. Select "Upload assets"
|
||||
4. Upload ONLY the files listed above
|
||||
5. Build settings: **LEAVE EMPTY** (no build needed)
|
||||
6. Deploy!
|
||||
|
||||
### Option 2: Wrangler CLI
|
||||
|
||||
\`\`\`bash
|
||||
# Install wrangler
|
||||
npm install -g wrangler
|
||||
|
||||
# Login
|
||||
wrangler login
|
||||
|
||||
# Deploy from project root
|
||||
wrangler pages deploy . --project-name=ebb-n-flow-website
|
||||
\`\`\`
|
||||
|
||||
### Option 3: GitHub Integration
|
||||
|
||||
1. Create a new repository with ONLY the files listed above
|
||||
2. In Cloudflare Pages, connect to Git
|
||||
3. Build settings:
|
||||
- **Build command:** (leave empty)
|
||||
- **Build output directory:** `/`
|
||||
- **Root directory:** `/`
|
||||
|
||||
## 🌐 Local Development
|
||||
|
||||
\`\`\`bash
|
||||
# Option 1: Python
|
||||
python -m http.server 8000
|
||||
|
||||
# Option 2: Node.js
|
||||
npx serve .
|
||||
|
||||
# Option 3: PHP
|
||||
php -S localhost:8000
|
||||
\`\`\`
|
||||
|
||||
Visit: http://localhost:8000
|
||||
|
||||
## ✅ Verification Checklist
|
||||
|
||||
After deploying, verify:
|
||||
- [ ] Homepage loads at https://ebb-n-flow-website.pages.dev/
|
||||
- [ ] All navigation links work
|
||||
- [ ] Images load correctly
|
||||
- [ ] Booking button links to ClinicSense
|
||||
- [ ] Mobile menu works
|
||||
- [ ] All pages (about, contact, movement, what-to-expect) load
|
||||
|
||||
## 🎨 Features
|
||||
|
||||
- Pure HTML/CSS/JavaScript (no frameworks)
|
||||
- Mobile responsive design
|
||||
- Smooth scroll navigation
|
||||
- Modal popups for service info
|
||||
- Collapsible mobile menu
|
||||
- Integrated booking system
|
||||
|
||||
## 📞 Contact Information
|
||||
|
||||
**Ebb'nFlow Therapeutics**
|
||||
- 📍 59 Wellington Street, St. Catharines, ON L2R 5P9
|
||||
- 📞 (289) 969-3219
|
||||
- ✉️ info@ebbnflowtherapeutics.com
|
||||
- 🌐 [Book Online](https://ebbnflowmassage.clinicsense.com)
|
||||
|
||||
## 🐛 Troubleshooting
|
||||
|
||||
**Site shows 404 or doesn't load?**
|
||||
- Make sure you uploaded ALL files (especially index.html)
|
||||
- Check that files are in the root directory, not in a subfolder
|
||||
|
||||
**Images not loading?**
|
||||
- Verify the `images/` folder was uploaded
|
||||
- Check image paths in HTML files (should be `images/filename.jpg`)
|
||||
|
||||
**Styles not working?**
|
||||
- Ensure `styles.css` is in the root directory
|
||||
- Clear browser cache (Ctrl+Shift+R or Cmd+Shift+R)
|
||||
|
||||
**JavaScript not working?**
|
||||
- Make sure `script.js` is in the root directory
|
||||
- Check browser console for errors (F12)
|
||||
|
||||
---
|
||||
|
||||
© 2025 Ebb'nFlow Therapeutics. All rights reserved.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
X-Frame-Options: DENY
|
||||
X-Content-Type-Options: nosniff
|
||||
Referrer-Policy: strict-origin-when-cross-origin
|
||||
Permissions-Policy: geolocation=(), microphone=(), camera=()
|
||||
|
||||
/*.html
|
||||
Content-Type: text/html; charset=utf-8
|
||||
|
||||
/*.css
|
||||
Content-Type: text/css; charset=utf-8
|
||||
Cache-Control: public, max-age=31536000, immutable
|
||||
|
||||
/*.js
|
||||
Content-Type: application/javascript; charset=utf-8
|
||||
Cache-Control: public, max-age=31536000, immutable
|
||||
|
||||
/images/*
|
||||
Cache-Control: public, max-age=31536000, immutable
|
||||
10
about.html
10
about.html
|
|
@ -16,7 +16,7 @@
|
|||
<div class="container">
|
||||
<nav>
|
||||
<a href="/" class="logo">
|
||||
<img src="images/logo.jpg" alt="Ebb'nFlow Therapeutics Logo">
|
||||
<img src="./images/logo.jpg" alt="Ebb'nFlow Therapeutics Logo">
|
||||
<span class="logo-text">Ebb'nFlow <span class="highlight">Therapeutics</span></span>
|
||||
</a>
|
||||
|
||||
|
|
@ -72,7 +72,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="content-image">
|
||||
<img src="images/dahlia-portrait.jpg" alt="Dahlia B. Steinberg, RMT - Founder of Ebb'nFlow Therapeutics">
|
||||
<img src="./images/dahlia-portrait.jpg" alt="Dahlia B. Steinberg, RMT - Founder of Ebb'nFlow Therapeutics">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -135,7 +135,7 @@
|
|||
|
||||
<div class="two-col-grid reverse">
|
||||
<div class="content-image">
|
||||
<img src="images/olivia-cat.png" alt="Olivia, the friendly clinic cat at Ebb'nFlow Therapeutics">
|
||||
<img src="./images/olivia-cat.png" alt="Olivia, the friendly clinic cat at Ebb'nFlow Therapeutics">
|
||||
</div>
|
||||
<div class="content-text">
|
||||
<div class="info-card">
|
||||
|
|
@ -158,7 +158,7 @@
|
|||
<a href="what-to-expect.html" class="btn btn-primary">What to Expect</a>
|
||||
</div>
|
||||
<div class="rmt-badge">
|
||||
<img src="images/rmt-certification.png" alt="Registered Massage Therapist - Professional Hands You Can Trust">
|
||||
<img src="./images/rmt-certification.png" alt="Registered Massage Therapist - Professional Hands You Can Trust">
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -168,7 +168,7 @@
|
|||
<div class="container">
|
||||
<div class="footer-grid">
|
||||
<div class="footer-brand">
|
||||
<img src="images/logo.jpg" alt="Ebb'nFlow Therapeutics Logo">
|
||||
<img src="./images/logo.jpg" alt="Ebb'nFlow Therapeutics Logo">
|
||||
<h3>Ebb'nFlow <span class="highlight">Therapeutics</span></h3>
|
||||
<p>A boutique wellness sanctuary. One client, one space, one transformative experience at a time.</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,229 +0,0 @@
|
|||
import { Button } from "@/components/ui/button"
|
||||
import { Card, CardContent } from "@/components/ui/card"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import Image from "next/image"
|
||||
import Link from "next/link"
|
||||
import ClinicSenseButton from "@/components/clinicsense-button"
|
||||
|
||||
export default function AboutPage() {
|
||||
return (
|
||||
<div className="min-h-screen bg-beige-lightest">
|
||||
{/* Hero Section */}
|
||||
<section className="bg-gradient-to-br from-beige-light to-beige py-20">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="max-w-4xl mx-auto text-center space-y-8">
|
||||
<Badge variant="outline" className="text-stone-600 border-stone-300">
|
||||
About Dahlia
|
||||
</Badge>
|
||||
<h1 className="text-4xl lg:text-5xl font-light text-stone-800">Dahlia B. Steinberg, RMT</h1>
|
||||
<div className="text-xl lg:text-2xl font-light text-stone-700 italic mb-4">
|
||||
Founder and Owner of Ebb'nFlow Therapeutics
|
||||
</div>
|
||||
<p className="text-xl text-stone-600 leading-relaxed">
|
||||
A lifelong interest in movement and the healing arts is the foundation of her practice as a massage
|
||||
therapist, laser therapist, and movement educator.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Bio Section */}
|
||||
<section className="py-20 bg-white">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="grid lg:grid-cols-2 gap-12 items-start">
|
||||
<div className="space-y-6">
|
||||
<h2 className="text-3xl font-light text-stone-800">Professional Background</h2>
|
||||
<p className="text-lg text-stone-600 leading-relaxed">
|
||||
Dahlia's personal and professional experience with a wide range of bodywork practices including yoga,
|
||||
pilates, somatic movement and modern dance spans 30 years and informs her unique style and approach to
|
||||
her clinical practice of massage therapy.
|
||||
</p>
|
||||
<p className="text-stone-600 leading-relaxed">
|
||||
She is registered with the College of Massage Therapists of Ontario (CMTO), which is the provincial
|
||||
regulatory body that protects the public interest by monitoring the ongoing professional development and
|
||||
ethical standards of RMTs.
|
||||
</p>
|
||||
|
||||
<div className="bg-beige-light p-6 rounded-lg">
|
||||
<h3 className="font-medium text-stone-800 mb-3">Practice Evolution</h3>
|
||||
<div className="space-y-3 text-stone-600 text-sm">
|
||||
<p>
|
||||
<strong>2013:</strong> Started Ebb'nflow Massage, working with Dr. Enrico Schirru at Absolute
|
||||
Chiropractic
|
||||
</p>
|
||||
<p>
|
||||
<strong>2013-2017:</strong> Worked at Paisley Spa and John Chan Physiotherapy Clinic
|
||||
</p>
|
||||
<p>
|
||||
<strong>2015:</strong> Established first home-based clinic on Ontario Street
|
||||
</p>
|
||||
<p>
|
||||
<strong>2017:</strong> Moved to home location on Woodbine Ave., working solely for herself
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<strong>2025:</strong> Relocated to downtown St. Catharines, rebranded to Ebb'nFlow Therapeutics
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative">
|
||||
<Image
|
||||
src="/images/dahlia-portrait.jpg"
|
||||
alt="Dahlia B. Steinberg, RMT - Founder of Ebb'nFlow Therapeutics"
|
||||
width={400}
|
||||
height={500}
|
||||
className="rounded-2xl shadow-lg object-cover"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Education & Training */}
|
||||
<section className="py-20 bg-beige-lightest">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<h2 className="text-3xl font-light text-stone-800 text-center mb-12">Education & Training</h2>
|
||||
|
||||
<div className="space-y-8">
|
||||
<Card className="border-beige">
|
||||
<CardContent className="p-6">
|
||||
<h3 className="text-xl font-medium text-stone-800 mb-4">Formal Education</h3>
|
||||
<div className="space-y-3 text-stone-600">
|
||||
<p>
|
||||
<strong>2021:</strong> Meditech International Inc. Bioflex Laser Therapy Certification
|
||||
</p>
|
||||
<p>
|
||||
<strong>2012:</strong> Graduate, Massage Therapy Program, Ontario College of Health and Technology
|
||||
</p>
|
||||
<p>
|
||||
<strong>2009:</strong> Pilates Teacher Training, STOTT Toronto (Beginner to Advanced Matwork)
|
||||
</p>
|
||||
<p>
|
||||
<strong>2003-05:</strong> Yoga Teacher Training, Yogaspace Toronto (200 hr diploma + Advanced
|
||||
Teacher Training)
|
||||
</p>
|
||||
<p>
|
||||
<strong>1998:</strong> School of Toronto Dance Theatre's Professional Training Program
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="border-beige">
|
||||
<CardContent className="p-6">
|
||||
<h3 className="text-xl font-medium text-stone-800 mb-4">Continuing Education</h3>
|
||||
<div className="space-y-2 text-stone-600">
|
||||
<p>• Myofascial therapy/structural integration</p>
|
||||
<p>• Biodynamic craniosacral therapy</p>
|
||||
<p>• Osteopathic techniques for RMTs</p>
|
||||
<p>• Advanced sacro-lumbar and thoracic spine assessments and joint mobilization</p>
|
||||
<p>• Axis Syllabus - evolving theory and practice of dynamic human movement</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="border-beige bg-beige-light">
|
||||
<CardContent className="p-6">
|
||||
<h3 className="text-xl font-medium text-stone-800 mb-4">Recognition & Support</h3>
|
||||
<div className="space-y-2 text-stone-600">
|
||||
<p>Massage Therapy is Dahlia's second career, supported by:</p>
|
||||
<p>• Training and subsistence grant from the Dancer's Transition and Resource Centre (2010)</p>
|
||||
<p>
|
||||
• Special second year award for academic excellence (Dancer’s Transition and Resource Centre,
|
||||
2011)
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Current Role */}
|
||||
<section className="py-20 bg-white">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="max-w-4xl mx-auto text-center space-y-8">
|
||||
<h2 className="text-3xl font-light text-stone-800">Teaching & Mentorship</h2>
|
||||
<p className="text-lg text-stone-600 leading-relaxed">
|
||||
Dahlia now also works once a week as a supervisor and teacher in the student massage therapy clinic, which
|
||||
is open to the public at the Ontario College of Health and Technology in Stoney Creek. This role helps to
|
||||
keep her engaged and informed in her current practice while inspiring her to encourage and mentor the next
|
||||
generation of massage therapists.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Meet Olivia Section */}
|
||||
<section className="py-20 bg-beige-lightest">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<h2 className="text-3xl font-light text-stone-800 text-center mb-12">Meet Olivia</h2>
|
||||
|
||||
<div className="grid lg:grid-cols-2 gap-8 items-center">
|
||||
<div className="relative">
|
||||
<Image
|
||||
src="/images/olivia-cat.png"
|
||||
alt="Olivia, the friendly clinic cat at Ebb'nFlow Therapeutics"
|
||||
width={400}
|
||||
height={400}
|
||||
className="rounded-2xl shadow-lg object-cover w-full"
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-4">
|
||||
<Card className="border-beige bg-white">
|
||||
<CardContent className="p-6">
|
||||
<p className="text-stone-600 leading-relaxed mb-4">
|
||||
No visit to Ebb'nFlow Therapeutics would be complete without meeting Olivia, our gentle and
|
||||
affectionate clinic companion. This sweet tabby girl has a calming presence that perfectly
|
||||
complements the therapeutic atmosphere of our space.
|
||||
</p>
|
||||
<p className="text-stone-600 leading-relaxed mb-4">
|
||||
Olivia enjoys greeting clients with soft purrs and will often curl up nearby during sessions,
|
||||
adding an extra layer of comfort and relaxation to your experience. Her friendly demeanor and
|
||||
peaceful energy make her a beloved part of the Ebb'nFlow family.
|
||||
</p>
|
||||
<p className="text-stone-600 leading-relaxed italic">
|
||||
Please let us know if you have any allergies or prefer a cat-free session—we're happy to
|
||||
accommodate all our clients' needs!
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* CTA Section */}
|
||||
<section className="py-16 bg-beige-light">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="text-center space-y-8">
|
||||
<h2 className="text-2xl font-light text-stone-800">Experience Dahlia's Unique Approach</h2>
|
||||
<p className="text-lg text-stone-600 max-w-2xl mx-auto">
|
||||
Combining 30 years of movement expertise with clinical massage therapy excellence.
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center items-center">
|
||||
<ClinicSenseButton size="medium" color="green" />
|
||||
<Button size="lg" asChild className="bg-nature-green hover:bg-nature-green-dark text-white">
|
||||
<Link href="/what-to-expect">What to Expect</Link>
|
||||
</Button>
|
||||
</div>
|
||||
<div className="pt-4">
|
||||
<Image
|
||||
src="/images/rmt-certification.png"
|
||||
alt="Registered Massage Therapist - Professional Hands You Can Trust"
|
||||
width={200}
|
||||
height={90}
|
||||
className="mx-auto"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -1,296 +0,0 @@
|
|||
"use client"
|
||||
|
||||
import type React from "react"
|
||||
import Image from "next/image"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { Label } from "@/components/ui/label"
|
||||
import { Textarea } from "@/components/ui/textarea"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import { Clock, Mail, MapPin, Phone } from "lucide-react"
|
||||
import { useState } from "react"
|
||||
import ClinicSenseButton from "@/components/clinicsense-button"
|
||||
|
||||
export default function ContactPage() {
|
||||
const [formData, setFormData] = useState({
|
||||
name: "",
|
||||
email: "",
|
||||
phone: "",
|
||||
service: "",
|
||||
message: "",
|
||||
})
|
||||
|
||||
const handleSubmit = (e: React.FormEvent) => {
|
||||
e.preventDefault()
|
||||
// Handle form submission here
|
||||
console.log("Form submitted:", formData)
|
||||
}
|
||||
|
||||
const handleChange = (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>) => {
|
||||
setFormData({
|
||||
...formData,
|
||||
[e.target.name]: e.target.value,
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-beige-lightest">
|
||||
{/* Hero Section */}
|
||||
<section className="bg-gradient-to-br from-beige-light to-beige py-20">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="max-w-4xl mx-auto text-center space-y-8">
|
||||
<Badge variant="outline" className="text-stone-600 border-stone-300">
|
||||
Get in Touch
|
||||
</Badge>
|
||||
<h1 className="text-4xl lg:text-5xl font-light text-stone-800">Contact Us</h1>
|
||||
<div className="text-xl font-light text-stone-700 italic mb-4">
|
||||
"A place to unwind, a place to heal, a place to grow"
|
||||
</div>
|
||||
<p className="text-xl text-stone-600 leading-relaxed">
|
||||
Ready to experience boutique wellness? Let's chat about creating your personalized sanctuary for healing
|
||||
and self-care.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Clinic Images Section */}
|
||||
<section className="py-12 bg-white">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="grid md:grid-cols-2 gap-8 max-w-4xl mx-auto">
|
||||
<div className="relative">
|
||||
<Image
|
||||
src="/images/clinic-exterior.jpg"
|
||||
alt="Ebb'nFlow Therapeutics clinic exterior"
|
||||
width={400}
|
||||
height={300}
|
||||
className="rounded-lg shadow-md object-cover w-full h-64"
|
||||
/>
|
||||
<div className="absolute bottom-4 left-4 bg-white/90 px-3 py-1 rounded-md">
|
||||
<p className="text-sm font-medium text-stone-800">Our Welcoming Exterior</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative">
|
||||
<Image
|
||||
src="/images/yellow-door.jpg"
|
||||
alt="Distinctive yellow entrance door"
|
||||
width={400}
|
||||
height={300}
|
||||
className="rounded-lg shadow-md object-cover w-full h-64"
|
||||
/>
|
||||
<div className="absolute bottom-4 left-4 bg-white/90 px-3 py-1 rounded-md">
|
||||
<p className="text-sm font-medium text-stone-800">Find Our Yellow Door</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Contact Form & Info Section */}
|
||||
<section className="py-20 bg-beige-lightest">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="grid lg:grid-cols-2 gap-12">
|
||||
{/* Contact Form */}
|
||||
<Card className="border-beige">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-2xl font-light text-stone-800">Send Us a Message</CardTitle>
|
||||
<CardDescription className="text-stone-600">
|
||||
Fill out the form below and we'll get back to you within 24 hours.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<form onSubmit={handleSubmit} className="space-y-6">
|
||||
<div className="grid md:grid-cols-2 gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="name" className="text-stone-700">
|
||||
Full Name
|
||||
</Label>
|
||||
<Input
|
||||
id="name"
|
||||
name="name"
|
||||
value={formData.name}
|
||||
onChange={handleChange}
|
||||
placeholder="Your full name"
|
||||
className="border-stone-300 focus:border-stone-500"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="email" className="text-stone-700">
|
||||
Email
|
||||
</Label>
|
||||
<Input
|
||||
id="email"
|
||||
name="email"
|
||||
type="email"
|
||||
value={formData.email}
|
||||
onChange={handleChange}
|
||||
placeholder="your@email.com"
|
||||
className="border-stone-300 focus:border-stone-500"
|
||||
required
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="phone" className="text-stone-700">
|
||||
Phone Number
|
||||
</Label>
|
||||
<Input
|
||||
id="phone"
|
||||
name="phone"
|
||||
type="tel"
|
||||
value={formData.phone}
|
||||
onChange={handleChange}
|
||||
placeholder="(289) 969-3219"
|
||||
className="border-stone-300 focus:border-stone-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="service" className="text-stone-700">
|
||||
Service of Interest
|
||||
</Label>
|
||||
<select
|
||||
id="service"
|
||||
name="service"
|
||||
value={formData.service}
|
||||
onChange={handleChange}
|
||||
className="w-full px-3 py-2 border border-stone-300 rounded-md focus:outline-none focus:border-stone-500"
|
||||
>
|
||||
<option value="">Select a service</option>
|
||||
<option value="massage">Massage Therapy</option>
|
||||
<option value="laser">Laser Therapy</option>
|
||||
<option value="movement">Movement Therapy</option>
|
||||
<option value="combination">Combination Treatment</option>
|
||||
<option value="consultation">Initial Consultation</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="message" className="text-stone-700">
|
||||
Message
|
||||
</Label>
|
||||
<Textarea
|
||||
id="message"
|
||||
name="message"
|
||||
value={formData.message}
|
||||
onChange={handleChange}
|
||||
placeholder="Tell us about your needs, concerns, or questions..."
|
||||
rows={5}
|
||||
className="border-stone-300 focus:border-stone-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Button type="submit" className="w-full bg-stone-700 hover:bg-stone-800">
|
||||
Send Message
|
||||
</Button>
|
||||
</form>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Contact Information */}
|
||||
<div className="space-y-8">
|
||||
<Card className="border-beige">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-xl font-medium text-stone-800">Visit Our Clinic</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-6">
|
||||
<div className="flex items-start gap-3">
|
||||
<MapPin className="h-5 w-5 text-stone-600 mt-1" />
|
||||
<div>
|
||||
<p className="font-medium text-stone-800">Address</p>
|
||||
<p className="text-stone-600">
|
||||
59 Wellington Street
|
||||
<br />
|
||||
St. Catharines, ON L2R 5P9
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-start gap-3">
|
||||
<Phone className="h-5 w-5 text-stone-600 mt-1" />
|
||||
<div>
|
||||
<p className="font-medium text-stone-800">Phone</p>
|
||||
<p className="text-stone-600">(289) 969-3219</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-start gap-3">
|
||||
<Mail className="h-5 w-5 text-stone-600 mt-1" />
|
||||
<div>
|
||||
<p className="font-medium text-stone-800">Email</p>
|
||||
<p className="text-stone-600">info@ebbnflowtherapeutics.com</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="border-beige">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-xl font-medium text-stone-800">Office Hours</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="space-y-3">
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-stone-700">Monday - Thursday</span>
|
||||
<span className="text-stone-600">9:00 AM - 7:00 PM</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-stone-700">Friday</span>
|
||||
<span className="text-stone-600">9:00 AM - 5:00 PM</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-stone-700">Saturday</span>
|
||||
<span className="text-stone-600">10:00 AM - 4:00 PM</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-stone-700">Sunday</span>
|
||||
<span className="text-stone-600">Closed</span>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="border-beige bg-beige-light">
|
||||
<CardContent className="p-6">
|
||||
<div className="flex items-start gap-3">
|
||||
<Clock className="h-5 w-5 text-stone-600 mt-1" />
|
||||
<div>
|
||||
<p className="font-medium text-stone-800 mb-2">Emergency Contact</p>
|
||||
<p className="text-sm text-stone-600">
|
||||
For urgent matters outside of business hours, please call our emergency line at (289) 969-3220
|
||||
or visit your nearest emergency room.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Booking Section */}
|
||||
<section className="py-16 bg-beige-light">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="text-center space-y-8">
|
||||
<h2 className="text-2xl font-light text-stone-800">Ready for Your Personal Wellness Experience?</h2>
|
||||
<p className="text-lg text-stone-600 max-w-2xl mx-auto">
|
||||
Book your private session in our cozy, boutique space. Experience what it means to have dedicated time and
|
||||
space just for your wellness journey.
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center">
|
||||
<ClinicSenseButton size="large" color="green" />
|
||||
<Button size="lg" className="bg-nature-green hover:bg-nature-green-dark text-white">
|
||||
Call for Personal Consultation
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
212
app/globals.css
212
app/globals.css
|
|
@ -1,212 +0,0 @@
|
|||
@import "tailwindcss";
|
||||
@import "tw-animate-css";
|
||||
|
||||
:root {
|
||||
--background: oklch(1 0 0);
|
||||
--foreground: oklch(0.145 0 0);
|
||||
--card: oklch(1 0 0);
|
||||
--card-foreground: oklch(0.145 0 0);
|
||||
--popover: oklch(1 0 0);
|
||||
--popover-foreground: oklch(0.145 0 0);
|
||||
--primary: oklch(0.45 0.15 130);
|
||||
--primary-foreground: oklch(0.985 0 0);
|
||||
--secondary: oklch(0.97 0 0);
|
||||
--secondary-foreground: oklch(0.145 0 0);
|
||||
--muted: oklch(0.97 0 0);
|
||||
--muted-foreground: oklch(0.556 0 0);
|
||||
--accent: oklch(0.55 0.18 125);
|
||||
--accent-foreground: oklch(0.985 0 0);
|
||||
--destructive: oklch(0.577 0.245 27.325);
|
||||
--destructive-foreground: oklch(0.577 0.245 27.325);
|
||||
--border: oklch(0.922 0 0);
|
||||
--input: oklch(0.922 0 0);
|
||||
--ring: oklch(0.45 0.15 130);
|
||||
--chart-1: oklch(0.55 0.18 125);
|
||||
--chart-2: oklch(0.6 0.118 184.704);
|
||||
--chart-3: oklch(0.398 0.07 227.392);
|
||||
--chart-4: oklch(0.828 0.189 84.429);
|
||||
--chart-5: oklch(0.769 0.188 70.08);
|
||||
--radius: 0.625rem;
|
||||
--sidebar: oklch(0.985 0 0);
|
||||
--sidebar-foreground: oklch(0.145 0 0);
|
||||
--sidebar-primary: oklch(0.45 0.15 130);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
--sidebar-accent: oklch(0.97 0 0);
|
||||
--sidebar-accent-foreground: oklch(0.145 0 0);
|
||||
--sidebar-border: oklch(0.922 0 0);
|
||||
--sidebar-ring: oklch(0.45 0.15 130);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: oklch(0.145 0 0);
|
||||
--foreground: oklch(0.985 0 0);
|
||||
--card: oklch(0.145 0 0);
|
||||
--card-foreground: oklch(0.985 0 0);
|
||||
--popover: oklch(0.145 0 0);
|
||||
--popover-foreground: oklch(0.985 0 0);
|
||||
--primary: oklch(0.55 0.18 125);
|
||||
--primary-foreground: oklch(0.145 0 0);
|
||||
--secondary: oklch(0.269 0 0);
|
||||
--secondary-foreground: oklch(0.985 0 0);
|
||||
--muted: oklch(0.269 0 0);
|
||||
--muted-foreground: oklch(0.708 0 0);
|
||||
--accent: oklch(0.55 0.18 125);
|
||||
--accent-foreground: oklch(0.145 0 0);
|
||||
--destructive: oklch(0.396 0.141 25.723);
|
||||
--destructive-foreground: oklch(0.637 0.237 25.331);
|
||||
--border: oklch(0.269 0 0);
|
||||
--input: oklch(0.269 0 0);
|
||||
--ring: oklch(0.55 0.18 125);
|
||||
--chart-1: oklch(0.55 0.18 125);
|
||||
--chart-2: oklch(0.696 0.17 162.48);
|
||||
--chart-3: oklch(0.769 0.188 70.08);
|
||||
--chart-4: oklch(0.627 0.265 303.9);
|
||||
--chart-5: oklch(0.645 0.246 16.439);
|
||||
--sidebar: oklch(0.145 0 0);
|
||||
--sidebar-foreground: oklch(0.985 0 0);
|
||||
--sidebar-primary: oklch(0.55 0.18 125);
|
||||
--sidebar-primary-foreground: oklch(0.145 0 0);
|
||||
--sidebar-accent: oklch(0.269 0 0);
|
||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
||||
--sidebar-border: oklch(0.269 0 0);
|
||||
--sidebar-ring: oklch(0.55 0.18 125);
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
--color-background: var(--background);
|
||||
--color-foreground: var(--foreground);
|
||||
--color-card: var(--card);
|
||||
--color-card-foreground: var(--card-foreground);
|
||||
--color-popover: var(--popover);
|
||||
--color-popover-foreground: var(--popover-foreground);
|
||||
--color-primary: var(--primary);
|
||||
--color-primary-foreground: var(--primary-foreground);
|
||||
--color-secondary: var(--secondary);
|
||||
--color-secondary-foreground: var(--secondary-foreground);
|
||||
--color-muted: var(--muted);
|
||||
--color-muted-foreground: var(--muted-foreground);
|
||||
--color-accent: var(--accent);
|
||||
--color-accent-foreground: var(--accent-foreground);
|
||||
--color-destructive: var(--destructive);
|
||||
--color-destructive-foreground: var(--destructive-foreground);
|
||||
--color-border: var(--border);
|
||||
--color-input: var(--input);
|
||||
--color-ring: var(--ring);
|
||||
--color-chart-1: var(--chart-1);
|
||||
--color-chart-2: var(--chart-2);
|
||||
--color-chart-3: var(--chart-3);
|
||||
--color-chart-4: var(--chart-4);
|
||||
--color-chart-5: var(--chart-5);
|
||||
--radius-sm: calc(var(--radius) - 4px);
|
||||
--radius-md: calc(var(--radius) - 2px);
|
||||
--radius-lg: var(--radius);
|
||||
--radius-xl: calc(var(--radius) + 4px);
|
||||
--color-sidebar: var(--sidebar);
|
||||
--color-sidebar-foreground: var(--sidebar-foreground);
|
||||
--color-sidebar-primary: var(--sidebar-primary);
|
||||
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
||||
--color-sidebar-accent: var(--sidebar-accent);
|
||||
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
||||
--color-sidebar-border: var(--sidebar-border);
|
||||
--color-sidebar-ring: var(--sidebar-ring);
|
||||
}
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border outline-ring/50;
|
||||
}
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
|
||||
/* Smooth scrolling for anchor links */
|
||||
html {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fade-in {
|
||||
from {
|
||||
opacity: 0;
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes fade-in-up {
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(20px);
|
||||
}
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.animate-fade-in {
|
||||
animation: fade-in 1s ease-in-out;
|
||||
}
|
||||
|
||||
.animate-fade-in-up {
|
||||
animation: fade-in-up 1s ease-in-out;
|
||||
}
|
||||
|
||||
/* Custom nature-inspired colors from logo */
|
||||
.bg-nature-green {
|
||||
background-color: #7cb342;
|
||||
}
|
||||
|
||||
.text-nature-green {
|
||||
color: #7cb342;
|
||||
}
|
||||
|
||||
.border-nature-green {
|
||||
border-color: #7cb342;
|
||||
}
|
||||
|
||||
.bg-nature-green-light {
|
||||
background-color: #aed581;
|
||||
}
|
||||
|
||||
.text-nature-green-light {
|
||||
color: #aed581;
|
||||
}
|
||||
|
||||
.bg-nature-green-dark {
|
||||
background-color: #558b2f;
|
||||
}
|
||||
|
||||
.text-nature-green-dark {
|
||||
color: #558b2f;
|
||||
}
|
||||
|
||||
.bg-sage-green {
|
||||
background-color: #8bc34a;
|
||||
}
|
||||
|
||||
.text-sage-green {
|
||||
color: #8bc34a;
|
||||
}
|
||||
|
||||
/* Beige color palette */
|
||||
.bg-beige-lightest {
|
||||
background-color: #f7f3ef;
|
||||
}
|
||||
|
||||
.bg-beige-light {
|
||||
background-color: #f0e9e0;
|
||||
}
|
||||
|
||||
.bg-beige {
|
||||
background-color: #e8dfd3;
|
||||
}
|
||||
|
||||
.bg-beige-medium {
|
||||
background-color: #d9cdbf;
|
||||
}
|
||||
|
||||
.bg-beige-dark {
|
||||
background-color: #c4b5a3;
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
import type React from "react"
|
||||
import type { Metadata } from "next"
|
||||
import { Inter } from "next/font/google"
|
||||
import "./globals.css"
|
||||
import Navbar from "@/components/navbar"
|
||||
import Footer from "@/components/footer"
|
||||
|
||||
const inter = Inter({ subsets: ["latin"] })
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: "Ebb n Flow Therapeutics - Massage, Laser & Movement Therapy",
|
||||
description:
|
||||
"Experience holistic healing through our integrated therapeutic services. Massage therapy, laser therapy, and movement therapy in a peaceful, professional setting.",
|
||||
keywords: "massage therapy, laser therapy, movement therapy, wellness, healing, therapeutic massage, pain relief",
|
||||
generator: 'v0.app'
|
||||
}
|
||||
|
||||
export default function RootLayout({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
}) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<body className={inter.className}>
|
||||
<Navbar />
|
||||
<main>{children}</main>
|
||||
<Footer />
|
||||
</body>
|
||||
</html>
|
||||
)
|
||||
}
|
||||
|
|
@ -1,254 +0,0 @@
|
|||
"use client"
|
||||
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import { Heart, Star } from "lucide-react"
|
||||
import Image from "next/image"
|
||||
import Link from "next/link"
|
||||
import ClinicSenseButton from "@/components/clinicsense-button"
|
||||
import { useEffect } from "react"
|
||||
|
||||
export default function MovementPage() {
|
||||
useEffect(() => {
|
||||
window.scrollTo(0, 0)
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-beige-lightest">
|
||||
{/* Hero Section */}
|
||||
<section className="bg-gradient-to-br from-beige-light to-beige py-20">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="max-w-4xl mx-auto text-center space-y-8">
|
||||
<Badge variant="outline" className="text-stone-600 border-stone-300">
|
||||
Movement Education
|
||||
</Badge>
|
||||
<h1 className="text-4xl lg:text-5xl font-light text-stone-800">Movement & Mobility</h1>
|
||||
<p className="text-xl text-stone-600 leading-relaxed">
|
||||
Free form/improvisational movement and mobility training as a form of personal and artistic expression and
|
||||
wellness is what ultimately drives Dahlia to continue to learn about our amazing bodies and how we can all
|
||||
move more gracefully as we age.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Movement Education Options */}
|
||||
<section className="py-20 bg-white">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<h2 className="text-3xl font-light text-stone-800 text-center mb-12">Movement Education Options</h2>
|
||||
|
||||
<div className="space-y-8">
|
||||
<Card className="border-beige">
|
||||
<CardContent className="p-8">
|
||||
<p className="text-stone-600 leading-relaxed mb-6">
|
||||
Remedial exercise aka "Rem-Ex" instruction involves teaching a few targeted strength, stretch or
|
||||
mobility exercises that are aimed at furthering the benefits of massage therapy long term, which is
|
||||
an intrinsic component of a comprehensive treatment.
|
||||
</p>
|
||||
<p className="text-stone-600 leading-relaxed mb-6">
|
||||
Although this often comes highly recommended, not everyone is interested in learning a new exercise
|
||||
immediately after having a massage. This makes a lot of sense, and yet Dahlia will still do her best
|
||||
to encourage you, within reason.
|
||||
</p>
|
||||
<p className="text-stone-600 leading-relaxed">That said, clients have a few options:</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<div className="grid md:grid-cols-3 gap-6">
|
||||
<Card className="border-beige">
|
||||
<CardHeader>
|
||||
<div className="w-12 h-12 bg-stone-700 rounded-full flex items-center justify-center mb-4">
|
||||
<span className="text-white font-bold">1</span>
|
||||
</div>
|
||||
<CardTitle className="text-lg font-medium text-stone-800">Personal Choice</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p className="text-stone-600">
|
||||
Clients may request or deny remedial exercise instruction as part of treatment, based on their
|
||||
personal goals.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="border-beige">
|
||||
<CardHeader>
|
||||
<div className="w-12 h-12 bg-stone-700 rounded-full flex items-center justify-center mb-4">
|
||||
<span className="text-white font-bold">2</span>
|
||||
</div>
|
||||
<CardTitle className="text-lg font-medium text-stone-800">Extended Sessions</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p className="text-stone-600">
|
||||
Clients can request to allot up to 50% of their treatment time (15 to 45 minutes) for Rem-Ex
|
||||
instruction before or after their massage.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="border-beige">
|
||||
<CardHeader>
|
||||
<div className="w-12 h-12 bg-stone-700 rounded-full flex items-center justify-center mb-4">
|
||||
<span className="text-white font-bold">3</span>
|
||||
</div>
|
||||
<CardTitle className="text-lg font-medium text-stone-800">Group Workshops</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p className="text-stone-600">
|
||||
Clients can also sign up for upcoming movement workshops for a more comprehensive group learning
|
||||
experience.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Origin Story */}
|
||||
<section className="py-20 bg-beige-lightest">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<h2 className="text-3xl font-light text-stone-800 text-center mb-12">The Ebb'nFlow Origin Story</h2>
|
||||
|
||||
<Card className="border-beige bg-white">
|
||||
<CardContent className="p-8">
|
||||
<div className="space-y-6 text-stone-600 leading-relaxed">
|
||||
<p>
|
||||
The original concept of Ebb'nFlow Massage (now Ebb'nFlow Therapeutics) was born out of Dahlia's
|
||||
initial work as a yoga instructor, before she became a massage therapist. Dahlia taught private,
|
||||
one-on-one sessions as well as classes around the GTA from 2004-2009.
|
||||
</p>
|
||||
<p>
|
||||
She recognized the need to meet students where they were instead of insisting that they push through
|
||||
their pain and fatigue similarly to the approach of a personal trainer. Some days they would arrive
|
||||
in a lot of pain and would need a gentler approach such as more periods of rest or "ebb" between
|
||||
exercises or hands on work such as massage at the end of their sessions.
|
||||
</p>
|
||||
<p>
|
||||
Dahlia's natural talent for massage as a component of her sessions enabled students to show up more
|
||||
consistently for practice instead of skipping practice out of concern that they would not be able to
|
||||
make it through a session.
|
||||
</p>
|
||||
<p className="font-medium text-stone-800">
|
||||
Since consistency is key to success, a more fluid and compassionate approach to teaching one-on-one
|
||||
was born and clients were given permission to move as they needed through periods of "ebb" or "flow"
|
||||
with grace and freedom from the need to over achieve.
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Workshops */}
|
||||
<section className="py-20 bg-white">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<h2 className="text-3xl font-light text-stone-800 text-center mb-12">Movement & Mobility Workshops</h2>
|
||||
|
||||
<div className="grid lg:grid-cols-2 gap-8 items-center">
|
||||
<div className="space-y-6">
|
||||
<Card className="border-beige">
|
||||
<CardHeader>
|
||||
<Heart className="h-8 w-8 text-stone-600 mb-2" />
|
||||
<CardTitle className="text-xl font-medium text-stone-800">Fun, Liberating & Educational</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p className="text-stone-600 leading-relaxed">
|
||||
Dahlia's movement and mobility workshops are aimed towards adults and seniors and offer
|
||||
opportunities to gain greater strength, flexibility, mobility and balance as well as to embrace
|
||||
the discovery of one's own unique expression through movement and dance.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="border-beige bg-beige-lightest">
|
||||
<CardContent className="p-6">
|
||||
<h3 className="font-medium text-stone-800 mb-3">Workshop Benefits</h3>
|
||||
<div className="space-y-2 text-stone-600">
|
||||
<div className="flex items-center gap-2">
|
||||
<Star className="h-4 w-4 text-stone-500" />
|
||||
<span>Greater strength and flexibility</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Star className="h-4 w-4 text-stone-500" />
|
||||
<span>Improved mobility and balance</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Star className="h-4 w-4 text-stone-500" />
|
||||
<span>Unique personal expression through movement</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Star className="h-4 w-4 text-stone-500" />
|
||||
<span>Discovery of dance and creative movement</span>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<div className="relative">
|
||||
<Image
|
||||
src="/images/dahlia-portrait.jpg"
|
||||
alt="Dahlia Steinberg - Movement and wellness educator"
|
||||
width={400}
|
||||
height={500}
|
||||
className="rounded-2xl shadow-lg object-cover"
|
||||
/>
|
||||
<div className="absolute bottom-4 left-4 bg-white/90 px-3 py-2 rounded-md">
|
||||
<p className="text-sm font-medium text-stone-800">Dahlia - Your Movement Guide</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Personal Expression */}
|
||||
<section className="py-20 bg-beige-lightest">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="max-w-4xl mx-auto text-center space-y-8">
|
||||
<h2 className="text-3xl font-light text-stone-800">Continuing the Dance</h2>
|
||||
<p className="text-lg text-stone-600 leading-relaxed">
|
||||
Free form/improvisational movement and mobility training as a form of personal and artistic expression and
|
||||
wellness is what ultimately drives Dahlia to continue to learn about our amazing bodies and how we can all
|
||||
move more gracefully as we age.
|
||||
</p>
|
||||
<p className="text-stone-600 leading-relaxed">
|
||||
She continues to dance for her own enjoyment and can be found performing or choreographing for community
|
||||
arts-based projects when opportunities arise.
|
||||
</p>
|
||||
<p className="text-stone-600 leading-relaxed">
|
||||
Dahlia is working towards offering more movement and mobility classes and workshops in the future so
|
||||
please stay tuned for updates by checking the Movement section of this website.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* CTA Section */}
|
||||
<section className="py-16 bg-beige-light">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="text-center space-y-8">
|
||||
<h2 className="text-2xl font-light text-stone-800">Ready to Move with More Freedom?</h2>
|
||||
<p className="text-lg text-stone-600 max-w-2xl mx-auto">
|
||||
If long lasting improvement is your goal than you may want to consider how Dahlia's skills as a teacher
|
||||
could benefit you through either one-on-one instruction sessions that can be combined with massage therapy
|
||||
or group workshops.
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center items-center">
|
||||
<ClinicSenseButton size="medium" color="green" />
|
||||
<Button size="lg" asChild className="bg-nature-green hover:bg-nature-green-dark text-white">
|
||||
<Link href="/contact">Ask About Workshops</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
400
app/page.tsx
400
app/page.tsx
|
|
@ -1,400 +0,0 @@
|
|||
"use client"
|
||||
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
||||
import { MapPin, Phone } from "lucide-react"
|
||||
import Image from "next/image"
|
||||
import Link from "next/link"
|
||||
import ServiceDropdown from "@/components/service-dropdown"
|
||||
import ClinicSenseButton from "@/components/clinicsense-button"
|
||||
import InfoModal from "@/components/info-modal"
|
||||
import { useState } from "react"
|
||||
|
||||
export default function HomePage() {
|
||||
const [modalContent, setModalContent] = useState<string>("")
|
||||
const [modalTitle, setModalTitle] = useState<string>("")
|
||||
const [isModalOpen, setIsModalOpen] = useState(false)
|
||||
|
||||
const scopeOfPracticeText = `Registered Massage Therapists in Ontario constitute a regulated health profession in much the same way that physicians, nurses, physiotherapists and chiropractors are regulated. The profession is governed by a Scope of Practice, which is defined as follows:
|
||||
|
||||
"The practice of massage therapy is the assessment of the soft tissue and joints of the body, and the treatment and prevention of physical dysfunction and pain of the soft tissues and joints by manipulation to develop, maintain, rehabilitate or augment physical function, or relieve pain." (Massage Therapy Act, 1991)
|
||||
|
||||
Within their practice, massage therapists will use a variety of procedures and modalities to provide services within the scope of practice. "Massage" is a general term describing one or several methods of treatment and is often mistakenly used and confused with the practice of massage therapy.`
|
||||
|
||||
const benefitsText = `Massage therapy treatments provided by a Registered Massage Therapist can offer significant benefits for a variety of conditions and for diverse patient populations. Whether you need to have a moment of relaxation, reduce muscle tension or attain relief from chronic pain, massage therapy can enhance your overall well-being. Massage therapy can help alleviate musculoskeletal disorders associated with everyday stress, muscular overuse, physical manifestation of mental distress and many persistent pain syndromes.
|
||||
|
||||
Massage therapy can be an important part of your health maintenance plan by:
|
||||
• Reducing or eliminating pain
|
||||
• Improving joint mobility
|
||||
• Improving lymphatic drainage
|
||||
• Reducing muscular tension
|
||||
|
||||
Massage therapy can treat both acute and chronic conditions. RMTs work with a wide variety of patients in the treatment of illness, injury, rehabilitation and disability.`
|
||||
|
||||
const conditionsTreatedText = `Massage therapy can prove beneficial to many conditions, including but not limited to the following:
|
||||
|
||||
• Anxiety and Depression
|
||||
• Arthritis
|
||||
• Asthma and Emphysema
|
||||
• Cancer
|
||||
• Carpal Tunnel Syndrome
|
||||
• Chronic Fatigue Syndrome
|
||||
• Dislocations
|
||||
• Edema
|
||||
• Fibromyalgia
|
||||
• Headaches
|
||||
• Inflammatory Conditions
|
||||
• Insomnia
|
||||
• Lymphoedema
|
||||
• Multiple Sclerosis
|
||||
• Muscle Tension and Spasm
|
||||
• Parkinson's Disease
|
||||
• Plantar Fasciitis
|
||||
• Post-Surgical Rehabilitation
|
||||
• Post-Traumatic Stress Disorder (PTSD)
|
||||
• Pregnancy and Labor Support
|
||||
• Sciatica
|
||||
• Scoliosis
|
||||
• Sports Injuries
|
||||
• Strains and Sprains
|
||||
• Stress and Stress-Related Conditions
|
||||
• Stroke
|
||||
• Tendinitis
|
||||
• Whiplash
|
||||
|
||||
Massage therapy can also be used as part of a preventative care program. This includes sports training, injury prevention, ongoing stress management and more!
|
||||
|
||||
Your massage therapist will require an overall picture of your current health and a detailed health history in order to design a treatment plan that's right for you. If a massage therapist determines that your condition would be better treated by another healthcare professional, they will make the appropriate referral.`
|
||||
|
||||
const techniquesText = `Treatments are based on General Swedish Massage techniques and may be combined with Deep Tissue Massage, Myofascial Release, Trigger Point Therapy, Manual Lymphatic Drainage and Joint Mobilization Techniques. Ongoing assessment, remedial exercise and/or home care instruction is also part of this comprehensive treatment session based on the client's goals and comfort.
|
||||
|
||||
Please note: In cases where there is more than one area of complaint, longer treatment times (75 or 90 minute) are recommended.`
|
||||
|
||||
const laserScienceText = `Ebb'nFlow Therapeutics uses the BIOFLEX® system of Class 3b lasers together with large surface arrays of bicolour LEDs that affect a large volume of circulating blood as well as underlying tissues resulting in both a powerful systemic and direct photobiomodulation effect.
|
||||
|
||||
Please visit BioflexLaser.com for more info.`
|
||||
|
||||
const massageDropdownItems = [
|
||||
{ title: "Scope of Practice", modal: scopeOfPracticeText },
|
||||
{ title: "Benefits of Massage Therapy", modal: benefitsText },
|
||||
{ title: "Conditions Treated", modal: conditionsTreatedText },
|
||||
{ title: "Techniques", modal: techniquesText },
|
||||
]
|
||||
|
||||
const laserDropdownItems = [{ title: "The Science", modal: laserScienceText }]
|
||||
|
||||
const handleModalOpen = (content: string, title: string) => {
|
||||
setModalContent(content)
|
||||
setModalTitle(title)
|
||||
setIsModalOpen(true)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-beige-lightest">
|
||||
<InfoModal isOpen={isModalOpen} onClose={() => setIsModalOpen(false)} content={modalContent} title={modalTitle} />
|
||||
|
||||
{/* Hero Section */}
|
||||
<section className="relative bg-gradient-to-br from-beige-light to-beige py-20 lg:py-32 min-h-screen flex items-center">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="grid lg:grid-cols-2 gap-12 items-center">
|
||||
<div className="space-y-8 flex flex-col items-center lg:items-start">
|
||||
<div className="space-y-6 text-center lg:text-left">
|
||||
<h1 className="text-4xl lg:text-5xl font-light text-gray-800">
|
||||
Ebb'nFlow <span className="font-normal text-nature-green">Therapeutics</span>
|
||||
</h1>
|
||||
<p className="text-2xl lg:text-3xl font-light text-gray-700 italic">
|
||||
Excellence in Massage Therapy Since 2013
|
||||
</p>
|
||||
<p className="text-xl text-gray-600 leading-relaxed">
|
||||
A serene, home-based practice in the heart of downtown St Catharines
|
||||
</p>
|
||||
<p className="text-lg text-nature-green font-medium">Owned and operated by Dahlia B. Steinberg RMT.</p>
|
||||
</div>
|
||||
<div className="flex flex-col sm:flex-row gap-4 w-full justify-center lg:justify-start">
|
||||
<ClinicSenseButton className="w-full sm:w-auto" size="medium" color="green" />
|
||||
<Button
|
||||
variant="outline"
|
||||
size="lg"
|
||||
className="border-nature-green text-nature-green hover:bg-beige-light bg-transparent w-full sm:w-auto"
|
||||
asChild
|
||||
>
|
||||
<Link href="/about">Learn More</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div className="relative lg:order-first">
|
||||
<Image
|
||||
src="/images/reception-area.jpg"
|
||||
alt="Welcoming reception area at Ebb'nFlow Therapeutics"
|
||||
width={600}
|
||||
height={700}
|
||||
className="rounded-2xl shadow-2xl object-cover w-full h-[500px] lg:h-[600px]"
|
||||
priority
|
||||
/>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/20 to-transparent rounded-2xl"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* About Section */}
|
||||
<section className="py-20 bg-white">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="max-w-4xl mx-auto text-center space-y-8">
|
||||
<div className="bg-beige-light p-8 rounded-2xl text-left max-w-3xl mx-auto border border-beige">
|
||||
<p className="text-gray-700 leading-relaxed mb-4">
|
||||
Ebb'nFlow Therapeutics provides Massage Therapy that is attentive to your unique needs and goals.
|
||||
Whether you are looking for recovery from the stress and strains of work, to manage pain, prevent injury
|
||||
or improve your physical performance, we're here to meet you where you are.
|
||||
</p>
|
||||
<p className="text-gray-700 leading-relaxed">
|
||||
Unlike any other massage therapy practice, Ebb'nFlow Therapeutics also offers a distinctly unique
|
||||
service that combines the cutting edge technology of Laser Therapy (Photobiomodulation) in combination
|
||||
with massage therapy for accelerated healing of acute pain conditions and injury.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Services Section */}
|
||||
<section id="services" className="py-20 bg-beige-lightest scroll-mt-16">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="text-center mb-16">
|
||||
<h2 className="text-3xl lg:text-4xl font-light text-gray-800 mb-4">Services</h2>
|
||||
<p className="text-lg text-gray-600 max-w-3xl mx-auto">
|
||||
Please click on the links below to learn more about the unique services offered, based on a comprehensive,
|
||||
clinical practice of Massage Therapy.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className="grid lg:grid-cols-3 gap-8 max-w-6xl mx-auto">
|
||||
{/* Massage Therapy */}
|
||||
<Card className="border-beige hover:shadow-lg transition-shadow duration-300 bg-white">
|
||||
<CardHeader className="pb-4">
|
||||
<Image
|
||||
src="/images/treatment-room.jpg"
|
||||
alt="Professional massage therapy treatment room"
|
||||
width={400}
|
||||
height={250}
|
||||
className="rounded-lg object-cover w-full h-48"
|
||||
/>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<CardTitle className="text-xl font-medium text-gray-800">Massage Therapy Treatment</CardTitle>
|
||||
<CardDescription className="text-gray-600 leading-relaxed">
|
||||
General Swedish Massage combined with specialized techniques tailored to your specific needs.
|
||||
</CardDescription>
|
||||
|
||||
<ServiceDropdown
|
||||
items={massageDropdownItems}
|
||||
title="Learn More About Massage Therapy"
|
||||
onModalOpen={handleModalOpen}
|
||||
/>
|
||||
<div className="pt-2">
|
||||
<ClinicSenseButton className="w-full" size="small" color="green" />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Laser Therapy */}
|
||||
<Card className="border-beige hover:shadow-lg transition-shadow duration-300 bg-white">
|
||||
<CardHeader className="pb-4">
|
||||
<Image
|
||||
src="/images/bioflex-laser.png"
|
||||
alt="BioFlex Laser Therapy - The safe and effective way to eliminate pain"
|
||||
width={400}
|
||||
height={250}
|
||||
className="rounded-lg object-cover w-full h-48"
|
||||
/>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<CardTitle className="text-xl font-medium text-gray-800">Laser Therapy Treatment</CardTitle>
|
||||
<CardDescription className="text-gray-600 leading-relaxed">
|
||||
Stand alone or combined with Massage Therapy (recommended). Laser therapy is the use of red and
|
||||
infrared light that provides accelerated healing for the treatment of musculoskeletal injury, wounds,
|
||||
arthritis, and nerve injury.
|
||||
</CardDescription>
|
||||
|
||||
<ServiceDropdown
|
||||
items={laserDropdownItems}
|
||||
title="Learn More About Laser Therapy"
|
||||
onModalOpen={handleModalOpen}
|
||||
/>
|
||||
<div className="pt-2">
|
||||
<ClinicSenseButton className="w-full" size="small" color="green" />
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Movement Education */}
|
||||
<Card className="border-beige hover:shadow-lg transition-shadow duration-300 bg-white">
|
||||
<CardHeader className="pb-4">
|
||||
<Image
|
||||
src="/images/movement-class.png"
|
||||
alt="Movement education class with participants in a studio"
|
||||
width={400}
|
||||
height={250}
|
||||
className="rounded-lg object-cover w-full h-48"
|
||||
/>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<CardTitle className="text-xl font-medium text-gray-800">Movement Education</CardTitle>
|
||||
<CardDescription className="text-gray-600 leading-relaxed">
|
||||
Remedial exercise aka "Rem-Ex" instruction involves teaching targeted strength, stretch or mobility
|
||||
exercises that further the benefits of massage therapy long term.
|
||||
</CardDescription>
|
||||
<Button
|
||||
variant="outline"
|
||||
className="w-full border-nature-green text-nature-green hover:bg-beige-light bg-transparent mb-2"
|
||||
asChild
|
||||
>
|
||||
<Link href="/movement">See Movement Workshops</Link>
|
||||
</Button>
|
||||
<ClinicSenseButton className="w-full" size="small" color="green" />
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Pricing Section */}
|
||||
<section id="prices" className="py-20 bg-white scroll-mt-16">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<h2 className="text-3xl lg:text-4xl font-light text-gray-800 text-center mb-12">Prices</h2>
|
||||
|
||||
<div className="grid md:grid-cols-2 gap-8">
|
||||
{/* Main Services */}
|
||||
<Card className="border-beige">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-xl font-medium text-gray-800">Massage and/or Laser Therapy</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div className="space-y-3">
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-gray-700">30 Minute</span>
|
||||
<span className="text-gray-800 font-medium">
|
||||
$53.50 <span className="text-sm text-gray-600">(+$6.95 HST)</span>
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-gray-700">45 Minute</span>
|
||||
<span className="text-gray-800 font-medium">
|
||||
$80.25 <span className="text-sm text-gray-600">(+$10.43 HST)</span>
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-gray-700">60 Minute</span>
|
||||
<span className="text-gray-800 font-medium">
|
||||
$107.00 <span className="text-sm text-gray-600">(+$13.91 HST)</span>
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-gray-700">75 Minute</span>
|
||||
<span className="text-gray-800 font-medium">
|
||||
$133.75 <span className="text-sm text-gray-600">(+$17.38 HST)</span>
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-gray-700">90 Minute</span>
|
||||
<span className="text-gray-800 font-medium">
|
||||
$160.50 <span className="text-sm text-gray-600">(+$20.86 HST)</span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
{/* Add-on Services */}
|
||||
<Card className="border-beige">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-xl font-medium text-gray-800">Add-on Laser Therapy</CardTitle>
|
||||
<CardDescription className="text-gray-600">
|
||||
If combined simultaneously with Massage Therapy for more than 15 minutes (Subject to therapist's
|
||||
discretion)
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div className="text-center">
|
||||
<span className="text-2xl font-medium text-nature-green">$1.00/minute</span>
|
||||
<span className="text-sm text-gray-600 block">(+ HST)</span>
|
||||
</div>
|
||||
<p className="text-sm text-gray-600 text-center">Available in 15, 30, 45 and 60 minute intervals</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
{/* Payment & Insurance Info */}
|
||||
<div className="mt-12 space-y-6">
|
||||
<Card className="border-beige bg-beige-lightest">
|
||||
<CardContent className="p-6">
|
||||
<div className="mb-6">
|
||||
<h3 className="text-2xl font-semibold text-gray-800 mb-3">Payment & Insurance</h3>
|
||||
<p className="text-lg font-bold text-nature-green">Direct billing is now available</p>
|
||||
</div>
|
||||
<div className="space-y-3 text-gray-700">
|
||||
<p>
|
||||
<strong>Accepted:</strong> Cash, Direct Billing, E-transfer, Debit, Credit Card (Visa, AmEx,
|
||||
Mastercard)
|
||||
</p>
|
||||
<p>
|
||||
RMTs are regulated health care professionals recognized by insurance companies across Ontario.
|
||||
</p>
|
||||
<p>
|
||||
It is recommended that clients check with their insurance provider about whether they are required
|
||||
to have a doctor's note in order to submit a claim.
|
||||
</p>
|
||||
<p>
|
||||
Your receipt will include the practitioner's registration number necessary for an insurance claim
|
||||
submission. This number verifies that your therapist is registered with the College of Massage
|
||||
Therapists of Ontario (CMTO).
|
||||
</p>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* CTA Section */}
|
||||
<section className="py-16 bg-beige-light">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="text-center space-y-8">
|
||||
<h2 className="text-2xl font-light text-gray-800">Ready to Begin Your Wellness Journey?</h2>
|
||||
<div className="flex flex-col sm:flex-row justify-center items-center gap-8 text-gray-600 mb-6">
|
||||
<div className="flex items-center gap-2">
|
||||
<Phone className="h-5 w-5 text-nature-green" />
|
||||
<span>(289) 969-3219</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<MapPin className="h-5 w-5 text-nature-green" />
|
||||
<span>Downtown St. Catharines</span>
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center items-center">
|
||||
<ClinicSenseButton className="w-full sm:w-auto" size="medium" color="green" />
|
||||
<Button
|
||||
size="lg"
|
||||
asChild
|
||||
className="bg-nature-green hover:bg-nature-green-dark text-white w-full sm:w-auto"
|
||||
>
|
||||
<Link href="/contact">Contact Dahlia</Link>
|
||||
</Button>
|
||||
</div>
|
||||
<div className="pt-4">
|
||||
<Image
|
||||
src="/images/rmt-certification.png"
|
||||
alt="Registered Massage Therapist - Professional Hands You Can Trust"
|
||||
width={200}
|
||||
height={90}
|
||||
className="mx-auto"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -1,233 +0,0 @@
|
|||
import { Button } from "@/components/ui/button"
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
|
||||
import { Badge } from "@/components/ui/badge"
|
||||
import { CheckCircle, Clock, FileText, Heart } from "lucide-react"
|
||||
import Link from "next/link"
|
||||
import ClinicSenseButton from "@/components/clinicsense-button"
|
||||
import Image from "next/image"
|
||||
|
||||
export default function WhatToExpectPage() {
|
||||
return (
|
||||
<div className="min-h-screen bg-beige-lightest">
|
||||
{/* Hero Section */}
|
||||
<section className="bg-gradient-to-br from-beige-light to-beige py-20">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="max-w-4xl mx-auto text-center space-y-8">
|
||||
<Badge variant="outline" className="text-stone-600 border-stone-300">
|
||||
Your First Visit
|
||||
</Badge>
|
||||
<h1 className="text-4xl lg:text-5xl font-light text-stone-800">What to Expect</h1>
|
||||
<p className="text-xl text-stone-600 leading-relaxed">
|
||||
Once you have successfully booked your initial appointment, you will receive a confirmation email with a
|
||||
few forms to fill out ahead of time.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Initial Appointment Process */}
|
||||
<section className="py-20 bg-white">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<h2 className="text-3xl font-light text-stone-800 text-center mb-12">The Initial Appointment</h2>
|
||||
|
||||
<div className="grid md:grid-cols-2 gap-8 mb-12">
|
||||
<Card className="border-beige">
|
||||
<CardHeader>
|
||||
<FileText className="h-8 w-8 text-stone-600 mb-2" />
|
||||
<CardTitle className="text-xl font-medium text-stone-800">Pre-Appointment Forms</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-3">
|
||||
<div className="flex items-center gap-2">
|
||||
<CheckCircle className="h-4 w-4 text-green-600" />
|
||||
<span className="text-stone-600">Contact Information</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<CheckCircle className="h-4 w-4 text-green-600" />
|
||||
<span className="text-stone-600">Reason for Visit</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<CheckCircle className="h-4 w-4 text-green-600" />
|
||||
<span className="text-stone-600">Health History</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<CheckCircle className="h-4 w-4 text-green-600" />
|
||||
<span className="text-stone-600">Consent to Policies, Assessment and Treatment</span>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="border-beige">
|
||||
<CardHeader>
|
||||
<Clock className="h-8 w-8 text-stone-600 mb-2" />
|
||||
<CardTitle className="text-xl font-medium text-stone-800">Assessment Process</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-3">
|
||||
<p className="text-stone-600">
|
||||
Your initial appointment begins with an in-person review of forms and an assessment that can range
|
||||
from simple to more involved, depending on the complexity or severity of your condition.
|
||||
</p>
|
||||
<p className="text-stone-600">
|
||||
This allows your therapist to ascertain whether there are any contraindications or modifications
|
||||
that may need to be considered for safe and effective treatment.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<Card className="border-beige bg-beige-light">
|
||||
<CardContent className="p-8">
|
||||
<h3 className="text-xl font-medium text-stone-800 mb-4">First Session Components</h3>
|
||||
<div className="grid md:grid-cols-2 gap-6">
|
||||
<div className="space-y-2">
|
||||
<p className="text-stone-700">• Forms review</p>
|
||||
<p className="text-stone-700">• Intake discussion</p>
|
||||
<p className="text-stone-700">• Initial assessment</p>
|
||||
<p className="text-stone-700">• Treatment plan development</p>
|
||||
</div>
|
||||
<div className="space-y-2">
|
||||
<p className="text-stone-700">• Treatment of sensitive areas (if indicated)</p>
|
||||
<p className="text-stone-700">• Diagnostics and referrals</p>
|
||||
<p className="text-stone-700">• Ongoing assessment planning</p>
|
||||
<p className="text-stone-700">• Treatment plan maintenance</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Assessment Details */}
|
||||
<section className="py-20 bg-beige-lightest">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<h2 className="text-3xl font-light text-stone-800 text-center mb-12">Comprehensive Assessment</h2>
|
||||
|
||||
<div className="space-y-6">
|
||||
<Card className="border-beige">
|
||||
<CardContent className="p-6">
|
||||
<p className="text-stone-600 leading-relaxed">
|
||||
The first treatment session requires additional time to go over the forms and perform an initial
|
||||
assessment that may include postural observations, range of motion testing, and/or neurological and
|
||||
special orthopaedic testing.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="border-beige">
|
||||
<CardContent className="p-6">
|
||||
<p className="text-stone-600 leading-relaxed">
|
||||
With numerous tools available to her, Dahlia continuously discerns which techniques may be most
|
||||
effective and regularly reassesses client responses to ensure that treatments continue to be
|
||||
beneficial.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Treatment Experience */}
|
||||
<section className="py-20 bg-white">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="max-w-4xl mx-auto">
|
||||
<h2 className="text-3xl font-light text-stone-800 text-center mb-12">Your Treatment Experience</h2>
|
||||
|
||||
<div className="grid lg:grid-cols-2 gap-8">
|
||||
<div className="space-y-6">
|
||||
<Card className="border-beige">
|
||||
<CardHeader>
|
||||
<Heart className="h-8 w-8 text-stone-600 mb-2" />
|
||||
<CardTitle className="text-xl font-medium text-stone-800">Personalized Approach</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p className="text-stone-600 leading-relaxed">
|
||||
Dahlia meets clients where they are, and is able to offer either a quiet retreat or a fun,
|
||||
friendly conversational interaction during treatments. She prioritizes client's goals, with the
|
||||
utmost respect for their comfort, time and resources.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="border-beige">
|
||||
<CardContent className="p-6">
|
||||
<h3 className="font-medium text-stone-800 mb-3">Communication & Consent</h3>
|
||||
<p className="text-stone-600 leading-relaxed">
|
||||
She encourages an atmosphere of open, two-way communication that respects privacy, autonomy and
|
||||
preferences such as depth of pressure and special consent for the treatment of sensitive areas if
|
||||
indicated, guided strictly by the principles of ethical practice adhered to by all registrants of
|
||||
the CMTO.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
|
||||
<div className="space-y-6">
|
||||
<div className="relative">
|
||||
<Image
|
||||
src="/images/treatment-room.jpg"
|
||||
alt="Professional treatment room setup"
|
||||
width={400}
|
||||
height={300}
|
||||
className="rounded-2xl shadow-lg object-cover w-full h-64"
|
||||
/>
|
||||
<div className="absolute bottom-4 left-4 bg-white/90 px-3 py-2 rounded-md">
|
||||
<p className="text-sm font-medium text-stone-800">Your Private Treatment Space</p>
|
||||
</div>
|
||||
</div>
|
||||
<Card className="border-beige bg-beige-lightest">
|
||||
<CardContent className="p-6">
|
||||
<h3 className="font-medium text-stone-800 mb-3">A Science and an Art Form</h3>
|
||||
<p className="text-stone-600 leading-relaxed mb-4">
|
||||
A massage from Dahlia is an experience and often also an education. Her approach is intuitive,
|
||||
evidence-based and trauma-informed. Her own personal experiences with injury and chronic pain has
|
||||
instilled a high level of empathy for and understanding of clients' complaints as well as her
|
||||
insistence on professionalism and excellence of care.
|
||||
</p>
|
||||
<p className="text-stone-600 leading-relaxed">
|
||||
There's always a unique and inspiring playlist in the background. Clients can also request music
|
||||
that they enjoy, adding to an experience that is tailored just for them. Complimentary
|
||||
aromatherapy is also available by request.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card className="border-beige">
|
||||
<CardContent className="p-6">
|
||||
<h3 className="font-medium text-stone-800 mb-3">Education & Home Care</h3>
|
||||
<p className="text-stone-600 leading-relaxed">
|
||||
Dahlia is a teacher at heart, so you likely won't be able to walk away without being encouraged to
|
||||
learn a stretch or strengthening exercise or about how to incorporate a home care practice into
|
||||
your routine to enhance the long term effects of treatment between sessions.
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* CTA Section */}
|
||||
<section className="py-16 bg-beige-light">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="text-center space-y-8">
|
||||
<h2 className="text-2xl font-light text-stone-800">Ready to Experience Holistic Care?</h2>
|
||||
<p className="text-lg text-stone-600 max-w-2xl mx-auto">
|
||||
You can expect to have your primary area of concern addressed directly, within a treatment that aims to
|
||||
treat the body holistically as an interconnected system.
|
||||
</p>
|
||||
<div className="flex flex-col sm:flex-row gap-4 justify-center items-center">
|
||||
<ClinicSenseButton size="medium" color="green" />
|
||||
<Button size="lg" asChild className="bg-nature-green hover:bg-nature-green-dark text-white">
|
||||
<Link href="/contact">Have Questions?</Link>
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
{
|
||||
"$schema": "https://ui.shadcn.com/schema.json",
|
||||
"style": "new-york",
|
||||
"rsc": true,
|
||||
"tsx": true,
|
||||
"tailwind": {
|
||||
"config": "",
|
||||
"css": "app/globals.css",
|
||||
"baseColor": "neutral",
|
||||
"cssVariables": true,
|
||||
"prefix": ""
|
||||
},
|
||||
"aliases": {
|
||||
"components": "@/components",
|
||||
"utils": "@/lib/utils",
|
||||
"ui": "@/components/ui",
|
||||
"lib": "@/lib",
|
||||
"hooks": "@/hooks"
|
||||
},
|
||||
"iconLibrary": "lucide"
|
||||
}
|
||||
|
|
@ -1,81 +0,0 @@
|
|||
"use client"
|
||||
|
||||
import { useEffect, useState } from "react"
|
||||
|
||||
export default function AnimatedHero() {
|
||||
const [currentStep, setCurrentStep] = useState(0)
|
||||
|
||||
useEffect(() => {
|
||||
const steps = [
|
||||
{ delay: 1000, step: 1 }, // "Welcome to Ebb'nFlow Therapeutics"
|
||||
{ delay: 2000, step: 2 }, // "Take a deep breath"
|
||||
{ delay: 1500, step: 3 }, // "Unwind"
|
||||
{ delay: 1500, step: 4 }, // "Heal"
|
||||
{ delay: 2000, step: 5 }, // "Leave feeling..."
|
||||
]
|
||||
|
||||
let totalDelay = 0
|
||||
steps.forEach(({ delay, step }) => {
|
||||
totalDelay += delay
|
||||
setTimeout(() => {
|
||||
setCurrentStep(step)
|
||||
}, totalDelay)
|
||||
})
|
||||
}, [])
|
||||
|
||||
return (
|
||||
<div className="space-y-6 min-h-[400px] flex flex-col justify-center items-center lg:items-start">
|
||||
{/* Welcome to Ebb'nFlow Therapeutics */}
|
||||
<div
|
||||
className={`transition-all duration-1000 ease-in-out ${
|
||||
currentStep >= 1 ? "opacity-100 translate-y-0" : "opacity-0 translate-y-4"
|
||||
}`}
|
||||
>
|
||||
<div className="space-y-2">
|
||||
<p className="text-lg text-gray-600 text-center lg:text-left">Welcome to</p>
|
||||
<h2 className="text-3xl lg:text-4xl font-light text-gray-800 text-center lg:text-left">
|
||||
Ebb'nFlow <span className="font-normal text-nature-green">Therapeutics</span>
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Take a deep breath */}
|
||||
<div
|
||||
className={`transition-all duration-1000 ease-in-out ${
|
||||
currentStep >= 2 ? "opacity-100 translate-y-0" : "opacity-0 translate-y-4"
|
||||
}`}
|
||||
>
|
||||
<p className="text-4xl lg:text-5xl font-light text-gray-700 text-center lg:text-left">Take a deep breath</p>
|
||||
</div>
|
||||
|
||||
{/* Unwind */}
|
||||
<div
|
||||
className={`transition-all duration-1000 ease-in-out ${
|
||||
currentStep >= 3 ? "opacity-100 translate-y-0" : "opacity-0 translate-y-4"
|
||||
}`}
|
||||
>
|
||||
<h1 className="text-4xl lg:text-5xl font-light text-gray-800 text-center lg:text-left">Unwind</h1>
|
||||
</div>
|
||||
|
||||
{/* Heal */}
|
||||
<div
|
||||
className={`transition-all duration-1000 ease-in-out ${
|
||||
currentStep >= 4 ? "opacity-100 translate-y-0" : "opacity-0 translate-y-4"
|
||||
}`}
|
||||
>
|
||||
<h1 className="text-4xl lg:text-5xl font-light text-nature-green text-center lg:text-left">Heal</h1>
|
||||
</div>
|
||||
|
||||
{/* Leave feeling... */}
|
||||
<div
|
||||
className={`transition-all duration-1000 ease-in-out ${
|
||||
currentStep >= 5 ? "opacity-100 translate-y-0" : "opacity-0 translate-y-4"
|
||||
}`}
|
||||
>
|
||||
<p className="text-xl lg:text-2xl font-light text-gray-700 leading-relaxed text-center lg:text-left max-w-lg">
|
||||
Leave feeling relaxed, renewed and able to move with more freedom and ease.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
"use client"
|
||||
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Calendar } from "lucide-react"
|
||||
|
||||
interface ClinicSenseButtonProps {
|
||||
className?: string
|
||||
size?: "small" | "medium" | "large"
|
||||
color?: "black" | "blue" | "green"
|
||||
}
|
||||
|
||||
export default function ClinicSenseButton({ className = "", size = "small", color = "green" }: ClinicSenseButtonProps) {
|
||||
const getSizeClasses = () => {
|
||||
switch (size) {
|
||||
case "small":
|
||||
return "h-9 px-3 text-sm"
|
||||
case "medium":
|
||||
return "h-10 px-4 text-sm"
|
||||
case "large":
|
||||
return "h-11 px-8 text-base"
|
||||
default:
|
||||
return "h-9 px-3 text-sm"
|
||||
}
|
||||
}
|
||||
|
||||
const getColorClasses = () => {
|
||||
switch (color) {
|
||||
case "blue":
|
||||
return "bg-blue-600 hover:bg-blue-700 text-white"
|
||||
case "black":
|
||||
return "bg-gray-900 hover:bg-black text-white"
|
||||
case "green":
|
||||
default:
|
||||
return "bg-nature-green hover:bg-nature-green-dark text-white"
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Button className={`${getSizeClasses()} ${getColorClasses()} ${className} inline-flex items-center gap-2`} asChild>
|
||||
<a href="https://ebbnflowmassage.clinicsense.com" target="_blank" rel="noopener noreferrer">
|
||||
<Calendar className="h-4 w-4" />
|
||||
Book Appointment
|
||||
</a>
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
|
@ -1,129 +0,0 @@
|
|||
import { Mail, MapPin, Phone } from "lucide-react"
|
||||
import Link from "next/link"
|
||||
import Image from "next/image"
|
||||
|
||||
export default function Footer() {
|
||||
return (
|
||||
<footer className="bg-gray-900 text-gray-200">
|
||||
<div className="container mx-auto px-4 py-12">
|
||||
<div className="grid md:grid-cols-4 gap-8">
|
||||
{/* Brand */}
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center space-x-3">
|
||||
<Image
|
||||
src="/images/logo.jpg"
|
||||
alt="Ebb'nFlow Therapeutics Logo"
|
||||
width={32}
|
||||
height={32}
|
||||
className="object-contain"
|
||||
/>
|
||||
<h3 className="text-xl font-light text-white">
|
||||
Ebb'nFlow <span className="font-normal text-nature-green">Therapeutics</span>
|
||||
</h3>
|
||||
</div>
|
||||
<p className="text-sm text-gray-300 leading-relaxed">
|
||||
A boutique wellness sanctuary. One client, one space, one transformative experience at a time. A place to
|
||||
unwind, heal, and grow.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Services */}
|
||||
<div className="space-y-4">
|
||||
<h4 className="font-medium text-white">Services</h4>
|
||||
<ul className="space-y-2 text-sm">
|
||||
<li>
|
||||
<Link href="/#services" className="text-gray-300 hover:text-nature-green transition-colors">
|
||||
Massage Therapy
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/#services" className="text-gray-300 hover:text-nature-green transition-colors">
|
||||
Laser Therapy
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/#services" className="text-gray-300 hover:text-nature-green transition-colors">
|
||||
Movement Therapy
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/contact" className="text-gray-300 hover:text-nature-green transition-colors">
|
||||
Consultation
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* Quick Links */}
|
||||
<div className="space-y-4">
|
||||
<h4 className="font-medium text-white">Quick Links</h4>
|
||||
<ul className="space-y-2 text-sm">
|
||||
<li>
|
||||
<Link href="/about" className="text-gray-300 hover:text-nature-green transition-colors">
|
||||
About
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/#prices" className="text-gray-300 hover:text-nature-green transition-colors">
|
||||
Prices
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/contact" className="text-gray-300 hover:text-nature-green transition-colors">
|
||||
Contact
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/what-to-expect" className="text-gray-300 hover:text-nature-green transition-colors">
|
||||
What to Expect
|
||||
</Link>
|
||||
</li>
|
||||
<li>
|
||||
<Link href="/movement" className="text-gray-300 hover:text-nature-green transition-colors">
|
||||
Movement Workshops
|
||||
</Link>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* Contact Info */}
|
||||
<div className="space-y-4">
|
||||
<h4 className="font-medium text-white">Contact Info</h4>
|
||||
<div className="space-y-3 text-sm">
|
||||
<div className="flex items-start gap-2">
|
||||
<MapPin className="h-4 w-4 text-nature-green mt-0.5" />
|
||||
<span className="text-gray-300">
|
||||
59 Wellington Street
|
||||
<br />
|
||||
St. Catharines, ON L2R 5P9
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Phone className="h-4 w-4 text-nature-green" />
|
||||
<span className="text-gray-300">(289) 969-3219</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Mail className="h-4 w-4 text-nature-green" />
|
||||
<span className="text-gray-300">info@ebbnflowtherapeutics.com</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="border-t border-gray-700 mt-8 pt-8 flex flex-col md:flex-row justify-between items-center">
|
||||
<p className="text-sm text-gray-400">
|
||||
© {new Date().getFullYear()} Ebb'nFlow Therapeutics. All rights reserved.
|
||||
</p>
|
||||
<div className="flex space-x-6 mt-4 md:mt-0">
|
||||
<Link href="#" className="text-sm text-gray-400 hover:text-nature-green transition-colors">
|
||||
Privacy Policy
|
||||
</Link>
|
||||
<Link href="#" className="text-sm text-gray-400 hover:text-nature-green transition-colors">
|
||||
Terms of Service
|
||||
</Link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
)
|
||||
}
|
||||
|
|
@ -1,39 +0,0 @@
|
|||
"use client"
|
||||
|
||||
import { X } from "lucide-react"
|
||||
|
||||
interface InfoModalProps {
|
||||
isOpen: boolean
|
||||
onClose: () => void
|
||||
content: string
|
||||
title: string
|
||||
}
|
||||
|
||||
export default function InfoModal({ isOpen, onClose, content, title }: InfoModalProps) {
|
||||
if (!isOpen) return null
|
||||
|
||||
return (
|
||||
<div className="fixed inset-0 z-50 flex items-center justify-center p-4 bg-black/50" onClick={onClose}>
|
||||
<div
|
||||
className="bg-white rounded-lg shadow-xl max-w-2xl w-full max-h-[80vh] overflow-y-auto"
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<div className="sticky top-0 bg-white border-b border-gray-200 p-4 flex items-center justify-between">
|
||||
<h3 className="text-xl font-medium text-gray-800">{title}</h3>
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="text-gray-500 hover:text-gray-700 transition-colors"
|
||||
aria-label="Close modal"
|
||||
>
|
||||
<X className="h-6 w-6" />
|
||||
</button>
|
||||
</div>
|
||||
<div className="p-6">
|
||||
<div className="prose prose-gray max-w-none">
|
||||
<p className="text-gray-700 leading-relaxed whitespace-pre-line">{content}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -1,120 +0,0 @@
|
|||
"use client"
|
||||
|
||||
import type React from "react"
|
||||
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet"
|
||||
import { Menu } from "lucide-react"
|
||||
import Link from "next/link"
|
||||
import { usePathname } from "next/navigation"
|
||||
import ClinicSenseButton from "@/components/clinicsense-button"
|
||||
import Image from "next/image"
|
||||
|
||||
export default function Navbar() {
|
||||
const pathname = usePathname()
|
||||
|
||||
const handleSmoothScroll = (e: React.MouseEvent<HTMLAnchorElement>, href: string) => {
|
||||
// Only handle smooth scroll if we're on the homepage
|
||||
if (pathname === "/" && href.startsWith("/#")) {
|
||||
e.preventDefault()
|
||||
const targetId = href.substring(2) // Remove "/#" to get the ID
|
||||
const element = document.getElementById(targetId)
|
||||
if (element) {
|
||||
const headerOffset = 80 // Height of sticky header
|
||||
const elementPosition = element.getBoundingClientRect().top
|
||||
const offsetPosition = elementPosition + window.pageYOffset - headerOffset
|
||||
|
||||
window.scrollTo({
|
||||
top: offsetPosition,
|
||||
behavior: "smooth",
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const navItems = [
|
||||
{ href: "/#services", label: "Services" },
|
||||
{ href: "/#prices", label: "Prices" },
|
||||
{ href: "/about", label: "About" },
|
||||
{ href: "/contact", label: "Contact" },
|
||||
]
|
||||
|
||||
return (
|
||||
<header className="sticky top-0 z-50 w-full border-b border-beige bg-white/95 backdrop-blur supports-[backdrop-filter]:bg-white/60">
|
||||
<div className="container mx-auto px-4">
|
||||
<div className="flex h-16 items-center">
|
||||
<div className="grid grid-cols-[1fr_auto_1fr] items-center w-full gap-4">
|
||||
{/* Logo - Left aligned */}
|
||||
<Link href="/" className="flex items-center space-x-3 justify-self-start">
|
||||
<Image
|
||||
src="/images/logo.jpg"
|
||||
alt="Ebb'nFlow Therapeutics Logo"
|
||||
width={40}
|
||||
height={40}
|
||||
className="object-contain"
|
||||
/>
|
||||
<div className="text-xl font-light text-gray-800 hidden lg:block">
|
||||
Ebb'nFlow <span className="font-normal text-nature-green">Therapeutics</span>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
{/* Desktop Navigation - Centered */}
|
||||
<nav className="hidden md:flex items-center justify-center">
|
||||
<div className="flex items-center space-x-6 lg:space-x-8">
|
||||
{navItems.map((item) => (
|
||||
<Link
|
||||
key={item.href}
|
||||
href={item.href}
|
||||
onClick={(e) => handleSmoothScroll(e, item.href)}
|
||||
className={`text-sm font-medium transition-colors hover:text-nature-green whitespace-nowrap ${
|
||||
pathname === item.href ? "text-nature-green border-b-2 border-nature-green pb-1" : "text-gray-600"
|
||||
}`}
|
||||
>
|
||||
{item.label}
|
||||
</Link>
|
||||
))}
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
{/* Desktop CTA - Right aligned */}
|
||||
<div className="hidden md:flex justify-self-end">
|
||||
<ClinicSenseButton size="small" color="green" />
|
||||
</div>
|
||||
|
||||
{/* Mobile Navigation Button */}
|
||||
<Sheet>
|
||||
<SheetTrigger asChild>
|
||||
<Button variant="ghost" size="icon" className="md:hidden ml-auto">
|
||||
<Menu className="h-5 w-5" />
|
||||
<span className="sr-only">Toggle menu</span>
|
||||
</Button>
|
||||
</SheetTrigger>
|
||||
<SheetContent side="right" className="w-[300px] sm:w-[400px]">
|
||||
<div className="flex flex-col space-y-4 mt-8">
|
||||
<Link href="/" className="text-lg font-light text-gray-800 mb-4">
|
||||
Ebb'nFlow <span className="font-normal text-nature-green">Therapeutics</span>
|
||||
</Link>
|
||||
{navItems.map((item) => (
|
||||
<Link
|
||||
key={item.href}
|
||||
href={item.href}
|
||||
onClick={(e) => handleSmoothScroll(e, item.href)}
|
||||
className={`text-lg font-medium transition-colors hover:text-nature-green ${
|
||||
pathname === item.href ? "text-nature-green" : "text-gray-600"
|
||||
}`}
|
||||
>
|
||||
{item.label}
|
||||
</Link>
|
||||
))}
|
||||
<div className="pt-4">
|
||||
<ClinicSenseButton className="w-full" size="small" color="green" />
|
||||
</div>
|
||||
</div>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
)
|
||||
}
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
"use client"
|
||||
|
||||
import { useState } from "react"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { ChevronDown, ChevronUp } from "lucide-react"
|
||||
import Link from "next/link"
|
||||
|
||||
interface DropdownItem {
|
||||
title: string
|
||||
href?: string
|
||||
modal?: string
|
||||
}
|
||||
|
||||
interface ServiceDropdownProps {
|
||||
items: DropdownItem[]
|
||||
title: string
|
||||
onModalOpen?: (content: string, title: string) => void
|
||||
}
|
||||
|
||||
export default function ServiceDropdown({ items, title, onModalOpen }: ServiceDropdownProps) {
|
||||
const [isOpen, setIsOpen] = useState(false)
|
||||
|
||||
const handleItemClick = (item: DropdownItem) => {
|
||||
if (item.modal && onModalOpen) {
|
||||
onModalOpen(item.modal, item.title)
|
||||
}
|
||||
setIsOpen(false)
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="relative">
|
||||
<Button
|
||||
variant="outline"
|
||||
className="w-full border-nature-green text-nature-green hover:bg-green-100 justify-between bg-transparent"
|
||||
onClick={() => setIsOpen(!isOpen)}
|
||||
>
|
||||
{title}
|
||||
{isOpen ? <ChevronUp className="h-4 w-4" /> : <ChevronDown className="h-4 w-4" />}
|
||||
</Button>
|
||||
|
||||
{isOpen && (
|
||||
<div className="absolute top-full left-0 right-0 mt-1 bg-white border border-green-200 rounded-md shadow-lg z-10">
|
||||
{items.map((item, index) =>
|
||||
item.href ? (
|
||||
<Link
|
||||
key={index}
|
||||
href={item.href}
|
||||
className="block px-4 py-3 text-sm text-gray-700 hover:bg-green-50 border-b border-green-100 last:border-b-0"
|
||||
onClick={() => setIsOpen(false)}
|
||||
>
|
||||
{item.title}
|
||||
</Link>
|
||||
) : (
|
||||
<button
|
||||
key={index}
|
||||
onClick={() => handleItemClick(item)}
|
||||
className="w-full text-left px-4 py-3 text-sm text-gray-700 hover:bg-green-50 border-b border-green-100 last:border-b-0"
|
||||
>
|
||||
{item.title}
|
||||
</button>
|
||||
),
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
@ -1,11 +0,0 @@
|
|||
'use client'
|
||||
|
||||
import * as React from 'react'
|
||||
import {
|
||||
ThemeProvider as NextThemesProvider,
|
||||
type ThemeProviderProps,
|
||||
} from 'next-themes'
|
||||
|
||||
export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
|
||||
return <NextThemesProvider {...props}>{children}</NextThemesProvider>
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
import * as React from 'react'
|
||||
import { Slot } from '@radix-ui/react-slot'
|
||||
import { cva, type VariantProps } from 'class-variance-authority'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const badgeVariants = cva(
|
||||
'inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden',
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default:
|
||||
'border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90',
|
||||
secondary:
|
||||
'border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90',
|
||||
destructive:
|
||||
'border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',
|
||||
outline:
|
||||
'text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: 'default',
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
function Badge({
|
||||
className,
|
||||
variant,
|
||||
asChild = false,
|
||||
...props
|
||||
}: React.ComponentProps<'span'> &
|
||||
VariantProps<typeof badgeVariants> & { asChild?: boolean }) {
|
||||
const Comp = asChild ? Slot : 'span'
|
||||
|
||||
return (
|
||||
<Comp
|
||||
data-slot="badge"
|
||||
className={cn(badgeVariants({ variant }), className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export { Badge, badgeVariants }
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
import * as React from 'react'
|
||||
import { Slot } from '@radix-ui/react-slot'
|
||||
import { cva, type VariantProps } from 'class-variance-authority'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
const buttonVariants = cva(
|
||||
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default:
|
||||
'bg-primary text-primary-foreground shadow-xs hover:bg-primary/90',
|
||||
destructive:
|
||||
'bg-destructive text-white shadow-xs hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60',
|
||||
outline:
|
||||
'border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50',
|
||||
secondary:
|
||||
'bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80',
|
||||
ghost:
|
||||
'hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50',
|
||||
link: 'text-primary underline-offset-4 hover:underline',
|
||||
},
|
||||
size: {
|
||||
default: 'h-9 px-4 py-2 has-[>svg]:px-3',
|
||||
sm: 'h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5',
|
||||
lg: 'h-10 rounded-md px-6 has-[>svg]:px-4',
|
||||
icon: 'size-9',
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: 'default',
|
||||
size: 'default',
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
function Button({
|
||||
className,
|
||||
variant,
|
||||
size,
|
||||
asChild = false,
|
||||
...props
|
||||
}: React.ComponentProps<'button'> &
|
||||
VariantProps<typeof buttonVariants> & {
|
||||
asChild?: boolean
|
||||
}) {
|
||||
const Comp = asChild ? Slot : 'button'
|
||||
|
||||
return (
|
||||
<Comp
|
||||
data-slot="button"
|
||||
className={cn(buttonVariants({ variant, size, className }))}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export { Button, buttonVariants }
|
||||
|
|
@ -1,92 +0,0 @@
|
|||
import * as React from 'react'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
function Card({ className, ...props }: React.ComponentProps<'div'>) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card"
|
||||
className={cn(
|
||||
'bg-card text-card-foreground flex flex-col gap-6 rounded-xl border py-6 shadow-sm',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function CardHeader({ className, ...props }: React.ComponentProps<'div'>) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-header"
|
||||
className={cn(
|
||||
'@container/card-header grid auto-rows-min grid-rows-[auto_auto] items-start gap-1.5 px-6 has-data-[slot=card-action]:grid-cols-[1fr_auto] [.border-b]:pb-6',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function CardTitle({ className, ...props }: React.ComponentProps<'div'>) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-title"
|
||||
className={cn('leading-none font-semibold', className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function CardDescription({ className, ...props }: React.ComponentProps<'div'>) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-description"
|
||||
className={cn('text-muted-foreground text-sm', className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function CardAction({ className, ...props }: React.ComponentProps<'div'>) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-action"
|
||||
className={cn(
|
||||
'col-start-2 row-span-2 row-start-1 self-start justify-self-end',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function CardContent({ className, ...props }: React.ComponentProps<'div'>) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-content"
|
||||
className={cn('px-6', className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function CardFooter({ className, ...props }: React.ComponentProps<'div'>) {
|
||||
return (
|
||||
<div
|
||||
data-slot="card-footer"
|
||||
className={cn('flex items-center px-6 [.border-t]:pt-6', className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export {
|
||||
Card,
|
||||
CardHeader,
|
||||
CardFooter,
|
||||
CardTitle,
|
||||
CardAction,
|
||||
CardDescription,
|
||||
CardContent,
|
||||
}
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
import * as React from 'react'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
function Input({ className, type, ...props }: React.ComponentProps<'input'>) {
|
||||
return (
|
||||
<input
|
||||
type={type}
|
||||
data-slot="input"
|
||||
className={cn(
|
||||
'file:text-foreground placeholder:text-muted-foreground selection:bg-primary selection:text-primary-foreground dark:bg-input/30 border-input flex h-9 w-full min-w-0 rounded-md border bg-transparent px-3 py-1 text-base shadow-xs transition-[color,box-shadow] outline-none file:inline-flex file:h-7 file:border-0 file:bg-transparent file:text-sm file:font-medium disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
|
||||
'focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]',
|
||||
'aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export { Input }
|
||||
|
|
@ -1,24 +0,0 @@
|
|||
'use client'
|
||||
|
||||
import * as React from 'react'
|
||||
import * as LabelPrimitive from '@radix-ui/react-label'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
function Label({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof LabelPrimitive.Root>) {
|
||||
return (
|
||||
<LabelPrimitive.Root
|
||||
data-slot="label"
|
||||
className={cn(
|
||||
'flex items-center gap-2 text-sm leading-none font-medium select-none group-data-[disabled=true]:pointer-events-none group-data-[disabled=true]:opacity-50 peer-disabled:cursor-not-allowed peer-disabled:opacity-50',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export { Label }
|
||||
|
|
@ -1,139 +0,0 @@
|
|||
'use client'
|
||||
|
||||
import * as React from 'react'
|
||||
import * as SheetPrimitive from '@radix-ui/react-dialog'
|
||||
import { XIcon } from 'lucide-react'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
function Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) {
|
||||
return <SheetPrimitive.Root data-slot="sheet" {...props} />
|
||||
}
|
||||
|
||||
function SheetTrigger({
|
||||
...props
|
||||
}: React.ComponentProps<typeof SheetPrimitive.Trigger>) {
|
||||
return <SheetPrimitive.Trigger data-slot="sheet-trigger" {...props} />
|
||||
}
|
||||
|
||||
function SheetClose({
|
||||
...props
|
||||
}: React.ComponentProps<typeof SheetPrimitive.Close>) {
|
||||
return <SheetPrimitive.Close data-slot="sheet-close" {...props} />
|
||||
}
|
||||
|
||||
function SheetPortal({
|
||||
...props
|
||||
}: React.ComponentProps<typeof SheetPrimitive.Portal>) {
|
||||
return <SheetPrimitive.Portal data-slot="sheet-portal" {...props} />
|
||||
}
|
||||
|
||||
function SheetOverlay({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof SheetPrimitive.Overlay>) {
|
||||
return (
|
||||
<SheetPrimitive.Overlay
|
||||
data-slot="sheet-overlay"
|
||||
className={cn(
|
||||
'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function SheetContent({
|
||||
className,
|
||||
children,
|
||||
side = 'right',
|
||||
...props
|
||||
}: React.ComponentProps<typeof SheetPrimitive.Content> & {
|
||||
side?: 'top' | 'right' | 'bottom' | 'left'
|
||||
}) {
|
||||
return (
|
||||
<SheetPortal>
|
||||
<SheetOverlay />
|
||||
<SheetPrimitive.Content
|
||||
data-slot="sheet-content"
|
||||
className={cn(
|
||||
'bg-background data-[state=open]:animate-in data-[state=closed]:animate-out fixed z-50 flex flex-col gap-4 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500',
|
||||
side === 'right' &&
|
||||
'data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right inset-y-0 right-0 h-full w-3/4 border-l sm:max-w-sm',
|
||||
side === 'left' &&
|
||||
'data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left inset-y-0 left-0 h-full w-3/4 border-r sm:max-w-sm',
|
||||
side === 'top' &&
|
||||
'data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top inset-x-0 top-0 h-auto border-b',
|
||||
side === 'bottom' &&
|
||||
'data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom inset-x-0 bottom-0 h-auto border-t',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
<SheetPrimitive.Close className="ring-offset-background focus:ring-ring data-[state=open]:bg-secondary absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none">
|
||||
<XIcon className="size-4" />
|
||||
<span className="sr-only">Close</span>
|
||||
</SheetPrimitive.Close>
|
||||
</SheetPrimitive.Content>
|
||||
</SheetPortal>
|
||||
)
|
||||
}
|
||||
|
||||
function SheetHeader({ className, ...props }: React.ComponentProps<'div'>) {
|
||||
return (
|
||||
<div
|
||||
data-slot="sheet-header"
|
||||
className={cn('flex flex-col gap-1.5 p-4', className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function SheetFooter({ className, ...props }: React.ComponentProps<'div'>) {
|
||||
return (
|
||||
<div
|
||||
data-slot="sheet-footer"
|
||||
className={cn('mt-auto flex flex-col gap-2 p-4', className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function SheetTitle({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof SheetPrimitive.Title>) {
|
||||
return (
|
||||
<SheetPrimitive.Title
|
||||
data-slot="sheet-title"
|
||||
className={cn('text-foreground font-semibold', className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
function SheetDescription({
|
||||
className,
|
||||
...props
|
||||
}: React.ComponentProps<typeof SheetPrimitive.Description>) {
|
||||
return (
|
||||
<SheetPrimitive.Description
|
||||
data-slot="sheet-description"
|
||||
className={cn('text-muted-foreground text-sm', className)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export {
|
||||
Sheet,
|
||||
SheetTrigger,
|
||||
SheetClose,
|
||||
SheetContent,
|
||||
SheetHeader,
|
||||
SheetFooter,
|
||||
SheetTitle,
|
||||
SheetDescription,
|
||||
}
|
||||
|
|
@ -1,18 +0,0 @@
|
|||
import * as React from 'react'
|
||||
|
||||
import { cn } from '@/lib/utils'
|
||||
|
||||
function Textarea({ className, ...props }: React.ComponentProps<'textarea'>) {
|
||||
return (
|
||||
<textarea
|
||||
data-slot="textarea"
|
||||
className={cn(
|
||||
'border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export { Textarea }
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
<div class="container">
|
||||
<nav>
|
||||
<a href="/" class="logo">
|
||||
<img src="images/logo.jpg" alt="Ebb'nFlow Therapeutics Logo">
|
||||
<img src="./images/logo.jpg" alt="Ebb'nFlow Therapeutics Logo">
|
||||
<span class="logo-text">Ebb'nFlow <span class="highlight">Therapeutics</span></span>
|
||||
</a>
|
||||
|
||||
|
|
@ -56,11 +56,11 @@
|
|||
<div class="container">
|
||||
<div class="image-grid">
|
||||
<div class="image-card">
|
||||
<img src="images/clinic-exterior.jpg" alt="Ebb'nFlow Therapeutics clinic exterior">
|
||||
<img src="./images/clinic-exterior.jpg" alt="Ebb'nFlow Therapeutics clinic exterior">
|
||||
<div class="image-caption">Our Welcoming Exterior</div>
|
||||
</div>
|
||||
<div class="image-card">
|
||||
<img src="images/yellow-door.jpg" alt="Distinctive yellow entrance door">
|
||||
<img src="./images/yellow-door.jpg" alt="Distinctive yellow entrance door">
|
||||
<div class="image-caption">Find Our Yellow Door</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -163,7 +163,7 @@
|
|||
<div class="container">
|
||||
<div class="footer-grid">
|
||||
<div class="footer-brand">
|
||||
<img src="images/logo.jpg" alt="Ebb'nFlow Therapeutics Logo">
|
||||
<img src="./images/logo.jpg" alt="Ebb'nFlow Therapeutics Logo">
|
||||
<h3>Ebb'nFlow <span class="highlight">Therapeutics</span></h3>
|
||||
<p>A boutique wellness sanctuary. One client, one space, one transformative experience at a time.</p>
|
||||
</div>
|
||||
|
|
|
|||
14
index.html
14
index.html
|
|
@ -16,7 +16,7 @@
|
|||
<div class="container">
|
||||
<nav>
|
||||
<a href="/" class="logo">
|
||||
<img src="images/logo.jpg" alt="Ebb'nFlow Therapeutics Logo">
|
||||
<img src="./images/logo.jpg" alt="Ebb'nFlow Therapeutics Logo">
|
||||
<span class="logo-text">Ebb'nFlow <span class="highlight">Therapeutics</span></span>
|
||||
</a>
|
||||
|
||||
|
|
@ -57,7 +57,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="hero-image">
|
||||
<img src="images/reception-area.jpg" alt="Welcoming reception area at Ebb'nFlow Therapeutics">
|
||||
<img src="./images/reception-area.jpg" alt="Welcoming reception area at Ebb'nFlow Therapeutics">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -82,7 +82,7 @@
|
|||
<div class="services-grid">
|
||||
<!-- Massage Therapy -->
|
||||
<div class="service-card">
|
||||
<img src="images/treatment-room.jpg" alt="Professional massage therapy treatment room">
|
||||
<img src="./images/treatment-room.jpg" alt="Professional massage therapy treatment room">
|
||||
<div class="service-content">
|
||||
<h3>Massage Therapy Treatment</h3>
|
||||
<p>General Swedish Massage combined with specialized techniques tailored to your specific needs.</p>
|
||||
|
|
@ -93,7 +93,7 @@
|
|||
|
||||
<!-- Laser Therapy -->
|
||||
<div class="service-card">
|
||||
<img src="images/bioflex-laser.png" alt="BioFlex Laser Therapy">
|
||||
<img src="./images/bioflex-laser.png" alt="BioFlex Laser Therapy">
|
||||
<div class="service-content">
|
||||
<h3>Laser Therapy Treatment</h3>
|
||||
<p>Stand alone or combined with Massage Therapy (recommended). Laser therapy provides accelerated healing for musculoskeletal injury, wounds, arthritis, and nerve injury.</p>
|
||||
|
|
@ -104,7 +104,7 @@
|
|||
|
||||
<!-- Movement Education -->
|
||||
<div class="service-card">
|
||||
<img src="images/movement-class.png" alt="Movement education class">
|
||||
<img src="./images/movement-class.png" alt="Movement education class">
|
||||
<div class="service-content">
|
||||
<h3>Movement Education</h3>
|
||||
<p>Remedial exercise instruction involves teaching targeted strength, stretch or mobility exercises that further the benefits of massage therapy long term.</p>
|
||||
|
|
@ -191,7 +191,7 @@
|
|||
<a href="contact.html" class="btn btn-primary">Contact Dahlia</a>
|
||||
</div>
|
||||
<div class="rmt-badge">
|
||||
<img src="images/rmt-certification.png" alt="Registered Massage Therapist - Professional Hands You Can Trust">
|
||||
<img src="./images/rmt-certification.png" alt="Registered Massage Therapist - Professional Hands You Can Trust">
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -201,7 +201,7 @@
|
|||
<div class="container">
|
||||
<div class="footer-grid">
|
||||
<div class="footer-brand">
|
||||
<img src="images/logo.jpg" alt="Ebb'nFlow Therapeutics Logo">
|
||||
<img src="./images/logo.jpg" alt="Ebb'nFlow Therapeutics Logo">
|
||||
<h3>Ebb'nFlow <span class="highlight">Therapeutics</span></h3>
|
||||
<p>A boutique wellness sanctuary. One client, one space, one transformative experience at a time.</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
import { clsx, type ClassValue } from 'clsx'
|
||||
import { twMerge } from 'tailwind-merge'
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
<div class="container">
|
||||
<nav>
|
||||
<a href="/" class="logo">
|
||||
<img src="images/logo.jpg" alt="Ebb'nFlow Therapeutics Logo">
|
||||
<img src="./images/logo.jpg" alt="Ebb'nFlow Therapeutics Logo">
|
||||
<span class="logo-text">Ebb'nFlow <span class="highlight">Therapeutics</span></span>
|
||||
</a>
|
||||
|
||||
|
|
@ -127,7 +127,7 @@
|
|||
</div>
|
||||
|
||||
<div class="content-image">
|
||||
<img src="images/dahlia-portrait.jpg" alt="Dahlia Steinberg - Movement and wellness educator">
|
||||
<img src="./images/dahlia-portrait.jpg" alt="Dahlia Steinberg - Movement and wellness educator">
|
||||
<div class="image-caption">Dahlia - Your Movement Guide</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -163,7 +163,7 @@
|
|||
<div class="container">
|
||||
<div class="footer-grid">
|
||||
<div class="footer-brand">
|
||||
<img src="images/logo.jpg" alt="Ebb'nFlow Therapeutics Logo">
|
||||
<img src="./images/logo.jpg" alt="Ebb'nFlow Therapeutics Logo">
|
||||
<h3>Ebb'nFlow <span class="highlight">Therapeutics</span></h3>
|
||||
<p>A boutique wellness sanctuary. One client, one space, one transformative experience at a time.</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
/** @type {import('next').NextConfig} */
|
||||
const nextConfig = {
|
||||
eslint: {
|
||||
ignoreDuringBuilds: true,
|
||||
},
|
||||
typescript: {
|
||||
ignoreBuildErrors: true,
|
||||
},
|
||||
images: {
|
||||
unoptimized: true,
|
||||
},
|
||||
}
|
||||
|
||||
export default nextConfig
|
||||
39
package.json
39
package.json
|
|
@ -1,43 +1,8 @@
|
|||
{
|
||||
"name": "ebb-n-flow-therapeutics",
|
||||
"name": "my-v0-project",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "next build",
|
||||
"dev": "next dev",
|
||||
"lint": "next lint",
|
||||
"start": "next start"
|
||||
},
|
||||
"dependencies": {
|
||||
"@radix-ui/react-accordion": "^1.2.2",
|
||||
"@radix-ui/react-alert-dialog": "^1.1.4",
|
||||
"@radix-ui/react-avatar": "^1.1.2",
|
||||
"@radix-ui/react-checkbox": "^1.1.3",
|
||||
"@radix-ui/react-dialog": "latest",
|
||||
"@radix-ui/react-dropdown-menu": "^2.1.4",
|
||||
"@radix-ui/react-label": "latest",
|
||||
"@radix-ui/react-scroll-area": "^1.2.2",
|
||||
"@radix-ui/react-separator": "^1.1.1",
|
||||
"@radix-ui/react-slot": "latest",
|
||||
"@radix-ui/react-tabs": "^1.1.2",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"lucide-react": "^0.454.0",
|
||||
"next": "15.2.4",
|
||||
"next-themes": "latest",
|
||||
"react": "^19",
|
||||
"react-dom": "^19",
|
||||
"tailwind-merge": "^2.5.5",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"tw-animate-css": "latest"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tailwindcss/postcss": "^4.1.9",
|
||||
"@types/node": "^22",
|
||||
"@types/react": "^19",
|
||||
"@types/react-dom": "^19",
|
||||
"postcss": "^8.5",
|
||||
"tailwindcss": "^4.1.9",
|
||||
"typescript": "^5"
|
||||
"build": "echo 'no build script'"
|
||||
}
|
||||
}
|
||||
2343
pnpm-lock.yaml
2343
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
|
|
@ -1,8 +0,0 @@
|
|||
/** @type {import('postcss-load-config').Config} */
|
||||
const config = {
|
||||
plugins: {
|
||||
'@tailwindcss/postcss': {},
|
||||
},
|
||||
}
|
||||
|
||||
export default config
|
||||
|
|
@ -1,125 +0,0 @@
|
|||
@import 'tailwindcss';
|
||||
@import 'tw-animate-css';
|
||||
|
||||
@custom-variant dark (&:is(.dark *));
|
||||
|
||||
:root {
|
||||
--background: oklch(1 0 0);
|
||||
--foreground: oklch(0.145 0 0);
|
||||
--card: oklch(1 0 0);
|
||||
--card-foreground: oklch(0.145 0 0);
|
||||
--popover: oklch(1 0 0);
|
||||
--popover-foreground: oklch(0.145 0 0);
|
||||
--primary: oklch(0.205 0 0);
|
||||
--primary-foreground: oklch(0.985 0 0);
|
||||
--secondary: oklch(0.97 0 0);
|
||||
--secondary-foreground: oklch(0.205 0 0);
|
||||
--muted: oklch(0.97 0 0);
|
||||
--muted-foreground: oklch(0.556 0 0);
|
||||
--accent: oklch(0.97 0 0);
|
||||
--accent-foreground: oklch(0.205 0 0);
|
||||
--destructive: oklch(0.577 0.245 27.325);
|
||||
--destructive-foreground: oklch(0.577 0.245 27.325);
|
||||
--border: oklch(0.922 0 0);
|
||||
--input: oklch(0.922 0 0);
|
||||
--ring: oklch(0.708 0 0);
|
||||
--chart-1: oklch(0.646 0.222 41.116);
|
||||
--chart-2: oklch(0.6 0.118 184.704);
|
||||
--chart-3: oklch(0.398 0.07 227.392);
|
||||
--chart-4: oklch(0.828 0.189 84.429);
|
||||
--chart-5: oklch(0.769 0.188 70.08);
|
||||
--radius: 0.625rem;
|
||||
--sidebar: oklch(0.985 0 0);
|
||||
--sidebar-foreground: oklch(0.145 0 0);
|
||||
--sidebar-primary: oklch(0.205 0 0);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
--sidebar-accent: oklch(0.97 0 0);
|
||||
--sidebar-accent-foreground: oklch(0.205 0 0);
|
||||
--sidebar-border: oklch(0.922 0 0);
|
||||
--sidebar-ring: oklch(0.708 0 0);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--background: oklch(0.145 0 0);
|
||||
--foreground: oklch(0.985 0 0);
|
||||
--card: oklch(0.145 0 0);
|
||||
--card-foreground: oklch(0.985 0 0);
|
||||
--popover: oklch(0.145 0 0);
|
||||
--popover-foreground: oklch(0.985 0 0);
|
||||
--primary: oklch(0.985 0 0);
|
||||
--primary-foreground: oklch(0.205 0 0);
|
||||
--secondary: oklch(0.269 0 0);
|
||||
--secondary-foreground: oklch(0.985 0 0);
|
||||
--muted: oklch(0.269 0 0);
|
||||
--muted-foreground: oklch(0.708 0 0);
|
||||
--accent: oklch(0.269 0 0);
|
||||
--accent-foreground: oklch(0.985 0 0);
|
||||
--destructive: oklch(0.396 0.141 25.723);
|
||||
--destructive-foreground: oklch(0.637 0.237 25.331);
|
||||
--border: oklch(0.269 0 0);
|
||||
--input: oklch(0.269 0 0);
|
||||
--ring: oklch(0.439 0 0);
|
||||
--chart-1: oklch(0.488 0.243 264.376);
|
||||
--chart-2: oklch(0.696 0.17 162.48);
|
||||
--chart-3: oklch(0.769 0.188 70.08);
|
||||
--chart-4: oklch(0.627 0.265 303.9);
|
||||
--chart-5: oklch(0.645 0.246 16.439);
|
||||
--sidebar: oklch(0.205 0 0);
|
||||
--sidebar-foreground: oklch(0.985 0 0);
|
||||
--sidebar-primary: oklch(0.488 0.243 264.376);
|
||||
--sidebar-primary-foreground: oklch(0.985 0 0);
|
||||
--sidebar-accent: oklch(0.269 0 0);
|
||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
||||
--sidebar-border: oklch(0.269 0 0);
|
||||
--sidebar-ring: oklch(0.439 0 0);
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
--font-sans: var(--font-geist-sans);
|
||||
--font-mono: var(--font-geist-mono);
|
||||
--color-background: var(--background);
|
||||
--color-foreground: var(--foreground);
|
||||
--color-card: var(--card);
|
||||
--color-card-foreground: var(--card-foreground);
|
||||
--color-popover: var(--popover);
|
||||
--color-popover-foreground: var(--popover-foreground);
|
||||
--color-primary: var(--primary);
|
||||
--color-primary-foreground: var(--primary-foreground);
|
||||
--color-secondary: var(--secondary);
|
||||
--color-secondary-foreground: var(--secondary-foreground);
|
||||
--color-muted: var(--muted);
|
||||
--color-muted-foreground: var(--muted-foreground);
|
||||
--color-accent: var(--accent);
|
||||
--color-accent-foreground: var(--accent-foreground);
|
||||
--color-destructive: var(--destructive);
|
||||
--color-destructive-foreground: var(--destructive-foreground);
|
||||
--color-border: var(--border);
|
||||
--color-input: var(--input);
|
||||
--color-ring: var(--ring);
|
||||
--color-chart-1: var(--chart-1);
|
||||
--color-chart-2: var(--chart-2);
|
||||
--color-chart-3: var(--chart-3);
|
||||
--color-chart-4: var(--chart-4);
|
||||
--color-chart-5: var(--chart-5);
|
||||
--radius-sm: calc(var(--radius) - 4px);
|
||||
--radius-md: calc(var(--radius) - 2px);
|
||||
--radius-lg: var(--radius);
|
||||
--radius-xl: calc(var(--radius) + 4px);
|
||||
--color-sidebar: var(--sidebar);
|
||||
--color-sidebar-foreground: var(--sidebar-foreground);
|
||||
--color-sidebar-primary: var(--sidebar-primary);
|
||||
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
||||
--color-sidebar-accent: var(--sidebar-accent);
|
||||
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
||||
--color-sidebar-border: var(--sidebar-border);
|
||||
--color-sidebar-ring: var(--sidebar-ring);
|
||||
}
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border outline-ring/50;
|
||||
}
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,27 +0,0 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
"allowJs": true,
|
||||
"target": "ES6",
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"noEmit": true,
|
||||
"esModuleInterop": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "bundler",
|
||||
"resolveJsonModule": true,
|
||||
"isolatedModules": true,
|
||||
"jsx": "preserve",
|
||||
"incremental": true,
|
||||
"plugins": [
|
||||
{
|
||||
"name": "next"
|
||||
}
|
||||
],
|
||||
"paths": {
|
||||
"@/*": ["./*"]
|
||||
}
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
<div class="container">
|
||||
<nav>
|
||||
<a href="/" class="logo">
|
||||
<img src="images/logo.jpg" alt="Ebb'nFlow Therapeutics Logo">
|
||||
<img src="./images/logo.jpg" alt="Ebb'nFlow Therapeutics Logo">
|
||||
<span class="logo-text">Ebb'nFlow <span class="highlight">Therapeutics</span></span>
|
||||
</a>
|
||||
|
||||
|
|
@ -139,7 +139,7 @@
|
|||
|
||||
<div class="experience-visual">
|
||||
<div class="content-image">
|
||||
<img src="images/treatment-room.jpg" alt="Professional treatment room setup">
|
||||
<img src="./images/treatment-room.jpg" alt="Professional treatment room setup">
|
||||
<div class="image-caption">Your Private Treatment Space</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -190,7 +190,7 @@
|
|||
<div class="container">
|
||||
<div class="footer-grid">
|
||||
<div class="footer-brand">
|
||||
<img src="images/logo.jpg" alt="Ebb'nFlow Therapeutics Logo">
|
||||
<img src="./images/logo.jpg" alt="Ebb'nFlow Therapeutics Logo">
|
||||
<h3>Ebb'nFlow <span class="highlight">Therapeutics</span></h3>
|
||||
<p>A boutique wellness sanctuary. One client, one space, one transformative experience at a time.</p>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
name = "ebb-n-flow-website"
|
||||
compatibility_date = "2024-01-01"
|
||||
|
||||
pages_build_output_dir = "."
|
||||
# No build configuration needed for static files
|
||||
|
|
|
|||
Loading…
Reference in New Issue