Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 0 additions & 15 deletions src/app/login/layout.tsx

This file was deleted.

77 changes: 0 additions & 77 deletions src/app/login/page.tsx

This file was deleted.

5 changes: 1 addition & 4 deletions src/app/ui/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import type { JSX } from 'react';
import React from 'react';
import ThemeRegistry from '@ui/providers/ThemeRegistry';
import { AppBar, Container, Toolbar, Typography } from '@mui/material';
import PageContainer from '@ui/components/common/PageContainer';
import type { SharedLayoutProps } from '@shared/props/SharedLayoutProps';

export const metadata: Metadata = {
Expand All @@ -28,9 +27,7 @@ export default function RootLayout({
<Typography variant="h6">Locklite</Typography>
</Toolbar>
</AppBar>
<Container component="main">
<PageContainer>{children}</PageContainer>
</Container>
<Container component="main">{children}</Container>
</ThemeRegistry>
</body>
</html>
Expand Down
17 changes: 17 additions & 0 deletions src/app/ui/login/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
'use client';

import React from 'react';
import type { JSX } from 'react';
import PageContainer from '@ui/components/common/PageContainer';
import { SessionProvider } from 'next-auth/react';
import { SignInForm } from '@ui/components/auth/molecules/SignInForm';

export default function SignInPage(): JSX.Element {
return (
<PageContainer title={'Login'}>
<SessionProvider>
<SignInForm />
</SessionProvider>
</PageContainer>
);
}
3 changes: 2 additions & 1 deletion src/app/ui/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { JSX } from 'react';
import { redirect } from 'next/navigation';
import { RoutesEnum } from '@ui/router/routes.enum';

export default function HomePage(): JSX.Element {
redirect('/ui/workspace');
redirect(RoutesEnum.LOGIN);
}
7 changes: 0 additions & 7 deletions src/app/ui/workspace/layout.tsx

This file was deleted.

18 changes: 4 additions & 14 deletions src/app/ui/workspace/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,13 @@
import 'reflect-metadata';
import React from 'react';
import type { JSX } from 'react';
import DynamicVaultsList from '@ui/components/vaults/templates/DynamicVaultsList';
import { Container, Typography } from '@mui/material';
import DynamicVaultsList from '@ui/components/vaults/organisms/DynamicVaultsList';
import PageContainer from '@ui/components/common/PageContainer';

export default function WorkspacePage(): JSX.Element {
return (
<Container
sx={{
padding: '2rem',
display: 'flex',
flexDirection: 'column',
gap: '3rem',
}}
>
<Typography variant={'h3'} textAlign={'left'}>
My vaults
</Typography>
<PageContainer title={'My vaults'}>
<DynamicVaultsList />
</Container>
</PageContainer>
);
}
6 changes: 5 additions & 1 deletion src/lib/auth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { PrismaAdapter } from '@next-auth/prisma-adapter';
import prisma from '@lib/prisma';
import { compare } from 'bcrypt';
import type { User } from '@prisma/generated';
import { RoutesEnum } from '@ui/router/routes.enum';

export const authOptions: NextAuthOptions = {
adapter: PrismaAdapter(prisma),
Expand All @@ -30,6 +31,9 @@ export const authOptions: NextAuthOptions = {
},
}),
],
pages: { signIn: '/login' },
pages: {
signIn: RoutesEnum.LOGIN,
signOut: RoutesEnum.LOGIN,
},
secret: process.env.NEXTAUTH_SECRET,
};
5 changes: 5 additions & 0 deletions src/modules/shared/auth/session-status.enum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export enum SessionStatus {
AUTHENTICATED = 'authenticated',
LOADING = 'loading',
UNAUTHENTICATED = 'unauthenticated',
}
86 changes: 86 additions & 0 deletions src/modules/ui/components/auth/molecules/SignInForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
'use client';

import type { JSX } from 'react';
import React, { useState, useEffect } from 'react';
import type { SignInResponse } from 'next-auth/react';
import { signIn, useSession } from 'next-auth/react';
import { useRouter } from 'next/navigation';
import Button from '@mui/material/Button';
import TextField from '@mui/material/TextField';
import type { AppRouterInstance } from 'next/dist/shared/lib/app-router-context.shared-runtime';
import { SessionStatus } from '@shared/auth/session-status.enum';
import { RoutesEnum } from '@ui/router/routes.enum';
import CircularLoader from '@ui/components/common/CircularLoader';
import { Box } from '@mui/material';

export function SignInForm(): JSX.Element | null {
const { data: session, status } = useSession();
const router: AppRouterInstance = useRouter();
const [email, setEmail] = useState<string>('');
const [password, setPassword] = useState<string>('');
const [error, setError] = useState<Error | null>(null);

useEffect(() => {
if (status === SessionStatus.AUTHENTICATED) {
router.push(RoutesEnum.WORKSPACE);
}
}, [session, status, router]);

if (status === SessionStatus.LOADING) {
return <CircularLoader loading={true} />;
}

if (status === SessionStatus.AUTHENTICATED) {
return null;
}

async function handleSubmit(e: React.FormEvent): Promise<void> {
e.preventDefault();
setError(null);
const res: SignInResponse | undefined = await signIn('credentials', {
email,
password,
redirect: false,
});
if (res?.error) {
setError(new Error('Invalid credentials'));
} else {
router.push(RoutesEnum.WORKSPACE);
}
}

return (
// eslint-disable-next-line no-restricted-syntax
<form onSubmit={handleSubmit}>
<Box display="flex" flexDirection="column" width={500} gap={2}>
<Box display="flex" flexDirection="column" gap={2}>
<TextField
error={!!error}
helperText={error ? error.message : null}
label="Email"
type="email"
fullWidth
value={email}
onChange={e => setEmail(e.target.value)}
/>
<TextField
error={!!error}
helperText={error ? error.message : null}
label="Password"
type="password"
fullWidth
value={password}
onChange={e => setPassword(e.target.value)}
/>
</Box>
<Button
type="submit"
variant={'contained'}
sx={{ width: 'fit-content' }}
>
Sign in
</Button>
</Box>
</form>
);
}
22 changes: 19 additions & 3 deletions src/modules/ui/components/common/PageContainer.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import type { JSX } from 'react';
import React from 'react';
import { Container } from '@mui/material';
import { Container, Typography } from '@mui/material';
import type { SharedChildrenProps } from '@shared/props/SharedChildrenProps';

export default function PageContainer(props: SharedChildrenProps): JSX.Element {
type PageContainerProps = {
title: string;
} & SharedChildrenProps;

export default function PageContainer(props: PageContainerProps): JSX.Element {
return (
<Container
sx={{
Expand All @@ -14,7 +18,19 @@ export default function PageContainer(props: SharedChildrenProps): JSX.Element {
alignItems: 'center',
}}
>
{props.children}
<Container
sx={{
padding: '2rem',
display: 'flex',
flexDirection: 'column',
gap: '3rem',
}}
>
<Typography variant={'h3'} textAlign={'left'}>
{props.title}
</Typography>
{props.children}
</Container>
</Container>
);
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Box, Button } from '@mui/material';
import ErrorMessage from '@ui/components/common/ErrorMessage';
import SearchBar from '@ui/components/common/SearchBar';
import AddVaultModal from '@ui/components/vaults/templates/AddVaultModal';
import AddVaultModal from '@ui/components/vaults/organisms/AddVaultModal';
import React, { useState } from 'react';
import type { JSX } from 'react';
import VaultsList from '../organisms/VaultsList';
import { useVaults } from '@ui/hooks/useVaults';
import VaultsList from './VaultsList';
import { useVaults } from '@ui/hooks/api/fetch/useVaults';
import type { VaultModelDto } from '@shared/dto/models/vault.model.dto';
import AddIcon from '@mui/icons-material/Add';

Expand Down
5 changes: 5 additions & 0 deletions src/modules/ui/router/routes.enum.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export enum RoutesEnum {
HOMEPAGE = '/ui',
WORKSPACE = '/ui/workspace',
LOGIN = '/ui/login',
}