diff --git a/.gitignore b/.gitignore index a547bf3..3a2b7b7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +.env +.env.* + # Logs logs *.log diff --git a/src/App.jsx b/src/App.jsx index ef0bf83..899ddbc 100644 --- a/src/App.jsx +++ b/src/App.jsx @@ -1,12 +1,24 @@ -import React from 'react'; +import React, { useState } from 'react'; import AppRoutes from './routes/AppRoutes'; import CampfireAppBar from './components/AppBar'; +import { useNavigate, useLocation } from 'react-router-dom'; function App() { + const [isLoggedIn, setIsLoggedIn] = useState(false); + const navigate = useNavigate(); + const location = useLocation(); + + const handleLogin = (isLoggedInState) => { + setIsLoggedIn(isLoggedInState); + if (isLoggedInState) { + navigate('/dashboard'); + } + }; + return (
- - + {location.pathname !== '/login' && } +
); diff --git a/src/App.css b/src/assets/css/App.css similarity index 81% rename from src/App.css rename to src/assets/css/App.css index b9d355d..49a0137 100644 --- a/src/App.css +++ b/src/assets/css/App.css @@ -3,6 +3,12 @@ margin: 0 auto; padding: 2rem; text-align: center; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + min-height: 100vh; + caret-color: transparent; } .logo { diff --git a/src/index.css b/src/assets/css/index.css similarity index 76% rename from src/index.css rename to src/assets/css/index.css index 08a3ac9..463fc3c 100644 --- a/src/index.css +++ b/src/assets/css/index.css @@ -25,6 +25,8 @@ a:hover { body { margin: 0; display: flex; + flex-direction: column; + justify-content: center; place-items: center; min-width: 320px; min-height: 100vh; @@ -66,3 +68,26 @@ button:focus-visible { background-color: #f9f9f9; } } + +.page-enter { + opacity: 0; + position: absolute; + top: 0; + left: 0; + width: 100%; +} +.page-enter-active { + opacity: 1; + transition: opacity 300ms; +} +.page-exit { + opacity: 1; + position: absolute; + top: 0; + left: 0; + width: 100%; +} +.page-exit-active { + opacity: 0; + transition: opacity 300ms; +} \ No newline at end of file diff --git a/src/assets/images/campfire_logs_square_logo.png b/src/assets/images/campfire_logs_square_logo.png new file mode 100644 index 0000000..179f5bd Binary files /dev/null and b/src/assets/images/campfire_logs_square_logo.png differ diff --git a/src/assets/images/campfire_logs_square_logo_no_bg.png b/src/assets/images/campfire_logs_square_logo_no_bg.png new file mode 100644 index 0000000..179f5bd Binary files /dev/null and b/src/assets/images/campfire_logs_square_logo_no_bg.png differ diff --git a/src/components/AppBar.jsx b/src/components/AppBar.jsx index f7438b1..fcd7924 100644 --- a/src/components/AppBar.jsx +++ b/src/components/AppBar.jsx @@ -1,26 +1,46 @@ import React from 'react'; import { AppBar, AppBarSection, AppBarSpacer } from '@progress/kendo-react-layout'; import { Button } from '@progress/kendo-react-buttons'; -import { Link } from 'react-router-dom'; +import { Link, useNavigate } from 'react-router-dom'; + +const CampfireAppBar = ({ isLoggedIn, onLogin }) => { + const navigate = useNavigate(); + + const handleLogout = () => { + onLogin(false); + navigate('/login'); + }; -const CampfireAppBar = () => { return ( - - - - - - - - - +
+

Campfire Logs

+ + + + + + + + + + + - + - - - - + + {isLoggedIn ? ( + + ) : ( + + + + )} + + +
); }; diff --git a/src/components/LoginComponent.jsx b/src/components/LoginComponent.jsx new file mode 100644 index 0000000..4df0f4c --- /dev/null +++ b/src/components/LoginComponent.jsx @@ -0,0 +1,55 @@ +import React, { useState } from 'react'; +import { Input } from '@progress/kendo-react-inputs'; +import { Label } from '@progress/kendo-react-labels'; +import { Button } from '@progress/kendo-react-buttons'; +import { Link } from 'react-router-dom'; +import { Notification, NotificationGroup } from '@progress/kendo-react-notification'; + +const LoginComponent = ({ onLogin }) => { + const [username, setUsername] = useState(''); + const [password, setPassword] = useState(''); + const [error, setError] = useState(''); + + const handleSubmit = (event) => { + event.preventDefault(); + + const mockUsername = import.meta.env.VITE_MOCK_USERNAME; + const mockPassword = import.meta.env.VITE_MOCK_PASSWORD; + + if (username === mockUsername && password === mockPassword) { + onLogin(true); + } else { + console.error("Invalid username or password"); + setError("Invalid username or password. Please try again."); + setTimeout(() => { + setError(''); + }, 50000); + } + }; + + return ( + <> +
+
+ + setUsername(e.target.value)} autoComplete="username" /> +
+
+ + setPassword(e.target.value)} autoComplete="current-password" /> +
+ + +
+ + {error && ( setError('')}> + {error} + )} + +
+
+ + ); +}; + +export default LoginComponent; \ No newline at end of file diff --git a/src/main.jsx b/src/main.jsx index d249a6f..683f359 100644 --- a/src/main.jsx +++ b/src/main.jsx @@ -2,7 +2,7 @@ import { StrictMode } from 'react'; import { createRoot } from 'react-dom/client'; import { BrowserRouter } from 'react-router-dom'; import 'campfire-logs-dashboard/dist/css/campfire-logs-dashboard.css'; -import './index.css'; +import './assets/css/index.css'; import App from './App.jsx'; createRoot(document.getElementById('root')).render( diff --git a/src/pages/Dashboard.jsx b/src/pages/Dashboard.jsx index 3a33106..33f57e4 100644 --- a/src/pages/Dashboard.jsx +++ b/src/pages/Dashboard.jsx @@ -1,9 +1,10 @@ import React from 'react'; -const Dashboard = () => { +const Dashboard = React.forwardRef((props, ref) => { return ( -

This is the Dashboard Page

+
+
); -}; +}); export default Dashboard; \ No newline at end of file diff --git a/src/pages/EditorPage.jsx b/src/pages/EditorPage.jsx index 151c9fa..e8e671a 100644 --- a/src/pages/EditorPage.jsx +++ b/src/pages/EditorPage.jsx @@ -1,9 +1,11 @@ import React from 'react'; -const EditorPage = () => { +const EditorPage = React.forwardRef((props, ref) => { return ( -

This is the Editor Page

+
+

This is the Editor Page

+
); -}; +}); export default EditorPage; \ No newline at end of file diff --git a/src/pages/Login.jsx b/src/pages/Login.jsx new file mode 100644 index 0000000..b922d45 --- /dev/null +++ b/src/pages/Login.jsx @@ -0,0 +1,15 @@ +import React from 'react'; +import LoginComponent from '../components/LoginComponent'; +import Logo from '../assets/images/campfire_logs_square_logo.png'; + +const LoginPage = React.forwardRef(({ onLogin }, ref) => { + return ( +
+ Campfire Logs Logo +
+ +
+ ); +}); + +export default LoginPage; \ No newline at end of file diff --git a/src/pages/NotFound.jsx b/src/pages/NotFound.jsx index 9636ea2..0f9732d 100644 --- a/src/pages/NotFound.jsx +++ b/src/pages/NotFound.jsx @@ -1,9 +1,11 @@ import React from 'react'; -const NotFound = () => { +const NotFound = React.forwardRef((props, ref) => { return ( -

404: Page Not Found

+
+

404: Page Not Found

+
); -}; +}); export default NotFound; \ No newline at end of file diff --git a/src/routes/AppRoutes.jsx b/src/routes/AppRoutes.jsx index baff392..4c963a6 100644 --- a/src/routes/AppRoutes.jsx +++ b/src/routes/AppRoutes.jsx @@ -1,18 +1,30 @@ import React from 'react' -import { Routes, Route } from 'react-router-dom'; +import { Routes, Route, Navigate, useLocation } from 'react-router-dom'; +import { CSSTransition, SwitchTransition } from 'react-transition-group'; import Dashboard from '../pages/Dashboard'; import EditorPage from '../pages/EditorPage'; +import LoginPage from '../pages/Login'; import NotFound from '../pages/NotFound'; -const AppRoutes = () => { +const AppRoutes = ({ isLoggedIn, onLogin }) => { + const location = useLocation(); + const nodeRef = React.useRef(null); + return ( - - } /> - } /> - } /> - } /> - + + +
+ + : } /> + : } /> + : } /> + } /> + } /> + +
+
+
); };