Working client
This commit is contained in:
@@ -14,6 +14,9 @@
|
||||
"@thilawyn/thilalib": "^0.1.5",
|
||||
"@trpc/client": "^10.45.2",
|
||||
"@trpc/react-query": "^10.45.2",
|
||||
"effect": "^3.4.7",
|
||||
"mobx": "^6.13.0",
|
||||
"mobx-react-lite": "^4.0.7",
|
||||
"react": "^18.3.1",
|
||||
"react-dom": "^18.3.1"
|
||||
},
|
||||
|
||||
@@ -1,15 +1,20 @@
|
||||
import { Schema as S } from "@effect/schema"
|
||||
import { JsonifiableTodo } from "@todo-tests/common/data"
|
||||
import { flow } from "effect"
|
||||
import { observable } from "mobx"
|
||||
import { Todo } from "./data"
|
||||
import { VTodos } from "./todo/VTodos"
|
||||
import { trpc } from "./trpc/trpc"
|
||||
|
||||
|
||||
const decodeTodos = S.decodeSync(
|
||||
S.mutable(
|
||||
S.Array(
|
||||
const decodeTodos = flow(
|
||||
S.decodeSync(
|
||||
S.mutable(S.Array(
|
||||
JsonifiableTodo.pipe(S.compose(Todo))
|
||||
)
|
||||
)
|
||||
))
|
||||
),
|
||||
|
||||
observable.array,
|
||||
)
|
||||
|
||||
|
||||
@@ -22,7 +27,18 @@ export function Index() {
|
||||
<div className="container mx-auto">
|
||||
<p className="text-4xl text-center">Todos</p>
|
||||
|
||||
{function() {
|
||||
switch (todosQuery.status) {
|
||||
case "success":
|
||||
return <VTodos todos={todosQuery.data} />
|
||||
|
||||
case "error":
|
||||
return <p>Failed.</p>
|
||||
|
||||
case "loading":
|
||||
return <p>Loading...</p>
|
||||
}
|
||||
}()}
|
||||
</div>
|
||||
</>
|
||||
|
||||
|
||||
19
packages/webui/src/todo/VTodo.tsx
Normal file
19
packages/webui/src/todo/VTodo.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import { observer } from "mobx-react-lite"
|
||||
import { Todo } from "../data"
|
||||
|
||||
|
||||
export interface VTodoProps {
|
||||
todo: Todo
|
||||
}
|
||||
|
||||
|
||||
export const VTodo = observer(({ todo }: VTodoProps) => {
|
||||
|
||||
return (
|
||||
<div className="flex flex-col px-6 pt-10 pb-8 bg-white ring-1 shadow-xl ring-gray-900/5 sm:mx-auto sm:max-w-lg sm:rounded-lg sm:px-10">
|
||||
<p className="text-xs">{todo.title}</p>
|
||||
<p className="text-sm">{todo.content}</p>
|
||||
</div>
|
||||
)
|
||||
|
||||
})
|
||||
29
packages/webui/src/todo/VTodos.tsx
Normal file
29
packages/webui/src/todo/VTodos.tsx
Normal file
@@ -0,0 +1,29 @@
|
||||
import { Option, identity } from "effect"
|
||||
import { IObservableArray } from "mobx"
|
||||
import { observer } from "mobx-react-lite"
|
||||
import { Todo } from "../data"
|
||||
import { VTodo } from "./VTodo"
|
||||
|
||||
|
||||
export interface VTodosProps {
|
||||
todos: IObservableArray<Todo>
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Displays a vertical list of todos
|
||||
*/
|
||||
export const VTodos = observer(({ todos }: VTodosProps) => (
|
||||
<div className="flex flex-col gap-1">
|
||||
{todos.map((todo, index) => (
|
||||
<VTodo
|
||||
key={Option.match(todo.id, {
|
||||
onSome: identity,
|
||||
onNone: () => index,
|
||||
})}
|
||||
|
||||
todo={todo}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
))
|
||||
Reference in New Issue
Block a user