Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: hero section #11

Closed
wants to merge 18 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 6 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,18 +9,19 @@
"lint": "next lint"
},
"dependencies": {
"@fontsource/dm-sans": "^5.1.0",
"next": "15.0.4",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"next": "15.0.4"
"react-dom": "^19.0.0"
},
"devDependencies": {
"typescript": "^5",
"@types/node": "^20",
"@types/react": "^19",
"@types/react-dom": "^19",
"eslint": "^8",
"eslint-config-next": "15.0.4",
"postcss": "^8",
"tailwindcss": "^3.4.1",
"eslint": "^8",
"eslint-config-next": "15.0.4"
"typescript": "^5"
}
}
Binary file added public/doctor.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
42 changes: 42 additions & 0 deletions src/app/components/HeroSection.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import translations from "../data/translations.json";

type TranslationKeys = keyof typeof translations;

type HeroSectionProps = {
selectedLang: TranslationKeys;
};

const HeroSection = ({ selectedLang }: HeroSectionProps) => {
return (
<section className="bg-gradient-to-b from-blue-50 to-white/80 py-16">
<div className="container mx-auto px-4 lg:px-16 flex flex-col-reverse lg:flex-row items-center gap-8">
<div className="text-center lg:text-left flex-1 lg:pr-8">
<h1
className="text-3xl lg:text-5xl font-bold mb-6 leading-snug"
style={{ color: "#484848" }}
>
{translations[selectedLang].title}
</h1>
<p className="text-lg mb-6" style={{ color: "#555555" }}>
{translations[selectedLang].description}
</p>
<button
className="text-white px-8 py-3 text-lg rounded-md shadow hover:brightness-110 transition"
style={{ backgroundColor: "#2F7CC4" }}
>
{translations[selectedLang].button}
</button>
</div>
<div className="flex-shrink-0 flex-1">
<img
src="/doctor.png"
alt="Doctor providing medical advice"
className="w-full lg:w-[550px] rounded-lg shadow-md"
/>
</div>
</div>
</section>
);
};

export default HeroSection;
259 changes: 259 additions & 0 deletions src/app/components/Navbar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,259 @@
"use client";

import React, { useState, useEffect, useRef } from "react";
import Link from "next/link";
import { usePathname } from "next/navigation";

const languages = [
{ label: "English", value: "en" },
{ label: "සිංහල", value: "si" },
{ label: "தமிழ்", value: "ta" },
];

const Navbar = () => {
const [isOpen, setIsOpen] = useState(false);
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
const [selectedLanguage, setSelectedLanguage] = useState("en");
const pathname = usePathname();
const dropdownRef = useRef<HTMLDivElement>(null);

const toggleMenu = () => setIsOpen(!isOpen);
const closeMenu = () => setIsOpen(false);

const toggleDropdown = () => setIsDropdownOpen(!isDropdownOpen);
const closeDropdown = () => setIsDropdownOpen(false);

const handleLanguageSelect = (lang: string) => {
setSelectedLanguage(lang);
closeDropdown();
};

useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (
dropdownRef.current &&
!dropdownRef.current.contains(event.target as Node)
) {
closeDropdown();
}
};

const handleEscape = (event: KeyboardEvent) => {
if (event.key === "Escape") {
closeDropdown();
}
};

document.addEventListener("mousedown", handleClickOutside);
document.addEventListener("keydown", handleEscape);

return () => {
document.removeEventListener("mousedown", handleClickOutside);
document.removeEventListener("keydown", handleEscape);
};
}, []);

return (
<header className="bg-white shadow sticky top-0 z-50">
<div className="container mx-auto px-4 flex items-center justify-between py-4">
<Link
href="/"
className="text-2xl font-bold text-blue-600 flex-shrink-0"
>
Rheuma<span className="text-gray-800">Connect</span>
</Link>

<nav className="hidden md:flex items-center space-x-6 ml-6">
{[
{ href: "/", label: "Home" },
{ href: "/categories", label: "Categories" },
{ href: "/clinic", label: "Clinic" },
{ href: "/contact", label: "Contact" },
].map(({ href, label }) => (
<Link
key={href}
href={href}
className={`hover:text-blue-600 text-gray-800 font-medium ${
pathname === href ? "underline text-blue-600" : ""
}`}
>
{label}
</Link>
))}

<button
className="bg-[#2F7CC4] text-white rounded-[10px] text-[14px] font-medium hover:bg-[#276ca3] transition flex items-center justify-center"
style={{ width: "98px", height: "38px", lineHeight: "18px" }}
>
Explore
</button>

<div className="relative" ref={dropdownRef}>
<button
onClick={toggleDropdown}
className="bg-white border border-gray-400 text-gray-800 rounded-[10px] text-[14px] font-medium flex items-center justify-center hover:bg-gray-100 transition"
style={{ width: "98px", height: "38px", lineHeight: "18px" }}
>
<span>English</span>
<svg
className={`w-4 h-4 text-black transform ${
isDropdownOpen ? "rotate-180" : "rotate-0"
}`}
fill="none"
stroke="currentColor"
strokeWidth="2"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M19 9l-7 7-7-7"
/>
</svg>
</button>

{isDropdownOpen && (
<div className="absolute mt-2 w-40 bg-white border border-gray-200 rounded shadow-lg">
{languages.map(({ label, value }) => (
<button
key={value}
onClick={() => handleLanguageSelect(value)}
className="block w-full text-left px-4 py-2 hover:bg-gray-200 text-gray-800"
>
{label}
</button>
))}
</div>
)}
</div>
</nav>

<button
onClick={toggleMenu}
className="md:hidden text-gray-800 focus:outline-none"
aria-label="Toggle Menu"
>
{isOpen ? (
<svg
className="w-6 h-6"
fill="none"
stroke="currentColor"
strokeWidth="2"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M6 18L18 6M6 6l12 12"
/>
</svg>
) : (
<svg
className="w-6 h-6"
fill="none"
stroke="currentColor"
strokeWidth="2"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M4 6h16M4 12h16m-7 6h7"
/>
</svg>
)}
</button>
</div>

{isOpen && (
<div
className="fixed inset-0 bg-black bg-opacity-50 z-40 md:hidden"
onClick={closeMenu}
>
<div
className="absolute top-0 left-0 w-64 bg-white shadow-lg h-full rounded-r-md"
onClick={(e) => e.stopPropagation()}
>
<div className="p-6 space-y-4">
{[
{ href: "/", label: "Home" },
{ href: "/categories", label: "Categories" },
{ href: "/clinic", label: "Clinic" },
{ href: "/contact", label: "Contact" },
].map(({ href, label }) => (
<Link
key={href}
href={href}
onClick={closeMenu}
className={`block py-2 px-4 text-gray-800 hover:bg-gray-200 rounded ${
pathname === href
? "bg-gray-200 font-bold text-blue-600"
: ""
}`}
>
{label}
</Link>
))}
<button
className="px-6 py-2 bg-[#2F7CC4] text-white rounded-full text-sm hover:bg-[#276ca3] transition"
style={{ width: "98px", height: "38px" }}
>
Explore
</button>
<div className="mt-4">
<div className="relative" ref={dropdownRef}>
<button
onClick={toggleDropdown}
className="px-4 py-2 bg-white border border-gray-300 rounded-full text-sm flex items-center space-x-2 shadow-sm hover:bg-gray-100 transition w-full"
>
<span className="text-black">
{
languages.find(
(lang) => lang.value === selectedLanguage
)?.label
}
</span>
<svg
className={`w-4 h-4 text-black transform ${
isDropdownOpen ? "rotate-180" : "rotate-0"
}`}
fill="none"
stroke="currentColor"
strokeWidth="2"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<path
strokeLinecap="round"
strokeLinejoin="round"
d="M19 9l-7 7-7-7"
/>
</svg>
</button>
{isDropdownOpen && (
<div className="absolute mt-2 w-full bg-white border border-gray-200 rounded shadow-lg">
{languages.map(({ label, value }) => (
<button
key={value}
onClick={() => handleLanguageSelect(value)}
className="block w-full text-left px-4 py-2 hover:bg-gray-200 text-gray-800"
>
{label}
</button>
))}
</div>
)}
</div>
</div>
</div>
</div>
</div>
)}
</header>
);
};

export default Navbar;
7 changes: 7 additions & 0 deletions src/app/data/translations.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"en": {
"title": "Expert backed, FREE medical advice for your Rheumatic Condition",
"description": "Everything about your pre-diagnosed rheumatic condition is just a button-click away with RheumaConnect.",
"button": "Get Started"
}
}
Loading