diff --git a/apps/frontend/package.json b/apps/frontend/package.json index 6ebd588..6839b92 100644 --- a/apps/frontend/package.json +++ b/apps/frontend/package.json @@ -10,9 +10,12 @@ "preview": "vite preview" }, "dependencies": { + "clsx": "^2.1.1", + "framer-motion": "^11.3.6", "react": "^18.2.0", "react-dom": "^18.2.0", - "react-router-dom": "^6.24.0" + "react-router-dom": "^6.24.0", + "tailwind-merge": "^2.4.0" }, "devDependencies": { "@types/react": "^18.2.66", diff --git a/apps/frontend/src/assets/explore.gif b/apps/frontend/src/assets/explore.gif new file mode 100644 index 0000000..627507e Binary files /dev/null and b/apps/frontend/src/assets/explore.gif differ diff --git a/apps/frontend/src/assets/sign_up.gif b/apps/frontend/src/assets/sign_up.gif new file mode 100644 index 0000000..1d8e775 Binary files /dev/null and b/apps/frontend/src/assets/sign_up.gif differ diff --git a/apps/frontend/src/assets/support.gif b/apps/frontend/src/assets/support.gif new file mode 100644 index 0000000..81af46c Binary files /dev/null and b/apps/frontend/src/assets/support.gif differ diff --git a/apps/frontend/src/components/homepage/Hero.tsx b/apps/frontend/src/components/homepage/Hero.tsx new file mode 100644 index 0000000..786e165 --- /dev/null +++ b/apps/frontend/src/components/homepage/Hero.tsx @@ -0,0 +1,53 @@ +import { HeroCard} from "./HeroCard" +import { HeroCard2 } from "./HeroCard2" +import { HeroCard3 } from "./HeroCard3" +const Hero = () => { + return ( +
+
+
+ Request Help + + + + + +
+

+ {/* Control your Finances with our + Smart Tool */} + + +Join events, offer services, or get help securely with Unite. +

+

+ Join our platform effortlessly and start making a difference in your community today. +

+ + Join as a Volunteer + + + + +
+ + + + + + + +
+
+
+ ) +} + +export default Hero \ No newline at end of file diff --git a/apps/frontend/src/components/homepage/HeroCard.tsx b/apps/frontend/src/components/homepage/HeroCard.tsx new file mode 100644 index 0000000..a06c216 --- /dev/null +++ b/apps/frontend/src/components/homepage/HeroCard.tsx @@ -0,0 +1,55 @@ + +import { CardBody, CardContainer, CardItem } from "../ui/3d-card"; +import img from '../../assets/sign_up.gif' + +export function HeroCard() { + return ( + + + + Easy Volunteer Signup + + + Hover over this card to unleash the power of CSS perspective + + + thumbnail + + {/*
+ + Try now → + + + Sign up + +
*/} +
+
+ ); +} \ No newline at end of file diff --git a/apps/frontend/src/components/homepage/HeroCard2.tsx b/apps/frontend/src/components/homepage/HeroCard2.tsx new file mode 100644 index 0000000..a95c7f8 --- /dev/null +++ b/apps/frontend/src/components/homepage/HeroCard2.tsx @@ -0,0 +1,56 @@ + +import { CardBody, CardContainer, CardItem } from "../ui/3d-card"; +import img from '../../assets/support.gif' + +export function HeroCard2() { + return ( + + + + Request Support + + + Hover over this card to unleash the power of CSS perspective + + + thumbnail + + {/*
+ + Try now → + + + Sign up + +
*/} +
+
+ ); +} \ No newline at end of file diff --git a/apps/frontend/src/components/homepage/HeroCard3.tsx b/apps/frontend/src/components/homepage/HeroCard3.tsx new file mode 100644 index 0000000..501cece --- /dev/null +++ b/apps/frontend/src/components/homepage/HeroCard3.tsx @@ -0,0 +1,56 @@ + +import { CardBody, CardContainer, CardItem } from "../ui/3d-card"; +import img from '../../assets/explore.gif' + +export function HeroCard3() { + return ( + + + + Connect & Collaborate + + + Hover over this card to unleash the power of CSS perspective + + + thumbnail + + {/*
+ + Try now → + + + Sign up + +
*/} +
+
+ ); +} \ No newline at end of file diff --git a/apps/frontend/src/components/homepage/Home.tsx b/apps/frontend/src/components/homepage/Home.tsx index 2403e4c..2e0e2f7 100644 --- a/apps/frontend/src/components/homepage/Home.tsx +++ b/apps/frontend/src/components/homepage/Home.tsx @@ -1,8 +1,10 @@ +import Hero from "./Hero" const Home = () => { return ( -
- Home +
+ +
) } diff --git a/apps/frontend/src/components/ui/3d-card.tsx b/apps/frontend/src/components/ui/3d-card.tsx new file mode 100644 index 0000000..1b5dc5c --- /dev/null +++ b/apps/frontend/src/components/ui/3d-card.tsx @@ -0,0 +1,154 @@ + +import { cn } from "../../lib/utils"; + +import React, { + createContext, + useState, + useContext, + useRef, + useEffect, +} from "react"; + +const MouseEnterContext = createContext< + [boolean, React.Dispatch>] | undefined +>(undefined); + +export const CardContainer = ({ + children, + className, + containerClassName, +}: { + children?: React.ReactNode; + className?: string; + containerClassName?: string; +}) => { + const containerRef = useRef(null); + const [isMouseEntered, setIsMouseEntered] = useState(false); + + const handleMouseMove = (e: React.MouseEvent) => { + if (!containerRef.current) return; + const { left, top, width, height } = + containerRef.current.getBoundingClientRect(); + const x = (e.clientX - left - width / 2) / 25; + const y = (e.clientY - top - height / 2) / 25; + containerRef.current.style.transform = `rotateY(${x}deg) rotateX(${y}deg)`; + }; + + const handleMouseEnter = (e: React.MouseEvent) => { + setIsMouseEntered(true); + if (!containerRef.current) return; + }; + + const handleMouseLeave = (e: React.MouseEvent) => { + if (!containerRef.current) return; + setIsMouseEntered(false); + containerRef.current.style.transform = `rotateY(0deg) rotateX(0deg)`; + }; + return ( + +
+
+ {children} +
+
+
+ ); +}; + +export const CardBody = ({ + children, + className, +}: { + children: React.ReactNode; + className?: string; +}) => { + return ( +
*]:[transform-style:preserve-3d]", + className + )} + > + {children} +
+ ); +}; + +export const CardItem = ({ + as: Tag = "div", + children, + className, + translateX = 0, + translateY = 0, + translateZ = 0, + rotateX = 0, + rotateY = 0, + rotateZ = 0, + ...rest +}: { + as?: React.ElementType; + children: React.ReactNode; + className?: string; + translateX?: number | string; + translateY?: number | string; + translateZ?: number | string; + rotateX?: number | string; + rotateY?: number | string; + rotateZ?: number | string; + [key: string]: any; +}) => { + const ref = useRef(null); + const [isMouseEntered] = useMouseEnter(); + + useEffect(() => { + handleAnimations(); + }, [isMouseEntered]); + + const handleAnimations = () => { + if (!ref.current) return; + if (isMouseEntered) { + ref.current.style.transform = `translateX(${translateX}px) translateY(${translateY}px) translateZ(${translateZ}px) rotateX(${rotateX}deg) rotateY(${rotateY}deg) rotateZ(${rotateZ}deg)`; + } else { + ref.current.style.transform = `translateX(0px) translateY(0px) translateZ(0px) rotateX(0deg) rotateY(0deg) rotateZ(0deg)`; + } + }; + + return ( + + {children} + + ); +}; + +// Create a hook to use the context +export const useMouseEnter = () => { + const context = useContext(MouseEnterContext); + if (context === undefined) { + throw new Error("useMouseEnter must be used within a MouseEnterProvider"); + } + return context; +}; \ No newline at end of file diff --git a/apps/frontend/src/lib/utils.tsx b/apps/frontend/src/lib/utils.tsx new file mode 100644 index 0000000..95b19a8 --- /dev/null +++ b/apps/frontend/src/lib/utils.tsx @@ -0,0 +1,6 @@ +import { ClassValue, clsx } from "clsx"; +import { twMerge } from "tailwind-merge"; + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} \ No newline at end of file