Merge branch 'front-end' into back-end

This commit is contained in:
Pattadon 2024-11-20 09:26:20 +07:00
commit 38e09f80b6
13 changed files with 384 additions and 174 deletions

View File

@ -26,8 +26,12 @@ const nextConfig = {
hostname: "avatars.githubusercontent.com", hostname: "avatars.githubusercontent.com",
pathname: "/**", pathname: "/**",
}, },
{
protocol: "https",
hostname: "assets.republic.com",
pathname: "/**",
},
], ],
}, },
}; };
export default nextConfig; export default nextConfig;

View File

@ -98,7 +98,7 @@ export default async function ProjectDealPage({ params }: { params: { id: number
))} ))}
</div> </div>
</div> </div>
<div id="sub-content" className="flex flex-row mt-5"> <div id="sub-content" className="grid grid-cols-1 md:grid-cols-2 mt-5 space-y-5 md:space-y-0">
{/* image carousel */} {/* image carousel */}
<div id="image-carousel" className="w-full"> <div id="image-carousel" className="w-full">
<Gallery images={carouselData} /> <Gallery images={carouselData} />
@ -152,62 +152,28 @@ export default async function ProjectDealPage({ params }: { params: { id: number
</Button> </Button>
)} )}
</div> </div>
<div className="flex justify-between w-full"> <div className="flex justify-between gap-4 w-full">
<Button className="w-[48%] h-12 dark:text-white" variant={"outline"}> <Button
<Link href={`/dataroom/${params.id}/files`}>Access Dataroom</Link> className="flex justify-center items-center w-[48%] h-12 text-xs md:text-sm text-center dark:text-white"
variant="outline"
>
<Link href={`/dataroom/${params.id}/files`} className="block text-center break-words">
<span className="block lg:inline">Access</span>
<span className="block lg:inline"> Dataroom</span>
</Link>
</Button> </Button>
<Button className="w-[48%] h-12 dark:text-white" variant={"outline"}> <Button
<Link href={`/dataroom/overview`}>Request Dataroom Access</Link> className="flex justify-center items-center w-[48%] h-12 text-xs md:text-sm text-center dark:text-white"
variant="outline"
>
<Link href={`/dataroom/overview`} className="block text-center break-words">
<span className="block lg:inline">Request</span>
<span className="block lg:inline"> Dataroom Access</span>
</Link>
</Button> </Button>
</div> </div>
</CardFooter> </CardFooter>
</Card> </Card>
{/* <div id="stats" className="flex flex-col w-full mt-4 pl-12">
<div className="pl-5">
<span>
<h1 className="font-semibold text-xl md:text-4xl mt-8">${totalDealAmount}</h1>
<p className="text-sm md:text-lg">
{toPercentage(totalDealAmount, projectData?.target_investment)}% raised of $
{projectData?.target_investment} max goal
</p>
<Progress
value={toPercentage(totalDealAmount, projectData?.target_investment)}
className="w-[60%] h-3 mt-3"
/>
</span>
<span>
<h1 className="font-semibold text-4xl md:mt-8">
<p className="text-xl md:text-4xl">{dealList.length}</p>
</h1>
<p className="text-sm md:text-lg">Investors</p>
</span>
<Separator decorative className="mt-3 w-3/4 ml-5" />
<span>
<h1 className="font-semibold text-xl md:text-4xl mt-8 ml-5"></h1>
{projectData?.investment_deadline ? (
<>
<p className="text-xl md:text-4xl">{Math.floor(hourLeft)} hours</p>
<p>Left to invest</p>
</>
) : (
<p className="text-xl md:text-4xl">No deadline</p>
)}
</span>
<Button className="mt-5 w-3/4 h-12 dark:text-white">
<Link href={`/invest/${params.id}`}>Invest in {projectData?.project_name}</Link>
</Button>
<div className="flex flex-col space-y-2 py-4 mt-5 w-3/4 h-12 border-2 border-border rounded-md">
<p className="text-md font-bold">Dataroom</p>
<Button className=" dark:text-white">
<Link href={`/invest/${params.id}`}>Access Dataroom</Link>
</Button>
<Button className=" dark:text-white">
<Link href={`/invest/${params.id}`}>Manage Dataroom</Link>
</Button>
</div>
</div>
</div> */}
</div> </div>
{/* menu */} {/* menu */}
<div id="deck"> <div id="deck">
@ -215,7 +181,6 @@ export default async function ProjectDealPage({ params }: { params: { id: number
<Tabs.Root defaultValue="pitch" className="w-full"> <Tabs.Root defaultValue="pitch" className="w-full">
<Tabs.List className="list-none flex gap-10 text-lg md:text-xl"> <Tabs.List className="list-none flex gap-10 text-lg md:text-xl">
<Tabs.Trigger value="pitch">Pitch</Tabs.Trigger> <Tabs.Trigger value="pitch">Pitch</Tabs.Trigger>
{/* <Tabs.Trigger value="general">General Data</Tabs.Trigger> */}
<Tabs.Trigger value="update">Updates</Tabs.Trigger> <Tabs.Trigger value="update">Updates</Tabs.Trigger>
</Tabs.List> </Tabs.List>
<Separator className="mb-4 mt-2 w-full border-1" /> <Separator className="mb-4 mt-2 w-full border-1" />
@ -235,17 +200,6 @@ export default async function ProjectDealPage({ params }: { params: { id: number
</CardContent> </CardContent>
</Card> </Card>
</Tabs.Content> </Tabs.Content>
{/* <Tabs.Content value="general">
<Card>
<CardHeader>
<CardTitle>general</CardTitle>
<CardDescription>general Description</CardDescription>
</CardHeader>
<CardContent>
<p>general Content</p>
</CardContent>
</Card>
</Tabs.Content> */}
<Tabs.Content value="update"> <Tabs.Content value="update">
<Card> <Card>
<CardHeader> <CardHeader>

View File

@ -0,0 +1,31 @@
import { Button } from "@/components/ui/button";
import Image from "next/image";
import Link from "next/link";
type CardProps = {
imageSrc: string;
imageAlt: string;
heading: string;
content: string[];
link: string;
buttonText: string;
};
const InfoCard = ({ imageSrc, imageAlt, heading, content, link, buttonText }: CardProps) => {
return (
<div className="flex flex-col items-center justify-center">
<Image alt={imageAlt} width={460} height={460} className="w-36" src={imageSrc} />
<h1 className="text-2xl font-bold mt-3">{heading}</h1>
{content.map((text, index) => (
<p key={index} className={index === 0 ? "mt-3" : ""}>
{text}
</p>
))}
<Link href={link}>
<Button className="p-6 font-semibold text-base mt-5">{buttonText}</Button>
</Link>
</div>
);
};
export default InfoCard;

View File

@ -1,5 +1,6 @@
import Image from "next/image"; "use client";
import { Separator } from "@/components/ui/separator"; import { Separator } from "@/components/ui/separator";
import InfoCard from "./infoCard";
export default function About() { export default function About() {
// Static data for the cards // Static data for the cards
@ -38,11 +39,69 @@ export default function About() {
}, },
]; ];
const imageData = {
img1: "https://assets.republic.com/assets/static_pages/about/growth_opportunities/individual_investors-0e85dfd02359a24ac4b232be008c7168fc57d3437a2f526f5d5889b874b20221.png",
img2: "https://assets.republic.com/assets/static_pages/about/growth_opportunities/accredited_investors-42d6aa046861adb7f0648f26ca3f798b07f3b13bf7024f7dc17c17acb78fdf2c.png",
img3: "https://assets.republic.com/assets/static_pages/about/growth_opportunities/entrepreneurs-a0ff450c2f3ba0cea82e2c55cd9265ad5612455c79ec831adaa2c94d09a0e617.png",
};
return ( return (
<div className="container max-w-screen-xl p-10"> <div className="container max-w-screen-xl p-10">
<h1 className="mt-3 font-bold text-lg md:text-3xl">About us</h1> <div className="flex flex-col items-center justify-center">
<Separator className="my-3" /> <h1 className="mt-3 font-bold text-lg md:text-5xl font-black">Growth opportunities for all sides </h1>
<div className="border border-border rounded-md"> <h1 className="mt-3 font-bold text-lg md:text-5xl font-black">of the investment market</h1>
<h1 className="text-gray-500 text-2xl mt-1">
B2DVentures is where both accredited and non-accredited investors meet
</h1>
<h1 className="text-gray-500 text-2xl">entrepreneurs and access high-growth potential deals across a range</h1>
<h1 className="text-gray-500 text-2xl">of private markets.</h1>
</div>
<div className="mt-10">
<div className="grid grid-cols-1 md:grid-cols-[1fr,auto,1fr] gap-3">
<InfoCard
imageSrc={imageData.img1}
imageAlt="Image1"
heading="Individual investors"
content={[
"B2DVentures's success has been built off our hundreds",
"of sourced private deals, all available for",
"investment from you with as little as $10 or as ",
"much as $124,000.",
]}
link="/deals"
buttonText="Explore opportunities"
/>
<Separator orientation="vertical" />
<InfoCard
imageSrc={imageData.img2}
imageAlt="Image2"
heading="Accredited investors"
content={[
"The benefits of the Republic platform, optimized for",
"accredited investors. Access a curated investor",
"portal for unique private investment opportunities. ",
]}
link="/dataroom/overview"
buttonText="Learn more"
/>
</div>
<Separator className="mt-5 mb-5" />
<InfoCard
imageSrc={imageData.img3}
imageAlt="Image3"
heading="Entrepreneurs"
content={[
"Seek funding from a wider base of diverse",
"investors while simultaneously growing a loyal",
"base and leveraging Republics private investment",
"network.",
]}
link="/project/apply"
buttonText="Raise money"
/>
</div>
{/* <div className="border border-border rounded-md">
<p className="p-5"> <p className="p-5">
Welcome to B2D Ventures! We&apos;re a dynamic platform committed to bridging the gap between visionary Welcome to B2D Ventures! We&apos;re a dynamic platform committed to bridging the gap between visionary
entrepreneurs and passionate investors. Our mission is to empower innovation by connecting groundbreaking entrepreneurs and passionate investors. Our mission is to empower innovation by connecting groundbreaking
@ -56,15 +115,15 @@ export default function About() {
lasting impact. lasting impact.
</p> </p>
<p className="p-5">Let&apos;s build the future, together.</p> <p className="p-5">Let&apos;s build the future, together.</p>
</div> </div> */}
<div className="mt-10 text-center"> {/* <div className="mt-10 text-center">
<h2 className="font-bold text-lg md:text-3xl">Our Team</h2> <h2 className="font-bold text-lg md:text-3xl">Our Team</h2>
<Separator className="my-3" /> <Separator className="my-3" />
</div> </div> */}
{/* Card Section */} {/* Card Section */}
<div className="mt-10 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6"> {/* <div className="mt-10 grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-6">
{cardData.map((card, index) => ( {cardData.map((card, index) => (
<div key={index} className="bg-white rounded-lg shadow-lg overflow-hidden"> <div key={index} className="bg-white rounded-lg shadow-lg overflow-hidden">
<Image src={card.imageSrc} width={460} height={460} alt={card.name} className="w-full h-48 object-cover" /> <Image src={card.imageSrc} width={460} height={460} alt={card.name} className="w-full h-48 object-cover" />
@ -74,7 +133,7 @@ export default function About() {
</div> </div>
</div> </div>
))} ))}
</div> </div> */}
</div> </div>
); );
} }

View File

@ -27,7 +27,7 @@ export default function ProjectCardCalendarManageSection({ projectData }: Projec
const [currentProjectId, setCurrentProjectId] = useState<number | undefined>(undefined); const [currentProjectId, setCurrentProjectId] = useState<number | undefined>(undefined);
return ( return (
<div id="content" className="grid grid-cols-2 space-x-2"> <div id="content" className="grid grid-cols-1 md:grid-cols-2 space-x-2">
{projectData != null ? ( {projectData != null ? (
projectData.map((project) => ( projectData.map((project) => (
<Card key={project.id} className="mb-3"> <Card key={project.id} className="mb-3">

View File

@ -208,7 +208,7 @@ export function DataTable({ data }: { data: ModalProps[] }) {
placeholder="Filter names..." placeholder="Filter names..."
value={(table.getColumn("name")?.getFilterValue() as string) ?? ""} value={(table.getColumn("name")?.getFilterValue() as string) ?? ""}
onChange={(event) => table.getColumn("name")?.setFilterValue(event.target.value)} onChange={(event) => table.getColumn("name")?.setFilterValue(event.target.value)}
className="max-w-sm" className="md:max-w-sm max-w-xs"
/> />
<DropdownMenu> <DropdownMenu>
<DropdownMenuTrigger asChild> <DropdownMenuTrigger asChild>

View File

@ -0,0 +1,28 @@
import { NavigationMenuLink } from "@/components/ui/navigation-menu";
import { cn } from "@/lib/utils";
import React from "react";
const ListItem = React.forwardRef<React.ElementRef<"a">, React.ComponentPropsWithoutRef<"a">>(
({ className, title, children, ...props }, ref) => {
return (
<li>
<NavigationMenuLink asChild>
<a
ref={ref}
className={cn(
"block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
className
)}
{...props}
>
<div className="text-sm font-medium leading-none">{title}</div>
<hr />
<p className="line-clamp-2 text-sm leading-snug text-muted-foreground">{children}</p>
</a>
</NavigationMenuLink>
</li>
);
}
);
ListItem.displayName = "ListItem";
export default ListItem;

View File

@ -1,27 +0,0 @@
"use client";
import { useState } from "react";
import { Menu, X } from "lucide-react";
import { Button } from "./ui/button";
import { motion } from "framer-motion";
export function MobileMenu() {
const [isVisible, setIsVisible] = useState(false);
return (
<div>
<Button onClick={() => setIsVisible((prev) => !prev)}>
<Menu />
</Button>
{isVisible && (
<motion.div
initial={{ x: "-100%" }}
animate={{ x: 0 }}
exit={{ x: "-100%" }}
transition={{ duration: 0.3 }}
className="fixed top-0 left-0 w-full bg-gray-800 text-white"
>
<X className="cursor-pointer" onClick={() => setIsVisible(false)} />
</motion.div>
)}
</div>
);
}

View File

@ -0,0 +1,23 @@
export const businessComponents = [
{
title: "Business",
href: "/business/apply",
description: "Apply to raise on on B2DVentures",
},
];
export const projectComponents = [
{
title: "Projects",
href: "/project/apply",
description: "Start your new project on B2DVentures",
},
];
export const dataroomComponents = [
{
title: "Overview",
href: "/dataroom/overview",
description: "View all dataroom available to you",
},
];

View File

@ -0,0 +1,103 @@
"use client";
import { useState } from "react";
import { Menu, X } from "lucide-react";
import { Button } from "../ui/button";
import { AnimatePresence, motion } from "framer-motion";
import {
NavigationMenu,
NavigationMenuContent,
NavigationMenuItem,
NavigationMenuLink,
NavigationMenuList,
NavigationMenuTrigger,
} from "@/components/ui/navigation-menu";
import React from "react";
import { SearchBar } from "./serchBar";
import ListItem from "../listItem";
import { businessComponents, projectComponents, dataroomComponents } from "./menu";
import { ThemeToggle } from "../theme-toggle";
export function MobileMenu() {
const [isVisible, setIsVisible] = useState(false);
return (
<div>
<Button onClick={() => setIsVisible((prev) => !prev)}>
<Menu />
</Button>
<AnimatePresence>
{isVisible && (
<motion.div
initial={{ y: -100 }}
animate={{ y: 0 }}
exit={{ y: -100 }}
transition={{ type: "spring", stiffness: 300, damping: 30 }}
className="fixed top-0 left-0 w-full bg-white dark:bg-slate-900 border-b dark:border-slate-800 shadow-sm z-50"
>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex items-center justify-between h-16">
<div className="flex items-center">
<button
onClick={() => setIsVisible(false)}
className="p-2 rounded-md hover:bg-slate-100 dark:hover:bg-slate-800"
>
<X className="w-5 h-5" />
</button>
<NavigationMenu>
<NavigationMenuList className="flex space-x-2">
<NavigationMenuItem>
<NavigationMenuTrigger className="text-sm font-medium">Businesses</NavigationMenuTrigger>
<NavigationMenuContent>
<ul className="w-[240px] p-4 gap-3">
{businessComponents.map((component) => (
<ListItem key={component.title} title={component.title} href={component.href}>
{component.description}
</ListItem>
))}
</ul>
</NavigationMenuContent>
</NavigationMenuItem>
<NavigationMenuItem>
<NavigationMenuTrigger className="text-sm font-medium">Projects</NavigationMenuTrigger>
<NavigationMenuContent>
<ul className="w-[240px] p-4 gap-3">
{projectComponents.map((component) => (
<ListItem key={component.title} title={component.title} href={component.href}>
{component.description}
</ListItem>
))}
</ul>
</NavigationMenuContent>
</NavigationMenuItem>
<NavigationMenuItem>
<NavigationMenuTrigger className="text-sm font-medium">Dataroom</NavigationMenuTrigger>
<NavigationMenuContent>
<ul className="w-[240px] p-4 gap-3">
{dataroomComponents.map((component) => (
<ListItem key={component.title} title={component.title} href={component.href}>
{component.description}
</ListItem>
))}
</ul>
</NavigationMenuContent>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>
</div>
<div className="flex items-center ml-2">
<SearchBar />
<div className="-ml-2">
<ThemeToggle />
</div>
</div>
</div>
</div>
</motion.div>
)}
</AnimatePresence>
</div>
);
}

View File

@ -2,7 +2,6 @@ import * as React from "react";
import Link from "next/link"; import Link from "next/link";
import Image from "next/image"; import Image from "next/image";
import { cn } from "@/lib/utils";
import { Separator } from "@/components/ui/separator"; import { Separator } from "@/components/ui/separator";
import { ThemeToggle } from "@/components/theme-toggle"; import { ThemeToggle } from "@/components/theme-toggle";
import { import {
@ -21,31 +20,9 @@ import { createSupabaseClient } from "@/lib/supabase/serverComponentClient";
import { getUserId } from "@/lib/supabase/actions/getUserId"; import { getUserId } from "@/lib/supabase/actions/getUserId";
import { getUnreadNotificationCountByUserId } from "@/lib/data/notificationQuery"; import { getUnreadNotificationCountByUserId } from "@/lib/data/notificationQuery";
import { MobileMenu } from "../mobileMenu"; import { MobileMenu } from "./mobileMenu";
import ListItem from "../listItem";
const ListItem = React.forwardRef<React.ElementRef<"a">, React.ComponentPropsWithoutRef<"a">>( import { businessComponents, projectComponents, dataroomComponents } from "./menu";
({ className, title, children, ...props }, ref) => {
return (
<li>
<NavigationMenuLink asChild>
<a
ref={ref}
className={cn(
"block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
className
)}
{...props}
>
<div className="text-sm font-medium leading-none">{title}</div>
<hr />
<p className="line-clamp-2 text-sm leading-snug text-muted-foreground">{children}</p>
</a>
</NavigationMenuLink>
</li>
);
}
);
ListItem.displayName = "ListItem";
export async function NavigationBar() { export async function NavigationBar() {
const client = createSupabaseClient(); const client = createSupabaseClient();
@ -59,30 +36,6 @@ export async function NavigationBar() {
notification_count = 0; notification_count = 0;
} }
const businessComponents = [
{
title: "Business",
href: "/business/apply",
description: "Apply to raise on on B2DVentures",
},
];
const projectComponents = [
{
title: "Projects",
href: "/project/apply",
description: "Start your new project on B2DVentures",
},
];
const dataroomComponents = [
{
title: "Overview",
href: "/dataroom/overview",
description: "View all dataroom available to you",
},
];
return ( return (
<header className="sticky top-0 flex flex-wrap w-full bg-card text-sm py-3 border-b-2 border-border z-50"> <header className="sticky top-0 flex flex-wrap w-full bg-card text-sm py-3 border-b-2 border-border z-50">
<nav className="max-w-screen-xl w-full mx-auto px-4"> <nav className="max-w-screen-xl w-full mx-auto px-4">
@ -93,15 +46,31 @@ export async function NavigationBar() {
href="/" href="/"
aria-label="Brand" aria-label="Brand"
> >
<span className="inline-flex items-center gap-x-2 text-xl font-semibold dark:text-white"> <span className="lg:inline-flex flex items-center gap-x-2 text-xl font-semibold dark:text-white">
<Image src="/logo.svg" alt="logo" width={50} height={50} /> <Image src="/logo.svg" alt="logo" width={50} height={50} className="w-10 h-10 sm:w-16 sm:h-16" />
B2DVentures <span className="block lg:inline">
B2D<span className=" lg:inline">Ventures</span>
</span>
</span> </span>
</Link> </Link>
</div> </div>
<div className="md:hidden"> <div className="md:hidden grid grid-cols-2 justify-items-center items-center">
<MobileMenu /> <div className="flex justify-end w-10">
{userId ? (
<AuthenticatedComponents
uid={userId}
avatarUrl={avatarUrl?.avatar_url}
notificationCount={notification_count}
/>
) : (
<UnAuthenticatedComponents />
)}
</div>
<div className="justify-end flex">
<MobileMenu />
</div>
</div> </div>
<div className="hidden md:flex items-center "> <div className="hidden md:flex items-center ">
<NavigationMenu> <NavigationMenu>
<NavigationMenuList> <NavigationMenuList>

View File

@ -2,34 +2,100 @@
import * as React from "react"; import * as React from "react";
import { useRouter } from "next/navigation"; import { useRouter } from "next/navigation";
import { Search } from "lucide-react"; import { Search, X } from "lucide-react";
import { cn } from "@/lib/utils"; import { cn } from "@/lib/utils";
import { useEffect, useRef } from "react";
export function SearchBar() { export function SearchBar() {
const [searchActive, setSearchActive] = React.useState(false); const [searchActive, setSearchActive] = React.useState(false);
const [query, setQuery] = React.useState("");
const router = useRouter(); const router = useRouter();
const inputRef = useRef<HTMLInputElement>(null);
const containerRef = useRef<HTMLDivElement>(null);
const handleKeyDown = async (e: React.KeyboardEvent<HTMLInputElement>) => { const handleKeyDown = async (e: React.KeyboardEvent<HTMLInputElement>) => {
if (e.key === "Enter") { if (e.key === "Enter") {
const query = (e.target as HTMLInputElement).value.trim(); const trimmedQuery = query.trim();
if (query) { if (trimmedQuery) {
router.push(`/find?query=${encodeURIComponent(query)}`); router.push(`/find?query=${encodeURIComponent(trimmedQuery)}`);
setSearchActive(false);
setQuery("");
} }
} else if (e.key === "Escape") {
setSearchActive(false);
setQuery("");
} }
}; };
// Handle clicks outside of search bar
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (containerRef.current && !containerRef.current.contains(event.target as Node)) {
setSearchActive(false);
}
};
document.addEventListener("mousedown", handleClickOutside);
return () => document.removeEventListener("mousedown", handleClickOutside);
}, []);
// Focus input when search becomes active
useEffect(() => {
if (searchActive && inputRef.current) {
inputRef.current.focus();
}
}, [searchActive]);
return ( return (
<div className="flex items-center"> <div
<Search onClick={() => setSearchActive(!searchActive)} className="cursor-pointer" /> ref={containerRef}
<input className={cn(
type="text" "relative flex items-center transition-all duration-300",
placeholder="Enter business name..." searchActive &&
className={cn( "fixed inset-0 bg-white/95 dark:bg-slate-900/95 z-50 px-4 md:relative md:bg-transparent md:dark:bg-transparent md:px-0"
"ml-2 border rounded-md px-2 py-1 transition-all duration-300 ease-in-out", )}
searchActive ? "w-48 opacity-100" : "w-0 opacity-0" >
)} {/* Mobile overlay header when search is active */}
onKeyDown={handleKeyDown} {searchActive && (
/> <div className="absolute top-0 left-0 right-0 flex items-center p-4 md:hidden">
<X
className="w-6 h-6 cursor-pointer text-slate-600 dark:text-slate-400"
onClick={() => {
setSearchActive(false);
setQuery("");
}}
/>
</div>
)}
<div className={cn("flex items-center w-full md:w-auto", searchActive ? "mt-16 md:mt-0" : "")}>
<Search
onClick={() => setSearchActive(!searchActive)}
className={cn(
"w-5 h-5 cursor-pointer transition-colors",
searchActive ? "text-blue-500" : "text-slate-600 dark:text-slate-400",
"md:hover:text-blue-500"
)}
/>
<input
ref={inputRef}
type="text"
value={query}
onChange={(e) => setQuery(e.target.value)}
placeholder="Enter business name..."
className={cn(
"ml-2 rounded-md transition-all duration-300 ease-in-out outline-none",
"placeholder:text-slate-400 dark:placeholder:text-slate-500",
"bg-transparent md:bg-slate-100 md:dark:bg-slate-800",
"md:px-3 md:py-1.5",
searchActive
? "w-full opacity-100 border-b md:border md:w-48 lg:w-64 md:border-slate-200 md:dark:border-slate-700"
: "w-0 opacity-0 border-transparent"
)}
onKeyDown={handleKeyDown}
/>
</div>
</div> </div>
); );
} }

View File

@ -16,7 +16,7 @@ export function SiteFooter() {
Home Home
</Link> </Link>
<Link href="/about" className="hover:underline"> <Link href="/about" className="hover:underline">
About Us About
</Link> </Link>
<Link href="/privacy" className="hover:underline"> <Link href="/privacy" className="hover:underline">
Privacy Privacy