diff --git a/frontend/public/manifest.json b/frontend/public/manifest.json new file mode 100644 index 0000000..cd713dd --- /dev/null +++ b/frontend/public/manifest.json @@ -0,0 +1,8 @@ +{ + "short_name": "React App", + "name": "Create React App Sample", + "start_url": "./index.html", + "display": "standalone", + "theme_color": "#000000", + "background_color": "#ffffff" +} diff --git a/frontend/src/api/common.js b/frontend/src/api/common.js index d3e2848..2af2011 100644 --- a/frontend/src/api/common.js +++ b/frontend/src/api/common.js @@ -1,5 +1,4 @@ import axios from "axios"; -import { API_URL } from "../const"; export class ApiBase {} @@ -12,7 +11,6 @@ const commonHeaders = { }; export const axiosUnauthorizedInstance = axios.create({ - baseURL: API_URL, timeout: 5000, headers: commonHeaders, }); @@ -25,7 +23,6 @@ axiosUnauthorizedInstance.interceptors.response.use( ); export const axiosInstance = axios.create({ - baseURL: API_URL, timeout: 5000, headers: { ...commonHeaders, diff --git a/frontend/src/api/index.js b/frontend/src/api/index.js index 0bd0a78..68350ae 100644 --- a/frontend/src/api/index.js +++ b/frontend/src/api/index.js @@ -1 +1,2 @@ export { machinesApi } from "./machines"; +export { productsApi } from "./products"; diff --git a/frontend/src/api/machines.js b/frontend/src/api/machines.js index 6f9de38..58a0f1b 100644 --- a/frontend/src/api/machines.js +++ b/frontend/src/api/machines.js @@ -1,14 +1,17 @@ import { axiosInstance, ApiBase } from "./common"; +import { MACHINES_API_URL } from "../const"; + +const baseUrl = `${MACHINES_API_URL}/machines`; class MachinesApi extends ApiBase { list = async () => { - return axiosInstance.get(`/machines`, {}); + return axiosInstance.get(`${baseUrl}`, {}); }; get = async (machineId) => { - return axiosInstance.get(`/machines/${machineId}`, {}); + return axiosInstance.get(`${baseUrl}/${machineId}`, {}); }; listProducts = async (machineId) => { - return axiosInstance.get(`/machines/${machineId}/products`, {}); + return axiosInstance.get(`${baseUrl}/${machineId}/products`, {}); }; } diff --git a/frontend/src/api/products.js b/frontend/src/api/products.js new file mode 100644 index 0000000..9fa81b6 --- /dev/null +++ b/frontend/src/api/products.js @@ -0,0 +1,12 @@ +import { axiosInstance, ApiBase } from "./common"; +import { PRODUCTS_API_URL } from "../const"; + +const baseUrl = `${PRODUCTS_API_URL}/products`; + +class ProductsApi extends ApiBase { + get = async (productId) => { + return axiosInstance.get(`${baseUrl}/${productId}`, {}); + }; +} + +export const productsApi = new ProductsApi(); diff --git a/frontend/src/components/ProductCard.js b/frontend/src/components/ProductCard.js index b8d7958..47b6eaa 100644 --- a/frontend/src/components/ProductCard.js +++ b/frontend/src/components/ProductCard.js @@ -6,20 +6,21 @@ import Typography from "@mui/material/Typography"; import { CardActionArea } from "@mui/material"; import { PRODUCT_IMAGE_DIR } from "../const"; -function ProductCard({ product }) { +function ProductCard({ product, onClick }) { const productImg = `${PRODUCT_IMAGE_DIR}/${product.image}`; return ( - - - + + { + onClick(product.id); + }} + > + - + {product.name} - - {product.description} - diff --git a/frontend/src/components/ProductModal.js b/frontend/src/components/ProductModal.js new file mode 100644 index 0000000..e0e6090 --- /dev/null +++ b/frontend/src/components/ProductModal.js @@ -0,0 +1,36 @@ +import * as React from "react"; +import Button from "@mui/material/Button"; +import Dialog from "@mui/material/Dialog"; +import DialogActions from "@mui/material/DialogActions"; +import DialogContent from "@mui/material/DialogContent"; +import DialogContentText from "@mui/material/DialogContentText"; +import DialogTitle from "@mui/material/DialogTitle"; +import CardMedia from "@mui/material/CardMedia"; +import { PRODUCT_IMAGE_DIR } from "../const"; + +function ProductModal({ product, onClose }) { + const productImg = `${PRODUCT_IMAGE_DIR}/${product.image}`; + + return ( + + {product.name} + + + {product.description} + + + + + + ); +} + +export { ProductModal }; diff --git a/frontend/src/components/Products.js b/frontend/src/components/Products.js index 0d02b15..71aab9c 100644 --- a/frontend/src/components/Products.js +++ b/frontend/src/components/Products.js @@ -2,12 +2,32 @@ import * as React from "react"; import Grid from "@mui/material/Unstable_Grid2"; import Typography from "@mui/material/Typography"; import { ProductCard } from "./ProductCard"; +import { ProductModal } from "./ProductModal"; +import { productsApi } from "../api"; function Products({ machineName, products, onSelect }) { + const [productModal, setProductModal] = React.useState({ isOpen: false, product: null }); + + const onProductSelect = (productId) => { + productsApi.get(productId).then((response) => { + setProductModal({ + isOpen: true, + product: response.data, + }); + }); + }; + + const onProductModalClose = () => { + setProductModal({ + isOpen: false, + productId: null, + }); + }; + const productItems = products.map((product) => { return ( - + ); }); @@ -21,6 +41,8 @@ function Products({ machineName, products, onSelect }) { {productItems} + + {productModal.isOpen && } ); } diff --git a/frontend/src/const.js b/frontend/src/const.js index 6e46ebd..d146677 100644 --- a/frontend/src/const.js +++ b/frontend/src/const.js @@ -1,2 +1,3 @@ -export const API_URL = process.env.REACT_APP_BACKEND_API_URL || "http://localhost:10000"; +export const MACHINES_API_URL = process.env.REACT_APP_MACHINES_API_URL || "http://localhost:4000"; +export const PRODUCTS_API_URL = process.env.REACT_APP_PRODUCTS_API_URL || "http://localhost:4001"; export const PRODUCT_IMAGE_DIR = "/static/products/"; diff --git a/frontend/src/pages/Home.js b/frontend/src/pages/Home.js index bd83bcd..d7231bb 100644 --- a/frontend/src/pages/Home.js +++ b/frontend/src/pages/Home.js @@ -18,9 +18,7 @@ function Home() { }, []); const onMachineSelect = (machineName, machineId) => { - console.log("selected:", machineName); machinesApi.listProducts(machineId).then((response) => { - console.log(response.data.products); setProductsData({ machineName, products: response.data.products,