updated UI, minor fixes
This commit is contained in:
parent
b5280b70a1
commit
755c56ee8a
9 changed files with 175 additions and 98 deletions
|
|
@ -1,7 +1,10 @@
|
|||
import { Button, Stack } from '@chakra-ui/react';
|
||||
import { createRootRoute, Link, Outlet } from '@tanstack/react-router';
|
||||
import { Icon, Stack, Text } from '@chakra-ui/react';
|
||||
import { createRootRouteWithContext, Link, Outlet } from '@tanstack/react-router';
|
||||
import React from 'react';
|
||||
import { Button } from '../components/ui/button';
|
||||
import { Tooltip } from '../components/ui/tooltip';
|
||||
import { useAuth } from '../hooks/auth';
|
||||
import { appName } from '../main';
|
||||
|
||||
const TanStackRouterDevtools =
|
||||
process.env.NODE_ENV === 'production'
|
||||
|
|
@ -15,17 +18,30 @@ const TanStackRouterDevtools =
|
|||
}))
|
||||
);
|
||||
|
||||
export const Route = createRootRoute({
|
||||
interface RouterContext {
|
||||
isAuthenticated: boolean;
|
||||
}
|
||||
|
||||
export const Route = createRootRouteWithContext<RouterContext>()({
|
||||
component: () => {
|
||||
const { isAuthenticated, logout } = useAuth();
|
||||
return (
|
||||
<Stack padding={3}>
|
||||
<Stack flexDirection={'row'} justifyContent={'space-between'}>
|
||||
<Link to="/">
|
||||
<Button>Home</Button>
|
||||
</Link>
|
||||
<Stack flexDirection="row" justifyContent="space-between" alignItems="center">
|
||||
<Stack flexDirection="row" alignItems="center" gap={4}>
|
||||
<Link to="/">
|
||||
<Text color="colorPalette.500" fontSize="xl">
|
||||
[{appName}]
|
||||
</Text>
|
||||
</Link>
|
||||
<Link to="/about">
|
||||
<Icon color="colorPalette.500" fontSize="md">
|
||||
<i className="nf nf-oct-question" />
|
||||
</Icon>
|
||||
</Link>
|
||||
</Stack>
|
||||
|
||||
<Stack flexDirection={'row'}>
|
||||
<Stack flexDirection="row" alignItems="center">
|
||||
{!isAuthenticated ? (
|
||||
<>
|
||||
<Link to="/login">
|
||||
|
|
@ -36,7 +52,11 @@ export const Route = createRootRoute({
|
|||
</Link>
|
||||
</>
|
||||
) : (
|
||||
<Button onClick={async () => logout()}>Log out</Button>
|
||||
<Tooltip content="Log out">
|
||||
<Icon color="colorPalette.500" fontSize="xl" onClick={async () => logout()}>
|
||||
<i className="nf nf-fa-sign_out" />
|
||||
</Icon>
|
||||
</Tooltip>
|
||||
)}
|
||||
</Stack>
|
||||
</Stack>
|
||||
|
|
|
|||
21
app/client/pages/about.tsx
Normal file
21
app/client/pages/about.tsx
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
import { Text, Icon, Stack } from '@chakra-ui/react';
|
||||
import { createFileRoute } from '@tanstack/react-router';
|
||||
|
||||
export const Route = createFileRoute('/about')({
|
||||
component: About
|
||||
});
|
||||
|
||||
function About() {
|
||||
return (
|
||||
<Stack flexDirection={'row'} alignItems={'center'}>
|
||||
<Text>Hello from About!</Text>
|
||||
<Text>And NerdFonts!</Text>
|
||||
<Icon>
|
||||
<i className="nf nf-fa-heart" />
|
||||
</Icon>
|
||||
<Icon>
|
||||
<i className="nf nf-custom-vim" />
|
||||
</Icon>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
|
@ -6,10 +6,10 @@ import { gql, useQuery } from '@apollo/client';
|
|||
import { BooksManyQuery } from '@generated/types';
|
||||
|
||||
export const Route = createFileRoute('/')({
|
||||
component: Index
|
||||
component: Dashboard
|
||||
});
|
||||
|
||||
function Index() {
|
||||
function Dashboard() {
|
||||
const { data, refetch } = useQuery<BooksManyQuery>(getBooksQuery);
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -2,14 +2,17 @@ import { Heading, Input, Stack } from '@chakra-ui/react';
|
|||
import { Button } from '@client/components/ui/button';
|
||||
import { Field } from '@client/components/ui/field';
|
||||
import { valibotResolver } from '@hookform/resolvers/valibot';
|
||||
import { createFileRoute, useNavigate } from '@tanstack/react-router';
|
||||
import { createFileRoute, redirect } from '@tanstack/react-router';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import * as v from 'valibot';
|
||||
import { PasswordInput } from '../components/ui/password-input';
|
||||
import { useAuth } from '../hooks/auth';
|
||||
|
||||
export const Route = createFileRoute('/login')({
|
||||
component: LoginComponent
|
||||
component: LoginComponent,
|
||||
beforeLoad: ({ context }) => {
|
||||
if (context.isAuthenticated) throw redirect({ to: '/' });
|
||||
}
|
||||
});
|
||||
|
||||
function LoginComponent() {
|
||||
|
|
@ -27,8 +30,6 @@ interface FormValues {
|
|||
}
|
||||
|
||||
function LoginForm() {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const schema = v.pipe(
|
||||
v.object({
|
||||
email: v.pipe(v.string(), v.nonEmpty('Email is required'), v.email('Invalid email')),
|
||||
|
|
@ -51,7 +52,7 @@ function LoginForm() {
|
|||
email: values.email,
|
||||
password: values.password
|
||||
});
|
||||
if (session != null) navigate({ to: '/' });
|
||||
if (session != null) window.history.back();
|
||||
})}
|
||||
>
|
||||
<Stack>
|
||||
|
|
|
|||
|
|
@ -5,13 +5,16 @@ import { Field } from '@client/components/ui/field';
|
|||
import { PasswordInput } from '@client/components/ui/password-input';
|
||||
import { Session } from '@generated/types';
|
||||
import { valibotResolver } from '@hookform/resolvers/valibot';
|
||||
import { createFileRoute, useNavigate } from '@tanstack/react-router';
|
||||
import { createFileRoute, redirect, useNavigate } from '@tanstack/react-router';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import * as v from 'valibot';
|
||||
import { useToastMutation } from '../hooks/useToastMutation';
|
||||
|
||||
export const Route = createFileRoute('/register')({
|
||||
component: RegisterComponent
|
||||
component: RegisterComponent,
|
||||
beforeLoad: ({ context }) => {
|
||||
if (context.isAuthenticated) throw redirect({ to: '/' });
|
||||
}
|
||||
});
|
||||
|
||||
function RegisterComponent() {
|
||||
|
|
@ -43,8 +46,11 @@ function SignUpForm() {
|
|||
username: v.pipe(v.string(), v.nonEmpty('Username is required')),
|
||||
password: v.pipe(
|
||||
v.string(),
|
||||
v.nonEmpty('Password is required'),
|
||||
v.minLength(8, 'Needs to be at least 8 characters')
|
||||
v.minLength(8, 'Your password is too short.'),
|
||||
v.maxLength(45, 'Your password is too long.'),
|
||||
v.regex(/[a-z]/, 'Your password must contain a lowercase letter.'),
|
||||
v.regex(/[A-Z]/, 'Your password must contain a uppercase letter.'),
|
||||
v.regex(/[0-9]/, 'Your password must contain a number.')
|
||||
),
|
||||
confirm_password: v.pipe(v.string(), v.nonEmpty('Confirm your password'))
|
||||
}),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue