From 3eafb413a48cde60dea8a7355ee621c6acca952f Mon Sep 17 00:00:00 2001
From: Doog <157747121+doogongithub@users.noreply.github.com>
Date: Wed, 21 Feb 2024 22:07:27 -0500
Subject: first commit

---
 fe/src/lib/Table.svelte | 41 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)
 create mode 100644 fe/src/lib/Table.svelte

(limited to 'fe/src/lib/Table.svelte')

diff --git a/fe/src/lib/Table.svelte b/fe/src/lib/Table.svelte
new file mode 100644
index 0000000..2df9f8c
--- /dev/null
+++ b/fe/src/lib/Table.svelte
@@ -0,0 +1,41 @@
+<script lang="ts">
+    export let data;
+    export let nofooter: boolean = false;
+    export let noheader: boolean = false;
+    export let title: string;
+</script>
+<table>
+    {#if title}
+    <h2>{title}</h2>
+    {/if}
+    {#if !noheader}
+    <thead>
+        <tr>
+            <th>
+                Data Header
+            </th>
+        </tr>
+    </thead>
+    {/if}
+    <tbody>
+        <tr>
+            <td>Data</td>
+        </tr>
+    </tbody>
+    {#if !nofooter}
+    <slot name="footer">
+       <tfoot>
+        <tr>
+            <td>Table Footer</td>
+        </tr>
+       </tfoot>
+    </slot>
+    {/if}
+</table>
+<style>
+table {
+    padding: 16px;
+    margin: 8px;
+    border: solid 1px black;
+}
+</style>
-- 
cgit v1.1


From e37c73e33a4aaf7fb8d25b5af03627f20bcda19f Mon Sep 17 00:00:00 2001
From: Doog <157747121+doogongithub@users.noreply.github.com>
Date: Sat, 24 Feb 2024 20:08:35 -0500
Subject: add gitignore

---
 fe/src/lib/Table.svelte | 61 ++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 53 insertions(+), 8 deletions(-)

(limited to 'fe/src/lib/Table.svelte')

diff --git a/fe/src/lib/Table.svelte b/fe/src/lib/Table.svelte
index 2df9f8c..5572280 100644
--- a/fe/src/lib/Table.svelte
+++ b/fe/src/lib/Table.svelte
@@ -1,8 +1,38 @@
 <script lang="ts">
-    export let data;
-    export let nofooter: boolean = false;
-    export let noheader: boolean = false;
-    export let title: string;
+import {afterUpdate} from 'svelte';
+export let data: Array<any> | undefined = undefined;
+export let nofooter: boolean = false;
+export let noheader: boolean = false;
+export let omit: string[] = ['id'];
+export let title: string | undefined = undefined;
+
+function getDataKeys(data: any[]): string[] {
+    if (!data || data.length === 0) return [];
+    return Object.keys(data[0]).map(k => k.split('_').join(' ')).filter(k => !omit.includes(k));
+}
+
+function getRow(row: Record<string, any>): Array<any> {
+   return Object.entries(row).filter(r => !omit.includes(r[0]));
+}
+
+const formatter = new Intl.DateTimeFormat('en', {
+    year: 'numeric',
+    month: 'numeric',
+    day: 'numeric',
+    hour: 'numeric',
+    minute: '2-digit',
+    second: '2-digit',
+    timeZone: "America/New_York"
+});
+
+function formatDatum([key, value]: any[]) {
+    if (key === 'date') {
+        const parsedDate = new Date(value);
+        return formatter.format(parsedDate);
+    }
+    return value;
+}
+
 </script>
 <table>
     {#if title}
@@ -11,16 +41,27 @@
     {#if !noheader}
     <thead>
         <tr>
-            <th>
-                Data Header
-            </th>
+            {#each getDataKeys(data) as header}
+                <th>{header}</th>
+            {/each}
         </tr>
     </thead>
     {/if}
     <tbody>
+        {#if data}
+        {#each data as row}
         <tr>
-            <td>Data</td>
+            {#each getRow(row) as datum}
+            
+            <td>{formatDatum(datum)}</td>
+            {/each}
         </tr>
+        {/each}
+        {:else}
+        <tr>
+            There is not data.
+        </tr>   
+        {/if}
     </tbody>
     {#if !nofooter}
     <slot name="footer">
@@ -38,4 +79,8 @@ table {
     margin: 8px;
     border: solid 1px black;
 }
+
+th {
+    text-transform: capitalize;
+}
 </style>
-- 
cgit v1.1


From 9f9a33cbf55d38987a66b709284d2bb4ffea0fe9 Mon Sep 17 00:00:00 2001
From: Doog <157747121+doogongithub@users.noreply.github.com>
Date: Thu, 29 Feb 2024 20:13:48 -0500
Subject: modify api, build additional FE components, add types

---
 fe/src/lib/Table.svelte | 19 +++++++++++++++++++
 1 file changed, 19 insertions(+)

(limited to 'fe/src/lib/Table.svelte')

diff --git a/fe/src/lib/Table.svelte b/fe/src/lib/Table.svelte
index 5572280..4b81800 100644
--- a/fe/src/lib/Table.svelte
+++ b/fe/src/lib/Table.svelte
@@ -30,6 +30,11 @@ function formatDatum([key, value]: any[]) {
         const parsedDate = new Date(value);
         return formatter.format(parsedDate);
     }
+
+    if (key === 'user') {
+        return value['name'];
+    }
+
     return value;
 }
 
@@ -78,9 +83,23 @@ table {
     padding: 16px;
     margin: 8px;
     border: solid 1px black;
+    border-collapse: collapse;
 }
 
 th {
     text-transform: capitalize;
 }
+
+thead tr {
+    background: rgba(0,0,23, 0.34);
+}
+
+tbody tr:nth-child(odd) {
+   background: rgba(0,0,23,0.14); 
+}
+
+th, td {
+    padding: 1em;
+    border: 1px solid rgba(0,0,0, 1);
+}
 </style>
-- 
cgit v1.1


From afeffe31bd7d0f8333627a972e1d32e64a325b5b Mon Sep 17 00:00:00 2001
From: Zach Berwaldt <zberwaldt@tutamail.com>
Date: Fri, 1 Mar 2024 18:17:42 -0500
Subject: reformat fe

---
 fe/src/lib/Table.svelte | 138 ++++++++++++++++++++++++------------------------
 1 file changed, 69 insertions(+), 69 deletions(-)

(limited to 'fe/src/lib/Table.svelte')

diff --git a/fe/src/lib/Table.svelte b/fe/src/lib/Table.svelte
index 4b81800..3a66e0d 100644
--- a/fe/src/lib/Table.svelte
+++ b/fe/src/lib/Table.svelte
@@ -1,105 +1,105 @@
 <script lang="ts">
-import {afterUpdate} from 'svelte';
-export let data: Array<any> | undefined = undefined;
-export let nofooter: boolean = false;
-export let noheader: boolean = false;
-export let omit: string[] = ['id'];
-export let title: string | undefined = undefined;
+  export let data: Array<any> | undefined = undefined;
+  export let nofooter: boolean = false;
+  export let noheader: boolean = false;
+  export let omit: string[] = ["id"];
+  export let title: string | undefined = undefined;
 
-function getDataKeys(data: any[]): string[] {
+  function getDataKeys(data: any[]): string[] {
     if (!data || data.length === 0) return [];
-    return Object.keys(data[0]).map(k => k.split('_').join(' ')).filter(k => !omit.includes(k));
-}
+    return Object.keys(data[0])
+      .map((k) => k.split("_").join(" "))
+      .filter((k) => !omit.includes(k));
+  }
 
-function getRow(row: Record<string, any>): Array<any> {
-   return Object.entries(row).filter(r => !omit.includes(r[0]));
-}
+  function getRow(row: Record<string, any>): Array<any> {
+    return Object.entries(row).filter((r) => !omit.includes(r[0]));
+  }
 
-const formatter = new Intl.DateTimeFormat('en', {
-    year: 'numeric',
-    month: 'numeric',
-    day: 'numeric',
-    hour: 'numeric',
-    minute: '2-digit',
-    second: '2-digit',
-    timeZone: "America/New_York"
-});
+  const formatter = new Intl.DateTimeFormat("en", {
+    year: "numeric",
+    month: "numeric",
+    day: "numeric",
+    hour: "numeric",
+    minute: "2-digit",
+    second: "2-digit",
+    timeZone: "America/New_York",
+  });
 
-function formatDatum([key, value]: any[]) {
-    if (key === 'date') {
-        const parsedDate = new Date(value);
-        return formatter.format(parsedDate);
+  function formatDatum([key, value]: any[]) {
+    if (key === "date") {
+      const parsedDate = new Date(value);
+      return formatter.format(parsedDate);
     }
 
-    if (key === 'user') {
-        return value['name'];
+    if (key === "user") {
+      return value["name"];
     }
 
     return value;
-}
-
+  }
 </script>
+
 <table>
-    {#if title}
+  {#if title}
     <h2>{title}</h2>
-    {/if}
-    {#if !noheader}
+  {/if}
+  {#if !noheader && data}
     <thead>
-        <tr>
-            {#each getDataKeys(data) as header}
-                <th>{header}</th>
-            {/each}
-        </tr>
+      <tr>
+        {#each getDataKeys(data) as header}
+          <th>{header}</th>
+        {/each}
+      </tr>
     </thead>
-    {/if}
-    <tbody>
-        {#if data}
-        {#each data as row}
+  {/if}
+  <tbody>
+    {#if data}
+      {#each data as row}
         <tr>
-            {#each getRow(row) as datum}
-            
+          {#each getRow(row) as datum}
             <td>{formatDatum(datum)}</td>
-            {/each}
+          {/each}
         </tr>
-        {/each}
-        {:else}
-        <tr>
-            There is not data.
-        </tr>   
-        {/if}
-    </tbody>
-    {#if !nofooter}
+      {/each}
+    {:else}
+      <tr> There is not data. </tr>
+    {/if}
+  </tbody>
+  {#if !nofooter}
     <slot name="footer">
-       <tfoot>
+      <tfoot>
         <tr>
-            <td>Table Footer</td>
+          <td>Table Footer</td>
         </tr>
-       </tfoot>
+      </tfoot>
     </slot>
-    {/if}
+  {/if}
 </table>
+
 <style>
-table {
+  table {
     padding: 16px;
     margin: 8px;
     border: solid 1px black;
     border-collapse: collapse;
-}
+  }
 
-th {
+  th {
     text-transform: capitalize;
-}
+  }
 
-thead tr {
-    background: rgba(0,0,23, 0.34);
-}
+  thead tr {
+    background: rgba(0, 0, 23, 0.34);
+  }
 
-tbody tr:nth-child(odd) {
-   background: rgba(0,0,23,0.14); 
-}
+  tbody tr:nth-child(odd) {
+    background: rgba(0, 0, 23, 0.14);
+  }
 
-th, td {
+  th,
+  td {
     padding: 1em;
-    border: 1px solid rgba(0,0,0, 1);
-}
+    border: 1px solid rgba(0, 0, 0, 1);
+  }
 </style>
-- 
cgit v1.1


From cf2113e77edabf8e3a632c7b76c769752039ba88 Mon Sep 17 00:00:00 2001
From: Zach Berwaldt <zberwaldt@tutamail.com>
Date: Sat, 2 Mar 2024 16:52:55 -0500
Subject: feat: Add API logging

Add logging to the API to keep track of specific requests and headers. Also added CORS middleware to handle OPTIONS requests.

---

The commit adds logging functionality to the API and includes a middleware function to handle CORS OPTIONS requests. This will allow us to track specific requests and headers received by the API.

[API/main.go](/api/main.go):
- Added import for the 'log' package
- Added logging statements to print the request headers and "_I am here_" message
- Removed unnecessary newlines and comments

[fe/src/app.css](/fe/src/app.css):
- Added a new style for button hover effects

[fe/src/lib/Card.svelte](/fe/src/lib/Card.svelte):
- Added a new `height` prop to the Card component

[fe/src/lib/Column.svelte](/fe/src/lib/Column.svelte):
- Added a new CSS class for column layout
- Set the width and gap using CSS variables

[fe/src/lib/DataView.svelte](/fe/src/lib/DataView.svelte):
- Updated the 'fetchData' function to also fetch 'totals' and 'userStats' data
- Added canvas references and chart variables for bar and line charts
- Added a new 'getLastSevenDays' function to calculate the labels for the charts
- Updated the 'onMount' function to initialize the bar and line charts using the canvas references and data
- Updated the 'onDestroy' function to destroy the bar and line charts
- Added a new 'addFormOpen' store and imported it
- Added a new 'onClick' handler for the Add button to open the AddForm modal
- Updated the layout and added Card components to display the bar and line charts and the JSON data
- Added a new 'fetchTotals' function to fetch data for the 'totals' section
- Added a new 'fetchStatsForUser' function to fetch data for the 'userStats' section

[fe/src/lib/Layout.svelte](/fe/src/lib/Layout.svelte):
- Added a new 'preferenceFormOpen' variable and initialized it to 'false'
- Added a new 'showPreferencesDialog' function to set 'preferenceFormOpen' to 'true'
- Added a new 'closePreferenceDialog' function to set 'preferenceFormOpen' to 'false'
- Added a new 'showAddDialog' function to open the AddForm modal
---
 fe/src/lib/Table.svelte | 172 +++++++++++++++++++++++++-----------------------
 1 file changed, 90 insertions(+), 82 deletions(-)

(limited to 'fe/src/lib/Table.svelte')

diff --git a/fe/src/lib/Table.svelte b/fe/src/lib/Table.svelte
index 3a66e0d..d1cd7da 100644
--- a/fe/src/lib/Table.svelte
+++ b/fe/src/lib/Table.svelte
@@ -1,105 +1,113 @@
 <script lang="ts">
-  export let data: Array<any> | undefined = undefined;
-  export let nofooter: boolean = false;
-  export let noheader: boolean = false;
-  export let omit: string[] = ["id"];
-  export let title: string | undefined = undefined;
+    export let data: Array<any> | undefined = undefined;
+    export let nofooter: boolean = false;
+    export let noheader: boolean = false;
+    export let omit: string[] = ["id"];
+    export let title: string | undefined = undefined;
 
-  function getDataKeys(data: any[]): string[] {
-    if (!data || data.length === 0) return [];
-    return Object.keys(data[0])
-      .map((k) => k.split("_").join(" "))
-      .filter((k) => !omit.includes(k));
-  }
+    function getDataKeys(data: any[]): string[] {
+        if (!data || data.length === 0) return [];
+        return Object.keys(data[0])
+            .map((k) => k.split("_").join(" "))
+            .filter((k) => !omit.includes(k));
+    }
 
-  function getRow(row: Record<string, any>): Array<any> {
-    return Object.entries(row).filter((r) => !omit.includes(r[0]));
-  }
+    function getRow(row: Record<string, any>): Array<any> {
+        return Object.entries(row).filter((r) => !omit.includes(r[0]));
+    }
 
-  const formatter = new Intl.DateTimeFormat("en", {
-    year: "numeric",
-    month: "numeric",
-    day: "numeric",
-    hour: "numeric",
-    minute: "2-digit",
-    second: "2-digit",
-    timeZone: "America/New_York",
-  });
 
-  function formatDatum([key, value]: any[]) {
-    if (key === "date") {
-      const parsedDate = new Date(value);
-      return formatter.format(parsedDate);
-    }
+    let limitedData: Array<any> = [];
 
-    if (key === "user") {
-      return value["name"];
+    if (data && (data as any[]).length > 0) {
+        limitedData = (data as any[]).slice(0, 4);
     }
 
-    return value;
-  }
+    const formatter = new Intl.DateTimeFormat("en", {
+        year: "numeric",
+        month: "numeric",
+        day: "numeric",
+        hour: "numeric",
+        minute: "2-digit",
+        second: "2-digit",
+        timeZone: "America/New_York"
+    });
+
+    function formatDatum([key, value]: any[]) {
+        if (key === "date") {
+            const parsedDate = new Date(value);
+            return formatter.format(parsedDate);
+        }
+
+        if (key === "user") {
+            return value["name"];
+        }
+
+        return value;
+    }
 </script>
 
 <table>
-  {#if title}
-    <h2>{title}</h2>
-  {/if}
-  {#if !noheader && data}
-    <thead>
-      <tr>
-        {#each getDataKeys(data) as header}
-          <th>{header}</th>
-        {/each}
-      </tr>
-    </thead>
-  {/if}
-  <tbody>
-    {#if data}
-      {#each data as row}
+    {#if title}
+        <h2>{title}</h2>
+    {/if}
+    {#if !noheader && data}
+        <thead>
         <tr>
-          {#each getRow(row) as datum}
-            <td>{formatDatum(datum)}</td>
-          {/each}
+            {#each getDataKeys(data) as header}
+                <th>{header}</th>
+            {/each}
         </tr>
-      {/each}
+        </thead>
+    {/if}
+    <tbody>
+    {#if data}
+        {#each limitedData as row}
+            <tr>
+                {#each getRow(row) as datum}
+                    <td>{formatDatum(datum)}</td>
+                {/each}
+            </tr>
+        {/each}
     {:else}
-      <tr> There is not data. </tr>
+        <tr> There is not data.</tr>
+    {/if}
+    </tbody>
+    {#if !nofooter}
+        <slot name="footer">
+            <tfoot>
+            <tr>
+                <td>Table Footer</td>
+            </tr>
+            </tfoot>
+        </slot>
     {/if}
-  </tbody>
-  {#if !nofooter}
-    <slot name="footer">
-      <tfoot>
-        <tr>
-          <td>Table Footer</td>
-        </tr>
-      </tfoot>
-    </slot>
-  {/if}
 </table>
 
 <style>
-  table {
-    padding: 16px;
-    margin: 8px;
-    border: solid 1px black;
-    border-collapse: collapse;
-  }
+    table {
+        padding: 16px;
+        margin: 8px;
+        border: solid 1px black;
+        border-collapse: collapse;
+        overflow-y: hidden;
+    }
 
-  th {
-    text-transform: capitalize;
-  }
+    th {
+        text-transform: capitalize;
+    }
 
-  thead tr {
-    background: rgba(0, 0, 23, 0.34);
-  }
+    thead tr {
+        background: rgba(0, 0, 23, 0.34);
+    }
 
-  tbody tr:nth-child(odd) {
-    background: rgba(0, 0, 23, 0.14);
-  }
+    tbody tr:nth-child(odd) {
+        background: rgba(0, 0, 23, 0.14);
+    }
 
-  th,
-  td {
-    padding: 1em;
-    border: 1px solid rgba(0, 0, 0, 1);
-  }
+    th,
+    td {
+        padding: 1em;
+        border: 1px solid rgba(0, 0, 0, 1);
+    }
 </style>
-- 
cgit v1.1


From 8fab2d03bce82e4dee798ebffb1e93c557f62a4b Mon Sep 17 00:00:00 2001
From: Zach Berwaldt <zberwaldt@tutamail.com>
Date: Thu, 7 Mar 2024 23:16:22 -0500
Subject: feat: Update authentication route and add comments to exported
 members

- The authentication route in the API has been updated to use a new router setup function.
- Comments have been added to all exported members of the `auth.go` module in the internal controllers package.
---
 fe/src/lib/Table.svelte | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

(limited to 'fe/src/lib/Table.svelte')

diff --git a/fe/src/lib/Table.svelte b/fe/src/lib/Table.svelte
index d1cd7da..621157e 100644
--- a/fe/src/lib/Table.svelte
+++ b/fe/src/lib/Table.svelte
@@ -5,6 +5,10 @@
     export let omit: string[] = ["id"];
     export let title: string | undefined = undefined;
 
+    export let sortBy: string = 'date';
+
+    type SortComparator = (a, b) => number
+
     function getDataKeys(data: any[]): string[] {
         if (!data || data.length === 0) return [];
         return Object.keys(data[0])
@@ -16,11 +20,8 @@
         return Object.entries(row).filter((r) => !omit.includes(r[0]));
     }
 
-
-    let limitedData: Array<any> = [];
-
-    if (data && (data as any[]).length > 0) {
-        limitedData = (data as any[]).slice(0, 4);
+    function sort(arr: Array<Record<string, any>>, fn: SortComparator = (a , b) => new Date(b[sortBy]) - new Date(a[sortBy])) {
+        return arr.sort(fn)
     }
 
     const formatter = new Intl.DateTimeFormat("en", {
@@ -62,7 +63,7 @@
     {/if}
     <tbody>
     {#if data}
-        {#each limitedData as row}
+        {#each sort(data) as row}
             <tr>
                 {#each getRow(row) as datum}
                     <td>{formatDatum(datum)}</td>
-- 
cgit v1.1

