mirror of
https://github.com/crocofied/CoreControl.git
synced 2025-12-29 16:14:43 +00:00
Settings Page & Bug Fixes
This commit is contained in:
@@ -32,6 +32,8 @@ export async function POST(request: NextRequest) {
|
||||
}
|
||||
});
|
||||
|
||||
const servers_all = await prisma.server.findMany()
|
||||
|
||||
const applicationsWithServers = applications.map(app => ({
|
||||
...app,
|
||||
server: servers.find(s => s.id === app.serverId)?.name || 'No server'
|
||||
@@ -42,7 +44,7 @@ export async function POST(request: NextRequest) {
|
||||
|
||||
return NextResponse.json({
|
||||
applications: applicationsWithServers,
|
||||
servers,
|
||||
servers: servers_all,
|
||||
maxPage
|
||||
});
|
||||
} catch (error: any) {
|
||||
|
||||
@@ -75,7 +75,7 @@ export default function Dashboard() {
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
const savedLayout = Cookies.get('layoutPreference');
|
||||
const savedLayout = Cookies.get('layoutPreference-app');
|
||||
const layout_bool = savedLayout === 'grid'
|
||||
setIsGridLayout(layout_bool);
|
||||
setItemsPerPage(layout_bool ? 15 : 5)
|
||||
@@ -84,7 +84,7 @@ export default function Dashboard() {
|
||||
const toggleLayout = () => {
|
||||
const newLayout = !isGridLayout;
|
||||
setIsGridLayout(newLayout);
|
||||
Cookies.set('layoutPreference', newLayout ? 'grid' : 'standard', {
|
||||
Cookies.set('layoutPreference-app', newLayout ? 'grid' : 'standard', {
|
||||
expires: 365,
|
||||
path: '/',
|
||||
sameSite: 'strict'
|
||||
|
||||
@@ -76,14 +76,14 @@ export default function Dashboard() {
|
||||
const [loading, setLoading] = useState(true);
|
||||
|
||||
useEffect(() => {
|
||||
const savedLayout = Cookies.get('layoutPreference');
|
||||
const savedLayout = Cookies.get('layoutPreference-servers');
|
||||
setIsGridLayout(savedLayout === 'grid');
|
||||
}, []);
|
||||
|
||||
const toggleLayout = () => {
|
||||
const newLayout = !isGridLayout;
|
||||
setIsGridLayout(newLayout);
|
||||
Cookies.set('layoutPreference', newLayout ? 'grid' : 'standard', {
|
||||
Cookies.set('layoutPreference-servers', newLayout ? 'grid' : 'standard', {
|
||||
expires: 365,
|
||||
path: '/',
|
||||
sameSite: 'strict'
|
||||
|
||||
78
app/dashboard/settings/Settings.tsx
Normal file
78
app/dashboard/settings/Settings.tsx
Normal file
@@ -0,0 +1,78 @@
|
||||
import { AppSidebar } from "@/components/app-sidebar"
|
||||
import {
|
||||
Breadcrumb,
|
||||
BreadcrumbItem,
|
||||
BreadcrumbList,
|
||||
BreadcrumbPage,
|
||||
BreadcrumbSeparator,
|
||||
} from "@/components/ui/breadcrumb"
|
||||
import { Separator } from "@/components/ui/separator"
|
||||
import {
|
||||
SidebarInset,
|
||||
SidebarProvider,
|
||||
SidebarTrigger,
|
||||
} from "@/components/ui/sidebar"
|
||||
import { Card, CardHeader } from "@/components/ui/card"
|
||||
import { useTheme } from "next-themes"
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/components/ui/select"
|
||||
|
||||
export default function Settings() {
|
||||
const { theme, setTheme } = useTheme()
|
||||
|
||||
return (
|
||||
<SidebarProvider>
|
||||
<AppSidebar />
|
||||
<SidebarInset>
|
||||
<header className="flex h-16 shrink-0 items-center gap-2 transition-[width,height] ease-linear group-has-[[data-collapsible=icon]]/sidebar-wrapper:h-12">
|
||||
<div className="flex items-center gap-2 px-4">
|
||||
<SidebarTrigger className="-ml-1" />
|
||||
<Separator orientation="vertical" className="mr-2 h-4" />
|
||||
<Breadcrumb>
|
||||
<BreadcrumbList>
|
||||
<BreadcrumbItem className="hidden md:block">
|
||||
<BreadcrumbPage>/</BreadcrumbPage>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator className="hidden md:block" />
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbPage>Dashboard</BreadcrumbPage>
|
||||
</BreadcrumbItem>
|
||||
<BreadcrumbSeparator className="hidden md:block" />
|
||||
<BreadcrumbItem>
|
||||
<BreadcrumbPage>Settings</BreadcrumbPage>
|
||||
</BreadcrumbItem>
|
||||
</BreadcrumbList>
|
||||
</Breadcrumb>
|
||||
</div>
|
||||
</header>
|
||||
<div className="pl-4 pr-4">
|
||||
<span className="text-2xl font-semibold">Settings</span>
|
||||
<div className="pt-4">
|
||||
<Card className="w-full mb-4 relative">
|
||||
<CardHeader>
|
||||
<span className="text-xl font-bold">Theme</span>
|
||||
<Select value={theme} onValueChange={setTheme}>
|
||||
<SelectTrigger className="w-full [&_svg]:hidden">
|
||||
<SelectValue>
|
||||
{theme?.charAt(0).toUpperCase() + theme?.slice(1)}
|
||||
</SelectValue>
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
<SelectItem value="light">Light</SelectItem>
|
||||
<SelectItem value="dark">Dark</SelectItem>
|
||||
<SelectItem value="system">System</SelectItem>
|
||||
</SelectContent>
|
||||
</Select>
|
||||
</CardHeader>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</SidebarInset>
|
||||
</SidebarProvider>
|
||||
)
|
||||
}
|
||||
59
app/dashboard/settings/page.tsx
Normal file
59
app/dashboard/settings/page.tsx
Normal file
@@ -0,0 +1,59 @@
|
||||
"use client";
|
||||
|
||||
import { useEffect, useState } from "react";
|
||||
import Cookies from "js-cookie";
|
||||
import { useRouter } from "next/navigation";
|
||||
import Settings from "./Settings"
|
||||
import axios from "axios";
|
||||
|
||||
export default function DashboardPage() {
|
||||
const router = useRouter();
|
||||
const [isAuthChecked, setIsAuthChecked] = useState(false);
|
||||
const [isValid, setIsValid] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const token = Cookies.get("token");
|
||||
if (!token) {
|
||||
router.push("/");
|
||||
} else {
|
||||
const checkToken = async () => {
|
||||
try {
|
||||
const response = await axios.post("/api/auth/validate", {
|
||||
token: token,
|
||||
});
|
||||
|
||||
if (response.status === 200) {
|
||||
setIsValid(true);
|
||||
}
|
||||
} catch (error: any) {
|
||||
Cookies.remove("token");
|
||||
router.push("/");
|
||||
}
|
||||
}
|
||||
checkToken();
|
||||
}
|
||||
setIsAuthChecked(true);
|
||||
}, [router]);
|
||||
|
||||
if (!isAuthChecked) {
|
||||
return (
|
||||
<div className="flex items-center justify-center h-screen">
|
||||
<div className='inline-block' role='status' aria-label='loading'>
|
||||
<svg className='w-6 h-6 stroke-white animate-spin ' viewBox='0 0 24 24' fill='none' xmlns='http://www.w3.org/2000/svg'>
|
||||
<g clip-path='url(#clip0_9023_61563)'>
|
||||
<path d='M14.6437 2.05426C11.9803 1.2966 9.01686 1.64245 6.50315 3.25548C1.85499 6.23817 0.504864 12.4242 3.48756 17.0724C6.47025 21.7205 12.6563 23.0706 17.3044 20.088C20.4971 18.0393 22.1338 14.4793 21.8792 10.9444' stroke='stroke-current' stroke-width='1.4' stroke-linecap='round' class='my-path'></path>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id='clip0_9023_61563'>
|
||||
<rect width='24' height='24' fill='white'></rect>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
<span className='sr-only'>Loading...</span>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
return isValid ? <Settings /> : null;
|
||||
}
|
||||
@@ -30,7 +30,7 @@ export default function RootLayout({
|
||||
>
|
||||
<ThemeProvider
|
||||
attribute="class"
|
||||
defaultTheme="dark"
|
||||
defaultTheme="system"
|
||||
enableSystem
|
||||
disableTransitionOnChange
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user