diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..33812f55
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,23 @@
+# See https://help.github.com/ignore-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+
+# testing
+/coverage
+
+# production
+/build
+
+# misc
+.DS_Store
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+/src/config.js
diff --git a/README.md b/README.md
index dc85464b..e22fc7af 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,4 @@
# assignment_exchange_rates
How much does a Big Mac cost in Italy?
+
+Alex Thomas
diff --git a/package.json b/package.json
new file mode 100644
index 00000000..70613fc3
--- /dev/null
+++ b/package.json
@@ -0,0 +1,17 @@
+{
+ "name": "assignment_exchange_rates",
+ "version": "0.1.0",
+ "private": true,
+ "dependencies": {
+ "bootstrap": "^4.0.0-alpha.6",
+ "react": "^16.0.0",
+ "react-dom": "^16.0.0",
+ "react-scripts": "1.0.14"
+ },
+ "scripts": {
+ "start": "react-scripts start",
+ "build": "react-scripts build",
+ "test": "react-scripts test --env=jsdom",
+ "eject": "react-scripts eject"
+ }
+}
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100644
index 00000000..a11777cc
Binary files /dev/null and b/public/favicon.ico differ
diff --git a/public/index.html b/public/index.html
new file mode 100644
index 00000000..9a67001c
--- /dev/null
+++ b/public/index.html
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+ Currency Converter
+
+
+
+
+
+
+
+
+
diff --git a/public/manifest.json b/public/manifest.json
new file mode 100644
index 00000000..be607e41
--- /dev/null
+++ b/public/manifest.json
@@ -0,0 +1,15 @@
+{
+ "short_name": "React App",
+ "name": "Create React App Sample",
+ "icons": [
+ {
+ "src": "favicon.ico",
+ "sizes": "192x192",
+ "type": "image/png"
+ }
+ ],
+ "start_url": "./index.html",
+ "display": "standalone",
+ "theme_color": "#000000",
+ "background_color": "#ffffff"
+}
diff --git a/src/App.test.js b/src/App.test.js
new file mode 100644
index 00000000..b84af98d
--- /dev/null
+++ b/src/App.test.js
@@ -0,0 +1,8 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import App from './App';
+
+it('renders without crashing', () => {
+ const div = document.createElement('div');
+ ReactDOM.render(, div);
+});
diff --git a/src/components/App.js b/src/components/App.js
new file mode 100644
index 00000000..9894f50f
--- /dev/null
+++ b/src/components/App.js
@@ -0,0 +1,85 @@
+import React, { Component } from "react";
+import CurrencyConverterContainer from "./CurrencyConverterContainer";
+import CurrencyRatesTableContainer from "./CurrencyRatesTableContainer";
+import JumbotronFluid from "./elements/JumbotronFluid";
+import config from '../config'
+class App extends Component {
+ constructor() {
+ super(),
+ (this.state = {
+ isFetching: false,
+ baseCurrency: "USD",
+ rates: [],
+ date: new Date().toISOString().slice(0, 10)
+ });
+ }
+
+
+ getRates = () => {
+ fetch(
+ `http://api.fixer.io/${this.state.date}?base=${this.state.baseCurrency}?{config.key}`
+ )
+ .then(response => response.json())
+ .then(json => {
+ this.setState({
+ rates: json.rates,
+ isFetching: false
+ });
+ });
+ };
+ componentDidMount() {
+ // Before performing the fetch, set isFetching to true
+ this.setState({ isFetching: true }, this.getRates());
+ }
+ shouldComponentUpdate() {
+ return this.state.isFetching !== false;
+ }
+
+ switch_currency = e => {
+ e.preventDefault();
+ //console.log("select-target", e.target);
+ //console.log("select-target.value", e.target.value);
+ this.setState(
+ {
+ baseCurrency: e.target.value
+ },
+ this.setState({ isFetching: true }, this.getRates())
+ );
+ };
+
+ setDate = e => {
+ //console.log("date-target", e.target);
+ //console.log("date-target.value", e.target.value);
+ this.setState(
+ {
+ date: e.target.value,
+ isFetching: true
+ },
+ this.getRates()
+ );
+ };
+ render() {
+ const { baseCurrency, rates, date } = this.state;
+ const currenciesArray = Object.keys(rates);
+ //console.log("RATES Passed", rates);
+ console.log("RATES Passed", config.key);
+ return (
+
+
+
+
+
+
+ );
+ }
+}
+
+export default App;
diff --git a/src/components/BaseCurrencyForm.js b/src/components/BaseCurrencyForm.js
new file mode 100644
index 00000000..3239e60e
--- /dev/null
+++ b/src/components/BaseCurrencyForm.js
@@ -0,0 +1,42 @@
+import React from "react";
+import Select from "./elements/Select";
+import Button from "./elements/Button";
+
+const BaseCurrencyForm = props => {
+ const {
+ rates,
+ baseCurrency,
+ switch_currency,
+ setDate,
+ date,
+ currenciesArray
+ } = props;
+ return (
+
+ );
+};
+
+BaseCurrencyForm.defaultProps = {
+ type: "button",
+ color: "default",
+ children: "Submit"
+};
+
+export default BaseCurrencyForm;
diff --git a/src/components/ConverterBaseCurrencySelector.js b/src/components/ConverterBaseCurrencySelector.js
new file mode 100644
index 00000000..85fa4058
--- /dev/null
+++ b/src/components/ConverterBaseCurrencySelector.js
@@ -0,0 +1,28 @@
+import React from "react";
+import Select from "./elements/Select";
+import PropTypes from "prop-types";
+
+const ConverterBaseCurrencySelector = ({
+ selectCurrency,
+ converterBaseCurrency,
+ currenciesArray
+}) => {
+ //currenciesArray.unshift(converterBaseCurrency);
+ return (
+
+ );
+};
+
+ConverterBaseCurrencySelector.propTypes = {
+ convertedCurrency: PropTypes.string.isRequired,
+ selectCurrency: PropTypes.func.isRequired,
+ currenciesArray: PropTypes.array.isRequired
+};
+export default ConverterBaseCurrencySelector;
+
diff --git a/src/components/ConverterConvertedCurrencySelector.js b/src/components/ConverterConvertedCurrencySelector.js
new file mode 100644
index 00000000..05045ab4
--- /dev/null
+++ b/src/components/ConverterConvertedCurrencySelector.js
@@ -0,0 +1,28 @@
+import React from "react";
+import Select from "./elements/Select";
+import PropTypes from "prop-types";
+
+const ConverterConvertedCurrencySelector = ({
+ selectCurrency,
+ convertedCurrency,
+ currenciesArray
+}) => {
+ //currenciesArray.unshift(convertedCurrency);
+ return (
+
+ );
+};
+
+ConverterConvertedCurrencySelector.propTypes = {
+ convertedCurrency: PropTypes.string.isRequired,
+ selectCurrency: PropTypes.func.isRequired,
+ currenciesArray: PropTypes.array.isRequired
+};
+
+export default ConverterConvertedCurrencySelector;
diff --git a/src/components/CurrencyConverter.js b/src/components/CurrencyConverter.js
new file mode 100644
index 00000000..fd8c1d4a
--- /dev/null
+++ b/src/components/CurrencyConverter.js
@@ -0,0 +1,8 @@
+import React from "react";
+import Converter from "./elements/Converter";
+
+const CurrencyConverter = () => {
+ return ;
+};
+
+export default CurrencyConverter;
diff --git a/src/components/CurrencyConverterContainer.js b/src/components/CurrencyConverterContainer.js
new file mode 100644
index 00000000..ca5b8503
--- /dev/null
+++ b/src/components/CurrencyConverterContainer.js
@@ -0,0 +1,125 @@
+import React, { Component } from "react";
+import Input from "./elements/Input";
+import CurrencyConverterForm from "./CurrencyConverterForm";
+import CurrencyConverterOutput from "./CurrencyConverterOutput";
+import PropTypes from "prop-types";
+
+class CurrencyConverterContainer extends Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ converterBaseCurrency: "USD",
+ convertedCurrency: "EUR",
+ converterBaseValue: 1,
+ currenciesArray: [],
+ convertingRate: "",
+ convertingOutcome: 0
+ };
+ }
+
+ //gets array of currencies for currency selectors
+ //will take the base currency
+ getCurrencies = base => {
+ this.setState({
+ isFetching: true
+ });
+ fetch(`http://api.fixer.io/latest?base=${base}`)
+ .then(response => {
+ return response.json();
+ })
+ .then(json => {
+ console.log("Fetched selector currencies");
+ this.setState({
+ isFetching: false,
+ currenciesArray: Object.keys(json.rates)
+ });
+ });
+ };
+ // component did mount with api call to populate selectors
+ componentDidMount = () => {
+ this.getCurrencies(this.state.converterBaseCurrency);
+ };
+ //another api call to get rates for selected currencies
+ //will take base cuurency and the converted currency
+
+ handleClick = e => {
+ e.preventDefault();
+ this.setState({
+ isFetching: true
+ });
+ fetch(
+ `http://api.fixer.io/latest?base=${this.state
+ .converterBaseCurrency}&symbols=${this.state.convertedCurrency}`
+ )
+ .then(response => response.json())
+ .then(json => {
+ let rate = Object.values(json.rates)[0];
+ this.setState(
+ {
+ convertingRate: rate
+ },
+ () => {
+ let outcome =
+ this.state.converterBaseValue * this.state.convertingRate;
+ let length = this.state.convertedBaseValue + 3;
+ outcome = outcome.toFixed(3);
+ this.setState({
+ convertingOutcome: outcome
+ });
+ }
+ );
+ });
+ };
+ baseCurrencyInput = e => {
+ let input = e.target.value;
+ this.setState({ converterBaseValue: input });
+ };
+ selectBaseCurrency = e => {
+ this.setState({ converterBaseCurrency: e.target.value });
+ this.getCurrencies(e.target.value);
+ };
+ selectConvertedCurrency = e => {
+ this.setState({ convertedCurrency: e.target.value });
+ this.getCurrencies(e.target.value);
+ };
+ render() {
+ const {
+ converterBaseCurrency,
+ convertedCurrency,
+ converterBaseValue,
+ currenciesArray,
+ convertingRate,
+ convertingOutcome
+ } = this.state;
+ console.log("rendered");
+ return (
+
+ Currency Calculator
+
+
+ );
+ }
+}
+
+CurrencyConverterContainer.propTypes = {
+ converterBaseCurrency: PropTypes.string.isRequired,
+ convertedCurrency: PropTypes.string.isRequired,
+ converterBaseValue: PropTypes.number,
+ currenciesArray: PropTypes.array.isRequired,
+ convertingRate: PropTypes.number,
+ convertingOutcome: PropTypes.number
+};
+export default CurrencyConverterContainer;
diff --git a/src/components/CurrencyConverterForm.js b/src/components/CurrencyConverterForm.js
new file mode 100644
index 00000000..f1bd0a70
--- /dev/null
+++ b/src/components/CurrencyConverterForm.js
@@ -0,0 +1,57 @@
+import React from "react";
+import Input from "./elements/Input";
+import ConverterBaseCurrencySelector from "./ConverterBaseCurrencySelector";
+import ConverterConvertedCurrencySelector from "./ConverterConvertedCurrencySelector";
+import PropTypes from "prop-types";
+
+const CurrencyConverterForm = ({
+ converterBaseCurrency,
+ selectBaseCurrency,
+ currenciesArray, //for populating selectors
+ convertedCurrency, //second selector
+ selectConvertedCurrency, //function upon selection
+ converterBaseValue, //value of user input
+ baseCurrencyInput, //function changes converterBaseValue upon user input
+ handleClick //function for submit btn
+}) => {
+ return (
+
+ );
+};
+
+CurrencyConverterForm.propTypes = {
+ converterBaseCurrency: PropTypes.string.isRequired,
+ selectBaseCurrency: PropTypes.string.isRequired,
+ currenciesArray: PropTypes.array.isRequired,
+ convertedCurrency: PropTypes.string.isRequired,
+ selectConvertedCurrency: PropTypes.func.isRequired,
+ converterBaseValue: PropTypes.number,
+ baseCurrencyInput: PropTypes.func.isRequired,
+ handleClick: PropTypes.func.isRequired
+};
+
+export default CurrencyConverterForm;
diff --git a/src/components/CurrencyConverterOutput.jsx b/src/components/CurrencyConverterOutput.jsx
new file mode 100644
index 00000000..f69174e0
--- /dev/null
+++ b/src/components/CurrencyConverterOutput.jsx
@@ -0,0 +1,37 @@
+import React from "react";
+import PropTypes from "prop-types";
+
+const CurrencyConverterOutput = ({
+ converterBaseValue,
+ converterBaseCurrency,
+ convertingOutcome,
+ convertedCurrency
+}) => {
+ return (
+
+
{converterBaseValue}
+
{converterBaseCurrency}
+
=
+
{convertingOutcome}
+
{convertedCurrency}
+
+ );
+};
+
+CurrencyConverterOutput.propTypes = {
+ converterBaseValue: PropTypes.number,
+ converterBaseCurrency: PropTypes.string.isRequired,
+ convertingOutcome: PropTypes.number,
+ convertedCurrency: PropTypes.string.isRequired,
+ customConverterBaseValue: function(
+ props,
+ converterBaseValue,
+ CurrencyConverterOutput
+ ) {
+ if (typeof converterBaseValue !== "number") {
+ return new Error("Value must be a number");
+ }
+ }
+};
+
+export default CurrencyConverterOutput;
diff --git a/src/components/CurrencyRatesTable.js b/src/components/CurrencyRatesTable.js
new file mode 100644
index 00000000..bad4a0f7
--- /dev/null
+++ b/src/components/CurrencyRatesTable.js
@@ -0,0 +1,12 @@
+import React from "react";
+import Table from "./elements/Table";
+
+const CurrencyRatesTable = props => {
+ return (
+
+ );
+};
+
+export default CurrencyRatesTable;
diff --git a/src/components/CurrencyRatesTableContainer.js b/src/components/CurrencyRatesTableContainer.js
new file mode 100644
index 00000000..541ee7ba
--- /dev/null
+++ b/src/components/CurrencyRatesTableContainer.js
@@ -0,0 +1,15 @@
+import React from "react";
+import CurrencyRatesTable from "./CurrencyRatesTable";
+import BaseCurrencyForm from "./BaseCurrencyForm";
+
+const CurrencyRatesTableContainer = props => {
+ //console.log("Table props", props);
+ return (
+
+ );
+};
+
+export default CurrencyRatesTableContainer;
diff --git a/src/components/elements/Alert.js b/src/components/elements/Alert.js
new file mode 100644
index 00000000..e6cdf49a
--- /dev/null
+++ b/src/components/elements/Alert.js
@@ -0,0 +1,13 @@
+import React from 'react'
+
+const Alert = ({type, children}) => (
+
+ {children}
+
+)
+
+Alert.defaultProps = {
+ type: 'success'
+}
+
+export default Alert
diff --git a/src/components/elements/Button.js b/src/components/elements/Button.js
new file mode 100644
index 00000000..cbcbac0d
--- /dev/null
+++ b/src/components/elements/Button.js
@@ -0,0 +1,23 @@
+import React from 'react'
+
+const Button = (props) => {
+ const {size, color, children, type} = props
+ const sizeClass = size ? `btn-${size}` : ''
+
+ return (
+
+ )
+}
+
+Button.defaultProps = {
+ type: 'button',
+ color: 'default',
+ children: 'Submit',
+}
+
+export default Button
diff --git a/src/components/elements/Converter.js b/src/components/elements/Converter.js
new file mode 100644
index 00000000..43a8bbf6
--- /dev/null
+++ b/src/components/elements/Converter.js
@@ -0,0 +1,10 @@
+const Converter = (baseValue, rate) => {
+ let exchangeValue = baseValue * rate;
+ let reverseExchangeValue = baseValue / rate;
+ return {
+ exchangeValue,
+ reverseExchangeValue
+ };
+};
+
+export default Converter;
diff --git a/src/components/elements/Input.js b/src/components/elements/Input.js
new file mode 100644
index 00000000..43ae7332
--- /dev/null
+++ b/src/components/elements/Input.js
@@ -0,0 +1,13 @@
+import React from "react";
+
+const Input = props => {
+ const classNames = `form-control ${props.className}`;
+
+ return ;
+};
+
+Input.defaultProps = {
+ type: "text"
+};
+
+export default Input;
diff --git a/src/components/elements/InputGroup.js b/src/components/elements/InputGroup.js
new file mode 100644
index 00000000..7c105ff7
--- /dev/null
+++ b/src/components/elements/InputGroup.js
@@ -0,0 +1,10 @@
+import React from "react";
+
+const InputGroup = ({ name, labelText, children }) => (
+
+
+ {children}
+
+);
+
+export default InputGroup;
diff --git a/src/components/elements/JumbotronFluid.js b/src/components/elements/JumbotronFluid.js
new file mode 100644
index 00000000..3c2c6f91
--- /dev/null
+++ b/src/components/elements/JumbotronFluid.js
@@ -0,0 +1,17 @@
+import React from 'react'
+import Showable from './Showable'
+
+const JumbotronFluid = ({heading, lead}) => (
+
+
+
+ {heading}
+
+
+ {lead}
+
+
+
+)
+
+export default JumbotronFluid
diff --git a/src/components/elements/Select.js b/src/components/elements/Select.js
new file mode 100644
index 00000000..1453e8a7
--- /dev/null
+++ b/src/components/elements/Select.js
@@ -0,0 +1,34 @@
+import React from "react";
+
+const Select = props => {
+ const { baseValue, handleSwitch, data } = props;
+
+ //gets keys from dataObject
+ //console.log("DAATA", data);
+ const optionsList = data.map((item, i) => {
+ return (
+
+ );
+ });
+ return (
+
+ );
+};
+
+Select.defaultProps = {
+ type: "text"
+};
+
+export default Select;
diff --git a/src/components/elements/Showable.js b/src/components/elements/Showable.js
new file mode 100644
index 00000000..11872e3a
--- /dev/null
+++ b/src/components/elements/Showable.js
@@ -0,0 +1,11 @@
+import React from "react";
+
+const Showable = ({ show, children }) => {
+ if (!show) {
+ return null;
+ }
+
+ return {children}
;
+};
+
+export default Showable;
diff --git a/src/components/elements/Table.js b/src/components/elements/Table.js
new file mode 100644
index 00000000..41a3e4ad
--- /dev/null
+++ b/src/components/elements/Table.js
@@ -0,0 +1,29 @@
+import React from "react";
+import Converter from "./Converter";
+
+const Table = props => {
+ const { baseCurrency, rates } = props;
+ const currenciesArr = [];
+
+ const currencies = Object.keys(rates).forEach(function(key, index) {
+ currenciesArr.push(
+
+ | {key} |
+ {rates[key]} |
+ {1 / rates[key]} |
+
+ );
+ });
+ return (
+
+
+ | Currency |
+ Units per {baseCurrency} |
+ {baseCurrency} per Unit |
+
+ {currenciesArr}
+
+ );
+};
+
+export default Table;
diff --git a/big_mac_2017_01.js b/src/components/elements/big_mac_2017_01.js
similarity index 100%
rename from big_mac_2017_01.js
rename to src/components/elements/big_mac_2017_01.js
diff --git a/src/index.css b/src/index.css
new file mode 100644
index 00000000..f0a4785a
--- /dev/null
+++ b/src/index.css
@@ -0,0 +1,104 @@
+body {
+ margin: 0;
+ padding: 0;
+ font-family: sans-serif;
+}
+
+.currency_table {
+ width: 90%;
+ margin: 2rem auto;
+ max-height: 15rem;
+ overflow: auto;
+ font-size: 1.2rem;
+}
+.currency_table * {
+ margin: 0 auto;
+}
+.currency_table th {
+ width: 1%;
+}
+#ChooseBaseCurrency {
+ width: 90%;
+ text-align: center;
+}
+
+#ChooseBaseCurrency * {
+ width: 30%;
+ margin: 0.5rem 3rem;
+ display: inline-block;
+ font-size: 1.5rem;
+}
+@media (max-width: 865px) {
+ #ChooseBaseCurrency * {
+ width: 60%;
+ margin: 1rem 3rem;
+ display: inline-block;
+ font-size: 1.5rem;
+ }
+ .currency_table {
+ width: 92%;
+ margin: 1rem auto;
+ max-height: fit-content;
+ font-size: 1rem;
+ }
+}
+
+section h1 {
+ width: 50%;
+ margin: 5rem auto;
+ text-decoration: none;
+ background-color: #9fbcdf;
+ outline: 38px solid #9fbcdf;
+}
+
+.converter_wrapper {
+ text-align: center;
+ margin-top: 3rem;
+}
+
+#currencyConverterForm {
+ outline: 1px solid #d9d8d8;
+ padding: 0.5rem;
+ margin-bottom: 8rem;
+}
+
+#currencyConverterForm input,
+#currencyConverterForm select {
+ width: 8rem;
+ height: 2.5rem;
+ margin: 0.5rem 1.5rem;
+}
+.converter_get_input,
+.outcome {
+ display: flex;
+ flex-wrap: wrap;
+ width: fit-content;
+ margin: 0.5rem auto;
+}
+#converter_to {
+ font-family: sans-serif;
+ margin: -0.1rem 3rem;
+ font-size: 2rem;
+ font-style: italic;
+ font-weight: 500;
+}
+
+.rate {
+ display: flex;
+ width: fit-content;
+ margin: 0.5rem auto;
+}
+
+.rate p {
+ margin: 0 2rem;
+ font-size: 2rem;
+}
+
+.outcome {
+ border: 2px solid #6ec2ba;
+ margin: 2rem auto;
+}
+.outcome p {
+ width: 10rem;
+ font-size: 2rem;
+}
diff --git a/src/index.js b/src/index.js
new file mode 100644
index 00000000..f8f271ca
--- /dev/null
+++ b/src/index.js
@@ -0,0 +1,9 @@
+import React from "react";
+import ReactDOM from "react-dom";
+import "bootstrap/dist/css/bootstrap.css";
+import "./index.css";
+import App from "./components/App";
+import registerServiceWorker from "./registerServiceWorker";
+
+ReactDOM.render(, document.getElementById("root"));
+registerServiceWorker();
diff --git a/src/logo.svg b/src/logo.svg
new file mode 100644
index 00000000..6b60c104
--- /dev/null
+++ b/src/logo.svg
@@ -0,0 +1,7 @@
+
diff --git a/src/registerServiceWorker.js b/src/registerServiceWorker.js
new file mode 100644
index 00000000..4a3ccf02
--- /dev/null
+++ b/src/registerServiceWorker.js
@@ -0,0 +1,108 @@
+// In production, we register a service worker to serve assets from local cache.
+
+// This lets the app load faster on subsequent visits in production, and gives
+// it offline capabilities. However, it also means that developers (and users)
+// will only see deployed updates on the "N+1" visit to a page, since previously
+// cached resources are updated in the background.
+
+// To learn more about the benefits of this model, read https://goo.gl/KwvDNy.
+// This link also includes instructions on opting out of this behavior.
+
+const isLocalhost = Boolean(
+ window.location.hostname === 'localhost' ||
+ // [::1] is the IPv6 localhost address.
+ window.location.hostname === '[::1]' ||
+ // 127.0.0.1/8 is considered localhost for IPv4.
+ window.location.hostname.match(
+ /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
+ )
+);
+
+export default function register() {
+ if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
+ // The URL constructor is available in all browsers that support SW.
+ const publicUrl = new URL(process.env.PUBLIC_URL, window.location);
+ if (publicUrl.origin !== window.location.origin) {
+ // Our service worker won't work if PUBLIC_URL is on a different origin
+ // from what our page is served on. This might happen if a CDN is used to
+ // serve assets; see https://github.com/facebookincubator/create-react-app/issues/2374
+ return;
+ }
+
+ window.addEventListener('load', () => {
+ const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
+
+ if (!isLocalhost) {
+ // Is not local host. Just register service worker
+ registerValidSW(swUrl);
+ } else {
+ // This is running on localhost. Lets check if a service worker still exists or not.
+ checkValidServiceWorker(swUrl);
+ }
+ });
+ }
+}
+
+function registerValidSW(swUrl) {
+ navigator.serviceWorker
+ .register(swUrl)
+ .then(registration => {
+ registration.onupdatefound = () => {
+ const installingWorker = registration.installing;
+ installingWorker.onstatechange = () => {
+ if (installingWorker.state === 'installed') {
+ if (navigator.serviceWorker.controller) {
+ // At this point, the old content will have been purged and
+ // the fresh content will have been added to the cache.
+ // It's the perfect time to display a "New content is
+ // available; please refresh." message in your web app.
+ console.log('New content is available; please refresh.');
+ } else {
+ // At this point, everything has been precached.
+ // It's the perfect time to display a
+ // "Content is cached for offline use." message.
+ console.log('Content is cached for offline use.');
+ }
+ }
+ };
+ };
+ })
+ .catch(error => {
+ console.error('Error during service worker registration:', error);
+ });
+}
+
+function checkValidServiceWorker(swUrl) {
+ // Check if the service worker can be found. If it can't reload the page.
+ fetch(swUrl)
+ .then(response => {
+ // Ensure service worker exists, and that we really are getting a JS file.
+ if (
+ response.status === 404 ||
+ response.headers.get('content-type').indexOf('javascript') === -1
+ ) {
+ // No service worker found. Probably a different app. Reload the page.
+ navigator.serviceWorker.ready.then(registration => {
+ registration.unregister().then(() => {
+ window.location.reload();
+ });
+ });
+ } else {
+ // Service worker found. Proceed as normal.
+ registerValidSW(swUrl);
+ }
+ })
+ .catch(() => {
+ console.log(
+ 'No internet connection found. App is running in offline mode.'
+ );
+ });
+}
+
+export function unregister() {
+ if ('serviceWorker' in navigator) {
+ navigator.serviceWorker.ready.then(registration => {
+ registration.unregister();
+ });
+ }
+}