diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..dac91d4 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,27 @@ +name: Template Build +on: + push: + branches: ['master'] + pull_request: + branches: ['master'] +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [18.x] + # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Bun + uses: oven-sh/setup-bun@v2 + + - name: Template Install dependencies + run: bun install + + - name: Template Test Build + # When fails, please check your build + run: | + bun run build \ No newline at end of file diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml new file mode 100644 index 0000000..4d85ce0 --- /dev/null +++ b/.github/workflows/check.yml @@ -0,0 +1,25 @@ +name: Template Check +on: + push: + branches: ["master"] + pull_request: + branches: ["master"] +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [18.x] + # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Bun + uses: oven-sh/setup-bun@v2 + + - name: Template Install dependencies + run: bun install + + - name: Template Check + run: bun run ci:check \ No newline at end of file diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml new file mode 100644 index 0000000..f8a2f37 --- /dev/null +++ b/.github/workflows/format.yml @@ -0,0 +1,25 @@ +name: Template Format +on: + push: + branches: ["master"] + pull_request: + branches: ["master"] +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [18.x] + # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Bun + uses: oven-sh/setup-bun@v2 + + - name: Template Install dependencies + run: bun install + + - name: Template Format + run: bun run ci:format \ No newline at end of file diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml new file mode 100644 index 0000000..70f03c2 --- /dev/null +++ b/.github/workflows/lint.yml @@ -0,0 +1,25 @@ +name: Template Lint +on: + push: + branches: ["master"] + pull_request: + branches: ["master"] +jobs: + build: + runs-on: ubuntu-latest + strategy: + matrix: + node-version: [18.x] + # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Setup Bun + uses: oven-sh/setup-bun@v2 + + - name: Template Install dependencies + run: bun install + + - name: Template Lint + run: bun run ci:lint \ No newline at end of file diff --git a/app/components/Agent.tsx b/app/components/Agent.tsx index b4c82fc..826efbb 100644 --- a/app/components/Agent.tsx +++ b/app/components/Agent.tsx @@ -1,29 +1,34 @@ -import { useState, useEffect, useCallback } from "react"; - -import Navbar from "./Navbar"; -import { ActionEntry, AgentMessage, Language, StreamEntry } from "../types"; -import Stream from "./Stream"; -import ChatInput from "./ChatInput"; -import Footer from "./Footer"; -import AgentProfile from "./AgentProfile"; -import AgentStats from "./AgentStats"; -import useChat from "../hooks/useChat"; +import { useCallback, useEffect, useState } from 'react'; + +import useChat from '../hooks/useChat'; +import type { + ActionEntry, + AgentMessage, + Language, + StreamEntry, +} from '../types'; +import AgentProfile from './AgentProfile'; +import AgentStats from './AgentStats'; +import ChatInput from './ChatInput'; +import Footer from './Footer'; +import Navbar from './Navbar'; +import Stream from './Stream'; export default function Agent() { const [streamEntries, setStreamEntries] = useState([]); - const [userInput, setUserInput] = useState(""); + const [userInput, setUserInput] = useState(''); const [isThinking, setIsThinking] = useState(true); - const [loadingDots, setLoadingDots] = useState(""); + const [loadingDots, setLoadingDots] = useState(''); const [isMobileMenuOpen, setIsMobileMenuOpen] = useState(false); - const [currentLanguage, setCurrentLanguage] = useState("en"); + const [currentLanguage, setCurrentLanguage] = useState('en'); const [isLiveDotVisible, setIsLiveDotVisible] = useState(true); const [isChatMode, setIsChatMode] = useState(false); const handleSuccess = useCallback((messages: AgentMessage[]) => { - const message = messages.find((res) => res.event === "agent"); + const message = messages.find((res) => res.event === 'agent'); const streamEntry = { timestamp: new Date(), - content: message?.data || "", + content: message?.data || '', }; setIsThinking(false); setStreamEntries((prev) => [...prev, streamEntry]); @@ -38,7 +43,7 @@ export default function Agent() { useEffect(() => { const streamInterval = setInterval(() => { if (!isLoading && !isChatMode) { - postChat("same a one liner that is inspiring"); + postChat('same a one liner that is inspiring'); } }, 1500); @@ -50,7 +55,7 @@ export default function Agent() { // enables dot animation for "agent is thinking..." useEffect(() => { const dotsInterval = setInterval(() => { - setLoadingDots((prev) => (prev.length >= 3 ? "" : prev + ".")); + setLoadingDots((prev) => (prev.length >= 3 ? '' : `${prev}.`)); }, 500); return () => clearInterval(dotsInterval); @@ -68,15 +73,17 @@ export default function Agent() { const handleSubmit = useCallback( async (e: React.FormEvent) => { e.preventDefault(); - if (!userInput.trim()) return; + if (!userInput.trim()) { + return; + } // disable live stream setIsChatMode(true); - setUserInput(""); + setUserInput(''); const userMessage: ActionEntry = { timestamp: new Date(), - type: "user", + type: 'user', content: userInput.trim(), }; @@ -84,17 +91,17 @@ export default function Agent() { postChat(userInput); }, - [postChat, userInput] + [postChat, userInput], ); const handleKeyPress = useCallback( (e: React.KeyboardEvent) => { - if (e.key === "Enter" && !e.shiftKey) { + if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); handleSubmit(e); } }, - [handleSubmit] + [handleSubmit], ); const handleLanguageChange = useCallback((lang: Language) => { @@ -103,7 +110,7 @@ export default function Agent() { }, []); return ( -
+
-
+
-
+
setShowToast(false), 2000); // Hide toast after 2 seconds }) .catch((err) => { - console.error("Failed to copy wallet address: ", err); + console.error('Failed to copy wallet address: ', err); }); }, []); @@ -37,24 +37,24 @@ export default function AgentProfile({ currentLanguage }: AgentProfileProps) { const normalizedX = Math.min( Math.max((dx / maxDistance) * 30 + 50, 20), - 80 + 80, ); const normalizedY = Math.min( Math.max((dy / maxDistance) * 30 + 50, 20), - 80 + 80, ); setEyePosition({ x: normalizedX, y: normalizedY }); } }; - window.addEventListener("mousemove", handleMouseMove); - return () => window.removeEventListener("mousemove", handleMouseMove); + window.addEventListener('mousemove', handleMouseMove); + return () => window.removeEventListener('mousemove', handleMouseMove); }, []); const formattedAddress = useMemo(() => { return `${AGENT_WALLET_ADDRESS.slice(0, 6)}...${AGENT_WALLET_ADDRESS.slice( - -4 + -4, )}`; }, []); @@ -81,16 +81,17 @@ export default function AgentProfile({ currentLanguage }: AgentProfileProps) {
-

{AGENT_NAME}

-
+

{AGENT_NAME}

+
{showToast && ( -
+
Copied
)} @@ -99,8 +100,8 @@ export default function AgentProfile({ currentLanguage }: AgentProfileProps) {

{translations[currentLanguage].profile.bio} diff --git a/app/components/AgentStats.tsx b/app/components/AgentStats.tsx index d4417ec..571b6da 100644 --- a/app/components/AgentStats.tsx +++ b/app/components/AgentStats.tsx @@ -1,7 +1,7 @@ -import { AGENT_WALLET_ADDRESS, notoSansThai } from "../constants"; -import { translations } from "../translations"; -import { Language } from "../types"; -import { useBalance } from "wagmi"; +import { useBalance } from 'wagmi'; +import { AGENT_WALLET_ADDRESS, notoSansThai } from '../constants'; +import { translations } from '../translations'; +import type { Language } from '../types'; type AgentStats = { currentLanguage: Language; @@ -22,41 +22,41 @@ export default function AgentStats({ currentLanguage }: AgentStats) { query: { refetchInterval: 5000 }, }); return ( -

+
- - {`${parseFloat(data?.formatted || "").toFixed(6)} ETH`} + + {`${Number.parseFloat(data?.formatted || '').toFixed(6)} ETH`} {/* TODO: update with actual data */}
  • {translations[currentLanguage].profile.stats.earned}: $ {dummyStats.earned.toFixed(2)}
  • {translations[currentLanguage].profile.stats.spent}: $ {dummyStats.spent.toFixed(2)}
  • - {translations[currentLanguage].profile.stats.nfts}:{" "} + {translations[currentLanguage].profile.stats.nfts}:{' '} {dummyStats.nftsOwned}
  • - {translations[currentLanguage].profile.stats.tokens}:{" "} + {translations[currentLanguage].profile.stats.tokens}:{' '} {dummyStats.tokensOwned}
  • - {translations[currentLanguage].profile.stats.transactions}:{" "} + {translations[currentLanguage].profile.stats.transactions}:{' '} {dummyStats.transactions}
diff --git a/app/components/ChatInput.tsx b/app/components/ChatInput.tsx index 287e7d3..7c46c39 100644 --- a/app/components/ChatInput.tsx +++ b/app/components/ChatInput.tsx @@ -1,8 +1,8 @@ -import { ChangeEvent, useCallback } from "react"; -import { Language } from "../types"; -import { notoSansThai } from "../constants"; -import { translations } from "../translations"; -import SendSvg from "../svg/SendSvg"; +import { type ChangeEvent, useCallback } from 'react'; +import { notoSansThai } from '../constants'; +import SendSvg from '../svg/SendSvg'; +import { translations } from '../translations'; +import type { Language } from '../types'; type PremadeChatInputProps = { text: string; @@ -17,9 +17,10 @@ function PremadeChatInput({ }: PremadeChatInputProps) { return (