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: implemented personal builder profile page #16

Merged
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
"use client";

import { useCallback, useEffect, useState } from "react";
import Image from "next/image";
import Link from "next/link";
import { Code, Cpu, Globe } from "lucide-react";
import { FaXTwitter } from "react-icons/fa6";
import { LuGithub, LuLinkedin } from "react-icons/lu";
import { Address } from "~~/components/scaffold-eth";

const DevvMichaelProfile = () => {
const [scrollY, setScrollY] = useState(0);
const [mouseX, setMouseX] = useState(0);
const [mouseY, setMouseY] = useState(0);

const handleScroll = useCallback(() => {
setScrollY(window.scrollY);
}, []);

const handleMouseMove = useCallback((e: MouseEvent) => {
setMouseX(e.clientX);
setMouseY(e.clientY);
}, []);

useEffect(() => {
// Check if window is defined (client-side)
if (typeof window !== "undefined") {
window.addEventListener("scroll", handleScroll);
window.addEventListener("mousemove", handleMouseMove);
}

return () => {
if (typeof window !== "undefined") {
window.removeEventListener("scroll", handleScroll);
window.removeEventListener("mousemove", handleMouseMove);
}
};
}, [handleScroll, handleMouseMove]);

const parallaxLayers = [
{ icon: <Code size={48} />, speed: 0.05, initialPos: { x: "18%", y: "14%" } },
{ icon: <Cpu size={48} />, speed: 0.1, initialPos: { x: "80%", y: "50%" } },
{ icon: <Globe size={48} />, speed: 0.15, initialPos: { x: "34%", y: "78%" } },
];

return (
<div className="relative min-h-screen overflow-hidden bg-gradient-to-br from-base-200 to-base-300">
{/* Parallax Background */}
<div className="absolute inset-0 z-0">
{parallaxLayers.map((layer, index) => (
<div
key={index}
className="absolute text-primary dark:text-base-100 opacity-40"
style={{
left: layer.initialPos.x,
top: layer.initialPos.y,
transform: `translate(
${(mouseX - (typeof window !== "undefined" ? window.innerWidth : 0) / 2) * layer.speed * 0.01}px,
${
(mouseY - (typeof window !== "undefined" ? window.innerHeight : 0) / 2) * layer.speed * 0.01 -
scrollY * layer.speed
}px
)`,
transition: "transform 0.3s ease-out",
}}
>
{layer.icon}
</div>
))}
</div>

{/* Floating Particles */}
{[...Array(20)].map((_, i) => (
<div
key={i}
className="absolute rounded-full bg-primary dark:bg-base-100 opacity-30"
style={{
width: Math.random() * 20 + 10 + "px",
height: Math.random() * 20 + 10 + "px",
left: Math.random() * 100 + "%",
top: Math.random() * 100 + "%",
transform: `translateY(${scrollY * (Math.random() * 0.2 + 0.05)}px)`,
transition: "transform 2s ease-out",
}}
/>
))}

{/* Main Content */}
<article className="relative z-10 flex items-center justify-center min-h-screen p-4">
<div className="bg-base-100/80 backdrop-blur-md shadow-lg hover:shadow-xl transition-shadow duration-300 rounded-lg w-full max-w-2xl">
<div className="p-6">
<div className="flex items-center space-x-4">
<Image src="/dvm0x742/avatar.jpg" width={100} height={100} alt="Profile" className="rounded-full" />
<div>
<h1 className="text-2xl font-bold text-base-content leading-tight">Michael Ojekunle</h1>
<div className="text-secondary-content flex flex-col gap-1">
<span className="">Frontend Developer / Smart Contract Writer</span>
<Address address="0x7429CbD5eD20736645723E972bE60B7F6BF5959c" format="long" size="xs" />
</div>
</div>
</div>
</div>
<div className="px-6 py-2 space-y-4">
<p className="text-sm text-base-content">
Hey, I&apos;m Michael! I&apos;m a frontend dev, blockchain explorer, and lover of all things tech.
I&apos;m all about building cool stuff, sharing what I learn, and helping others &ldquo;Code and
Thrive.&rdquo; When I&apos;m not coding or writing, I&apos;m probably geeking out on finance, snapping
photos of nature, or figuring out how to make life a little more awesome. Let&apos;s create something
amazing together!
</p>
</div>
<div className="px-6 py-4 flex justify-center space-x-4">
<SocialLink href="https://linkedin.com/in/michael-ojekunle" icon={<LuLinkedin />} label="LinkedIn" />
<SocialLink href="https://twitter.com/MichaelOjekunl2" icon={<FaXTwitter />} label="X (formerly Twitter)" />
<SocialLink href="https://github.com/michojekunle" icon={<LuGithub />} label="GitHub" />
</div>
</div>
</article>
</div>
);
};

const SocialLink = ({ href, icon, label }: { href: string; icon: React.ReactNode; label: string }) => (
<Link
href={href}
className="inline-flex items-center justify-center w-10 h-10 rounded-full text-primary hover:text-secondary bg-secondary hover:bg-secondary-content focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-primary transition-colors duration-300"
aria-label={label}
>
{icon}
</Link>
);

export default DevvMichaelProfile;
phipsae marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import dynamic from "next/dynamic";
import type { NextPage } from "next";

const DevvMichaelProfile: NextPage = dynamic(() => import("./_components/DevvMichaelProfile"), { ssr: false });

export default DevvMichaelProfile;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might want to consider typing your page as NextPage since we are using TypeScript, as this ensures better integration and adds clarity for future maintainers by indicating that the component is a Next.js page and also aligns with all the other builder pages.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alright, Awesome, I'm on it

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @phipsae, Thank you so much for the review. I've implemented the changes

2 changes: 2 additions & 0 deletions packages/nextjs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"blo": "^1.0.1",
"burner-connector": "^0.0.8",
"daisyui": "4.12.10",
"lucide-react": "^0.453.0",
"next": "^14.2.11",
"next-nprogress-bar": "^2.3.13",
"next-themes": "^0.3.0",
Expand All @@ -30,6 +31,7 @@
"react-copy-to-clipboard": "^5.1.0",
"react-dom": "^18.3.1",
"react-hot-toast": "^2.4.0",
"react-icons": "^5.3.0",
"use-debounce": "^8.0.4",
"usehooks-ts": "^2.13.0",
"viem": "2.21.7",
Expand Down
Binary file added packages/nextjs/public/dvm0x742/avatar.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -2182,6 +2182,7 @@ __metadata:
eslint-config-next: ^14.0.4
eslint-config-prettier: ^8.5.0
eslint-plugin-prettier: ^4.2.1
lucide-react: ^0.453.0
next: ^14.2.11
next-nprogress-bar: ^2.3.13
next-themes: ^0.3.0
Expand All @@ -2192,6 +2193,7 @@ __metadata:
react-copy-to-clipboard: ^5.1.0
react-dom: ^18.3.1
react-hot-toast: ^2.4.0
react-icons: ^5.3.0
tailwindcss: ^3.4.11
type-fest: ^4.6.0
typescript: 5.5.3
Expand Down Expand Up @@ -9367,6 +9369,15 @@ __metadata:
languageName: node
linkType: hard

"lucide-react@npm:^0.453.0":
version: 0.453.0
resolution: "lucide-react@npm:0.453.0"
peerDependencies:
react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0-rc
checksum: 1a48153fd9338266d8bb14c735bfe8bfb046c505ab91421586cbae0a8ac1924536e813d430d1f91c883bb4ea67f0664bfca273f58e478438f0ad8f8f09fced76
languageName: node
linkType: hard

"make-dir@npm:^3.1.0":
version: 3.1.0
resolution: "make-dir@npm:3.1.0"
Expand Down Expand Up @@ -11314,6 +11325,15 @@ __metadata:
languageName: node
linkType: hard

"react-icons@npm:^5.3.0":
version: 5.3.0
resolution: "react-icons@npm:5.3.0"
peerDependencies:
react: "*"
checksum: 3aa5f50e05aafc6d31e0d995fe0d98560069aa88717b24ce8aaa082a7e7b20ca95e1e19d847ed6e52d658a5a30e15826af20d7554bf993a743edd55586db62e3
languageName: node
linkType: hard

"react-is@npm:^16.13.1":
version: 16.13.1
resolution: "react-is@npm:16.13.1"
Expand Down