Skip to content

Commit

Permalink
add login page
Browse files Browse the repository at this point in the history
  • Loading branch information
Krauzy committed Sep 27, 2024
1 parent d31d51a commit 94459c5
Show file tree
Hide file tree
Showing 13 changed files with 416 additions and 7 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,6 @@ yarn-error.log*
# typescript
*.tsbuildinfo
next-env.d.ts

# env
*.env
3 changes: 3 additions & 0 deletions src/app/api/authentication/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export async function POST(request: Request) {

}
57 changes: 57 additions & 0 deletions src/app/login/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
'use client'

import Navbar from "@/components/Navbar";
import Tile from "@/components/Tile";
import getLocale from "@/config/data";
import { ThemeContext } from "@/contexts/ThemeContext";
import { useContext, useState } from "react";
import { AnchorBack, LoginButton, LoginContainer, LoginContent, LoginFooterContainer, LoginInnerContent, LoginTitle } from "./styles";
import { GhostAsset, GhostAssetContainer } from "../styles";
import TextBox from "@/components/TextBox";
import PasswordBox from "@/components/PasswordBox";

export default function Login() {

const { locale } = useContext(ThemeContext)
const localeData = getLocale(locale);
const title = 'login';

const [email, setEmail] = useState<string>('');
const [emailError, setEmailError] = useState<boolean>(false);
const [password, setPassword] = useState<string>('');
const [passwordError, setPasswordError] = useState<boolean>(false);

return (
<Tile maxWidth={1440} title={`krauzy • ${title}`}>
<Navbar />
<LoginContainer>
<LoginContent>
<LoginTitle>LOGIN</LoginTitle>
<LoginInnerContent>
<TextBox
placeholder={localeData.login.emailPlaceholder}
label={localeData.login.email}
value={email}
setValue={setEmail}
error={emailError ? localeData.login.emailError : undefined}
/>
<PasswordBox
placeholder={localeData.login.passwordPlaceholder}
label={localeData.login.password}
value={password}
setValue={setPassword}
error={passwordError ? localeData.login.passwordError : undefined}
/>
</LoginInnerContent>
<LoginFooterContainer>
<LoginButton>{localeData.login.loginButton}</LoginButton>
<AnchorBack href={'/'}>{localeData.login.back}</AnchorBack>
</LoginFooterContainer>
</LoginContent>
<GhostAssetContainer>
<GhostAsset src={'/assets/ghost.svg'} />
</GhostAssetContainer>
</LoginContainer>
</Tile>
)
}
95 changes: 95 additions & 0 deletions src/app/login/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import Link from "next/link";
import styled, { keyframes } from "styled-components"

export const LoginContainer = styled.div`
width: 100%;
display: flex;
padding-top: 10em;
@media screen and (max-width: 1100px) {
flex-direction: column-reverse;
padding-top: 3em;
gap: 4em;
padding-bottom: 10em;
}
`;

export const LoginContent = styled.div`
width: 60%;
display: flex;
flex-direction: column;
gap: 3em;
@media screen and (max-width: 1100px) {
width: 100%;
}
`;

export const LoginInnerContent = styled.div`
display: flex;
flex-direction: column;
width: 100%;
padding-right: 2em;
gap: 2em;
@media screen and (max-width: 1100px) {
padding-right: 0;
}
`;

export const LoginTitle = styled.span`
font-size: 1.8em;
font-weight: 700;
font-family: ${props => props.theme.fonts.spaceMono};
color: ${props => props.theme.color.secondary};
@media screen and (max-width: 1100px) {
font-size: 1.5em;
}
`;

export const LoginFooterContainer = styled.div`
width: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 1em;
`;

export const LoginButton = styled.button`
background-color: ${props => props.theme.color.purple};
width: 50%;
padding: .6em;
font-family: ${props => props.theme.fonts.spaceMono};
font-weight: 700;
font-size: 1.3em;
color: ${props => props.theme.color.secondary};
border-radius: 12px;
transition: all .2s ease-in-out;
&:hover {
opacity: .75;
}
@media screen and (max-width: 1100px) {
width: 100%;
font-size: 1.1em;
}
`;

export const AnchorBack = styled(Link)`
font-family: ${props => props.theme.fonts.spaceMono};
color: ${props => props.theme.color.variation.secondary(.40)};
text-decoration: underline;
transition: all .2s ease-in-out;
font-size: .9em;
&:hover {
color: ${props => props.theme.color.purple};
}
@media screen and (max-width: 1100px) {
font-size: .8em;
}
`;
8 changes: 4 additions & 4 deletions src/components/Navbar/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default function Navbar() {
<MenuList off>
<MenuItem href={'/'}>{localeData.menu.home}</MenuItem>
<MenuItem href={'/about'}>{localeData.menu.about}</MenuItem>
<MenuItem href={'/appplication'}>{localeData.menu.applications}</MenuItem>
<MenuItem href={'/application'}>{localeData.menu.applications}</MenuItem>
<MenuItem href={'/tools'}>{localeData.menu.tools}</MenuItem>
<MenuItem href={'/games'}>{localeData.menu.games}</MenuItem>
</MenuList>
Expand All @@ -36,12 +36,12 @@ export default function Navbar() {
<FontAwesomeIcon icon={actualTheme === 'light' ? faMoon : faSun} />
</ThemeSwitcher>
<LocaleSwitcher onClick={() => switchLocale(locale === 'pt' ? 'en' : 'pt')}>{locale}</LocaleSwitcher>
<LoginButton>login</LoginButton>
<LoginButton href={'/login'}>login</LoginButton>
</WidgetSettings>
<MenuList>
<MenuItem href={'/'}>{localeData.menu.home}</MenuItem>
<MenuItem href={'/about'}>{localeData.menu.about}</MenuItem>
<MenuItem href={'/appplication'}>{localeData.menu.applications}</MenuItem>
<MenuItem href={'/application'}>{localeData.menu.applications}</MenuItem>
<MenuItem href={'/tools'}>{localeData.menu.tools}</MenuItem>
<MenuItem href={'/games'}>{localeData.menu.games}</MenuItem>
</MenuList>
Expand All @@ -53,7 +53,7 @@ export default function Navbar() {
<FontAwesomeIcon icon={actualTheme === 'light' ? faMoon : faSun} />
</ThemeSwitcher>
<LocaleSwitcher onClick={() => switchLocale(locale === 'pt' ? 'en' : 'pt')}>{locale}</LocaleSwitcher>
<LoginButton>login</LoginButton>
<LoginButton href={'/login'}>login</LoginButton>
</WidgetSettings>
</NavContainer>
)
Expand Down
2 changes: 1 addition & 1 deletion src/components/Navbar/styles.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ export const LocaleSwitcher = styled.button`
}
`;

export const LoginButton = styled.button`
export const LoginButton = styled.a`
background-color: ${props => props.theme.color.purple};
height: 2.2em;
font-weight: 600;
Expand Down
41 changes: 41 additions & 0 deletions src/components/PasswordBox/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { faEye, faEyeSlash, faWarning } from "@fortawesome/free-solid-svg-icons";
import { PasswordBoxContainer, PasswordBoxError, PasswordBoxErrorContainer, PasswordBoxErrorIcon, PasswordBoxInput, PasswordBoxLabel, PasswordContentBox, PasswordShow } from "./styles";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { useState } from "react";

interface PasswordBoxProperties {
label: string;
placeholder: string;
value: string;
setValue: (value: string) => void;
error?: string;
}

export default function PasswordBox({
label,
placeholder,
value,
setValue,
error
}: PasswordBoxProperties) {

const [showPassword, setShowPassword] = useState<boolean>(false);

return (
<PasswordBoxContainer>
<PasswordBoxLabel>{label}</PasswordBoxLabel>
<PasswordContentBox>
<PasswordBoxInput placeholder={placeholder} type={showPassword ? 'text' : 'password'} />
<PasswordShow>
<FontAwesomeIcon icon={showPassword ? faEye : faEyeSlash} onClick={() => setShowPassword(!showPassword)} />
</PasswordShow>
</PasswordContentBox>
{error &&
<PasswordBoxErrorContainer>
<PasswordBoxErrorIcon icon={faWarning} />
<PasswordBoxError>{error}</PasswordBoxError>
</PasswordBoxErrorContainer>
}
</PasswordBoxContainer>
)
}
75 changes: 75 additions & 0 deletions src/components/PasswordBox/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import styled from "styled-components"

export const PasswordBoxContainer = styled.div`
display: flex;
flex-direction: column;
gap: .5em;
`;

export const PasswordBoxLabel = styled.label`
font-size: 1.2em;
font-weight: 600;
font-family: ${props => props.theme.fonts.spaceMono};
color: ${props => props.theme.color.secondary};
@media screen and (max-width: 1100px) {
font-size: 1em;
}
`;

export const PasswordShow = styled.button`
font-size: 1em;
color: ${props => props.theme.color.purple};
`;

export const PasswordContentBox = styled.div`
display: flex;
background-color: ${props => props.theme.color.variation.secondary(.10)};
padding: .8em 1em;
border-radius: 12px;
border: 2px solid ${props => props.theme.color.primary};
transition: all .2s ease-in-out;
&:focus-within {
border-color: ${props => props.theme.color.purple};
}
@media screen and (max-width: 1100px) {
padding: .6em 1em;
}
`;

export const PasswordBoxInput = styled.input`
background-color: transparent;
outline: none;
font-family: ${props => props.theme.fonts.spaceMono};
color: ${props => props.theme.color.secondary};
font-size: .9em;
width: 100%;
padding: 0;
@media screen and (max-width: 1100px) {
font-size: .8em;
}
`;

export const PasswordBoxErrorContainer = styled.div`
display: flex;
gap: .3em;
align-items: center;
font-size: .9em;
padding-left: 1em;
color: ${props => props.theme.color.error};
@media screen and (max-width: 1100px) {
font-size: .7em;
}
`;

export const PasswordBoxErrorIcon = styled(FontAwesomeIcon)`
`;

export const PasswordBoxError = styled.small`
font-family: ${props => props.theme.fonts.spaceMono};
`;
31 changes: 31 additions & 0 deletions src/components/TextBox/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { faWarning } from "@fortawesome/free-solid-svg-icons";
import { TextBoxContainer, TextBoxError, TextBoxErrorContainer, TextBoxErrorIcon, TextBoxInput, TextBoxLabel } from "./styles";

interface TextBoxProperties {
label: string;
placeholder: string;
value: string;
setValue: (value: string) => void;
error?: string;
}

export default function TextBox({
label,
placeholder,
value,
setValue,
error
}: TextBoxProperties) {
return (
<TextBoxContainer>
<TextBoxLabel>{label}</TextBoxLabel>
<TextBoxInput placeholder={placeholder} value={value} onChange={(e) => setValue(e.target.value)} />
{error &&
<TextBoxErrorContainer>
<TextBoxErrorIcon icon={faWarning} />
<TextBoxError>{error}</TextBoxError>
</TextBoxErrorContainer>
}
</TextBoxContainer>
)
}
Loading

0 comments on commit 94459c5

Please sign in to comment.