import type { Nullable , Path } from "@thi.ng/api" ; import { defAtom } from "@thi.ng/atom/atom" ; import { defView } from "@thi.ng/atom/view" ; import { exposeGlobal } from "@thi.ng/expose" ; import { start } from "@thi.ng/hdom/start" ; import { capitalize } from "@thi.ng/strings/case" ; interface State { state : string ; error ? : string ; user : { name ? : string ; } ; } const db = defAtom < State > ( { state : "login" , user : { } } ) ; const appState = defView ( db , [ "state" ] ) ; const error = defView ( db , [ "error" ] , ( error ) => error ? [ "div.error" , error ] : null ) ; const user = defView ( db , [ "user" , "name" ] , ( name ) => name ? capitalize ( name ) : null ) ; const setState = ( s ) => setValue ( appState . path , s ) ; const setError = ( err ) => setValue ( error . path , err ) ; const setUser = ( e ) => setValue ( user . path , ( < any > e . target ) . value ) ; const setValue = ( path , val ) => db . resetInUnsafe ( path , val ) ; const loginUser = ( ) => { if ( user . deref ( ) === "Admin" ) { setError ( null ) ; setState ( "main" ) ; } else { setError ( "sorry, wrong username (try 'admin')" ) ; } } ; const logoutUser = ( ) => { setValue ( user . path , null ) ; setState ( "logout" ) ; } ; const uiViews = { login : ( ) => [ "div#login" , [ "h1" , "Login" ] , error . deref ( ) , [ "input" , { type : "text" , onchange : setUser } ] , [ "button" , { onclick : loginUser } , "Login" ] , ] , logout : ( ) => [ "div#logout" , [ "h1" , "Good bye" ] , "You've been logged out. " , [ "a" , { href : "#" , onclick : ( ) => setState ( "login" ) } , "Log back in?" ] , ] , main : ( ) => [ "div#main" , [ "h1" , `Welcome, ${ user . deref ( ) }!` ] , [ "div" , "Current app state:" ] , [ "div" , [ "textarea" , { cols : 40 , rows : 10 } , JSON . stringify ( db . deref ( ) , null , 2 ) , ] , ] , [ "button" , { onclick : logoutUser } , "Logout" ] , ] , } ; const currView = defView ( db , [ "state" ] , ( state ) => uiViews [ state ] || [ "div" , [ "h1" , `No component for state: ${ state }` ] ] ) ; start ( ( ) => [ "div" , currView ] ) ; exposeGlobal ( "db" , db ) ;