-
Notifications
You must be signed in to change notification settings - Fork 10
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add initial components
- Loading branch information
Showing
5 changed files
with
255 additions
and
131 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
# dependencies | ||
/node_modules | ||
/.pnp | ||
.pnp.js | ||
|
||
# testing | ||
/coverage | ||
|
||
# next.js | ||
/.next/ | ||
/out/ | ||
|
||
# production | ||
/build | ||
|
||
# misc | ||
.DS_Store | ||
*.pem | ||
|
||
# debug | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
|
||
# local env files | ||
.env*.local | ||
|
||
# vercel | ||
.vercel | ||
|
||
# typescript | ||
*.tsbuildinfo | ||
next-env.d.ts | ||
|
||
.env |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,153 @@ | ||
import { useState, useEffect, ChangeEvent, useCallback } from "react"; | ||
import TerminalCursor from "./TerminalCursor"; | ||
|
||
type ThoughtEntry = { | ||
timestamp: Date; | ||
content: string; | ||
}; | ||
|
||
type AnimatedData = { | ||
earned: number; | ||
spent: number; | ||
staked: number; | ||
transactions: number; | ||
thoughts: number; | ||
}; | ||
|
||
export default function AgentComponent() { | ||
const [currentTime, setCurrentTime] = useState(new Date()); | ||
const [thoughts, setThoughts] = useState<ThoughtEntry[]>([]); | ||
const [userInput, setUserInput] = useState(""); | ||
const [animatedData, setAnimatedData] = useState<AnimatedData>({ | ||
earned: 10000, | ||
spent: 4000, | ||
staked: 1000, | ||
transactions: 0, | ||
thoughts: 900, | ||
}); | ||
|
||
const generateRandomThought = useCallback((): ThoughtEntry => { | ||
const thoughts = [ | ||
"Analyzing data patterns...", | ||
"Processing natural language input...", | ||
"Optimizing neural networks...", | ||
"Generating creative solutions...", | ||
"Evaluating ethical implications...", | ||
"Simulating complex scenarios...", | ||
"Integrating cross-domain knowledge...", | ||
"Refining machine learning models...", | ||
"Exploring innovative algorithms...", | ||
"Synthesizing information from multiple sources...", | ||
]; | ||
return { | ||
timestamp: new Date(), | ||
content: thoughts[Math.floor(Math.random() * thoughts.length)], | ||
}; | ||
}, []); | ||
|
||
const formatGMTDate = useCallback((date: Date) => { | ||
return date.toISOString().replace("T", " ").slice(0, -5); | ||
}, []); | ||
|
||
useEffect(() => { | ||
const timeInterval = setInterval(() => { | ||
setCurrentTime(new Date()); | ||
}, 1000); | ||
|
||
const thoughtInterval = setInterval(() => { | ||
const newThought = generateRandomThought(); | ||
setThoughts((prevThoughts) => [...prevThoughts, newThought].slice(-10)); | ||
setAnimatedData((prev) => ({ | ||
...prev, | ||
thoughts: prev.thoughts + 1, | ||
})); | ||
}, 3000); | ||
|
||
const dataInterval = setInterval(() => { | ||
setAnimatedData((prev) => ({ | ||
earned: prev.earned + Math.random() * 10, | ||
spent: prev.spent + Math.random() * 5, | ||
staked: prev.staked + Math.random() * 2, | ||
transactions: prev.transactions + (Math.random() > 0.7 ? 1 : 0), | ||
thoughts: prev.thoughts, | ||
})); | ||
}, 2000); | ||
|
||
return () => { | ||
clearInterval(timeInterval); | ||
clearInterval(thoughtInterval); | ||
clearInterval(dataInterval); | ||
}; | ||
}, [generateRandomThought]); | ||
|
||
const handleInputChange = useCallback( | ||
(e: ChangeEvent<HTMLTextAreaElement>) => { | ||
setUserInput(e.target.value); | ||
}, | ||
[] | ||
); | ||
|
||
const handleSubmit = useCallback( | ||
(e: React.FormEvent) => { | ||
e.preventDefault(); | ||
console.log("User input:", userInput); | ||
setUserInput(""); | ||
}, | ||
[userInput] | ||
); | ||
|
||
return ( | ||
<div className="flex flex-col h-screen bg-black font-mono ock-text-primary"> | ||
<div className="p-4 flex items-center justify-between border-b border-[#5788FA]"> | ||
<h1 className="text-xl font-bold">Based Agent</h1> | ||
<div className="text-sm" aria-live="polite"> | ||
{formatGMTDate(currentTime)} GMT | ||
</div> | ||
</div> | ||
<div className="flex flex-grow overflow-hidden"> | ||
<div className="flex-grow p-4 overflow-y-auto"> | ||
<p>Streaming real-time thoughts and actions...</p> | ||
<div className="mt-4 space-y-2" role="log" aria-live="polite"> | ||
{thoughts.map((thought, index) => ( | ||
<div key={index} className="flex"> | ||
<span className="mr-2 ock-text-primary"> | ||
{formatGMTDate(thought.timestamp)} | ||
</span> | ||
<span>{thought.content}</span> | ||
</div> | ||
))} | ||
</div> | ||
<TerminalCursor /> | ||
</div> | ||
<div className="w-1/3 p-4 border-l border-[#5788FA] flex flex-col"> | ||
<div className="mb-4 p-4 border border-[#5788FA]"> | ||
<ul className="space-y-1"> | ||
<li>Earned: ${animatedData.earned.toFixed(2)}</li> | ||
<li>Spent: ${animatedData.spent.toFixed(2)}</li> | ||
<li>Staked: ${animatedData.staked.toFixed(2)}</li> | ||
<li>Transactions: {animatedData.transactions}</li> | ||
<li>Thoughts: {animatedData.thoughts}</li> | ||
<li>Friends: {animatedData.transactions}</li> | ||
</ul> | ||
</div> | ||
<form onSubmit={handleSubmit} className="flex-grow flex flex-col"> | ||
<div className="relative flex-grow"> | ||
<textarea | ||
value={userInput} | ||
onChange={handleInputChange} | ||
className="w-full h-full bg-black border border-[#5788FA] ock-text-primary p-2 pb-12 resize-none placeholder-[#5788FA] placeholder-opacity-50" | ||
placeholder="Type your prompt here..." | ||
/> | ||
<button | ||
type="submit" | ||
className="absolute rounded bottom-2 right-2 ock-bg-primary text-black px-6 py-1.5 hover:bg-[#3D7BFF] transition-colors" | ||
> | ||
Send | ||
</button> | ||
</div> | ||
</form> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import { useState, useEffect, useRef, useCallback } from "react"; | ||
|
||
export default function TerminalCursor() { | ||
const [text, setText] = useState(""); | ||
const [cursorVisible, setCursorVisible] = useState(true); | ||
const inputRef = useRef<HTMLInputElement>(null); | ||
|
||
useEffect(() => { | ||
const cursorInterval = setInterval(() => { | ||
setCursorVisible((prev) => !prev); | ||
}, 530); | ||
|
||
return () => clearInterval(cursorInterval); | ||
}, []); | ||
|
||
useEffect(() => { | ||
inputRef.current?.focus(); | ||
}, []); | ||
|
||
const handleChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => { | ||
setText(e.target.value); | ||
}, []); | ||
|
||
const handleKeyDown = useCallback( | ||
(e: React.KeyboardEvent<HTMLInputElement>) => { | ||
if (e.key === "Enter") { | ||
console.log("Command entered:", text); | ||
setText(""); | ||
} | ||
}, | ||
[text] | ||
); | ||
|
||
return ( | ||
<div | ||
className="bg-black font-mono text-lg h-64 overflow-auto mt-4" | ||
onClick={() => inputRef.current?.focus()} | ||
> | ||
<div className="flex"> | ||
<span className="mr-2">$</span> | ||
<div className="relative flex-grow"> | ||
{text} | ||
<span | ||
className={`absolute inset-y-0 ${ | ||
cursorVisible ? "opacity-100" : "opacity-0" | ||
} transition-opacity duration-100`} | ||
style={{ left: `${text.length * 0.61}em` }} | ||
> | ||
▋ | ||
</span> | ||
</div> | ||
</div> | ||
<input | ||
ref={inputRef} | ||
type="text" | ||
value={text} | ||
onChange={handleChange} | ||
onKeyDown={handleKeyDown} | ||
className="opacity-0 absolute" | ||
autoFocus | ||
/> | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,135 +1,7 @@ | ||
'use client'; | ||
"use client"; | ||
|
||
import { | ||
ConnectWallet, | ||
Wallet, | ||
WalletDropdown, | ||
WalletDropdownLink, | ||
WalletDropdownDisconnect, | ||
} from '@coinbase/onchainkit/wallet'; | ||
import { | ||
Address, | ||
Avatar, | ||
Name, | ||
Identity, | ||
EthBalance, | ||
} from '@coinbase/onchainkit/identity'; | ||
import ArrowSvg from './svg/ArrowSvg'; | ||
import ImageSvg from './svg/Image'; | ||
import OnchainkitSvg from './svg/OnchainKit'; | ||
|
||
const components = [ | ||
{ | ||
name: 'Transaction', | ||
url: 'https://onchainkit.xyz/transaction/transaction', | ||
}, | ||
{ name: 'Swap', url: 'https://onchainkit.xyz/swap/swap' }, | ||
{ name: 'Checkout', url: 'https://onchainkit.xyz/checkout/checkout' }, | ||
{ name: 'Wallet', url: 'https://onchainkit.xyz/wallet/wallet' }, | ||
{ name: 'Identity', url: 'https://onchainkit.xyz/identity/identity' }, | ||
]; | ||
|
||
const templates = [ | ||
{ name: 'NFT', url: 'https://github.com/coinbase/onchain-app-template' }, | ||
{ name: 'Commerce', url: 'https://github.com/coinbase/onchain-commerce-template'}, | ||
{ name: 'Fund', url: 'https://github.com/fakepixels/fund-component' }, | ||
]; | ||
import AgentComponent from "./components/AgentComponent"; | ||
|
||
export default function App() { | ||
return ( | ||
<div className="flex flex-col min-h-screen font-sans dark:bg-background dark:text-white bg-white text-black"> | ||
<header className="pt-4 pr-4"> | ||
<div className="flex justify-end"> | ||
<div className="wallet-container"> | ||
<Wallet> | ||
<ConnectWallet> | ||
<Avatar className="h-6 w-6" /> | ||
<Name /> | ||
</ConnectWallet> | ||
<WalletDropdown> | ||
<Identity className="px-4 pt-3 pb-2" hasCopyAddressOnClick> | ||
<Avatar /> | ||
<Name /> | ||
<Address /> | ||
<EthBalance /> | ||
</Identity> | ||
<WalletDropdownLink | ||
icon="wallet" | ||
href="https://keys.coinbase.com" | ||
target="_blank" | ||
rel="noopener noreferrer" | ||
> | ||
Wallet | ||
</WalletDropdownLink> | ||
<WalletDropdownDisconnect /> | ||
</WalletDropdown> | ||
</Wallet> | ||
</div> | ||
</div> | ||
</header> | ||
|
||
<main className="flex-grow flex items-center justify-center"> | ||
<div className="max-w-4xl w-full p-4"> | ||
<div className="w-1/3 mx-auto mb-6"> | ||
<ImageSvg /> | ||
</div> | ||
<div className="flex justify-center mb-6"> | ||
<a target="_blank" rel="_template" href="https://onchainkit.xyz"> | ||
<OnchainkitSvg className="dark:text-white text-black" /> | ||
</a> | ||
</div> | ||
<p className="text-center mb-6"> | ||
Get started by editing | ||
<code className="p-1 ml-1 rounded dark:bg-gray-800 bg-gray-200">app/page.tsx</code>. | ||
</p> | ||
<div className="flex flex-col items-center"> | ||
<div className="max-w-2xl w-full"> | ||
<div className="flex flex-col md:flex-row justify-between mt-4"> | ||
<div className="md:w-1/2 mb-4 md:mb-0 flex flex-col items-center"> | ||
<p className="font-semibold mb-2 text-center"> | ||
Explore components | ||
</p> | ||
<ul className="list-disc pl-5 space-y-2 inline-block text-left"> | ||
{components.map((component, index) => ( | ||
<li key={index}> | ||
<a | ||
href={component.url} | ||
className="hover:underline inline-flex items-center dark:text-white text-black" | ||
target="_blank" | ||
rel="noopener noreferrer" | ||
> | ||
{component.name} | ||
<ArrowSvg /> | ||
</a> | ||
</li> | ||
))} | ||
</ul> | ||
</div> | ||
<div className="md:w-1/2 flex flex-col items-center"> | ||
<p className="font-semibold mb-2 text-center"> | ||
Explore templates | ||
</p> | ||
<ul className="list-disc pl-5 space-y-2 inline-block text-left"> | ||
{templates.map((template, index) => ( | ||
<li key={index}> | ||
<a | ||
href={template.url} | ||
className="hover:underline inline-flex items-center dark:text-white text-black" | ||
target="_blank" | ||
rel="noopener noreferrer" | ||
> | ||
{template.name} | ||
<ArrowSvg/> | ||
</a> | ||
</li> | ||
))} | ||
</ul> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</main> | ||
</div> | ||
); | ||
return <AgentComponent />; | ||
} |
Binary file not shown.