Skip to content

Commit

Permalink
#7: Tweak the main page
Browse files Browse the repository at this point in the history
  • Loading branch information
kcmikee committed Nov 13, 2024
1 parent 2110958 commit c279fd3
Show file tree
Hide file tree
Showing 6 changed files with 343 additions and 61 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const MichaelEsenwa: NextPage = () => {
Hi there, I am Kachukwu Michael Esenwa{" "}
</h1>
<div className="h-[100px] w-[100px] lg:w-[300px] lg:h-[300px] shrink-0 !overflow-hidden rounded-full relative lg:hidden">
<Image fill src="https://avatars.githubusercontent.com/u/42065630?v=4" alt="avatar" />
<Image fill src="https://avatars.githubusercontent.com/u/42065630?v=5" alt="avatar" />
</div>
</div>
<hr className="mt-2 border-gray-500" />
Expand Down Expand Up @@ -42,7 +42,7 @@ const MichaelEsenwa: NextPage = () => {
</div>
</div>
<div className="h-[100px] w-[100px] lg:w-[300px] lg:h-[300px] shrink-0 !overflow-hidden rounded-full relative hidden lg:block">
<Image fill src="https://avatars.githubusercontent.com/u/42065630?v=4" alt="avatar" />
<Image fill src="https://avatars.githubusercontent.com/u/42065630?v=5" alt="avatar" />
</div>
</div>
</div>
Expand Down
151 changes: 92 additions & 59 deletions packages/nextjs/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
"use client";

import Image from "next/image";
import Link from "next/link";
import "../styles/LandingPage.css";
import ShootingStars from "./builders/0x28482B1279E442f49eE76351801232D58f341CB9/components/ShootingStars";
import type { NextPage } from "next";
import { useAccount } from "wagmi";
import { BugAntIcon, MagnifyingGlassIcon } from "@heroicons/react/24/outline";
import { StarsBackground } from "~~/components/StarsBg";
import { Address } from "~~/components/scaffold-eth";
import { useScaffoldReadContract } from "~~/hooks/scaffold-eth";

Expand All @@ -19,6 +23,20 @@ interface BatchUserStatus {
isLoading: boolean;
}

const images = [
"/bello/bello.jpg",
"/dvm0x742/avatar.jpg",
"/lukmansImages/lukmansAvater.jpeg",
"/michaelNwachukwu-images/michael-nwachukwu.png",
"https://avatars.githubusercontent.com/u/42065630?v=5",
"/0x26BfbD8ED2B302ec2c2B6f063C4caF7abcB062e0-avatar.jpg",
"/avatar.webp",
"/emarc-pixels.jpg",
"/superior.jpeg",
"/cherry/cherrypfp.png",
"https://avatars.githubusercontent.com/u/141290516?v=4",
];

const Alert = ({ children, className = "" }: Props) => (
<div className={`rounded-lg border p-4 mt-6 max-w-md mx-auto ${className}`}>{children}</div>
);
Expand All @@ -30,7 +48,7 @@ const AlertTitle = ({ children }: Props) => (
const AlertDescription = ({ children }: Props) => <div className="text-sm opacity-70">{children}</div>;

const Card = ({ children, className = "" }: Props) => (
<div className={`rounded-lg border bg-card text-card-foreground shadow-sm mt-6 max-w-md mx-auto ${className}`}>
<div className={`rounded-lg border bg-card text-card-foreground shadow-sm mt-6 max-w-xl mx-auto ${className}`}>
{children}
</div>
);
Expand All @@ -52,7 +70,7 @@ const StatusSection = ({ connectedAddress, isAllowListed, isCheckedIn, isLoading
<CardContent>
<div className="flex items-center justify-center py-6">
<div className="flex items-center space-x-2">
<div className="h-6 w-6 animate-spin rounded-full border-b-2 border-gray-900"></div>
<div className="w-6 h-6 border-b-2 border-gray-900 rounded-full animate-spin"></div>
<p className="text-sm text-muted">Checking your status...</p>
</div>
</div>
Expand All @@ -76,7 +94,7 @@ const StatusSection = ({ connectedAddress, isAllowListed, isCheckedIn, isLoading
<CardHeader className="pb-3">
<div className="flex items-center justify-between">
<CardTitle>Your Status</CardTitle>
<span className="rounded-full px-2 py-1 text-sm font-medium bg-red-100 text-red-800">Not a Member</span>
<span className="px-2 py-1 text-sm font-medium text-red-800 bg-red-100 rounded-full">Not a Member</span>
</div>
</CardHeader>
<CardContent>
Expand All @@ -92,7 +110,7 @@ const StatusSection = ({ connectedAddress, isAllowListed, isCheckedIn, isLoading
<CardHeader className="pb-3">
<div className="flex items-center justify-between">
<CardTitle>Your Status</CardTitle>
<span className="rounded-full px-2 py-1 text-sm font-medium bg-yellow-100 text-yellow-800">
<span className="px-2 py-1 text-sm font-medium text-yellow-800 bg-yellow-100 rounded-full">
Ready to Check In
</span>
</div>
Expand All @@ -105,15 +123,15 @@ const StatusSection = ({ connectedAddress, isAllowListed, isCheckedIn, isLoading
}

return (
<Card>
<Card className="w-9/12 md:w-[446px]">
<CardHeader className="pb-3">
<div className="flex items-center justify-between">
<CardTitle>Your Status</CardTitle>
<span className="rounded-full px-2 py-1 text-sm font-medium bg-green-100 text-green-800">Checked In</span>
<span className="px-2 py-1 text-sm font-medium text-green-800 bg-green-100 rounded-full">Checked In</span>
</div>
</CardHeader>
<CardContent>
<div className="text-sm opacity-70">
<div className="text-sm text-left opacity-70">
Active with wallet address: <Address address={connectedAddress} />
</div>
</CardContent>
Expand Down Expand Up @@ -158,62 +176,77 @@ const Home: NextPage = () => {
const isCheckedIn = userContractAddress && userContractAddress !== "0x0000000000000000000000000000000000000000";

return (
<div className="flex items-center flex-col flex-grow pt-10">
<div className="px-5">
<h1 className="text-center">
<span className="block text-2xl mb-2">Welcome to</span>
<span className="block text-4xl font-bold">Batch 10</span>
</h1>
<p className="text-center text-lg">Get started by taking a look at your batch GitHub repository.</p>

{error ? (
<div className="p-4 rounded-lg bg-red-100 text-red-700" role="alert">
<p>Error fetching contract data: {error.message}</p>
</div>
) : (
<div>
<div className="text-lg flex gap-2 justify-center mb-4">
<span className="font-bold">Checked in builders count:</span>
{counterLoading ? (
<span className="animate-pulse">
<div className="h-6 bg-gray-200 rounded w-12"></div>
</span>
) : (
<span>{checkedInCounter !== undefined ? Number(checkedInCounter) : "0"}</span>
)}
<div className="relative flex flex-col items-center flex-grow min-h-screen overflow-hidden bg">
<ShootingStars />
<StarsBackground />
<div className="banner">
<div className="slider" style={{ "--quantity": 11 } as React.CSSProperties}>
{images.map((image, index) => (
<div key={index} className="item" style={{ "--position": index + 1 } as React.CSSProperties}>
<Image src={image} alt={`builder ${index + 1}`} width={300} height={300} />
</div>

<StatusSection
connectedAddress={connectedAddress as string}
isAllowListed={isAllowListed as boolean}
isCheckedIn={isCheckedIn as boolean}
isLoading={isLoading as boolean}
/>
))}
</div>
<div className="content">
<h1 data-content="BATCH 10" className="BuidlGuidl">
BATCH 10
</h1>
<div className="author">
<h2>Buidl Guidl</h2>
</div>
)}
<div className="model"></div>
</div>
</div>
<div className="!h-max banner">
<div className="flex-grow w-screen z-[9999]">
{error ? (
<div className="p-4 text-red-700 bg-red-100 rounded-lg" role="alert">
<p>Error fetching contract data: {error.message}</p>
</div>
) : (
<div className="relative">
<div className="flex justify-center gap-2 mb-4 text-lg">
<span className="font-bold">Checked in builders count:</span>
{counterLoading ? (
<span className="animate-pulse">
<div className="w-12 h-6 bg-gray-200 rounded"></div>
</span>
) : (
<span>{checkedInCounter !== undefined ? Number(checkedInCounter) : "0"}</span>
)}
</div>

<div className="flex-grow bg-base-300 w-full mt-16 px-8 py-12">
<div className="flex justify-center items-center gap-12 flex-col sm:flex-row">
<div className="flex flex-col bg-base-100 px-10 py-10 text-center items-center max-w-xs rounded-3xl">
<BugAntIcon className="h-8 w-8 fill-secondary" />
<p>
Tinker with your smart contract using the{" "}
<Link href="/debug" className="link">
Debug Contracts
</Link>{" "}
tab.
</p>
</div>
<div className="flex flex-col bg-base-100 px-10 py-10 text-center items-center max-w-xs rounded-3xl">
<MagnifyingGlassIcon className="h-8 w-8 fill-secondary" />
<p>
Explore your local transactions with the{" "}
<Link href="/blockexplorer" className="link">
Block Explorer
</Link>{" "}
tab.
</p>
<StatusSection
connectedAddress={connectedAddress as string}
isAllowListed={isAllowListed as boolean}
isCheckedIn={isCheckedIn as boolean}
isLoading={isLoading as boolean}
/>
</div>
)}
</div>
<div className="flex-grow w-screen !px-8 !py-12 mt-16 z-[9999]">
<div className="flex flex-col items-center justify-center gap-12 sm:flex-row">
<div className="flex flex-col items-center max-w-xs px-10 py-10 text-center bg-base-100 rounded-3xl">
<BugAntIcon className="w-8 h-8 fill-secondary" />
<p>
Tinker with your smart contract using the{" "}
<Link href="/debug" className="link">
Debug Contracts
</Link>{" "}
tab.
</p>
</div>
<div className="flex flex-col items-center max-w-xs px-10 py-10 text-center bg-base-100 rounded-3xl">
<MagnifyingGlassIcon className="w-8 h-8 fill-secondary" />
<p>
Explore your local transactions with the{" "}
<Link href="/blockexplorer" className="link">
Block Explorer
</Link>{" "}
tab.
</p>
</div>
</div>
</div>
</div>
Expand Down
116 changes: 116 additions & 0 deletions packages/nextjs/components/StarsBg.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
"use client";

import React, { RefObject, useCallback, useEffect, useRef, useState } from "react";

interface StarProps {
x: number;
y: number;
radius: number;
opacity: number;
twinkleSpeed: number | null;
}

interface StarBackgroundProps {
starDensity?: number;
allStarsTwinkle?: boolean;
twinkleProbability?: number;
minTwinkleSpeed?: number;
maxTwinkleSpeed?: number;
className?: string;
}

export const StarsBackground: React.FC<StarBackgroundProps> = ({
starDensity = 0.00015,
allStarsTwinkle = true,
twinkleProbability = 0.7,
minTwinkleSpeed = 0.5,
maxTwinkleSpeed = 1,
}) => {
const [stars, setStars] = useState<StarProps[]>([]);
const canvasRef: RefObject<HTMLCanvasElement> = useRef<HTMLCanvasElement>(null);

const generateStars = useCallback(
(width: number, height: number): StarProps[] => {
const area = width * height;
const numStars = Math.floor(area * starDensity);
return Array.from({ length: numStars }, () => createStar(width, height));
},
[starDensity, allStarsTwinkle, twinkleProbability, minTwinkleSpeed, maxTwinkleSpeed],
);

const createStar = (width: number, height: number): StarProps => {
const shouldTwinkle = allStarsTwinkle || Math.random() < twinkleProbability;
return {
x: Math.random() * width,
y: Math.random() * height,
radius: Math.random() * 0.05 + 0.5,
opacity: Math.random() * 0.5 + 0.5,
twinkleSpeed: shouldTwinkle ? minTwinkleSpeed + Math.random() * (maxTwinkleSpeed - minTwinkleSpeed) : null,
};
};

useEffect(() => {
const updateStars = () => {
if (canvasRef.current) {
const canvas = canvasRef.current;
const ctx = canvas.getContext("2d");
if (!ctx) return;

const { width, height } = canvas.getBoundingClientRect();
canvas.width = width;
canvas.height = height;
setStars(generateStars(width, height));
}
};

updateStars();

const resizeObserver = new ResizeObserver(updateStars);
const currentCanvas = canvasRef.current; // Copy the ref value to a variable
if (currentCanvas) {
resizeObserver.observe(currentCanvas);
}

return () => {
if (currentCanvas) {
resizeObserver.unobserve(currentCanvas);
}
};
}, [starDensity, allStarsTwinkle, twinkleProbability, minTwinkleSpeed, maxTwinkleSpeed, generateStars]);

useEffect(() => {
const canvas = canvasRef.current;
if (!canvas) return;

const ctx = canvas.getContext("2d");
if (!ctx) return;

let animationFrameId: number;

const render = () => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
stars.forEach(star => drawStar(ctx, star));

animationFrameId = requestAnimationFrame(render);
};

render();

return () => {
cancelAnimationFrame(animationFrameId);
};
}, [stars]);

const drawStar = (ctx: CanvasRenderingContext2D, star: StarProps) => {
ctx.beginPath();
ctx.arc(star.x, star.y, star.radius, 0, Math.PI * 2);
ctx.fillStyle = `rgba(255, 255, 255, ${star.opacity})`;
ctx.fill();

if (star.twinkleSpeed !== null) {
star.opacity = 0.5 + Math.abs(Math.sin((Date.now() * 0.001) / star.twinkleSpeed) * 0.5);
}
};

return <canvas ref={canvasRef} className={"min-h-full w-full absolute inset-0 !bg-black"} />;
};
Binary file added packages/nextjs/public/cherry/cherrypfp.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added packages/nextjs/public/guild.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit c279fd3

Please sign in to comment.