Skip to content
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
71 changes: 59 additions & 12 deletions packages/nextjs/app/sessions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ export const SPEAKERS = {
name: "Carlos Sánchez",
image: "/speakers/carlos.jpg",
},
SHIV: {
name: "Shiv Bhonde",
image: "/speakers/shiv.jpeg",
},
PABLO: {
name: "Pablo Alayeto",
image: "/speakers/pablo.png",
Expand Down Expand Up @@ -84,6 +88,14 @@ export const SPEAKERS = {
name: "Jeffrey Scholz",
image: "/speakers/jeffrey.jpg",
},
NIKOLAI: {
name: "Nikolai",
image: "/speakers/nikolai.jpeg",
},
HUNTER: {
name: "Hunter B.",
image: "/speakers/hunter.jpg",
},
};

export const sessions: Session[] = [
Expand All @@ -97,21 +109,33 @@ export const sessions: Session[] = [
"Explore what makes Ethereum fascinating and discover how the blockchain technology actually works. We'll dive into the core concepts, consensus mechanisms, and unique features that make Ethereum the world's most programmable blockchain platform.",
dayOfWeek: "Tuesday",
dateString: "November 18",
type: SessionType.WORKSHOP,
type: SessionType.TALK,
speaker: [SPEAKERS.PATRICK],
},
{
title: "Build your first dApp on Ethereum",
date: "2025-11-18",
startTime: "12:00",
endTime: "13:00",
startTime: "11:30",
endTime: "12:30",
description:
"Jump into Ethereum development with this hands-on workshop! Using Scaffold-ETH 2, you'll build and deploy your very first decentralized application from scratch. By the end of this session, you'll have a working dApp and understand the fundamentals of smart contract development. No prior blockchain experience required.",
dayOfWeek: "Tuesday",
dateString: "November 18",
type: SessionType.WORKSHOP,
speaker: [SPEAKERS.AUSTIN],
},
{
title: "Unveling Scaffold UI",
date: "2025-11-18",
startTime: "12:30",
endTime: "13:00",
description:
"Scaffold UI is a collection of React components and hooks designed specifically for building Ethereum dApps. These components provide a seamless way to interact with Ethereum addresses, balances, and user inputs in your decentralized applications.",
dayOfWeek: "Tuesday",
dateString: "November 18",
type: SessionType.WORKSHOP,
speaker: [SPEAKERS.SHIV],
},
{
title: "Introduction to SpeedRunEthereum",
date: "2025-11-18",
Expand Down Expand Up @@ -164,15 +188,27 @@ export const sessions: Session[] = [
{
title: "Zero-Knowledge Proofs",
date: "2025-11-19",
startTime: "11:30",
endTime: "12:30",
startTime: "11:00",
endTime: "12:00",
description:
"Explore the world of Zero-Knowledge proofs and privacy-preserving computation. This SpeedRunEthereum challenge guides you through implementing ZK circuits, understanding proof generation and verification, and building applications that can prove knowledge without revealing secrets.",
dayOfWeek: "Wednesday",
dateString: "November 19",
type: SessionType.CHALLENGE,
speaker: [SPEAKERS.PHILIP],
},
{
title: "Run your own Ethereum node",
date: "2025-11-19",
startTime: "12:00",
endTime: "13:00",
description:
"Take control of your Ethereum experience by running your own node! Discover why node operators are the backbone of decentralization, learn the difference between execution and consensus clients, and walk through the complete setup process. We'll cover hardware requirements, client selection, and best practices for maintaining a secure, synced node that gives you trustless access to the Ethereum network.",
dayOfWeek: "Thursday",
dateString: "November 20",
type: SessionType.WORKSHOP,
speaker: [SPEAKERS.SPENCER],
},
{
title: "Leveraging AI to build on Ethereum",
date: "2025-11-19",
Expand Down Expand Up @@ -235,16 +271,27 @@ export const sessions: Session[] = [
speaker: [SPEAKERS.HORSEFACTS],
},
{
title: "Run your own Ethereum node",
title: "Build a Farcaster Miniapp",
date: "2025-11-20",
startTime: "11:00",
endTime: "11:45",
description:
"Take control of your Ethereum experience by running your own node! Discover why node operators are the backbone of decentralization, learn the difference between execution and consensus clients, and walk through the complete setup process. We'll cover hardware requirements, client selection, and best practices for maintaining a secure, synced node that gives you trustless access to the Ethereum network.",
endTime: "11:30",
description: "Join Nikolai for a hands-on workshop on building & deploying Farcaster miniapps with Scaffold-ETH",
dayOfWeek: "Thursday",
dateString: "November 20",
type: SessionType.WORKSHOP,
speaker: [SPEAKERS.SPENCER],
speaker: [SPEAKERS.NIKOLAI],
},
{
title: "Miniapps ecosystem on Arbitrum",
date: "2025-11-20",
startTime: "11:30",
endTime: "12:00",
description:
"Join Hunter to explore the growing ecosystem of Farcaster miniapps on Arbitrum. We'll dive into the latest trends, use cases, and tools available for building on this Layer 2 network.",
dayOfWeek: "Thursday",
dateString: "November 20",
type: SessionType.TALK,
speaker: [SPEAKERS.HUNTER],
},
{
title: "PMfers live",
Expand Down Expand Up @@ -354,8 +401,8 @@ export const getSessionPosition = (session: Session) => {
const startOffsetMinutes = startMinutes - gridStartMinutes;
const durationMinutes = endMinutes - startMinutes;

// Each hour = 80px, so each minute = 80/60 px
const pixelsPerMinute = 80 / 60;
// Each hour = 104px, so each minute = 104/60 px
const pixelsPerMinute = 120 / 60;

return {
startRow: Math.floor(startOffsetMinutes / 60) + 1, // which hour row
Expand Down
137 changes: 70 additions & 67 deletions packages/nextjs/components/ScheduleCalendar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,86 +31,89 @@ export const ScheduleCalendar = () => {
};

return (
<div className="w-full max-w-7xl mx-auto p-4 sm:p-6 overflow-x-auto bg-white/40 rounded-xl">
<div className="flex gap-2 sm:gap-4 mb-6 min-w-[800px]">
<div className="w-8 text-sm font-medium text-base-content/60"></div>
{days.map(day => {
const { dayOfWeek, dateString } = getDayInfo(day);
return (
<div key={day} className="flex-1 text-center">
<h2 className="text-lg font-bold text-primary m-0">{dayOfWeek}</h2>
<p className="text-sm text-base-content/70 m-0">{dateString}</p>
</div>
);
})}
</div>

<div className="relative min-w-[800px]">
<div className="flex gap-2 sm:gap-4">
<div className="w-12 space-y-0">
{timeSlots.map(timeSlot => (
<div key={timeSlot.time24} className="h-20 border-b border-base-300 flex items-start pt-1">
<span className="text-sm font-medium text-base-content/70">{timeSlot.time12}</span>
// wrapping div with overflow-x-auto
<div className="overflow-x-auto">
<div className="w-[1320px] mx-auto p-4 sm:p-6 bg-white/40 rounded-xl">
<div className="flex gap-2 sm:gap-4 mb-6 min-w-[800px]">
<div className="w-8 text-sm font-medium text-base-content/60"></div>
{days.map(day => {
const { dayOfWeek, dateString } = getDayInfo(day);
return (
<div key={day} className="flex-1 text-center">
<h2 className="text-lg font-bold text-primary m-0">{dayOfWeek}</h2>
<p className="text-sm text-base-content/70 m-0">{dateString}</p>
</div>
))}
</div>
);
})}
</div>

{days.map(day => (
<div key={day} className="flex-1 relative space-y-0">
<div className="relative min-w-[800px]">
<div className="flex gap-2 sm:gap-4">
<div className="w-12 space-y-0">
{timeSlots.map(timeSlot => (
<div key={timeSlot.time24} className="h-20 border-b border-black/20"></div>
<div key={timeSlot.time24} className="h-30 border-b border-base-300 flex items-start pt-1">
<span className="text-sm font-medium text-base-content/70">{timeSlot.time12}</span>
</div>
))}
</div>
))}
</div>
</div>

<div className="absolute inset-0 flex gap-2 sm:gap-4">
<div className="w-12"></div>
<div className="absolute inset-0 flex gap-2 sm:gap-4">
<div className="w-12"></div>

{days.map(day => {
const daySessions = getSessionsForDay(day);
{days.map(day => {
const daySessions = getSessionsForDay(day);

return (
<div key={day} className="flex-1 relative">
{daySessions.map(session => {
const position = getSessionPosition(session);
const colors = sessionTypeColors[session.type];
const className =
"absolute left-0 right-0 outline outline-2 outline-gray-300 rounded-lg cursor-pointer hover:shadow-md transition-shadow p-2 z-10";
const style = { ...colors, top: `${position.startOffset}px`, height: `${position.duration}px` };
return (
<div key={day} className="flex-1 relative">
{daySessions.map(session => {
const position = getSessionPosition(session);
const colors = sessionTypeColors[session.type];
const className =
"absolute left-0 right-0 outline outline-2 outline-gray-300 rounded-lg cursor-pointer hover:shadow-md transition-shadow p-2.5 z-10";
const style = { ...colors, top: `${position.startOffset}px`, height: `${position.duration}px` };

return (
<div
key={session.title}
className={className}
style={style}
onClick={() => handleSessionClick(session)}
>
<div className="h-full flex flex-col justify-between">
<div>
<h3 className="font-semibold text-sm leading-tight mb-1">{session.title}</h3>
</div>
<div>
<p className="text-xs opacity-75 m-0">
{formatTo12Hour(session.startTime)} - {formatTo12Hour(session.endTime)}{" "}
{session.speaker && (
<span className="font-bold">
- {session.speaker.map(speaker => speaker.name).join(", ")}
</span>
)}
</p>
return (
<div
key={session.title}
className={className}
style={style}
onClick={() => handleSessionClick(session)}
>
<div className="h-full flex flex-col justify-between">
<div>
<h3 className="font-semibold text-sm leading-tight mb-1">{session.title}</h3>
</div>
<div>
<p className="text-xs opacity-75 m-0">
{formatTo12Hour(session.startTime)} - {formatTo12Hour(session.endTime)}{" "}
{session.speaker && (
<span className="font-bold">
- {session.speaker.map(speaker => speaker.name).join(", ")}
</span>
)}
</p>
</div>
</div>
</div>
</div>
);
})}
</div>
);
})}
);
})}
</div>
);
})}
</div>

{/* Lunch break banner */}
<div
className="absolute flex items-center justify-center pointer-events-none border-y-2 border-dashed border-base-content/20"
style={{ top: "365px", left: "68px", right: "0", height: "110px" }}
>
<span className="font-mono text-base-content/40">&#47;&#47; LUNCH_BREAK</span>
</div>
</div>
</div>

<SessionModal session={selectedSession} isOpen={isModalOpen} onClose={handleCloseModal} />
<SessionModal session={selectedSession} isOpen={isModalOpen} onClose={handleCloseModal} />
</div>
</div>
);
};
Binary file added packages/nextjs/public/speakers/hunter.jpg
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/speakers/nikolai.jpeg
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/speakers/shiv.jpeg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.