Finished Hub ESLINT rule enforcement

This commit is contained in:
PxlLoewe
2025-07-09 23:26:09 -07:00
parent 98ed0cb5ca
commit eec72a51b8
26 changed files with 199 additions and 195 deletions

View File

@@ -11,10 +11,10 @@ export const CustomErrorBoundary = ({ children }: { children?: React.ReactNode }
let errorTest;
let errorCode = 500;
if ("statusCode" in error) {
errorCode = (error as any).statusCode;
errorCode = error.statusCode;
}
if ("message" in error || error instanceof Error) {
errorTest = (error as any).message;
errorTest = error.message;
} else if (typeof error === "string") {
errorTest = error;
} else {

View File

@@ -1,8 +1,9 @@
"use client";
import { useEffect, useState, useCallback, Ref, useImperativeHandle } from "react";
import { useState, Ref, useImperativeHandle } from "react";
import SortableTable, { Pagination, SortableTableProps } from "./Table";
import { PrismaClient } from "@repo/db";
import { getData } from "./pagiantedTableActions";
import { useDebounce } from "@repo/shared-components";
export interface PaginatedTableRef {
refresh: () => void;
@@ -10,9 +11,8 @@ export interface PaginatedTableRef {
interface PaginatedTableProps<TData> extends Omit<SortableTableProps<TData>, "data"> {
prismaModel: keyof PrismaClient;
filter?: Record<string, any>;
filter?: Record<string, unknown>;
rowsPerPage?: number;
showEditButton?: boolean;
searchFields?: string[];
include?: Record<string, boolean>;
strictQuery?: boolean;
@@ -26,7 +26,6 @@ interface PaginatedTableProps<TData> extends Omit<SortableTableProps<TData>, "da
export function PaginatedTable<TData>({
prismaModel,
rowsPerPage = 10,
showEditButton = false,
searchFields = [],
filter,
include,
@@ -42,7 +41,6 @@ export function PaginatedTable<TData>({
const [page, setPage] = useState(0);
const [total, setTotal] = useState(0);
const [searchTerm, setSearchTerm] = useState("");
const [debouncedSearchTerm, setDebouncedSearchTerm] = useState(searchTerm);
const [orderBy, setOrderBy] = useState<Record<string, "asc" | "desc">>(
restProps.initialOrderBy
? restProps.initialOrderBy.reduce(
@@ -60,16 +58,19 @@ export function PaginatedTable<TData>({
prismaModel,
rowsPerPage,
page * rowsPerPage,
debouncedSearchTerm,
searchTerm,
searchFields,
filter,
include,
orderBy,
strictQuery
? restProps.columns
.filter((col: any) => "accessorKey" in col)
.map((col: any) => col.accessorKey)
.reduce((acc: Record<string, any>, key: string) => {
.filter(
(col): col is { accessorKey: string } =>
typeof (col as { accessorKey?: unknown }).accessorKey === "string",
)
.map((col) => col.accessorKey)
.reduce<Record<string, boolean>>((acc, key) => {
acc[key] = true;
return acc;
}, {})
@@ -82,35 +83,20 @@ export function PaginatedTable<TData>({
});
};
useEffect(() => {
RefreshTableData();
}, [filter, orderBy]);
useImperativeHandle(ref, () => ({
refresh: () => {
RefreshTableData();
},
}));
const debounce = (func: Function, delay: number) => {
let timer: NodeJS.Timeout;
return (...args: any[]) => {
clearTimeout(timer);
timer = setTimeout(() => func(...args), delay);
};
};
const handleSearchChange = useCallback(
debounce((value: string) => {
setDebouncedSearchTerm(value);
}, 500),
[],
useDebounce(
() => {
RefreshTableData();
},
500,
[searchTerm, page, rowsPerPage, orderBy, filter],
);
useEffect(() => {
RefreshTableData();
}, [page, debouncedSearchTerm]);
return (
<div className="space-y-4 m-4">
<div className="flex items-center gap-2">
@@ -122,7 +108,6 @@ export function PaginatedTable<TData>({
value={searchTerm}
onChange={(e) => {
setSearchTerm(e.target.value);
handleSearchChange(e.target.value);
setPage(0); // Reset to first page on search
}}
className="input input-bordered w-full max-w-xs justify-end"
@@ -134,7 +119,6 @@ export function PaginatedTable<TData>({
<SortableTable
data={data}
prismaModel={prismaModel}
showEditButton={showEditButton}
setOrderBy={setOrderBy}
{...restProps}
/>

View File

@@ -3,7 +3,7 @@
import { toast } from "react-hot-toast";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { ReactNode, useEffect, useState } from "react";
import { ReactNode, useState } from "react";
export function QueryProvider({ children }: { children: ReactNode }) {
const [queryClient] = useState(

View File

@@ -9,13 +9,11 @@ import {
flexRender,
} from "@tanstack/react-table";
import { ArrowLeft, ArrowRight, ChevronDown, ChevronUp } from "lucide-react"; // Icons for sorting
import Link from "next/link";
import { PrismaClient } from "@repo/db";
export interface SortableTableProps<TData> {
data: TData[];
columns: ColumnDef<TData>[];
showEditButton?: boolean;
prismaModel?: keyof PrismaClient;
setOrderBy?: (orderBy: Record<string, "asc" | "desc">) => void;
initialOrderBy?: SortingState;
@@ -26,28 +24,13 @@ export default function SortableTable<TData>({
columns,
initialOrderBy = [],
prismaModel,
showEditButton,
setOrderBy,
}: SortableTableProps<TData>) {
const [sorting, setSorting] = useState<SortingState>(initialOrderBy);
const table = useReactTable({
data,
columns: showEditButton
? [
...columns,
{
header: "Actions",
cell: ({ row }) => (
<div className="flex items-center gap-1">
<Link href={`/admin/${prismaModel as string}/${(row.original as any).id}`}>
<button className="btn btn-sm">Edit</button>
</Link>
</div>
),
},
]
: columns,
columns,
getCoreRowModel: getCoreRowModel(),
getSortedRowModel: getSortedRowModel(),
onSortingChange: setSorting,

View File

@@ -15,7 +15,7 @@ export const Button = ({
return (
<button
{...(props as any)}
{...props}
className={cn("btn", props.className)}
disabled={isLoadingState || props.disabled}
onClick={async (e) => {
@@ -27,7 +27,7 @@ export const Button = ({
}}
>
{isLoadingState && <span className="loading loading-spinner loading-sm"></span>}
{props.children as any}
{props.children}
</button>
);
};

View File

@@ -1,32 +1,24 @@
import DatePicker, { DatePickerProps, registerLocale } from "react-datepicker";
import { Control, Controller, FieldValues, Path } from "react-hook-form";
import { de } from "date-fns/locale";
registerLocale("de", de);
import { formatDate } from "date-fns";
interface DateInputProps<T extends FieldValues>
extends Omit<DatePickerProps, "onChange" | "selected"> {
control: Control<T>;
name: Path<T>;
}
export const DateInput = <T extends FieldValues>({
control,
name,
export const DateInput = ({
value,
onChange,
...props
}: DateInputProps<T>) => {
}: Omit<React.InputHTMLAttributes<HTMLInputElement>, "value" | "onChange"> & {
value?: Date | null;
onChange?: (date: Date) => void;
}) => {
return (
<Controller
control={control}
name={name}
render={({ field }) => (
<DatePicker
className="input input-bordered mt-2"
locale={"de"}
onChange={(date) => field.onChange(date)}
selected={field.value}
{...props}
/>
)}
<input
type="datetime-local"
className="input"
value={formatDate(value || new Date(), "yyyy-MM-dd hh:mm")}
onChange={(e) => {
const date = e.target.value ? new Date(e.target.value) : null;
if (!date) return;
onChange?.(date);
}}
{...props}
/>
);
};