From cb19925011d889c513e1bbedc446e399597e38a0 Mon Sep 17 00:00:00 2001
From: Ellie Huxtable <ellie@elliehuxtable.com>
Date: Wed, 17 Apr 2024 14:06:05 +0100
Subject: feat(gui): work on home page, sort state (#1956)

1. Start on a home page, can sort onboarding/etc from there
2. Introduce zustand for state management. It's nice!

Did a production build and clicked around for a while. Memory usage
seems nice and chill.
---
 ui/src/components/HistoryList.tsx | 131 +++++++++++++++++++++-----------------
 1 file changed, 72 insertions(+), 59 deletions(-)

(limited to 'ui/src/components/HistoryList.tsx')

diff --git a/ui/src/components/HistoryList.tsx b/ui/src/components/HistoryList.tsx
index b31a4be4..9616ecf0 100644
--- a/ui/src/components/HistoryList.tsx
+++ b/ui/src/components/HistoryList.tsx
@@ -1,75 +1,88 @@
-import { DateTime } from 'luxon';
-import { ChevronRightIcon } from '@heroicons/react/20/solid'
+import { ChevronRightIcon } from "@heroicons/react/20/solid";
 
-function msToTime(ms) {
-  let milliseconds = (ms).toFixed(1);
-  let seconds = (ms / 1000).toFixed(1);
-  let minutes = (ms / (1000 * 60)).toFixed(1);
-  let hours = (ms / (1000 * 60 * 60)).toFixed(1);
-  let days = (ms / (1000 * 60 * 60 * 24)).toFixed(1);
+// @ts-ignore
+import { DateTime } from "luxon";
+
+function msToTime(ms: number) {
+  let milliseconds = parseInt(ms.toFixed(1));
+  let seconds = parseInt((ms / 1000).toFixed(1));
+  let minutes = parseInt((ms / (1000 * 60)).toFixed(1));
+  let hours = parseInt((ms / (1000 * 60 * 60)).toFixed(1));
+  let days = parseInt((ms / (1000 * 60 * 60 * 24)).toFixed(1));
 
   if (milliseconds < 1000) return milliseconds + "ms";
   else if (seconds < 60) return seconds + "s";
   else if (minutes < 60) return minutes + "m";
   else if (hours < 24) return hours + "hr";
-  else return days + " Days"
+  else return days + " Days";
 }
 
-export default function HistoryList(props){
+export default function HistoryList(props: any) {
   return (
+    <ul
+      role="list"
+      className="divide-y divide-gray-100 overflow-hidden bg-white shadow-sm ring-1 ring-gray-900/5"
+    >
+      {props.history.map((h: any) => (
+        <li
+          key={h.id}
+          className="relative flex justify-between gap-x-6 px-4 py-5 hover:bg-gray-50 sm:px-6"
+        >
+          <div className="flex min-w-0 gap-x-4">
+            <div className="flex flex-col justify-center">
+              <p className="flex text-xs text-gray-500 justify-center">
+                {DateTime.fromMillis(h.timestamp / 1000000).toLocaleString(
+                  DateTime.TIME_WITH_SECONDS,
+                )}
+              </p>
+              <p className="flex text-xs mt-1 text-gray-400 justify-center">
+                {DateTime.fromMillis(h.timestamp / 1000000).toLocaleString(
+                  DateTime.DATE_SHORT,
+                )}
+              </p>
+            </div>
+            <div className="min-w-0 flex-col justify-center">
+              <pre className="whitespace-pre-wrap">
+                <code className="text-sm">{h.command}</code>
+              </pre>
+              <p className="mt-1 flex text-xs leading-5 text-gray-500">
+                <span className="relative truncate ">{h.user}</span>
 
-            <ul
-              role="list"
-              className="divide-y divide-gray-100 overflow-hidden bg-white shadow-sm ring-1 ring-gray-900/5"
-            >
-              {props.history.map((h) => (
-                <li key={h.id} className="relative flex justify-between gap-x-6 px-4 py-5 hover:bg-gray-50 sm:px-6">
-                  <div className="flex min-w-0 gap-x-4">
-                    <div className="flex flex-col justify-center">
-                      <p className="flex text-xs text-gray-500 justify-center">{ DateTime.fromMillis(h.timestamp / 1000000).toLocaleString(DateTime.TIME_WITH_SECONDS)}</p>
-                      <p className="flex text-xs mt-1 text-gray-400 justify-center">{ DateTime.fromMillis(h.timestamp / 1000000).toLocaleString(DateTime.DATE_SHORT)}</p>
-                    </div>
-                    <div className="min-w-0 flex-col justify-center">
-                      <pre className="whitespace-pre-wrap"><code className="text-sm">{h.command}</code></pre>
-                      <p className="mt-1 flex text-xs leading-5 text-gray-500">
-                        <span className="relative truncate ">
-                          {h.user}
-                        </span>
-
-                        <span>&nbsp;on&nbsp;</span>
+                <span>&nbsp;on&nbsp;</span>
 
-                        <span className="relative truncate ">
-                          {h.host}
-                        </span>
+                <span className="relative truncate ">{h.host}</span>
 
-                        <span>&nbsp;in&nbsp;</span>
+                <span>&nbsp;in&nbsp;</span>
 
-                        <span className="relative truncate ">
-                          {h.cwd}
-                        </span>
-                      </p>
-                    </div>
-                  </div>
-                  <div className="flex shrink-0 items-center gap-x-4">
-                    <div className="hidden sm:flex sm:flex-col sm:items-end">
-                      <p className="text-sm leading-6 text-gray-900">{h.exit}</p>
-                      {h.duration ? (
-                        <p className="mt-1 text-xs leading-5 text-gray-500">
-                          <time dateTime={h.duration}>{msToTime(h.duration / 1000000)}</time>
-                        </p>
-                      ) : (
-                        <div className="mt-1 flex items-center gap-x-1.5">
-                          <div className="flex-none rounded-full bg-emerald-500/20 p-1">
-                            <div className="h-1.5 w-1.5 rounded-full bg-emerald-500" />
-                          </div>
-                          <p className="text-xs leading-5 text-gray-500">Online</p>
-                        </div>
-                      )}
-                    </div>
-                    <ChevronRightIcon className="h-5 w-5 flex-none text-gray-400" aria-hidden="true" />
+                <span className="relative truncate ">{h.cwd}</span>
+              </p>
+            </div>
+          </div>
+          <div className="flex shrink-0 items-center gap-x-4">
+            <div className="hidden sm:flex sm:flex-col sm:items-end">
+              <p className="text-sm leading-6 text-gray-900">{h.exit}</p>
+              {h.duration ? (
+                <p className="mt-1 text-xs leading-5 text-gray-500">
+                  <time dateTime={h.duration}>
+                    {msToTime(h.duration / 1000000)}
+                  </time>
+                </p>
+              ) : (
+                <div className="mt-1 flex items-center gap-x-1.5">
+                  <div className="flex-none rounded-full bg-emerald-500/20 p-1">
+                    <div className="h-1.5 w-1.5 rounded-full bg-emerald-500" />
                   </div>
-                </li>
-              ))}
-            </ul>
+                  <p className="text-xs leading-5 text-gray-500">Online</p>
+                </div>
+              )}
+            </div>
+            <ChevronRightIcon
+              className="h-5 w-5 flex-none text-gray-400"
+              aria-hidden="true"
+            />
+          </div>
+        </li>
+      ))}
+    </ul>
   );
 }
-- 
cgit v1.3.1

