feat: remove legacy header and footer (#1509)

# Description

Also add a back to chat button in the user page to make up for the loss
of the legacy header.

## Screenshots (if appropriate):

<img width="754" alt="image"
src="https://github.com/StanGirard/quivr/assets/67386567/ad6d92a6-2f57-464f-b002-ec94f37a1ccd">
This commit is contained in:
Matthieu Jacq 2023-10-26 18:23:36 +02:00 committed by GitHub
parent e15177b7ab
commit c2bf3adc24
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 65 additions and 343 deletions

View File

@ -3,8 +3,6 @@
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { PropsWithChildren, useEffect } from "react";
import Footer from "@/lib/components/Footer";
import { NavBar } from "@/lib/components/NavBar";
import { useBrainContext } from "@/lib/context/BrainProvider/hooks/useBrainContext";
import { useSupabase } from "@/lib/context/SupabaseProvider";
import { UpdateMetadata } from "@/lib/helpers/updateMetadata";
@ -31,9 +29,7 @@ export const App = ({ children }: PropsWithChildren): JSX.Element => {
return (
<QueryClientProvider client={queryClient}>
<NavBar />
{children}
<Footer />
<UpdateMetadata />
</QueryClientProvider>
);

View File

@ -25,7 +25,7 @@ export const ChatInput = ({
return (
<>
{<OnboardingQuestions />}
<OnboardingQuestions />
<div className="flex mt-1 flex-col w-full shadow-md dark:shadow-primary/25 hover:shadow-xl transition-shadow rounded-xl bg-white dark:bg-black border border-black/10 dark:border-white/25 p-2">
<form
data-testid="chat-input-form"

View File

@ -20,68 +20,75 @@ const UserPage = (): JSX.Element => {
}
const { user } = session;
const { t } = useTranslation(["translation", "user", "config"]);
const { t } = useTranslation(["translation", "user", "config", "chat"]);
return (
<main className="container lg:w-2/3 mx-auto py-10 px-5">
<Card className="mb-5 shadow-sm hover:shadow-none">
<CardHeader>
<h2 className="font-bold text-xl">
{t("accountSection", { ns: "config" })}
</h2>
</CardHeader>
<>
<main className="container lg:w-2/3 mx-auto py-10 px-5">
<Link href="/chat">
<Button className="mb-5" variant="primary">
{t("chat:back_to_chat")}
</Button>
</Link>
<Card className="mb-5 shadow-sm hover:shadow-none">
<CardHeader>
<h2 className="font-bold text-xl">
{t("accountSection", { ns: "config" })}
</h2>
</CardHeader>
<CardBody className="flex flex-col items-stretch max-w-max gap-2">
<div className="flex gap-5 items-center">
<p>
<strong>{t("email")}:</strong> <span>{user.email}</span>
</p>
<Link href={"/logout"}>
<Button className="px-3 py-2" variant="secondary">
{t("logoutButton")}
</Button>
</Link>
</div>
<StripePricingOrManageButton />
</CardBody>
</Card>
<CardBody className="flex flex-col items-stretch max-w-max gap-2">
<div className="flex gap-5 items-center">
<p>
<strong>{t("email")}:</strong> <span>{user.email}</span>
</p>
<Link href={"/logout"}>
<Button className="px-3 py-2" variant="secondary">
{t("logoutButton")}
</Button>
</Link>
</div>
<StripePricingOrManageButton />
</CardBody>
</Card>
<Card className="mb-5 shadow-sm hover:shadow-none">
<CardHeader>
<h2 className="font-bold text-xl">
{t("settings", { ns: "config" })}
</h2>
</CardHeader>
<Card className="mb-5 shadow-sm hover:shadow-none">
<CardHeader>
<h2 className="font-bold text-xl">
{t("settings", { ns: "config" })}
</h2>
</CardHeader>
<CardBody>
<LanguageSelect />
<CardBody>
<LanguageSelect />
<ThemeSelect />
</CardBody>
</Card>
<Card className="mb-5 shadow-sm hover:shadow-none">
<CardHeader>
<h2 className="font-bold text-xl">
{t("brainUsage", { ns: "user" })}
</h2>
</CardHeader>
<ThemeSelect />
</CardBody>
</Card>
<CardBody>
<UserStatistics />
</CardBody>
</Card>
<Card className="mb-5 shadow-sm hover:shadow-none">
<CardHeader>
<h2 className="font-bold text-xl">
{t("apiKey", { ns: "config" })}
</h2>
</CardHeader>
<Card className="mb-5 shadow-sm hover:shadow-none">
<CardHeader>
<h2 className="font-bold text-xl">
{t("brainUsage", { ns: "user" })}
</h2>
</CardHeader>
<CardBody>
<UserStatistics />
</CardBody>
</Card>
<Card className="mb-5 shadow-sm hover:shadow-none">
<CardHeader>
<h2 className="font-bold text-xl">{t("apiKey", { ns: "config" })}</h2>
</CardHeader>
<CardBody className="p-3 flex flex-col">
<ApiKeyConfig />
</CardBody>
</Card>
</main>
<CardBody className="p-3 flex flex-col">
<ApiKeyConfig />
</CardBody>
</Card>
L
</main>
</>
);
};

View File

@ -1,60 +0,0 @@
"use client";
import { usePathname } from "next/navigation";
import { DISCORD_URL, GITHUB_URL, TWITTER_URL } from "@/lib/config/CONSTANTS";
import { useSupabase } from "@/lib/context/SupabaseProvider";
const Footer = (): JSX.Element => {
const { session } = useSupabase();
const path = usePathname();
const isHomePage = path === "/";
const isContactPage = path === "/contact";
const isLoginPage = path === "/login";
if (
session?.user !== undefined ||
isHomePage ||
isContactPage ||
isLoginPage
) {
return <></>;
}
return (
<footer className="bg-white dark:bg-black border-t dark:border-white/10 mt-auto py-4">
<div className="max-w-screen-xl mx-auto flex justify-center items-center gap-4">
<a
href={GITHUB_URL}
target="_blank"
rel="noopener noreferrer"
aria-label="Quivr GitHub"
>
<img
className="h-8 w-auto dark:invert"
src="/github.svg"
alt="GitHub"
/>
</a>
<a
href={TWITTER_URL}
target="_blank"
rel="noopener noreferrer"
aria-label="Quivr Twitter"
>
<img className="h-8 w-auto" src="/twitter.svg" alt="Twitter" />
</a>
<a
href={DISCORD_URL}
target="_blank"
rel="noopener noreferrer"
aria-label="Quivr Discord"
>
<img className="h-8 w-auto" src="/discord.svg" alt="Discord" />
</a>
</div>
</footer>
);
};
export default Footer;

View File

@ -1,34 +0,0 @@
/* eslint-disable */
import { useSupabase } from "@/lib/context/SupabaseProvider";
import { useEffect, useRef, useState } from "react";
export const useHeader = () => {
const [hidden, setHidden] = useState(false);
const scrollPos = useRef<number>(0);
const { session } = useSupabase();
useEffect(() => {
const handleScroll = (e: Event) => {
if (session?.user !== undefined) {
setHidden(false);
return;
}
const target = e.currentTarget as Window;
if (target.scrollY > scrollPos.current) {
setHidden(true);
} else {
setHidden(false);
}
scrollPos.current = target.scrollY;
};
window.addEventListener("scroll", handleScroll);
return () => window.removeEventListener("scroll", handleScroll);
}, []);
return {
hidden,
};
};

View File

@ -1,25 +0,0 @@
import { motion } from "framer-motion";
import { useHeader } from "./hooks/useHeader";
export const Header = ({
children,
}: {
children: React.ReactNode;
}): JSX.Element => {
const { hidden } = useHeader();
return (
<motion.header
animate={{
y: hidden ? "-100%" : "0%",
transition: { ease: "circOut" },
}}
className="sticky top-0 w-full border-b border-b-black/10 dark:border-b-white/25 bg-white dark:bg-black z-20"
>
<nav className="max-w-screen-xl mx-auto py-1 flex items-center justify-between gap-8">
{children}
</nav>
</motion.header>
);
};

View File

@ -1,17 +0,0 @@
/* eslint-disable */
import { useState } from "react";
import { NavItems } from "./NavItems";
export const MobileMenu = (): JSX.Element => {
const [open, setOpen] = useState(false);
return (
<div className="md:hidden flex flex-row items-center justify-between px-6 sm:hidden">
<NavItems
setOpen={setOpen}
className="text-3xl gap-10"
/>
</div>
);
};

View File

@ -1,33 +0,0 @@
import Link from "next/link";
import { usePathname } from "next/navigation";
import { useTranslation } from "react-i18next";
import Button from "@/lib/components/ui/Button";
export const AuthButtons = (): JSX.Element => {
const pathname = usePathname();
const { t } = useTranslation();
if (pathname === "/login") {
return (
<Link href={"/login"}>
<Button variant={"secondary"}>{t("loginButton")}</Button>
</Link>
);
}
if (pathname === "/login") {
return (
<Link href={"/login"}>
<Button variant={"secondary"}>{t("signUpButton")}</Button>
</Link>
);
}
return (
<Link href={"/login"}>
<Button data-testid="login-button" variant={"secondary"}>
{t("loginButton")}
</Button>
</Link>
);
};

View File

@ -1,24 +0,0 @@
/* eslint-disable */
import Link from "next/link";
import { Dispatch, ReactNode, SetStateAction } from "react";
interface NavLinkProps {
children: ReactNode;
to: string;
setOpen?: Dispatch<SetStateAction<boolean>>;
}
export const NavLink = ({
children,
to,
setOpen,
}: NavLinkProps): JSX.Element => {
return (
<li className="group relative">
<Link onClick={() => setOpen && setOpen(false)} href={to}>
{children}
</Link>
<hr className="aboslute top-full border border-transparent border-b-primary dark:border-b-white scale-x-0 group-hover:scale-x-100 group-focus-within:scale-x-100 transition-transform" />
</li>
);
};

View File

@ -1,45 +0,0 @@
"use client";
import { Dispatch, HTMLAttributes, SetStateAction } from "react";
import { useSupabase } from "@/lib/context/SupabaseProvider";
import { cn } from "@/lib/utils";
import { AuthButtons } from "./components/AuthButtons";
import { NavLink } from "./components/NavLink";
interface NavItemsProps extends HTMLAttributes<HTMLUListElement> {
setOpen?: Dispatch<SetStateAction<boolean>>;
}
export const NavItems = ({
className,
setOpen,
...props
}: NavItemsProps): JSX.Element => {
const { session } = useSupabase();
const isUserLoggedIn = session?.user !== undefined;
return (
<ul
className={cn(
"flex flex-row items-center gap-4 text-sm flex-1",
className
)}
{...props}
>
{!isUserLoggedIn && (
<>
<NavLink setOpen={setOpen} to="https://github.com/StanGirard/quivr">
Github
</NavLink>
<NavLink setOpen={setOpen} to="https://discord.gg/HUpRgp2HG8">
Discord
</NavLink>
</>
)}
<div className="flex sm:flex-1 sm:justify-end flex-row items-center justify-center sm:flex-row gap-5 sm:gap-2">
{!isUserLoggedIn && <AuthButtons />}
</div>
</ul>
);
};

View File

@ -1,32 +0,0 @@
"use client";
import { usePathname } from "next/navigation";
import { Header } from "./components/Header";
import { Logo } from "./components/Logo";
import { MobileMenu } from "./components/MobileMenu";
import { NavItems } from "./components/NavItems";
export const NavBar = (): JSX.Element => {
const path = usePathname();
const pageHasSidebar =
path === null ||
path.startsWith("/chat") ||
path.startsWith("/brains-management");
const isHomePage = path === "/";
const isContactPage = path === "/contact";
const isLoginPage = path === "/login";
if (pageHasSidebar || isHomePage || isContactPage || isLoginPage) {
return <></>;
}
return (
<Header>
<Logo />
<NavItems className="hidden sm:flex" />
<MobileMenu />
</Header>
);
};

View File

@ -1,7 +1,7 @@
import { Dispatch, SetStateAction } from "react";
import { LuPanelLeft } from "react-icons/lu";
import { Logo } from "@/lib/components/NavBar/components/Logo";
import { Logo } from "@/lib/components/Logo/Logo";
type SidebarProps = {
setOpen: Dispatch<SetStateAction<boolean>>;

View File

@ -6,8 +6,6 @@
"email": "Email",
"or": "or",
"and": "and",
"loginButton": "Login",
"signUpButton": "Sign up",
"logoutButton": "Logout",
"updateButton": "Update",
"uploadButton": "Upload",

View File

@ -12,7 +12,6 @@
"Explore": "Explorar",
"lang": "es-ES",
"loading": "Cargando...",
"loginButton": "Iniciar sesión",
"logoutButton": "Cerrar sesión",
"newChatButton": "Nueva conversación",
"or": "o",
@ -20,7 +19,6 @@
"Owner": "Propietario",
"resetButton": "Restaurar",
"shareButton": "Compartir",
"signUpButton": "Registrarse",
"title": "Quivr - Tu segundo cerebro con IA generativa",
"toastDismiss": "cerrar",
"updateButton": "Actualizar",

View File

@ -6,8 +6,7 @@
"email": "Email",
"or": "ou",
"and": "et",
"loginButton": "Connexion",
"signUpButton": "S'inscrire",
"logoutButton": "Déconnexion",
"updateButton": "Mettre à jour",
"uploadButton": "Télécharger",

View File

@ -6,8 +6,6 @@
"email": "Email",
"or": "ou",
"and": "e",
"loginButton": "Entrar",
"signUpButton": "Cadastre-se",
"logoutButton": "Sair",
"updateButton": "Atualizar",
"uploadButton": "Enviar",

View File

@ -6,8 +6,6 @@
"email": "Email",
"or": "или",
"and": "и",
"loginButton": "Войти",
"signUpButton": "Зарегистрироваться",
"logoutButton": "Выйти",
"updateButton": "Обновить",
"uploadButton": "Загрузить",

View File

@ -6,8 +6,6 @@
"email": "Email",
"or": "或",
"and": "和",
"loginButton": "登录",
"signUpButton": "注册",
"logoutButton": "注销",
"updateButton": "更新",
"uploadButton": "上传",