feat: design applications and first api calls

Co-authored-by: Walid <87608619+WalidKorchi@users.noreply.github.com>
This commit is contained in:
Divlo
2021-10-24 06:09:43 +02:00
parent 33bd2bb6bf
commit a0fa66e8f5
136 changed files with 14787 additions and 1668 deletions

View File

@ -0,0 +1,30 @@
import { Meta, Story } from '@storybook/react'
import { Input, InputProps } from './Input'
import { AuthenticationForm } from '../../Authentication/AuthenticationForm'
const Stories: Meta = {
title: 'Input',
component: Input
}
export default Stories
const Template: Story<InputProps> = (arguments_) => (
<AuthenticationForm>
<Input {...arguments_} />
</AuthenticationForm>
)
export const Text = Template.bind({})
Text.args = { label: 'Text', name: 'text', type: 'text' }
export const Password = Template.bind({})
Password.args = { label: 'Password', name: 'password', type: 'password' }
export const Error = Template.bind({})
Error.args = {
label: 'Error',
type: 'text',
error: 'Oops, this field is required 🙈.'
}

View File

@ -0,0 +1,52 @@
import { render, fireEvent } from '@testing-library/react'
import { Input, getInputType } from './'
describe('<Input />', () => {
it('should render the label', async () => {
const labelContent = 'label content'
const { getByText } = render(<Input label={labelContent} />)
expect(getByText(labelContent)).toBeInTheDocument()
})
it('should not render forgot password link', async () => {
const { queryByTestId } = render(
<Input type='text' label='content' showForgotPassword />
)
const forgotPasswordLink = queryByTestId('forgot-password-link')
expect(forgotPasswordLink).not.toBeInTheDocument()
})
it('should render forgot password link', async () => {
const { queryByTestId } = render(
<Input type='password' label='content' showForgotPassword />
)
const forgotPasswordLink = queryByTestId('forgot-password-link')
expect(forgotPasswordLink).toBeInTheDocument()
})
it('should not render the eye icon if the input is not of type "password"', async () => {
const { queryByTestId } = render(<Input type='text' label='content' />)
const passwordEye = queryByTestId('password-eye')
expect(passwordEye).not.toBeInTheDocument()
})
it('should handlePassword with eye icon', async () => {
const { findByTestId } = render(<Input type='password' label='content' />)
const passwordEye = await findByTestId('password-eye')
const input = await findByTestId('input')
expect(input).toHaveAttribute('type', 'password')
fireEvent.click(passwordEye)
expect(input).toHaveAttribute('type', 'text')
})
})
describe('getInputType', () => {
it('should return `text`', async () => {
expect(getInputType('password')).toEqual('text')
})
it('should return `password`', async () => {
expect(getInputType('text')).toEqual('password')
})
})

View File

@ -0,0 +1,90 @@
import { useState } from 'react'
import Link from 'next/link'
import useTranslation from 'next-translate/useTranslation'
import { FormState } from '../FormState'
export interface InputProps extends React.ComponentPropsWithRef<'input'> {
label: string
error?: string | null
showForgotPassword?: boolean
}
export const getInputType = (inputType: string): string => {
return inputType === 'password' ? 'text' : 'password'
}
export const Input: React.FC<InputProps> = (props) => {
const {
label,
name,
type = 'text',
showForgotPassword = false,
error,
...rest
} = props
const { t } = useTranslation()
const [inputType, setInputType] = useState(type)
const handlePassword = (): void => {
const oppositeType = getInputType(inputType)
setInputType(oppositeType)
}
return (
<>
<div className='flex flex-col'>
<div className='flex justify-between mt-6 mb-2'>
<label className='pl-1' htmlFor={name}>
{label}
</label>
{type === 'password' && showForgotPassword ? (
<Link href='/authentication/forgot-password'>
<a
className='font-headline text-center text-xs sm:text-sm text-green-800 dark:text-green-400 hover:underline'
data-testid='forgot-password-link'
>
{t('authentication:forgot-password')}
</a>
</Link>
) : null}
</div>
<div className='mt-0 relative'>
<input
data-testid='input'
data-cy={`input-${name ?? 'name'}`}
className='h-11 leading-10 px-3 rounded-lg bg-[#f1f1f1] text-[#2a2a2a] caret-green-600 font-paragraph w-full focus:border focus:outline-none focus:shadow-green border-0'
{...rest}
id={name}
name={name}
type={inputType}
/>
{type === 'password' && (
<div
data-testid='password-eye'
onClick={handlePassword}
className='password-eye absolute cursor-pointer bg-cover bg-[#f1f1f1]'
/>
)}
<FormState
id={`error-${name ?? 'input'}`}
state={error == null ? 'idle' : 'error'}
message={error}
/>
</div>
</div>
<style jsx>
{`
.password-eye {
top: 12px;
right: 16px;
z-index: 1;
width: 20px;
height: 20px;
background-image: url('/images/svg/icons/input/${inputType}.svg');
}
`}
</style>
</>
)
}

View File

@ -0,0 +1 @@
export * from './Input'