aboutsummaryrefslogtreecommitdiff
path: root/frontend/ts/src/main.ts
blob: e94043b1b8d648bf55057cedebba382d75f7fc8c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
import { h, Html } from 'lib/rx'
import * as rx from 'lib/rx'
import * as layout from 'ui/layout'
import * as request from 'request'
import * as login from 'pages/login'
import * as maps from 'pages/maps'
import * as notFound from 'pages/notFound'
import * as route from 'route'
import * as pagesLayout from 'pages/layout'
import * as map from 'pages/map'
import * as L from 'lib/loadable'
import { User } from 'models/user'

// Push internal route when clicking on link
document.addEventListener('click', (event: Event) => {
    if (event.target !== null) {
        const element = event.target as HTMLElement
        const href = element.getAttribute('href')
        if (href !== null) {
            const r = route.get(href)
            if (r !== undefined) {
                event.preventDefault()
                route.push(r)
            }
        }
    }
})

rx.mount(
    document.body,
    rx.withState<route.Route | undefined>(route.get(window.location.pathname), routeVar =>
        rx.withState<L.Loadable<User>>(L.init, userLoadableVar => {
            window.onpopstate = (event: Event) => {
                routeVar.update(_ => route.get(window.location.pathname))
            }

            return rx.map2([routeVar, userLoadableVar], (route, userLoadable) =>
                view({
                    route,
                    userLoadable,
                    updateUser: userLoadable => userLoadableVar.update(_ => userLoadable)
                })
            )
        })
    )
)

interface ViewParams {
    route: route.Route | undefined
    userLoadable: L.Loadable<User>
    updateUser: (userLoadable: L.Loadable<User>) => void
}

function view({ route, userLoadable, updateUser }: ViewParams): Html {
    if (route?.state == 'login') {
        return login.view({ updateUser: (user: User) => updateUser(L.loaded(user)) })
    } else {
        if (userLoadable == L.init) {
            request
                .get<User>('/api/user')
                .then(user => updateUser(L.loaded(user)))
                .catch(({ message }) => updateUser(L.failure(message)))
        }

        return layout.loadable(userLoadable, user =>
            pagesLayout.view(user, viewLoggedIn(route))
        )
    }
}

function viewLoggedIn(route?: route.Route): Html {
    if (route?.state == 'maps') {
        return maps.view()
    } else if (route?.state == 'map') {
        return map.view(route.id)
    } else {
        return notFound.view()
    }
}