🐛 handle click on done in Config (#304)

♻️ refactor Config Component
This commit is contained in:
Zineb El Bachiri 2023-06-12 13:15:03 +02:00 committed by GitHub
parent 537efc834d
commit b3453157e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 262 additions and 165 deletions

View File

@ -0,0 +1,54 @@
"use client";
import { BrainConfig } from "@/lib/context/BrainConfigProvider/types";
import { UseFormRegister } from "react-hook-form";
import Field from "../../components/ui/Field";
interface BackendConfigProps {
register: UseFormRegister<BrainConfig>;
}
export const BackendConfig = ({
register,
}: BackendConfigProps): JSX.Element => {
return (
<>
<div className="border-b border-gray-300 mt-8 mb-8">
<p className="text-center text-gray-600 uppercase tracking-wide font-semibold">
Backend config
</p>
</div>
<Field
type="text"
placeholder="Backend URL"
className="w-full"
label="Backend URL"
{...register("backendUrl")}
/>
<Field
type="text"
placeholder="Supabase URL"
className="w-full"
label="Supabase URL"
{...register("supabaseUrl")}
/>
<Field
type="text"
placeholder="Supabase key"
className="w-full"
label="Supabase key"
{...register("supabaseKey")}
/>
<label className="flex items-center">
<input
type="checkbox"
checked
name="keepLocal"
onChange={() => alert("Coming soon")}
className="form-checkbox h-5 w-5 text-indigo-600 rounded focus:ring-2 focus:ring-indigo-400"
/>
<span className="ml-2 text-gray-700">Keep in local</span>
</label>
</>
);
};

View File

@ -0,0 +1,61 @@
"use client";
import { useRouter } from "next/navigation";
import Button from "../../components/ui/Button";
import { useConfig } from "../hooks/useConfig";
import { BackendConfig } from "./BackendConfig";
import { ModelConfig } from "./ModelConfig";
import { UserAccountSection } from "./UserAccountSection";
export const ConfigForm = (): JSX.Element => {
const {
handleSubmit,
isDirty,
maxTokens,
openAiKey,
saveConfig,
register,
temperature,
model,
resetBrainConfig,
} = useConfig();
const router = useRouter();
const handleDoneClick = () => {
if (isDirty) {
saveConfig();
}
router.back();
};
return (
<form
className="flex flex-col gap-5 py-5 w-full max-w-xl"
onSubmit={handleSubmit(handleDoneClick)}
>
<ModelConfig
register={register}
model={model}
openAiKey={openAiKey}
temperature={temperature}
maxTokens={maxTokens}
/>
<BackendConfig register={register} />
<div className="flex justify-between">
<Button
variant="danger"
className="self-end"
type="button"
onClick={resetBrainConfig}
>
Reset
</Button>
<Button variant="secondary" className="self-end">
Done
</Button>
</div>
<UserAccountSection />
</form>
);
};

View File

@ -0,0 +1,10 @@
export const ConfigTitle = (): JSX.Element => {
return (
<div className="flex flex-col items-center justify-center">
<h1 className="text-3xl font-bold text-center">Configuration</h1>
<h2 className="opacity-50 text-center">
Here, you can choose your model, set your credentials...
</h2>
</div>
);
};

View File

@ -0,0 +1,96 @@
"use client";
import {
BrainConfig,
Model,
anthropicModels,
models,
paidModels,
} from "@/lib/context/BrainConfigProvider/types";
import { UseFormRegister } from "react-hook-form";
import Field from "../../components/ui/Field";
interface ModelConfigProps {
register: UseFormRegister<BrainConfig>;
model: Model;
openAiKey: string | undefined;
temperature: number;
maxTokens: number;
}
export const ModelConfig = ({
register,
model,
openAiKey,
temperature,
maxTokens,
}: ModelConfigProps): JSX.Element => {
return (
<>
<div className="border-b border-gray-300 mt-8 mb-8">
<p className="text-center text-gray-600 uppercase tracking-wide font-semibold">
Model config
</p>
</div>
<Field
type="password"
placeholder="Open AI Key"
className="w-full"
label="Open AI Key"
{...register("openAiKey")}
/>
<fieldset className="w-full flex flex-col">
<label className="flex-1 text-sm" htmlFor="model">
Model
</label>
<select
id="model"
{...register("model")}
className="px-5 py-2 dark:bg-gray-700 bg-gray-200 rounded-md"
>
{(openAiKey ? paidModels : models).map((model) => (
<option value={model} key={model}>
{model}
</option>
))}
</select>
</fieldset>
{(anthropicModels as readonly string[]).includes(model) && (
<Field
type="text"
placeholder="Anthropic API Key"
className="w-full"
label="Anthropic API Key"
{...register("anthropicKey")}
/>
)}
<fieldset className="w-full flex">
<label className="flex-1" htmlFor="temp">
Temperature: {temperature}
</label>
<input
id="temp"
type="range"
min="0"
max="1"
step="0.01"
value={temperature}
{...register("temperature")}
/>
</fieldset>
<fieldset className="w-full flex">
<label className="flex-1" htmlFor="tokens">
Tokens: {maxTokens}
</label>
<input
type="range"
min="256"
max="3000"
step="1"
value={maxTokens}
{...register("maxTokens")}
/>
</fieldset>
</>
);
};

View File

@ -0,0 +1,34 @@
"use client";
import { useSupabase } from "@/app/supabase-provider";
import Link from "next/link";
import Button from "../../components/ui/Button";
export const UserAccountSection = (): JSX.Element => {
const { session } = useSupabase();
if (session === null) {
return <></>;
}
return (
<>
<div className="border-b border-gray-300 mt-8 mb-8">
<p className="text-center text-gray-600 uppercase tracking-wide font-semibold">
Your Account
</p>
</div>
<div className="flex justify-between items-center w-full">
<span>
Signed In as: <b>{session.user.email}</b>
</span>
<Link className="mt-2" href={"/logout"}>
<Button className="px-3 py-2" variant={"danger"}>
Logout
</Button>
</Link>
{/* TODO: add functionality to change password */}
</div>
</>
);
};

View File

@ -0,0 +1,2 @@
export * from "./ConfigForm";
export * from "./ConfigTitle";

View File

@ -1,30 +1,12 @@
"use client";
import { redirect } from "next/navigation";
import {
anthropicModels,
models,
paidModels,
} from "@/lib/context/BrainConfigProvider/types";
import Link from "next/link";
import Button from "../components/ui/Button";
import Field from "../components/ui/Field";
import { useSupabase } from "../supabase-provider";
import { useConfig } from "./hooks/useConfig";
import { ConfigForm, ConfigTitle } from "./components";
export default function ExplorePage() {
// TODO: Use states instead of NEXTJS router to open and close modal
export default function ConfigPage() {
const { session } = useSupabase();
const {
handleSubmit,
isDirty,
maxTokens,
openAiKey,
saveConfig,
register,
temperature,
model,
resetBrainConfig,
} = useConfig();
if (session === null) {
redirect("/login");
@ -33,150 +15,8 @@ export default function ExplorePage() {
return (
<main className="w-full flex flex-col">
<section className="w-full outline-none pt-10 flex flex-col gap-5 items-center justify-center p-6">
<div className="flex flex-col items-center justify-center">
<h1 className="text-3xl font-bold text-center">Configuration</h1>
<h2 className="opacity-50 text-center">
Here, you can choose your model, set your credentials...
</h2>
</div>
<form
className="flex flex-col gap-5 py-5 w-full max-w-xl"
onSubmit={handleSubmit(saveConfig)}
>
<div className="border-b border-gray-300 mt-8 mb-8">
<p className="text-center text-gray-600 uppercase tracking-wide font-semibold">
Model config
</p>
</div>
<Field
type="password"
placeholder="Open AI Key"
className="w-full"
label="Open AI Key"
{...register("openAiKey")}
/>
<fieldset className="w-full flex flex-col">
<label className="flex-1 text-sm" htmlFor="model">
Model
</label>
<select
id="model"
{...register("model")}
className="px-5 py-2 dark:bg-gray-700 bg-gray-200 rounded-md"
>
{(openAiKey ? paidModels : models).map((model) => (
<option value={model} key={model}>
{model}
</option>
))}
</select>
</fieldset>
{(anthropicModels as readonly string[]).includes(model) && (
<Field
type="text"
placeholder="Anthropic API Key"
className="w-full"
label="Anthropic API Key"
{...register("anthropicKey")}
/>
)}
<fieldset className="w-full flex">
<label className="flex-1" htmlFor="temp">
Temperature: {temperature}
</label>
<input
id="temp"
type="range"
min="0"
max="1"
step="0.01"
value={temperature}
{...register("temperature")}
/>
</fieldset>
<fieldset className="w-full flex">
<label className="flex-1" htmlFor="tokens">
Tokens: {maxTokens}
</label>
<input
type="range"
min="256"
max="3000"
step="1"
value={maxTokens}
{...register("maxTokens")}
/>
</fieldset>
<div className="border-b border-gray-300 mt-8 mb-8">
<p className="text-center text-gray-600 uppercase tracking-wide font-semibold">
Backend config
</p>
</div>
<Field
type="text"
placeholder="Backend URL"
className="w-full"
label="Backend URL"
{...register("backendUrl")}
/>
<Field
type="text"
placeholder="Supabase URL"
className="w-full"
label="Supabase URL"
{...register("supabaseUrl")}
/>
<Field
type="text"
placeholder="Supabase key"
className="w-full"
label="Supabase key"
{...register("supabaseKey")}
/>
<label className="flex items-center">
<input
type="checkbox"
checked
name="keepLocal"
onChange={() => alert("Coming soon")}
className="form-checkbox h-5 w-5 text-indigo-600 rounded focus:ring-2 focus:ring-indigo-400"
/>
<span className="ml-2 text-gray-700">Keep in local</span>
</label>
<div className="flex justify-between">
<Button
variant="danger"
className="self-end"
type="button"
onClick={resetBrainConfig}
>
Reset
</Button>
<Button
disabled={!isDirty}
variant="secondary"
className="self-end"
>
Done
</Button>
</div>
<div className="border-b border-gray-300 mt-8 mb-8">
<p className="text-center text-gray-600 uppercase tracking-wide font-semibold">
Your Account
</p>
</div>
<div className="flex justify-between items-center w-full">
<span>
Signed In as: <b>{session.user.email}</b>
</span>
<Link className="mt-2" href={"/logout"}>
<Button className="px-3 py-2" variant={"danger"}>
Logout
</Button>
</Link>
{/* TODO: add functionality to change password */}
</div>
</form>
<ConfigTitle />
<ConfigForm />
</section>
</main>
);