wly %!s(int64=7) %!d(string=hai) anos
pai
achega
46ecadd9b8

+ 3 - 0
src/case/shopApp/src/App.css

@@ -0,0 +1,3 @@
+.App{
+    height: 100%;
+}

+ 23 - 0
src/case/shopApp/src/App.js

@@ -0,0 +1,23 @@
+import React, { Component } from 'react';
+import './App.css';
+
+
+import TabBarBottom from './components/App/TabBarBottom'
+
+class App extends Component {
+  constructor(props){
+    super(props)
+    this.state={
+      showComponent:'TabBarBottom'
+    }
+  }
+  //showComponent
+  render() {
+    return (
+      <div className="App">
+        {this.state.showComponent==='TabBarBottom'?<TabBarBottom />:''}
+      </div>
+    );
+  }
+}
+export default App;

+ 9 - 0
src/case/shopApp/src/App.test.js

@@ -0,0 +1,9 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import App from './App';
+
+it('renders without crashing', () => {
+  const div = document.createElement('div');
+  ReactDOM.render(<App />, div);
+  ReactDOM.unmountComponentAtNode(div);
+});

+ 30 - 0
src/case/shopApp/src/api/graphql/product.js

@@ -0,0 +1,30 @@
+export const getProductByProps=`query productbyprops($category: String, $updatedAt: String, $name: String, $createdAt: String, $status: String, $intro: String, $price: Float, $img: String, $stock: Int) {
+    productbyprops: product_by_props(category: $category updatedAt: $updatedAt name: $name createdAt: $createdAt status: $status intro: $intro price: $price img: $img stock: $stock) {
+        category
+        updatedAt
+        unit
+        name
+        createdAt
+        status
+        id
+        intro
+        price
+        img
+        stock
+    }
+}`
+export const getProductById=`query getProductById($id:ID){
+    product_by_id(id:$id){
+      category
+      createdAt
+      id
+      img
+      intro
+      name
+      price
+      status
+      stock
+      unit
+      updatedAt
+    }
+  }`

+ 33 - 0
src/case/shopApp/src/api/graphql_request.js

@@ -0,0 +1,33 @@
+import { request } from 'graphql-request'
+import URL from './url_config'
+
+
+export const graphqls=(query,variables)=>{
+   
+    //console.log(URL.HTTP_DATA_URL)
+    const http_request=URL.HTTP_DATA_URL
+      
+    return request(http_request, query,variables).then(data =>data)
+}
+
+
+/* import {graphqls} from './api/graphql_request'
+
+let query=`query productbyprops($category: String, $updatedAt: String, $name: String, $createdAt: String, $status: String, $intro: String, $price: Float, $img: String, $stock: Int) {
+    productbyprops: product_by_props(category: $category updatedAt: $updatedAt name: $name createdAt: $createdAt status: $status intro: $intro price: $price img: $img stock: $stock) {
+        category
+        updatedAt
+        unit
+        name
+        createdAt
+        status
+        id
+        intro
+        price
+        img
+        stock
+    }
+}`,
+variables={}
+
+graphqls(query,variables).then(data=>console.log(data)) */

+ 9 - 0
src/case/shopApp/src/api/url_config.js

@@ -0,0 +1,9 @@
+var config={
+    APPID:"wxc4831335ae194243",
+    HTTP_DATA_URL:'http://localhost:3001/graphql',
+    HTTP_PAY_URL:'https://xcx.ioobot.com/payinfo'
+}
+export default config
+
+
+

+ 4 - 0
src/case/shopApp/src/components/App/TabBarBottom.css

@@ -0,0 +1,4 @@
+/* .TabBarBottom{
+    position: absolute;
+    bottom: 0;
+} */

+ 149 - 0
src/case/shopApp/src/components/App/TabBarBottom.jsx

@@ -0,0 +1,149 @@
+import React, { Component } from 'react';
+import { TabBar } from 'antd-mobile';
+import './TabBarBottom.css'
+
+
+import HomePage from '../HomePage/HomePage'
+import ShopCar from '../ShopCarPage/shopCar'
+import UserPage from '../UserPage/userPage'
+
+
+
+
+class TabBarBottom extends Component {
+  constructor(props) {
+    super(props);
+    this.state = {
+      selectedTab: 'index',
+      hidden: false,
+      fullScreen: true,
+    };
+  }
+  
+
+  renderContent(page) { 
+    if(page==='index'){
+      //console.log(page)
+      return (
+        <div style={{ backgroundColor: 'white', height: '100%', textAlign: 'center' }}>
+         <HomePage />
+        </div>
+      );
+    }
+    if(page==='shopCar'){
+      //console.log(page)
+      return (
+        <div style={{ backgroundColor: 'white', height: '100%', textAlign: 'center' }}>
+         <ShopCar />
+        </div>
+      );
+    }
+    if(page==='user'){
+      //console.log(page)
+      return (
+        <div style={{ backgroundColor: 'white', height: '100%', textAlign: 'center' }}>
+        <UserPage />
+        </div>
+      );
+    }
+    
+  }
+  render() {
+    //这里渲染一次
+    return (
+      <div style={this.state.fullScreen ? { position: 'fixed', height: '100%', width: '100%', top: 0 } : { height: 400 }} className="TabBarBottom">
+        <TabBar
+          unselectedTintColor="#949494"
+          tintColor="#33A3F4"
+          barTintColor="white"
+          hidden={this.state.hidden}
+        >
+          <TabBar.Item
+            title="商品"
+            key="index"
+            icon={<div style={{
+              width: '22px',
+              height: '22px',
+              background: 'url(https://wly-1254337200.cos.ap-guangzhou.myqcloud.com/home.svg) center center /  21px 21px no-repeat' }}
+            />
+            }
+            selectedIcon={<div style={{
+              width: '22px',
+              height: '22px',
+              background: 'url(https://wly-1254337200.cos.ap-guangzhou.myqcloud.com/home_s.svg) center center /  21px 21px no-repeat' }}
+            />
+            }
+            selected={this.state.selectedTab === 'index'}
+         
+            onPress={() => {
+              this.setState({
+                selectedTab: 'index',
+              });
+            }}
+            data-seed="logId"
+          >
+            {this.renderContent('index')}
+          </TabBar.Item>
+          <TabBar.Item
+            icon={
+              <div style={{
+                width: '22px',
+                height: '22px',
+                background: 'url(https://wly-1254337200.cos.ap-guangzhou.myqcloud.com/shopcar.svg) center center /  21px 21px no-repeat' }}
+              />
+            }
+            selectedIcon={
+              <div style={{
+                width: '22px',
+                height: '22px',
+                background: 'url(https://wly-1254337200.cos.ap-guangzhou.myqcloud.com/shopcar_s.svg) center center /  21px 21px no-repeat' }}
+              />
+            }
+            title="购物车"
+            key="shopCar"
+          
+            selected={this.state.selectedTab === 'shopCar'}
+            onPress={() => {
+              this.setState({
+                selectedTab: 'shopCar',
+              });
+            }}
+            data-seed="logId1"
+          >
+            {this.renderContent('shopCar')}
+          </TabBar.Item>
+          <TabBar.Item
+            icon={
+              <div style={{
+                width: '22px',
+                height: '22px',
+                background: 'url(https://wly-1254337200.cos.ap-guangzhou.myqcloud.com/user.svg) center center /  21px 21px no-repeat' }}
+              />
+            }
+            selectedIcon={
+              <div style={{
+                width: '22px',
+                height: '22px',
+                background: 'url(https://wly-1254337200.cos.ap-guangzhou.myqcloud.com/user_s.svg) center center /  21px 21px no-repeat' }}
+              />
+            }
+            title="用户中心"
+            key="ser"
+  
+            selected={this.state.selectedTab === 'user'}
+            onPress={() => {
+              this.setState({
+                selectedTab: 'user',
+              });
+            }}
+          >
+            {this.renderContent('user')}
+          </TabBar.Item>
+        </TabBar>
+      </div>
+    );
+  }
+}
+
+
+export default TabBarBottom

+ 48 - 0
src/case/shopApp/src/components/HomePage/Cards.css

@@ -0,0 +1,48 @@
+div.Card{
+    font-size:15px;
+}
+
+div.imgWrap{
+    flex-basis:100px;
+}
+.hot{
+    color:red;
+    font-size: 12px;
+}
+.title{
+    font-size: 15px;
+}
+p{
+    padding: 0;
+    margin: 0;
+}
+
+.p1{
+    text-align: left;
+}
+
+.p3{
+    margin-top: 60px;
+}
+.sidebar{
+    padding-left:10px;
+    font-size: 14px;
+    flex-grow: 1;
+}
+.bodyWrap{
+    display: flex;
+    overflow: hidden;
+}
+
+.rightsidebar{
+    flex-basis:100px;
+}
+
+div.am-tab-bar-item{
+    height: auto;
+    background-color: #ccc;
+}
+
+div.am-card{
+    background: #f3f3f3;
+}

+ 73 - 0
src/case/shopApp/src/components/HomePage/Cards.jsx

@@ -0,0 +1,73 @@
+import React, { Component } from 'react';
+import { Link } from 'react-router-dom'
+import { Card, WingBlank, WhiteSpace } from 'antd-mobile';
+//import { Item } from 'antd-mobile/lib/tab-bar';
+import './Cards.css'
+
+
+
+
+class Cards extends Component{
+    constructor(props){
+        //console.log('111',props)
+        super(props)
+        this.stae={
+            product_id:''
+        }
+    }
+    //点击后跳转到商品详情页面
+    onClickChange(e,id){
+        console.log('product_id',id)
+    }
+    
+    render(){
+        //console.log(this.props.products)
+        const Cardss=this.props.products.map((item,index)=>{
+            //console.log(item)
+            return (
+                <WingBlank size="lg" key={index} className="Card">
+                    <WhiteSpace size="lg" />
+                        <Link to={"/detail?product_id="+item.id}>
+                            <Card onClick={(e)=>{this.onClickChange(e,item.id)}}>
+                                <Card.Header
+                                    title={<span className="title">{item.name}</span>}
+                                    extra={<span className="hot">热门</span>} 
+                                />
+                                <Card.Body>
+                                    <div className="bodyWrap">
+                                        <div className="imgWrap">
+                                            <img src={item.img} alt="xxx" height="100px" width="100px"/>
+                                        </div>
+                                        <div className="sidebar">
+                                            <p className="p1">{item.intro}</p>
+                                        </div>
+                                        <div className="rightsidebar">
+                                            <p className="p2">{item.price}/斤</p>
+                                            <p className="p3">库存:{item.stock}</p>
+                                        </div>
+                                    </div>
+                                </Card.Body>
+                                <Card.Footer content="" extra={<div></div>} />
+                            </Card>
+                        </Link>
+                    <WhiteSpace size="lg" />
+                </WingBlank>
+            )
+        })
+
+        return (
+            <div>
+               {Cardss}
+            </div>
+        )
+    }
+}
+export default Cards
+
+
+
+
+
+
+
+

+ 79 - 0
src/case/shopApp/src/components/HomePage/HomePage.jsx

@@ -0,0 +1,79 @@
+import React, { Component } from 'react';
+
+import Search from './Search'
+import TabBarTop from './TabBarTop'
+import Cards from './Cards'
+
+import {graphqls} from '../../api/graphql_request'
+import {getProductByProps} from '../../api/graphql/product'
+
+
+
+class HomePage extends Component{
+    constructor(props){
+        super(props)
+        this.state={
+            tabs:[],
+            products:[],
+            select:'所有果品'
+        }
+    }
+
+    componentDidMount () {
+        //console.log('tets')
+        this.getGoods()
+    }
+    //获取所有商品
+    getGoods(variables={}){
+        return graphqls(getProductByProps,variables).then((data)=>{
+        //console.log("data",data.productbyprops)
+        let products=data.productbyprops
+        let arr=products.map((item)=>{
+          return item.category
+        })
+  
+        arr = Array.from(new Set(arr))
+  
+        let tabs=arr.map((item)=>{
+          return {title:item}
+        })
+      
+        this.setState({
+          tabs:[{title: '所有果品'},...tabs],
+          products:products,
+          select:'所有果品'
+        })
+        sessionStorage.setItem("products",JSON.stringify(products))
+        })
+    }
+
+    tabChange(e){
+        let category=e.title,
+            products = JSON.parse(sessionStorage.getItem("products"));
+        if(category==='所有果品'){
+          this.setState({
+            products:products
+          })
+        }else{
+          let arr =products.filter((item)=>{
+            return item.category===category
+          })
+          this.setState({
+            products:arr
+          })
+        } 
+    }
+
+
+    render(){
+        return (
+            <div>
+                <Search getProductByName={this.getGoods.bind(this)}/>
+                <TabBarTop tabs={this.state.tabs} tabChange={this.tabChange.bind(this)}/>
+                <Cards products={this.state.products||[]}/>
+            </div>
+        )
+    }
+}
+
+export default HomePage

+ 42 - 0
src/case/shopApp/src/components/HomePage/Search.jsx

@@ -0,0 +1,42 @@
+import React, { Component } from 'react';
+import { SearchBar } from 'antd-mobile';
+
+class Search extends Component {
+  constructor(props){
+    super(props)
+    this.state={
+      value:''
+    }
+  }
+  componentDidMount() {
+    //this.autoFocusInst.focus();
+    //console.log(this.props.getProductByName)
+  }
+  onChange= (value) => {
+    this.setState({ value });
+    console.log(value)
+  };
+  clear = () => {
+    this.setState({ value: '' });
+  };
+  handleClick = () => {
+    this.manualFocusInst.focus();
+  }
+  render() {
+    return (<div>
+      <SearchBar
+        value={this.state.value}
+        placeholder="请输入要搜索的商品名"
+        onSubmit={value => this.props.getProductByName({name:value})}
+        onClear={value => console.log(value, 'onClear')}
+        onFocus={() => console.log('onFocus')}
+        onBlur={() => console.log('onBlur')}
+        onCancel={() => {this.props.getProductByName({}) ;this.clear()}}
+        showCancelButton
+        onChange={this.onChange}
+      />
+    </div>);
+  }
+}
+
+export default Search

+ 24 - 0
src/case/shopApp/src/components/HomePage/TabBarTop.jsx

@@ -0,0 +1,24 @@
+import React, { Component } from 'react';
+
+import { Tabs, WhiteSpace } from 'antd-mobile';
+
+
+
+
+
+class TabBarTop extends Component {
+    render() {
+      //console.log('this.state.products',this.state.products)
+      return (
+        <div>
+          <WhiteSpace />
+            <Tabs onChange={e=>this.props.tabChange(e)} tabs={this.props.tabs} renderTabBar={props => <Tabs.DefaultTabBar {...props} page={4} />}>
+            </Tabs>
+          <WhiteSpace />
+        </div>
+      );
+    }
+  }
+
+  export default TabBarTop
+

+ 21 - 0
src/case/shopApp/src/components/ShopCarPage/shopCar.jsx

@@ -0,0 +1,21 @@
+import React, { Component } from 'react';
+
+class ShopCar extends Component{
+    constructor(props){
+        super(props)
+        this.state={
+
+        }
+    }
+
+    render(){
+        return(
+            <div>ShopCar</div>
+        )
+    }
+}
+
+
+
+
+export default ShopCar

+ 18 - 0
src/case/shopApp/src/components/UserPage/userPage.jsx

@@ -0,0 +1,18 @@
+import React, { Component } from 'react';
+
+class UserPage extends Component{
+    constructor(props){
+        super(props)
+        this.state={
+
+        }
+    }
+
+    render(){
+        return(
+            <div>UserPage</div>
+        )
+    }
+}
+
+export default UserPage

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
src/case/shopApp/src/images/goods.svg


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
src/case/shopApp/src/images/goods_select.svg


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
src/case/shopApp/src/images/shopcar.svg


A diferenza do arquivo foi suprimida porque é demasiado grande
+ 0 - 0
src/case/shopApp/src/images/shopcar_select.svg


+ 1 - 0
src/case/shopApp/src/images/user.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1543305670471" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4005" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M511.47776 959.86688c-247.40864 0-448.6656-201.25184-448.6656-448.6656 0-247.36256 201.25696-448.6656 448.6656-448.6656 247.41376 0 448.61952 201.30304 448.61952 448.6656 0 247.41376-201.20576 448.6656-448.6144 448.6656z m0-851.072c-221.92128 0-402.40128 180.5312-402.40128 402.4064s180.48 402.4064 402.40128 402.4064c221.8752 0 402.36032-180.5312 402.36032-402.4064s-180.48512-402.4064-402.36032-402.4064z m0 484.64384c-99.64544 0-180.73088-81.08032-180.73088-180.73088s81.08544-180.736 180.736-180.736c99.64544 0 180.72576 81.08544 180.72576 180.736 0 99.65056-81.08032 180.73088-180.73088 180.73088z m0-315.19744c-74.15808 0-134.46656 60.30848-134.46656 134.46656s60.3136 134.47168 134.46656 134.47168c74.1632 0 134.47168-60.3136 134.47168-134.47168s-60.3136-134.46656-134.47168-134.46656z m225.29024 487.64928a23.168 23.168 0 0 1-22.03136-16.15872c-28.29824-88.76032-109.9776-148.41856-203.25888-148.41856-87.7056 0-167.7312 54.99392-199.18848 136.832a23.02976 23.02976 0 0 1-29.85472 13.29152 23.0912 23.0912 0 0 1-13.30176-29.8496c38.23616-99.59936 135.6288-166.53312 242.35008-166.53312 113.44384 0 212.89472 72.6528 247.31648 180.6336a23.12704 23.12704 0 0 1-15.0016 29.10208 24.8064 24.8064 0 0 1-7.02976 1.09568z" p-id="4006" fill="#707070"></path></svg>

+ 1 - 0
src/case/shopApp/src/images/user_select.svg

@@ -0,0 +1 @@
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1543305670471" class="icon" style="" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4005" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><defs><style type="text/css"></style></defs><path d="M511.47776 959.86688c-247.40864 0-448.6656-201.25184-448.6656-448.6656 0-247.36256 201.25696-448.6656 448.6656-448.6656 247.41376 0 448.61952 201.30304 448.61952 448.6656 0 247.41376-201.20576 448.6656-448.6144 448.6656z m0-851.072c-221.92128 0-402.40128 180.5312-402.40128 402.4064s180.48 402.4064 402.40128 402.4064c221.8752 0 402.36032-180.5312 402.36032-402.4064s-180.48512-402.4064-402.36032-402.4064z m0 484.64384c-99.64544 0-180.73088-81.08032-180.73088-180.73088s81.08544-180.736 180.736-180.736c99.64544 0 180.72576 81.08544 180.72576 180.736 0 99.65056-81.08032 180.73088-180.73088 180.73088z m0-315.19744c-74.15808 0-134.46656 60.30848-134.46656 134.46656s60.3136 134.47168 134.46656 134.47168c74.1632 0 134.47168-60.3136 134.47168-134.47168s-60.3136-134.46656-134.47168-134.46656z m225.29024 487.64928a23.168 23.168 0 0 1-22.03136-16.15872c-28.29824-88.76032-109.9776-148.41856-203.25888-148.41856-87.7056 0-167.7312 54.99392-199.18848 136.832a23.02976 23.02976 0 0 1-29.85472 13.29152 23.0912 23.0912 0 0 1-13.30176-29.8496c38.23616-99.59936 135.6288-166.53312 242.35008-166.53312 113.44384 0 212.89472 72.6528 247.31648 180.6336a23.12704 23.12704 0 0 1-15.0016 29.10208 24.8064 24.8064 0 0 1-7.02976 1.09568z" p-id="4006" fill="#1296db"></path></svg>

+ 14 - 0
src/case/shopApp/src/index.css

@@ -0,0 +1,14 @@
+body {
+  margin: 0;
+  padding: 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;
+}

+ 34 - 0
src/case/shopApp/src/index.js

@@ -0,0 +1,34 @@
+import React, { Component } from 'react';
+import ReactDOM from 'react-dom';
+import { BrowserRouter as Router, Switch, Route} from 'react-router-dom';
+
+
+import './index.css';
+import App from './App';
+import * as serviceWorker from './serviceWorker';
+//import { Button } from 'antd-mobile';
+
+
+class MainApp extends Component{
+        render(){
+            return(
+                <Router>
+                    <Switch>
+                        <Route exact path="/" render={() => {
+                            return <App />;
+                        }}/>
+                    </Switch>
+                </Router>
+            )
+        }
+    }
+
+
+ReactDOM.render(<MainApp />, document.getElementById('root'));
+
+// If you want your app to work offline and load faster, you can change
+// unregister() to register() below. Note this comes with some pitfalls.
+// Learn more about service workers: http://bit.ly/CRA-PWA
+serviceWorker.unregister();
+
+

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 2 - 0
src/case/shopApp/src/logo.svg


+ 135 - 0
src/case/shopApp/src/serviceWorker.js

@@ -0,0 +1,135 @@
+// This optional code is used to register a service worker.
+// register() is not called by default.
+
+// 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 subsequent visits to a page, after all the
+// existing tabs open on the page have been closed, since previously cached
+// resources are updated in the background.
+
+// To learn more about the benefits of this model and instructions on how to
+// opt-in, read http://bit.ly/CRA-PWA
+
+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 function register(config) {
+  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.href);
+    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/facebook/create-react-app/issues/2374
+      return;
+    }
+
+    window.addEventListener('load', () => {
+      const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;
+
+      if (isLocalhost) {
+        // This is running on localhost. Let's check if a service worker still exists or not.
+        checkValidServiceWorker(swUrl, config);
+
+        // Add some additional logging to localhost, pointing developers to the
+        // service worker/PWA documentation.
+        navigator.serviceWorker.ready.then(() => {
+          console.log(
+            'This web app is being served cache-first by a service ' +
+              'worker. To learn more, visit http://bit.ly/CRA-PWA'
+          );
+        });
+      } else {
+        // Is not localhost. Just register service worker
+        registerValidSW(swUrl, config);
+      }
+    });
+  }
+}
+
+function registerValidSW(swUrl, config) {
+  navigator.serviceWorker
+    .register(swUrl)
+    .then(registration => {
+      registration.onupdatefound = () => {
+        const installingWorker = registration.installing;
+        if (installingWorker == null) {
+          return;
+        }
+        installingWorker.onstatechange = () => {
+          if (installingWorker.state === 'installed') {
+            if (navigator.serviceWorker.controller) {
+              // At this point, the updated precached content has been fetched,
+              // but the previous service worker will still serve the older
+              // content until all client tabs are closed.
+              console.log(
+                'New content is available and will be used when all ' +
+                  'tabs for this page are closed. See http://bit.ly/CRA-PWA.'
+              );
+
+              // Execute callback
+              if (config && config.onUpdate) {
+                config.onUpdate(registration);
+              }
+            } 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.');
+
+              // Execute callback
+              if (config && config.onSuccess) {
+                config.onSuccess(registration);
+              }
+            }
+          }
+        };
+      };
+    })
+    .catch(error => {
+      console.error('Error during service worker registration:', error);
+    });
+}
+
+function checkValidServiceWorker(swUrl, config) {
+  // 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.
+      const contentType = response.headers.get('content-type');
+      if (
+        response.status === 404 ||
+        (contentType != null && contentType.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, config);
+      }
+    })
+    .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();
+    });
+  }
+}

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio