Initial
This commit is contained in:
25
frontend/src/App.js
Normal file
25
frontend/src/App.js
Normal file
@ -0,0 +1,25 @@
|
||||
import { ThemeProvider, createTheme } from "@mui/material/styles";
|
||||
import Container from "@mui/material/Container";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import { Home } from "./pages/Home";
|
||||
|
||||
const darkTheme = createTheme({
|
||||
palette: {
|
||||
mode: "light",
|
||||
},
|
||||
});
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<ThemeProvider theme={darkTheme}>
|
||||
<Container fixed>
|
||||
<Typography variant="h2" gutterBottom>
|
||||
Komponiranje frontend demo
|
||||
</Typography>
|
||||
<Home />
|
||||
</Container>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
||||
|
||||
export default App;
|
||||
33
frontend/src/api/common.js
Normal file
33
frontend/src/api/common.js
Normal file
@ -0,0 +1,33 @@
|
||||
import axios from "axios";
|
||||
import { API_URL } from "../const";
|
||||
|
||||
export class ApiBase {}
|
||||
|
||||
const commonHeaders = {
|
||||
"Content-Type": "application/json",
|
||||
Accept: "application/json",
|
||||
"Access-Control-Allow-Origin": "*",
|
||||
"Access-Control-Max-Age": 60,
|
||||
"x-timezone": Intl.DateTimeFormat().resolvedOptions().timeZone,
|
||||
};
|
||||
|
||||
export const axiosUnauthorizedInstance = axios.create({
|
||||
baseURL: API_URL,
|
||||
timeout: 5000,
|
||||
headers: commonHeaders,
|
||||
});
|
||||
|
||||
axiosUnauthorizedInstance.interceptors.response.use(
|
||||
(response) => response,
|
||||
(error) => {
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
export const axiosInstance = axios.create({
|
||||
baseURL: API_URL,
|
||||
timeout: 5000,
|
||||
headers: {
|
||||
...commonHeaders,
|
||||
},
|
||||
});
|
||||
1
frontend/src/api/index.js
Normal file
1
frontend/src/api/index.js
Normal file
@ -0,0 +1 @@
|
||||
export { machinesApi } from "./machines";
|
||||
15
frontend/src/api/machines.js
Normal file
15
frontend/src/api/machines.js
Normal file
@ -0,0 +1,15 @@
|
||||
import { axiosInstance, ApiBase } from "./common";
|
||||
|
||||
class MachinesApi extends ApiBase {
|
||||
list = async () => {
|
||||
return axiosInstance.get(`/machines`, {});
|
||||
};
|
||||
get = async (machineId) => {
|
||||
return axiosInstance.get(`/machines/${machineId}`, {});
|
||||
};
|
||||
listProducts = async (machineId) => {
|
||||
return axiosInstance.get(`/machines/${machineId}/products`, {});
|
||||
};
|
||||
}
|
||||
|
||||
export const machinesApi = new MachinesApi();
|
||||
44
frontend/src/components/Machines.js
Normal file
44
frontend/src/components/Machines.js
Normal file
@ -0,0 +1,44 @@
|
||||
import * as React from "react";
|
||||
import { useState } from "react";
|
||||
|
||||
import List from "@mui/material/List";
|
||||
import ListItem from "@mui/material/ListItem";
|
||||
import ListItemButton from "@mui/material/ListItemButton";
|
||||
import ListItemText from "@mui/material/ListItemText";
|
||||
import Typography from "@mui/material/Typography";
|
||||
import Paper from "@mui/material/Paper";
|
||||
|
||||
function Machines({ machines, onSelect }) {
|
||||
const [selectedId, setSelectedId] = useState(null);
|
||||
|
||||
const handleOnClick = (machineName, machineId) => {
|
||||
onSelect(machineName, machineId);
|
||||
setSelectedId(machineId);
|
||||
};
|
||||
|
||||
const machineItems = machines.map((machine) => {
|
||||
return (
|
||||
<ListItem key={machine.id} disablePadding>
|
||||
<ListItemButton
|
||||
selected={selectedId === machine.id}
|
||||
onClick={(event) => handleOnClick(machine.name, machine.id)}
|
||||
>
|
||||
<ListItemText primary={machine.name} />
|
||||
</ListItemButton>
|
||||
</ListItem>
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<>
|
||||
<Typography variant="h4" gutterBottom>
|
||||
Machines
|
||||
</Typography>
|
||||
<List>
|
||||
<Paper>{machineItems}</Paper>
|
||||
</List>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export { Machines };
|
||||
1
frontend/src/const.js
Normal file
1
frontend/src/const.js
Normal file
@ -0,0 +1 @@
|
||||
export const API_URL = process.env.REACT_APP_BACKEND_API_URL || "http://localhost:10000";
|
||||
13
frontend/src/index.css
Normal file
13
frontend/src/index.css
Normal file
@ -0,0 +1,13 @@
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
|
||||
'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
|
||||
sans-serif;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: source-code-pro, Menlo, Monaco, Consolas, 'Courier New',
|
||||
monospace;
|
||||
}
|
||||
17
frontend/src/index.js
Normal file
17
frontend/src/index.js
Normal file
@ -0,0 +1,17 @@
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom/client';
|
||||
import './index.css';
|
||||
import App from './App';
|
||||
import reportWebVitals from './reportWebVitals';
|
||||
|
||||
const root = ReactDOM.createRoot(document.getElementById('root'));
|
||||
root.render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>
|
||||
);
|
||||
|
||||
// If you want to start measuring performance in your app, pass a function
|
||||
// to log results (for example: reportWebVitals(console.log))
|
||||
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
|
||||
reportWebVitals();
|
||||
35
frontend/src/pages/Home.js
Normal file
35
frontend/src/pages/Home.js
Normal file
@ -0,0 +1,35 @@
|
||||
import * as React from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
|
||||
import Grid from "@mui/material/Unstable_Grid2";
|
||||
|
||||
import { machinesApi } from "../api";
|
||||
import { Machines } from "../components/Machines";
|
||||
|
||||
function Home() {
|
||||
const [machines, setMachines] = useState([]);
|
||||
|
||||
useEffect(() => {
|
||||
machinesApi.list().then((response) => {
|
||||
setMachines(response.data.machines);
|
||||
});
|
||||
}, []);
|
||||
|
||||
const onMachineSelect = (machineName, machineId) => {
|
||||
console.log("selected:", machineName);
|
||||
machinesApi.listProducts(machineId).then((response) => {
|
||||
console.log(response.data.products);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Grid container spacing={2}>
|
||||
<Grid md={4}>
|
||||
<Machines machines={machines} onSelect={onMachineSelect} />
|
||||
</Grid>
|
||||
<Grid md={8}>...</Grid>
|
||||
</Grid>
|
||||
);
|
||||
}
|
||||
|
||||
export { Home };
|
||||
13
frontend/src/reportWebVitals.js
Normal file
13
frontend/src/reportWebVitals.js
Normal file
@ -0,0 +1,13 @@
|
||||
const reportWebVitals = onPerfEntry => {
|
||||
if (onPerfEntry && onPerfEntry instanceof Function) {
|
||||
import('web-vitals').then(({ getCLS, getFID, getFCP, getLCP, getTTFB }) => {
|
||||
getCLS(onPerfEntry);
|
||||
getFID(onPerfEntry);
|
||||
getFCP(onPerfEntry);
|
||||
getLCP(onPerfEntry);
|
||||
getTTFB(onPerfEntry);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
export default reportWebVitals;
|
||||
Reference in New Issue
Block a user