From c751088e06982acba71e088440a956f2977f1922 Mon Sep 17 00:00:00 2001 From: GAURAV SINHA Date: Fri, 29 Sep 2023 12:17:13 +0530 Subject: [PATCH 1/2] feat: login page(UI) --- .eslintrc | 5 ++ __tests__/pages/login.js | 39 ++++++++++++++ src/pages/_app.js | 13 ++++- src/pages/dashboard/index.js | 78 +++++++++++++++++++++++++++ src/pages/index.tsx | 85 ++--------------------------- src/pages/login/index.js | 102 +++++++++++++++++++++++++++++++++++ src/styles/global.css | 4 ++ 7 files changed, 243 insertions(+), 83 deletions(-) create mode 100644 __tests__/pages/login.js create mode 100644 src/pages/dashboard/index.js create mode 100644 src/pages/login/index.js diff --git a/.eslintrc b/.eslintrc index cefaf8c..80e4b5e 100644 --- a/.eslintrc +++ b/.eslintrc @@ -11,6 +11,11 @@ "ecmaVersion": "latest", "sourceType": "module" }, + "globals": { + "describe": "readonly", + "it": "readonly", + "expect": "readonly" + }, "plugins": ["@typescript-eslint", "prettier"], "rules": { "linebreak-style": ["error", "unix"], diff --git a/__tests__/pages/login.js b/__tests__/pages/login.js new file mode 100644 index 0000000..5dccd9c --- /dev/null +++ b/__tests__/pages/login.js @@ -0,0 +1,39 @@ +import LoginPage from '../../src/pages/login'; +import { render, fireEvent } from '@testing-library/react'; + +describe('LoginPage', () => { + it('should render without throwing an error', function () { + const { container } = render(); + expect(container).toMatchSnapshot(); + }); + it('should render username input', () => { + const { getByLabelText } = render(); + expect(getByLabelText('Username')).toBeInTheDocument(); + expect(getByLabelText('Username')).toHaveAttribute('type', 'text'); + }); + it('should render password input', () => { + const { getByLabelText } = render(); + expect(getByLabelText('Password')).toBeInTheDocument(); + expect(getByLabelText('Password')).toHaveAttribute('type', 'password'); + }); + it('should render the `Login` button', () => { + const { getByText } = render(); + expect(getByText('Log in')).toBeInTheDocument(); + }); + it('should accept valid username that takes only alphanumeric characters and underscore', () => { + const { getByLabelText } = render(); + const usernameInput = getByLabelText('Username'); + usernameInput.value = 'John_doe'; + expect(usernameInput.value).toBe('John_doe'); + }); + it('should not accept invalid username that doesnt take only alphanumeric characters and underscore', () => { + const { getByLabelText } = render(); + const input = getByLabelText('Username'); + fireEvent.change(input, { target: { value: 'valid_username' } }); + expect(input).toHaveStyle('border-color: `#65a30d'); + + // Invalid input + fireEvent.change(input, { target: { value: 'invalid-username' } }); + expect(input).toHaveStyle('border-color: `#ef4444`'); + }); +}); diff --git a/src/pages/_app.js b/src/pages/_app.js index 2d8c29f..6375af4 100644 --- a/src/pages/_app.js +++ b/src/pages/_app.js @@ -1,5 +1,16 @@ import '@/styles/global.css'; +import { Footer } from '@/components/Footer/Footer'; +import { Navbar } from '@/components/Navbar/Navbar'; export default function MyApp({ Component, pageProps }) { - return ; + return ( +
+ URL Shortener + +
+ +
+
+
+ ); } diff --git a/src/pages/dashboard/index.js b/src/pages/dashboard/index.js new file mode 100644 index 0000000..7e52711 --- /dev/null +++ b/src/pages/dashboard/index.js @@ -0,0 +1,78 @@ +import React, { useState } from 'react'; +import CopyIcon from '../../../public/assets/icons/copy'; +import AddIcon from '../../../public/assets/icons/add'; +import ReloadIcon from '../../../public/assets/icons/reload'; + +const Dashboard = () => { + const [url, getUrl] = useState(''); + const [shortUrl, setUrl] = useState(''); + + function generateRandomString() { + const randomString = Math.random().toString(36).substring(2, 7); + return randomString; + } + + return ( +
+

URL Shortener

+
+ { + getUrl(e.target.value); + }} + /> + +
+
+ +
+ + + +
+
+
+ ); +}; + +export default Dashboard; diff --git a/src/pages/index.tsx b/src/pages/index.tsx index 482d7f5..bc645e8 100644 --- a/src/pages/index.tsx +++ b/src/pages/index.tsx @@ -1,85 +1,6 @@ -import React, { useState } from 'react'; -import { Footer } from '@/components/Footer/Footer'; -import { Navbar } from '@/components/Navbar/Navbar'; -import CopyIcon from './../../public/assets/icons/copy'; -import AddIcon from './../../public/assets/icons/add'; -import ReloadIcon from './../../public/assets/icons/reload'; +import React from 'react'; +import Dashboard from './dashboard'; export default function Home() { - const [url, getUrl] = useState(''); - const [shortUrl, setUrl] = useState(''); - - function generateRandomString() { - const randomString = Math.random().toString(36).substring(2, 7); - return randomString; - } - - return ( -
- URL Shortener - -
-
-

URL Shortener

-
- { - getUrl(e.target.value); - }} - /> - -
-
- -
- - - -
-
-
-
-
-
- ); + return ; } diff --git a/src/pages/login/index.js b/src/pages/login/index.js new file mode 100644 index 0000000..022288c --- /dev/null +++ b/src/pages/login/index.js @@ -0,0 +1,102 @@ +import React, { useState } from 'react'; + +const LoginPage = () => { + const [isValid, setIsValid] = useState(null); + const handleChange = (event) => { + const inputValue = event.target.value; + const regex = /^[a-zA-Z0-9_]+$/; // Alphanumeric characters and underscores + + if (regex.test(inputValue)) { + setIsValid(true); + } else { + setIsValid(false); + } + }; + return ( +
+
+ URL Shortener +
+
+
+
+
+ + +
+
+ + +
+
+
+
+ +
+
+ +
+
+ + Forgot password? + +
+ +

+ Don’t have an account yet?{' '} + + Sign up + +

+
+
+
+
+ ); +}; + +export default LoginPage; diff --git a/src/styles/global.css b/src/styles/global.css index b5c61c9..9a66659 100644 --- a/src/styles/global.css +++ b/src/styles/global.css @@ -1,3 +1,7 @@ @tailwind base; @tailwind components; @tailwind utilities; + +.h-container { + height: calc(100vh - (82px + 6vh)); +} From 4f7b4fe953ab2df8262e6f1c1b436c06260f1a71 Mon Sep 17 00:00:00 2001 From: GAURAV SINHA Date: Fri, 29 Sep 2023 22:08:54 +0530 Subject: [PATCH 2/2] removed comments --- __tests__/pages/login.js | 1 - src/pages/login/index.js | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/__tests__/pages/login.js b/__tests__/pages/login.js index 5dccd9c..c01cdcd 100644 --- a/__tests__/pages/login.js +++ b/__tests__/pages/login.js @@ -32,7 +32,6 @@ describe('LoginPage', () => { fireEvent.change(input, { target: { value: 'valid_username' } }); expect(input).toHaveStyle('border-color: `#65a30d'); - // Invalid input fireEvent.change(input, { target: { value: 'invalid-username' } }); expect(input).toHaveStyle('border-color: `#ef4444`'); }); diff --git a/src/pages/login/index.js b/src/pages/login/index.js index 022288c..1a5457a 100644 --- a/src/pages/login/index.js +++ b/src/pages/login/index.js @@ -4,7 +4,7 @@ const LoginPage = () => { const [isValid, setIsValid] = useState(null); const handleChange = (event) => { const inputValue = event.target.value; - const regex = /^[a-zA-Z0-9_]+$/; // Alphanumeric characters and underscores + const regex = /^[a-zA-Z0-9_]+$/; if (regex.test(inputValue)) { setIsValid(true);