diff --git a/package-lock.json b/package-lock.json
index 98f6c4a..c02098d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,6 +8,7 @@
"name": "issp5-front-end",
"version": "0.0.0",
"dependencies": {
+ "@fortawesome/fontawesome-free": "^6.7.2",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-router-dom": "^6.27.0",
@@ -910,6 +911,15 @@
"node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
+ "node_modules/@fortawesome/fontawesome-free": {
+ "version": "6.7.2",
+ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.7.2.tgz",
+ "integrity": "sha512-JUOtgFW6k9u4Y+xeIaEiLr3+cjoUPiAuLXoyKOJSia6Duzb7pq+A76P9ZdPDoAoxHdHzq6gE9/jKBGXlZT8FbA==",
+ "license": "(CC-BY-4.0 AND OFL-1.1 AND MIT)",
+ "engines": {
+ "node": ">=6"
+ }
+ },
"node_modules/@humanfs/core": {
"version": "0.19.1",
"resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
diff --git a/package.json b/package.json
index c5e630d..7788980 100644
--- a/package.json
+++ b/package.json
@@ -10,6 +10,7 @@
"preview": "vite preview"
},
"dependencies": {
+ "@fortawesome/fontawesome-free": "^6.7.2",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-router-dom": "^6.27.0",
diff --git a/src/components/Header.jsx b/src/components/Header.jsx
index ad99c38..0d0ede9 100644
--- a/src/components/Header.jsx
+++ b/src/components/Header.jsx
@@ -1,11 +1,23 @@
-
+import { Link } from "react-router-dom";
const Header = () => {
-
- return (
-
- );
-}
+ return (
+
+
+ {" "}
+ ISSP5{" "}
+
+
+
+ );
+};
-export default Header;
\ No newline at end of file
+export default Header;
diff --git a/src/components/ProtectedRoute.jsx b/src/components/ProtectedRoute.jsx
new file mode 100644
index 0000000..72e6258
--- /dev/null
+++ b/src/components/ProtectedRoute.jsx
@@ -0,0 +1,14 @@
+import { Navigate } from "react-router-dom";
+
+const ProtectedRoute = ({ children }) => {
+ const isLoggedIn = localStorage.getItem("isLoggedIn") === "true";
+
+ if (!isLoggedIn) {
+ // Redirect to login if not logged in
+ return ;
+ }
+
+ return children;
+};
+
+export default ProtectedRoute;
diff --git a/src/pages/PageHome.jsx b/src/pages/HomePage.jsx
similarity index 100%
rename from src/pages/PageHome.jsx
rename to src/pages/HomePage.jsx
diff --git a/src/pages/LoginPage.jsx b/src/pages/LoginPage.jsx
new file mode 100644
index 0000000..e7b1385
--- /dev/null
+++ b/src/pages/LoginPage.jsx
@@ -0,0 +1,64 @@
+// Page - Login
+import { useEffect, useState } from "react";
+import SignInForm from "./SignIn";
+import SignUpForm from "./SignUp";
+import "../scss/styles.scss";
+
+const LoginPage = () => {
+ const [type, setType] = useState("signIn");
+
+ useEffect(() => {
+ document.title = "Login / Sign Up";
+ }, []);
+
+ const handleOnClick = (text) => {
+ if (text !== type) {
+ setType(text);
+ }
+ };
+
+ const containerClass =
+ "container " + (type === "signUp" ? "right-panel-active" : "");
+
+ return (
+
+
+ Sign In/Sign Up
+
+
+
+
+
+
+
Welcome Back!
+
+ To keep connected with us please login with your personal info
+
+
+
+
+
Hello, Friend!
+
Enter your personal details and start journey with us
+
+
+
+
+
+
+
+ );
+};
+
+export default LoginPage;
diff --git a/src/pages/SignIn.jsx b/src/pages/SignIn.jsx
new file mode 100644
index 0000000..b6a203a
--- /dev/null
+++ b/src/pages/SignIn.jsx
@@ -0,0 +1,68 @@
+import React from "react";
+import "@fortawesome/fontawesome-free/css/all.min.css";
+
+function SignInForm() {
+ const [state, setState] = React.useState({
+ email: "",
+ password: "",
+ });
+ const handleChange = (evt) => {
+ const value = evt.target.value;
+ setState({
+ ...state,
+ [evt.target.name]: value,
+ });
+ };
+
+ const handleOnSubmit = (evt) => {
+ evt.preventDefault();
+
+ const { email, password } = state;
+ alert(`You are login with email: ${email} and password: ${password}`);
+
+ for (const key in state) {
+ setState({
+ ...state,
+ [key]: "",
+ });
+ }
+ };
+
+ return (
+
+ );
+}
+
+export default SignInForm;
diff --git a/src/pages/SignUp.jsx b/src/pages/SignUp.jsx
new file mode 100644
index 0000000..64d9042
--- /dev/null
+++ b/src/pages/SignUp.jsx
@@ -0,0 +1,75 @@
+import React from "react";
+function SignUpForm() {
+ const [state, setState] = React.useState({
+ name: "",
+ email: "",
+ password: "",
+ });
+ const handleChange = (evt) => {
+ const value = evt.target.value;
+ setState({
+ ...state,
+ [evt.target.name]: value,
+ });
+ };
+
+ const handleOnSubmit = (evt) => {
+ evt.preventDefault();
+
+ const { name, email, password } = state;
+ alert(
+ `You are sign up with name: ${name} email: ${email} and password: ${password}`
+ );
+
+ for (const key in state) {
+ setState({
+ ...state,
+ [key]: "",
+ });
+ }
+ };
+
+ return (
+
+ );
+}
+
+export default SignUpForm;
diff --git a/src/routers/AppRouter.jsx b/src/routers/AppRouter.jsx
index 2f67646..f076fc5 100644
--- a/src/routers/AppRouter.jsx
+++ b/src/routers/AppRouter.jsx
@@ -5,23 +5,33 @@ import { BrowserRouter, Routes, Route } from "react-router-dom";
// Components
import Header from "../components/Header";
import Footer from "../components/Footer";
+import ProtectedRoute from "../components/ProtectedRoute";
// Pages
-import PageHome from "../pages/PageHome";
+import HomePage from "../pages/HomePage";
+import LoginPage from "../pages/LoginPage";
import PageNotFound from "../pages/PageNotFound";
-function AppRouter() {
+const AppRouter = () => {
return (
- } />
+ } />
+
+
+
+ }
+ />
} />
);
-}
+};
export default AppRouter;
diff --git a/src/scss/components/_header.scss b/src/scss/components/_header.scss
index ea88f2d..58bb0f4 100644
--- a/src/scss/components/_header.scss
+++ b/src/scss/components/_header.scss
@@ -1,11 +1,45 @@
// Header
-@use '../base/settings' as *;
-@use '../utilities/mixins' as *;
+@use "../base/settings" as *;
+@use "../utilities/mixins" as *;
header {
- padding: $section-padding;
- h1 {
- @include flatten;
+ padding: $section-padding;
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ border-bottom: 1px solid $grey;
+
+ h1 {
+ @include flatten;
+
+ a {
+ text-decoration: none;
+ color: $dark;
+
+ &:hover {
+ color: $yellow;
+ }
}
-}
\ No newline at end of file
+ }
+
+ nav {
+ ul {
+ @include flatten(true);
+ display: flex;
+ gap: 1rem;
+
+ li {
+ a {
+ text-decoration: none;
+ color: $dark;
+ font-weight: bold;
+
+ &:hover {
+ color: $yellow;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/scss/login.scss b/src/scss/login.scss
new file mode 100644
index 0000000..d2c183f
--- /dev/null
+++ b/src/scss/login.scss
@@ -0,0 +1,88 @@
+.login-container {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ min-height: 100vh;
+ background-color: #f5f5f5;
+
+ .login-card {
+ width: 100%;
+ max-width: 400px;
+ padding: 2rem;
+ background-color: white;
+ border-radius: 8px;
+ box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
+
+ h2 {
+ text-align: center;
+ margin-bottom: 1.5rem;
+ color: #333;
+ }
+
+ .error-message {
+ background-color: #ffecec;
+ color: #d63031;
+ padding: 0.75rem;
+ border-radius: 4px;
+ margin-bottom: 1rem;
+ text-align: center;
+ }
+
+ .form-group {
+ margin-bottom: 1rem;
+
+ label {
+ display: block;
+ margin-bottom: 0.5rem;
+ font-weight: 500;
+ }
+
+ input {
+ width: 100%;
+ padding: 0.75rem;
+ border: 1px solid #ddd;
+ border-radius: 4px;
+ font-size: 1rem;
+
+ &:focus {
+ outline: none;
+ border-color: #4a90e2;
+ }
+ }
+ }
+
+ .login-button {
+ width: 100%;
+ padding: 0.75rem;
+ background-color: #4a90e2;
+ color: white;
+ border: none;
+ border-radius: 4px;
+ font-size: 1rem;
+ cursor: pointer;
+ transition: background-color 0.3s;
+
+ &:hover {
+ background-color: #3a7bc8;
+ }
+ }
+
+ .login-footer {
+ margin-top: 1.5rem;
+ text-align: center;
+
+ p {
+ margin-bottom: 0.5rem;
+ }
+
+ a {
+ color: #4a90e2;
+ text-decoration: none;
+
+ &:hover {
+ text-decoration: underline;
+ }
+ }
+ }
+ }
+}
diff --git a/src/scss/page/_login.scss b/src/scss/page/_login.scss
new file mode 100644
index 0000000..d80b2f5
--- /dev/null
+++ b/src/scss/page/_login.scss
@@ -0,0 +1,257 @@
+.App {
+ font-family: sans-serif;
+ text-align: center;
+}
+
+@import url("https://fonts.googleapis.com/css?family=Montserrat:400,800");
+
+* {
+ box-sizing: border-box;
+}
+
+body {
+ background: #f6f5f7;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ flex-direction: column;
+ font-family: "Montserrat", sans-serif;
+ height: 100vh;
+ margin: -20px 0 50px;
+}
+
+h1 {
+ font-weight: bold;
+ margin: 0;
+}
+
+h2 {
+ text-align: center;
+}
+
+p {
+ font-size: 14px;
+ font-weight: 100;
+ line-height: 20px;
+ letter-spacing: 0.5px;
+ margin: 20px 0 30px;
+}
+
+span {
+ font-size: 12px;
+}
+
+a {
+ color: #333;
+ font-size: 14px;
+ text-decoration: none;
+ margin: 15px 0;
+}
+
+button {
+ border-radius: 20px;
+ border: 1px solid #ff4b2b;
+ background-color: #ff4b2b;
+ color: #ffffff;
+ font-size: 12px;
+ font-weight: bold;
+ padding: 12px 45px;
+ letter-spacing: 1px;
+ text-transform: uppercase;
+ transition: transform 80ms ease-in;
+}
+
+button:active {
+ transform: scale(0.95);
+}
+
+button:focus {
+ outline: none;
+}
+
+button.ghost {
+ background-color: transparent;
+ border-color: #ffffff;
+}
+
+form {
+ background-color: #ffffff;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-direction: column;
+ padding: 0 50px;
+ height: 100%;
+ text-align: center;
+}
+
+input {
+ background-color: #eee;
+ border: none;
+ padding: 12px 15px;
+ margin: 8px 0;
+ width: 100%;
+}
+
+.container {
+ background-color: #fff;
+ border-radius: 10px;
+ box-shadow: 0 14px 28px rgba(0, 0, 0, 0.25), 0 10px 10px rgba(0, 0, 0, 0.22);
+ position: relative;
+ overflow: hidden;
+ width: 768px;
+ max-width: 100%;
+ min-height: 480px;
+}
+
+.form-container {
+ position: absolute;
+ top: 0;
+ height: 100%;
+ transition: all 0.6s ease-in-out;
+}
+
+.sign-in-container {
+ left: 0;
+ width: 50%;
+ z-index: 2;
+}
+
+.container.right-panel-active .sign-in-container {
+ transform: translateX(100%);
+}
+
+.sign-up-container {
+ left: 0;
+ width: 50%;
+ opacity: 0;
+ z-index: 1;
+}
+
+.container.right-panel-active .sign-up-container {
+ transform: translateX(100%);
+ opacity: 1;
+ z-index: 5;
+ animation: show 0.6s;
+}
+
+@keyframes show {
+ 0%,
+ 49.99% {
+ opacity: 0;
+ z-index: 1;
+ }
+
+ 50%,
+ 100% {
+ opacity: 1;
+ z-index: 5;
+ }
+}
+
+.overlay-container {
+ position: absolute;
+ top: 0;
+ left: 50%;
+ width: 50%;
+ height: 100%;
+ overflow: hidden;
+ transition: transform 0.6s ease-in-out;
+ z-index: 100;
+}
+
+.container.right-panel-active .overlay-container {
+ transform: translateX(-100%);
+}
+
+.overlay {
+ background: #ff416c;
+ background: -webkit-linear-gradient(to right, #ff4b2b, #ff416c);
+ background: linear-gradient(to right, #ff4b2b, #ff416c);
+ background-repeat: no-repeat;
+ background-size: cover;
+ background-position: 0 0;
+ color: #ffffff;
+ position: relative;
+ left: -100%;
+ height: 100%;
+ width: 200%;
+ transform: translateX(0);
+ transition: transform 0.6s ease-in-out;
+}
+
+.container.right-panel-active .overlay {
+ transform: translateX(50%);
+}
+
+.overlay-panel {
+ position: absolute;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ flex-direction: column;
+ padding: 0 40px;
+ text-align: center;
+ top: 0;
+ height: 100%;
+ width: 50%;
+ transform: translateX(0);
+ transition: transform 0.6s ease-in-out;
+}
+
+.overlay-left {
+ transform: translateX(-20%);
+}
+
+.container.right-panel-active .overlay-left {
+ transform: translateX(0);
+}
+
+.overlay-right {
+ right: 0;
+ transform: translateX(0);
+}
+
+.container.right-panel-active .overlay-right {
+ transform: translateX(20%);
+}
+
+.social-container {
+ margin: 20px 0;
+}
+
+.social-container a {
+ border: 1px solid #dddddd;
+ border-radius: 50%;
+ display: inline-flex;
+ justify-content: center;
+ align-items: center;
+ margin: 0 5px;
+ height: 40px;
+ width: 40px;
+}
+
+footer {
+ background-color: #222;
+ color: #fff;
+ font-size: 14px;
+ bottom: 0;
+ position: fixed;
+ left: 0;
+ right: 0;
+ text-align: center;
+ z-index: 999;
+}
+
+footer p {
+ margin: 10px 0;
+}
+
+footer i {
+ color: red;
+}
+
+footer a {
+ color: #3c97bf;
+ text-decoration: none;
+}
diff --git a/src/scss/styles.scss b/src/scss/styles.scss
index 8f5285f..4a12dad 100644
--- a/src/scss/styles.scss
+++ b/src/scss/styles.scss
@@ -1,20 +1,20 @@
// Imports
// Resets and base styling
-@use './base/reset';
-@use './base/type';
-@use './base/main';
-
+@use "./base/reset";
+@use "./base/type";
+@use "./base/main";
// Components
-@use './components/header';
-@use './components/footer';
+@use "./components/header";
+@use "./components/footer";
//page specific styling
-@use './page//home';
+@use "./page//home";
+@use "./page//login";
// Utilities
-@use './utilities/utility-classes';
+@use "./utilities/utility-classes";
// Google Fonts - Import
-@import url('https://fonts.googleapis.com/css?family=Alatsi|Roboto:400,400i,700,700i&display=swap');
\ No newline at end of file
+@import url("https://fonts.googleapis.com/css?family=Alatsi|Roboto:400,400i,700,700i&display=swap");