Create config page using tailwind, shadcn components, styling

- Include side pane but with only the account info in it
- Replicate styling of the old config page
This commit is contained in:
Debanjum Singh Solanky 2024-07-16 20:06:50 +05:30
parent 88007d7552
commit 7e8e80f29e
3 changed files with 192 additions and 0 deletions

View file

@ -0,0 +1,36 @@
import type { Metadata } from "next";
import { Noto_Sans } from "next/font/google";
import "../globals.css";
const inter = Noto_Sans({ subsets: ["latin"] });
export const metadata: Metadata = {
title: "Khoj AI - Settings",
description: "Configure Khoj to get personalized, deeper assistance.",
icons: {
icon: "/static/favicon.ico",
},
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<meta httpEquiv="Content-Security-Policy"
content="default-src 'self' https://assets.khoj.dev;
script-src 'self' https://assets.khoj.dev 'unsafe-inline' 'unsafe-eval';
connect-src 'self' https://ipapi.co/json ws://localhost:42110;
style-src 'self' https://assets.khoj.dev 'unsafe-inline' https://fonts.googleapis.com;
img-src 'self' data: https://*.khoj.dev https://*.googleusercontent.com;
font-src 'self' https://assets.khoj.dev https://fonts.gstatic.com;
child-src 'none';
object-src 'none';"></meta>
<body className={inter.className}>
{children}
</body>
</html>
);
}

View file

@ -0,0 +1,145 @@
"use client";
import styles from "./settings.module.css";
import { Suspense, useEffect, useState } from "react";
import { useUserConfig } from "../common/auth";
import { Button } from "@/components/ui/button";
import {
Card,
CardContent,
CardFooter,
CardHeader,
} from "@/components/ui/card";
import NavMenu from "../components/navMenu/navMenu";
import SidePanel from "../components/sidePanel/chatHistorySidePanel";
import Loading from "../components/loading/loading";
interface CardComponentProps {
header: string;
children: React.ReactNode;
footer: React.ReactNode;
}
const CardComponent: React.FC<CardComponentProps> = ({ header, children, footer }) => {
return (
<Card className="w-1/3 grid grid-flow-column border border-gray-300 shadow-md rounded-lg">
<CardHeader className="text-xl">{header}</CardHeader>
<CardContent>
{children}
</CardContent>
<CardFooter className="flex gap-4">
{footer}
</CardFooter>
</Card>
);
};
export default function SettingsView() {
const [title, setTitle] = useState("Settings");
const [isMobileWidth, setIsMobileWidth] = useState(false);
const userConfig = useUserConfig(true);
const cardClassName = "w-1/3 grid grid-flow-column border border-gray-300 shadow-md rounded-lg";
useEffect(() => {
setIsMobileWidth(window.innerWidth < 786);
const handleResize = () => setIsMobileWidth(window.innerWidth < 786);
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, []);
return (
<div id="page" className={styles.page}>
<title>
{title}
</title>
<div className={styles.sidePanel}>
<SidePanel
webSocketConnected={true}
conversationId={null}
uploadedFiles={[]}
isMobileWidth={isMobileWidth}
/>
</div>
<div className={styles.content}>
<NavMenu selected="Settings" title="Settings" showLogo={true} />
<div className={styles.contentBody}>
<Suspense fallback={<Loading />}>
<div id="content" className="grid grid-flow-column gap-16 m-8">
<div className="section grid gap-8">
<div className="text-4xl">Profile</div>
<div className="cards flex flex-wrap gap-16">
<Card className={cardClassName}>
<CardHeader className="text-xl">Name</CardHeader>
<CardContent>
<input type="text" className="border border-gray-300 rounded-lg p-4" defaultValue={userConfig?.given_name} />
</CardContent>
<CardFooter className="flex gap-4">
<Button variant="outline" size="sm">Save</Button>
</CardFooter>
</Card>
</div>
</div>
<div className="section grid gap-8">
<div className="text-4xl">Content</div>
<div className="cards flex flex-wrap gap-16">
<Card className={cardClassName}>
<CardHeader className="text-xl">Files</CardHeader>
<CardContent>
Manage your synced files
</CardContent>
<CardFooter className="flex gap-4">
<Button variant="outline" size="sm">Update</Button>
<Button variant="outline" size="sm">Disable</Button>
</CardFooter>
</Card>
<Card className={cardClassName}>
<CardHeader className="text-xl">Github</CardHeader>
<CardContent>
Set repositories to index
</CardContent>
<CardFooter className="flex gap-4">
<Button variant="outline" size="sm">Setup</Button>
<Button variant="outline" size="sm">Sync</Button>
</CardFooter>
</Card>
<Card className={cardClassName}>
<CardHeader className="text-xl">Notion</CardHeader>
<CardContent>
Sync your Notion pages
</CardContent>
<CardFooter className="flex gap-4">
<Button variant="outline" size="sm">Setup</Button>
<Button variant="outline" size="sm">Sync</Button>
</CardFooter>
</Card>
<Card className={cardClassName}>
<CardHeader className="text-xl">Language</CardHeader>
<CardContent>
<select className="border border-gray-300 rounded-lg">
{userConfig?.search_model_options.map(option => (
<option
key={option.id}
value={option.id}
selected={option.id === userConfig?.selected_search_model_config}
>
{option.name}
</option>
))}
</select>
</CardContent>
<CardFooter className="flex gap-4">
<Button variant="outline" size="sm">Save</Button>
</CardFooter>
</Card>
</div>
</div>
</div>
</Suspense>
</div>
</div>
</div>
);
}

View file

@ -0,0 +1,11 @@
div.page {
display: grid;
grid-template-columns: auto 1fr;
gap: 1rem;
height: 100vh;
color: hsla(var(--foreground));
}
div.contentBody {
display: grid;
margin: auto;
}