mirror of
https://github.com/jaypyles/Scraperr.git
synced 2025-12-17 13:16:10 +00:00
feat: add themeing
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React, { useState } from "react";
|
||||
import React from "react";
|
||||
import {
|
||||
TextField,
|
||||
Table,
|
||||
@@ -7,6 +7,8 @@ import {
|
||||
TableHead,
|
||||
TableRow,
|
||||
Button,
|
||||
Box,
|
||||
Typography,
|
||||
} from "@mui/material";
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
@@ -59,6 +61,18 @@ const JobTable: React.FC<JobTableProps> = ({ jobs }) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
width="fullWidth"
|
||||
bgcolor="background.paper"
|
||||
className="flex justify-center"
|
||||
>
|
||||
<Box
|
||||
maxWidth="lg"
|
||||
minHeight="100vh"
|
||||
bgcolor="background.paper"
|
||||
className="p-4"
|
||||
>
|
||||
<Typography variant="h4">Scrape Jobs</Typography>
|
||||
<Table>
|
||||
<TableHead>
|
||||
<TableRow>
|
||||
@@ -109,7 +123,9 @@ const JobTable: React.FC<JobTableProps> = ({ jobs }) => {
|
||||
</Button>
|
||||
</TableCell>
|
||||
<TableCell>
|
||||
<Button onClick={() => handleNavigate(row.elements, row.url)}>
|
||||
<Button
|
||||
onClick={() => handleNavigate(row.elements, row.url)}
|
||||
>
|
||||
Rerun
|
||||
</Button>
|
||||
</TableCell>
|
||||
@@ -117,6 +133,8 @@ const JobTable: React.FC<JobTableProps> = ({ jobs }) => {
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</Box>
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -13,13 +13,19 @@ import {
|
||||
IconButton,
|
||||
Typography,
|
||||
Button,
|
||||
Switch,
|
||||
} from "@mui/material";
|
||||
import HomeIcon from "@mui/icons-material/Home";
|
||||
import HttpIcon from "@mui/icons-material/Http";
|
||||
import MenuIcon from "@mui/icons-material/Menu";
|
||||
import { useRouter } from "next/router";
|
||||
|
||||
const NavDrawer: React.FC = () => {
|
||||
interface NavDrawerProps {
|
||||
toggleTheme: () => void;
|
||||
isDarkMode: boolean;
|
||||
}
|
||||
|
||||
const NavDrawer: React.FC<NavDrawerProps> = ({ toggleTheme, isDarkMode }) => {
|
||||
const router = useRouter();
|
||||
const { login, logout, user, isAuthenticated } = useAuth();
|
||||
const [open, setOpen] = useState<boolean>(false);
|
||||
@@ -70,6 +76,7 @@ const NavDrawer: React.FC = () => {
|
||||
<>
|
||||
<AppBar position="static">
|
||||
<Toolbar className="flex flex-row justify-between items-center">
|
||||
<div className="flex flex-row">
|
||||
<IconButton
|
||||
edge="start"
|
||||
color="inherit"
|
||||
@@ -78,12 +85,14 @@ const NavDrawer: React.FC = () => {
|
||||
>
|
||||
<MenuIcon />
|
||||
</IconButton>
|
||||
<Switch checked={isDarkMode} onChange={toggleTheme} />
|
||||
</div>
|
||||
{isAuthenticated ? (
|
||||
<div className="flex flex-row items-center">
|
||||
<Typography variant="body1" sx={{ marginRight: 2 }}>
|
||||
Welcome, {user?.full_name}
|
||||
</Typography>
|
||||
<Button color="inherit" onClick={logout}>
|
||||
<Button color="inherit" onClick={logout} className="!color-white">
|
||||
Logout
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
@@ -1,21 +1,143 @@
|
||||
import "bootstrap/dist/css/bootstrap.min.css";
|
||||
import "../styles/globals.css";
|
||||
|
||||
import React from "react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import type { AppProps } from "next/app";
|
||||
import Head from "next/head";
|
||||
import { SessionProvider } from "next-auth/react";
|
||||
import { ThemeProvider, createTheme, CssBaseline } from "@mui/material";
|
||||
import NavDrawer from "../components/NavDrawer";
|
||||
|
||||
const lightTheme = createTheme({
|
||||
palette: {
|
||||
mode: "light",
|
||||
primary: {
|
||||
main: "#1976d2",
|
||||
},
|
||||
secondary: {
|
||||
main: "#dc004e",
|
||||
},
|
||||
background: {
|
||||
default: "#f4f6f8",
|
||||
paper: "#ffffff",
|
||||
},
|
||||
text: {
|
||||
primary: "#000000",
|
||||
secondary: "#333333",
|
||||
},
|
||||
},
|
||||
typography: {
|
||||
fontFamily: "Roboto, sans-serif",
|
||||
h1: {
|
||||
fontWeight: 500,
|
||||
},
|
||||
h2: {
|
||||
fontWeight: 500,
|
||||
},
|
||||
},
|
||||
components: {
|
||||
MuiButton: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
borderRadius: 8,
|
||||
color: "black",
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiPaper: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
padding: 16,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const darkTheme = createTheme({
|
||||
palette: {
|
||||
mode: "dark",
|
||||
primary: {
|
||||
main: "#90caf9",
|
||||
},
|
||||
secondary: {
|
||||
main: "#f48fb1",
|
||||
},
|
||||
background: {
|
||||
default: "#121212",
|
||||
paper: "#1e1e1e",
|
||||
},
|
||||
text: {
|
||||
primary: "#ffffff",
|
||||
secondary: "#bbbbbb",
|
||||
},
|
||||
},
|
||||
typography: {
|
||||
fontFamily: "Roboto, sans-serif",
|
||||
h1: {
|
||||
fontWeight: 500,
|
||||
color: "white",
|
||||
},
|
||||
h2: {
|
||||
fontWeight: 500,
|
||||
color: "white",
|
||||
},
|
||||
h4: {
|
||||
fontWeight: 500,
|
||||
color: "white",
|
||||
},
|
||||
},
|
||||
components: {
|
||||
MuiButton: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
borderRadius: 8,
|
||||
color: "white",
|
||||
},
|
||||
},
|
||||
},
|
||||
MuiPaper: {
|
||||
styleOverrides: {
|
||||
root: {
|
||||
padding: 16,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
const App: React.FC<AppProps> = ({ Component, pageProps }) => {
|
||||
const [isDarkMode, setIsDarkMode] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
const savedTheme = localStorage.getItem("theme");
|
||||
if (savedTheme) {
|
||||
setIsDarkMode(savedTheme === "dark");
|
||||
} else {
|
||||
const prefersDarkMode = window.matchMedia(
|
||||
"(prefers-color-scheme: dark)",
|
||||
).matches;
|
||||
setIsDarkMode(prefersDarkMode);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const toggleTheme = () => {
|
||||
const newTheme = !isDarkMode;
|
||||
setIsDarkMode(newTheme);
|
||||
localStorage.setItem("theme", newTheme ? "dark" : "light");
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>Webapp Template</title>
|
||||
</Head>
|
||||
<SessionProvider session={pageProps.session}>
|
||||
<NavDrawer />
|
||||
<ThemeProvider theme={isDarkMode ? darkTheme : lightTheme}>
|
||||
<CssBaseline />
|
||||
<NavDrawer isDarkMode={isDarkMode} toggleTheme={toggleTheme} />
|
||||
<Component {...pageProps} />
|
||||
</ThemeProvider>
|
||||
</SessionProvider>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -16,6 +16,7 @@ import {
|
||||
import AddIcon from "@mui/icons-material/Add";
|
||||
import { useAuth } from "../hooks/useAuth";
|
||||
import { useRouter } from "next/router";
|
||||
import CircularProgress from "@mui/material/CircularProgress";
|
||||
|
||||
interface Element {
|
||||
name: string;
|
||||
@@ -58,6 +59,7 @@ const Home = () => {
|
||||
xpath: "",
|
||||
url: "",
|
||||
});
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const resultsRef = useRef<HTMLTableElement | null>(null);
|
||||
|
||||
@@ -99,6 +101,7 @@ const Home = () => {
|
||||
|
||||
setIsValidUrl(true);
|
||||
setUrlError(null);
|
||||
setLoading(true);
|
||||
|
||||
fetch("/api/submit-scrape-job", {
|
||||
method: "POST",
|
||||
@@ -111,11 +114,13 @@ const Home = () => {
|
||||
}),
|
||||
})
|
||||
.then((response) => response.json())
|
||||
.then((data) => setResults(data));
|
||||
.then((data) => setResults(data))
|
||||
.finally(() => setLoading(false));
|
||||
};
|
||||
|
||||
return (
|
||||
<Box
|
||||
bgcolor="background.paper"
|
||||
display="flex"
|
||||
flexDirection="column"
|
||||
justifyContent="center"
|
||||
@@ -141,14 +146,13 @@ const Home = () => {
|
||||
helperText={!isValidURL ? urlError : ""}
|
||||
/>
|
||||
<Button
|
||||
className="!text-black"
|
||||
variant="contained"
|
||||
color="primary"
|
||||
size="small"
|
||||
onClick={handleSubmit}
|
||||
disabled={!(rows.length > 0)}
|
||||
disabled={!(rows.length > 0) || loading}
|
||||
>
|
||||
Submit
|
||||
{loading ? <CircularProgress size={24} /> : "Submit"}
|
||||
</Button>
|
||||
</div>
|
||||
<Box display="flex" gap={2} marginBottom={2} className="items-center">
|
||||
|
||||
Reference in New Issue
Block a user