0.1.13 #18
@@ -1,6 +1,5 @@
|
|||||||
import { ThSchema } from "@thilawyn/thilaschema"
|
import { ThSchema } from "@thilawyn/thilaschema"
|
||||||
import { GetRandomValues, makeUuid4 } from "@typed/id"
|
import { Schema } from "effect"
|
||||||
import { Effect, Schema } from "effect"
|
|
||||||
|
|
||||||
|
|
||||||
export class Todo extends Schema.Class<Todo>("Todo")({
|
export class Todo extends Schema.Class<Todo>("Todo")({
|
||||||
@@ -18,9 +17,4 @@ export const TodoFromJsonStruct = Schema.Struct({
|
|||||||
ThSchema.assertEncodedJsonifiable
|
ThSchema.assertEncodedJsonifiable
|
||||||
)
|
)
|
||||||
|
|
||||||
export const TodoFromJson = TodoFromJsonStruct.pipe(Schema.compose(Todo))
|
export const TodoFromJson = Schema.compose(TodoFromJsonStruct, Todo)
|
||||||
|
|
||||||
|
|
||||||
export const generateUniqueID = makeUuid4.pipe(
|
|
||||||
Effect.provide(GetRandomValues.CryptoRandom)
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
import { Todo } from "@/domain"
|
import { Todo } from "@/domain"
|
||||||
import { Box, Button, Card, Flex, TextArea } from "@radix-ui/themes"
|
import { Box, Button, Card, Flex, TextArea } from "@radix-ui/themes"
|
||||||
|
import { GetRandomValues, makeUuid4 } from "@typed/id"
|
||||||
import { Effect, Option, Ref } from "effect"
|
import { Effect, Option, Ref } from "effect"
|
||||||
import { R } from "../reffuse"
|
import { R } from "../reffuse"
|
||||||
import { TodosState } from "../services"
|
import { TodosState } from "../services"
|
||||||
|
|
||||||
|
|
||||||
const createEmptyTodo = Effect.map(Todo.generateUniqueID, id => Todo.Todo.make({
|
const createEmptyTodo = makeUuid4.pipe(
|
||||||
id,
|
Effect.map(id => Todo.Todo.make({ id, content: "", completedAt: Option.none()}, true)),
|
||||||
content: "",
|
Effect.provide(GetRandomValues.CryptoRandom),
|
||||||
completedAt: Option.none(),
|
)
|
||||||
}, true))
|
|
||||||
|
|
||||||
|
|
||||||
export function VNewTodo() {
|
export function VNewTodo() {
|
||||||
|
|
||||||
const todoRef = R.useRef(() => createEmptyTodo)
|
const todoRef = R.useRef(() => createEmptyTodo)
|
||||||
const [content, setContent] = R.useRefState(R.useSubRef(todoRef, ["content"]))
|
const [content, setContent] = R.useRefState(R.useSubRefFromPath(todoRef, ["content"]))
|
||||||
|
|
||||||
const add = R.useCallbackSync(() => Effect.all([TodosState.TodosState, todoRef]).pipe(
|
const add = R.useCallbackSync(() => Effect.all([TodosState.TodosState, todoRef]).pipe(
|
||||||
Effect.flatMap(([state, todo]) => state.prepend(todo)),
|
Effect.flatMap(([state, todo]) => state.prepend(todo)),
|
||||||
|
|||||||
@@ -1,20 +1,20 @@
|
|||||||
import { Todo } from "@/domain"
|
import { Todo } from "@/domain"
|
||||||
import { Box, Card, Flex, IconButton, TextArea } from "@radix-ui/themes"
|
import { Box, Card, Flex, IconButton, TextArea } from "@radix-ui/themes"
|
||||||
import { Effect } from "effect"
|
import { Effect, Ref, SubscriptionRef } from "effect"
|
||||||
import { Delete } from "lucide-react"
|
import { Delete } from "lucide-react"
|
||||||
import { useState } from "react"
|
import { useState } from "react"
|
||||||
import { R } from "../reffuse"
|
import { R } from "../reffuse"
|
||||||
import { TodosState } from "../services"
|
|
||||||
|
|
||||||
|
|
||||||
export interface VTodoProps {
|
export interface VTodoProps {
|
||||||
readonly index: number
|
readonly todoRef: SubscriptionRef.SubscriptionRef<Todo.Todo>
|
||||||
readonly todo: Todo.Todo
|
readonly remove: Effect.Effect<void>
|
||||||
}
|
}
|
||||||
|
|
||||||
export function VTodo({ index, todo }: VTodoProps) {
|
export function VTodo({ todoRef, remove }: VTodoProps) {
|
||||||
|
|
||||||
const runSync = R.useRunSync()
|
const runSync = R.useRunSync()
|
||||||
|
const [todo] = R.useSubscribeRefs(todoRef)
|
||||||
const editorMode = useState(false)
|
const editorMode = useState(false)
|
||||||
|
|
||||||
|
|
||||||
@@ -24,12 +24,11 @@ export function VTodo({ index, todo }: VTodoProps) {
|
|||||||
<Flex direction="column" align="stretch" gap="1">
|
<Flex direction="column" align="stretch" gap="1">
|
||||||
<TextArea
|
<TextArea
|
||||||
value={todo.content}
|
value={todo.content}
|
||||||
onChange={e => TodosState.TodosState.pipe(
|
onChange={e => runSync(
|
||||||
Effect.flatMap(state => state.replace(
|
Ref.set(todoRef, Todo.Todo.make({
|
||||||
index,
|
...todo,
|
||||||
Todo.Todo.make({ ...todo, content: e.target.value }, true),
|
content: e.target.value,
|
||||||
)),
|
}, true))
|
||||||
runSync,
|
|
||||||
)}
|
)}
|
||||||
disabled={!editorMode}
|
disabled={!editorMode}
|
||||||
/>
|
/>
|
||||||
@@ -38,12 +37,7 @@ export function VTodo({ index, todo }: VTodoProps) {
|
|||||||
<Box></Box>
|
<Box></Box>
|
||||||
|
|
||||||
<Flex direction="row" align="center" gap="1">
|
<Flex direction="row" align="center" gap="1">
|
||||||
<IconButton
|
<IconButton onClick={() => runSync(remove)}>
|
||||||
onClick={() => TodosState.TodosState.pipe(
|
|
||||||
Effect.flatMap(state => state.remove(index)),
|
|
||||||
runSync,
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<Delete />
|
<Delete />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { Box, Flex } from "@radix-ui/themes"
|
import { Box, Flex } from "@radix-ui/themes"
|
||||||
import { Chunk, Effect } from "effect"
|
import { Chunk, Effect, Ref } from "effect"
|
||||||
import { R } from "../reffuse"
|
import { R } from "../reffuse"
|
||||||
import { TodosState } from "../services"
|
import { TodosState } from "../services"
|
||||||
import { VNewTodo } from "./VNewTodo"
|
import { VNewTodo } from "./VNewTodo"
|
||||||
@@ -8,7 +8,7 @@ import { VTodo } from "./VTodo"
|
|||||||
|
|
||||||
export function VTodos() {
|
export function VTodos() {
|
||||||
|
|
||||||
const todosRef = R.useMemo(() => TodosState.TodosState.pipe(Effect.map(state => state.todos)), [])
|
const todosRef = R.useMemo(() => Effect.map(TodosState.TodosState, state => state.todos), [])
|
||||||
const [todos] = R.useSubscribeRefs(todosRef)
|
const [todos] = R.useSubscribeRefs(todosRef)
|
||||||
|
|
||||||
|
|
||||||
@@ -20,7 +20,16 @@ export function VTodos() {
|
|||||||
|
|
||||||
{Chunk.map(todos, (todo, index) => (
|
{Chunk.map(todos, (todo, index) => (
|
||||||
<Box key={todo.id} width="500px">
|
<Box key={todo.id} width="500px">
|
||||||
<VTodo index={index} todo={todo} />
|
<R.SubRefFromGetSet
|
||||||
|
parent={todosRef}
|
||||||
|
getter={parentValue => Chunk.unsafeGet(parentValue, index)}
|
||||||
|
setter={(parentValue, value) => Chunk.replace(parentValue, index, value)}
|
||||||
|
>
|
||||||
|
{ref => <VTodo
|
||||||
|
todoRef={ref}
|
||||||
|
remove={Ref.update(todosRef, Chunk.remove(index))}
|
||||||
|
/>}
|
||||||
|
</R.SubRefFromGetSet>
|
||||||
</Box>
|
</Box>
|
||||||
))}
|
))}
|
||||||
</Flex>
|
</Flex>
|
||||||
|
|||||||
Reference in New Issue
Block a user