From 1034ddbb592c61a5aa37623f4dab73e18f0264ff Mon Sep 17 00:00:00 2001 From: balibabu Date: Tue, 15 Oct 2024 13:56:16 +0800 Subject: [PATCH] feat: Modify error page #1841 (#2045) ### What problem does this PR solve? feat: Modify error page #1841 ### Type of change - [x] New Feature (non-breaking change which adds functionality) --- gui/app/(dashboard)/actions.ts | 33 +-- .../[databaseId]/table/[tableId]/columns.tsx | 91 -------- .../[databaseId]/table/[tableId]/page.tsx | 6 +- gui/app/(dashboard)/database/hooks.ts | 14 +- gui/app/(dashboard)/database/layout.tsx | 2 +- gui/app/(dashboard)/database/tree.tsx | 23 +- gui/app/(dashboard)/databases/page.tsx | 37 +--- gui/app/(dashboard)/error.tsx | 13 +- gui/app/(dashboard)/page.tsx | 20 +- gui/app/(dashboard)/search.tsx | 10 +- gui/app/(dashboard)/system/page.tsx | 17 +- gui/app/(dashboard)/system/product.tsx | 49 ----- gui/app/(dashboard)/system/products-table.tsx | 113 ---------- gui/app/(dashboard)/tables/context-menu.tsx | 6 +- gui/app/(dashboard)/tables/page.tsx | 13 +- .../tables/table-creating-dialog.tsx | 2 +- .../tables/table-creating-form.tsx | 4 +- gui/app/(dashboard)/user.tsx | 8 +- gui/app/api/seed/route.ts | 207 +++++++++--------- gui/app/layout.tsx | 5 +- gui/components/hooks/use-toast.ts | 1 + gui/components/ui/button.tsx | 7 +- gui/components/ui/input.tsx | 4 +- gui/components/ui/side-menu.tsx | 2 +- gui/lib/databse-interface.ts | 4 +- gui/lib/interfaces.ts | 2 +- gui/lib/request.ts | 9 +- gui/lib/utils.ts | 5 + 28 files changed, 197 insertions(+), 510 deletions(-) delete mode 100644 gui/app/(dashboard)/database/[databaseId]/table/[tableId]/columns.tsx delete mode 100644 gui/app/(dashboard)/system/product.tsx delete mode 100644 gui/app/(dashboard)/system/products-table.tsx diff --git a/gui/app/(dashboard)/actions.ts b/gui/app/(dashboard)/actions.ts index 0d9a88da68..5fd3c3281f 100644 --- a/gui/app/(dashboard)/actions.ts +++ b/gui/app/(dashboard)/actions.ts @@ -8,6 +8,8 @@ import { ITableSegment } from '@/lib/databse-interface'; import { drop, get, post } from '@/lib/request'; +import { isResponseListExist } from '@/lib/utils'; +import { unstable_rethrow } from 'next/navigation'; export const listDatabase = async () => { try { @@ -15,7 +17,8 @@ export const listDatabase = async () => { console.log('🚀 ~ x:', x); return x; } catch (error) { - console.log('🚀 ~ error:', error); + unstable_rethrow(error); + return { databases: [] }; } }; @@ -142,6 +145,8 @@ export const showConfigs = async () => { return x; } catch (error) { console.log('🚀 ~ error:', error); + unstable_rethrow(error); + return {}; } }; @@ -150,16 +155,9 @@ export const showVariables = async () => { const x = await get(`${ApiUrl.variables}/global`); return x; } catch (error) { + unstable_rethrow(error); console.log('🚀 ~ error:', error); - } -}; - -export const showCurrentNode = async () => { - try { - const x = await get(`${ApiUrl.variables}/global`); - return x; - } catch (error) { - console.log('🚀 ~ error:', error); + return {}; } }; @@ -174,11 +172,12 @@ export const showTableColumns = async ({ const x = await get( `${ApiUrl.databases}/${database_name}/${ApiUrl.tables}/${table_name}/${ApiUrl.columns}` ); - if (x.error_code === 0) { + if (isResponseListExist(x, 'columns')) { return x.columns; } return []; - } catch (error) { + } catch (error: unknown) { + console.log('🚀 ~ error:', error); return []; } }; @@ -194,11 +193,12 @@ export const showTableIndexes = async ({ const x = await get( `${ApiUrl.databases}/${database_name}/${ApiUrl.tables}/${table_name}/${ApiUrl.indexes}` ); - if (x.error_code === 0) { + if (isResponseListExist(x, 'indexes')) { return x.indexes; } return []; - } catch (error) { + } catch (error: unknown) { + console.log('🚀 ~ error:', error); return []; } }; @@ -214,11 +214,12 @@ export const showTableSegments = async ({ const x = await get( `${ApiUrl.databases}/${database_name}/${ApiUrl.tables}/${table_name}/${ApiUrl.segments}` ); - if (x.error_code === 0) { + if (isResponseListExist(x, 'segments')) { return x?.segments ?? []; } return []; - } catch (error) { + } catch (error: unknown) { + console.log('🚀 ~ error:', error); return []; } }; diff --git a/gui/app/(dashboard)/database/[databaseId]/table/[tableId]/columns.tsx b/gui/app/(dashboard)/database/[databaseId]/table/[tableId]/columns.tsx deleted file mode 100644 index 592a8cf9da..0000000000 --- a/gui/app/(dashboard)/database/[databaseId]/table/[tableId]/columns.tsx +++ /dev/null @@ -1,91 +0,0 @@ -import { - Table, - TableBody, - TableCaption, - TableCell, - TableFooter, - TableHead, - TableHeader, - TableRow -} from '@/components/ui/table'; -import { DatabaseRouteParams } from 'app/(dashboard)/database/interface'; - -const invoices = [ - { - invoice: 'INV001', - paymentStatus: 'Paid', - totalAmount: '$250.00', - paymentMethod: 'Credit Card' - }, - { - invoice: 'INV002', - paymentStatus: 'Pending', - totalAmount: '$150.00', - paymentMethod: 'PayPal' - }, - { - invoice: 'INV003', - paymentStatus: 'Unpaid', - totalAmount: '$350.00', - paymentMethod: 'Bank Transfer' - }, - { - invoice: 'INV004', - paymentStatus: 'Paid', - totalAmount: '$450.00', - paymentMethod: 'Credit Card' - }, - { - invoice: 'INV005', - paymentStatus: 'Paid', - totalAmount: '$550.00', - paymentMethod: 'PayPal' - }, - { - invoice: 'INV006', - paymentStatus: 'Pending', - totalAmount: '$200.00', - paymentMethod: 'Bank Transfer' - }, - { - invoice: 'INV007', - paymentStatus: 'Unpaid', - totalAmount: '$300.00', - paymentMethod: 'Credit Card' - } -]; - -export function TableColumns({ - tableId, - databaseId -}: DatabaseRouteParams['params']) { - return ( - - TableColumns - - - Invoice - Status - Method - Amount - - - - {invoices.map((invoice) => ( - - {invoice.invoice} - {invoice.paymentStatus} - {invoice.paymentMethod} - {invoice.totalAmount} - - ))} - - - - Total - $2,500.00 - - -
- ); -} diff --git a/gui/app/(dashboard)/database/[databaseId]/table/[tableId]/page.tsx b/gui/app/(dashboard)/database/[databaseId]/table/[tableId]/page.tsx index acf0a7dccf..f8a0ee0043 100644 --- a/gui/app/(dashboard)/database/[databaseId]/table/[tableId]/page.tsx +++ b/gui/app/(dashboard)/database/[databaseId]/table/[tableId]/page.tsx @@ -12,12 +12,16 @@ const TableMap = { [Leaf.Segments]: TableSegments }; +const Empty = () => { + return
empty
; +}; + export default async function DatabasePage({ searchParams: { tab }, params: { tableId, databaseId } }: DatabaseRouteParams) { const DatabaseTable: React.FunctionComponent = - TableMap[tab]; + TableMap[tab] ?? Empty; return (
diff --git a/gui/app/(dashboard)/database/hooks.ts b/gui/app/(dashboard)/database/hooks.ts index b57ee89a83..80a9f56b46 100644 --- a/gui/app/(dashboard)/database/hooks.ts +++ b/gui/app/(dashboard)/database/hooks.ts @@ -39,7 +39,7 @@ export const useHandleClickTreeName = () => { } } }, - [] + [router] ); return { handleClickTreeName }; @@ -55,7 +55,7 @@ export const useBuildTreeData = () => { try { setLoading(true); const ret = await listDatabase(); - if (ret.databases.length > 0) { + if (ret.databases?.length > 0) { setData( updateTreeData( [ @@ -125,7 +125,7 @@ export const useBuildTreeData = () => { }, [fetchDatabases]); const onLoadData = async ({ element }: { element: INode }) => { - if (element.children.length > 0) { + if (element?.children?.length > 0) { return; } @@ -157,7 +157,7 @@ export const useBuildTreeData = () => { }; const wrappedOnLoadData = async (props: ITreeViewOnLoadDataProps) => { - const nodeHasNoChildData = props.element.children.length === 0; + const nodeHasNoChildData = props.element.children?.length === 0; const nodeHasAlreadyBeenLoaded = nodesAlreadyLoaded.find( (e) => e.id === props.element.id ); @@ -196,7 +196,7 @@ export const useFetchTableColumns = ({ }); setTableColumns(data); - }, []); + }, [databaseId, tableId]); useEffect(() => { fetchTableColumns(); @@ -218,7 +218,7 @@ export const useFetchTableIndexes = ({ }); setTableIndexes(data); - }, []); + }, [databaseId, tableId]); useEffect(() => { fetchTableIndexes(); @@ -240,7 +240,7 @@ export const useFetchTableSegments = ({ }); setTableSegments(data); - }, []); + }, [databaseId, tableId]); useEffect(() => { fetchTableSegments(); diff --git a/gui/app/(dashboard)/database/layout.tsx b/gui/app/(dashboard)/database/layout.tsx index d851c97548..e000712df5 100644 --- a/gui/app/(dashboard)/database/layout.tsx +++ b/gui/app/(dashboard)/database/layout.tsx @@ -9,7 +9,7 @@ export default async function DatabaseLayout({ children: React.ReactNode; }) { return ( -
+
diff --git a/gui/app/(dashboard)/database/tree.tsx b/gui/app/(dashboard)/database/tree.tsx index a7cea43447..e2bf9b77a6 100644 --- a/gui/app/(dashboard)/database/tree.tsx +++ b/gui/app/(dashboard)/database/tree.tsx @@ -59,7 +59,7 @@ function AsyncTree() { const branchNode = (isExpanded: boolean, element: INode) => { return isExpanded && !element.metadata?.isEmpty && - element.children.length === 0 ? ( + element.children?.length === 0 ? ( <> {isBranch && branchNode(isExpanded, element)} -
+
{renderIcon(level, element.name)} {element.name}
diff --git a/gui/app/(dashboard)/databases/page.tsx b/gui/app/(dashboard)/databases/page.tsx index 6d7c355fc6..ca7e4ab375 100644 --- a/gui/app/(dashboard)/databases/page.tsx +++ b/gui/app/(dashboard)/databases/page.tsx @@ -1,51 +1,18 @@ import { Card, CardHeader, CardTitle } from '@/components/ui/card'; import AddIcon from '/public/add.svg'; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue -} from '@radix-ui/react-select'; import { listDatabase } from '../actions'; import { DatabaseCard } from '../database-card'; import { DatabaseCreatingDialog } from '../database-creating-dialog'; -interface IDatabaseSelectProps { - placeholder?: string; - options: Array<{ label: string; value: string }>; -} - -export function DatabaseSelect({ placeholder, options }: IDatabaseSelectProps) { - return ( - - ); -} - -export default async function HomePage({ - searchParams -}: { +export default async function HomePage({}: { searchParams: { q: string; offset: string }; }) { const ret = await listDatabase(); - const search = searchParams.q ?? ''; - const offset = searchParams.offset ?? 0; return (
- {ret.databases.map((x: string, idx: number) => ( + {ret?.databases?.map((x: string, idx: number) => ( ))} diff --git a/gui/app/(dashboard)/error.tsx b/gui/app/(dashboard)/error.tsx index 66bcfca317..cd279cf9c4 100644 --- a/gui/app/(dashboard)/error.tsx +++ b/gui/app/(dashboard)/error.tsx @@ -3,8 +3,7 @@ import { useEffect } from 'react'; export default function Error({ - error, - reset + error }: { error: Error & { digest?: string }; reset: () => void; @@ -15,12 +14,12 @@ export default function Error({ }, [error]); return ( -
+
-

- Please complete setup +

+ Connection failed

-

+ {/*

Inside the Vercel Postgres dashboard, create a table based on the schema defined in this repository.

@@ -39,7 +38,7 @@ export default function Error({ {`INSERT INTO users (id, email, name, username) VALUES (1, 'me@site.com', 'Me', 'username');`} - + */}
); diff --git a/gui/app/(dashboard)/page.tsx b/gui/app/(dashboard)/page.tsx index bed4ec14de..3c06fec619 100644 --- a/gui/app/(dashboard)/page.tsx +++ b/gui/app/(dashboard)/page.tsx @@ -8,27 +8,9 @@ import { import { showConfigs, showVariables } from './actions'; // import { getProducts } from '@/lib/db'; -export default async function ProductsPage({ - searchParams -}: { - searchParams: { q: string; offset: string }; -}) { - const search = searchParams.q ?? ''; - const offset = searchParams.offset ?? 0; +export default async function ProductsPage() { const configs = await showConfigs(); const variables = await showVariables(); - // const { products, newOffset, totalProducts } = await getProducts( - // search, - // Number(offset) - // ); - console.log(variables); - // const products = await request('http://localhost:3000/products'); - - const { newOffset, totalProducts, products } = { - newOffset: 0, - totalProducts: 0, - products: [] - }; return (
diff --git a/gui/app/(dashboard)/search.tsx b/gui/app/(dashboard)/search.tsx index 8d106bbd09..70ba2d60dd 100644 --- a/gui/app/(dashboard)/search.tsx +++ b/gui/app/(dashboard)/search.tsx @@ -1,18 +1,18 @@ 'use client'; -import { useTransition } from 'react'; -import { useRouter } from 'next/navigation'; -import { Input } from '@/components/ui/input'; import { Spinner } from '@/components/icons'; +import { Input } from '@/components/ui/input'; import { Search } from 'lucide-react'; +import { useRouter } from 'next/navigation'; +import { useTransition } from 'react'; export function SearchInput() { const router = useRouter(); const [isPending, startTransition] = useTransition(); function searchAction(formData: FormData) { - let value = formData.get('q') as string; - let params = new URLSearchParams({ q: value }); + const value = formData.get('q') as string; + const params = new URLSearchParams({ q: value }); startTransition(() => { router.replace(`/?${params.toString()}`); }); diff --git a/gui/app/(dashboard)/system/page.tsx b/gui/app/(dashboard)/system/page.tsx index 2e497d8787..4639761731 100644 --- a/gui/app/(dashboard)/system/page.tsx +++ b/gui/app/(dashboard)/system/page.tsx @@ -8,27 +8,12 @@ import { import { showConfigs, showVariables } from '../actions'; // import { getProducts } from '@/lib/db'; -export default async function ProductsPage({ - searchParams -}: { +export default async function ProductsPage({}: { searchParams: { q: string; offset: string }; }) { - const search = searchParams.q ?? ''; - const offset = searchParams.offset ?? 0; const configs = await showConfigs(); const variables = await showVariables(); - // const { products, newOffset, totalProducts } = await getProducts( - // search, - // Number(offset) - // ); console.log(variables); - // const products = await request('http://localhost:3000/products'); - - const { newOffset, totalProducts, products } = { - newOffset: 0, - totalProducts: 0, - products: [] - }; return (
diff --git a/gui/app/(dashboard)/system/product.tsx b/gui/app/(dashboard)/system/product.tsx deleted file mode 100644 index a4981c4782..0000000000 --- a/gui/app/(dashboard)/system/product.tsx +++ /dev/null @@ -1,49 +0,0 @@ -import { Badge } from '@/components/ui/badge'; -import { Button } from '@/components/ui/button'; -import { - DropdownMenu, - DropdownMenuContent, - DropdownMenuItem, - DropdownMenuLabel, - DropdownMenuTrigger -} from '@/components/ui/dropdown-menu'; -import { TableCell, TableRow } from '@/components/ui/table'; -import { MoreHorizontal } from 'lucide-react'; -// import { SelectProduct } from '@/lib/db'; - -export function Product({ product }: { product: any }) { - return ( - - {product.name} - - - {product.status} - - - {`$${product.price}`} - {product.stock} - - {product.availableAt} - - - - - - - - Actions - Edit - -
- -
-
-
-
-
-
- ); -} diff --git a/gui/app/(dashboard)/system/products-table.tsx b/gui/app/(dashboard)/system/products-table.tsx deleted file mode 100644 index c152c97c8e..0000000000 --- a/gui/app/(dashboard)/system/products-table.tsx +++ /dev/null @@ -1,113 +0,0 @@ -'use client'; - -import { - Card, - CardContent, - CardDescription, - CardFooter, - CardHeader, - CardTitle -} from '@/components/ui/card'; -import { - Table, - TableBody, - TableHead, - TableHeader, - TableRow -} from '@/components/ui/table'; -import { Product } from './product'; -// import { SelectProduct } from '@/lib/db'; -import { Button } from '@/components/ui/button'; -import { ChevronLeft, ChevronRight } from 'lucide-react'; -import { useRouter } from 'next/navigation'; - -export function ProductsTable({ - products, - offset, - totalProducts -}: { - products: any[]; - offset: number; - totalProducts: number; -}) { - let router = useRouter(); - let productsPerPage = 5; - - function prevPage() { - router.back(); - } - - function nextPage() { - router.push(`/?offset=${offset}`, { scroll: false }); - } - - return ( - - - Products - - Manage your products and view their sales performance. - - - - - - - - Image - - Name - Status - Price - - Total Sales - - Created at - - Actions - - - - - {products.map((product) => ( - - ))} - -
-
- -
-
- Showing{' '} - - {Math.min(offset - productsPerPage, totalProducts) + 1}-{offset} - {' '} - of {totalProducts} products -
-
- - -
-
-
-
- ); -} diff --git a/gui/app/(dashboard)/tables/context-menu.tsx b/gui/app/(dashboard)/tables/context-menu.tsx index 95c5b40c02..b198fc6662 100644 --- a/gui/app/(dashboard)/tables/context-menu.tsx +++ b/gui/app/(dashboard)/tables/context-menu.tsx @@ -8,11 +8,7 @@ import { useSeDialogState } from '@/lib/hooks'; import { TableCreatingDialog } from './table-creating-dialog'; import AddIcon from '/public/add.svg'; -export function InfinityContextMenuContent({ - databaseName -}: { - databaseName: string; -}) { +export function InfinityContextMenuContent({}: { databaseName: string }) { const { showDialog, visible, hideDialog, switchVisible } = useSeDialogState(); return ( <> diff --git a/gui/app/(dashboard)/tables/page.tsx b/gui/app/(dashboard)/tables/page.tsx index 374113d54d..8ca62edc8a 100644 --- a/gui/app/(dashboard)/tables/page.tsx +++ b/gui/app/(dashboard)/tables/page.tsx @@ -30,14 +30,9 @@ async function InfinityTable() { ); } -export default async function DatabasePage({ - searchParams -}: { +export default async function DatabasePage({}: { searchParams: { q: string; offset: string }; }) { - const search = searchParams.q ?? ''; - const offset = searchParams.offset ?? 0; - const items: MenuItem[] = [ { key: 'sub1', @@ -56,14 +51,14 @@ export default async function DatabasePage({ ]; const ret = await listDatabase(); - if (ret.databases.length > 1) { - const latestDatabase = ret.databases.at(-1); + if (ret.databases?.length > 1) { + const latestDatabase = ret.databases?.at(-1); const tables = await listTable(latestDatabase); console.log('🚀 ~ ret:', tables); items.push({ key: latestDatabase, label: latestDatabase, - children: tables.tables + children: tables?.tables ?? [] }); } diff --git a/gui/app/(dashboard)/tables/table-creating-dialog.tsx b/gui/app/(dashboard)/tables/table-creating-dialog.tsx index f99be95179..9d5b695873 100644 --- a/gui/app/(dashboard)/tables/table-creating-dialog.tsx +++ b/gui/app/(dashboard)/tables/table-creating-dialog.tsx @@ -18,7 +18,7 @@ export function TableCreatingDialog({ visible, switchVisible, hideDialog -}: React.PropsWithChildren>) { +}: React.PropsWithChildren>) { return ( {children} diff --git a/gui/app/(dashboard)/tables/table-creating-form.tsx b/gui/app/(dashboard)/tables/table-creating-form.tsx index d66302bfb8..696782a00c 100644 --- a/gui/app/(dashboard)/tables/table-creating-form.tsx +++ b/gui/app/(dashboard)/tables/table-creating-form.tsx @@ -26,12 +26,12 @@ import { CreateOption } from '@/lib/constant/common'; import { createDatabase } from '../actions'; export const FormSchema = z.object({ - name: z + database_name: z .string({ required_error: 'Please input name' }) .trim(), - fields: z.array(), + // fields: z.array(), create_option: z.nativeEnum(CreateOption) }); diff --git a/gui/app/(dashboard)/user.tsx b/gui/app/(dashboard)/user.tsx index 24755de369..08d7a7d988 100644 --- a/gui/app/(dashboard)/user.tsx +++ b/gui/app/(dashboard)/user.tsx @@ -1,6 +1,4 @@ import { Button } from '@/components/ui/button'; -import { auth, signOut } from '@/lib/auth'; -import Image from 'next/image'; import { DropdownMenu, DropdownMenuContent, @@ -9,11 +7,13 @@ import { DropdownMenuSeparator, DropdownMenuTrigger } from '@/components/ui/dropdown-menu'; +import { auth, signOut } from '@/lib/auth'; +import Image from 'next/image'; import Link from 'next/link'; export async function User() { - let session = await auth(); - let user = session?.user; + const session = await auth(); + const user = session?.user; return ( diff --git a/gui/app/api/seed/route.ts b/gui/app/api/seed/route.ts index 725f1d7806..643603c077 100644 --- a/gui/app/api/seed/route.ts +++ b/gui/app/api/seed/route.ts @@ -1,4 +1,4 @@ -import { db, products } from 'lib/db'; +// import { db, products } from 'lib/db'; export const dynamic = 'force-dynamic'; @@ -6,107 +6,106 @@ export async function GET() { // return Response.json({ // message: 'Uncomment to seed data after DB is set up.' // }); - - await db.insert(products).values([ - { - id: 1, - imageUrl: - 'https://uwja77bygk2kgfqe.public.blob.vercel-storage.com/smartphone-gaPvyZW6aww0IhD3dOpaU6gBGILtcJ.webp', - name: 'Smartphone X Pro', - status: 'active', - price: '999.00', - stock: 150, - availableAt: new Date() - }, - { - id: 2, - imageUrl: - 'https://uwja77bygk2kgfqe.public.blob.vercel-storage.com/earbuds-3rew4JGdIK81KNlR8Edr8NBBhFTOtX.webp', - name: 'Wireless Earbuds Ultra', - status: 'active', - price: '199.00', - stock: 300, - availableAt: new Date() - }, - { - id: 3, - imageUrl: - 'https://uwja77bygk2kgfqe.public.blob.vercel-storage.com/home-iTeNnmKSMnrykOS9IYyJvnLFgap7Vw.webp', - name: 'Smart Home Hub', - status: 'active', - price: '149.00', - stock: 200, - availableAt: new Date() - }, - { - id: 4, - imageUrl: - 'https://uwja77bygk2kgfqe.public.blob.vercel-storage.com/tv-H4l26crxtm9EQHLWc0ddrsXZ0V0Ofw.webp', - name: '4K Ultra HD Smart TV', - status: 'active', - price: '799.00', - stock: 50, - availableAt: new Date() - }, - { - id: 5, - imageUrl: - 'https://uwja77bygk2kgfqe.public.blob.vercel-storage.com/laptop-9bgUhjY491hkxiMDeSgqb9R5I3lHNL.webp', - name: 'Gaming Laptop Pro', - status: 'active', - price: '1299.00', - stock: 75, - availableAt: new Date() - }, - { - id: 6, - imageUrl: - 'https://uwja77bygk2kgfqe.public.blob.vercel-storage.com/headset-lYnRnpjDbZkB78lS7nnqEJFYFAUDg6.webp', - name: 'VR Headset Plus', - status: 'active', - price: '349.00', - stock: 120, - availableAt: new Date() - }, - { - id: 7, - imageUrl: - 'https://uwja77bygk2kgfqe.public.blob.vercel-storage.com/watch-S2VeARK6sEM9QFg4yNQNjHFaHc3sXv.webp', - name: 'Smartwatch Elite', - status: 'active', - price: '249.00', - stock: 250, - availableAt: new Date() - }, - { - id: 8, - imageUrl: - 'https://uwja77bygk2kgfqe.public.blob.vercel-storage.com/speaker-4Zk0Ctx5AvxnwNNTFWVK4Gtpru4YEf.webp', - name: 'Bluetooth Speaker Max', - status: 'active', - price: '99.00', - stock: 400, - availableAt: new Date() - }, - { - id: 9, - imageUrl: - 'https://uwja77bygk2kgfqe.public.blob.vercel-storage.com/charger-GzRr0NSkCj0ZYWkTMvxXGZQu47w9r5.webp', - name: 'Portable Charger Super', - status: 'active', - price: '59.00', - stock: 500, - availableAt: new Date() - }, - { - id: 10, - imageUrl: - 'https://uwja77bygk2kgfqe.public.blob.vercel-storage.com/thermostat-8GnK2LDE3lZAjUVtiBk61RrSuqSTF7.webp', - name: 'Smart Thermostat Pro', - status: 'active', - price: '199.00', - stock: 175, - availableAt: new Date() - } - ]); + // await db.insert(products).values([ + // { + // id: 1, + // imageUrl: + // 'https://uwja77bygk2kgfqe.public.blob.vercel-storage.com/smartphone-gaPvyZW6aww0IhD3dOpaU6gBGILtcJ.webp', + // name: 'Smartphone X Pro', + // status: 'active', + // price: '999.00', + // stock: 150, + // availableAt: new Date() + // }, + // { + // id: 2, + // imageUrl: + // 'https://uwja77bygk2kgfqe.public.blob.vercel-storage.com/earbuds-3rew4JGdIK81KNlR8Edr8NBBhFTOtX.webp', + // name: 'Wireless Earbuds Ultra', + // status: 'active', + // price: '199.00', + // stock: 300, + // availableAt: new Date() + // }, + // { + // id: 3, + // imageUrl: + // 'https://uwja77bygk2kgfqe.public.blob.vercel-storage.com/home-iTeNnmKSMnrykOS9IYyJvnLFgap7Vw.webp', + // name: 'Smart Home Hub', + // status: 'active', + // price: '149.00', + // stock: 200, + // availableAt: new Date() + // }, + // { + // id: 4, + // imageUrl: + // 'https://uwja77bygk2kgfqe.public.blob.vercel-storage.com/tv-H4l26crxtm9EQHLWc0ddrsXZ0V0Ofw.webp', + // name: '4K Ultra HD Smart TV', + // status: 'active', + // price: '799.00', + // stock: 50, + // availableAt: new Date() + // }, + // { + // id: 5, + // imageUrl: + // 'https://uwja77bygk2kgfqe.public.blob.vercel-storage.com/laptop-9bgUhjY491hkxiMDeSgqb9R5I3lHNL.webp', + // name: 'Gaming Laptop Pro', + // status: 'active', + // price: '1299.00', + // stock: 75, + // availableAt: new Date() + // }, + // { + // id: 6, + // imageUrl: + // 'https://uwja77bygk2kgfqe.public.blob.vercel-storage.com/headset-lYnRnpjDbZkB78lS7nnqEJFYFAUDg6.webp', + // name: 'VR Headset Plus', + // status: 'active', + // price: '349.00', + // stock: 120, + // availableAt: new Date() + // }, + // { + // id: 7, + // imageUrl: + // 'https://uwja77bygk2kgfqe.public.blob.vercel-storage.com/watch-S2VeARK6sEM9QFg4yNQNjHFaHc3sXv.webp', + // name: 'Smartwatch Elite', + // status: 'active', + // price: '249.00', + // stock: 250, + // availableAt: new Date() + // }, + // { + // id: 8, + // imageUrl: + // 'https://uwja77bygk2kgfqe.public.blob.vercel-storage.com/speaker-4Zk0Ctx5AvxnwNNTFWVK4Gtpru4YEf.webp', + // name: 'Bluetooth Speaker Max', + // status: 'active', + // price: '99.00', + // stock: 400, + // availableAt: new Date() + // }, + // { + // id: 9, + // imageUrl: + // 'https://uwja77bygk2kgfqe.public.blob.vercel-storage.com/charger-GzRr0NSkCj0ZYWkTMvxXGZQu47w9r5.webp', + // name: 'Portable Charger Super', + // status: 'active', + // price: '59.00', + // stock: 500, + // availableAt: new Date() + // }, + // { + // id: 10, + // imageUrl: + // 'https://uwja77bygk2kgfqe.public.blob.vercel-storage.com/thermostat-8GnK2LDE3lZAjUVtiBk61RrSuqSTF7.webp', + // name: 'Smart Thermostat Pro', + // status: 'active', + // price: '199.00', + // stock: 175, + // availableAt: new Date() + // } + // ]); } diff --git a/gui/app/layout.tsx b/gui/app/layout.tsx index effcbbea6e..a6137d321e 100644 --- a/gui/app/layout.tsx +++ b/gui/app/layout.tsx @@ -4,9 +4,8 @@ import { Toaster } from '@/components/ui/toaster'; import { Analytics } from '@vercel/analytics/react'; export const metadata = { - title: 'Next.js App Router + NextAuth + Tailwind CSS', - description: - 'A user admin dashboard configured with Next.js, Postgres, NextAuth, Tailwind CSS, TypeScript, and Prettier.' + title: 'Infinity', + description: 'AI-native database for LLM | Infinity' }; export default function RootLayout({ diff --git a/gui/components/hooks/use-toast.ts b/gui/components/hooks/use-toast.ts index 79aa53c718..97b441ce0e 100644 --- a/gui/components/hooks/use-toast.ts +++ b/gui/components/hooks/use-toast.ts @@ -15,6 +15,7 @@ type ToasterToast = ToastProps & { action?: ToastActionElement; }; +// eslint-disable-next-line @typescript-eslint/no-unused-vars const actionTypes = { ADD_TOAST: 'ADD_TOAST', UPDATE_TOAST: 'UPDATE_TOAST', diff --git a/gui/components/ui/button.tsx b/gui/components/ui/button.tsx index 2c66fc7970..bd06c36d57 100644 --- a/gui/components/ui/button.tsx +++ b/gui/components/ui/button.tsx @@ -1,6 +1,6 @@ -import * as React from 'react'; import { Slot } from '@radix-ui/react-slot'; import { cva, type VariantProps } from 'class-variance-authority'; +import * as React from 'react'; import { cn } from '@/lib/utils'; @@ -37,7 +37,10 @@ export interface ButtonProps extends React.ButtonHTMLAttributes, VariantProps { asChild?: boolean; - formAction?: any; + formAction?: + | string + | React.DO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_FORM_ACTIONS[keyof React.DO_NOT_USE_OR_YOU_WILL_BE_FIRED_EXPERIMENTAL_FORM_ACTIONS] + | undefined; } const Button = React.forwardRef( diff --git a/gui/components/ui/input.tsx b/gui/components/ui/input.tsx index d2008f0b36..9505a3d686 100644 --- a/gui/components/ui/input.tsx +++ b/gui/components/ui/input.tsx @@ -3,7 +3,9 @@ import * as React from 'react'; import { cn } from '@/lib/utils'; export interface InputProps - extends React.InputHTMLAttributes {} + extends React.InputHTMLAttributes { + test?: string; +} const Input = React.forwardRef( ({ className, type, ...props }, ref) => { diff --git a/gui/components/ui/side-menu.tsx b/gui/components/ui/side-menu.tsx index 395cf35d55..f35955b162 100644 --- a/gui/components/ui/side-menu.tsx +++ b/gui/components/ui/side-menu.tsx @@ -7,7 +7,7 @@ import Link from 'next/link'; import { ReactNode } from 'react'; import { ContextMenu, ContextMenuTrigger } from './context-menu'; -function ChevronRightIcon(props: any) { +function ChevronRightIcon(props: React.SVGProps) { return ( = { +export type IResponseBody> = { error_code: number; } & { [U: string | number]: T }; export interface ITableColumns { name: string; type: string; - default: any; + default: unknown; } export interface ITableIndex { diff --git a/gui/lib/interfaces.ts b/gui/lib/interfaces.ts index 3f649723f6..c32bf6c825 100644 --- a/gui/lib/interfaces.ts +++ b/gui/lib/interfaces.ts @@ -4,5 +4,5 @@ export interface IDialogProps { switchVisible(): void; visible?: boolean; loading?: boolean; - onOk?(payload?: T): Promise | void; + onOk?(payload?: T): Promise | void; } diff --git a/gui/lib/request.ts b/gui/lib/request.ts index fe2ca7d95b..2e158a8e37 100644 --- a/gui/lib/request.ts +++ b/gui/lib/request.ts @@ -2,11 +2,11 @@ const baseUrl = 'http://127.0.0.1:23820/'; export const request = async ( url: string, - params: Record = {}, + params: Record = {}, method: string = 'GET' ) => { let nextUrl = `${baseUrl}${url}`; - const options: any = { + const options: RequestInit = { headers: { accept: 'application/json' }, @@ -15,7 +15,8 @@ export const request = async ( }; if (method === 'GET') { - nextUrl += '?' + new URLSearchParams(params).toString(); + nextUrl += + '?' + new URLSearchParams(params as Record).toString(); } else { options.body = JSON.stringify(params); } @@ -32,7 +33,7 @@ export const request = async ( export const get = (url: string, params?: Record) => request(url, params, 'GET'); -export const post = (url: string, params: Record) => +export const post = (url: string, params: Record) => request(url, params, 'POST'); export const drop = (url: string, params: Record) => diff --git a/gui/lib/utils.ts b/gui/lib/utils.ts index 9ad0df4269..a2999a258e 100644 --- a/gui/lib/utils.ts +++ b/gui/lib/utils.ts @@ -1,6 +1,11 @@ import { type ClassValue, clsx } from 'clsx'; import { twMerge } from 'tailwind-merge'; +import { IResponseBody } from './databse-interface'; export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)); } + +export const isResponseListExist = (response: IResponseBody, filed: string) => { + return response.error_code === 0 && Array.isArray(response[filed]); +};