Summary.res
1let getLongestDistance = (wp: Waypoint.attributes): float => {
2 let maxDistance = switch wp.from {
3 | Some(d) =>
4 d
5 ->Dict.toArray
6 ->Array.reduce(0.0, (a, (_, route)) => {
7 let dist = route.d->Option.getOr(0.0)
8 dist > a ? dist : a
9 })
10 | None => 0.0
11 }
12 maxDistance
13}
14let getLongestTime = (wp: Waypoint.attributes): float => {
15 let maxTime = switch wp.from {
16 | Some(d) =>
17 d
18 ->Dict.toArray
19 ->Array.reduce(0.0, (a, (_, route)) => {
20 let time = route.t->Option.getOr(0.0)
21 time > a ? time : a
22 })
23 | None => 0.0
24 }
25 maxTime
26}
27
28module StatusText = {
29 @jsx.component
30 let make = (~id: string, ~status: string) => {
31 <div
32 id={id}
33 ref={PreactDOM.Ref.callbackDomRef(elem => {
34 let _ =
35 elem->Nullable.toOption->Option.map(elem => elem->Preact.ClassList.remove("md:opacity-0"))
36 let _ = Window.setTimeout(() => {
37 let _ =
38 elem
39 ->Nullable.toOption
40 ->Option.map(elem => elem->Preact.ClassList.add("md:opacity-0"))
41 }, 5000)
42 None
43 })}
44 className="hidden md:block md:transition-opacity md:ease-in-out md:duration-1000"
45 >
46 {status->Preact.string}
47 </div>
48 }
49}
50
51@jsx.component
52let make = (~doc: string) => {
53 let distance = switch State.waypoints->Map.get(doc) {
54 | Some(wp) =>
55 wp->Preact.Signal.get->Array.reduce(0.0, (total, wp) => total + getLongestDistance(wp))
56 | None => 0.0
57 }
58 let time = switch State.waypoints->Map.get(doc) {
59 | Some(wp) => wp->Preact.Signal.get->Array.reduce(0.0, (total, wp) => total + getLongestTime(wp))
60 | None => 0.0
61 }
62 let numPoints = switch State.waypoints->Map.get(doc) {
63 | Some(wp) => wp->Preact.Signal.get->Array.length
64 | None => 0
65 }
66 let status = State.ysweetStatus->Preact.Signal.get
67 <div
68 id={`summary-${doc}`}
69 className={Preact.cls(
70 "fixed box-border bottom-0 left-0 w-[100cqw] rounded-sm shadow-xl",
71 dict{"border-t-2 border-gray-300": !(Panel.isMinimized->Preact.Signal.get)},
72 )}
73 >
74 <div className="flex flex-row justify-between">
75 <div
76 className="flex flex-row gap-4 md:gap-8 text-xs items-center justify-start bg-paper px-4 py-2"
77 >
78 <div className="flex flex-row gap-2">
79 <div className="capitalize"> {"WAYPOINTS"->Preact.string} </div>
80 <div className="font-extrabold"> {numPoints->Int.toFixed->Preact.string} </div>
81 </div>
82 <div className="flex flex-row gap-2">
83 <div className="capitalize"> {"DISTANCE"->Preact.string} </div>
84 <div className="font-extrabold"> {distance->Units.distance(#km)->Preact.string} </div>
85 </div>
86 <div className="flex flex-row gap-2">
87 <div className="capitalize"> {"TIME"->Preact.string} </div>
88 <div className="font-extrabold"> {time->Time.humanize->Preact.string} </div>
89 </div>
90 </div>
91 {State.readonly->Preact.Signal.get
92 ? <div className="">
93 <Menu.Root>
94 <Menu.Trigger className="flex flex-row gap-1 rounded-full bg-orange">
95 <Icons.Split className="my-auto" />
96 {"Edit"->Preact.string}
97 </Menu.Trigger>
98 <Menu.Portal>
99 <Menu.Positioner align={#end} side={#top}>
100 <Menu.Popup className="flex flex-col gap-2 w-40">
101 <Menu.Group>
102 <Menu.GroupLabel>
103 {"This document is read-only. If you want to make changes, you can fork it to create your own editable copy."->Preact.string}
104 </Menu.GroupLabel>
105 <Menu.LinkItem href={`fork/${doc}`} className="">
106 {"Fork a copy of this document"->Preact.string}
107 </Menu.LinkItem>
108 </Menu.Group>
109 </Menu.Popup>
110 </Menu.Positioner>
111 </Menu.Portal>
112 </Menu.Root>
113 </div>
114 : Preact.null}
115 <div className="px-4 py-2">
116 <div className="flex flex-row items-center justify-center gap-1 text-xs">
117 {switch status {
118 | Offline => <StatusText id="status-offline" status="Offline" />
119 | Connecting => <StatusText id="status-connecting" status="Connecting" />
120 | Synced => <StatusText id="status-synced" status="Saved" />
121 | Saving => <StatusText id="status-saving" status="Saving" />
122 }}
123 <div
124 className={Preact.cls(
125 "m-auto",
126 dict{
127 "text-yellow": status == State.Connecting || status == State.Saving,
128 "text-green": status == State.Synced,
129 "text-red": status == State.Offline,
130 },
131 )}
132 >
133 {switch status {
134 | Offline => <Icons.GlobeOff strokeWidth=3 size=14 />
135 | Connecting => <Icons.WifiSync strokeWidth=3 size=14 />
136 | Synced => <Icons.Check strokeWidth=4 size=14 />
137 | Saving => <Icons.CloudUpload strokeWidth=3 size=14 />
138 }}
139 </div>
140 </div>
141 </div>
142 </div>
143 </div>
144}