Merge pull request #4 from kjannette/style2
more style, mostly of w3 compliance
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import { Routes, Route, Link, Navigate } from "react-router-dom";
|
import { Routes, Route, Navigate } from "react-router-dom";
|
||||||
import { useAuth } from "./contexts/AuthContext";
|
import { useAuth } from "./contexts/AuthContext";
|
||||||
|
import Navbar from "./components/Navbar";
|
||||||
import Login from "./pages/Login";
|
import Login from "./pages/Login";
|
||||||
import Signup from "./pages/Signup";
|
import Signup from "./pages/Signup";
|
||||||
import Addresses from "./pages/Addresses";
|
import Addresses from "./pages/Addresses";
|
||||||
@@ -7,9 +8,8 @@ import Alerts from "./pages/Alerts";
|
|||||||
import AlertHistory from "./pages/AlertHistory";
|
import AlertHistory from "./pages/AlertHistory";
|
||||||
|
|
||||||
export default function App() {
|
export default function App() {
|
||||||
const { currentUser, logout } = useAuth();
|
const { currentUser } = useAuth();
|
||||||
|
|
||||||
// Show login/signup routes if not authenticated
|
|
||||||
if (!currentUser) {
|
if (!currentUser) {
|
||||||
return (
|
return (
|
||||||
<Routes>
|
<Routes>
|
||||||
@@ -20,51 +20,9 @@ export default function App() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show main app if authenticated
|
|
||||||
return (
|
return (
|
||||||
<div style={{ padding: "1rem" }}>
|
<div>
|
||||||
<nav
|
<Navbar />
|
||||||
style={{
|
|
||||||
marginBottom: "1rem",
|
|
||||||
display: "flex",
|
|
||||||
justifyContent: "space-between",
|
|
||||||
alignItems: "center",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div>
|
|
||||||
<Link to="/addresses">Addresses</Link>
|
|
||||||
{" | "}
|
|
||||||
<Link to="/alerts">Alerts</Link>
|
|
||||||
{" | "}
|
|
||||||
<Link to="/history">History</Link>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
display: "flex",
|
|
||||||
alignItems: "center",
|
|
||||||
gap: "1rem",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<span style={{ fontSize: "0.9rem", color: "#999" }}>
|
|
||||||
{currentUser.email}
|
|
||||||
</span>
|
|
||||||
<button
|
|
||||||
onClick={logout}
|
|
||||||
style={{
|
|
||||||
padding: "0.5rem 1rem",
|
|
||||||
fontSize: "0.9rem",
|
|
||||||
backgroundColor: "#333",
|
|
||||||
color: "white",
|
|
||||||
border: "1px solid #555",
|
|
||||||
borderRadius: "4px",
|
|
||||||
cursor: "pointer",
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
Logout
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
|
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/" element={<Addresses />} />
|
<Route path="/" element={<Addresses />} />
|
||||||
<Route path="/addresses" element={<Addresses />} />
|
<Route path="/addresses" element={<Addresses />} />
|
||||||
|
|||||||
85
frontend/src/components/Navbar.jsx
Normal file
85
frontend/src/components/Navbar.jsx
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
import { Link, useLocation } from "react-router-dom";
|
||||||
|
import { useAuth } from "../contexts/AuthContext";
|
||||||
|
|
||||||
|
const navLinks = [
|
||||||
|
{ to: "/addresses", label: "Addresses" },
|
||||||
|
{ to: "/alerts", label: "Configure Alerts" },
|
||||||
|
{ to: "/history", label: "Alert History" },
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function Navbar() {
|
||||||
|
const { currentUser, logout } = useAuth();
|
||||||
|
const location = useLocation();
|
||||||
|
|
||||||
|
if (!currentUser) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<nav style={{
|
||||||
|
display: "flex",
|
||||||
|
justifyContent: "space-between",
|
||||||
|
alignItems: "center",
|
||||||
|
padding: "1rem 2rem",
|
||||||
|
marginBottom: "1.5rem",
|
||||||
|
backgroundColor: "#1a1a1a",
|
||||||
|
borderBottom: "1px solid #333",
|
||||||
|
}}>
|
||||||
|
<div style={{ display: "flex", alignItems: "center", gap: "0.5rem" }}>
|
||||||
|
<span style={{
|
||||||
|
fontWeight: 700,
|
||||||
|
fontSize: "1.1rem",
|
||||||
|
color: "#fff",
|
||||||
|
marginRight: "2rem",
|
||||||
|
letterSpacing: "0.5px",
|
||||||
|
}}>
|
||||||
|
Koin Ping
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div style={{ display: "flex", gap: "0.25rem" }}>
|
||||||
|
{navLinks.map(({ to, label }) => {
|
||||||
|
const isActive = location.pathname === to;
|
||||||
|
return (
|
||||||
|
<Link
|
||||||
|
key={to}
|
||||||
|
to={to}
|
||||||
|
style={{
|
||||||
|
padding: "0.5rem 1.25rem",
|
||||||
|
borderRadius: "6px",
|
||||||
|
textDecoration: "none",
|
||||||
|
fontSize: "1.425rem",
|
||||||
|
fontWeight: isActive ? 600 : 200,
|
||||||
|
color: isActive ? "#fff" : "#999",
|
||||||
|
backgroundColor: isActive ? "#333" : "transparent",
|
||||||
|
transition: "all 0.15s ease",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{label}
|
||||||
|
</Link>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style={{ display: "flex", alignItems: "center", gap: "1.25rem" }}>
|
||||||
|
<span style={{ fontSize: "1.275rem", color: "#777" }}>
|
||||||
|
{currentUser.email}
|
||||||
|
</span>
|
||||||
|
<button
|
||||||
|
onClick={logout}
|
||||||
|
style={{
|
||||||
|
padding: "0.4rem 1rem",
|
||||||
|
fontSize: "1.275rem",
|
||||||
|
fontWeight: 400,
|
||||||
|
backgroundColor: "transparent",
|
||||||
|
color: "#999",
|
||||||
|
border: "1px solid #444",
|
||||||
|
borderRadius: "6px",
|
||||||
|
cursor: "pointer",
|
||||||
|
transition: "all 0.15s ease",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
Logout
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
);
|
||||||
|
}
|
||||||
33
frontend/src/index.css
Normal file
33
frontend/src/index.css
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
@import url('https://fonts.googleapis.com/css2?family=Nunito:ital,wght@0,200..1000;1,200..1000&display=swap');
|
||||||
|
|
||||||
|
*,
|
||||||
|
*::before,
|
||||||
|
*::after {
|
||||||
|
box-sizing: border-box;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: 'Nunito', sans-serif;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
font-weight: 200;
|
||||||
|
line-height: 1.6;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
font-family: 'Nunito', sans-serif;
|
||||||
|
font-weight: 200;
|
||||||
|
}
|
||||||
|
|
||||||
|
input, select, textarea, button {
|
||||||
|
font-family: 'Nunito', sans-serif;
|
||||||
|
font-size: 1rem;
|
||||||
|
font-weight: 200;
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ import ReactDOM from "react-dom/client";
|
|||||||
import { BrowserRouter } from "react-router-dom";
|
import { BrowserRouter } from "react-router-dom";
|
||||||
import { AuthProvider } from "./contexts/AuthContext";
|
import { AuthProvider } from "./contexts/AuthContext";
|
||||||
import App from "./App";
|
import App from "./App";
|
||||||
|
import "./index.css";
|
||||||
|
|
||||||
ReactDOM.createRoot(document.getElementById("root")).render(
|
ReactDOM.createRoot(document.getElementById("root")).render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ export default function Addresses() {
|
|||||||
{loading && <p>Loading addresses...</p>}
|
{loading && <p>Loading addresses...</p>}
|
||||||
{error && <p style={{ color: "red" }}>Error: {error}</p>}
|
{error && <p style={{ color: "red" }}>Error: {error}</p>}
|
||||||
{!loading && !error && addresses.length === 0 && (
|
{!loading && !error && addresses.length === 0 && (
|
||||||
<p style={{ color: "#666" }}>
|
<p style={{ color: "#808080" }}>
|
||||||
No addresses tracked yet. Add one above to get started.
|
No addresses tracked yet. Add one above to get started.
|
||||||
</p>
|
</p>
|
||||||
)}
|
)}
|
||||||
@@ -63,8 +63,9 @@ export default function Addresses() {
|
|||||||
style={{
|
style={{
|
||||||
padding: "1rem",
|
padding: "1rem",
|
||||||
marginBottom: "0.5rem",
|
marginBottom: "0.5rem",
|
||||||
border: "1px solid #ddd",
|
border: "1px solid #444",
|
||||||
borderRadius: "4px",
|
borderRadius: "4px",
|
||||||
|
backgroundColor: "#333",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
@@ -78,7 +79,8 @@ export default function Addresses() {
|
|||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
fontFamily: "monospace",
|
fontFamily: "monospace",
|
||||||
fontSize: "0.9rem",
|
fontSize: "1.035rem",
|
||||||
|
color: "#b3b3b3",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{addr.address}
|
{addr.address}
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ export default function AlertHistory() {
|
|||||||
<h1>Recent Alerts</h1>
|
<h1>Recent Alerts</h1>
|
||||||
|
|
||||||
{alertEvents.length === 0 ? (
|
{alertEvents.length === 0 ? (
|
||||||
<p style={{ color: "#666" }}>No alerts yet</p>
|
<p style={{ color: "#808080" }}>No alerts yet</p>
|
||||||
) : (
|
) : (
|
||||||
<ul style={{ listStyle: "none", padding: 0 }}>
|
<ul style={{ listStyle: "none", padding: 0 }}>
|
||||||
{alertEvents.map((event) => (
|
{alertEvents.map((event) => (
|
||||||
@@ -48,8 +48,9 @@ export default function AlertHistory() {
|
|||||||
style={{
|
style={{
|
||||||
padding: "1rem",
|
padding: "1rem",
|
||||||
marginBottom: "0.75rem",
|
marginBottom: "0.75rem",
|
||||||
border: "1px solid #ddd",
|
border: "1px solid #444",
|
||||||
borderRadius: "4px",
|
borderRadius: "4px",
|
||||||
|
backgroundColor: "#333",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div style={{ marginBottom: "0.5rem" }}>
|
<div style={{ marginBottom: "0.5rem" }}>
|
||||||
@@ -58,15 +59,15 @@ export default function AlertHistory() {
|
|||||||
{event.address_label && (
|
{event.address_label && (
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
fontSize: "0.9rem",
|
fontSize: "1.035rem",
|
||||||
color: "#666",
|
color: "#808080",
|
||||||
marginBottom: "0.25rem",
|
marginBottom: "0.25rem",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Address: {event.address_label}
|
Address: {event.address_label}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<small style={{ color: "#999" }}>
|
<small style={{ color: "#b3b3b3" }}>
|
||||||
{formatTimestamp(event.timestamp)}
|
{formatTimestamp(event.timestamp)}
|
||||||
</small>
|
</small>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
@@ -250,15 +250,15 @@ export default function Alerts() {
|
|||||||
style={{
|
style={{
|
||||||
padding: "1rem",
|
padding: "1rem",
|
||||||
marginBottom: "2rem",
|
marginBottom: "2rem",
|
||||||
backgroundColor: "#2a2a2a",
|
backgroundColor: "#333",
|
||||||
borderRadius: "4px",
|
borderRadius: "4px",
|
||||||
border: "1px solid #444",
|
border: "1px solid #444",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
fontSize: "0.9rem",
|
fontSize: "1.035rem",
|
||||||
color: "#999",
|
color: "#b3b3b3",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Managing alerts for:
|
Managing alerts for:
|
||||||
@@ -274,8 +274,8 @@ export default function Alerts() {
|
|||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
fontFamily: "monospace",
|
fontFamily: "monospace",
|
||||||
fontSize: "0.9rem",
|
fontSize: "1.035rem",
|
||||||
color: "#999",
|
color: "#b3b3b3",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{selectedAddress.address}
|
{selectedAddress.address}
|
||||||
@@ -316,7 +316,7 @@ export default function Alerts() {
|
|||||||
marginBottom: "0.5rem",
|
marginBottom: "0.5rem",
|
||||||
border: "1px solid #444",
|
border: "1px solid #444",
|
||||||
borderRadius: "4px",
|
borderRadius: "4px",
|
||||||
backgroundColor: "#2a2a2a",
|
backgroundColor: "#333",
|
||||||
opacity: alert.enabled
|
opacity: alert.enabled
|
||||||
? 1
|
? 1
|
||||||
: 0.6,
|
: 0.6,
|
||||||
@@ -348,8 +348,8 @@ export default function Alerts() {
|
|||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
fontSize:
|
fontSize:
|
||||||
"0.9rem",
|
"1.035rem",
|
||||||
color: "#999",
|
color: "#b3b3b3",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Threshold:{" "}
|
Threshold:{" "}
|
||||||
@@ -362,8 +362,8 @@ export default function Alerts() {
|
|||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
fontSize:
|
fontSize:
|
||||||
"0.85rem",
|
"0.978rem",
|
||||||
color: "#666",
|
color: "#808080",
|
||||||
marginTop:
|
marginTop:
|
||||||
"0.25rem",
|
"0.25rem",
|
||||||
}}
|
}}
|
||||||
@@ -451,7 +451,7 @@ export default function Alerts() {
|
|||||||
style={{
|
style={{
|
||||||
marginBottom: "2rem",
|
marginBottom: "2rem",
|
||||||
padding: "1rem",
|
padding: "1rem",
|
||||||
backgroundColor: "#f5f5f5",
|
backgroundColor: "#333",
|
||||||
borderRadius: "4px",
|
borderRadius: "4px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -480,8 +480,8 @@ export default function Alerts() {
|
|||||||
</label>
|
</label>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
fontSize: "0.85rem",
|
fontSize: "0.978rem",
|
||||||
color: "#666",
|
color: "#808080",
|
||||||
marginTop: "0.5rem",
|
marginTop: "0.5rem",
|
||||||
marginLeft: "26px",
|
marginLeft: "26px",
|
||||||
}}
|
}}
|
||||||
@@ -524,8 +524,8 @@ export default function Alerts() {
|
|||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
fontSize: "0.85rem",
|
fontSize: "0.978rem",
|
||||||
color: "#999",
|
color: "#b3b3b3",
|
||||||
marginTop: "0.5rem",
|
marginTop: "0.5rem",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ export default function Login() {
|
|||||||
width: "100%",
|
width: "100%",
|
||||||
padding: "0.5rem",
|
padding: "0.5rem",
|
||||||
fontSize: "1rem",
|
fontSize: "1rem",
|
||||||
backgroundColor: "#1a1a1a",
|
backgroundColor: "#242424",
|
||||||
border: "1px solid #444",
|
border: "1px solid #444",
|
||||||
borderRadius: "4px",
|
borderRadius: "4px",
|
||||||
color: "white",
|
color: "white",
|
||||||
@@ -103,7 +103,7 @@ export default function Login() {
|
|||||||
width: "100%",
|
width: "100%",
|
||||||
padding: "0.5rem",
|
padding: "0.5rem",
|
||||||
fontSize: "1rem",
|
fontSize: "1rem",
|
||||||
backgroundColor: "#1a1a1a",
|
backgroundColor: "#242424",
|
||||||
border: "1px solid #444",
|
border: "1px solid #444",
|
||||||
borderRadius: "4px",
|
borderRadius: "4px",
|
||||||
color: "white",
|
color: "white",
|
||||||
@@ -131,7 +131,7 @@ export default function Login() {
|
|||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div style={{ marginTop: "1.5rem", textAlign: "center" }}>
|
<div style={{ marginTop: "1.5rem", textAlign: "center" }}>
|
||||||
<p style={{ color: "#999" }}>
|
<p style={{ color: "#b3b3b3" }}>
|
||||||
Don't have an account?{" "}
|
Don't have an account?{" "}
|
||||||
<Link
|
<Link
|
||||||
to="/signup"
|
to="/signup"
|
||||||
|
|||||||
@@ -101,7 +101,7 @@ export default function Signup() {
|
|||||||
width: "100%",
|
width: "100%",
|
||||||
padding: "0.5rem",
|
padding: "0.5rem",
|
||||||
fontSize: "1rem",
|
fontSize: "1rem",
|
||||||
backgroundColor: "#1a1a1a",
|
backgroundColor: "#242424",
|
||||||
border: "1px solid #444",
|
border: "1px solid #444",
|
||||||
borderRadius: "4px",
|
borderRadius: "4px",
|
||||||
color: "white",
|
color: "white",
|
||||||
@@ -123,7 +123,7 @@ export default function Signup() {
|
|||||||
width: "100%",
|
width: "100%",
|
||||||
padding: "0.5rem",
|
padding: "0.5rem",
|
||||||
fontSize: "1rem",
|
fontSize: "1rem",
|
||||||
backgroundColor: "#1a1a1a",
|
backgroundColor: "#242424",
|
||||||
border: "1px solid #444",
|
border: "1px solid #444",
|
||||||
borderRadius: "4px",
|
borderRadius: "4px",
|
||||||
color: "white",
|
color: "white",
|
||||||
@@ -145,7 +145,7 @@ export default function Signup() {
|
|||||||
width: "100%",
|
width: "100%",
|
||||||
padding: "0.5rem",
|
padding: "0.5rem",
|
||||||
fontSize: "1rem",
|
fontSize: "1rem",
|
||||||
backgroundColor: "#1a1a1a",
|
backgroundColor: "#242424",
|
||||||
border: "1px solid #444",
|
border: "1px solid #444",
|
||||||
borderRadius: "4px",
|
borderRadius: "4px",
|
||||||
color: "white",
|
color: "white",
|
||||||
@@ -173,7 +173,7 @@ export default function Signup() {
|
|||||||
</form>
|
</form>
|
||||||
|
|
||||||
<div style={{ marginTop: "1.5rem", textAlign: "center" }}>
|
<div style={{ marginTop: "1.5rem", textAlign: "center" }}>
|
||||||
<p style={{ color: "#999" }}>
|
<p style={{ color: "#b3b3b3" }}>
|
||||||
Already have an account?{" "}
|
Already have an account?{" "}
|
||||||
<Link
|
<Link
|
||||||
to="/login"
|
to="/login"
|
||||||
|
|||||||
Reference in New Issue
Block a user