diff --git a/bun.lockb b/bun.lockb
index b7d0b14..89a38a0 100755
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/package.json b/package.json
index 64b8d02..0cf7ef5 100644
--- a/package.json
+++ b/package.json
@@ -28,6 +28,7 @@
"@t3-oss/env-nextjs": "^0.10.1",
"@tanstack/eslint-plugin-query": "^5.43.1",
"@tanstack/react-query": "^5.45.0",
+ "@tanstack/react-table": "^8.19.2",
"@vercel/postgres": "^0.8.0",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
diff --git a/src/app/whishper/page.tsx b/src/app/whishper/page.tsx
index a757f36..45e5547 100644
--- a/src/app/whishper/page.tsx
+++ b/src/app/whishper/page.tsx
@@ -3,7 +3,7 @@
import { SignedIn, SignedOut } from "@clerk/nextjs";
import { usePathname, useRouter, useSearchParams } from "next/navigation";
import { useForm } from "react-hook-form";
-import { array, z } from "zod";
+import { z } from "zod";
import { Button } from "@/components/ui/button";
import {
Form,
@@ -27,6 +27,23 @@ import LoadingSpinner from "@/components/loading-spinner";
import type { WhishperRecordingsType } from "@/types";
import OpenInternalLink from "@/components/internal-link";
import OpenExternalLInk from "@/components/external-link";
+import AudioViewer from "@/components/audio-viewer";
+import {
+ type ColumnDef,
+ flexRender,
+ getCoreRowModel,
+ useReactTable,
+} from "@tanstack/react-table";
+import {
+ Table,
+ TableBody,
+ TableCell,
+ TableHead,
+ TableHeader,
+ TableRow,
+} from "@/components/ui/table";
+import { ExternalLink } from "lucide-react";
+import { columns } from "@/types";
const queryClient = new QueryClient();
@@ -39,11 +56,27 @@ async function getWhishperRecordings(query: string) {
const data = (await response.json()) as WhishperRecordingsType;
const lowerCaseQuery = query.toLowerCase();
- return data.filter(
- (item) =>
- item.fileName.toLowerCase().includes(lowerCaseQuery) ||
- item.result.text.toLowerCase().includes(lowerCaseQuery),
- );
+ const filteredAndScored = data
+ .filter(
+ (item) =>
+ item.fileName.toLowerCase().includes(lowerCaseQuery) ||
+ item.result.text.toLowerCase().includes(lowerCaseQuery),
+ )
+ .map((item) => {
+ const fileNameOccurrences = (
+ item.fileName.toLowerCase().match(new RegExp(lowerCaseQuery, "g")) ?? []
+ ).length;
+ const textOccurrences = (
+ item.result.text.toLowerCase().match(new RegExp(lowerCaseQuery, "g")) ??
+ []
+ ).length;
+ const score = fileNameOccurrences + textOccurrences;
+ return { ...item, score };
+ });
+ const sortedByScore = filteredAndScored.sort((a, b) => b.score - a.score);
+
+ // Step 4: Return the sorted array without the score
+ return sortedByScore.map(({ ...item }) => item);
}
function SearchForm() {
@@ -160,22 +193,76 @@ function RecordingsList() {
return (
<>
Search Results
-
- {WhishperRecordingsMap.map((recording, index) => (
- -
-
- {recording.fileName.split("_WHSHPR_")[1]}
-
-
- ))}
-
+
+ data={WhishperRecordingsMap as WhishperRecordingsType[]}
+ />
>
);
}
+interface DataTableProps {
+ columns: ColumnDef[];
+ data: TData[];
+}
+
+function DataTable({
+ columns,
+ data,
+}: DataTableProps) {
+ const table = useReactTable({
+ data,
+ columns,
+ getCoreRowModel: getCoreRowModel(),
+ });
+
+ return (
+
+
+
+ {table.getHeaderGroups().map((headerGroup) => (
+
+ {headerGroup.headers.map((header) => {
+ return (
+
+ {header.isPlaceholder
+ ? null
+ : flexRender(
+ header.column.columnDef.header,
+ header.getContext(),
+ )}
+
+ );
+ })}
+
+ ))}
+
+
+ {table.getRowModel().rows?.length ? (
+ table.getRowModel().rows.map((row) => (
+
+ {row.getVisibleCells().map((cell) => (
+
+ {flexRender(cell.column.columnDef.cell, cell.getContext())}
+
+ ))}
+
+ ))
+ ) : (
+
+
+ No results.
+
+
+ )}
+
+
+
+ );
+}
+
export default function WhishperPage() {
return (
diff --git a/src/components/audio-viewer.tsx b/src/components/audio-viewer.tsx
new file mode 100644
index 0000000..25b5022
--- /dev/null
+++ b/src/components/audio-viewer.tsx
@@ -0,0 +1,8 @@
+
+
+
+
+export default function AudioViewer()
+
+ return ;
+}
diff --git a/src/components/ui/table.tsx b/src/components/ui/table.tsx
new file mode 100644
index 0000000..973c6e5
--- /dev/null
+++ b/src/components/ui/table.tsx
@@ -0,0 +1,117 @@
+import * as React from "react"
+
+import { cn } from "@/lib/utils"
+
+const Table = React.forwardRef<
+ HTMLTableElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+Table.displayName = "Table"
+
+const TableHeader = React.forwardRef<
+ HTMLTableSectionElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+TableHeader.displayName = "TableHeader"
+
+const TableBody = React.forwardRef<
+ HTMLTableSectionElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+TableBody.displayName = "TableBody"
+
+const TableFooter = React.forwardRef<
+ HTMLTableSectionElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+ tr]:last:border-b-0 dark:bg-slate-800/50",
+ className
+ )}
+ {...props}
+ />
+))
+TableFooter.displayName = "TableFooter"
+
+const TableRow = React.forwardRef<
+ HTMLTableRowElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+TableRow.displayName = "TableRow"
+
+const TableHead = React.forwardRef<
+ HTMLTableCellElement,
+ React.ThHTMLAttributes
+>(({ className, ...props }, ref) => (
+ |
+))
+TableHead.displayName = "TableHead"
+
+const TableCell = React.forwardRef<
+ HTMLTableCellElement,
+ React.TdHTMLAttributes
+>(({ className, ...props }, ref) => (
+ |
+))
+TableCell.displayName = "TableCell"
+
+const TableCaption = React.forwardRef<
+ HTMLTableCaptionElement,
+ React.HTMLAttributes
+>(({ className, ...props }, ref) => (
+
+))
+TableCaption.displayName = "TableCaption"
+
+export {
+ Table,
+ TableHeader,
+ TableBody,
+ TableFooter,
+ TableHead,
+ TableRow,
+ TableCell,
+ TableCaption,
+}
diff --git a/src/types/index.ts b/src/types/index.ts
index bd1bb75..3eedd6c 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -1,3 +1,5 @@
+import type { ColumnDef } from "@tanstack/react-table";
+
export type PaperlessSearchType = {
total: number;
documents: {
@@ -104,3 +106,18 @@ export type AdviceAPIType = {
advice: string;
};
};
+
+export const columns: ColumnDef[] = [
+ {
+ accessorKey: "name",
+ header: "Name",
+ },
+ {
+ accessorKey: "status",
+ header: "Status",
+ },
+ {
+ accessorKey: "link",
+ header: "Link",
+ },
+];