From de084bd89849f63b5354c5e09b4f479cbdfbebca Mon Sep 17 00:00:00 2001 From: Tiago Yamamoto Date: Thu, 11 Dec 2025 19:36:21 -0300 Subject: [PATCH] Add hello world Appwrite function and dashboard page --- README.md | 4 +- appwrite-functions/hello-world/function.json | 8 ++ .../hello-world/package-lock.json | 13 ++++ appwrite-functions/hello-world/package.json | 8 ++ appwrite-functions/hello-world/src/index.js | 13 ++++ dashboard/src/App.tsx | 12 +-- dashboard/src/layouts/DashboardLayout.tsx | 3 +- dashboard/src/pages/Hello.tsx | 78 +++++++++++++++++++ 8 files changed, 131 insertions(+), 8 deletions(-) create mode 100644 appwrite-functions/hello-world/function.json create mode 100644 appwrite-functions/hello-world/package-lock.json create mode 100644 appwrite-functions/hello-world/package.json create mode 100644 appwrite-functions/hello-world/src/index.js create mode 100644 dashboard/src/pages/Hello.tsx diff --git a/README.md b/README.md index d19d1f1..6a19f8d 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ Ambiente monorepo com três camadas principais: **Landing (Fresh + Deno)**, **Da - `apiKey` (string) - `label` (string) 6. Ative o provedor **Email/Password** em *Authentication* e crie um usuário de teste. -7. Implante as Functions `sync-github` e `check-cloudflare-status` (fontes em `appwrite-functions/`). +7. Implante as Functions `hello-world`, `sync-github` e `check-cloudflare-status` (fontes em `appwrite-functions/`). ## Variáveis de ambiente Copie o arquivo de exemplo e preencha com os IDs anotados: @@ -46,7 +46,7 @@ Campos principais: ## Estrutura de pastas - `landing/`: app Fresh (Deno) para a landing page. - `dashboard/`: painel React + Vite com integrações Appwrite (auth, Functions, Database, Realtime). -- `appwrite-functions/`: funções `sync-github` e `check-cloudflare-status`. +- `appwrite-functions/`: funções `hello-world`, `sync-github` e `check-cloudflare-status`. ## Rodando os ambientes 1) **Appwrite local (opcional)** diff --git a/appwrite-functions/hello-world/function.json b/appwrite-functions/hello-world/function.json new file mode 100644 index 0000000..8996b6f --- /dev/null +++ b/appwrite-functions/hello-world/function.json @@ -0,0 +1,8 @@ +{ + "$schema": "https://appwrite.io/docs/schemas/functions.json", + "name": "hello-world", + "entrypoint": "src/index.js", + "runtime": "node-20.0", + "commands": ["npm install"], + "ignore": ["node_modules", ".npm", "npm-debug.log", "build"] +} diff --git a/appwrite-functions/hello-world/package-lock.json b/appwrite-functions/hello-world/package-lock.json new file mode 100644 index 0000000..e6f267d --- /dev/null +++ b/appwrite-functions/hello-world/package-lock.json @@ -0,0 +1,13 @@ +{ + "name": "hello-world", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "hello-world", + "version": "1.0.0", + "license": "MIT" + } + } +} diff --git a/appwrite-functions/hello-world/package.json b/appwrite-functions/hello-world/package.json new file mode 100644 index 0000000..8c04632 --- /dev/null +++ b/appwrite-functions/hello-world/package.json @@ -0,0 +1,8 @@ +{ + "name": "hello-world", + "version": "1.0.0", + "type": "module", + "main": "src/index.js", + "license": "MIT", + "scripts": {} +} diff --git a/appwrite-functions/hello-world/src/index.js b/appwrite-functions/hello-world/src/index.js new file mode 100644 index 0000000..7942d72 --- /dev/null +++ b/appwrite-functions/hello-world/src/index.js @@ -0,0 +1,13 @@ +export default async function ({ req, res, log }) { + const payload = req.body ? JSON.parse(req.body) : {}; + const name = payload.name?.trim() || 'Appwrite'; + + const message = `Hello, ${name}! Your function is deployed and responding.`; + log(`hello-world executed for ${name}`); + + return res.json({ + message, + inputName: name, + timestamp: new Date().toISOString() + }); +} diff --git a/dashboard/src/App.tsx b/dashboard/src/App.tsx index d2ec431..678e045 100644 --- a/dashboard/src/App.tsx +++ b/dashboard/src/App.tsx @@ -2,6 +2,7 @@ import { BrowserRouter, Navigate, Route, Routes } from 'react-router-dom' import DashboardLayout from './layouts/DashboardLayout' import { PrivateRoute } from './contexts/Auth' import Cloudflare from './pages/Cloudflare' +import Hello from './pages/Hello' import Github from './pages/Github' import Home from './pages/Home' import Login from './pages/Login' @@ -14,11 +15,12 @@ function App() { } /> }> - }> - } /> - } /> - } /> - } /> + }> + } /> + } /> + } /> + } /> + } /> diff --git a/dashboard/src/layouts/DashboardLayout.tsx b/dashboard/src/layouts/DashboardLayout.tsx index 5753a10..7f7a2c4 100644 --- a/dashboard/src/layouts/DashboardLayout.tsx +++ b/dashboard/src/layouts/DashboardLayout.tsx @@ -1,10 +1,11 @@ -import { Cloud, Github, Home, LogOut, Settings, Terminal } from 'lucide-react' +import { Cloud, Github, Home, LogOut, Settings, Sparkles, Terminal } from 'lucide-react' import { NavLink, Outlet, useNavigate } from 'react-router-dom' import { TerminalLogs } from '../components/TerminalLogs' import { useAuth } from '../contexts/Auth' const navItems = [ { label: 'Overview', to: '/', icon: Home }, + { label: 'Hello World', to: '/hello', icon: Sparkles }, { label: 'GitHub Repos', to: '/github', icon: Github }, { label: 'Cloudflare Zones', to: '/cloudflare', icon: Cloud }, { label: 'Settings', to: '/settings', icon: Settings }, diff --git a/dashboard/src/pages/Hello.tsx b/dashboard/src/pages/Hello.tsx new file mode 100644 index 0000000..ef6e83d --- /dev/null +++ b/dashboard/src/pages/Hello.tsx @@ -0,0 +1,78 @@ +import { type Models } from 'appwrite' +import { useState } from 'react' +import { functions } from '../lib/appwrite' + +export default function Hello() { + const [name, setName] = useState('') + const [execution, setExecution] = useState(null) + const [message, setMessage] = useState(null) + const [error, setError] = useState(null) + const [loading, setLoading] = useState(false) + + const handleExecute = async () => { + setLoading(true) + setError(null) + setMessage(null) + + try { + const executionResult = await functions.createExecution( + 'hello-world', + name.trim() ? JSON.stringify({ name }) : undefined, + ) + + setExecution(executionResult) + + const payload = executionResult.responseBody ? JSON.parse(executionResult.responseBody) : {} + setMessage(payload.message || 'Função executada com sucesso.') + } catch (err) { + console.error(err) + setError('Não foi possível executar a função hello-world.') + } finally { + setLoading(false) + } + } + + return ( +
+
+

Funções

+

Hello World

+

+ Teste rápido da função hello-world implantada no Appwrite. +

+ +
+ setName(e.target.value)} + placeholder="Nome opcional para o cumprimento" + className="w-full rounded-lg border border-slate-800 bg-slate-950 px-3 py-2 text-sm text-slate-100 outline-none focus:border-cyan-400" + /> + +
+ + {error ?

{error}

: null} + {execution ? ( +

Execução #{execution.$id} • Status: {execution.status}

+ ) : null} +
+ +
+

Resultado

+ {message ? ( +

{message}

+ ) : ( +

Aguardando execução.

+ )} +
+
+ ) +}