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}