aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorParker <contact@pkrm.dev>2024-11-12 16:37:28 -0600
committerParker <contact@pkrm.dev>2024-11-12 16:37:28 -0600
commit3b2258877fcbd211314b153c56273e3a597ad08b (patch)
tree28fddd745f436ab70a9f29ad486d5a6d38b2ebbb
parent41a21ee0b597d971169d5ce4e19f86a1248dbf96 (diff)
Begin navbar
-rw-r--r--app/src/components/Dashboard.tsx159
-rw-r--r--app/src/components/Login.tsx76
-rw-r--r--app/src/components/Navbar.tsx11
-rw-r--r--app/src/styles/Navbar.module.css18
4 files changed, 153 insertions, 111 deletions
diff --git a/app/src/components/Dashboard.tsx b/app/src/components/Dashboard.tsx
index 51d3020..e16c44e 100644
--- a/app/src/components/Dashboard.tsx
+++ b/app/src/components/Dashboard.tsx
@@ -4,6 +4,7 @@ import styles from '../styles/Dashboard.module.css';
import { useNavigate } from 'react-router-dom';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faTrash } from '@fortawesome/free-solid-svg-icons';
+import Navbar from './Navbar';
function Dashboard() {
document.title = 'LinkLogger | Dashboard';
@@ -44,10 +45,15 @@ function Dashboard() {
}
})
- // Catch 404 error = user has no links
-
- .catch(() => {
- navigate('/login');
+ .catch((error: unknown) => {
+ if (axios.isAxiosError(error)) {
+ if (error.response?.status === 404) {
+ // Create a message alerting the user there are no links
+ navigate('/login');
+ } else {
+ navigate('/login');
+ }
+ }
});
}, []);
@@ -109,79 +115,82 @@ function Dashboard() {
};
return (
- <table id={styles.mainTable}>
- <thead>
- <tr style={{ border: '2px solid #ccc' }}>
- <th>Link</th>
- <th>Visits</th>
- <th>Redirect</th>
- <th>Expire Date</th>
- </tr>
- </thead>
- <tbody>
- {/* For every link and its logs */}
- {links.map((link) => (
- <React.Fragment key={link.link}>
- <tr className={styles.linkTableRow}>
- <td>
- <button
- onClick={() => toggleLogRow(link.link)}
- className={styles.linkButton}
- >
- {link.link}
- </button>
- </td>
- <td>
- {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>
+ <>
+ <Navbar />
+ <table id={styles.mainTable}>
+ <thead>
+ <tr style={{ border: '2px solid #ccc' }}>
+ <th>Link</th>
+ <th>Visits</th>
+ <th>Redirect</th>
+ <th>Expire Date</th>
+ </tr>
+ </thead>
+ <tbody>
+ {/* For every link and its logs */}
+ {links.map((link) => (
+ <React.Fragment key={link.link}>
+ <tr className={styles.linkTableRow}>
+ <td>
+ <button
+ onClick={() => toggleLogRow(link.link)}
+ className={styles.linkButton}
+ >
+ {link.link}
+ </button>
+ </td>
+ <td>
+ {logs.filter((log) => log.link === link.link).length || 0}
</td>
+ <td>{link.redirect_link}</td>
+ <td>{link.expire_date}</td>
</tr>
- )}
- </React.Fragment>
- ))}
- </tbody>
- </table>
+
+ {/* 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>
+ </tr>
+ )}
+ </React.Fragment>
+ ))}
+ </tbody>
+ </table>
+ </>
);
}
diff --git a/app/src/components/Login.tsx b/app/src/components/Login.tsx
index 2a81295..807face 100644
--- a/app/src/components/Login.tsx
+++ b/app/src/components/Login.tsx
@@ -3,6 +3,7 @@ import styles from '../styles/Login.module.css';
import { Link } from 'react-router-dom';
import { useNavigate } from 'react-router-dom';
import axios from 'axios';
+import Navbar from './Navbar';
function Login() {
document.title = 'LinkLogger | Login';
@@ -48,43 +49,46 @@ function Login() {
};
return (
- <div id={styles.container}>
- <p id={styles.loginText}>Log In</p>
- <p id={styles.error} className={error ? 'visible' : 'hidden'}>
- {error}
- </p>
- <div>
- <header>
- <hr></hr>
- <form onSubmit={handleSubmit}>
- <input
- type="text"
- placeholder="username"
- value={username}
- onChange={(e) => setUsername(e.target.value)}
- required
- />
- <input
- type="password"
- placeholder="password"
- value={password}
- onChange={(e) => setPassword(e.target.value)}
- required
- />
- <button type="submit" disabled={isSubmitting}>
- {isSubmitting ? 'Submitting...' : 'Submit'}
- </button>
- </form>
- <hr></hr>
- <p id={styles.bottomText}>
- Don't have an account?{' '}
- <Link to="/signup" className={styles.link}>
- Create one now
- </Link>
- </p>
- </header>
+ <>
+ <Navbar />
+ <div id={styles.container}>
+ <p id={styles.loginText}>Log In</p>
+ <p id={styles.error} className={error ? 'visible' : 'hidden'}>
+ {error}
+ </p>
+ <div>
+ <header>
+ <hr></hr>
+ <form onSubmit={handleSubmit}>
+ <input
+ type="text"
+ placeholder="username"
+ value={username}
+ onChange={(e) => setUsername(e.target.value)}
+ required
+ />
+ <input
+ type="password"
+ placeholder="password"
+ value={password}
+ onChange={(e) => setPassword(e.target.value)}
+ required
+ />
+ <button type="submit" disabled={isSubmitting}>
+ {isSubmitting ? 'Submitting...' : 'Submit'}
+ </button>
+ </form>
+ <hr></hr>
+ <p id={styles.bottomText}>
+ Don't have an account?{' '}
+ <Link to="/signup" className={styles.link}>
+ Create one now
+ </Link>
+ </p>
+ </header>
+ </div>
</div>
- </div>
+ </>
);
}
diff --git a/app/src/components/Navbar.tsx b/app/src/components/Navbar.tsx
new file mode 100644
index 0000000..7ffb514
--- /dev/null
+++ b/app/src/components/Navbar.tsx
@@ -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;
diff --git a/app/src/styles/Navbar.module.css b/app/src/styles/Navbar.module.css
new file mode 100644
index 0000000..217e4b1
--- /dev/null
+++ b/app/src/styles/Navbar.module.css
@@ -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;
+} \ No newline at end of file