Working client
This commit is contained in:
@@ -14,6 +14,9 @@
|
|||||||
"@thilawyn/thilalib": "^0.1.5",
|
"@thilawyn/thilalib": "^0.1.5",
|
||||||
"@trpc/client": "^10.45.2",
|
"@trpc/client": "^10.45.2",
|
||||||
"@trpc/react-query": "^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": "^18.3.1",
|
||||||
"react-dom": "^18.3.1"
|
"react-dom": "^18.3.1"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,15 +1,20 @@
|
|||||||
import { Schema as S } from "@effect/schema"
|
import { Schema as S } from "@effect/schema"
|
||||||
import { JsonifiableTodo } from "@todo-tests/common/data"
|
import { JsonifiableTodo } from "@todo-tests/common/data"
|
||||||
|
import { flow } from "effect"
|
||||||
|
import { observable } from "mobx"
|
||||||
import { Todo } from "./data"
|
import { Todo } from "./data"
|
||||||
|
import { VTodos } from "./todo/VTodos"
|
||||||
import { trpc } from "./trpc/trpc"
|
import { trpc } from "./trpc/trpc"
|
||||||
|
|
||||||
|
|
||||||
const decodeTodos = S.decodeSync(
|
const decodeTodos = flow(
|
||||||
S.mutable(
|
S.decodeSync(
|
||||||
S.Array(
|
S.mutable(S.Array(
|
||||||
JsonifiableTodo.pipe(S.compose(Todo))
|
JsonifiableTodo.pipe(S.compose(Todo))
|
||||||
)
|
))
|
||||||
)
|
),
|
||||||
|
|
||||||
|
observable.array,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -22,7 +27,18 @@ export function Index() {
|
|||||||
<div className="container mx-auto">
|
<div className="container mx-auto">
|
||||||
<p className="text-4xl text-center">Todos</p>
|
<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>
|
</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