adding agent pages.

This commit is contained in:
killian-larcher
2024-11-10 23:12:38 +01:00
parent 84030dcba0
commit c76727f0d1
30 changed files with 627 additions and 8469 deletions
+1
View File
@@ -0,0 +1 @@
nodeLinker: "node-modules"
+5 -3
View File
@@ -1,11 +1,13 @@
"use client" "use client"
import {useSearchParams} from "next/navigation";
import {LoginForm} from "@/components/wrappers/Auth/Login/LoginForm/LoginForm";
import {useEffect, useRef} from "react"; import {useEffect, useRef} from "react";
import {useSearchParams} from "next/navigation";
import {LoginForm} from "@/components/wrappers/Auth/Login/LoginForm/LoginForm";
import {toast} from "sonner"; import {toast} from "sonner";
export default function SignInPage(props: { export default function SignInPage(props: {
searchParams: { callbackUrl: string | undefined } searchParams: Promise<{ callbackUrl: string | undefined }>
}) { }) {
const searchParams = useSearchParams(); const searchParams = useSearchParams();
@@ -0,0 +1,98 @@
import {PageParams} from "@/types/next";
import {Page, PageActions, PageContent, PageDescription, PageHeader, PageTitle} from "@/features/layout/page";
import {Button} from "@/components/ui/button";
import {Tabs, TabsContent, TabsList, TabsTrigger} from "@/components/ui/tabs";
import {Card, CardContent, CardHeader} from "@/components/ui/card";
import {Table, TableBody, TableCell, TableHead, TableHeader, TableRow} from "@/components/ui/table";
import { Badge } from "@/components/ui/badge"
export default async function RoutePage(props: PageParams<{}>) {
return (
<Page>
<PageHeader>
<PageTitle>
Agent 1
</PageTitle>
<PageActions>
<Button>Backup</Button>
<Button>Restore</Button>
</PageActions>
</PageHeader>
<PageDescription>My beautiful project!</PageDescription>
<PageContent>
<div className="flex flex-row sm:justify-between gap-6 mb-8">
<Card className="w-full">
<CardHeader>
Backups
</CardHeader>
<CardContent></CardContent>
</Card>
<Card className="w-full">
<CardHeader>
Success rate
</CardHeader>
<CardContent></CardContent>
</Card>
<Card className="w-full">
<CardHeader>
Last contact
</CardHeader>
<CardContent></CardContent>
</Card>
</div>
<Tabs defaultValue="backup">
<TabsList className="grid w-full grid-cols-2">
<TabsTrigger value="backup">Backup</TabsTrigger>
<TabsTrigger value="restore">Restore</TabsTrigger>
</TabsList>
<TabsContent className="flex flex-col gap-6" value="backup">
<Table>
<TableHeader>
<TableRow>
<TableHead>Reference</TableHead>
<TableHead>Date</TableHead>
<TableHead>Status</TableHead>
<TableHead></TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell>azertyuiop</TableCell>
<TableCell><Badge variant="outline" className="text-orange-500 border-2 border-orange-500">ongoing</Badge></TableCell>
<TableCell>28/01/25</TableCell>
<TableCell></TableCell>
</TableRow>
</TableBody>
</Table>
</TabsContent>
<TabsContent className="flex flex-col gap-6" value="restore">
<Table>
<TableHeader>
<TableRow>
<TableHead>Backup reference</TableHead>
<TableHead>Date</TableHead>
<TableHead>Status</TableHead>
<TableHead></TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell>azertyuiop</TableCell>
<TableCell>ongoing</TableCell>
<TableCell>28/01/25</TableCell>
<TableCell></TableCell>
</TableRow>
</TableBody>
</Table>
</TabsContent>
</Tabs>
</PageContent>
</Page>
)
}
@@ -0,0 +1,7 @@
import {PageParams} from "@/types/next";
export default async function RoutePage(props: PageParams<{}>) {
return (
<div>new agent</div>
)
}
+42 -8
View File
@@ -1,15 +1,49 @@
import {PageParams} from "@/types/next"; import {PageParams} from "@/types/next";
import {prisma} from "@/prisma";
import {AgentCard} from "@/components/wrappers/Agent/AgentCard/AgentCard";
import {CardsWithPagination} from "@/components/wrappers/cards-with-pagination";
import {Button} from "@/components/ui/button";
import Link from 'next/link'
import {Page, PageActions, PageContent, PageHeader, PageTitle} from "@/features/layout/page";
export default async function RoutePage(props: PageParams<{}>) { export default async function RoutePage(props: PageParams<{}>) {
// const agents = await prisma.agent.findMany({})
const agents = [
{"id": "467911b6-1234-4321-8765-111111111111", "name": "My Agent 1", "lastContact": "null"},
{"id": "15f03a2a-f81e-4339-bb3d-222222222222", "name": "My Agent 2", "lastContact": "null"},
{"id": "2e9b6e1a-5678-9012-3456-333333333333", "name": "My Agent 3", "lastContact": "null"},
{"id": "8c637541-1111-2222-3333-444444444444", "name": "My Agent 4", "lastContact": "null"},
{"id": "9e02f789-5555-6666-7777-555555555555", "name": "My Agent 5", "lastContact": "null"},
{"id": "1a2b3c4d-8888-9999-0000-666666666666", "name": "My Agent 6", "lastContact": "null"},
{"id": "7d8e9f0g-3333-4444-5555-777777777777", "name": "My Agent 7", "lastContact": "null"},
{"id": "3f4g5h6j-9999-0000-1111-888888888888", "name": "My Agent 8", "lastContact": "null"},
{"id": "5c6d7e8f-2222-3333-4444-999999999999", "name": "My Agent 9", "lastContact": "null"},
{"id": "9a0b1c2d-6666-7777-8888-000000000000", "name": "My Agent 10", "lastContact": "null"}
]
return ( return (
<div className="flex flex-1 flex-col gap-4 p-4"> <Page>
<div className="grid auto-rows-min gap-4 md:grid-cols-3"> <PageHeader>
<div className="aspect-video rounded-xl bg-muted/50"/> <PageTitle>
<div className="aspect-video rounded-xl bg-muted/50"/> Agents
<div className="aspect-video rounded-xl bg-muted/50"/> </PageTitle>
</div> <PageActions>
<div className="min-h-[100vh] flex-1 rounded-xl bg-muted/50 md:min-h-min"/> <Link href={"/dashboard/agents/new"}>
</div> <Button>+ Create Agent</Button>
</Link>
</PageActions>
</PageHeader>
<PageContent>
<CardsWithPagination
data={agents}
cardItem={AgentCard}
cardsPerPage={4}
numberOfColumns={1}
/>
</PageContent>
</Page>
) )
} }
+9 -8
View File
@@ -1,24 +1,25 @@
import {SidebarInset, SidebarProvider, SidebarTrigger } from "@/components/ui/sidebar" import React from "react";
import {redirect} from "next/navigation";
import {SidebarInset, SidebarProvider} from "@/components/ui/sidebar"
import {AppSidebar} from "@/components/wrappers/Dashboard/SideBar/app-sidebar"; import {AppSidebar} from "@/components/wrappers/Dashboard/SideBar/app-sidebar";
import {currentUser} from "@/auth/current-user"; import {currentUser} from "@/auth/current-user";
import {redirect} from "next/navigation";
import {LoggedInButton} from "@/components/wrappers/Dashboard/LoggedInButton/LoggedInButton";
import {ModeToggle} from "@/features/theme/ModeToggle";
import {Header} from "@/features/layout/Header"; import {Header} from "@/features/layout/Header";
export default async function Layout({children}: { children: React.ReactNode }) { export default async function Layout({children}: { children: React.ReactNode }) {
const user = await currentUser() const user = await currentUser()
if (!user) { if (!user) redirect('/login')
redirect('/login')
}
return ( return (
<SidebarProvider> <SidebarProvider>
<AppSidebar/> <AppSidebar/>
<SidebarInset> <SidebarInset>
<Header/> <Header/>
<main>{children}</main> <main>
{children}
</main>
</SidebarInset> </SidebarInset>
</SidebarProvider> </SidebarProvider>
) )
-2
View File
@@ -1,5 +1,3 @@
import Image from "next/image";
export default function Home() { export default function Home() {
return ( return (
<div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]"> <div className="grid grid-rows-[20px_1fr_20px] items-center justify-items-center min-h-screen p-8 pb-20 gap-16 sm:p-20 font-[family-name:var(--font-geist-sans)]">
-1
View File
@@ -2,7 +2,6 @@ import {redirect} from "next/navigation";
import {currentUser} from "@/auth/current-user"; import {currentUser} from "@/auth/current-user";
export default async function Index() { export default async function Index() {
const user = await currentUser() const user = await currentUser()
if (user) { if (user) {
+3 -1
View File
@@ -1,8 +1,10 @@
import React from "react";
import type {Metadata} from "next"; import type {Metadata} from "next";
import {Inter} from "next/font/google";
import "./globals.css"; import "./globals.css";
import {Providers} from "./providers"; import {Providers} from "./providers";
import {cn} from "@/lib/utils"; import {cn} from "@/lib/utils";
import {Inter} from "next/font/google";
const inter = Inter({subsets: ["latin"]}); const inter = Inter({subsets: ["latin"]});
+6 -5
View File
@@ -1,17 +1,18 @@
"use client" "use client"
import {PropsWithChildren} from "react"; import {PropsWithChildren} from "react";
import {ThemeProvider} from "@/features/theme/theme-provider";
import {Toaster} from "@/components/ui/sonner"; import {Toaster} from "@/components/ui/sonner";
import { import {QueryClient, QueryClientProvider,} from '@tanstack/react-query'
QueryClient,
QueryClientProvider,
} from '@tanstack/react-query'
import {SessionProvider} from "next-auth/react"; import {SessionProvider} from "next-auth/react";
export type ProviderProps = PropsWithChildren<{}>; export type ProviderProps = PropsWithChildren<{}>;
const queryClient = new QueryClient() const queryClient = new QueryClient()
import dynamic from 'next/dynamic';
const ThemeProvider = dynamic(() => import('@/features/theme/theme-provider'), {ssr: false});
export const Providers = (props: ProviderProps) => { export const Providers = (props: ProviderProps) => {
return ( return (
<SessionProvider> <SessionProvider>
+10 -3
View File
@@ -1,6 +1,14 @@
FROM node:20-alpine AS base FROM node:20-alpine AS base
# Install dependencies only when needed ENV YARN_VERSION=4.2.2
RUN apk add --no-cache libc6-compat
# install and use yarn 4.x
RUN corepack enable && corepack prepare yarn@${YARN_VERSION}
RUN yarn set version ${YARN_VERSION}
FROM base AS deps FROM base AS deps
WORKDIR /app WORKDIR /app
@@ -8,7 +16,7 @@ WORKDIR /app
COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./ COPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./
RUN \ RUN \
if [ -f yarn.lock ]; then yarn --frozen-lockfile; \ if [ -f yarn.lock ]; then yarn; \
elif [ -f package-lock.json ]; then npm ci; \ elif [ -f package-lock.json ]; then npm ci; \
elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm i --frozen-lockfile; \ elif [ -f pnpm-lock.yaml ]; then corepack enable pnpm && pnpm i --frozen-lockfile; \
else echo "Lockfile not found." && exit 1; \ else echo "Lockfile not found." && exit 1; \
@@ -28,7 +36,6 @@ RUN chmod +x /app/docker/entrypoints/app-dev-entrypoint.sh
ENTRYPOINT ["sh","/app/docker/entrypoints/app-dev-entrypoint.sh"] ENTRYPOINT ["sh","/app/docker/entrypoints/app-dev-entrypoint.sh"]
# Rebuild the source code only when needed # Rebuild the source code only when needed
FROM base AS builder FROM base AS builder
-8241
View File
File diff suppressed because it is too large Load Diff
+11 -7
View File
@@ -3,7 +3,7 @@
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "next dev -p 80", "dev": "next dev --turbopack -p 80",
"build": "next build", "build": "next build",
"start": "next start", "start": "next start",
"lint": "next lint" "lint": "next lint"
@@ -51,14 +51,14 @@
"embla-carousel-react": "^8.3.1", "embla-carousel-react": "^8.3.1",
"input-otp": "^1.4.0", "input-otp": "^1.4.0",
"lucide-react": "^0.454.0", "lucide-react": "^0.454.0",
"next": "14.2.16", "next": "15.0.3",
"next-auth": "^5.0.0-beta.25", "next-auth": "^5.0.0-beta.25",
"next-intl": "^3.24.0", "next-intl": "^3.24.0",
"next-safe-action": "^7.4.3", "next-safe-action": "^7.4.3",
"next-themes": "^0.3.0", "next-themes": "^0.3.0",
"react": "^18", "react": "19.0.0-rc-66855b96-20241106",
"react-day-picker": "^8.10.1", "react-day-picker": "^8.10.1",
"react-dom": "^18", "react-dom": "19.0.0-rc-66855b96-20241106",
"react-hook-form": "^7.53.1", "react-hook-form": "^7.53.1",
"react-resizable-panels": "^2.1.6", "react-resizable-panels": "^2.1.6",
"react-twc": "^1.4.2", "react-twc": "^1.4.2",
@@ -71,13 +71,17 @@
}, },
"devDependencies": { "devDependencies": {
"@types/node": "^20", "@types/node": "^20",
"@types/react": "^18", "@types/react": "npm:types-react@19.0.0-rc.1",
"@types/react-dom": "^18", "@types/react-dom": "npm:types-react-dom@19.0.0-rc.1",
"eslint": "^8", "eslint": "^8",
"eslint-config-next": "14.2.16", "eslint-config-next": "15.0.3",
"postcss": "^8", "postcss": "^8",
"prisma": "^5.21.1", "prisma": "^5.21.1",
"tailwindcss": "^3.4.1", "tailwindcss": "^3.4.1",
"typescript": "^5" "typescript": "^5"
},
"overrides": {
"@types/react": "npm:types-react@19.0.0-rc.1",
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.1"
} }
} }
+39
View File
@@ -70,3 +70,42 @@ model User {
@@map("users") @@map("users")
} }
model Agent {
id String @id @default(cuid())
name String
description String?
lastContact DateTime? @map("last_contact")
createdAt DateTime @default(now()) @map("created_at")
}
model Database {
id String @id @default(cuid())
agentId String @map("agent_id")
name String
description String?
backupPolicy String? @map("backup_policy")
createdAt DateTime @default(now()) @map("created_at")
}
enum Status {
waiting
ongoing
failed
success
}
model Backup {
id String @id @default(cuid())
databaseId String @map("database_id")
status Status @default(waiting)
file String?
createdAt DateTime @default(now()) @map("created_at")
}
model Restore {
id String @id @default(cuid())
backupId String @map("backup_id")
status Status @default(waiting)
createdAt DateTime @default(now()) @map("created_at")
}
@@ -0,0 +1,24 @@
"use client";
import {Card, CardContent, CardHeader} from "@/components/ui/card";
import Link from "next/link";
export type agentCardProps = {
id: string;
name: string;
lastContact: string;
}
export const AgentCard = (props: agentCardProps) => {
const {id, name, lastContact} = props;
return (
<Link href={`/dashboard/agents/${id}`}>
<Card>
<CardHeader>{name}</CardHeader>
<CardContent>Agent's Description</CardContent>
</Card>
</Link>
)
}
@@ -59,6 +59,7 @@ export const LoginForm = (props: loginFormProps) => {
<FormField <FormField
control={form.control} control={form.control}
name="email" name="email"
defaultValue=""
render={({field}) => ( render={({field}) => (
<FormItem> <FormItem>
<FormLabel>Email</FormLabel> <FormLabel>Email</FormLabel>
@@ -73,6 +74,7 @@ export const LoginForm = (props: loginFormProps) => {
<FormField <FormField
control={form.control} control={form.control}
name="password" name="password"
defaultValue=""
render={({field}) => ( render={({field}) => (
<FormItem> <FormItem>
@@ -63,6 +63,7 @@ export const RegisterForm = (props: registerFormProps) => {
<FormField <FormField
control={form.control} control={form.control}
name="name" name="name"
defaultValue=""
render={({field}) => ( render={({field}) => (
<FormItem> <FormItem>
<FormLabel>Name</FormLabel> <FormLabel>Name</FormLabel>
@@ -77,6 +78,7 @@ export const RegisterForm = (props: registerFormProps) => {
<FormField <FormField
control={form.control} control={form.control}
name="email" name="email"
defaultValue=""
render={({field}) => ( render={({field}) => (
<FormItem> <FormItem>
<FormLabel>Email</FormLabel> <FormLabel>Email</FormLabel>
@@ -91,6 +93,7 @@ export const RegisterForm = (props: registerFormProps) => {
<FormField <FormField
control={form.control} control={form.control}
name="password" name="password"
defaultValue=""
render={({field}) => ( render={({field}) => (
<FormItem> <FormItem>
<FormLabel className="flex">Password <FormLabel className="flex">Password
@@ -115,6 +118,7 @@ export const RegisterForm = (props: registerFormProps) => {
<FormField <FormField
control={form.control} control={form.control}
name="confirmPassword" name="confirmPassword"
defaultValue=""
render={({field}) => ( render={({field}) => (
<FormItem> <FormItem>
<FormLabel>Password Confirmation</FormLabel> <FormLabel>Password Confirmation</FormLabel>
@@ -1,4 +1,3 @@
import {Button} from "@/components/ui/button"
import {Avatar, AvatarFallback, AvatarImage} from "@/components/ui/avatar" import {Avatar, AvatarFallback, AvatarImage} from "@/components/ui/avatar"
import {currentUser} from "@/auth/current-user"; import {currentUser} from "@/auth/current-user";
import {LoggedInDropdown} from "@/components/wrappers/Dashboard/LoggedInDropdown/LoggedInDropdown"; import {LoggedInDropdown} from "@/components/wrappers/Dashboard/LoggedInDropdown/LoggedInDropdown";
@@ -9,23 +9,16 @@ import {
} from "@/components/ui/sidebar" } from "@/components/ui/sidebar"
import {DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger} from "@/components/ui/dropdown-menu"; import {DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger} from "@/components/ui/dropdown-menu";
import { import {
Calendar,
ChartArea, ChartArea,
ChevronDown, ChevronDown,
ChevronUp,
Home, Home,
Inbox,
Search,
Settings, Settings,
ShieldHalf, ShieldHalf,
User2
} from "lucide-react"; } from "lucide-react";
import Link from "next/link"; import Link from "next/link";
import {signOutAction} from "@/features/auth/auth.action";
import {UserAvatar} from "@/components/wrappers/Dashboard/UserAvatar/UserAvatar";
import {LoggedInDropdown} from "@/components/wrappers/Dashboard/LoggedInDropdown/LoggedInDropdown";
import {LoggedInButton} from "@/components/wrappers/Dashboard/LoggedInButton/LoggedInButton"; import {LoggedInButton} from "@/components/wrappers/Dashboard/LoggedInButton/LoggedInButton";
import {Button, buttonVariants} from "@/components/ui/button" import {buttonVariants} from "@/components/ui/button"
import {cn} from "@/lib/utils"; import {cn} from "@/lib/utils";
@@ -91,7 +84,10 @@ export function AppSidebar() {
<SidebarMenuItem key={item.title}> <SidebarMenuItem key={item.title}>
<SidebarMenuButton asChild> <SidebarMenuButton asChild>
<Link <Link
className={cn(buttonVariants({size: "lg", variant: "ghost"}), "justify-start p-0")} className={cn(buttonVariants({
size: "lg",
variant: "ghost"
}), "justify-start p-0")}
href={`${BASE_URL}/${item.url}`}> href={`${BASE_URL}/${item.url}`}>
<item.icon/> <item.icon/>
<span>{item.title}</span> <span>{item.title}</span>
@@ -0,0 +1,150 @@
'use client'
import React, {useState} from 'react'
import {Card} from "@/components/ui/card"
import {cn} from "@/lib/utils";
import {
Pagination, PaginationContent,
PaginationEllipsis,
PaginationItem,
PaginationLink,
PaginationNext, PaginationPrevious
} from "@/components/ui/pagination";
export type cardsWithPaginationProps = {
data: Array<{}>;
cardItem: React.ComponentType;
cardsPerPage?: number
numberOfColumns?: number
}
export const CardsWithPagination = (props: cardsWithPaginationProps) => {
const {data, cardItem, cardsPerPage = 5, numberOfColumns = 1} = props
const CardItem = cardItem
const [currentPage, setCurrentPage] = useState(1)
const totalPages = Math.ceil(data.length / cardsPerPage)
const indexOfLastCard = currentPage * cardsPerPage
const indexOfFirstCard = indexOfLastCard - cardsPerPage
const currentCards = data.slice(indexOfFirstCard, indexOfLastCard)
const handlePageChange = (pageNumber: number) => {
setCurrentPage(pageNumber)
}
const renderPaginationItems = () => {
const items = []
const maxVisiblePages = 3
if (totalPages <= maxVisiblePages) {
for (let i = 1; i <= totalPages; i++) {
items.push(
<PaginationItem key={i}>
<PaginationLink
onClick={() => handlePageChange(i)}
isActive={currentPage === i}
>
{i}
</PaginationLink>
</PaginationItem>
)
}
} else {
if (currentPage <= 2) {
for (let i = 1; i <= maxVisiblePages; i++) {
items.push(
<PaginationItem key={i}>
<PaginationLink
onClick={() => handlePageChange(i)}
isActive={currentPage === i}
>
{i}
</PaginationLink>
</PaginationItem>
)
}
items.push(
<PaginationItem key="ellipsis1">
<PaginationEllipsis/>
</PaginationItem>
)
} else if (currentPage >= totalPages - 1) {
items.push(
<PaginationItem key="ellipsis2">
<PaginationEllipsis/>
</PaginationItem>
)
for (let i = totalPages - 2; i <= totalPages; i++) {
items.push(
<PaginationItem key={i}>
<PaginationLink
onClick={() => handlePageChange(i)}
isActive={currentPage === i}
>
{i}
</PaginationLink>
</PaginationItem>
)
}
} else {
items.push(
<PaginationItem key="ellipsis3">
<PaginationEllipsis/>
</PaginationItem>
)
for (let i = currentPage - 1; i <= currentPage + 1; i++) {
items.push(
<PaginationItem key={i}>
<PaginationLink
onClick={() => handlePageChange(i)}
isActive={currentPage === i}
>
{i}
</PaginationLink>
</PaginationItem>
)
}
items.push(
<PaginationItem key="ellipsis4">
<PaginationEllipsis/>
</PaginationItem>
)
}
}
return items
}
return (
<div className="">
<div className={cn(`grid auto-rows-min gap-4 md:grid-cols-${numberOfColumns}`)}>
{currentCards.map((card, key) => (
<CardItem key={key} {...card}/>
))}
</div>
<Pagination className="mt-8">
<PaginationContent>
<PaginationItem>
<PaginationPrevious
onClick={() => handlePageChange(Math.max(1, currentPage - 1))}
aria-disabled={currentPage === 1}
tabIndex={currentPage === 1 ? -1 : 0}
/>
</PaginationItem>
{renderPaginationItems()}
<PaginationItem>
<PaginationNext
onClick={() => handlePageChange(Math.min(totalPages, currentPage + 1))}
aria-disabled={currentPage === totalPages}
tabIndex={currentPage === totalPages ? -1 : 0}
/>
</PaginationItem>
</PaginationContent>
</Pagination>
</div>
)
}
+2 -1
View File
@@ -1,6 +1,7 @@
"use server" "use server"
import {signIn, signOut} from "@/auth/auth";
import {redirect} from "next/navigation"; import {redirect} from "next/navigation";
import {signIn, signOut} from "@/auth/auth";
export const signOutAction = async () => { export const signOutAction = async () => {
await signOut({redirectTo: '/', redirect: true}) await signOut({redirectTo: '/', redirect: true})
+2 -6
View File
@@ -1,10 +1,6 @@
import Image from "next/image"
import {Layout} from "@/components/layout";
import Link from "next/link";
import {Badge} from "@/components/ui/badge";
import {currentUser} from "@/auth/current-user";
import {notFound} from "next/navigation"; import {notFound} from "next/navigation";
import {buttonVariants} from "@/components/ui/button";
import {currentUser} from "@/auth/current-user";
import {LoggedInButton} from "@/components/wrappers/Dashboard/LoggedInButton/LoggedInButton"; import {LoggedInButton} from "@/components/wrappers/Dashboard/LoggedInButton/LoggedInButton";
import {SidebarTrigger} from "@/components/ui/sidebar"; import {SidebarTrigger} from "@/components/ui/sidebar";
import {ModeToggle} from "@/features/theme/ModeToggle"; import {ModeToggle} from "@/features/theme/ModeToggle";
+38
View File
@@ -0,0 +1,38 @@
import {PropsWithChildren} from 'react';
export const Page = ({children}: PropsWithChildren<{}>) => {
return (
<div className="flex flex-1 flex-col gap-4 px-10 py-6">{children}</div>
);
};
export const PageHeader = ({children}: PropsWithChildren<{}>) => {
return (
<div className="flex justify-between">{children}</div>
);
};
export const PageTitle = ({children}: PropsWithChildren<{}>) => {
return (
<h1 className="text-3xl font-bold mb-6">{children}</h1>
);
};
export const PageDescription = ({children}: PropsWithChildren<{}>) => {
return (
<h2 className="text-s mb-6 text-gray-700">{children}</h2>
);
};
export const PageActions = ({children}: PropsWithChildren<{}>) => {
return (
<h1 className="flex gap-4">{children}</h1>
);
};
export const PageContent = ({children}: PropsWithChildren<{}>) => {
return (
<div className="">{children}</div>
);
};
+1 -6
View File
@@ -5,12 +5,7 @@ import { Moon, Sun } from "lucide-react"
import {useTheme} from "next-themes" import {useTheme} from "next-themes"
import {Button} from "@/components/ui/button" import {Button} from "@/components/ui/button"
import { import {DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger} from "@/components/ui/dropdown-menu"
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
export function ModeToggle() { export function ModeToggle() {
const {setTheme} = useTheme() const {setTheme} = useTheme()
+1 -1
View File
@@ -4,6 +4,6 @@ import * as React from "react"
import { ThemeProvider as NextThemesProvider } from "next-themes" import { ThemeProvider as NextThemesProvider } from "next-themes"
import { type ThemeProviderProps } from "next-themes/dist/types" import { type ThemeProviderProps } from "next-themes/dist/types"
export function ThemeProvider({ children, ...props }: ThemeProviderProps) { export default function ThemeProvider({ children, ...props }: ThemeProviderProps) {
return <NextThemesProvider {...props}>{children}</NextThemesProvider> return <NextThemesProvider {...props}>{children}</NextThemesProvider>
} }
+2 -1
View File
@@ -26,7 +26,8 @@
"./src/*" "./src/*"
] ]
}, },
"strict": false "strict": false,
"target": "ES2017"
}, },
"include": [ "include": [
"next-env.d.ts", "next-env.d.ts",