From 61c4a2ca27e91700b44c85c8789c914bdeecafe4 Mon Sep 17 00:00:00 2001 From: jjoel1630 Date: Mon, 21 Oct 2024 16:03:51 -0400 Subject: [PATCH 01/10] connected preview and file display functionality --- src/components/DataTable.tsx | 26 ++++- src/components/PreviewCard.tsx | 187 ++++++++++++++++++++------------- src/routes/root.tsx | 12 ++- 3 files changed, 146 insertions(+), 79 deletions(-) diff --git a/src/components/DataTable.tsx b/src/components/DataTable.tsx index 5ea1257..2e7d999 100644 --- a/src/components/DataTable.tsx +++ b/src/components/DataTable.tsx @@ -1,14 +1,32 @@ -import { useState } from "react"; import { Table } from "@mantine/core"; import { useMantineTheme } from "@mantine/core"; interface DataTableProps { data?: MCAPFileInformation[]; + selectedRow?: string; + setSelectedRow: React.Dispatch>; + setSelectedData: React.Dispatch< + React.SetStateAction + >; } -export default function DataTable({ data }: DataTableProps) { +export default function DataTable({ + data, + selectedRow, + setSelectedRow, + setSelectedData, +}: DataTableProps) { const theme = useMantineTheme(); - const [selectedRow, setSelectedRow] = useState(); + + const setPreviewData = (file: MCAPFileInformation) => { + if (selectedRow === file.id) { + setSelectedRow(""); + setSelectedData(undefined); + } else { + setSelectedRow(file.id); + setSelectedData(file); + } + }; const rows = !data ? ( @@ -26,7 +44,7 @@ export default function DataTable({ data }: DataTableProps) { data.map((file) => ( setSelectedRow(file.id)} + onClick={() => setPreviewData(file)} /*fw={selectedRow === file.id ? "bold" : ""}*/ bg={selectedRow === file.id ? theme.primaryColor : ""} > diff --git a/src/components/PreviewCard.tsx b/src/components/PreviewCard.tsx index 6beee2f..b6f5633 100644 --- a/src/components/PreviewCard.tsx +++ b/src/components/PreviewCard.tsx @@ -1,9 +1,28 @@ -import { useState } from 'react'; -import { Text, Button, Grid, Menu, rem, Table, ScrollArea, TextInput } from "@mantine/core"; -import { IconDownload, IconChevronDown, IconFile, IconSearch } from "@tabler/icons-react"; +import { useState } from "react"; +import { + Text, + Button, + Grid, + Menu, + rem, + Table, + ScrollArea, + TextInput, +} from "@mantine/core"; +import { + IconDownload, + IconChevronDown, + IconFile, + IconSearch, +} from "@tabler/icons-react"; import "@/css/PreviewCard.css"; -function PreviewCard() { +interface PreviewCardProps { + selectedRow?: string; + selectedData: MCAPFileInformation | undefined; +} + +function PreviewCard({ selectedData }: PreviewCardProps) { return (
@@ -25,61 +44,73 @@ function PreviewCard() { -
- - run 2024-18-10.mcap - -
-
- - Date:{" "} - - {/* Spacer */} - - Fri, Oct 18, 2024 - -
-
- - Time:{" "} - - {/* Spacer */} - - 12:24:02 PM - -
-
- - Location:{" "} - - {/* Spacer */} - - MRDC - -
-
- - Sensors:{" "} - - {/* Spacer */} - - aero_sensor_1 - -
-
- - -
+ {selectedData ? ( + <> +
+ + run 2024-18-10.mcap + +
+
+ + Date:{" "} + + {/* Spacer */} + + Fri, Oct 18, 2024 + +
+
+ + Time:{" "} + + {/* Spacer */} + + 12:24:02 PM + +
+
+ + Location:{" "} + + {/* Spacer */} + + MRDC + +
+
+ + Sensors:{" "} + + {/* Spacer */} + + aero_sensor_1 + +
+
+ + +
+ + ) : ( + <> +
+ + No file selected + +
+ + )}
@@ -148,8 +179,6 @@ export function DownloadButton({ buttonText }: DownloadButtonProps) { ); } - - export const SchemaTable = () => { // Example data for the table const initialData = Array.from({ length: 20 }, (_, index) => ({ @@ -157,15 +186,16 @@ export const SchemaTable = () => { value: `${index + 1 + "." + index + "." + index}`, })); - const [searchTerm, setSearchTerm] = useState(''); + const [searchTerm, setSearchTerm] = useState(""); const [filteredData, setFilteredData] = useState(initialData); // Function to filter data based on the search term const handleSearch = (term: string) => { const lowercasedTerm = term.toLowerCase(); - const filtered = initialData.filter(item => - item.name.toLowerCase().includes(lowercasedTerm) || - item.value.toLowerCase().includes(lowercasedTerm) + const filtered = initialData.filter( + (item) => + item.name.toLowerCase().includes(lowercasedTerm) || + item.value.toLowerCase().includes(lowercasedTerm), ); setFilteredData(filtered); }; @@ -175,7 +205,6 @@ export const SchemaTable = () => { {/* Search input */} } placeholder="Search schemas" // very hacky text spacing value={searchTerm} @@ -185,8 +214,18 @@ export const SchemaTable = () => { }} /> - {/* Scrollable area with height limit */} - + + {" "} + {/* Scrollable area with height limit */} +
Name @@ -196,14 +235,16 @@ export const SchemaTable = () => { {filteredData.length > 0 ? ( filteredData.map((item, index) => ( - - {item.name} - {item.value} + + {item.name} + + {item.value} + )) ) : ( - + No results found @@ -213,4 +254,4 @@ export const SchemaTable = () => { ); -}; \ No newline at end of file +}; diff --git a/src/routes/root.tsx b/src/routes/root.tsx index db987bd..de01f99 100644 --- a/src/routes/root.tsx +++ b/src/routes/root.tsx @@ -7,17 +7,25 @@ import PreviewCard from "@/components/PreviewCard"; export default function Root() { const [filteredData, setFilteredData] = useState(data); + const [selectedRow, setSelectedRow] = useState(""); + const [selectedData, setSelectedData] = useState(); + return ( <>
- +
- +
); From 1718513b8b79fb0ff8e96a67a26a7ba9bedaf8b0 Mon Sep 17 00:00:00 2001 From: jjoel1630 Date: Mon, 21 Oct 2024 16:09:50 -0400 Subject: [PATCH 02/10] fixed lowercase search issue --- src/components/SearchBar.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/SearchBar.tsx b/src/components/SearchBar.tsx index 81e335a..31a44b1 100644 --- a/src/components/SearchBar.tsx +++ b/src/components/SearchBar.tsx @@ -49,9 +49,11 @@ function SearchBarWithFilter({ setFilteredData }: SearchBarWithFilterProps) { // Match filters const matchesLocation = - filters.location === "" || item.location === filters.location; + filters.location === "" || + item.location.toLowerCase() === filters.location.toLowerCase(); const matchesEventType = - filters.eventType === "" || item.event_type === filters.eventType; + filters.eventType.toLowerCase() === "" || + item.event_type?.toLowerCase() === filters.eventType.toLowerCase(); const matchesDate = isDateInRange( item.date, filters.beforeDate, From 4ea09fedb9b568f51822fe4e90884b03ba65ee14 Mon Sep 17 00:00:00 2001 From: jjoel1630 Date: Wed, 23 Oct 2024 22:06:02 -0400 Subject: [PATCH 03/10] added route connection --- src/components/SearchBar.tsx | 4 +++- src/routes/root.tsx | 39 +++++++++++++++++++++++++++++++++--- src/types/index.d.ts | 1 + 3 files changed, 40 insertions(+), 4 deletions(-) diff --git a/src/components/SearchBar.tsx b/src/components/SearchBar.tsx index 31a44b1..5ba667a 100644 --- a/src/components/SearchBar.tsx +++ b/src/components/SearchBar.tsx @@ -4,7 +4,9 @@ import { eventType, location } from "@/data/dataFilters"; import "@/css/SearchBar.css"; interface SearchBarWithFilterProps { - setFilteredData: React.Dispatch>; + setFilteredData: React.Dispatch< + React.SetStateAction + >; } function SearchBarWithFilter({ setFilteredData }: SearchBarWithFilterProps) { diff --git a/src/routes/root.tsx b/src/routes/root.tsx index de01f99..af68b9b 100644 --- a/src/routes/root.tsx +++ b/src/routes/root.tsx @@ -1,15 +1,48 @@ -import { data } from "@/data/sampledata"; -import { useState } from "react"; +import { useEffect, useState } from "react"; import SearchBar from "@/components/SearchBar"; import "@/css/Root.css"; import DataTable from "@/components/DataTable"; import PreviewCard from "@/components/PreviewCard"; +import { location } from "@/data/dataFilters"; export default function Root() { - const [filteredData, setFilteredData] = useState(data); + const [filteredData, setFilteredData] = useState(); const [selectedRow, setSelectedRow] = useState(""); const [selectedData, setSelectedData] = useState(); + useEffect(() => { + const fetchData = async (loc: string) => { + const res = await fetch( + `http://localhost:8080/api/v2/mcap/get?location=${loc}`, + ); + const data = await res.json(); + + return data; + }; + + const assignData = async () => { + const apiData = await Promise.all( + location.map(async (loc: string) => await fetchData(loc)), + ); + const validData = apiData.filter((data) => data !== null); + + const flattenedData = validData.flat(); + + const sortedData = flattenedData.sort((a, b) => { + const [monthA, dayA, yearA] = a.date.split("-"); + const [monthB, dayB, yearB] = b.date.split("-"); + const dateA = new Date(`${yearA}-${monthA}-${dayA}`); + const dateB = new Date(`${yearB}-${monthB}-${dayB}`); + + return dateB.getTime() - dateA.getTime(); + }); + + setFilteredData(sortedData); + }; + + assignData(); + }, []); + return ( <>
diff --git a/src/types/index.d.ts b/src/types/index.d.ts index 84a8f94..e7486bb 100644 --- a/src/types/index.d.ts +++ b/src/types/index.d.ts @@ -11,4 +11,5 @@ type MCAPFileInformation = { location: string; notes: string?; event_type: string?; + signed_url: string?; }; From bdc58d3b416c67efad6bd1c962f6b1f506cf4296 Mon Sep 17 00:00:00 2001 From: jjoel1630 Date: Wed, 23 Oct 2024 22:32:25 -0400 Subject: [PATCH 04/10] finished route connection --- .gitignore | 2 + src/components/PreviewCard.tsx | 95 +++++++++++++++++++++------------- src/routes/root.tsx | 2 +- 3 files changed, 63 insertions(+), 36 deletions(-) diff --git a/.gitignore b/.gitignore index acb0ad0..0692b67 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,5 @@ dist-ssr *.njsproj *.sln *.sw? + +.env \ No newline at end of file diff --git a/src/components/PreviewCard.tsx b/src/components/PreviewCard.tsx index b6f5633..05c03eb 100644 --- a/src/components/PreviewCard.tsx +++ b/src/components/PreviewCard.tsx @@ -23,6 +23,27 @@ interface PreviewCardProps { } function PreviewCard({ selectedData }: PreviewCardProps) { + const formatDate = (dateString: string) => { + const [month, day, year] = dateString.split("-"); + const date = new Date(`${year}-${month}-${day}`); + return date.toLocaleDateString("en-US", { + weekday: "short", + year: "numeric", + month: "short", + day: "numeric", + }); + }; + + const formatTime = (dateString: string) => { + const [month, day, year] = dateString.split("-"); + const date = new Date(`${year}-${month}-${day}T00:00:00`); + return date.toLocaleTimeString("en-US", { + hour: "2-digit", + minute: "2-digit", + second: "2-digit", + }); + }; + return (
@@ -48,43 +69,52 @@ function PreviewCard({ selectedData }: PreviewCardProps) { <>
- run 2024-18-10.mcap + {selectedData.mcap_file_name}{" "}
Date:{" "} - {/* Spacer */} + - Fri, Oct 18, 2024 + {formatDate(selectedData.date)}{" "}
Time:{" "} - {/* Spacer */} + - 12:24:02 PM + {formatTime(selectedData.date)}{" "}
Location:{" "} - {/* Spacer */} + - MRDC + {selectedData.location}
Sensors:{" "} - {/* Spacer */} + - aero_sensor_1 + {selectedData.event_type || "N/A"}{" "} + +
+
+ + Notes:{" "} + + + + {selectedData.notes || "N/A"}{" "}
- - + +
) : ( @@ -121,9 +159,15 @@ export default PreviewCard; interface DownloadButtonProps { buttonText: string; + fileName: string; + signedUrl: string | null; } -export function DownloadButton({ buttonText }: DownloadButtonProps) { +export function DownloadButton({ + buttonText, + fileName, + signedUrl, +}: DownloadButtonProps) { return ( } + onClick={() => { + window.open(signedUrl, "_blank"); + }} > - File_1 - - - - } - > - File_2 - - - - } - > - File_3 + {fileName} diff --git a/src/routes/root.tsx b/src/routes/root.tsx index af68b9b..ca57b8c 100644 --- a/src/routes/root.tsx +++ b/src/routes/root.tsx @@ -13,7 +13,7 @@ export default function Root() { useEffect(() => { const fetchData = async (loc: string) => { const res = await fetch( - `http://localhost:8080/api/v2/mcap/get?location=${loc}`, + `${process.env.API_URL}/api/v2/mcap/get?location=${loc}`, ); const data = await res.json(); From 7a9e99c69bd98892d80d60c8d7c6f2afa354cd61 Mon Sep 17 00:00:00 2001 From: jjoel1630 Date: Thu, 24 Oct 2024 17:46:26 -0400 Subject: [PATCH 05/10] fixed render repeated divs --- .gitignore | 2 +- src/components/PreviewCard.tsx | 88 +++++++++++++++------------------- 2 files changed, 39 insertions(+), 51 deletions(-) diff --git a/.gitignore b/.gitignore index 0692b67..73a5420 100644 --- a/.gitignore +++ b/.gitignore @@ -25,4 +25,4 @@ dist-ssr *.sln *.sw? -.env \ No newline at end of file +.env.local \ No newline at end of file diff --git a/src/components/PreviewCard.tsx b/src/components/PreviewCard.tsx index 05c03eb..0f68fa3 100644 --- a/src/components/PreviewCard.tsx +++ b/src/components/PreviewCard.tsx @@ -67,56 +67,26 @@ function PreviewCard({ selectedData }: PreviewCardProps) { {selectedData ? ( <> -
- - {selectedData.mcap_file_name}{" "} - -
-
- - Date:{" "} - - - - {formatDate(selectedData.date)}{" "} - -
-
- - Time:{" "} - - - - {formatTime(selectedData.date)}{" "} - -
-
- - Location:{" "} - - - - {selectedData.location} - -
-
- - Sensors:{" "} - - - - {selectedData.event_type || "N/A"}{" "} - -
-
- - Notes:{" "} - - - - {selectedData.notes || "N/A"}{" "} - -
+ + + + + + + +
+ + {name}:{" "} + + + + {val} + +
+ ); +} + interface DownloadButtonProps { buttonText: string; fileName: string; From a2a7252af07ac0ab11777faffd21aa948d93c8dd Mon Sep 17 00:00:00 2001 From: jjoel1630 Date: Thu, 24 Oct 2024 18:05:24 -0400 Subject: [PATCH 06/10] added .env.local --- .env | 1 + 1 file changed, 1 insertion(+) create mode 100644 .env diff --git a/.env b/.env new file mode 100644 index 0000000..beafddf --- /dev/null +++ b/.env @@ -0,0 +1 @@ +VITE_API_URL=https://api-url:port \ No newline at end of file From 7ebed12e042c5c2d5359b3dc6407bd3c0464fb3e Mon Sep 17 00:00:00 2001 From: jjoel1630 Date: Thu, 24 Oct 2024 22:49:32 -0400 Subject: [PATCH 07/10] fixed all comment issues, added .env.local, fixed filtering data and calling api for each search call --- src/components/PreviewCard.tsx | 8 +- src/components/SearchBar.tsx | 123 ++++++++++++++-------------- src/data/sampledata.ts | 1 - src/routes/root.tsx | 102 +++++++++++++++++------ src/stories/DataTable.stories.tsx | 1 - src/stories/PreviewCard.stories.tsx | 7 +- src/types/index.d.ts | 15 +++- 7 files changed, 164 insertions(+), 93 deletions(-) diff --git a/src/components/PreviewCard.tsx b/src/components/PreviewCard.tsx index 0f68fa3..5a4976a 100644 --- a/src/components/PreviewCard.tsx +++ b/src/components/PreviewCard.tsx @@ -83,9 +83,9 @@ function PreviewCard({ selectedData }: PreviewCardProps) { - +
} onClick={() => { - window.open(signedUrl, "_blank"); + window.open(signedUrl ?? undefined, "_blank"); }} > {fileName} diff --git a/src/components/SearchBar.tsx b/src/components/SearchBar.tsx index 5ba667a..8e3f424 100644 --- a/src/components/SearchBar.tsx +++ b/src/components/SearchBar.tsx @@ -1,5 +1,4 @@ -import React, { useState, useEffect } from "react"; -import { data } from "@/data/sampledata"; +import React, { useState } from "react"; import { eventType, location } from "@/data/dataFilters"; import "@/css/SearchBar.css"; @@ -7,79 +6,80 @@ interface SearchBarWithFilterProps { setFilteredData: React.Dispatch< React.SetStateAction >; + setSearchFilters: React.Dispatch>; } -function SearchBarWithFilter({ setFilteredData }: SearchBarWithFilterProps) { +function SearchBarWithFilter({ setSearchFilters }: SearchBarWithFilterProps) { const [searchTerm, setSearchTerm] = useState(""); - const [filters, setFilters] = useState({ - location: "", - eventType: "", - beforeDate: "", - afterDate: "", - }); - useEffect(() => { - // add code to get data from server here - // setFilteredData(serverData) - }, []); + // const [filters] = useState({ + // location: "", + // eventType: "", + // beforeDate: "", + // afterDate: "", + // }); // Check if a date is in the valid range - const isDateInRange = ( - dateStr: string, - beforeDate: string, - afterDate: string, - ) => { - const itemDate = new Date(dateStr); - const before = beforeDate ? new Date(beforeDate) : null; - const after = afterDate ? new Date(afterDate) : null; + // const isDateInRange = ( + // dateStr: string, + // beforeDate: string, + // afterDate: string, + // ) => { + // const itemDate = new Date(dateStr); + // const before = beforeDate ? new Date(beforeDate) : null; + // const after = afterDate ? new Date(afterDate) : null; - if (before && itemDate > before) return false; - if (after && itemDate < after) return false; + // if (before && itemDate > before) return false; + // if (after && itemDate < after) return false; - return true; - }; + // return true; + // }; // Filter logic - const handleSearch = () => { - const filtered = data.filter((item) => { - // Match search term in multiple fields - const matchesSearch = - item.mcap_file_name.toLowerCase().includes(searchTerm.toLowerCase()) || - item.matlab_file_name - .toLowerCase() - .includes(searchTerm.toLowerCase()) || - item.notes?.toLowerCase().includes(searchTerm.toLowerCase()); - - // Match filters - const matchesLocation = - filters.location === "" || - item.location.toLowerCase() === filters.location.toLowerCase(); - const matchesEventType = - filters.eventType.toLowerCase() === "" || - item.event_type?.toLowerCase() === filters.eventType.toLowerCase(); - const matchesDate = isDateInRange( - item.date, - filters.beforeDate, - filters.afterDate, - ); - - return ( - matchesSearch && matchesLocation && matchesEventType && matchesDate - ); - }); - setFilteredData(filtered); - }; + // const handleSearch = () => { + // const filtered = data.filter((item) => { + // // Match search term in multiple fields + // const matchesSearch = + // item.mcap_file_name.toLowerCase().includes(searchTerm.toLowerCase()) || + // item.matlab_file_name + // .toLowerCase() + // .includes(searchTerm.toLowerCase()) || + // item.notes?.toLowerCase().includes(searchTerm.toLowerCase()); + + // // Match filters + // const matchesLocation = + // filters.location === "" || + // item.location.toLowerCase() === filters.location.toLowerCase(); + // const matchesEventType = + // filters.eventType.toLowerCase() === "" || + // item.event_type?.toLowerCase() === filters.eventType.toLowerCase(); + // const matchesDate = isDateInRange( + // item.date, + // filters.beforeDate, + // filters.afterDate, + // ); + + // return ( + // matchesSearch && matchesLocation && matchesEventType && matchesDate + // ); + // }); + // setFilteredData(filtered); + // }; // Trigger search on filter or search term change - useEffect(() => { - handleSearch(); - }, [searchTerm, filters]); + // useEffect(() => { + // handleSearch(); + // }, [searchTerm, filters]); // Handle filter changes function handleFilterChange( e: React.ChangeEvent, ) { - const { name, value } = e.target; - setFilters((prevFilters) => ({ + let { name } = e.target; + const { value } = e.target; + + if (name == "") name = "notes"; + + setSearchFilters((prevFilters) => ({ ...prevFilters, [name]: value, })); @@ -98,7 +98,10 @@ function SearchBarWithFilter({ setFilteredData }: SearchBarWithFilterProps) { className="search-bar" placeholder="Search by file name or notes..." value={searchTerm} - onChange={(e) => setSearchTerm(e.target.value)} + onChange={(e) => { + handleFilterChange(e); + setSearchTerm(e.target.value); + }} /> {/* Filter Options */} diff --git a/src/data/sampledata.ts b/src/data/sampledata.ts index e90d100..2cf53ba 100644 --- a/src/data/sampledata.ts +++ b/src/data/sampledata.ts @@ -95,6 +95,5 @@ export const data: MCAPFileInformation[] = [ date: "08-29-2024", location: "MRDC", notes: "car did not turn on", - event_type: null, }, ]; diff --git a/src/routes/root.tsx b/src/routes/root.tsx index ca57b8c..ba96fd7 100644 --- a/src/routes/root.tsx +++ b/src/routes/root.tsx @@ -9,40 +9,93 @@ export default function Root() { const [filteredData, setFilteredData] = useState(); const [selectedRow, setSelectedRow] = useState(""); const [selectedData, setSelectedData] = useState(); + const [searchFilters, setSearchFilters] = useState({ + location: "", + eventType: "", + beforeDate: "", + afterDate: "", + }); - useEffect(() => { - const fetchData = async (loc: string) => { - const res = await fetch( - `${process.env.API_URL}/api/v2/mcap/get?location=${loc}`, - ); - const data = await res.json(); + const fetchData = async (filters: SearchFilter) => { + const { location, date, notes, eventType } = filters; + let { afterDate, beforeDate } = filters; + + beforeDate = beforeDate + ? `${beforeDate?.split("-")[1]}-${beforeDate?.split("-")[2]}-${beforeDate?.split("-")[0]}` + : undefined; + afterDate = afterDate + ? `${afterDate?.split("-")[1]}-${afterDate?.split("-")[2]}-${afterDate?.split("-")[0]}` + : undefined; - return data; + // console.log(beforeDate); + // console.log(afterDate); + + const params: Record = { + ...(location ? { location } : {}), + ...(eventType ? { eventType } : {}), + ...(date ? { date } : {}), + ...(notes ? { notes } : {}), + ...(afterDate ? { afterDate } : {}), + ...(beforeDate ? { beforeDate } : {}), }; - const assignData = async () => { - const apiData = await Promise.all( - location.map(async (loc: string) => await fetchData(loc)), - ); - const validData = apiData.filter((data) => data !== null); + const queryString = new URLSearchParams(params).toString(); + console.log(queryString); - const flattenedData = validData.flat(); + // console.log(queryString); + // console.log(searchFilters); - const sortedData = flattenedData.sort((a, b) => { - const [monthA, dayA, yearA] = a.date.split("-"); - const [monthB, dayB, yearB] = b.date.split("-"); - const dateA = new Date(`${yearA}-${monthA}-${dayA}`); - const dateB = new Date(`${yearB}-${monthB}-${dayB}`); + const res = await fetch( + `${import.meta.env.VITE_API_URL}/api/v2/mcap/get?${queryString}`, + ); - return dateB.getTime() - dateA.getTime(); - }); + const data = await res.json(); + return data.data; + }; - setFilteredData(sortedData); - }; + const assignData = async () => { + const apiData = await Promise.all( + location.map(async (loc: string) => await fetchData({ location: loc })), + ); + const validData = apiData.filter((data) => data !== null); + + const flattenedData = validData.flat(); + + const sortedData = flattenedData.sort((a, b) => { + const [monthA, dayA, yearA] = a.date.split("-"); + const [monthB, dayB, yearB] = b.date.split("-"); + const dateA = new Date(`${yearA}-${monthA}-${dayA}`); + const dateB = new Date(`${yearB}-${monthB}-${dayB}`); + return dateB.getTime() - dateA.getTime(); + }); + + setFilteredData(sortedData); + }; + + useEffect(() => { assignData(); }, []); + useEffect(() => { + const getData = async () => { + const data = await fetchData(searchFilters); + // console.log(data); + const sortedData = data.sort( + (a: MCAPFileInformation, b: MCAPFileInformation) => { + const [monthA, dayA, yearA] = a.date.split("-"); + const [monthB, dayB, yearB] = b.date.split("-"); + const dateA = new Date(`${yearA}-${monthA}-${dayA}`); + const dateB = new Date(`${yearB}-${monthB}-${dayB}`); + + return dateB.getTime() - dateA.getTime(); + }, + ); + setFilteredData(sortedData); + }; + getData(); + }, [searchFilters]); + return ( <>
@@ -55,7 +108,10 @@ export default function Root() { />
- +
diff --git a/src/stories/DataTable.stories.tsx b/src/stories/DataTable.stories.tsx index 5f93d3e..354d6da 100644 --- a/src/stories/DataTable.stories.tsx +++ b/src/stories/DataTable.stories.tsx @@ -107,7 +107,6 @@ const sampleData = [ date: "08-29-2024", location: "MRDC", notes: "car did not turn on", - event_type: null, }, ]; diff --git a/src/stories/PreviewCard.stories.tsx b/src/stories/PreviewCard.stories.tsx index fb38332..a751201 100644 --- a/src/stories/PreviewCard.stories.tsx +++ b/src/stories/PreviewCard.stories.tsx @@ -10,4 +10,9 @@ export default meta; type Story = StoryObj; -export const Default: Story = {}; +export const Default: Story = { + args: { + selectedRow: undefined, + selectedData: undefined, + }, +}; diff --git a/src/types/index.d.ts b/src/types/index.d.ts index e7486bb..6919104 100644 --- a/src/types/index.d.ts +++ b/src/types/index.d.ts @@ -9,7 +9,16 @@ type MCAPFileInformation = { velocity_plot_path: string; date: string; location: string; - notes: string?; - event_type: string?; - signed_url: string?; + notes?: string; + event_type?: string; + signed_url?: string; +}; + +type SearchFilter = { + location?: string; + date?: string; + notes?: string; + eventType?: string; + afterDate?: string; + beforeDate?: string; }; From 1ced654d28f29804c6e4eae1f73851730a2916fa Mon Sep 17 00:00:00 2001 From: jjoel1630 Date: Fri, 25 Oct 2024 01:54:05 -0400 Subject: [PATCH 08/10] fixed filter with multiple params --- src/components/SearchBar.tsx | 16 +++++- src/routes/root.tsx | 107 ++++++++++++++++++++++++++++------- src/types/index.d.ts | 1 + 3 files changed, 100 insertions(+), 24 deletions(-) diff --git a/src/components/SearchBar.tsx b/src/components/SearchBar.tsx index 8e3f424..ef6bde4 100644 --- a/src/components/SearchBar.tsx +++ b/src/components/SearchBar.tsx @@ -74,13 +74,25 @@ function SearchBarWithFilter({ setSearchFilters }: SearchBarWithFilterProps) { function handleFilterChange( e: React.ChangeEvent, ) { - let { name } = e.target; + const { name } = e.target; const { value } = e.target; - if (name == "") name = "notes"; + const filt: SearchFilter = { + notes: "", + filename: "", + }; + + if (name == "") { + filt.notes = value; + filt.filename = value; + } + + // console.log("search", filt); setSearchFilters((prevFilters) => ({ ...prevFilters, + notes: filt.notes, + filename: filt.filename, [name]: value, })); } diff --git a/src/routes/root.tsx b/src/routes/root.tsx index ba96fd7..2c31790 100644 --- a/src/routes/root.tsx +++ b/src/routes/root.tsx @@ -16,41 +16,104 @@ export default function Root() { afterDate: "", }); + // const fetchData = async (filters: SearchFilter) => { + // const { location, date, notes, eventType, filename } = filters; + // let { afterDate, beforeDate } = filters; + + // beforeDate = beforeDate + // ? `${beforeDate?.split("-")[1]}-${beforeDate?.split("-")[2]}-${beforeDate?.split("-")[0]}` + // : undefined; + // afterDate = afterDate + // ? `${afterDate?.split("-")[1]}-${afterDate?.split("-")[2]}-${afterDate?.split("-")[0]}` + // : undefined; + + // const params: Record = { + // ...(location ? { location } : {}), + // ...(eventType ? { eventType } : {}), + // ...(date ? { date } : {}), + // ...(notes ? { notes } : {}), + // ...(filename ? { filename } : {}), + // ...(afterDate ? { afterDate } : {}), + // ...(beforeDate ? { beforeDate } : {}), + // }; + + // const queryString = new URLSearchParams(params).toString(); + + // const res = await fetch( + // `${import.meta.env.VITE_API_URL}/api/v2/mcap/get?${queryString}`, + // ); + + // const data = await res.json(); + // return data.data; + // }; + const fetchData = async (filters: SearchFilter) => { - const { location, date, notes, eventType } = filters; + const { location, date, notes, eventType, filename } = filters; let { afterDate, beforeDate } = filters; beforeDate = beforeDate - ? `${beforeDate?.split("-")[1]}-${beforeDate?.split("-")[2]}-${beforeDate?.split("-")[0]}` + ? `${beforeDate.split("-")[1]}-${beforeDate.split("-")[2]}-${beforeDate.split("-")[0]}` : undefined; afterDate = afterDate - ? `${afterDate?.split("-")[1]}-${afterDate?.split("-")[2]}-${afterDate?.split("-")[0]}` + ? `${afterDate.split("-")[1]}-${afterDate.split("-")[2]}-${afterDate.split("-")[0]}` : undefined; - // console.log(beforeDate); - // console.log(afterDate); - - const params: Record = { - ...(location ? { location } : {}), - ...(eventType ? { eventType } : {}), - ...(date ? { date } : {}), - ...(notes ? { notes } : {}), - ...(afterDate ? { afterDate } : {}), - ...(beforeDate ? { beforeDate } : {}), + const buildParams = (additionalParams: Record = {}) => { + return { + ...(location ? { location } : {}), + ...(eventType ? { eventType } : {}), + ...(date ? { date } : {}), + ...(afterDate ? { afterDate } : {}), + ...(beforeDate ? { beforeDate } : {}), + ...additionalParams, + }; }; - const queryString = new URLSearchParams(params).toString(); - console.log(queryString); + if (!notes && !filename) { + const params = buildParams(); + const queryString = new URLSearchParams(params).toString(); + + const res = await fetch( + `${import.meta.env.VITE_API_URL}/api/v2/mcap/get?${queryString}`, + ); + const data = await res.json(); + return data.data; + } + + const promises: Promise[] = []; + + if (notes) { + const paramsNotes = buildParams({ notes }); + const queryStringNotes = new URLSearchParams(paramsNotes).toString(); + promises.push( + fetch( + `${import.meta.env.VITE_API_URL}/api/v2/mcap/get?${queryStringNotes}`, + ), + ); + } + + if (filename) { + const paramsFilename = buildParams({ filename }); + const queryStringFilename = new URLSearchParams( + paramsFilename, + ).toString(); + promises.push( + fetch( + `${import.meta.env.VITE_API_URL}/api/v2/mcap/get?${queryStringFilename}`, + ), + ); + } + + const results = await Promise.all(promises); + const data = await Promise.all(results.map((res) => res.json())); - // console.log(queryString); - // console.log(searchFilters); + const combinedData = data.flatMap((entry) => entry.data || []); - const res = await fetch( - `${import.meta.env.VITE_API_URL}/api/v2/mcap/get?${queryString}`, - ); + const uniqueData = Array.from( + new Set(combinedData.map((item) => item.id)), + ).map((id) => combinedData.find((item) => item.id === id)); - const data = await res.json(); - return data.data; + return uniqueData; }; const assignData = async () => { diff --git a/src/types/index.d.ts b/src/types/index.d.ts index 6919104..2e71ea4 100644 --- a/src/types/index.d.ts +++ b/src/types/index.d.ts @@ -16,6 +16,7 @@ type MCAPFileInformation = { type SearchFilter = { location?: string; + filename?: string; date?: string; notes?: string; eventType?: string; From e8665ddbb063fe47795bee31ab225fe512e5c7f7 Mon Sep 17 00:00:00 2001 From: jjoel1630 Date: Fri, 25 Oct 2024 22:44:26 -0400 Subject: [PATCH 09/10] removed .env from gitignore --- .gitignore | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 73a5420..4a9b1e4 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,4 @@ dist-ssr *.ntvs* *.njsproj *.sln -*.sw? - -.env.local \ No newline at end of file +*.sw? \ No newline at end of file From 70eacc5e0efa011299e9d2ab0e61783eae223ead Mon Sep 17 00:00:00 2001 From: jjoel1630 Date: Fri, 25 Oct 2024 22:48:09 -0400 Subject: [PATCH 10/10] fixed npm build issue --- src/data/sampledata.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/data/sampledata.ts b/src/data/sampledata.ts index 7f40535..07e1cc7 100644 --- a/src/data/sampledata.ts +++ b/src/data/sampledata.ts @@ -39,7 +39,6 @@ export const data: MCAPFileInformation[] = [ date: "08-29-2024", location: "MRDC", notes: "car did jk turn on", - event_type: null, }, { id: "07a0sdjwne-597f-4637-8b61-6134e75e6f76", @@ -152,4 +151,4 @@ export const data: MCAPFileInformation[] = [ location: "MRDC", notes: "car did not turn on", }, -]; \ No newline at end of file +];