diff --git a/app/@types/nextjs-routes.d.ts b/app/@types/nextjs-routes.d.ts index fbccfff..79d87f2 100644 --- a/app/@types/nextjs-routes.d.ts +++ b/app/@types/nextjs-routes.d.ts @@ -25,6 +25,7 @@ declare module "nextjs-routes" { | StaticRoute<"/home"> | StaticRoute<"/"> | StaticRoute<"/sentry-example-page"> + | StaticRoute<"/settings"> | StaticRoute<"/world-champs"> | StaticRoute<"/world-champs/signup">; diff --git a/app/src/components/nav/AppShell.tsx b/app/src/components/nav/AppShell.tsx index 2356dca..4dcbdfc 100644 --- a/app/src/components/nav/AppShell.tsx +++ b/app/src/components/nav/AppShell.tsx @@ -12,7 +12,7 @@ import { } from "@chakra-ui/react"; import Head from "next/head"; import Link from "next/link"; -import { BsGithub, BsPersonCircle } from "react-icons/bs"; +import { BsGearFill, BsGithub, BsPersonCircle } from "react-icons/bs"; import { RiDatabase2Line, RiFlaskLine } from "react-icons/ri"; import { signIn, useSession } from "next-auth/react"; import UserMenu from "./UserMenu"; @@ -76,6 +76,21 @@ const NavSidebar = () => { )} + + + CONFIGURATION + + + + + {user && } diff --git a/app/src/components/nav/PageHeaderContainer.tsx b/app/src/components/nav/PageHeaderContainer.tsx new file mode 100644 index 0000000..944f33d --- /dev/null +++ b/app/src/components/nav/PageHeaderContainer.tsx @@ -0,0 +1,15 @@ +import { Flex, type FlexProps } from "@chakra-ui/react"; + +const PageHeaderContainer = (props: FlexProps) => { + return ; +}; + +export default PageHeaderContainer; diff --git a/app/src/components/nav/UserMenu.tsx b/app/src/components/nav/UserMenu.tsx index 7abf17b..8960e5b 100644 --- a/app/src/components/nav/UserMenu.tsx +++ b/app/src/components/nav/UserMenu.tsx @@ -8,7 +8,6 @@ import { PopoverTrigger, PopoverContent, Link, - useColorMode, type StackProps, } from "@chakra-ui/react"; import { type Session } from "next-auth"; @@ -17,7 +16,6 @@ import { BsBoxArrowRight, BsChevronRight, BsPersonCircle } from "react-icons/bs" import NavSidebarOption from "./NavSidebarOption"; export default function UserMenu({ user, ...rest }: { user: Session } & StackProps) { - const { colorMode } = useColorMode(); const profileImage = user.user.image ? ( profile picture @@ -28,39 +26,28 @@ export default function UserMenu({ user, ...rest }: { user: Session } & StackPro return ( <> - - - ACCOUNT - - - - - {profileImage} - - - {user.user.name} - - - {/* {user.user.email} */} - - - - - - - + + + + {profileImage} + + + {user.user.name} + + + {/* {user.user.email} */} + + + + + + {/* sign out */} diff --git a/app/src/pages/data/[id].tsx b/app/src/pages/data/[id].tsx index 5b68a02..2cb6228 100644 --- a/app/src/pages/data/[id].tsx +++ b/app/src/pages/data/[id].tsx @@ -18,6 +18,7 @@ import { api } from "~/utils/api"; import { useDataset, useHandledAsyncCallback } from "~/utils/hooks"; import DatasetEntriesTable from "~/components/datasets/DatasetEntriesTable"; import { DatasetHeaderButtons } from "~/components/datasets/DatasetHeaderButtons/DatasetHeaderButtons"; +import PageHeaderContainer from "~/components/nav/PageHeaderContainer"; export default function Dataset() { const router = useRouter(); @@ -55,14 +56,8 @@ export default function Dataset() { return ( - - + + @@ -88,7 +83,7 @@ export default function Dataset() { - + {datasetId && } diff --git a/app/src/pages/data/index.tsx b/app/src/pages/data/index.tsx index 5c9a411..94b5f50 100644 --- a/app/src/pages/data/index.tsx +++ b/app/src/pages/data/index.tsx @@ -1,14 +1,12 @@ import { SimpleGrid, Icon, - VStack, Breadcrumb, BreadcrumbItem, Flex, Center, Text, Link, - HStack, } from "@chakra-ui/react"; import AppShell from "~/components/nav/AppShell"; import { api } from "~/utils/api"; @@ -19,6 +17,7 @@ import { DatasetCardSkeleton, NewDatasetCard, } from "~/components/datasets/DatasetCard"; +import PageHeaderContainer from "~/components/nav/PageHeaderContainer"; export default function DatasetsPage() { const datasets = api.datasets.list.useQuery(); @@ -50,34 +49,32 @@ export default function DatasetsPage() { return ( - - - - - - Datasets - - - - - - - {datasets.data && !datasets.isLoading ? ( - datasets?.data?.map((dataset) => ( - - )) - ) : ( - <> - - - - - )} - - + + + + + Datasets + + + + + + + {datasets.data && !datasets.isLoading ? ( + datasets?.data?.map((dataset) => ( + + )) + ) : ( + <> + + + + + )} + ); } diff --git a/app/src/pages/experiments/[id].tsx b/app/src/pages/experiments/[id].tsx index 83dfcbb..515986b 100644 --- a/app/src/pages/experiments/[id].tsx +++ b/app/src/pages/experiments/[id].tsx @@ -23,6 +23,7 @@ import { useAppStore } from "~/state/store"; import { useSyncVariantEditor } from "~/state/sync"; import { ExperimentHeaderButtons } from "~/components/experiments/ExperimentHeaderButtons/ExperimentHeaderButtons"; import Head from "next/head"; +import PageHeaderContainer from "~/components/nav/PageHeaderContainer"; // TODO: import less to fix deployment with server side props // export const getServerSideProps = async (context: GetServerSidePropsContext<{ id: string }>) => { @@ -104,15 +105,8 @@ export default function Experiment() { )} - - + + @@ -144,7 +138,7 @@ export default function Experiment() { - + diff --git a/app/src/pages/experiments/index.tsx b/app/src/pages/experiments/index.tsx index b9915e7..eb66b72 100644 --- a/app/src/pages/experiments/index.tsx +++ b/app/src/pages/experiments/index.tsx @@ -1,14 +1,12 @@ import { SimpleGrid, Icon, - VStack, Breadcrumb, BreadcrumbItem, Flex, Center, Text, Link, - HStack, } from "@chakra-ui/react"; import { RiFlaskLine } from "react-icons/ri"; import AppShell from "~/components/nav/AppShell"; @@ -19,6 +17,7 @@ import { NewExperimentCard, } from "~/components/experiments/ExperimentCard"; import { signIn, useSession } from "next-auth/react"; +import PageHeaderContainer from "~/components/nav/PageHeaderContainer"; export default function ExperimentsPage() { const experiments = api.experiments.list.useQuery(); @@ -50,29 +49,27 @@ export default function ExperimentsPage() { return ( - - - - - - Experiments - - - - - - - {experiments.data && !experiments.isLoading ? ( - experiments?.data?.map((exp) => ) - ) : ( - <> - - - - - )} - - + + + + + Experiments + + + + + + + {experiments.data && !experiments.isLoading ? ( + experiments?.data?.map((exp) => ) + ) : ( + <> + + + + + )} + ); } diff --git a/app/src/pages/home/index.tsx b/app/src/pages/home/index.tsx index b79caec..516a6e8 100644 --- a/app/src/pages/home/index.tsx +++ b/app/src/pages/home/index.tsx @@ -1,6 +1,7 @@ -import { Breadcrumb, BreadcrumbItem, HStack, Input } from "@chakra-ui/react"; +import { Breadcrumb, BreadcrumbItem, Input } from "@chakra-ui/react"; import { useEffect, useState } from "react"; import AppShell from "~/components/nav/AppShell"; +import PageHeaderContainer from "~/components/nav/PageHeaderContainer"; import { api } from "~/utils/api"; import { useHandledAsyncCallback, useSelectedOrg } from "~/utils/hooks"; @@ -25,13 +26,7 @@ export default function HomePage() { }, [selectedOrg?.name]); return ( - + - + ); } diff --git a/app/src/pages/settings/index.tsx b/app/src/pages/settings/index.tsx new file mode 100644 index 0000000..ef77742 --- /dev/null +++ b/app/src/pages/settings/index.tsx @@ -0,0 +1,52 @@ +import { Breadcrumb, BreadcrumbItem, Input } from "@chakra-ui/react"; +import { useEffect, useState } from "react"; +import AppShell from "~/components/nav/AppShell"; +import PageHeaderContainer from "~/components/nav/PageHeaderContainer"; +import { api } from "~/utils/api"; +import { useHandledAsyncCallback, useSelectedOrg } from "~/utils/hooks"; + +export default function Settings() { + const utils = api.useContext(); + const { data: selectedOrg } = useSelectedOrg(); + + const updateMutation = api.organizations.update.useMutation(); + const [onSaveName] = useHandledAsyncCallback(async () => { + if (name && name !== selectedOrg?.name && selectedOrg?.id) { + await updateMutation.mutateAsync({ + id: selectedOrg.id, + updates: { name }, + }); + await Promise.all([utils.organizations.get.invalidate({ id: selectedOrg.id })]); + } + }, [updateMutation, selectedOrg]); + + const [name, setName] = useState(selectedOrg?.name); + useEffect(() => { + setName(selectedOrg?.name); + }, [selectedOrg?.name]); + + return ( + + + + + setName(e.target.value)} + onBlur={onSaveName} + borderWidth={1} + borderColor="transparent" + fontSize={16} + px={0} + minW={{ base: 100, lg: 300 }} + flex={1} + _hover={{ borderColor: "gray.300" }} + _focus={{ borderColor: "blue.500", outline: "none" }} + /> + + + + + ); +}