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 (
+ <>
+
+ >
+ );
+};
+
+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 (
+
+

+
+
+
+ );
+});
+
+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 (
-
- } />
- } />
- } />
- } />
-
+
+
+
+
+ : } />
+ : } />
+ : } />
+ } />
+ } />
+
+
+
+
);
};