Begin navbar

This commit is contained in:
Parker M. 2024-11-12 16:37:28 -06:00
parent 41a21ee0b5
commit 3b2258877f
Signed by: parker
GPG Key ID: 505ED36FC12B5D5E
4 changed files with 153 additions and 111 deletions

View File

@ -4,6 +4,7 @@ import styles from '../styles/Dashboard.module.css';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faTrash } from '@fortawesome/free-solid-svg-icons'; import { faTrash } from '@fortawesome/free-solid-svg-icons';
import Navbar from './Navbar';
function Dashboard() { function Dashboard() {
document.title = 'LinkLogger | Dashboard'; document.title = 'LinkLogger | Dashboard';
@ -44,10 +45,15 @@ function Dashboard() {
} }
}) })
// Catch 404 error = user has no links .catch((error: unknown) => {
if (axios.isAxiosError(error)) {
.catch(() => { if (error.response?.status === 404) {
navigate('/login'); // Create a message alerting the user there are no links
navigate('/login');
} else {
navigate('/login');
}
}
}); });
}, []); }, []);
@ -109,79 +115,82 @@ function Dashboard() {
}; };
return ( return (
<table id={styles.mainTable}> <>
<thead> <Navbar />
<tr style={{ border: '2px solid #ccc' }}> <table id={styles.mainTable}>
<th>Link</th> <thead>
<th>Visits</th> <tr style={{ border: '2px solid #ccc' }}>
<th>Redirect</th> <th>Link</th>
<th>Expire Date</th> <th>Visits</th>
</tr> <th>Redirect</th>
</thead> <th>Expire Date</th>
<tbody> </tr>
{/* For every link and its logs */} </thead>
{links.map((link) => ( <tbody>
<React.Fragment key={link.link}> {/* For every link and its logs */}
<tr className={styles.linkTableRow}> {links.map((link) => (
<td> <React.Fragment key={link.link}>
<button <tr className={styles.linkTableRow}>
onClick={() => toggleLogRow(link.link)} <td>
className={styles.linkButton} <button
> onClick={() => toggleLogRow(link.link)}
{link.link} className={styles.linkButton}
</button> >
</td> {link.link}
<td> </button>
{logs.filter((log) => log.link === link.link).length || 0}
</td>
<td>{link.redirect_link}</td>
<td>{link.expire_date}</td>
</tr>
{/* Conditionally render logs for this link */}
{visibleLog === link.link && (
<tr className={styles.logTableRow}>
<td colSpan={6}>
<table>
<thead>
<tr>
<th>ID</th>
<th>Timestamp</th>
<th>IP</th>
<th>Location</th>
<th colSpan={2}>ISP</th>
</tr>
</thead>
<tbody>
{/* Render logs only if visibleLog matches the link */}
{logs
.filter((log) => log.link === link.link)
.map((log, index, filteredLogs) => (
<tr key={log.id}>
<td>{filteredLogs.length - index}</td>
<td>{log.timestamp}</td>
<td>{log.ip}</td>
<td>{log.location}</td>
<td>{log.isp}</td>
<td>
<FontAwesomeIcon
icon={faTrash}
className={styles.trashBin}
id={log.id.toString()}
onClick={deleteLog}
/>
</td>
</tr>
))}
</tbody>
</table>
</td> </td>
<td>
{logs.filter((log) => log.link === link.link).length || 0}
</td>
<td>{link.redirect_link}</td>
<td>{link.expire_date}</td>
</tr> </tr>
)}
</React.Fragment> {/* Conditionally render logs for this link */}
))} {visibleLog === link.link && (
</tbody> <tr className={styles.logTableRow}>
</table> <td colSpan={6}>
<table>
<thead>
<tr>
<th>ID</th>
<th>Timestamp</th>
<th>IP</th>
<th>Location</th>
<th colSpan={2}>ISP</th>
</tr>
</thead>
<tbody>
{/* Render logs only if visibleLog matches the link */}
{logs
.filter((log) => log.link === link.link)
.map((log, index, filteredLogs) => (
<tr key={log.id}>
<td>{filteredLogs.length - index}</td>
<td>{log.timestamp}</td>
<td>{log.ip}</td>
<td>{log.location}</td>
<td>{log.isp}</td>
<td>
<FontAwesomeIcon
icon={faTrash}
className={styles.trashBin}
id={log.id.toString()}
onClick={deleteLog}
/>
</td>
</tr>
))}
</tbody>
</table>
</td>
</tr>
)}
</React.Fragment>
))}
</tbody>
</table>
</>
); );
} }

View File

@ -3,6 +3,7 @@ import styles from '../styles/Login.module.css';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
import axios from 'axios'; import axios from 'axios';
import Navbar from './Navbar';
function Login() { function Login() {
document.title = 'LinkLogger | Login'; document.title = 'LinkLogger | Login';
@ -48,43 +49,46 @@ function Login() {
}; };
return ( return (
<div id={styles.container}> <>
<p id={styles.loginText}>Log In</p> <Navbar />
<p id={styles.error} className={error ? 'visible' : 'hidden'}> <div id={styles.container}>
{error} <p id={styles.loginText}>Log In</p>
</p> <p id={styles.error} className={error ? 'visible' : 'hidden'}>
<div> {error}
<header> </p>
<hr></hr> <div>
<form onSubmit={handleSubmit}> <header>
<input <hr></hr>
type="text" <form onSubmit={handleSubmit}>
placeholder="username" <input
value={username} type="text"
onChange={(e) => setUsername(e.target.value)} placeholder="username"
required value={username}
/> onChange={(e) => setUsername(e.target.value)}
<input required
type="password" />
placeholder="password" <input
value={password} type="password"
onChange={(e) => setPassword(e.target.value)} placeholder="password"
required value={password}
/> onChange={(e) => setPassword(e.target.value)}
<button type="submit" disabled={isSubmitting}> required
{isSubmitting ? 'Submitting...' : 'Submit'} />
</button> <button type="submit" disabled={isSubmitting}>
</form> {isSubmitting ? 'Submitting...' : 'Submit'}
<hr></hr> </button>
<p id={styles.bottomText}> </form>
Don't have an account?{' '} <hr></hr>
<Link to="/signup" className={styles.link}> <p id={styles.bottomText}>
Create one now Don't have an account?{' '}
</Link> <Link to="/signup" className={styles.link}>
</p> Create one now
</header> </Link>
</p>
</header>
</div>
</div> </div>
</div> </>
); );
} }

View File

@ -0,0 +1,11 @@
import styles from '../styles/Navbar.module.css';
function Navbar() {
return (
<nav className={styles.navbar}>
<span>LinkLogger</span>
</nav>
);
}
export default Navbar;

View File

@ -0,0 +1,18 @@
/* Create the nav and center the span */
.navbar {
display: flex;
justify-content: center;
align-items: center;
height: 60px;
background-color: #f8f9fa;
}
/* Create the nav links */
span {
font-size: 35px;
font-weight: 600;
color: #333;
text-decoration: none;
margin-right: 10px;
}