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

Add responsiveness to Navbar and Chatbot #80

Merged
merged 1 commit into from
Jan 28, 2025
Merged
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
Improve Scroll Behavior and Responsiveness of Navbar,Chatbot and remo…
…ve scroll bar for better look
asmit27rai committed Dec 31, 2024
commit dae7c7ddd30ebdd1b978b92e21096cdc8494ba6c
23 changes: 12 additions & 11 deletions client/app/components/Cards/ElectionInfoCard.tsx
Original file line number Diff line number Diff line change
@@ -13,29 +13,30 @@ const ElectionInfoCard = ({ counts, filterStatus, setFilterStatus }: any) => {
{ name: "Active", image: TbCalendarDot, count: counts.active },
{ name: "Ended", image: TbCalendarOff, count: counts.ended },
];

return (
<div className="relative flex border border-gray-300 w-full flex-col rounded-xl bg-white p-4 text-gray-700 bg-clip-border shadow-xl shadow-blue-gray-900/5">
<div className="p-4">
<h5 className="block font-sans text-xl antialiased font-semibold leading-snug tracking-normal text-blue-gray-900">
<div className="relative flex border border-gray-300 w-full max-w-sm sm:max-w-full flex-col rounded-xl bg-white p-2 sm:p-4 text-gray-700 bg-clip-border shadow-xl shadow-blue-gray-900/5">
<div className="p-2 sm:p-4">
<h5 className="block font-sans text-lg sm:text-xl antialiased font-semibold leading-snug tracking-normal text-blue-gray-900">
Election List
</h5>
</div>
<nav className="flex flex-col gap-1 p-2 font-sans text-base font-normal text-blue-gray-700">
<nav className="flex flex-col gap-1 p-1 sm:p-2 font-sans text-sm sm:text-base font-normal text-blue-gray-700 overflow-y-auto">
{ElectionInfoImage.map((electionPart, key) => {
return (
<button
key={key}
onClick={() => setFilterStatus(key)}
className={`flex relative items-center w-full p-3 leading-tight transition-all rounded-lg outline-none text-start hover:bg-blue-gray-50 hover:bg-opacity-80 hover:text-blue-gray-900 focus:bg-blue-gray-50 focus:bg-opacity-80 focus:text-blue-gray-900 active:bg-blue-gray-50 active:bg-opacity-80 active:text-blue-gray-900 ${
key === filterStatus && " bg-slate-100"
className={`flex relative items-center w-full p-2 sm:p-3 leading-tight transition-all rounded-lg outline-none text-start hover:bg-blue-gray-50 hover:bg-opacity-80 hover:text-blue-gray-900 focus:bg-blue-gray-50 focus:bg-opacity-80 focus:text-blue-gray-900 active:bg-blue-gray-50 active:bg-opacity-80 active:text-blue-gray-900 ${
key === filterStatus && "bg-slate-100"
}`}
>
<div className="grid mr-4 place-items-center">
<electionPart.image size={20} />
<div className="grid mr-2 sm:mr-4 place-items-center">
<electionPart.image size={18} />
</div>
{electionPart.name}
<div className="absolute right-2 px-2 font-sans text-sm font-semibold uppercase rounded-full whitespace-nowrap text-blue-gray-900">
<span className="">{electionPart.count}</span>
<div className="absolute right-2 px-1 sm:px-2 font-sans text-xs sm:text-sm font-semibold uppercase rounded-full whitespace-nowrap text-blue-gray-900">
<span>{electionPart.count}</span>
</div>
</button>
);
@@ -45,4 +46,4 @@ const ElectionInfoCard = ({ counts, filterStatus, setFilterStatus }: any) => {
);
};

export default ElectionInfoCard;
export default ElectionInfoCard;
36 changes: 19 additions & 17 deletions client/app/components/ChatBot/ChatBot.tsx
Original file line number Diff line number Diff line change
@@ -3,6 +3,7 @@
import React, { useState, useRef, useEffect } from "react";
import { motion, AnimatePresence } from "framer-motion";
import { ArrowUpIcon, ChatBubbleLeftRightIcon } from "@heroicons/react/24/solid";
import { XMarkIcon } from "@heroicons/react/24/outline"; // Corrected the import for XMarkIcon

interface Message {
content: string;
@@ -49,7 +50,6 @@ const ChatBot: React.FC = () => {
setMessages((prevMessages) => [...prevMessages, reply]);
} catch (error) {
console.error("Error:", error);
// Add error message in chatbot here
}
};

@@ -72,12 +72,19 @@ const ChatBot: React.FC = () => {
animate={{ opacity: 1, scale: 1, y: 0 }}
exit={{ opacity: 0, scale: 0.95, y: 20 }}
transition={{ duration: 0.2 }}
className="absolute bottom-16 right-0 w-96 h-[32rem] bg-white rounded-lg shadow-xl overflow-hidden flex flex-col"
className="absolute bottom-16 right-0 w-[280px] xs:w-[320px] sm:w-[350px] md:w-[380px] h-[450px] bg-white rounded-lg shadow-xl overflow-hidden flex flex-col"
>
<div className="bg-blue-600 text-white p-4 text-center font-semibold">
Agora Chatbot
<div className="bg-blue-600 text-white p-3 flex items-center justify-between">
<h3 className="font-semibold">Agora Chatbot</h3>
<button
onClick={() => setIsOpen(false)} // Close chatbot on click
className="text-white focus:outline-none"
>
<XMarkIcon className="w-6 h-6" />
</button>
</div>
<div className="flex-grow overflow-auto p-4 space-y-4">

<div className="flex-grow overflow-auto p-3 space-y-3">
{messages.map((msg, index) => (
<motion.div
key={index}
@@ -87,28 +94,23 @@ const ChatBot: React.FC = () => {
className={`flex ${msg.role === "assistant" ? "justify-start" : "justify-end"}`}
>
<div
className={`max-w-[80%] p-3 rounded-lg ${
msg.role === "assistant"
? "bg-gray-200 text-gray-800"
: "bg-blue-600 text-white"
}`}
className={`max-w-[85%] p-2.5 rounded-lg text-sm ${msg.role === "assistant" ? "bg-gray-200 text-gray-800" : "bg-blue-600 text-white"}`}
>
{msg.content}
</div>
</motion.div>
))}
<div ref={messageEndRef} />
</div>
<form onSubmit={handleSubmit} className="p-4 bg-gray-100">
<div className="flex items-center bg-white rounded-full overflow-hidden shadow">

<form onSubmit={handleSubmit} className="p-3 bg-gray-100">
<div className="flex items-center gap-2">
<input
type="text"
value={inputMessage}
onChange={(e: React.ChangeEvent<HTMLInputElement>) =>
setInputMessage(e.target.value)
}
onChange={(e) => setInputMessage(e.target.value)}
placeholder="Type your message..."
className="flex-grow px-4 py-2 focus:outline-none"
className="flex-grow px-3 py-2 rounded-full focus:outline-none focus:ring-2 focus:ring-blue-500 text-sm"
/>
<button type="submit" className="bg-blue-600 text-white p-2 rounded-full">
<ArrowUpIcon className="w-5 h-5" />
@@ -123,4 +125,4 @@ const ChatBot: React.FC = () => {
);
};

export default ChatBot;
export default ChatBot;
177 changes: 124 additions & 53 deletions client/app/components/Header/Header.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
"use client";

import React from "react";
import React, { useState } from "react";
import Link from "next/link";
import { usePathname } from "next/navigation";
import { motion } from "framer-motion";
import { motion, AnimatePresence } from "framer-motion";
import {
PlusCircleIcon,
UserIcon,
HomeIcon,
XMarkIcon,
Bars3Icon,
} from "@heroicons/react/24/outline";
import Web3Connect from "../Helper/Web3Connect";
import Image from "next/image";
@@ -20,61 +22,130 @@ const menuItems = [

const Header = () => {
const pathname = usePathname();
const [isSidebarOpen, setIsSidebarOpen] = useState(false);

const toggleSidebar = () => setIsSidebarOpen(!isSidebarOpen);

return (
<motion.header
className="bg-white border-b border-gray-200 fixed w-full z-30 shadow-sm"
initial={{ y: -100 }}
animate={{ y: 0 }}
transition={{ type: "spring", stiffness: 300, damping: 30 }}
>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between h-16">
<Link href="/" className="flex-shrink-0 flex items-center">
<Image
width={32}
height={32}
className="h-8 w-auto"
src="/aossie.png"
alt="Agora Blockchain"
/>
<h1 className="ml-3 text-xl font-bold text-gray-800 hidden sm:block">
Agora Blockchain
</h1>
</Link>
<>
<motion.header
className="bg-white border-b border-gray-200 fixed w-full z-30 shadow-sm"
initial={{ y: -100 }}
animate={{ y: 0 }}
transition={{ type: "spring", stiffness: 300, damping: 30 }}
>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between h-16">
<Link href="/" className="flex-shrink-0 flex items-center">
<Image
width={32}
height={32}
className="h-8 w-auto"
src="/aossie.png"
alt="Agora Blockchain"
/>
<h1 className="ml-3 text-xl font-bold text-gray-800 hidden sm:block">
Agora Blockchain
</h1>
</Link>

<nav className="flex items-center space-x-4">
{menuItems.map((item) => (
<Link key={item.name} href={item.href} className="relative">
<motion.button
className={`inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md ${
pathname === item.href
? "text-indigo-600"
: "text-gray-700 hover:text-indigo-600"
} bg-white hover:bg-gray-50`}
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
>
<item.icon className="h-5 w-5 mr-2" aria-hidden="true" />
<span className="hidden sm:inline">{item.name}</span>
</motion.button>
{pathname === item.href && (
<motion.div
className="absolute bottom-0 left-0 right-0 h-0.5 bg-indigo-600"
layoutId="underline"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.3 }}
/>
)}
</Link>
))}
<Web3Connect />
</nav>
{/* Desktop/Tablet Navigation */}
<nav className="hidden lg:flex items-center space-x-4">
{menuItems.map((item) => (
<Link key={item.name} href={item.href} className="relative">
<motion.button
className={`inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md ${
pathname === item.href
? "text-indigo-600"
: "text-gray-700 hover:text-indigo-600"
} bg-white hover:bg-gray-50`}
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
>
<item.icon className="h-5 w-5 mr-2" aria-hidden="true" />
<span>{item.name}</span>
</motion.button>
{pathname === item.href && (
<motion.div
className="absolute bottom-0 left-0 right-0 h-0.5 bg-indigo-600"
layoutId="underline"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ duration: 0.3 }}
/>
)}
</Link>
))}
<div className="hidden lg:block">
<Web3Connect />
</div>
</nav>

{/* Mobile/Tablet Menu Button */}
<div className="lg:hidden flex items-center space-x-2">
<div className="scale-90">
<Web3Connect />
</div>
<button
onClick={toggleSidebar}
className="p-2 rounded-md text-gray-600 hover:text-gray-900 hover:bg-gray-100"
>
<Bars3Icon className="h-6 w-6" />
</button>
</div>
</div>
</div>
</div>
</motion.header>
</motion.header>

{/* Mobile/Tablet Sidebar */}
<AnimatePresence>
{isSidebarOpen && (
<>
<motion.div
className="fixed inset-0 bg-black bg-opacity-50 z-40"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
onClick={toggleSidebar}
/>
<motion.div
className="fixed right-0 top-0 h-full w-72 bg-white z-50 shadow-lg"
initial={{ x: "100%" }}
animate={{ x: 0 }}
exit={{ x: "100%" }}
transition={{ type: "spring", damping: 20 }}
>
<div className="p-6">
<button
onClick={toggleSidebar}
className="absolute top-4 right-4 p-2 rounded-md text-gray-600 hover:text-gray-900 hover:bg-gray-100"
>
<XMarkIcon className="h-6 w-6" />
</button>
<div className="mt-8 space-y-6">
{menuItems.map((item) => (
<Link
key={item.name}
href={item.href}
onClick={toggleSidebar}
className={`flex items-center p-4 rounded-lg transition-colors ${
pathname === item.href
? "bg-indigo-50 text-indigo-600"
: "text-gray-700 hover:bg-gray-50"
}`}
>
<item.icon className="h-6 w-6 mr-4" />
<span className="text-base font-medium">{item.name}</span>
</Link>
))}
</div>
</div>
</motion.div>
</>
)}
</AnimatePresence>
</>
);
};

export default Header;
export default Header;
2 changes: 1 addition & 1 deletion client/app/components/Pages/HomePage.tsx
Original file line number Diff line number Diff line change
@@ -5,7 +5,7 @@ import Dashboard from "./Dashboard";
const HomePage = () => {
const { isConnected } = useAccount();
return (
<main className="h-screen pt-20 w-full bg-white ">
<main className="h-screen pt-20 w-full bg-white overflow-hidden">
{isConnected ? <Dashboard /> : <LoginPage />}
</main>
);
2 changes: 1 addition & 1 deletion client/app/election/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -78,4 +78,4 @@ const ElectionPage = ({ params }: { params: { id: `0x${string}` } }) => {
);
};

export default ElectionPage;
export default ElectionPage;
5 changes: 5 additions & 0 deletions client/app/globals.css
Original file line number Diff line number Diff line change
@@ -4,8 +4,13 @@

body {
background-color: #ffffff;
margin: 0;
overflow: hidden;
}

html {
scroll-behavior: smooth;
}

::-webkit-scrollbar {
width: 1px;
2 changes: 1 addition & 1 deletion client/app/page.tsx
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ import HomePage from "./components/Pages/HomePage";

export default function Home() {
return (
<main className="flex min-h-screen w-screen flex-col items-center justify-between ">
<main className="flex min-h-screen w-screen flex-col items-center justify-between overflow-hidden">
<HomePage />
</main>
);