170 lines
5.7 KiB
TypeScript
170 lines
5.7 KiB
TypeScript
import React, { useState } from 'react';
|
|
import { Link } from 'react-router-dom';
|
|
import { motion, AnimatePresence } from 'framer-motion';
|
|
import Modal from 'react-modal';
|
|
|
|
const Header: React.FC = () => {
|
|
const [isMenuOpen, setIsMenuOpen] = useState(false);
|
|
|
|
return (
|
|
<header className="bg-[#8C1D40] text-white shadow-md">
|
|
<div className="container mx-auto px-4 py-4">
|
|
<div className="flex justify-between items-center">
|
|
<div className="flex items-center">
|
|
<img src="/mcdi-logo-small.png" alt="MCDi Logo" className="w-12 h-12 md:w-20 md:h-20 mr-2 md:mr-4" />
|
|
<h1 className="text-lg md:text-2xl font-bold">Missoula Council of the Deaf, Inc</h1>
|
|
</div>
|
|
<nav className="hidden md:block">
|
|
<ul className="flex space-x-6 items-center">
|
|
<li><NavItem href="/">Home</NavItem></li>
|
|
<li><AboutDropdown /></li>
|
|
<li><NavItem href="/calendar">Calendar</NavItem></li>
|
|
<li><NavItem href="/joinmcdi">Join MCDi</NavItem></li>
|
|
<li><DonateButton /></li>
|
|
</ul>
|
|
</nav>
|
|
<button
|
|
className="md:hidden text-white"
|
|
onClick={() => setIsMenuOpen(!isMenuOpen)}
|
|
>
|
|
<svg className="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
|
|
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M4 6h16M4 12h16m-7 6h7" />
|
|
</svg>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
<AnimatePresence>
|
|
{isMenuOpen && (
|
|
<motion.div
|
|
initial={{ opacity: 0, height: 0 }}
|
|
animate={{ opacity: 1, height: 'auto' }}
|
|
exit={{ opacity: 0, height: 0 }}
|
|
className="md:hidden bg-[#8C1D40] px-4 py-2"
|
|
>
|
|
<ul className="space-y-2">
|
|
<li><NavItem href="/" onClick={() => setIsMenuOpen(false)}>Home</NavItem></li>
|
|
<li><NavItem href="/about" onClick={() => setIsMenuOpen(false)}>About MCDi</NavItem></li>
|
|
<li><NavItem href="/calendar" onClick={() => setIsMenuOpen(false)}>Calendar</NavItem></li>
|
|
<li><NavItem href="/joinmcdi" onClick={() => setIsMenuOpen(false)}>Join MCDi</NavItem></li>
|
|
<li><DonateButton onClick={() => setIsMenuOpen(false)} /></li>
|
|
</ul>
|
|
</motion.div>
|
|
)}
|
|
</AnimatePresence>
|
|
</header>
|
|
);
|
|
};
|
|
|
|
interface NavItemProps {
|
|
href: string;
|
|
children: React.ReactNode;
|
|
onClick?: () => void;
|
|
}
|
|
|
|
const NavItem: React.FC<NavItemProps> = ({ href, children, onClick }) => (
|
|
<Link to={href} className="block hover:text-yellow-200 transition-colors duration-200" onClick={onClick}>
|
|
<motion.span whileHover={{ scale: 1.05 }} className="inline-block">
|
|
{children}
|
|
</motion.span>
|
|
</Link>
|
|
);
|
|
|
|
const AboutDropdown: React.FC = () => {
|
|
const [isOpen, setIsOpen] = useState(false);
|
|
|
|
return (
|
|
<div
|
|
className="relative"
|
|
onMouseEnter={() => setIsOpen(true)}
|
|
onMouseLeave={() => setIsOpen(false)}
|
|
>
|
|
<Link
|
|
to="/about"
|
|
className="hover:text-yellow-200 transition-colors duration-200"
|
|
>
|
|
<motion.span whileHover={{ scale: 1.05 }} className="inline-block">
|
|
About MCDi
|
|
</motion.span>
|
|
</Link>
|
|
<AnimatePresence>
|
|
{isOpen && (
|
|
<motion.div
|
|
initial={{ opacity: 0, y: -10 }}
|
|
animate={{ opacity: 1, y: 0 }}
|
|
exit={{ opacity: 0, y: -10 }}
|
|
className="absolute left-0 mt-2 w-48 bg-[#8C1D40] rounded-md shadow-lg z-10"
|
|
>
|
|
<div className="py-1">
|
|
<DropdownItem href="/meet-board">Meet MCDi Board</DropdownItem>
|
|
<DropdownItem href="/bylaws">Bylaws</DropdownItem>
|
|
<DropdownItem href="/minutes">Minutes</DropdownItem>
|
|
<DropdownItem href="/sponsors">Sponsors</DropdownItem>
|
|
</div>
|
|
</motion.div>
|
|
)}
|
|
</AnimatePresence>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
const DropdownItem: React.FC<NavItemProps> = ({ href, children }) => (
|
|
<Link to={href} className="block px-4 py-2 hover:bg-[#6B1631] transition-colors duration-200">
|
|
<motion.span whileHover={{ x: 5 }} className="inline-block">
|
|
{children}
|
|
</motion.span>
|
|
</Link>
|
|
);
|
|
|
|
const DonateButton: React.FC<{ onClick?: () => void }> = ({ onClick }) => {
|
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
|
|
|
const handleDonateClick = () => {
|
|
setIsModalOpen(true);
|
|
if (onClick) onClick();
|
|
};
|
|
|
|
const closeModal = () => {
|
|
setIsModalOpen(false);
|
|
};
|
|
|
|
return (
|
|
<motion.div
|
|
whileHover={{ scale: 1.05 }}
|
|
whileTap={{ scale: 0.95 }}
|
|
>
|
|
<button
|
|
onClick={handleDonateClick}
|
|
className="inline-block bg-yellow-400 text-[#8C1D40] font-bold py-2 px-4 rounded-full hover:bg-yellow-300 transition-colors duration-200 shadow-md"
|
|
>
|
|
Donate
|
|
</button>
|
|
<Modal
|
|
isOpen={isModalOpen}
|
|
onRequestClose={closeModal}
|
|
contentLabel="Donate to MCDi"
|
|
className="modal"
|
|
overlayClassName="overlay"
|
|
>
|
|
<div className="h-full flex flex-col">
|
|
<h2 className="text-2xl font-bold text-[#8C1D40] mb-4">Donate to MCDi</h2>
|
|
<div className="flex-grow overflow-y-auto">
|
|
<iframe
|
|
src="https://www.zeffy.com/embed/donation-form/1cbff18e-c057-4fa6-8276-a993037de0bb"
|
|
width="100%"
|
|
height="100%"
|
|
frameBorder="0"
|
|
></iframe>
|
|
</div>
|
|
<button
|
|
onClick={closeModal}
|
|
className="mt-4 bg-[#8C1D40] text-white font-bold py-2 px-4 rounded"
|
|
>
|
|
Close
|
|
</button>
|
|
</div>
|
|
</Modal>
|
|
</motion.div>
|
|
);
|
|
};
|
|
|
|
export default Header;
|