mirror of
https://github.com/QuivrHQ/quivr.git
synced 2024-09-11 14:36:35 +03:00
Devx/add linter rules (#331)
* remove duplicate import * 🚧 add new linter configuration * 🧑💻 add and run prettier * 🐛 add babel parser for linter * 🧑💻 add lint-fix command * 🚨 use lint-fix * 🚨 remove 'FC' as a type. Use const and JSX.Element * 🚨 enforce arrow function rule from linter * 🔥 delete unused file * 🚨 adding /* eslint-disable */ in failing files * 💩 add ts-expect-error to Victory components
This commit is contained in:
parent
e6e5099d6b
commit
1d7bc8a5bc
188
frontend/.eslintrc.js
Normal file
188
frontend/.eslintrc.js
Normal file
@ -0,0 +1,188 @@
|
||||
/* eslint-disable max-lines */
|
||||
module.exports = {
|
||||
plugins: ["prefer-arrow", "import"],
|
||||
extends: [
|
||||
"next",
|
||||
"next/core-web-vitals",
|
||||
"eslint:recommended",
|
||||
"plugin:import/recommended",
|
||||
],
|
||||
ignorePatterns: ["**/node_modules/", "**/.next/"],
|
||||
rules: {
|
||||
"import/extensions": 0,
|
||||
"import/no-unresolved": 0,
|
||||
"import/prefer-default-export": 0,
|
||||
"import/no-duplicates": "error",
|
||||
complexity: ["error", 8],
|
||||
"max-lines": ["error", 100],
|
||||
"max-depth": ["error", 3],
|
||||
"max-params": ["error", 4],
|
||||
eqeqeq: ["error", "smart"],
|
||||
"import/no-extraneous-dependencies": [
|
||||
"error",
|
||||
{
|
||||
devDependencies: true,
|
||||
optionalDependencies: false,
|
||||
peerDependencies: false,
|
||||
},
|
||||
],
|
||||
"no-shadow": [
|
||||
"error",
|
||||
{
|
||||
hoist: "all",
|
||||
},
|
||||
],
|
||||
"prefer-const": "error",
|
||||
"import/order": [
|
||||
"error",
|
||||
{
|
||||
pathGroups: [{ pattern: "@lib/**", group: "unknown" }],
|
||||
groups: [
|
||||
["external", "builtin"],
|
||||
"unknown",
|
||||
"internal",
|
||||
["parent", "sibling", "index"],
|
||||
],
|
||||
alphabetize: {
|
||||
order: "asc",
|
||||
caseInsensitive: false,
|
||||
},
|
||||
"newlines-between": "always",
|
||||
pathGroupsExcludedImportTypes: ["builtin"],
|
||||
},
|
||||
],
|
||||
"import/namespace": "off",
|
||||
"sort-imports": [
|
||||
"error",
|
||||
{
|
||||
ignoreCase: true,
|
||||
ignoreDeclarationSort: true,
|
||||
ignoreMemberSort: false,
|
||||
memberSyntaxSortOrder: ["none", "all", "multiple", "single"],
|
||||
},
|
||||
],
|
||||
"padding-line-between-statements": [
|
||||
"error",
|
||||
{
|
||||
blankLine: "always",
|
||||
prev: "*",
|
||||
next: "return",
|
||||
},
|
||||
],
|
||||
"prefer-arrow/prefer-arrow-functions": [
|
||||
"error",
|
||||
{
|
||||
disallowPrototype: true,
|
||||
singleReturnOnly: false,
|
||||
classPropertiesAllowed: false,
|
||||
},
|
||||
],
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
paths: [
|
||||
{
|
||||
name: "lodash",
|
||||
message: "Please use lodash/{module} import instead",
|
||||
},
|
||||
{
|
||||
name: "aws-sdk",
|
||||
message: "Please use aws-sdk/{module} import instead",
|
||||
},
|
||||
{
|
||||
name: ".",
|
||||
message: "Please use explicit import file",
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
curly: ["error", "all"],
|
||||
},
|
||||
root: true,
|
||||
env: {
|
||||
es6: true,
|
||||
node: true,
|
||||
browser: true,
|
||||
},
|
||||
parserOptions: {
|
||||
ecmaVersion: 9,
|
||||
sourceType: "module",
|
||||
babelOptions: {
|
||||
presets: [require.resolve("next/babel")],
|
||||
},
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ["**/*.ts?(x)"],
|
||||
extends: [
|
||||
"plugin:@typescript-eslint/recommended",
|
||||
"plugin:@typescript-eslint/recommended-requiring-type-checking",
|
||||
"plugin:import/typescript",
|
||||
],
|
||||
parser: "@typescript-eslint/parser",
|
||||
parserOptions: {
|
||||
project: "./tsconfig.eslint.json",
|
||||
tsconfigRootDir: __dirname,
|
||||
sourceType: "module",
|
||||
},
|
||||
rules: {
|
||||
"@typescript-eslint/prefer-optional-chain": "error",
|
||||
"no-shadow": "off",
|
||||
"@typescript-eslint/no-shadow": "error",
|
||||
"@typescript-eslint/prefer-nullish-coalescing": "error",
|
||||
"@typescript-eslint/strict-boolean-expressions": [
|
||||
"error",
|
||||
{
|
||||
allowString: false,
|
||||
allowNumber: false,
|
||||
allowNullableObject: true,
|
||||
},
|
||||
],
|
||||
"@typescript-eslint/ban-ts-comment": [
|
||||
"error",
|
||||
{
|
||||
"ts-ignore": "allow-with-description",
|
||||
minimumDescriptionLength: 10,
|
||||
},
|
||||
],
|
||||
"@typescript-eslint/explicit-function-return-type": 0,
|
||||
"@typescript-eslint/explicit-member-accessibility": 0,
|
||||
"@typescript-eslint/camelcase": 0,
|
||||
"@typescript-eslint/interface-name-prefix": 0,
|
||||
"@typescript-eslint/explicit-module-boundary-types": "error",
|
||||
"@typescript-eslint/no-explicit-any": "error",
|
||||
"@typescript-eslint/no-unused-vars": "error",
|
||||
"@typescript-eslint/ban-types": [
|
||||
"error",
|
||||
{
|
||||
types: {
|
||||
FC: "Use `const MyComponent = (props: Props): JSX.Element` instead",
|
||||
SFC: "Use `const MyComponent = (props: Props): JSX.Element` instead",
|
||||
FunctionComponent:
|
||||
"Use `const MyComponent = (props: Props): JSX.Element` instead",
|
||||
"React.FC":
|
||||
"Use `const MyComponent = (props: Props): JSX.Element` instead",
|
||||
"React.SFC":
|
||||
"Use `const MyComponent = (props: Props): JSX.Element` instead",
|
||||
"React.FunctionComponent":
|
||||
"Use `const MyComponent = (props: Props): JSX.Element` instead",
|
||||
},
|
||||
extendDefaults: true,
|
||||
},
|
||||
],
|
||||
"@typescript-eslint/no-unnecessary-boolean-literal-compare": "error",
|
||||
"@typescript-eslint/no-unnecessary-condition": "error",
|
||||
"@typescript-eslint/no-unnecessary-type-arguments": "error",
|
||||
"@typescript-eslint/prefer-string-starts-ends-with": "error",
|
||||
"@typescript-eslint/switch-exhaustiveness-check": "error",
|
||||
"@typescript-eslint/restrict-template-expressions": [
|
||||
"error",
|
||||
{
|
||||
allowNumber: true,
|
||||
allowBoolean: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
@ -1,14 +0,0 @@
|
||||
{
|
||||
"extends": [
|
||||
"next/core-web-vitals",
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/recommended"
|
||||
],
|
||||
"plugins": ["@typescript-eslint"],
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"rules": {
|
||||
"no-unused-vars": "off",
|
||||
"@typescript-eslint/no-unused-vars": "error",
|
||||
"@typescript-eslint/no-explicit-any": "error"
|
||||
}
|
||||
}
|
4
frontend/.lintstagedrc.js
Normal file
4
frontend/.lintstagedrc.js
Normal file
@ -0,0 +1,4 @@
|
||||
module.exports = {
|
||||
"*": "prettier --ignore-unknown --write",
|
||||
"*.{js,ts, tsx}": "pnpm lint-fix",
|
||||
};
|
@ -1,6 +1,8 @@
|
||||
/* eslint-disable */
|
||||
import { useState } from "react";
|
||||
|
||||
import { useSupabase } from "@/app/supabase-provider";
|
||||
import { useToast } from "@/lib/hooks/useToast";
|
||||
import { useState } from "react";
|
||||
|
||||
export const useGoogleLogin = () => {
|
||||
const { supabase } = useSupabase();
|
||||
|
@ -1,3 +1,4 @@
|
||||
/* eslint-disable */
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
|
||||
import { useGoogleLogin } from "./hooks/useGoogleLogin";
|
||||
|
@ -1,8 +1,10 @@
|
||||
/* eslint-disable */
|
||||
"use client";
|
||||
import { useState } from "react";
|
||||
|
||||
import { useSupabase } from "@/app/supabase-provider";
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
import { useToast } from "@/lib/hooks/useToast";
|
||||
import { useState } from "react";
|
||||
|
||||
type MaginLinkLoginProps = {
|
||||
email: string;
|
||||
@ -21,6 +23,7 @@ export const MagicLinkLogin = ({ email, setEmail }: MaginLinkLoginProps) => {
|
||||
variant: "danger",
|
||||
text: "Please enter your email address",
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,9 @@
|
||||
/* eslint-disable */
|
||||
"use client";
|
||||
import Link from "next/link";
|
||||
import { redirect } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
|
||||
import { useSupabase } from "@/app/supabase-provider";
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
import Card from "@/lib/components/ui/Card";
|
||||
@ -6,9 +11,7 @@ import { Divider } from "@/lib/components/ui/Divider";
|
||||
import Field from "@/lib/components/ui/Field";
|
||||
import PageHeading from "@/lib/components/ui/PageHeading";
|
||||
import { useToast } from "@/lib/hooks/useToast";
|
||||
import Link from "next/link";
|
||||
import { redirect } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
|
||||
import { GoogleLoginButton } from "./components/GoogleLogin";
|
||||
import { MagicLinkLogin } from "./components/MagicLinkLogin";
|
||||
|
||||
|
@ -1,12 +1,14 @@
|
||||
/* eslint-disable */
|
||||
"use client";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
|
||||
import { useSupabase } from "@/app/supabase-provider";
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
import Card from "@/lib/components/ui/Card";
|
||||
import PageHeading from "@/lib/components/ui/PageHeading";
|
||||
import { useToast } from "@/lib/hooks/useToast";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useState } from "react";
|
||||
|
||||
export default function Logout() {
|
||||
const { supabase } = useSupabase();
|
||||
|
@ -1,12 +1,14 @@
|
||||
/* eslint-disable */
|
||||
"use client";
|
||||
import Link from "next/link";
|
||||
import { useState } from "react";
|
||||
|
||||
import { useSupabase } from "@/app/supabase-provider";
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
import Card from "@/lib/components/ui/Card";
|
||||
import Field from "@/lib/components/ui/Field";
|
||||
import PageHeading from "@/lib/components/ui/PageHeading";
|
||||
import { useToast } from "@/lib/hooks/useToast";
|
||||
import Link from "next/link";
|
||||
import { useState } from "react";
|
||||
|
||||
export default function SignUp() {
|
||||
const { supabase } = useSupabase();
|
||||
|
@ -1,5 +1,4 @@
|
||||
import Card from "@/lib/components/ui/Card";
|
||||
import { FC, ReactNode } from "react";
|
||||
import { ReactNode } from "react";
|
||||
import {
|
||||
GiArtificialIntelligence,
|
||||
GiBrain,
|
||||
@ -9,7 +8,9 @@ import {
|
||||
GiOpenBook,
|
||||
} from "react-icons/gi";
|
||||
|
||||
const Features: FC = () => {
|
||||
import Card from "@/lib/components/ui/Card";
|
||||
|
||||
const Features = (): JSX.Element => {
|
||||
return (
|
||||
<section className="my-20 text-center flex flex-col items-center justify-center gap-10">
|
||||
<div>
|
||||
@ -58,7 +59,7 @@ interface FeatureProps {
|
||||
desc: string;
|
||||
}
|
||||
|
||||
const Feature: FC<FeatureProps> = ({ title, desc, icon }) => {
|
||||
const Feature = ({ title, desc, icon }: FeatureProps): JSX.Element => {
|
||||
return (
|
||||
<Card className="p-10 max-w-xs flex flex-col gap-5 w-full">
|
||||
{icon}
|
||||
|
@ -1,11 +1,12 @@
|
||||
"use client";
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
import { motion, useScroll, useSpring, useTransform } from "framer-motion";
|
||||
import Link from "next/link";
|
||||
import { FC, useRef } from "react";
|
||||
import { useRef } from "react";
|
||||
import { MdNorthEast } from "react-icons/md";
|
||||
|
||||
const Hero: FC = () => {
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
|
||||
const Hero = (): JSX.Element => {
|
||||
const targetRef = useRef<HTMLDivElement | null>(null);
|
||||
const { scrollYProgress } = useScroll({
|
||||
target: targetRef,
|
||||
@ -19,6 +20,7 @@ const Hero: FC = () => {
|
||||
if (pos === 1) {
|
||||
return "relative";
|
||||
}
|
||||
|
||||
return "sticky";
|
||||
});
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
import Features from "./Features";
|
||||
import Hero from "./Hero";
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
export default function HomePage() {
|
||||
import Features from "./Features";
|
||||
import Hero from "./Hero";
|
||||
|
||||
const HomePage = (): JSX.Element => {
|
||||
if (process.env.NEXT_PUBLIC_ENV === "local") {
|
||||
redirect("/upload");
|
||||
}
|
||||
@ -13,4 +14,6 @@ export default function HomePage() {
|
||||
<Features />
|
||||
</main>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default HomePage;
|
||||
|
@ -1,8 +1,11 @@
|
||||
/* eslint-disable */
|
||||
"use client";
|
||||
import PageHeading from "@/lib/components/ui/PageHeading";
|
||||
import useChatsContext from "@/lib/context/ChatsProvider/hooks/useChatsContext";
|
||||
import { UUID } from "crypto";
|
||||
import { useEffect } from "react";
|
||||
|
||||
import PageHeading from "@/lib/components/ui/PageHeading";
|
||||
import useChatsContext from "@/lib/context/ChatsProvider/hooks/useChatsContext";
|
||||
|
||||
import { ChatInput, ChatMessages } from "../components";
|
||||
|
||||
interface ChatPageProps {
|
||||
@ -18,7 +21,9 @@ export default function ChatPage({ params }: ChatPageProps) {
|
||||
|
||||
useEffect(() => {
|
||||
// if (chatId)
|
||||
if (!chatId) resetChat();
|
||||
if (!chatId) {
|
||||
resetChat();
|
||||
}
|
||||
fetchChat(chatId);
|
||||
}, [fetchChat, chatId]);
|
||||
|
||||
|
@ -1,9 +1,10 @@
|
||||
"use client";
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
import Link from "next/link";
|
||||
import { MdSettings } from "react-icons/md";
|
||||
|
||||
export function ConfigButton() {
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
|
||||
export const ConfigButton = (): JSX.Element => {
|
||||
return (
|
||||
<Link href={"/config"}>
|
||||
<Button className="p-2 sm:px-3" variant={"tertiary"}>
|
||||
@ -11,4 +12,4 @@ export function ConfigButton() {
|
||||
</Button>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
@ -1,9 +1,11 @@
|
||||
/* eslint-disable */
|
||||
"use client";
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
import { useSpeech } from "@/lib/context/ChatsProvider/hooks/useSpeech";
|
||||
import { MdMic, MdMicOff } from "react-icons/md";
|
||||
|
||||
export function MicButton() {
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
import { useSpeech } from "@/lib/context/ChatsProvider/hooks/useSpeech";
|
||||
|
||||
export const MicButton = (): JSX.Element => {
|
||||
const { isListening, speechSupported, startListening } = useSpeech();
|
||||
|
||||
return (
|
||||
@ -21,4 +23,4 @@ export function MicButton() {
|
||||
)}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
@ -1,17 +1,22 @@
|
||||
/* eslint-disable */
|
||||
"use client";
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
import useChatsContext from "@/lib/context/ChatsProvider/hooks/useChatsContext";
|
||||
|
||||
import { ConfigButton } from "./ConfigButton";
|
||||
import { MicButton } from "./MicButton";
|
||||
|
||||
export function ChatInput() {
|
||||
export const ChatInput = (): JSX.Element => {
|
||||
const { isSendingMessage, sendMessage, setMessage, message, chat } =
|
||||
useChatsContext();
|
||||
|
||||
return (
|
||||
<form
|
||||
onSubmit={(e) => {
|
||||
e.preventDefault();
|
||||
if (!isSendingMessage) sendMessage(chat?.chatId);
|
||||
if (!isSendingMessage) {
|
||||
sendMessage(chat?.chatId);
|
||||
}
|
||||
}}
|
||||
className="sticky bottom-0 p-5 bg-white dark:bg-black rounded-t-md border border-black/10 dark:border-white/25 border-b-0 w-full max-w-3xl flex items-center justify-center gap-2 z-20"
|
||||
>
|
||||
@ -22,7 +27,9 @@ export function ChatInput() {
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === "Enter" && !e.shiftKey) {
|
||||
e.preventDefault(); // Prevents the newline from being entered in the textarea
|
||||
if (!isSendingMessage) sendMessage(chat?.chatId); // Call the submit function here
|
||||
if (!isSendingMessage) {
|
||||
sendMessage(chat?.chatId);
|
||||
} // Call the submit function here
|
||||
}
|
||||
}}
|
||||
className="w-full p-2 border border-gray-300 dark:border-gray-500 outline-none rounded dark:bg-gray-800"
|
||||
@ -41,4 +48,4 @@ export function ChatInput() {
|
||||
</div>
|
||||
</form>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
@ -1,9 +1,11 @@
|
||||
/* eslint-disable */
|
||||
"use client";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { forwardRef, Ref } from "react";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
|
||||
const ChatMessage = forwardRef(
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
export const ChatMessage = forwardRef(
|
||||
(
|
||||
{
|
||||
speaker,
|
||||
@ -46,5 +48,3 @@ const ChatMessage = forwardRef(
|
||||
);
|
||||
|
||||
ChatMessage.displayName = "ChatMessage";
|
||||
|
||||
export default ChatMessage;
|
||||
|
@ -1,26 +1,32 @@
|
||||
/* eslint-disable */
|
||||
"use client";
|
||||
import { useEffect, useRef } from "react";
|
||||
|
||||
import Card from "@/lib/components/ui/Card";
|
||||
import useChatsContext from "@/lib/context/ChatsProvider/hooks/useChatsContext";
|
||||
import { FC, useEffect, useRef } from "react";
|
||||
import ChatMessage from "./ChatMessage";
|
||||
import { ChatMessage } from "./ChatMessage";
|
||||
|
||||
export const ChatMessages: FC = () => {
|
||||
export const ChatMessages = (): JSX.Element => {
|
||||
const lastChatRef = useRef<HTMLDivElement | null>(null);
|
||||
|
||||
const { chat } = useChatsContext();
|
||||
|
||||
useEffect(() => {
|
||||
if (!chat || !lastChatRef.current) return;
|
||||
if (!chat || !lastChatRef.current) {
|
||||
return;
|
||||
}
|
||||
|
||||
// if (chat.history.length > 2) {
|
||||
lastChatRef.current?.scrollIntoView({
|
||||
lastChatRef.current.scrollIntoView({
|
||||
behavior: "smooth",
|
||||
block: "end",
|
||||
});
|
||||
// }
|
||||
}, [chat, lastChatRef]);
|
||||
|
||||
if (!chat) return null;
|
||||
if (!chat) {
|
||||
return <></>;
|
||||
}
|
||||
|
||||
return (
|
||||
<Card className="p-5 max-w-3xl w-full flex flex-col h-full mb-8">
|
||||
|
@ -1,10 +1,12 @@
|
||||
import { cn } from "@/lib/utils";
|
||||
/* eslint-disable */
|
||||
import { UUID } from "crypto";
|
||||
import Link from "next/link";
|
||||
import { usePathname } from "next/navigation";
|
||||
import { FC } from "react";
|
||||
import { FiTrash2 } from "react-icons/fi";
|
||||
import { MdChatBubbleOutline } from "react-icons/md";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
import { Chat } from "../../../../lib/types/Chat";
|
||||
|
||||
interface ChatsListItemProps {
|
||||
@ -12,7 +14,10 @@ interface ChatsListItemProps {
|
||||
deleteChat: (id: UUID) => void;
|
||||
}
|
||||
|
||||
const ChatsListItem: FC<ChatsListItemProps> = ({ chat, deleteChat }) => {
|
||||
const ChatsListItem = ({
|
||||
chat,
|
||||
deleteChat,
|
||||
}: ChatsListItemProps): JSX.Element => {
|
||||
const pathname = usePathname()?.split("/").at(-1);
|
||||
const selected = chat.chatId === pathname;
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
import Link from "next/link";
|
||||
import { BsPlusSquare } from "react-icons/bs";
|
||||
|
||||
export const NewChatButton = () => (
|
||||
export const NewChatButton = (): JSX.Element => (
|
||||
<Link
|
||||
href="/chat"
|
||||
className="px-4 py-2 mx-4 my-2 border border-primary bg-white dark:bg-black hover:text-white hover:bg-primary shadow-lg rounded-lg flex items-center justify-center sticky top-2 z-20"
|
||||
|
@ -1,12 +1,15 @@
|
||||
/* eslint-disable */
|
||||
"use client";
|
||||
import useChatsContext from "@/lib/context/ChatsProvider/hooks/useChatsContext";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { MotionConfig, motion } from "framer-motion";
|
||||
import { useState } from "react";
|
||||
import { MdChevronRight } from "react-icons/md";
|
||||
import useChatsContext from "@/lib/context/ChatsProvider/hooks/useChatsContext";
|
||||
|
||||
import ChatsListItem from "./ChatsListItem";
|
||||
import { NewChatButton } from "./NewChatButton";
|
||||
export function ChatsList() {
|
||||
|
||||
export const ChatsList = (): JSX.Element => {
|
||||
const { allChats, deleteChat } = useChatsContext();
|
||||
|
||||
const [open, setOpen] = useState(false);
|
||||
@ -69,4 +72,4 @@ export function ChatsList() {
|
||||
</motion.div>
|
||||
</MotionConfig>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
export * from "./ChatMessages";
|
||||
export * from "./ChatMessages/ChatInput";
|
||||
export * from "./ChatMessages/ChatMessage";
|
||||
export * from "./ChatMessages";
|
||||
export * from "./ChatsList";
|
||||
|
@ -1,17 +1,21 @@
|
||||
"use client";
|
||||
import { ChatsProvider } from "@/lib/context/ChatsProvider/chats-provider";
|
||||
import { redirect } from "next/navigation";
|
||||
import { FC, ReactNode } from "react";
|
||||
import { useSupabase } from "../supabase-provider";
|
||||
import { ReactNode } from "react";
|
||||
|
||||
import { ChatsProvider } from "@/lib/context/ChatsProvider/chats-provider";
|
||||
|
||||
import { ChatsList } from "./components";
|
||||
import { useSupabase } from "../supabase-provider";
|
||||
|
||||
interface LayoutProps {
|
||||
children?: ReactNode;
|
||||
}
|
||||
|
||||
const Layout: FC<LayoutProps> = ({ children }) => {
|
||||
const Layout = ({ children }: LayoutProps): JSX.Element => {
|
||||
const { session } = useSupabase();
|
||||
if (!session) redirect("/login");
|
||||
if (!session) {
|
||||
redirect("/login");
|
||||
}
|
||||
|
||||
return (
|
||||
<ChatsProvider>
|
||||
|
@ -1,8 +1,10 @@
|
||||
/* eslint-disable */
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
import { useAxios } from "@/lib/useAxios";
|
||||
import { useState } from "react";
|
||||
|
||||
export const ApiKeyConfig = (): JSX.Element => {
|
||||
const [apiKey, setApiKey] = useState("");
|
||||
@ -40,13 +42,13 @@ export const ApiKeyConfig = (): JSX.Element => {
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<div className="flex items-center space-x-4">
|
||||
{!apiKey && (
|
||||
{apiKey === "" && (
|
||||
<Button variant="secondary" onClick={handleCreateClick}>
|
||||
Create New Key
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
{apiKey && (
|
||||
{apiKey !== "" && (
|
||||
<div className="flex items-center space-x-4">
|
||||
<span className="text-gray-600">{apiKey}</span>
|
||||
<Button variant="secondary" onClick={handleCopyClick}>
|
||||
|
@ -1,8 +1,10 @@
|
||||
/* eslint-disable */
|
||||
"use client";
|
||||
|
||||
import { UseFormRegister } from "react-hook-form";
|
||||
|
||||
import Field from "@/lib/components/ui/Field";
|
||||
import { BrainConfig } from "@/lib/context/BrainConfigProvider/types";
|
||||
import { UseFormRegister } from "react-hook-form";
|
||||
|
||||
interface BackendConfigProps {
|
||||
register: UseFormRegister<BrainConfig>;
|
||||
|
@ -1,7 +1,10 @@
|
||||
/* eslint-disable */
|
||||
"use client";
|
||||
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
import { useRouter } from "next/navigation";
|
||||
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
|
||||
import { useConfig } from "../hooks/useConfig";
|
||||
import { BackendConfig } from "./BackendConfig";
|
||||
import { ModelConfig } from "./ModelConfig";
|
||||
|
@ -1,5 +1,8 @@
|
||||
/* eslint-disable */
|
||||
"use client";
|
||||
|
||||
import { UseFormRegister } from "react-hook-form";
|
||||
|
||||
import Field from "@/lib/components/ui/Field";
|
||||
import {
|
||||
BrainConfig,
|
||||
@ -9,7 +12,6 @@ import {
|
||||
models,
|
||||
paidModels,
|
||||
} from "@/lib/context/BrainConfigProvider/types";
|
||||
import { UseFormRegister } from "react-hook-form";
|
||||
|
||||
interface ModelConfigProps {
|
||||
register: UseFormRegister<BrainConfig>;
|
||||
|
@ -1,8 +1,10 @@
|
||||
/* eslint-disable */
|
||||
"use client";
|
||||
|
||||
import Link from "next/link";
|
||||
|
||||
import { useSupabase } from "@/app/supabase-provider";
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
import Link from "next/link";
|
||||
|
||||
export const UserAccountSection = (): JSX.Element => {
|
||||
const { session } = useSupabase();
|
||||
|
@ -1,8 +1,9 @@
|
||||
import { useToast } from "@/lib/hooks/useToast";
|
||||
/* eslint-disable */
|
||||
import { useEffect } from "react";
|
||||
import { useForm } from "react-hook-form";
|
||||
|
||||
import { useBrainConfig } from "@/lib/context/BrainConfigProvider/hooks/useBrainConfig";
|
||||
import { useEffect } from "react";
|
||||
import { useToast } from "@/lib/hooks/useToast";
|
||||
|
||||
export const useConfig = () => {
|
||||
const { config, updateConfig, resetConfig } = useBrainConfig();
|
||||
|
@ -1,3 +1,4 @@
|
||||
/* eslint-disable */
|
||||
"use client";
|
||||
import { redirect } from "next/navigation";
|
||||
|
||||
@ -6,7 +7,7 @@ import { ConfigForm, ConfigTitle } from "./components";
|
||||
import { ApiKeyConfig } from "./components/ApiKeyConfig";
|
||||
|
||||
// TODO: Use states instead of NEXTJS router to open and close modal
|
||||
export default function ConfigPage() {
|
||||
const ConfigPage = (): JSX.Element => {
|
||||
const { session } = useSupabase();
|
||||
|
||||
if (session === null) {
|
||||
@ -22,4 +23,6 @@ export default function ConfigPage() {
|
||||
</section>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default ConfigPage;
|
||||
|
@ -1,5 +1,8 @@
|
||||
import { useAxios } from "@/lib/useAxios";
|
||||
/* eslint-disable */
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
import { useAxios } from "@/lib/useAxios";
|
||||
|
||||
import { useSupabase } from "../../supabase-provider";
|
||||
|
||||
interface DocumentDataProps {
|
||||
|
@ -1,19 +1,22 @@
|
||||
/* eslint-disable */
|
||||
"use client";
|
||||
import {
|
||||
Dispatch,
|
||||
forwardRef,
|
||||
RefObject,
|
||||
SetStateAction,
|
||||
useState,
|
||||
} from "react";
|
||||
|
||||
import { useSupabase } from "@/app/supabase-provider";
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
import { AnimatedCard } from "@/lib/components/ui/Card";
|
||||
import Ellipsis from "@/lib/components/ui/Ellipsis";
|
||||
import Modal from "@/lib/components/ui/Modal";
|
||||
import { useToast } from "@/lib/hooks/useToast";
|
||||
import { Document } from "@/lib/types/Document";
|
||||
import { useAxios } from "@/lib/useAxios";
|
||||
import {
|
||||
Dispatch,
|
||||
RefObject,
|
||||
SetStateAction,
|
||||
forwardRef,
|
||||
useState,
|
||||
} from "react";
|
||||
import { Document } from "../../../lib/types/Document";
|
||||
|
||||
import DocumentData from "./DocumentData";
|
||||
|
||||
interface DocumentProps {
|
||||
|
@ -1,17 +1,19 @@
|
||||
/* eslint-disable */
|
||||
"use client";
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
import Spinner from "@/lib/components/ui/Spinner";
|
||||
|
||||
import { Document } from "@/lib/types/Document";
|
||||
import { useAxios } from "@/lib/useAxios";
|
||||
import { AnimatePresence, motion } from "framer-motion";
|
||||
import Link from "next/link";
|
||||
import { redirect } from "next/navigation";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
import Spinner from "@/lib/components/ui/Spinner";
|
||||
import { Document } from "@/lib/types/Document";
|
||||
import { useAxios } from "@/lib/useAxios";
|
||||
|
||||
import { useSupabase } from "../supabase-provider";
|
||||
import DocumentItem from "./DocumentItem";
|
||||
|
||||
export default function ExplorePage() {
|
||||
const ExplorePage = (): JSX.Element => {
|
||||
const [documents, setDocuments] = useState<Document[]>([]);
|
||||
const [isPending, setIsPending] = useState(true);
|
||||
const { session } = useSupabase();
|
||||
@ -79,4 +81,6 @@ export default function ExplorePage() {
|
||||
</section>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default ExplorePage;
|
||||
|
@ -1,13 +1,13 @@
|
||||
@import 'tailwindcss/base';
|
||||
@import 'tailwindcss/components';
|
||||
@import 'tailwindcss/utilities';
|
||||
|
||||
@import "tailwindcss/base";
|
||||
@import "tailwindcss/components";
|
||||
@import "tailwindcss/utilities";
|
||||
|
||||
main {
|
||||
@apply max-w-screen-xl mx-auto flex flex-col;
|
||||
}
|
||||
|
||||
header, section {
|
||||
header,
|
||||
section {
|
||||
@apply px-5 md:px-10;
|
||||
}
|
||||
|
||||
@ -43,4 +43,4 @@ a {
|
||||
max-height: 60vh; /* Adjust this value based on the desired maximum height */
|
||||
overflow-y: auto; /* Enable vertical scroll if the content exceeds the maximum height */
|
||||
padding-right: 1rem; /* Optional: Add some padding if the scrollbar appears, so the text is not squished */
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
import Footer from "@/lib/components/Footer";
|
||||
import { NavBar } from "@/lib/components/NavBar";
|
||||
import { ToastProvider } from "@/lib/components/ui/Toast";
|
||||
import { createServerComponentSupabaseClient } from "@supabase/auth-helpers-nextjs";
|
||||
import { Analytics } from "@vercel/analytics/react";
|
||||
import { Inter } from "next/font/google";
|
||||
import { cookies, headers } from "next/headers";
|
||||
import { BrainConfigProvider } from "../lib/context/BrainConfigProvider/brain-config-provider";
|
||||
|
||||
import Footer from "@/lib/components/Footer";
|
||||
import { NavBar } from "@/lib/components/NavBar";
|
||||
import { ToastProvider } from "@/lib/components/ui/Toast";
|
||||
import { BrainConfigProvider } from "@/lib/context/BrainConfigProvider/brain-config-provider";
|
||||
|
||||
import "./globals.css";
|
||||
import SupabaseProvider from "./supabase-provider";
|
||||
|
||||
@ -17,11 +19,11 @@ export const metadata = {
|
||||
"Quivr is your second brain in the cloud, designed to easily store and retrieve unstructured information.",
|
||||
};
|
||||
|
||||
export default async function RootLayout({
|
||||
const RootLayout = async ({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
}): Promise<JSX.Element> => {
|
||||
const supabase = createServerComponentSupabaseClient({
|
||||
headers,
|
||||
cookies,
|
||||
@ -49,4 +51,6 @@ export default async function RootLayout({
|
||||
</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default RootLayout;
|
||||
|
@ -1,56 +1,59 @@
|
||||
'use client'
|
||||
"use client";
|
||||
|
||||
import { createContext, useContext, useEffect, useState } from 'react'
|
||||
import { Session, createBrowserSupabaseClient } from '@supabase/auth-helpers-nextjs'
|
||||
import { useRouter } from 'next/navigation'
|
||||
import type { SupabaseClient } from "@supabase/auth-helpers-nextjs";
|
||||
import {
|
||||
createBrowserSupabaseClient,
|
||||
Session,
|
||||
} from "@supabase/auth-helpers-nextjs";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { createContext, useContext, useEffect, useState } from "react";
|
||||
|
||||
import type { SupabaseClient } from '@supabase/auth-helpers-nextjs'
|
||||
|
||||
|
||||
type MaybeSession = Session | null
|
||||
type MaybeSession = Session | null;
|
||||
|
||||
type SupabaseContext = {
|
||||
supabase: SupabaseClient
|
||||
session: MaybeSession
|
||||
}
|
||||
supabase: SupabaseClient;
|
||||
session: MaybeSession;
|
||||
};
|
||||
|
||||
const Context = createContext<SupabaseContext | undefined>(undefined)
|
||||
const Context = createContext<SupabaseContext | undefined>(undefined);
|
||||
|
||||
export default function SupabaseProvider({
|
||||
const SupabaseProvider = ({
|
||||
children,
|
||||
session,
|
||||
}: {
|
||||
children: React.ReactNode
|
||||
session: MaybeSession
|
||||
}) {
|
||||
const [supabase] = useState(() => createBrowserSupabaseClient())
|
||||
const router = useRouter()
|
||||
children: React.ReactNode;
|
||||
session: MaybeSession;
|
||||
}): JSX.Element => {
|
||||
const [supabase] = useState(() => createBrowserSupabaseClient());
|
||||
const router = useRouter();
|
||||
|
||||
useEffect(() => {
|
||||
const {
|
||||
data: { subscription },
|
||||
} = supabase.auth.onAuthStateChange(() => {
|
||||
router.refresh()
|
||||
})
|
||||
router.refresh();
|
||||
});
|
||||
|
||||
return () => {
|
||||
subscription.unsubscribe()
|
||||
}
|
||||
}, [router, supabase])
|
||||
subscription.unsubscribe();
|
||||
};
|
||||
}, [router, supabase]);
|
||||
|
||||
return (
|
||||
<Context.Provider value={{ supabase, session }}>
|
||||
<>{children}</>
|
||||
</Context.Provider>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export const useSupabase = () => {
|
||||
const context = useContext(Context)
|
||||
export const useSupabase = (): SupabaseContext => {
|
||||
const context = useContext(Context);
|
||||
|
||||
if (context === undefined) {
|
||||
throw new Error('useSupabase must be used inside SupabaseProvider')
|
||||
throw new Error("useSupabase must be used inside SupabaseProvider");
|
||||
}
|
||||
|
||||
return context
|
||||
}
|
||||
return context;
|
||||
};
|
||||
|
||||
export default SupabaseProvider;
|
||||
|
@ -1,6 +1,7 @@
|
||||
export const isValidUrl = (string: string) => {
|
||||
export const isValidUrl = (string: string): boolean => {
|
||||
try {
|
||||
new URL(string);
|
||||
|
||||
return true;
|
||||
} catch (_) {
|
||||
return false;
|
||||
|
@ -1,8 +1,11 @@
|
||||
/* eslint-disable */
|
||||
import { redirect } from "next/navigation";
|
||||
import { useCallback, useRef, useState } from "react";
|
||||
|
||||
import { useSupabase } from "@/app/supabase-provider";
|
||||
import { useToast } from "@/lib/hooks/useToast";
|
||||
import { useAxios } from "@/lib/useAxios";
|
||||
import { redirect } from "next/navigation";
|
||||
import { useCallback, useRef, useState } from "react";
|
||||
|
||||
import { isValidUrl } from "../helpers/isValidUrl";
|
||||
|
||||
export const useCrawler = () => {
|
||||
@ -26,6 +29,7 @@ export const useCrawler = () => {
|
||||
variant: "danger",
|
||||
text: "Invalid URL",
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2,10 +2,12 @@
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
import Card from "@/lib/components/ui/Card";
|
||||
import Field from "@/lib/components/ui/Field";
|
||||
|
||||
import { useCrawler } from "./hooks/useCrawler";
|
||||
|
||||
export const Crawler = (): JSX.Element => {
|
||||
const { urlInputRef, isCrawling, crawlWebsite } = useCrawler();
|
||||
|
||||
return (
|
||||
<div className="w-full">
|
||||
<div className="flex justify-center gap-5 px-6">
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* eslint-disable */
|
||||
import { motion } from "framer-motion";
|
||||
import { Dispatch, RefObject, SetStateAction, forwardRef } from "react";
|
||||
import { Dispatch, forwardRef, RefObject, SetStateAction } from "react";
|
||||
import { MdClose } from "react-icons/md";
|
||||
|
||||
interface FileComponentProps {
|
||||
|
@ -1,10 +1,12 @@
|
||||
import { useSupabase } from "@/app/supabase-provider";
|
||||
import { useToast } from "@/lib/hooks/useToast";
|
||||
import { useAxios } from "@/lib/useAxios";
|
||||
/* eslint-disable */
|
||||
import { redirect } from "next/navigation";
|
||||
import { useCallback, useState } from "react";
|
||||
import { FileRejection, useDropzone } from "react-dropzone";
|
||||
|
||||
import { useSupabase } from "@/app/supabase-provider";
|
||||
import { useToast } from "@/lib/hooks/useToast";
|
||||
import { useAxios } from "@/lib/useAxios";
|
||||
|
||||
export const useFileUploader = () => {
|
||||
const [isPending, setIsPending] = useState(false);
|
||||
const { publish } = useToast();
|
||||
@ -44,6 +46,7 @@ export const useFileUploader = () => {
|
||||
const onDrop = (acceptedFiles: File[], fileRejections: FileRejection[]) => {
|
||||
if (fileRejections.length > 0) {
|
||||
publish({ variant: "danger", text: "File too big." });
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -69,6 +72,7 @@ export const useFileUploader = () => {
|
||||
text: "Please, add files to upload",
|
||||
variant: "warning",
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
setIsPending(true);
|
||||
|
@ -1,7 +1,10 @@
|
||||
/* eslint-disable */
|
||||
"use client";
|
||||
import { AnimatePresence } from "framer-motion";
|
||||
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
import Card from "@/lib/components/ui/Card";
|
||||
import { AnimatePresence } from "framer-motion";
|
||||
|
||||
import FileComponent from "./components/FileComponent";
|
||||
import { useFileUploader } from "./hooks/useFileUploader";
|
||||
|
||||
|
@ -1,12 +1,14 @@
|
||||
"use client";
|
||||
import Link from "next/link";
|
||||
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
import { Divider } from "@/lib/components/ui/Divider";
|
||||
import PageHeading from "@/lib/components/ui/PageHeading";
|
||||
import Link from "next/link";
|
||||
|
||||
import { Crawler } from "./components/Crawler";
|
||||
import { FileUploader } from "./components/FileUploader";
|
||||
|
||||
export default function UploadPage() {
|
||||
const UploadPage = (): JSX.Element => {
|
||||
return (
|
||||
<main className="pt-10">
|
||||
<PageHeading
|
||||
@ -25,4 +27,6 @@ export default function UploadPage() {
|
||||
</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default UploadPage;
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { GiBrain } from "react-icons/gi";
|
||||
|
||||
import { UserStats } from "../../../lib/types/User";
|
||||
|
||||
export const BrainConsumption = (userStats: UserStats): JSX.Element => {
|
||||
@ -27,6 +28,7 @@ export const BrainConsumption = (userStats: UserStats): JSX.Element => {
|
||||
className="fill-pink-300 stroke-black stoke-1"
|
||||
/>
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center w-fit">
|
||||
<div className="w-24 h-24 relative">
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { HTMLAttributes } from "react";
|
||||
|
||||
import { UserStats } from "../../../lib/types/User";
|
||||
|
||||
interface DateComponentProps extends HTMLAttributes<HTMLSpanElement> {
|
||||
|
@ -1,5 +1,4 @@
|
||||
"use client";
|
||||
import { FC } from "react";
|
||||
import {
|
||||
VictoryContainer,
|
||||
VictoryPie,
|
||||
@ -12,26 +11,29 @@ interface BrainSpaceChartProps extends VictoryPieProps {
|
||||
max_brain_size: number;
|
||||
}
|
||||
|
||||
const BrainSpaceChart: FC<BrainSpaceChartProps> = ({
|
||||
const BrainSpaceChart = ({
|
||||
current_brain_size,
|
||||
max_brain_size,
|
||||
...props
|
||||
}) => {
|
||||
}: BrainSpaceChartProps): JSX.Element => {
|
||||
return (
|
||||
<VictoryPie
|
||||
data={[
|
||||
{ x: "Used", y: current_brain_size },
|
||||
{ x: "Unused", y: max_brain_size - current_brain_size },
|
||||
]}
|
||||
containerComponent={
|
||||
<VictoryContainer
|
||||
className="bg-white rounded-md w-full h-full"
|
||||
responsive={true}
|
||||
/>
|
||||
}
|
||||
{...props}
|
||||
theme={VictoryTheme.material}
|
||||
/>
|
||||
<>
|
||||
{/* @ts-expect-error Server Component */}
|
||||
<VictoryPie
|
||||
data={[
|
||||
{ x: "Used", y: current_brain_size },
|
||||
{ x: "Unused", y: max_brain_size - current_brain_size },
|
||||
]}
|
||||
containerComponent={
|
||||
<VictoryContainer
|
||||
className="bg-white rounded-md w-full h-full"
|
||||
responsive={true}
|
||||
/>
|
||||
}
|
||||
{...props}
|
||||
theme={VictoryTheme.material}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* eslint-disable */
|
||||
"use client";
|
||||
import { format, subDays } from "date-fns";
|
||||
import React from "react";
|
||||
import {
|
||||
VictoryAxis,
|
||||
VictoryChart,
|
||||
@ -20,14 +20,15 @@ interface RequestsPerDayChartProps extends VictoryChartProps {
|
||||
requests_stats: RequestStat[];
|
||||
}
|
||||
|
||||
export const RequestsPerDayChart: React.FC<RequestsPerDayChartProps> = ({
|
||||
export const RequestsPerDayChart = ({
|
||||
requests_stats,
|
||||
...props
|
||||
}) => {
|
||||
}: RequestsPerDayChartProps): JSX.Element => {
|
||||
const data = Array.from({ length: 7 }, (_, i) => subDays(new Date(), i))
|
||||
.map((date) => {
|
||||
const dateString = format(date, "yyyyMMdd");
|
||||
const stat = requests_stats.find((s) => s.date === dateString);
|
||||
|
||||
return {
|
||||
date: format(date, "MM/dd/yyyy"),
|
||||
requests_count: stat ? stat.requests_count : 0,
|
||||
@ -50,12 +51,15 @@ export const RequestsPerDayChart: React.FC<RequestsPerDayChartProps> = ({
|
||||
}}
|
||||
{...props}
|
||||
>
|
||||
{/* @ts-expect-error Server Component */}
|
||||
<VictoryAxis
|
||||
tickFormat={(tick) => {
|
||||
return `${tick.split("/")[0]}/${tick.split("/")[1]}`;
|
||||
}}
|
||||
/>
|
||||
{/* @ts-expect-error Server Component */}
|
||||
<VictoryAxis dependentAxis />
|
||||
{/* @ts-expect-error Server Component */}
|
||||
<VictoryLine data={data} x="date" y="requests_count" />
|
||||
</VictoryChart>
|
||||
);
|
||||
|
@ -1,10 +1,13 @@
|
||||
/* eslint-disable */
|
||||
"use client";
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
import { cn } from "@/lib/utils";
|
||||
import Link from "next/link";
|
||||
import prettyBytes from "pretty-bytes";
|
||||
import { HTMLAttributes } from "react";
|
||||
import { UserStats } from "../../../lib/types/User";
|
||||
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
import { UserStats } from "@/lib/types/User";
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
import { BrainConsumption } from "./BrainConsumption";
|
||||
import { DateComponent } from "./Date";
|
||||
import BrainSpaceChart from "./Graphs/BrainSpaceChart";
|
||||
@ -13,6 +16,7 @@ import { RequestsPerDayChart } from "./Graphs/RequestsPerDayChart";
|
||||
export const UserStatistics = (userStats: UserStats): JSX.Element => {
|
||||
const { email, current_brain_size, max_brain_size, date, requests_stats } =
|
||||
userStats;
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="flex flex-col sm:flex-row sm:items-center py-10 gap-5">
|
||||
|
@ -1 +1 @@
|
||||
export { UserStatistics } from "./UserStatistics";
|
||||
export { UserStatistics } from "./UserStatistics";
|
||||
|
@ -1,13 +1,16 @@
|
||||
/* eslint-disable */
|
||||
"use client";
|
||||
import Spinner from "@/lib/components/ui/Spinner";
|
||||
import { useAxios } from "@/lib/useAxios";
|
||||
import { redirect } from "next/navigation";
|
||||
import { useEffect, useState } from "react";
|
||||
import { UserStats } from "../../lib/types/User";
|
||||
|
||||
import Spinner from "@/lib/components/ui/Spinner";
|
||||
import { UserStats } from "@/lib/types/User";
|
||||
import { useAxios } from "@/lib/useAxios";
|
||||
|
||||
import { useSupabase } from "../supabase-provider";
|
||||
import { UserStatistics } from "./components/UserStatistics";
|
||||
|
||||
export default function UserPage() {
|
||||
const UserPage = (): JSX.Element => {
|
||||
const [userStats, setUserStats] = useState<UserStats>();
|
||||
const { session } = useSupabase();
|
||||
const { axiosInstance } = useAxios();
|
||||
@ -57,4 +60,5 @@ export default function UserPage() {
|
||||
</section>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
};
|
||||
export default UserPage;
|
||||
|
@ -1,4 +1,4 @@
|
||||
const Footer = () => {
|
||||
const Footer = (): JSX.Element => {
|
||||
return (
|
||||
<footer className="bg-white dark:bg-black border-t dark:border-white/10 mt-auto py-10">
|
||||
<div className="max-w-screen-xl mx-auto flex justify-center items-center gap-4">
|
||||
|
@ -1,3 +1,4 @@
|
||||
/* eslint-disable */
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
|
||||
export const useHeader = () => {
|
||||
@ -16,6 +17,7 @@ export const useHeader = () => {
|
||||
};
|
||||
|
||||
window.addEventListener("scroll", handleScroll);
|
||||
|
||||
return () => window.removeEventListener("scroll", handleScroll);
|
||||
}, []);
|
||||
|
||||
|
@ -1,7 +1,12 @@
|
||||
import { motion } from "framer-motion";
|
||||
|
||||
import { useHeader } from "./hooks/useHeader";
|
||||
|
||||
export const Header = ({ children }: { children: React.ReactNode }) => {
|
||||
export const Header = ({
|
||||
children,
|
||||
}: {
|
||||
children: React.ReactNode;
|
||||
}): JSX.Element => {
|
||||
const { hidden } = useHeader();
|
||||
|
||||
return (
|
||||
|
@ -1,7 +1,7 @@
|
||||
import Image from "next/image";
|
||||
import Link from "next/link";
|
||||
|
||||
export const Logo = () => {
|
||||
export const Logo = (): JSX.Element => {
|
||||
return (
|
||||
<Link href={"/"} className="flex items-center gap-4">
|
||||
<Image
|
||||
|
@ -1,11 +1,13 @@
|
||||
import * as Dialog from "@radix-ui/react-dialog";
|
||||
import { AnimatePresence, motion } from "framer-motion";
|
||||
import { FC, useState } from "react";
|
||||
import { useState } from "react";
|
||||
import { MdClose, MdMenu } from "react-icons/md";
|
||||
|
||||
import { NavItems } from "./NavItems";
|
||||
|
||||
export const MobileMenu: FC = () => {
|
||||
export const MobileMenu = (): JSX.Element => {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<Dialog.Root onOpenChange={setOpen} open={open}>
|
||||
<Dialog.Trigger asChild>
|
||||
|
@ -1,16 +1,19 @@
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
import Link from "next/link";
|
||||
import { usePathname } from "next/navigation";
|
||||
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
|
||||
export const AuthButtons = (): JSX.Element => {
|
||||
const pathname = usePathname();
|
||||
|
||||
if (pathname === "/signup")
|
||||
if (pathname === "/signup") {
|
||||
return (
|
||||
<Link href={"/login"}>
|
||||
<Button variant={"secondary"}>Login</Button>
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<Link href={"/signup"}>
|
||||
<Button variant={"secondary"}>Register</Button>
|
||||
|
@ -1,9 +1,11 @@
|
||||
/* eslint-disable */
|
||||
"use client";
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
import { FC, useEffect, useLayoutEffect, useState } from "react";
|
||||
import { useEffect, useLayoutEffect, useState } from "react";
|
||||
import { MdDarkMode, MdLightMode } from "react-icons/md";
|
||||
|
||||
export const DarkModeToggle: FC = () => {
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
|
||||
export const DarkModeToggle = (): JSX.Element => {
|
||||
const [dark, setDark] = useState(false);
|
||||
|
||||
useLayoutEffect(() => {
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* eslint-disable */
|
||||
import Link from "next/link";
|
||||
import { Dispatch, FC, ReactNode, SetStateAction } from "react";
|
||||
import { Dispatch, ReactNode, SetStateAction } from "react";
|
||||
|
||||
interface NavLinkProps {
|
||||
children: ReactNode;
|
||||
@ -7,7 +8,11 @@ interface NavLinkProps {
|
||||
setOpen?: Dispatch<SetStateAction<boolean>>;
|
||||
}
|
||||
|
||||
export const NavLink: FC<NavLinkProps> = ({ children, to, setOpen }) => {
|
||||
export const NavLink = ({
|
||||
children,
|
||||
to,
|
||||
setOpen,
|
||||
}: NavLinkProps): JSX.Element => {
|
||||
return (
|
||||
<li className="group relative">
|
||||
<Link onClick={() => setOpen && setOpen(false)} href={to}>
|
||||
|
@ -1,10 +1,13 @@
|
||||
/* eslint-disable */
|
||||
"use client";
|
||||
import Link from "next/link";
|
||||
import { Dispatch, HTMLAttributes, SetStateAction } from "react";
|
||||
import { MdPerson, MdSettings } from "react-icons/md";
|
||||
|
||||
import { useSupabase } from "@/app/supabase-provider";
|
||||
import Button from "@/lib/components/ui/Button";
|
||||
import { cn } from "@/lib/utils";
|
||||
import Link from "next/link";
|
||||
import { Dispatch, FC, HTMLAttributes, SetStateAction } from "react";
|
||||
import { MdPerson, MdSettings } from "react-icons/md";
|
||||
|
||||
import { AuthButtons } from "./components/AuthButtons";
|
||||
import { DarkModeToggle } from "./components/DarkModeToggle";
|
||||
import { NavLink } from "./components/NavLink";
|
||||
@ -13,11 +16,11 @@ interface NavItemsProps extends HTMLAttributes<HTMLUListElement> {
|
||||
setOpen?: Dispatch<SetStateAction<boolean>>;
|
||||
}
|
||||
|
||||
export const NavItems: FC<NavItemsProps> = ({
|
||||
export const NavItems = ({
|
||||
className,
|
||||
setOpen,
|
||||
...props
|
||||
}) => {
|
||||
}: NavItemsProps): JSX.Element => {
|
||||
const { session } = useSupabase();
|
||||
const isUserLoggedIn = session?.user !== undefined;
|
||||
|
||||
|
@ -1,12 +1,11 @@
|
||||
"use client";
|
||||
import { FC } from "react";
|
||||
|
||||
import { Header } from "./components/Header";
|
||||
import { Logo } from "./components/Logo";
|
||||
import { MobileMenu } from "./components/MobileMenu";
|
||||
import { NavItems } from "./components/NavItems";
|
||||
|
||||
export const NavBar: FC = () => {
|
||||
export const NavBar = (): JSX.Element => {
|
||||
return (
|
||||
<Header>
|
||||
<Logo />
|
||||
|
@ -1,8 +1,10 @@
|
||||
import { cn } from "@/lib/utils";
|
||||
/* eslint-disable */
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
import { ButtonHTMLAttributes, FC, LegacyRef, forwardRef } from "react";
|
||||
import { ButtonHTMLAttributes, forwardRef, LegacyRef } from "react";
|
||||
import { FaSpinner } from "react-icons/fa";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
const ButtonVariants = cva(
|
||||
"px-8 py-3 text-sm disabled:opacity-80 text-center font-medium rounded-md focus:ring ring-primary/10 outline-none flex items-center justify-center gap-2 transition-opacity",
|
||||
{
|
||||
@ -34,11 +36,18 @@ export interface ButtonProps
|
||||
isLoading?: boolean;
|
||||
}
|
||||
|
||||
const Button: FC<ButtonProps> = forwardRef(
|
||||
const Button = forwardRef(
|
||||
(
|
||||
{ className, children, variant, brightness, isLoading, ...props },
|
||||
{
|
||||
className,
|
||||
children,
|
||||
variant,
|
||||
brightness,
|
||||
isLoading,
|
||||
...props
|
||||
}: ButtonProps,
|
||||
forwardedRef
|
||||
) => {
|
||||
): JSX.Element => {
|
||||
return (
|
||||
<button
|
||||
className={cn(ButtonVariants({ variant, brightness, className }))}
|
||||
|
@ -1,12 +1,14 @@
|
||||
/* eslint-disable */
|
||||
"use client";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { motion } from "framer-motion";
|
||||
import { FC, HTMLAttributes, LegacyRef, forwardRef } from "react";
|
||||
import { forwardRef, HTMLAttributes, LegacyRef } from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
type CardProps = HTMLAttributes<HTMLDivElement>;
|
||||
|
||||
const Card: FC<CardProps> = forwardRef(
|
||||
({ children, className, ...props }, ref) => {
|
||||
const Card = forwardRef(
|
||||
({ children, className, ...props }: CardProps, ref): JSX.Element => {
|
||||
return (
|
||||
<div
|
||||
ref={ref as LegacyRef<HTMLDivElement>}
|
||||
|
@ -1,12 +1,14 @@
|
||||
/* eslint-disable */
|
||||
import { forwardRef, HTMLAttributes, LegacyRef } from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
import { FC, HTMLAttributes, LegacyRef, forwardRef } from "react";
|
||||
|
||||
type DividerProps = HTMLAttributes<HTMLDivElement> & {
|
||||
text?: string;
|
||||
};
|
||||
|
||||
const Divider: FC<DividerProps> = forwardRef(
|
||||
({ className, text, ...props }, ref) => {
|
||||
const Divider = forwardRef(
|
||||
({ className, text, ...props }: DividerProps, ref): JSX.Element => {
|
||||
return (
|
||||
<div
|
||||
ref={ref as LegacyRef<HTMLDivElement>}
|
||||
|
@ -1,6 +1,9 @@
|
||||
/* eslint-disable */
|
||||
"use client";
|
||||
import { HTMLAttributes } from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
import { FC, HTMLAttributes } from "react";
|
||||
|
||||
import Tooltip from "./Tooltip";
|
||||
|
||||
interface EllipsisProps extends HTMLAttributes<HTMLDivElement> {
|
||||
@ -9,12 +12,12 @@ interface EllipsisProps extends HTMLAttributes<HTMLDivElement> {
|
||||
tooltip?: boolean;
|
||||
}
|
||||
|
||||
const Ellipsis: FC<EllipsisProps> = ({
|
||||
const Ellipsis = ({
|
||||
children: originalContent,
|
||||
className,
|
||||
maxCharacters,
|
||||
tooltip = false,
|
||||
}) => {
|
||||
}: EllipsisProps): JSX.Element => {
|
||||
const renderedContent =
|
||||
originalContent.length > maxCharacters
|
||||
? `${originalContent.slice(0, maxCharacters)}...`
|
||||
|
@ -1,11 +1,13 @@
|
||||
import { cn } from "@/lib/utils";
|
||||
/* eslint-disable */
|
||||
import {
|
||||
DetailedHTMLProps,
|
||||
forwardRef,
|
||||
InputHTMLAttributes,
|
||||
RefObject,
|
||||
forwardRef,
|
||||
} from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
interface FieldProps
|
||||
extends DetailedHTMLProps<
|
||||
InputHTMLAttributes<HTMLInputElement>,
|
||||
|
@ -1,8 +1,9 @@
|
||||
"use client";
|
||||
import * as Dialog from "@radix-ui/react-dialog";
|
||||
import { AnimatePresence, motion } from "framer-motion";
|
||||
import { FC, ReactNode, useState } from "react";
|
||||
import { ReactNode, useState } from "react";
|
||||
import { MdClose } from "react-icons/md";
|
||||
|
||||
import Button from "./Button";
|
||||
|
||||
interface ModalProps {
|
||||
@ -13,14 +14,15 @@ interface ModalProps {
|
||||
CloseTrigger?: ReactNode;
|
||||
}
|
||||
|
||||
const Modal: FC<ModalProps> = ({
|
||||
const Modal = ({
|
||||
title,
|
||||
desc,
|
||||
children,
|
||||
Trigger,
|
||||
CloseTrigger,
|
||||
}) => {
|
||||
}: ModalProps): JSX.Element => {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<Dialog.Root onOpenChange={setOpen}>
|
||||
<Dialog.Trigger asChild>
|
||||
@ -58,7 +60,7 @@ const Modal: FC<ModalProps> = ({
|
||||
{children}
|
||||
|
||||
<Dialog.Close asChild>
|
||||
{CloseTrigger ? (
|
||||
{CloseTrigger !== undefined ? (
|
||||
CloseTrigger
|
||||
) : (
|
||||
<Button variant={"secondary"} className="self-end">
|
||||
|
@ -1,15 +1,15 @@
|
||||
import { FC } from "react";
|
||||
|
||||
interface PageHeadingProps {
|
||||
title: string;
|
||||
subtitle?: string;
|
||||
}
|
||||
|
||||
const PageHeading: FC<PageHeadingProps> = ({ title, subtitle }) => {
|
||||
const PageHeading = ({ title, subtitle }: PageHeadingProps): JSX.Element => {
|
||||
return (
|
||||
<div className="flex flex-col items-center justify-center px-5">
|
||||
<h1 className="text-3xl font-bold text-center">{title}</h1>
|
||||
{subtitle && <h2 className="opacity-50 text-center">{subtitle}</h2>}
|
||||
{subtitle !== undefined && (
|
||||
<h2 className="opacity-50 text-center">{subtitle}</h2>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { FC } from "react";
|
||||
import { FaSpinner } from "react-icons/fa";
|
||||
|
||||
const Spinner: FC = () => {
|
||||
const Spinner = (): JSX.Element => {
|
||||
return <FaSpinner className="animate-spin m-5" />;
|
||||
};
|
||||
|
||||
|
@ -1,8 +1,11 @@
|
||||
/* eslint-disable */
|
||||
"use client";
|
||||
import { cn } from "@/lib/utils";
|
||||
import * as ToastPrimitive from "@radix-ui/react-toast";
|
||||
import { AnimatePresence, motion } from "framer-motion";
|
||||
import { ReactNode } from "react";
|
||||
|
||||
import { cn } from "@/lib/utils";
|
||||
|
||||
import Button from "../../Button";
|
||||
import { ToastContext } from "../domain/ToastContext";
|
||||
import { ToastVariants } from "../domain/types";
|
||||
@ -11,15 +14,21 @@ import { useToastBuilder } from "../hooks/useToastBuilder";
|
||||
export const Toast = ({
|
||||
children,
|
||||
...toastProviderProps
|
||||
}: { children?: ReactNode } & ToastPrimitive.ToastProviderProps) => {
|
||||
}: {
|
||||
children?: ReactNode;
|
||||
} & ToastPrimitive.ToastProviderProps): JSX.Element => {
|
||||
const { publish, toasts, toggleToast } = useToastBuilder();
|
||||
|
||||
return (
|
||||
<ToastPrimitive.Provider {...toastProviderProps}>
|
||||
<ToastContext.Provider value={{ publish }}>
|
||||
{children}
|
||||
<AnimatePresence mode="popLayout">
|
||||
{toasts.map((toast) => {
|
||||
if (!toast.open) return;
|
||||
if (toast.open !== true) {
|
||||
return;
|
||||
}
|
||||
|
||||
return (
|
||||
<ToastPrimitive.Root
|
||||
open={toast.open}
|
||||
|
@ -1,11 +1,14 @@
|
||||
"use client";
|
||||
import * as ToastPrimitive from "@radix-ui/react-toast";
|
||||
import { ReactNode } from "react";
|
||||
|
||||
import { Toast } from "./Toast";
|
||||
|
||||
export const ToastProvider = ({
|
||||
children,
|
||||
...toastProviderProps
|
||||
}: { children?: ReactNode } & ToastPrimitive.ToastProviderProps) => {
|
||||
}: {
|
||||
children?: ReactNode;
|
||||
} & ToastPrimitive.ToastProviderProps): JSX.Element => {
|
||||
return <Toast {...toastProviderProps}>{children}</Toast>;
|
||||
};
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { createContext } from "react";
|
||||
|
||||
import { ToastPublisher } from "./types";
|
||||
|
||||
const publish: ToastPublisher = () => void 0;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { VariantProps, cva } from "class-variance-authority";
|
||||
import { cva, VariantProps } from "class-variance-authority";
|
||||
|
||||
export const ToastVariants = cva(
|
||||
"bg-white dark:bg-black px-8 max-w-sm w-full py-5 border border-black/10 dark:border-white/25 rounded-xl shadow-xl flex items-center pointer-events-auto data-[swipe=end]:opacity-0 data-[state=closed]:opacity-0 transition-opacity",
|
||||
|
@ -1,5 +1,6 @@
|
||||
export const generateToastUniqueId = () => {
|
||||
export const generateToastUniqueId = (): string => {
|
||||
const timestamp = Date.now();
|
||||
const random = Math.floor(Math.random() * 10000);
|
||||
|
||||
return `${timestamp}-${random}`;
|
||||
};
|
||||
|
@ -1,4 +1,6 @@
|
||||
/* eslint-disable */
|
||||
import { useState } from "react";
|
||||
|
||||
import { ToastContent, ToastData, ToastPublisher } from "../domain/types";
|
||||
import { generateToastUniqueId } from "../helpers/generateToastUniqueId";
|
||||
|
||||
@ -12,6 +14,7 @@ export const useToastBuilder = () => {
|
||||
if (toast.id === toastId) {
|
||||
toast.open = value;
|
||||
}
|
||||
|
||||
return toast;
|
||||
})
|
||||
);
|
||||
|
@ -1,15 +1,16 @@
|
||||
"use client";
|
||||
import * as TooltipPrimitive from "@radix-ui/react-tooltip";
|
||||
import { AnimatePresence, motion } from "framer-motion";
|
||||
import { FC, ReactNode, useState } from "react";
|
||||
import { ReactNode, useState } from "react";
|
||||
|
||||
interface TooltipProps {
|
||||
children?: ReactNode;
|
||||
tooltip?: ReactNode;
|
||||
}
|
||||
|
||||
const Tooltip: FC<TooltipProps> = ({ children, tooltip }) => {
|
||||
const Tooltip = ({ children, tooltip }: TooltipProps): JSX.Element => {
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<TooltipPrimitive.Provider>
|
||||
<TooltipPrimitive.Root onOpenChange={setOpen} open={open}>
|
||||
|
@ -1,7 +1,10 @@
|
||||
/* eslint-disable */
|
||||
"use client";
|
||||
|
||||
import { setEmptyStringsUndefined } from "@/lib/helpers/setEmptyStringsUndefined";
|
||||
import { createContext, useEffect, useState } from "react";
|
||||
|
||||
import { setEmptyStringsUndefined } from "@/lib/helpers/setEmptyStringsUndefined";
|
||||
|
||||
import {
|
||||
getBrainConfigFromLocalStorage,
|
||||
saveBrainConfigInLocalStorage,
|
||||
|
@ -1,3 +1,4 @@
|
||||
/* eslint-disable */
|
||||
import { BrainConfig } from "../types";
|
||||
|
||||
const BRAIN_CONFIG_LOCAL_STORAGE_KEY = "userBrainConfig";
|
||||
@ -12,6 +13,9 @@ export const getBrainConfigFromLocalStorage = (): BrainConfig | undefined => {
|
||||
const persistedBrainConfig = localStorage.getItem(
|
||||
BRAIN_CONFIG_LOCAL_STORAGE_KEY
|
||||
);
|
||||
if (persistedBrainConfig === null) return;
|
||||
if (persistedBrainConfig === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
return JSON.parse(persistedBrainConfig);
|
||||
};
|
||||
|
@ -1,4 +1,6 @@
|
||||
/* eslint-disable */
|
||||
import { useContext } from "react";
|
||||
|
||||
import { BrainConfigContext } from "../brain-config-provider";
|
||||
|
||||
export const useBrainConfig = () => {
|
||||
|
@ -20,8 +20,18 @@ export type ConfigContext = {
|
||||
|
||||
// export const openAiModels = ["gpt-3.5-turbo", "gpt-4"] as const; ## TODO activate GPT4 when not in demo mode
|
||||
|
||||
export const openAiModels = ["gpt-3.5-turbo","gpt-3.5-turbo-0613","gpt-3.5-turbo-16k"] as const;
|
||||
export const openAiPaidModels = ["gpt-3.5-turbo","gpt-3.5-turbo-0613","gpt-3.5-turbo-16k","gpt-4","gpt-4-0613"] as const;
|
||||
export const openAiModels = [
|
||||
"gpt-3.5-turbo",
|
||||
"gpt-3.5-turbo-0613",
|
||||
"gpt-3.5-turbo-16k",
|
||||
] as const;
|
||||
export const openAiPaidModels = [
|
||||
"gpt-3.5-turbo",
|
||||
"gpt-3.5-turbo-0613",
|
||||
"gpt-3.5-turbo-16k",
|
||||
"gpt-4",
|
||||
"gpt-4-0613",
|
||||
] as const;
|
||||
|
||||
export const anthropicModels = [
|
||||
// "claude-v1",
|
||||
@ -39,7 +49,7 @@ export const models = [
|
||||
...googleModels,
|
||||
] as const;
|
||||
|
||||
export const paidModels = [...openAiPaidModels, ...googleModels] as const;
|
||||
export const paidModels = [...openAiPaidModels] as const;
|
||||
|
||||
export type PaidModels = (typeof paidModels)[number];
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
/* eslint-disable */
|
||||
"use client";
|
||||
|
||||
import { createContext } from "react";
|
||||
|
||||
import useChats from "./hooks/useChats";
|
||||
import { ChatsState } from "./types";
|
||||
|
||||
|
@ -1,9 +1,12 @@
|
||||
import { useBrainConfig } from "@/lib/context/BrainConfigProvider/hooks/useBrainConfig";
|
||||
import { useToast } from "@/lib/hooks/useToast";
|
||||
import { useAxios } from "@/lib/useAxios";
|
||||
/* eslint-disable */
|
||||
import { UUID } from "crypto";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
|
||||
import { useBrainConfig } from "@/lib/context/BrainConfigProvider/hooks/useBrainConfig";
|
||||
import { useToast } from "@/lib/hooks/useToast";
|
||||
import { useAxios } from "@/lib/useAxios";
|
||||
|
||||
import { Chat, ChatMessage } from "../../../types/Chat";
|
||||
|
||||
export default function useChats() {
|
||||
@ -38,7 +41,9 @@ export default function useChats() {
|
||||
|
||||
const fetchChat = useCallback(
|
||||
async (chatId?: UUID) => {
|
||||
if (!chatId) return;
|
||||
if (!chatId) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
console.log(`Fetching chat ${chatId}`);
|
||||
const response = await axiosInstance.get<Chat>(`/chat/${chatId}`);
|
||||
@ -64,6 +69,7 @@ export default function useChats() {
|
||||
options: Record<string, string | unknown>;
|
||||
}) => {
|
||||
fetchAllChats();
|
||||
|
||||
return axiosInstance.post<ChatResponse>(`/chat`, options);
|
||||
};
|
||||
|
||||
@ -78,7 +84,9 @@ export default function useChats() {
|
||||
const sendMessage = async (chatId?: UUID, msg?: ChatMessage) => {
|
||||
setIsSendingMessage(true);
|
||||
|
||||
if (msg) setMessage(msg);
|
||||
if (msg) {
|
||||
setMessage(msg);
|
||||
}
|
||||
const options: Record<string, unknown> = {
|
||||
chat_id: chatId,
|
||||
model,
|
||||
@ -101,6 +109,7 @@ export default function useChats() {
|
||||
});
|
||||
setMessage(["", ""]);
|
||||
setIsSendingMessage(false);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -114,6 +123,7 @@ export default function useChats() {
|
||||
console.log("---- Creating a new chat ----");
|
||||
setAllChats((chats) => {
|
||||
console.log({ chats });
|
||||
|
||||
return [...chats, newChat];
|
||||
});
|
||||
setChat(newChat);
|
||||
|
@ -1,4 +1,6 @@
|
||||
/* eslint-disable */
|
||||
import { useContext } from "react";
|
||||
|
||||
import { ChatsContext } from "../chats-provider";
|
||||
|
||||
const useChatsContext = () => {
|
||||
|
@ -1,5 +1,8 @@
|
||||
import { isSpeechRecognitionSupported } from "@/lib/helpers/isSpeechRecognitionSupported";
|
||||
/* eslint-disable */
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
import { isSpeechRecognitionSupported } from "@/lib/helpers/isSpeechRecognitionSupported";
|
||||
|
||||
import useChatsContext from "./useChatsContext";
|
||||
|
||||
export const useSpeech = () => {
|
||||
|
@ -1,9 +1,10 @@
|
||||
export function isSpeechRecognitionSupported() {
|
||||
export const isSpeechRecognitionSupported = (): boolean => {
|
||||
if (
|
||||
typeof window !== "undefined" &&
|
||||
("SpeechRecognition" in window || "webkitSpeechRecognition" in window)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
@ -1,6 +1,8 @@
|
||||
import { ToastContext } from "@/lib/components/ui/Toast/domain/ToastContext";
|
||||
/* eslint-disable */
|
||||
import { useContext } from "react";
|
||||
|
||||
import { ToastContext } from "@/lib/components/ui/Toast/domain/ToastContext";
|
||||
|
||||
export const useToast = () => {
|
||||
const { publish } = useContext(ToastContext);
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
export type Message = {
|
||||
type: "success" | "error" | "warning";
|
||||
text: string;
|
||||
type: "success" | "error" | "warning";
|
||||
text: string;
|
||||
};
|
||||
|
@ -1,20 +1,23 @@
|
||||
/* eslint-disable */
|
||||
import axios, { AxiosInstance } from "axios";
|
||||
|
||||
import { useSupabase } from "@/app/supabase-provider";
|
||||
import axios from "axios";
|
||||
|
||||
import { useBrainConfig } from "./context/BrainConfigProvider/hooks/useBrainConfig";
|
||||
|
||||
const axiosInstance = axios.create({
|
||||
baseURL: `${process.env.NEXT_PUBLIC_BACKEND_URL}`,
|
||||
baseURL: `${process.env.NEXT_PUBLIC_BACKEND_URL ?? ""}`,
|
||||
});
|
||||
|
||||
export const useAxios = () => {
|
||||
export const useAxios = (): { axiosInstance: AxiosInstance } => {
|
||||
const { session } = useSupabase();
|
||||
const {
|
||||
config: { backendUrl, openAiKey },
|
||||
} = useBrainConfig();
|
||||
axiosInstance.interceptors.request.clear();
|
||||
axiosInstance.interceptors.request.use(
|
||||
async (config) => {
|
||||
config.headers["Authorization"] = "Bearer " + session?.access_token;
|
||||
(config) => {
|
||||
config.headers["Authorization"] = `Bearer ${session?.access_token}`;
|
||||
config.headers["Openai-Api-Key"] = openAiKey;
|
||||
config.baseURL = backendUrl ?? config.baseURL;
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import clsx, { ClassValue } from "clsx";
|
||||
import { twMerge } from "tailwind-merge";
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
export const cn = (...inputs: ClassValue[]): string => {
|
||||
return twMerge(clsx(inputs));
|
||||
}
|
||||
};
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { createMiddlewareSupabaseClient } from '@supabase/auth-helpers-nextjs'
|
||||
import { NextResponse } from 'next/server'
|
||||
|
||||
import type { NextRequest } from 'next/server'
|
||||
import { createMiddlewareSupabaseClient } from "@supabase/auth-helpers-nextjs";
|
||||
import type { NextRequest } from "next/server";
|
||||
import { NextResponse } from "next/server";
|
||||
// import type { Database } from '@/lib/database.types'
|
||||
|
||||
export async function middleware(req: NextRequest) {
|
||||
const res = NextResponse.next()
|
||||
const supabase = createMiddlewareSupabaseClient({ req, res })
|
||||
await supabase.auth.getSession()
|
||||
return res
|
||||
}
|
||||
export const middleware = async (req: NextRequest): Promise<NextResponse> => {
|
||||
const res = NextResponse.next();
|
||||
const supabase = createMiddlewareSupabaseClient({ req, res });
|
||||
await supabase.auth.getSession();
|
||||
|
||||
return res;
|
||||
};
|
||||
|
@ -7,9 +7,12 @@
|
||||
"build": "next build",
|
||||
"start": "next start",
|
||||
"lint": "next lint",
|
||||
"lint-fix": "eslint --fix .",
|
||||
"test-type": "tsc --noEmit --emitDeclarationOnly false",
|
||||
"test": "yarn test-type",
|
||||
"precommit": "yarn lint && yarn test"
|
||||
"precommit": "yarn lint && yarn test",
|
||||
"format-check": "prettier --check .",
|
||||
"format-fix": "prettier --write ."
|
||||
},
|
||||
"dependencies": {
|
||||
"@emotion/react": "^11.11.0",
|
||||
@ -35,9 +38,11 @@
|
||||
"encoding": "^0.1.13",
|
||||
"eslint": "^8.41.0",
|
||||
"eslint-config-next": "13.4.2",
|
||||
"eslint-plugin-prefer-arrow": "^1.2.3",
|
||||
"framer-motion": "^10.12.12",
|
||||
"next": "13.4.2",
|
||||
"postcss": "8.4.23",
|
||||
"prettier": "^2.8.8",
|
||||
"pretty-bytes": "^6.1.0",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
|
@ -1,3 +1,5 @@
|
||||
export default function About() {
|
||||
return <div>About</div>;
|
||||
}
|
||||
const About = (): JSX.Element => {
|
||||
return <div>About</div>;
|
||||
};
|
||||
|
||||
export default About;
|
||||
|
@ -3,4 +3,4 @@ module.exports = {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
||||
};
|
||||
|
@ -2,25 +2,23 @@
|
||||
module.exports = {
|
||||
darkMode: "class",
|
||||
content: [
|
||||
'./pages/**/*.{js,ts,jsx,tsx,mdx}',
|
||||
'./components/**/*.{js,ts,jsx,tsx,mdx}',
|
||||
'./app/**/*.{js,ts,jsx,tsx,mdx}',
|
||||
'./lib/**/*.{js,ts,jsx,tsx,mdx}',
|
||||
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
"./components/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
"./app/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
"./lib/**/*.{js,ts,jsx,tsx,mdx}",
|
||||
],
|
||||
theme: {
|
||||
extend: {
|
||||
backgroundImage: {
|
||||
'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))',
|
||||
'gradient-conic':
|
||||
'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))',
|
||||
"gradient-radial": "radial-gradient(var(--tw-gradient-stops))",
|
||||
"gradient-conic":
|
||||
"conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))",
|
||||
},
|
||||
colors: {
|
||||
black: "#00121F",
|
||||
primary: "#4F46E5",
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: [
|
||||
require('@tailwindcss/typography'),
|
||||
],
|
||||
}
|
||||
plugins: [require("@tailwindcss/typography")],
|
||||
};
|
||||
|
42
frontend/tsconfig.eslint.json
Normal file
42
frontend/tsconfig.eslint.json
Normal file
@ -0,0 +1,42 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"typeRoots": ["node_modules/@types"],
|
||||
"composite": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"emitDeclarationOnly": true,
|
||||
"incremental": true,
|
||||
"noEmitOnError": true,
|
||||
"skipLibCheck": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"esModuleInterop": true,
|
||||
"isolatedModules": true,
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"strict": true,
|
||||
"strictNullChecks": true,
|
||||
"target": "esnext",
|
||||
"types": ["node", "vitest/globals"],
|
||||
"lib": ["dom", "dom.iterable","es2020"],
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"sourceMap": true,
|
||||
"noImplicitReturns": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"plugins": [
|
||||
{
|
||||
"name": "next"
|
||||
}
|
||||
],
|
||||
},
|
||||
"ts-node": {
|
||||
"compilerOptions": {
|
||||
"module": "NodeNext"
|
||||
},
|
||||
"require": ["tsconfig-paths/register"]
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
@ -1,9 +1,10 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"typeRoots": ["node_modules/@types"],
|
||||
"target": "es5",
|
||||
"lib": ["dom", "dom.iterable", "esnext"],
|
||||
|
||||
"lib": [
|
||||
"dom",
|
||||
"dom.iterable",
|
||||
"esnext"
|
||||
],
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
@ -21,10 +22,18 @@
|
||||
"name": "next"
|
||||
}
|
||||
],
|
||||
"strictNullChecks": true,
|
||||
"paths": {
|
||||
"@/*": ["./*"]
|
||||
}
|
||||
},
|
||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
"include": [
|
||||
"next-env.d.ts",
|
||||
".next/types/**/*.ts",
|
||||
"**/*.ts",
|
||||
"**/*.tsx"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
|
2088
frontend/yarn.lock
2088
frontend/yarn.lock
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user