Skip to content

Commit

Permalink
feat: Initial gui (#1842)
Browse files Browse the repository at this point in the history
### What problem does this PR solve?

feat: Initial gui

Issue link:#1841

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
  • Loading branch information
cike8899 authored Sep 10, 2024
1 parent 417e110 commit 04accd1
Show file tree
Hide file tree
Showing 44 changed files with 7,868 additions and 0 deletions.
37 changes: 37 additions & 0 deletions gui/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
.pnpm-debug.log*

# env files
.env*
!.env.example

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
2 changes: 2 additions & 0 deletions gui/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
registry=https://registry.npmmirror.com/

6 changes: 6 additions & 0 deletions gui/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
## run project

```
pnpm install
pnpm dev
```
10 changes: 10 additions & 0 deletions gui/app/(dashboard)/actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
'use server';

import { deleteProductById } from '@/lib/db';
import { revalidatePath } from 'next/cache';

export async function deleteProduct(formData: FormData) {
// let id = Number(formData.get('id'));
// await deleteProductById(id);
// revalidatePath('/');
}
19 changes: 19 additions & 0 deletions gui/app/(dashboard)/customers/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {
Card,
CardContent,
CardDescription,
CardHeader,
CardTitle
} from '@/components/ui/card';

export default function CustomersPage() {
return (
<Card>
<CardHeader>
<CardTitle>Customers</CardTitle>
<CardDescription>View all customers and their orders.</CardDescription>
</CardHeader>
<CardContent></CardContent>
</Card>
);
}
26 changes: 26 additions & 0 deletions gui/app/(dashboard)/database/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs';
import { File, PlusCircle } from 'lucide-react';
import { Button } from '@/components/ui/button';

export default async function ProductsPage({
searchParams
}: {
searchParams: { q: string; offset: string };
}) {
const search = searchParams.q ?? '';
const offset = searchParams.offset ?? 0;
// const { products, newOffset, totalProducts } = await getProducts(
// search,
// Number(offset)
// );

const ret = await fetch('http://localhost:3000/products');
const products = await ret.json();

const { newOffset, totalProducts } = {
newOffset: 0,
totalProducts: 0
};

return <div>database</div>;
}
46 changes: 46 additions & 0 deletions gui/app/(dashboard)/error.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
'use client';

import { useEffect } from 'react';

export default function Error({
error,
reset
}: {
error: Error & { digest?: string };
reset: () => void;
}) {
useEffect(() => {
// Log the error to an error reporting service
console.error(error);
}, [error]);

return (
<main className="p-4 md:p-6">
<div className="mb-8 space-y-4">
<h1 className="font-semibold text-lg md:text-2xl">
Please complete setup
</h1>
<p>
Inside the Vercel Postgres dashboard, create a table based on the
schema defined in this repository.
</p>
<pre className="my-4 px-3 py-4 bg-black text-white rounded-lg max-w-2xl overflow-scroll flex text-wrap">
<code>
{`CREATE TABLE users (
id SERIAL PRIMARY KEY,
email VARCHAR(255) NOT NULL,
name VARCHAR(255),
username VARCHAR(255)
);`}
</code>
</pre>
<p>Insert a row for testing:</p>
<pre className="my-4 px-3 py-4 bg-black text-white rounded-lg max-w-2xl overflow-scroll flex text-wrap">
<code>
{`INSERT INTO users (id, email, name, username) VALUES (1, '[email protected]', 'Me', 'username');`}
</code>
</pre>
</div>
</main>
);
}
192 changes: 192 additions & 0 deletions gui/app/(dashboard)/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
import Link from 'next/link';
import {
Home,
LineChart,
Package,
Package2,
PanelLeft,
Settings,
ShoppingCart,
Users2
} from 'lucide-react';

import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator
} from '@/components/ui/breadcrumb';
import { Button } from '@/components/ui/button';
import { Sheet, SheetContent, SheetTrigger } from '@/components/ui/sheet';
import {
Tooltip,
TooltipContent,
TooltipTrigger
} from '@/components/ui/tooltip';
import { Analytics } from '@vercel/analytics/react';
import { User } from './user';
import Providers from './providers';
import { NavItem } from './nav-item';
import { SearchInput } from './search';
import Logo from '/logo.svg';

export default function DashboardLayout({
children
}: {
children: React.ReactNode;
}) {
return (
<Providers>
<main className="flex min-h-screen w-full flex-col bg-muted/40">
<DesktopNav />
<div className="flex flex-col sm:gap-4 sm:py-4 sm:pl-14">
<header className="sticky top-0 z-30 flex h-14 items-center gap-4 border-b bg-background px-4 sm:static sm:h-auto sm:border-0 sm:bg-transparent sm:px-6">
<MobileNav />
<DashboardBreadcrumb />
<SearchInput />
<User />
</header>
<main className="grid flex-1 items-start gap-2 p-4 sm:px-6 sm:py-0 md:gap-4 bg-muted/40">
{children}
</main>
</div>
<Analytics />
</main>
</Providers>
);
}

function DesktopNav() {
return (
<aside className="fixed inset-y-0 left-0 z-10 hidden w-14 flex-col border-r bg-background sm:flex">
<nav className="flex flex-col items-center gap-4 px-2 sm:py-5">
<Link
href="https://github.com/infiniflow"
className="group flex h-9 shrink-0 items-center justify-center gap-2 rounded-full text-lg font-semibold text-primary-foreground md:h-8 md:text-base"
>
<Logo></Logo>
{/* <span className="sr-only">Acme Inc</span> */}
</Link>

<NavItem href="#" label="Dashboard">
<Home className="h-5 w-5" />
</NavItem>

<NavItem href="#" label="Orders">
<ShoppingCart className="h-5 w-5" />
</NavItem>

<NavItem href="/" label="Products">
<Package className="h-5 w-5" />
</NavItem>

<NavItem href="/customers" label="Customers">
<Users2 className="h-5 w-5" />
</NavItem>

<NavItem href="#" label="Analytics">
<LineChart className="h-5 w-5" />
</NavItem>
</nav>
<nav className="mt-auto flex flex-col items-center gap-4 px-2 sm:py-5">
<Tooltip>
<TooltipTrigger asChild>
<Link
href="#"
className="flex h-9 w-9 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:text-foreground md:h-8 md:w-8"
>
<Settings className="h-5 w-5" />
<span className="sr-only">Settings</span>
</Link>
</TooltipTrigger>
<TooltipContent side="right">Settings</TooltipContent>
</Tooltip>
</nav>
</aside>
);
}

function MobileNav() {
return (
<Sheet>
<SheetTrigger asChild>
<Button size="icon" variant="outline" className="sm:hidden">
<PanelLeft className="h-5 w-5" />
<span className="sr-only">Toggle Menu</span>
</Button>
</SheetTrigger>
<SheetContent side="left" className="sm:max-w-xs">
<nav className="grid gap-6 text-lg font-medium">
<Link
href="#"
className="group flex h-10 w-10 shrink-0 items-center justify-center gap-2 rounded-full bg-primary text-lg font-semibold text-primary-foreground md:text-base"
>
<Package2 className="h-5 w-5 transition-all group-hover:scale-110" />
<span className="sr-only">Vercel</span>
</Link>
<Link
href="#"
className="flex items-center gap-4 px-2.5 text-muted-foreground hover:text-foreground"
>
<Home className="h-5 w-5" />
Dashboard
</Link>
<Link
href="#"
className="flex items-center gap-4 px-2.5 text-muted-foreground hover:text-foreground"
>
<ShoppingCart className="h-5 w-5" />
Orders
</Link>
<Link
href="#"
className="flex items-center gap-4 px-2.5 text-foreground"
>
<Package className="h-5 w-5" />
Products
</Link>
<Link
href="#"
className="flex items-center gap-4 px-2.5 text-muted-foreground hover:text-foreground"
>
<Users2 className="h-5 w-5" />
Customers
</Link>
<Link
href="#"
className="flex items-center gap-4 px-2.5 text-muted-foreground hover:text-foreground"
>
<LineChart className="h-5 w-5" />
Settings
</Link>
</nav>
</SheetContent>
</Sheet>
);
}

function DashboardBreadcrumb() {
return (
<Breadcrumb className="hidden md:flex">
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink asChild>
<Link href="#">Dashboard</Link>
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink asChild>
<Link href="#">Products</Link>
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>All Products</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
);
}
42 changes: 42 additions & 0 deletions gui/app/(dashboard)/nav-item.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
'use client';

import {
Tooltip,
TooltipContent,
TooltipTrigger
} from '@/components/ui/tooltip';
import clsx from 'clsx';
import Link from 'next/link';
import { usePathname } from 'next/navigation';

export function NavItem({
href,
label,
children
}: {
href: string;
label: string;
children: React.ReactNode;
}) {
const pathname = usePathname();

return (
<Tooltip>
<TooltipTrigger asChild>
<Link
href={href}
className={clsx(
'flex h-9 w-9 items-center justify-center rounded-lg text-muted-foreground transition-colors hover:text-foreground md:h-8 md:w-8',
{
'bg-accent text-black': pathname === href
}
)}
>
{children}
<span className="sr-only">{label}</span>
</Link>
</TooltipTrigger>
<TooltipContent side="right">{label}</TooltipContent>
</Tooltip>
);
}
Loading

0 comments on commit 04accd1

Please sign in to comment.