Current section

Files

Jump to
sprocket src docs components clock.gleam
Raw

src/docs/components/clock.gleam

import gleam/io
import gleam/erlang
import gleam/int
import gleam/option.{None, Option, Some}
import sprocket/socket.{Socket}
import sprocket/component.{render}
import sprocket/hooks.{WithDeps, dep}
import sprocket/hooks/reducer.{State, reducer}
import sprocket/hooks/effect.{effect}
import sprocket/html.{span, text}
import docs/utils/timer.{interval}
type Model {
Model(time: Int, timezone: String)
}
type Msg {
UpdateTime(Int)
}
fn update(model: Model, msg: Msg) -> Model {
case msg {
UpdateTime(time) -> {
Model(..model, time: time)
}
}
}
fn initial() -> Model {
Model(time: erlang.system_time(erlang.Second), timezone: "UTC")
}
pub type ClockProps {
ClockProps(label: Option(String))
}
pub fn clock(socket: Socket, props) {
let ClockProps(label) = props
// Define a reducer to handle events and update the state
use socket, State(Model(time: time, ..), dispatch) <- reducer(
socket,
initial(),
update,
)
// Example effect with an empty list of dependencies, runs once on mount
use socket <- effect(
socket,
fn() {
io.println("Clock component mounted!")
None
},
WithDeps([]),
)
// Example effect that runs whenever the `time` variable changes and has a cleanup function
use socket <- effect(
socket,
fn() {
let cancel =
interval(
1000,
fn() { dispatch(UpdateTime(erlang.system_time(erlang.Second))) },
)
Some(fn() { cancel() })
},
WithDeps([dep(time)]),
)
let current_time = int.to_string(time)
render(
socket,
case label {
Some(label) -> [span([], [text(label)]), span([], [text(current_time)])]
None -> [text(current_time)]
},
)
}