diff --git a/README.md b/README.md new file mode 100644 index 0000000..416d45b --- /dev/null +++ b/README.md @@ -0,0 +1,18 @@ +# Online Hardware Store + +This is a simple online hardware store application built with React, incorporating error tracking using Sentry. Users can browse through items, add them to the cart, and proceed to checkout. The application includes error handling and logging for better debugging and monitoring. + +## Features + +- View a list of hardware items with prices. +- Add items to the shopping cart. +- View the contents of the shopping cart. +- Checkout functionality with error handling. +- Logging and monitoring errors using Sentry. + +## Setup + +1. Clone the repository: + + ```bash + git clone https://github.com/your-username/online-hardware-store.git diff --git a/package-lock.json b/package-lock.json index e60779e..9ea7419 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "css-loader": "^6.8.1", "html-webpack-plugin": "^5.5.3", "style-loader": "^3.3.3", - "webpack": "^5.87.0", + "webpack": "^5.89.0", "webpack-cli": "^5.1.4", "webpack-dev-server": "^4.15.1" } @@ -6006,9 +6006,9 @@ } }, "node_modules/webpack": { - "version": "5.87.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.87.0.tgz", - "integrity": "sha512-GOu1tNbQ7p1bDEoFRs2YPcfyGs8xq52yyPBZ3m2VGnXGtV9MxjrkABHm4V9Ia280OefsSLzvbVoXcfLxjKY/Iw==", + "version": "5.89.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", + "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", "dev": true, "dependencies": { "@types/eslint-scope": "^3.7.3", @@ -10813,9 +10813,9 @@ } }, "webpack": { - "version": "5.87.0", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.87.0.tgz", - "integrity": "sha512-GOu1tNbQ7p1bDEoFRs2YPcfyGs8xq52yyPBZ3m2VGnXGtV9MxjrkABHm4V9Ia280OefsSLzvbVoXcfLxjKY/Iw==", + "version": "5.89.0", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.89.0.tgz", + "integrity": "sha512-qyfIC10pOr70V+jkmud8tMfajraGCZMBWJtrmuBymQKCrLTRejBI8STDp1MCyZu/QTdZSeacCQYpYNQVOzX5kw==", "dev": true, "requires": { "@types/eslint-scope": "^3.7.3", diff --git a/package.json b/package.json index 26beb8e..9186c66 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,7 @@ "css-loader": "^6.8.1", "html-webpack-plugin": "^5.5.3", "style-loader": "^3.3.3", - "webpack": "^5.87.0", + "webpack": "^5.89.0", "webpack-cli": "^5.1.4", "webpack-dev-server": "^4.15.1" }, diff --git a/src/components/App.js b/src/components/App.js index 2cad7de..f003bcf 100644 --- a/src/components/App.js +++ b/src/components/App.js @@ -1,5 +1,5 @@ import React, { Component } from "react"; -// import * as Sentry from "@sentry/react"; +import * as Sentry from "@sentry/react"; import "./App.css"; import wrenchImg from "../assets/wrench.png"; import nailsImg from "../assets/nails.png"; @@ -13,10 +13,12 @@ class App extends Component { super(props); this.state = { cart: [], + hasError: false, + success: false, }; - // generate random email - this.email = Math.random().toString(36).substring(2, 6) + "@yahoo.com"; + + this.email = Math.random().toString(36).substring(2, 6) + "@gmail.com"; this.store = [ { @@ -38,6 +40,7 @@ class App extends Component { img: hammerImg, }, ]; + this.buyItem = this.buyItem.bind(this); this.checkout = this.checkout.bind(this); this.resetCart = this.resetCart.bind(this); @@ -52,29 +55,30 @@ class App extends Component { // Add context to error/event // View this data in "Tags" - // Sentry.configureScope((scope) => { - // scope.setUser({ email: this.email }); // attach user/email context - // scope.setTag("customerType", "medium-plan"); // custom-tag - // }); + Sentry.configureScope((scope) => { + scope.setUser({ email: this.email }); // attach user/email context + scope.setTag("customerType", "medium-plan"); // custom-tag + }); } buyItem(item) { - const cart = [].concat(this.state.cart); + const cart = [...this.state.cart]; cart.push(item); console.log(item); this.setState({ cart, success: false }); // Add context to error/event // View this data in "Additional Data" - // Sentry.configureScope((scope) => { - // scope.setExtra("cart", JSON.stringify(cart)); - // }); - // // View this data in "Breadcrumbs" - // Sentry.addBreadcrumb({ - // category: "cart", - // message: "User added " + item.name + " to cart", - // level: "info", - // }); + Sentry.configureScope((scope) => { + scope.setExtra("cart", JSON.stringify(cart)); + }); + + // View this data in "Breadcrumbs" + Sentry.addBreadcrumb({ + category: "cart", + message: "User added " + item.name + " to cart", + level: "info", + }); } resetCart(event) { @@ -82,19 +86,23 @@ class App extends Component { this.setState({ cart: [], hasError: false, success: false }); // Reset context for error/event - // Sentry.configureScope((scope) => { - // scope.setExtra("cart", ""); - // }); - // Sentry.addBreadcrumb({ - // category: "cart", - // message: "User emptied cart", - // level: "info", - // }); + Sentry.configureScope((scope) => { + scope.setExtra("cart", ""); + }); + Sentry.addBreadcrumb({ + category: "cart", + message: "User emptied cart", + level: "info", + }); } checkout() { // Generate an error - // this.myCodeIsPerfect(); + try { + this.myCodeIsPerfect(); + } catch (error) { + console.error(error); + } const order = { email: this.email, @@ -103,9 +111,9 @@ class App extends Component { // generate unique transactionId and set as Sentry tag const transactionId = getUniqueId(); - // Sentry.configureScope((scope) => { - // scope.setTag("transaction_id", transactionId); - // }); + Sentry.configureScope((scope) => { + scope.setTag("transaction_id", transactionId); + }); // Set transctionID as header const fetchData = { @@ -119,22 +127,22 @@ class App extends Component { - Custom header with transactionId for transaction tracing - throw error if response !== 200 */ - // fetch("http://localhost:8000/checkout", fetchData).then( - // (error, response) => { - // if (error) { - // throw error; - // } - // if (response.statusCode === 200) { - // this.setState({ success: true }); - // } else { - // throw new Error( - // response.statusCode + - // " - " + - // (response.statusMessage || response.body) - // ); - // } - // } - // ); + fetch("http://localhost:8000/checkout", fetchData) + .then((response) => { + if (response.ok) { + this.setState({ success: true }); + } else { + throw new Error( + response.status + + " - " + + (response.statusText || response.body) + ); + } + }) + .catch((error) => { + console.error(error); + this.setState({ hasError: true, success: false }); + }); } render() { @@ -228,3 +236,4 @@ class App extends Component { } export default App; +