-
Notifications
You must be signed in to change notification settings - Fork 1
/
d2e01fa0.d060bfb9.js
1 lines (1 loc) · 47.8 KB
/
d2e01fa0.d060bfb9.js
1
(window.webpackJsonp=window.webpackJsonp||[]).push([[34],{102:function(e,t,n){"use strict";n.r(t),n.d(t,"frontMatter",(function(){return i})),n.d(t,"metadata",(function(){return s})),n.d(t,"rightToc",(function(){return c})),n.d(t,"default",(function(){return u}));var a=n(3),o=n(8),r=(n(0),n(111)),i={id:"amplify-04",title:"DataStore - CRUD (Create Read Update Delete)",sidebar_label:"DataStore - CRUD"},s={unversionedId:"amplify-04",id:"amplify-04",isDocsHomePage:!1,title:"DataStore - CRUD (Create Read Update Delete)",description:"The line between the backend and the frontend is broken! An innovative step in the evolution of state managers.",source:"@site/docs/amplify04.md",slug:"/amplify-04",permalink:"/docs/amplify-04",editUrl:"https://github.com/facebook/docusaurus/edit/master/website/docs/amplify04.md",version:"current",sidebar_label:"DataStore - CRUD",sidebar:"someSidebar",previous:{title:"Amplify API - AppSync - CRUD (Create Read Update Delete)",permalink:"/docs/amplify-03"},next:{title:"Push Notification with Amplify",permalink:"/docs/notif-00"}},c=[{value:"Advantages of AWS Amplify DataStore over Redux, MobX, Apollo, Relay, selectors:",id:"advantages-of-aws-amplify-datastore-over-redux-mobx-apollo-relay-selectors",children:[]},{value:"1. Real time out of the box.",id:"1-real-time-out-of-the-box",children:[]},{value:"2. Code generation.",id:"2-code-generation",children:[]},{value:"3. Offline data & cloud sync",id:"3-offline-data--cloud-sync",children:[]},{value:"How much does it all cost?",id:"how-much-does-it-all-cost",children:[]},{value:"Clone the repository",id:"clone-the-repository",children:[]},{value:"Register your AWS account",id:"register-your-aws-account",children:[]},{value:"Initializing AWS Amplify in a React Native Project",id:"initializing-aws-amplify-in-a-react-native-project",children:[]},{value:"Connect the authentication plugin",id:"connect-the-authentication-plugin",children:[]},{value:"Installing dependencies",id:"installing-dependencies",children:[]},{value:"Connecting the API plugin (App Sync)",id:"connecting-the-api-plugin-app-sync",children:[]},{value:"Model generation",id:"model-generation",children:[]},{value:"Updating API",id:"updating-api",children:[]},{value:"READ",id:"read",children:[]},{value:"CREATE UPDATE DELETE",id:"create-update-delete",children:[]},{value:"Navigation",id:"navigation",children:[]},{value:"Jobs Button",id:"jobs-button",children:[]},{value:"Done \u2705",id:"done-",children:[]},{value:"References:",id:"references",children:[]}],l={rightToc:c};function u(e){var t=e.components,i=Object(o.a)(e,["components"]);return Object(r.b)("wrapper",Object(a.a)({},l,i,{components:t,mdxType:"MDXLayout"}),Object(r.b)("p",null,"The line between the backend and the frontend is broken! An innovative step in the evolution of state managers."),Object(r.b)("h1",{id:"goodbye-redux-mobx-apollo"},"Goodbye Redux, MobX, Apollo!"),Object(r.b)("p",null,Object(r.b)("a",Object(a.a)({parentName:"p"},{href:"https://youtu.be/rKTHKZ87Hh4"}),Object(r.b)("img",{alt:"AWS Amplify",src:n(276).default}))),Object(r.b)("p",null,"One of the most difficult tasks in developing web and mobile applications is to synchronize data between devices and perform offline operations. Ideally, when the device is offline, your customers should be able to continue to use your application not only to access data, but also to create and modify it. When the device returns online, the application must reconnect to the backend, synchronize the data and resolve conflicts, if any. Correct handling of all extreme cases requires a lot of undifferentiated code, even when using the AWS AppSync SDK cache on a device with autonomous mutations and delta synchronization."),Object(r.b)("p",null,"Amplify DataStore provides persistent storage on the device for recording, reading and monitoring data changes if you are connected to the Internet or offline, and also makes it easy to synchronize data with the cloud and between devices."),Object(r.b)("p",null,"Amplify DataStore allows developers to write applications using distributed data without writing additional code for an offline or online script."),Object(r.b)("p",null,"You can use the Amplify DataStore for offline use in local-only mode without an AWS account or provide the entire backend using AWS AppSync and Amazon DynamoDB."),Object(r.b)("p",null,"The DataStore includes Delta Sync using your GraphQL backend and several conflict resolution strategies."),Object(r.b)("h2",{id:"advantages-of-aws-amplify-datastore-over-redux-mobx-apollo-relay-selectors"},"Advantages of AWS Amplify DataStore over Redux, MobX, Apollo, Relay, selectors:"),Object(r.b)("p",null,"Comparing AWS Amplify with Redux, MobX is not correct, since AWS Amplify is not only a state manager, but also a client-server, so in the client-server class we will compare it with Apollo and Relay."),Object(r.b)("h2",{id:"1-real-time-out-of-the-box"},"1. Real time out of the box."),Object(r.b)("p",null,"I don\u2019t think that a business can be considered serious if his mobile application is not affected by subscription events implemented using web sockets technology.\nAnd how many applications nowadays work on web sockets?\nI think not, due to the fact that real time is an additional work of developers on the back and front-end.\nFor us, ",Object(r.b)("a",Object(a.a)({parentName:"p"},{href:"https://fullstackserverless.github.io/docs/amplify-01"}),"fullStack serverless")," developers on AWS Amplify, real time goes out of the box, both on the front and on the back and we don\u2019t we need to write an implementation code for integrating web sockets for each model, since it is generated automatically, as well as writing documentation for all of our generated code, implemented in our project based on the GraphQL schema instruction. In order not to scare with big words, I will show you an example from ",Object(r.b)("a",Object(a.a)({parentName:"p"},{href:"https://fullstackserverless.github.io/docs/amplify-03"}),"the last lesson"),", how Store is defined in AWS Amplify:"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-graphql"}),'type Job @model @auth(rules: [{ allow: owner, ownerField: "owner", operations: [create, update, delete] }]) {\n id: ID!\n position: String!\n rate: String!\n description: String!\n owner: String\n}\n')),Object(r.b)("p",null,"This determines the model in the store, not only for the frontend, but also for the backend. One source of truth for frontend and backend. Yes, yes, I see that I will repeat it more than once in my life, since this is a killer feature and punch line vs Redux, MobX, Apollo, Relay."),Object(r.b)("p",null,"It is this architecture, which is different from Redux, MobX, Apollo, that erases the line between the backend and frontend. And puts AWS Amplify DataStore over everyone"),Object(r.b)("p",null,"If you are from the backend, then you no longer need to write resolvers to the database and drag subscriptions to each data model."),Object(r.b)("p",null,"Serverless - this is when the backend developers came to learn the frontend, as their services are needed exclusively for projects that do not keep up with the times, and from which they do not live real time."),Object(r.b)("h2",{id:"2-code-generation"},"2. Code generation."),Object(r.b)("p",null,"What is code generation you can read without me on Wikipedia, unless of course you know its meaning, which in this punch reminds us of yourself.\nUse fetch or axios?\nBy sending requests to the deep forest API, which we also write in conjunction with Redux, MobX, Apollo, Relay.\nSo here is another news of the day!\nYou no longer need to write these API calls, you only need to call them.\nThis means that you no longer need to create this rather big daddy with the server request code, since in AWS Amplify DataStore they are also generated in your project based on your store, defined by the very same GraphQL diagram of their first item. And this is filled with one command:"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-bash"}),"amplify codegen model\n")),Object(r.b)("p",null,"As a result, we get the models folder with the generated code."),Object(r.b)("p",null,Object(r.b)("img",{alt:"DataStore",src:n(277).default})),Object(r.b)("p",null,"And the graphql folder after pushing to the server, with all the request in Flow, TS or vanilla JavaScript."),Object(r.b)("p",null,Object(r.b)("img",{alt:"DataStore",src:n(278).default})),Object(r.b)("h2",{id:"3-offline-data--cloud-sync"},"3. Offline data & cloud sync"),Object(r.b)("p",null,"No need to write additional code to send a request to the server after the application is online.\nSometimes you find yourself in an unreliable situation, but you better wait longer than obviously fail the operation.\nApollo has apollo-link-retry which provides exponential rollback and server requests between default attempts. True, he (currently) does not handle retries for GraphQL errors in the response, only for network errors.\nRedux, MobX, of course, does not have this solution under the hood, since they are not clients and you have to use third-party middleware, because REST is like a retired grandfather with the support of any grandchildren. Detailed analysis of ",Object(r.b)("a",Object(a.a)({parentName:"p"},{href:"https://fullstackserverless.github.io/docs/amplify-02"}),"GraphQL vs REST"),".\nAWS Amplify DataStore has not only an analog of apollo-link-retry, but also a built-in and customizable familiar programming model with automatic version control, conflict detection and resolution in the cloud."),Object(r.b)("p",null,"Among the disadvantages of AWS Amplify, I want to mention that Apollo hooks with its loading and error out of the box reduce the amount of code written on the front."),Object(r.b)("p",null,Object(r.b)("a",Object(a.a)({parentName:"p"},{href:"https://aws-amplify.github.io/docs/js/datastore"}),"Official documentation")),Object(r.b)("p",null,"At the end of this lesson we will collect with you this mobile application using the Amplify DataStore:"),Object(r.b)("p",null,Object(r.b)("img",{alt:"dataStore",src:n(279).default})),Object(r.b)("h2",{id:"how-much-does-it-all-cost"},"How much does it all cost?"),Object(r.b)("p",null,"With AWS AppSync, you pay only for what you use with no minimum fees or mandatory service usage. You are billed separately for query and data modification operations, and for performing real-time updates on your data. This provides you with transparency and a low price regardless of your workload type, because you only pay for the specific AWS AppSync features you use."),Object(r.b)("p",null,"Query and Data Modification Operations"),Object(r.b)("p",null,"Query Operations enable your app to fetch data and cache it locally. Data Modification Operations enable your app to create, update, and delete data."),Object(r.b)("p",null,"4.00 dollars per million Query and Data Modification Operations","*"),Object(r.b)("p",null,Object(r.b)("a",Object(a.a)({parentName:"p"},{href:"https://aws.amazon.com/appsync/pricing/"}),"Details")),Object(r.b)("h1",{id:"go"},"Go!"),Object(r.b)("p",null,"Our AWS Amplify support chat ",Object(r.b)("a",Object(a.a)({parentName:"p"},{href:"https://discord.gg/Ntuttww"}),"Discord")),Object(r.b)("p",null,"The final code for this part can be found on ",Object(r.b)("a",Object(a.a)({parentName:"p"},{href:"https://github.com/fullstackserverless/startup/tree/datastore"}),"Github"),"."),Object(r.b)("p",null,Object(r.b)("img",{alt:"Step01",src:n(116).default})),Object(r.b)("h2",{id:"clone-the-repository"},"Clone the repository"),Object(r.b)("p",null,"If you continue the last lesson, you can go directly to step 5."),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-bash"}),"git clone https://github.com/fullstackserverless/startup.git\n")),Object(r.b)("p",null,"Go to the project folder"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-bash"}),"cd startup\n")),Object(r.b)("p",null,"Install dependencies"),Object(r.b)("p",null,Object(r.b)("inlineCode",{parentName:"p"},"yarn")),Object(r.b)("p",null,"or"),Object(r.b)("p",null,Object(r.b)("inlineCode",{parentName:"p"},"npm install")),Object(r.b)("p",null,Object(r.b)("img",{alt:"Step02",src:n(117).default})),Object(r.b)("h2",{id:"register-your-aws-account"},"Register your AWS account"),Object(r.b)("p",null,"Step For Those Not Yet AWS Registered\nWe register according to ",Object(r.b)("a",Object(a.a)({parentName:"p"},{href:"https://portal.aws.amazon.com/billing/signup?redirect_url=https%3A%2F%2Faws.amazon.com%2Fregistration-confirmation#/start"}),"this")," instructions \ud83d\udcc3 and by the video tutorial \u0435\u043c we check all 5 steps."),Object(r.b)("div",{class:"alert alert--warning",role:"alert"},"You need a bank card \ud83d\udcb3, where should be more than 1$ \ud83d\udcb5 There we look and put the Amplify Command Line Interface (CLI)"),Object(r.b)("p",null,Object(r.b)("img",{alt:"Step03",src:n(120).default})),Object(r.b)("h2",{id:"initializing-aws-amplify-in-a-react-native-project"},"Initializing AWS Amplify in a React Native Project"),Object(r.b)("p",null,"Initialize our AWS Amplify project in the root directory of the React Native project."),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-bash"}),"amplify init\n")),Object(r.b)("p",null,"We answer the questions:\n",Object(r.b)("img",{alt:"amplify init",src:n(135).default})),Object(r.b)("p",null,"The project was initialized \ud83d\ude80"),Object(r.b)("p",null,Object(r.b)("img",{alt:"Step04",src:n(121).default})),Object(r.b)("h2",{id:"connect-the-authentication-plugin"},"Connect the authentication plugin"),Object(r.b)("p",null,"Now that the application is in the cloud, you can add some features, such as allowing users to register with our application and log in."),Object(r.b)("p",null,"We connect the authentication function."),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-bash"}),"amplify add auth\n")),Object(r.b)("p",null,Object(r.b)("img",{alt:"amplify init",src:n(136).default})),Object(r.b)("p",null,"Submitting changes to the cloud \ud83d\udcad"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-bash"}),"amplify push\n")),Object(r.b)("p",null,"\u2714 All resources are updated in the cloud"),Object(r.b)("p",null,"We collect the project and check the operation of authentication."),Object(r.b)("p",null,Object(r.b)("img",{alt:"Hello screen",src:n(158).default})),Object(r.b)("p",null,Object(r.b)("img",{alt:"Step05",src:n(122).default})),Object(r.b)("h2",{id:"installing-dependencies"},"Installing dependencies"),Object(r.b)("p",null,"Detailed installation ",Object(r.b)("a",Object(a.a)({parentName:"p"},{href:"https://aws-amplify.github.io/docs/js/datastore#setup"}),"here")),Object(r.b)("p",null,"If you have a React Native Cli, then"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-bash"}),"yarn add @aws-amplify/datastore @react-native-community/netinfo @react-native-community/async-storage\n")),Object(r.b)("p",null,"And if you use React Native> 0.60, then run the following command for iOS:"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-bash"}),"cd ios && pod install && cd ..\n")),Object(r.b)("p",null,Object(r.b)("img",{alt:"Step06",src:n(123).default})),Object(r.b)("h2",{id:"connecting-the-api-plugin-app-sync"},"Connecting the API plugin (App Sync)"),Object(r.b)("p",null,"If you connected it in ",Object(r.b)("a",Object(a.a)({parentName:"p"},{href:"https://fullstackserverless.github.io/docs/amplify-03"}),"the last lesson"),", then skip this step.\nIf not, connect the API plugin"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-bash"}),"amplify add api\n")),Object(r.b)("p",null,Object(r.b)("img",{alt:"AWSAmplify",src:n(160).default})),Object(r.b)("p",null,"After the selected items, the GraphQL schema will open in ",Object(r.b)("inlineCode",{parentName:"p"},"amplify/backend/api/<datasourcename>/schema.graphql")," where we insert this model:"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-graphql"}),'type Job @model @auth(rules: [{ allow: owner, ownerField: "owner", operations: [create, update, delete] }]) {\n id: ID!\n position: String!\n rate: String!\n description: String!\n owner: String\n}\n')),Object(r.b)("p",null,"More about ",Object(r.b)("a",Object(a.a)({parentName:"p"},{href:"https://fullstackserverless.github.io/docs/amplify-03#schemagraphql"}),"here")),Object(r.b)("p",null,Object(r.b)("img",{alt:"Step07",src:n(124).default})),Object(r.b)("h2",{id:"model-generation"},"Model generation"),Object(r.b)("p",null,"Modeling your data and creating the models used by the DataStore is the first step to getting started. GraphQL is used as a common language for JavaScript, iOS and Android for this process, and is also used as a network protocol when synchronizing with the cloud. GraphQL also supports some features, such as Automerge in AppSync."),Object(r.b)("blockquote",null,Object(r.b)("p",{parentName:"blockquote"},"You do not need an AWS account to run it and use DataStore locally, however, if you want to synchronize with the cloud, it is recommended to install and configure Amplify CLI as in the last lesson")),Object(r.b)("p",null,"Since we described the circuit in the last lesson, now it\u2019s enough for us to run the command"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-bash"}),"amplify codegen model\n")),Object(r.b)("p",null,"and get the generated model in the src/models folder"),Object(r.b)("p",null,Object(r.b)("img",{alt:"Step08",src:n(129).default})),Object(r.b)("h2",{id:"updating-api"},"Updating API"),Object(r.b)("p",null,"We include DataStore for all API"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-bash"}),"amplify update api\n")),Object(r.b)("p",null,Object(r.b)("img",{alt:"amplify update api",src:n(280).default})),Object(r.b)("p",null,"Submitting changes to the cloud \ud83d\udcad"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-bash"}),"amplify push\n")),Object(r.b)("p",null,"\u2714 All resources are updated in the cloud"),Object(r.b)("p",null,Object(r.b)("img",{alt:"Step09",src:n(130).default})),Object(r.b)("h2",{id:"read"},"READ"),Object(r.b)("p",null,"Create the JobsMain src/screens/Jobs/JobsMain.js screen"),Object(r.b)("p",null,Object(r.b)("img",{alt:"READ",src:n(281).default})),Object(r.b)("p",null,"On this screen, we will make a Query query, with the pagination option, where the number is through the useQuery hook and it will return an array to us, which we will send to Flatlist."),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-jsx"}),"import React, { useEffect, useState } from 'react'\nimport { FlatList } from 'react-native'\nimport { Auth } from 'aws-amplify'\nimport { AppContainer, CardVacancies, Space, Header } from 'react-native-unicorn-uikit'\nimport { DataStore } from '@aws-amplify/datastore'\nimport { Job } from '../../models'\nimport { goBack, onScreen } from '../../constants'\n\nconst JobsMain = ({ navigation }) => {\n const [data, updateJobs] = useState([])\n\n const fetchJobs = async () => {\n const mess = await DataStore.query(Job)\n updateJobs(mess)\n }\n\n useEffect(() => {\n fetchJobs()\n const subscription = DataStore.observe(Job).subscribe(() => fetchJobs())\n return () => {\n subscription.unsubscribe()\n }\n }, [data])\n\n const _renderItem = ({ item }) => {\n const owner = Auth.user.attributes.sub\n const check = owner === item.owner\n return (\n <>\n <CardVacancies obj={item} onPress={onScreen(check ? 'JOB_ADD' : 'JOB_DETAIL', navigation, item)} />\n <Space height={20} />\n </>\n )\n }\n\n const _keyExtractor = obj => obj.id.toString()\n\n return (\n <AppContainer onPress={goBack(navigation)} flatlist>\n <FlatList\n scrollEventThrottle={16}\n data={data}\n renderItem={_renderItem}\n keyExtractor={_keyExtractor}\n onEndReachedThreshold={0.5}\n ListHeaderComponent={\n <Header\n onPress={goBack(navigation)}\n onPressRight={onScreen('JOB_ADD', navigation)}\n iconLeft=\"angle-dobule-left\"\n iconRight=\"plus-a\"\n />\n }\n stickyHeaderIndices={[0]}\n />\n </AppContainer>\n )\n}\n\nexport { JobsMain }\n")),Object(r.b)("p",null,"To disclose the details of the vacancy, create the screen JobDetail src/screens/Jobs/JobDetail.js"),Object(r.b)("p",null,Object(r.b)("img",{src:n(282).default})),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-jsx"}),"import React from 'react'\nimport { Platform } from 'react-native'\nimport { AppContainer, CardVacancies, Space, Header } from 'react-native-unicorn-uikit'\nimport { goBack } from '../../constants'\n\nconst JobDetail = ({ route, navigation }) => {\n return (\n <AppContainer>\n <Header onPress={goBack(navigation)} iconLeft=\"angle-dobule-left\" />\n <CardVacancies obj={route.params} detail />\n <Space height={Platform.OS === 'ios' ? 100 : 30} />\n </AppContainer>\n )\n}\n\nexport { JobDetail }\n")),Object(r.b)("p",null,Object(r.b)("img",{alt:"Step10",src:n(137).default})),Object(r.b)("h2",{id:"create-update-delete"},"CREATE UPDATE DELETE"),Object(r.b)("p",null,"Create the screen JobAdd src/screens/Jobs/JobAdd.js, where we perform the functions CREATE UPDATE DELETE"),Object(r.b)("p",null,Object(r.b)("img",{src:n(283).default})),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-jsx"}),"import React, { useState, useEffect, useRef } from 'react'\nimport { AppContainer, Input, Space, Button, Header, ButtonLink } from 'react-native-unicorn-uikit'\nimport { DataStore } from '@aws-amplify/datastore'\nimport { Formik } from 'formik'\nimport * as Yup from 'yup'\nimport { Job } from '../../models'\nimport { goBack } from '../../constants'\n\nconst JobAdd = ({ route, navigation }) => {\n const [loading, setLoading] = useState(false)\n const [check, setOwner] = useState(false)\n const [error, setError] = useState('')\n\n const [input, setJob] = useState({\n id: '',\n position: '',\n rate: '',\n description: ''\n })\n\n const formikRef = useRef()\n\n useEffect(() => {\n const obj = route.params\n if (typeof obj !== 'undefined') {\n setOwner(true)\n setJob(obj)\n const { setFieldValue } = formikRef.current\n const { position, rate, description } = obj\n setFieldValue('position', position)\n setFieldValue('rate', rate)\n setFieldValue('description', description)\n }\n }, [route.params])\n\n const createJob = async values => (await DataStore.save(new Job({ ...values }))) && goBack(navigation)()\n\n const updateJob = async ({ position, rate, description }) => {\n try {\n setLoading(true)\n const original = await DataStore.query(Job, input.id)\n const update = await DataStore.save(\n Job.copyOf(original, updated => {\n updated.position = position\n updated.rate = rate\n updated.description = description\n })\n )\n update && goBack(navigation)()\n setLoading(false)\n } catch (err) {\n setError(err)\n }\n }\n\n const deleteJob = async () => {\n try {\n setLoading(true)\n const job = await DataStore.query(Job, input.id)\n const del = await DataStore.delete(job)\n del && goBack(navigation)()\n setLoading(false)\n } catch (err) {\n setError(err)\n }\n }\n\n return (\n <AppContainer onPress={goBack(navigation)} loading={loading} error={error}>\n <Header onPress={goBack(navigation)} iconLeft=\"angle-dobule-left\" />\n <Space height={20} />\n <Formik\n innerRef={formikRef}\n initialValues={input}\n onSubmit={values => (check ? updateJob(values) : createJob(values))}\n validationSchema={Yup.object().shape({\n position: Yup.string()\n .min(3)\n .required(),\n rate: Yup.string()\n .min(3)\n .required(),\n description: Yup.string()\n .min(3)\n .required()\n })}\n >\n {({ values, handleChange, errors, setFieldTouched, touched, isValid, handleSubmit }) => (\n <>\n <Input\n name=\"position\"\n value={values.position}\n onChangeText={handleChange('position')}\n onBlur={() => setFieldTouched('position')}\n placeholder=\"Position\"\n touched={touched}\n errors={errors}\n />\n <Input\n name=\"rate\"\n keyboardType=\"numeric\"\n value={`${values.rate}`}\n onChangeText={handleChange('rate')}\n onBlur={() => setFieldTouched('rate')}\n placeholder=\"Rate\"\n touched={touched}\n errors={errors}\n />\n <Input\n name=\"description\"\n value={values.description}\n onChangeText={handleChange('description')}\n onBlur={() => setFieldTouched('description')}\n placeholder=\"Description\"\n touched={touched}\n errors={errors}\n multiline\n numberOfLines={5}\n />\n <Space height={40} />\n <Button title={check ? 'Update' : 'Create'} disabled={!isValid} onPress={handleSubmit} formik />\n {check && (\n <>\n <Space height={10} />\n <ButtonLink title=\"or\" textStyle={{ alignSelf: 'center' }} />\n <Space height={15} />\n <Button title=\"DELETE\" onPress={deleteJob} cancel />\n </>\n )}\n </>\n )}\n </Formik>\n <Space height={100} />\n </AppContainer>\n )\n}\n\nexport { JobAdd }\n")),Object(r.b)("p",null,"and in screens/Jobs/index.js we export screens"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-jsx"}),"export * from './JobsMain'\nexport * from './JobDetail'\nexport * from './JobAdd'\n")),Object(r.b)("p",null,Object(r.b)("img",{alt:"Step11",src:n(138).default})),Object(r.b)("h2",{id:"navigation"},"Navigation"),Object(r.b)("p",null,"Add import of Jobs screens and connect them to StackNavigator"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-jsx"}),'import * as React from \'react\'\nimport { createStackNavigator } from \'@react-navigation/stack\'\nimport { enableScreens } from \'react-native-screens\' // eslint-disable-line\nimport { Hello, SignUp, SignIn, ConfirmSignUp, User, Forgot, ForgotPassSubmit } from \'./screens/Authenticator\'\nimport { JobsMain, JobDetail, JobAdd } from \'./screens/Jobs\'\n\nenableScreens()\n\nconst Stack = createStackNavigator()\n\nconst AppNavigator = () => {\n return (\n <Stack.Navigator\n screenOptions={{\n headerShown: false\n }}\n initialRouteName="HELLO"\n >\n <Stack.Screen name="HELLO" component={Hello} />\n <Stack.Screen name="SIGN_UP" component={SignUp} />\n <Stack.Screen name="SIGN_IN" component={SignIn} />\n <Stack.Screen name="FORGOT" component={Forgot} />\n <Stack.Screen name="FORGOT_PASSWORD_SUBMIT" component={ForgotPassSubmit} />\n <Stack.Screen name="CONFIRM_SIGN_UP" component={ConfirmSignUp} />\n <Stack.Screen name="USER" component={User} />\n <Stack.Screen name="JOBS_MAIN" component={JobsMain} />\n <Stack.Screen name="JOB_DETAIL" component={JobDetail} />\n <Stack.Screen name="JOB_ADD" component={JobAdd} />\n </Stack.Navigator>\n )\n}\n\nexport default AppNavigator\n')),Object(r.b)("p",null,Object(r.b)("img",{alt:"Step12",src:n(159).default})),Object(r.b)("h2",{id:"jobs-button"},"Jobs Button"),Object(r.b)("p",null,"Editing the User screen in screens/Authenticator/User/index.js"),Object(r.b)("pre",null,Object(r.b)("code",Object(a.a)({parentName:"pre"},{className:"language-jsx"}),"import React, { useState, useEffect } from 'react'\nimport { Auth } from 'aws-amplify'\nimport * as Keychain from 'react-native-keychain'\nimport { AppContainer, Button } from 'react-native-unicorn-uikit'\nimport { goHome, onScreen } from '../../../constants'\n\nconst User = ({ navigation }) => {\n const [loading, setLoading] = useState(false)\n const [error, setError] = useState('')\n\n useEffect(() => {\n const checkUser = async () => {\n await Auth.currentAuthenticatedUser()\n }\n checkUser()\n })\n\n const _onPress = async () => {\n setLoading(true)\n try {\n await Auth.signOut()\n await Keychain.resetInternetCredentials('auth')\n goHome(navigation)()\n } catch (err) {\n setError(err.message)\n }\n }\n\n const _onPressJob = () => onScreen('JOBS_MAIN', navigation)() // \u043f\u0435\u0440\u0435\u0445\u043e\u0434 \u043d\u0430 \u044d\u043a\u0440\u0430\u043d JOBS_MAIN\n\n return (\n <AppContainer message={error} loading={loading}>\n <Button title=\"Sign Out\" onPress={_onPress} />\n <Button title=\"Jobs\" onPress={_onPressJob} />\n </AppContainer>\n )\n}\n\nexport { User }\n")),Object(r.b)("p",null,"Build the application and test"),Object(r.b)("h2",{id:"done-"},"Done \u2705"),Object(r.b)("h2",{id:"references"},"References:"),Object(r.b)("p",null,Object(r.b)("a",Object(a.a)({parentName:"p"},{href:"https://aws-amplify.github.io"}),"https://aws-amplify.github.io")),Object(r.b)("p",null,Object(r.b)("a",Object(a.a)({parentName:"p"},{href:"https://learning.oreilly.com/library/view/full-stack-serverless/9781492059882/"}),"https://learning.oreilly.com/library/view/full-stack-serverless/9781492059882/")),Object(r.b)("p",null,Object(r.b)("a",Object(a.a)({parentName:"p"},{href:"https://www.altexsoft.com/blog/engineering/graphql-core-features-architecture-pros-and-cons/"}),"https://www.altexsoft.com/blog/engineering/graphql-core-features-architecture-pros-and-cons/")),Object(r.b)("p",null,Object(r.b)("a",Object(a.a)({parentName:"p"},{href:"https://engineering.fb.com/core-data/graphql-a-data-query-language/"}),"https://engineering.fb.com/core-data/graphql-a-data-query-language/")),Object(r.b)("p",null,Object(r.b)("a",Object(a.a)({parentName:"p"},{href:"https://graphql.org/learn"}),"https://graphql.org/learn")),Object(r.b)("p",null,Object(r.b)("a",Object(a.a)({parentName:"p"},{href:"https://www.patreon.com/bePatron?u=34467235"}),Object(r.b)("img",{alt:"Become a Patron!",src:n(112).default}))))}u.isMDXComponent=!0},111:function(e,t,n){"use strict";n.d(t,"a",(function(){return p})),n.d(t,"b",(function(){return h}));var a=n(0),o=n.n(a);function r(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function i(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);t&&(a=a.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),n.push.apply(n,a)}return n}function s(e){for(var t=1;t<arguments.length;t++){var n=null!=arguments[t]?arguments[t]:{};t%2?i(Object(n),!0).forEach((function(t){r(e,t,n[t])})):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(n)):i(Object(n)).forEach((function(t){Object.defineProperty(e,t,Object.getOwnPropertyDescriptor(n,t))}))}return e}function c(e,t){if(null==e)return{};var n,a,o=function(e,t){if(null==e)return{};var n,a,o={},r=Object.keys(e);for(a=0;a<r.length;a++)n=r[a],t.indexOf(n)>=0||(o[n]=e[n]);return o}(e,t);if(Object.getOwnPropertySymbols){var r=Object.getOwnPropertySymbols(e);for(a=0;a<r.length;a++)n=r[a],t.indexOf(n)>=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(o[n]=e[n])}return o}var l=o.a.createContext({}),u=function(e){var t=o.a.useContext(l),n=t;return e&&(n="function"==typeof e?e(t):s(s({},t),e)),n},p=function(e){var t=u(e.components);return o.a.createElement(l.Provider,{value:t},e.children)},d={inlineCode:"code",wrapper:function(e){var t=e.children;return o.a.createElement(o.a.Fragment,{},t)}},b=o.a.forwardRef((function(e,t){var n=e.components,a=e.mdxType,r=e.originalType,i=e.parentName,l=c(e,["components","mdxType","originalType","parentName"]),p=u(n),b=a,h=p["".concat(i,".").concat(b)]||p[b]||d[b]||r;return n?o.a.createElement(h,s(s({ref:t},l),{},{components:n})):o.a.createElement(h,s({ref:t},l))}));function h(e,t){var n=arguments,a=t&&t.mdxType;if("string"==typeof e||a){var r=n.length,i=new Array(r);i[0]=b;var s={};for(var c in t)hasOwnProperty.call(t,c)&&(s[c]=t[c]);s.originalType=e,s.mdxType="string"==typeof e?e:a,i[1]=s;for(var l=2;l<r;l++)i[l]=n[l];return o.a.createElement.apply(null,i)}return o.a.createElement.apply(null,n)}b.displayName="MDXCreateElement"},112:function(e,t,n){"use strict";n.r(t),t.default=n.p+"assets/images/patreon-15b4e66595efdb2e079faf18b89cff7c.png"},116:function(e,t,n){"use strict";n.r(t),t.default=n.p+"assets/images/01-a23cc15b10aa8903a2768742f2d5f639.png"},117:function(e,t,n){"use strict";n.r(t),t.default=n.p+"assets/images/02-d8f056a9ee77817d5fa34ed27b8a9ded.png"},120:function(e,t,n){"use strict";n.r(t),t.default=n.p+"assets/images/03-99e9f84b954c87f14c5b1c2a2fc7beb5.png"},121:function(e,t,n){"use strict";n.r(t),t.default=n.p+"assets/images/04-b7fa82403420155f5bc0c2e2b713251f.png"},122:function(e,t,n){"use strict";n.r(t),t.default=n.p+"assets/images/05-1c1a60851841e4476b56c3edf139208b.png"},123:function(e,t,n){"use strict";n.r(t),t.default=n.p+"assets/images/06-e6c67e52061de238f27f3c609644f4b9.png"},124:function(e,t,n){"use strict";n.r(t),t.default=n.p+"assets/images/07-8a3ce13813e6679ceb6d32560f619235.png"},129:function(e,t,n){"use strict";n.r(t),t.default=n.p+"assets/images/08-c284e2b885bb0393ec87b2e5af025826.png"},130:function(e,t,n){"use strict";n.r(t),t.default=n.p+"assets/images/09-e3185a977d8228e9551c978b4032cfeb.png"},135:function(e,t,n){"use strict";n.r(t),t.default=n.p+"assets/images/auth02-a6bbe130e5a203fb1094bf10025c251c.png"},136:function(e,t,n){"use strict";n.r(t),t.default=n.p+"assets/images/auth03-c26b5e57e8cf643cec8fddc2a31ad7d1.png"},137:function(e,t,n){"use strict";n.r(t),t.default=n.p+"assets/images/10-4f1052b7e740229f97d3918602f76c7b.png"},138:function(e,t,n){"use strict";n.r(t),t.default="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJYAAAC4CAYAAAF2oCUyAAAABGdBTUEAALGPC/xhBQAAAHhlWElmTU0AKgAAAAgABQESAAMAAAABAAEAAAEaAAUAAAABAAAASgEbAAUAAAABAAAAUgEoAAMAAAABAAIAAIdpAAQAAAABAAAAWgAAAAAAAABIAAAAAQAAAEgAAAABAAKgAgAEAAAAAQAAAJagAwAEAAAAAQAAALgAAAAA1Ug89AAAAAlwSFlzAAALEwAACxMBAJqcGAAAAgRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IlhNUCBDb3JlIDUuNC4wIj4KICAgPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4KICAgICAgPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIKICAgICAgICAgICAgeG1sbnM6ZXhpZj0iaHR0cDovL25zLmFkb2JlLmNvbS9leGlmLzEuMC8iCiAgICAgICAgICAgIHhtbG5zOnRpZmY9Imh0dHA6Ly9ucy5hZG9iZS5jb20vdGlmZi8xLjAvIj4KICAgICAgICAgPGV4aWY6UGl4ZWxYRGltZW5zaW9uPjI0NTwvZXhpZjpQaXhlbFhEaW1lbnNpb24+CiAgICAgICAgIDxleGlmOlBpeGVsWURpbWVuc2lvbj4zMDA8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICAgICA8dGlmZjpPcmllbnRhdGlvbj4xPC90aWZmOk9yaWVudGF0aW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAgPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KDTdu6wAAIk9JREFUeAHtXXuwLEdZ/3r3nN09e87NzYPwCIQLJOGSCyQCiQQsNYWCmATlkUQwKPKwwFcIIBbBKrgUCFYQKd7wh2goKRWwFEgFAioxGAokUJqYIHkQIAQh73vPvs/utL9fz/Tu7OzM7szunHNmb7pPzZme7q+/7+tff/11T0/PrMiDIqhwLXWlocPXjKvehqGZlmfLlGwkj/PKGBO18hxzXeo1ZVC6djxPkEdyb79o7wNjebMuWK24qum11s8m5eVaTcdsVhNN5j9IMBvvAWEY9ODp4cthvL12o6wejs8bEuUQGfMalp8WXVKiPJ5tWuSa3sWUZbqlGRIzwe9zzbdLpbllCCrNHuIDHL3gGvHuQKqtDyOtzzjKDExe9B8y+jg8Xdl8h82jgHBcV5pdaFwm3TC92ryT8THNRK2XpYdDqbre2DzeEo/O6yK9eg1VM9roioZnad6uuuuPHNEEMV1vnklNxqROaIb81eYHSQMNYzGfYOwSEhEYAohW+TosLdJN6hjqSoqtJtKMMFHfU731k8KJ46YRzpkjPuroZXWxeOW9In0oKF8a46Va52KY83uF7o/njRHGXKAHmGFOV2BKkRDYIY31tkhWpAcEuRMcoqUSrmMxQ3eZi18sswTBM5MTmM3X5xKY5VrNI02zUQ8It5X2gj7amcR0OASWu+EiuceHXoOc6YbDBhse6sKSObzZPMZt3ng1Ki1P11rvMv69evjxZogzQ53H4c4MbWaoY2mTboa6yd4CSRy+0IEx4iBupfm+jGMqOz+GuUqjxbxR+mgotGVYxXUUeCLVJ1ObYQt5ZAYYePjMOL7SaY7COGYYhJEFrVQXXrRGMhZQPQVvawZdQ88bDZs+YuViu4zAWFtaXdBun0T8yfY6+azW0Oan2HxdbXwfFnbYXieeldypuhu/mpiPjHiXIQrDtE6h2No4b72+b3LYHycxV1phljc9jHfy6bQ7mhuLGJrnrDgt2M/huuKyTBq7bzSTN80y8L4RTZ91nQmxCamzuC+Qn0mxMRe4gNA0RTMpFh6x0jBfhCaTYnYMWURg2rKZFHOIAdaMiKVtiMXpMimGaceOdcyMis03iV8cP8dhAQQwkX4bpj9cVwruqBtb+qjmmWSpq539utJFevTw58e60pnMqzY/YspO5GEyX28+IpWqcKT+HUC1+Y+IGztEcc6vB7p66OQwE1/x8Qk70swkng7ZHrZMNM9XlvStsY4VP7vAYpju4Zak2rpSKjLQgqW6apM3AyLdo263QqafsRxT4YqICeS3BgcdLPmZPCyKKMwrG7z18VSvPtYRYxUzrHiTheqKtC/Aql5bdO0KxMHKMvclxv0nSkowFyy3fmuYv9p6imzJdf41VwNlddtGEiowFBxE4tIszbQ8S+PODgGHQBEQiOvaJSwCfRvKjTm3OGWxknJaOB0e/PrwdUIcKzIbpyfkmeQ4pcpQigtw9LxTg32ObIk4DNl48lnBm+ORy5QwE40pZbctaxeUmhwNorXbBaWiKkxexw3OnpRWniu6H7I3kOkyHnnMWOtV3AkwFkoY3r+AlBCv2fcDIeIxZhMXuoIZDWYM4RA19HAe4xiI2Wn4HGcoB0x0qbcxtYWmZkaF5HE91G4Ksx1XKoXPmO0gp1RoriyHVFrY0kyHd9ym0ii/40qlma/vuFKFRMrZVJpmSUvjbIpIFbL3FXKYwSxm5pi8Cza1pNPhXUBqdvPFzdHj3YluPAMZw+0O8UQTqZ7oQeQZ5MpMm5rg4hKWCYFEX0bPmzSiIy+2g4B+uN0mCkJCHvzDpOEnG3pFQ8AmeFu9zeou6bVUsF1nuDodEt8DcaWPvGh/GAiWsFdxD9gQWa2OSvBeFfeFvXpoeTthuUdXeugh2M2j1I9xv/NyRHAXyrXw5v0+ww5OWxDO+0xzMI6Dwaaxk4UP5mlkMt+mmziUjash6YPAZuPuHSzrmIV6O4D6j0La3DI0bLqAjhKGgU8T7JKQ4UV+wRI3tiNtRvLM1iSbZpkMBdgE08aqfTGu+XgEu6r6eGzR7KheVaneGu0s2ja26NgZZbtSaXXMUW1NbEuhHJ+X2RwyVrEJpchZdesfwF5i7IWqIp8bm4EJHyitbb5wTPL0C66KBMfQME0J8OIDKh5ocpiFYFvytGAgr7L5cKCpeJCeDHRli2lDBmmbz8qzzeeXoww0da3xsjBP0k70PsKqdeMB5B0tVfmB6NVzdKlxKToUlFtBlSe7sBUaPmNbyouAgulpeEikpb3+9yLofAhx21jCZYe1DidCcyzhsEcQ2mHAWuXG2Fola0ya8JKQ/9hswuwGxhwqDfRetRGmH3KfJ2IUTSgYhT+BzCU7BBwCDgGHgEPAIZAOgdhJQ7SoP4lofRWTrDMw6AfzRDt3JIukuOXE/Kioaln1VqKJtkCw8x9v05kQJQvzs3F7ZoFonAnq++H93T7fbP8npn1TihMkHKNXHHxaKmZDUpz54TxeB5gzmhyCGV20LAuE02zcnsfzkcoJdCqByarkwGAa8yMtb2G0lwGQtDdBs+qSpRuSF6w56j/iRIS7Q1x+2rQ0sshrujze8wCwtEIT6VKBBUHcq/hMcJkp0dCazQR8Q2smeaJiWEuAbvXkfD+nLGvtp2I35temCdtxy4LAifvi6TUx9/9zo0XQp/OnPRmLyqjXLK7J+dvms47E2/1tAyu5fXY+J6+G2zaw8vITeUCbly7bBlZerZkHWP6cdHFO2wbW4qrlySHdYvMsidsG1tzD4CyN58ofPS6Yq3hQaNvAWkSp/MsW3LKmz6nzh2M6x4JbVrG64XQo0+ZuWzcslmWlhWM63baBNV3scuZuG1h5TQTzgbXgDj6fSubFpeAOvlgz+IJbVpFGw7wabtt8Fhb+CjMg5uU/tw2svFozD6+Vly6plpWzKzzAgvKslc7B2Mal7DKCEtiwhRhXVRN7PjJA4y28opooYG7lURAtmQqI2YDO1iKwmjQ9BENi1qXx2fIdhUPAIbCjCGT2WfARvn+otLBlVZ8vgr3hw20ETQ/7vz+EDwxfTL8V9km4XpVqdx9ql3ZKUVLd2i1Ew/9gTDVduUr1EPbF3wvZ2NP7wOPwCZXkOlZ6h9TmUfcYGajXLJ+WzIgcQoGVl0rnJRh4LkeydajhEYaVYXrAEw9IK82HSeM9UOat2ITdPRkwfTd2F39Izii6Ptw3bDYzY8BDZUbZ8TFs+1cfla36JaDFzuxNvE5gPiY4qyB050elu+dJt/5FRGKfWc5iYlQCUObdCrsvGYkDfLnhvaq98UYDonwaSfgWDp9cV5qfgy2cgwMj4oapMGhKeHL8SBkMPoUdS8EXeTQqVv5Ff9SnGOCsBtfg7DcEvmKE/cxPY46/99nODrBX/tFSk7sPTT6uVns1HmL31I9V8MHSMFgot3HfXhkcC70OQRZom1v7RG1dDgn88iPl9tEzLgdgr04CjPqkCna7O7bCmzcUAMwtunb45wHGhmWg5VOppg2kH+dn5kuWzdjZWNbws83JdGOFDH/ztgRedPC/CMt8NvwkXfNa0AQfstpiD4kNmSal5qOu1da74UT+GB9GQFPrk8UrXYPuBiXMlnsKwlcT8OJCqfNS6dT+Di0U7qqxSqRJJGO/lpAV+pp7qCz6qXp+cjfqQu3mVXivBvdhRlcid6zIOqy3GbBH91vt/i72dWCXnbLfpBqKmEB5mJMhws/viir/imj9NsyUYWWW7cjvxLELdWtkJ9MGryAEFWJv8eD7hn7Tsh5ISf++dL5wjZILjc9J4bPIMzjWsBOxDCCTX+eytbICp55HlUMLlPV/w2c9DczZ7SiQgbtazoRt4ddBmATDVb0nSHfPLXEWNuLHorPAGvksY+G+XBaMhuFMfRysKfzBK42PSg0WQCnJXvy19X3mFTFfRXYx8ID/9/Gi6dquzfitcNKn+qST/7OApcdHQ9s4UaYcDT8WPxr6YE2znCiz6LWtWDR94tpYxiG5H8LQnzfwsbzGlaLX8IaXP3j5BfiSVRuv+nivVL09/zDBJJrAptLmTbBRz43S8FqtRRd8khoZ7zq11kYsynAJwWVSiRGxizkEHAIOAYeAQ8Ah4BBwCDgEHAIOAYeAQ8AhkCcCqe/FdXXzNix/jH08ZAFFuLRzE74f8tLoOpeWr6xI9cz3YMXnF0CTeol6hi4VyDoVspKWdmYU97NTL9GIrj/OX0pmQbO2EgiIwzuqU5jG5AEsPf7B3oCbyNnIap2IfweQBLDCZUnE8jbNxu2Z+Qz22p7LuYCeHix/3SoQSiVsCMdtWvQ8QYPa2hfTo7TmmmhwoQzyJsoiOZxm4/ZsyodomJ4LVmMrd1aKOycgEF7mTCBxyRYBB5ZFIsXZgZUCJEviwLJIpDg7sFKAZEkyTB1YxM5vbPGkc3QYT6JLTKcgTi8SCUYZC8sasZoRSw+WanFnTPD83xYLP1OlpH4Zs/wzETmIY16rxYNSfRBTow/iHKBl5YFrOJQwsR3or+I5ZTh12+IJWsTI69Zjfq089OFTU+SOFamcEE2MYZacxFsSvaWvx/dLZ5oVaLHFydwI0Lxm0idLTZeTGiwqNoslH43jiTC+mzyLcno+mOyMqUxXYyJ33q4ywejBkODAytDKDiwHVgYEMpA6y3JgZUAgA6mzLAdWBgQykDrLcmBlQCADqbMsB1YGBDKQOstyYGVAIAOpsywHVgYEMpA6y3JgZUAgA6mzLAdWBgQykDrLcmBlQCADqbMsB1YGBDKQOstyYGVAIAOpsywHVgYEMpA6y3JgZUAgA6mzLAdWBgQykDrLcmBlQCADqbMsB1YGBDKQpt6Am4Ent99ys+60bbjYYDt7Q286mZ6VN2W3Mr/jvHhVF+cwXqOBdHv/IauVn8Oe+CnKr2hsSG7msitZq7Nmf86zZL6GOa5q9qspFcrOjCXM9u50LwwMPzc3nyS/FOSlevMyzdb0RfRwZR0CDgGHgEPAIfDgQGCuqQOH66ShOCkP6ZlvrTgPQznqmFrP8NwthUxOX6ZNnsesINOklIob5mvNC7XXvAzfd30UPvoeMOyhSv3vide+CO8Kfn1MCi9qnUejeKo5kSlb8rq6re9EvI5vyT/cpM3+V5Ku+B/cx2enpXoYXx5J+Oi+6mjp7L2dLAlqGOQkMalbzAKlza+Pt/k+YFyLs5WY/l18JvgJYaH40vYD+HLH3nTzVXO39G3pfecsWTvwazIofybMKzleCb4/j8+s1889XfrVb42+Nx9XahWJUFe1PoZfR3hNHEU4LXXXoEX530JuExCWIyisFYHjwTjTGB7Hb8X70eC/gr3JAHQ4zTw88sI7xfjO9YC805QhjQ0XUEccs8rxG/v4FpGWV6Axwwwso7FzKrBgVWV8ZvyFo++mUxd8E7kkV+GTMpcAx9dC4L+bNJ89m+xkfeIDJ9HEA4lhUI3pBOn2ZAFnHo6kHxUiO3qPuMOyijuzHaNlCCgDfl/DGEPzCi0Hrb5+Vuh/Wp+FiuiXoRwrgjLDn1sI+6CPwPrwzjK+nY9Pe4Pek7tWPgT6cwN534TdHQWlqLXCy+KPxfkRJs62Fflf6Hs/WsAvi66MtGjAB/L1R6TSOyilODDxejZcZ0zgD2B8SWrVi8xPMpDAK5WlW3oOPlT9SeiLBAK2fq6Sg2y02JAKLNMFVWMPqsSKhgOvyXw0qqj2TaDb7xOp0wkg46q7cZ6fRmRAvrr5HljlxUgD4HgnWsmfSHf9SsoK0YUbg8laPNWVzT3wf0auJZ191vhywCFBObjNUfiMrLZvg+xgQGpqfWLnJLmjejv0mAAt0eRG/EzlAKoKOVn+NAIsqNL+M3ws/4RwBQHKE+HcV8zRXaflxAXIDYsGeLQ2+XQ4Ma4cqbbYAJQZPeIL2NRY+i3Zuvf6kPvQ8n/6BFsiep6tHEpAqT5Giw+DKVs6aHmarvcGfFfhDjp+ggcneYOuN80vmkQF5XSNRtNvxODRnTwGBrx4OSNrDecTbKkd9xb4YmP98DAlqdXY/YfWHaZP1Q1ZwEwdekoFvw5A5gQa4JHv8Ot2B6Svr0NFWqq3HnwVH9n5BsgdDhohztPaHWteSp6BH/zAtymoLw0ZPLR6unijX3bhnFE11F0hpmPR1GCxFYaArbZfgS79fswXAQi/GtIleNQg0FjXdMXTqoe5Xu7BNHpcy0+ThQFFHgJVnuWraZQCven+VkN45Pavo46JdyfTmsMyGZ6N2eJKba19HJazwR/ekF77eFldOQ9j5FWhvg++7b6utszPYA0ZLB4hSHTut00cqvmTGewJDntCcNiG5QhfQzOrd+JnaK5AHdnwsSE1WJxkGt9UhX/CMeL2l/dJs/plaV35PAOe/c0IY+be66YJH/FIHcN3auTj/DIkjv1jR3c90TH73Dn1o2cIH/wBHvVZOeaeDenU32KNIUmbVN2Qpgm/9DUcj4GyKFMTfRB9/uBNiB9gPwR4xwfAmxm+Lw+/DJIkeIF0drfYRoaeHIziLAM69j+retXzo3JN3X5a92YBxXKpwAKdJ+XSm2Wgftufl3ZE3rk+kOpj34sb50+BS1m8M07TuvH2QBlWiHOn66FMqpvUoNysUwlz2v24Kb8QmISsOyimyyvSkU/EMKE+NK2JkADuBB0TUoFlUG/LneiKt6LMPhwQzHsq9UcA5HVmXu9P4qgUD4RaWTbKz4fyk5XyCeb5T4s6R7wBPk8VF8zP88WBFUecOS3WnJO4wKmfAix+iHwAQAz4OzvmzCLkRaDQDegXeufLPfhhrtCMHIk5BDuBNbJs49hzDvyTWaSyrHBxAHayXm88W7ZKn8PUAcNIOAAn1fkK1pR4z8XuF+c//AIlvYYfr4MvNKEkpU1Y6wXBZehUhhUPCH6KENg0KBkD76F6mGc1UzJJIScLie/ws5TYOVroNoJs58Q6SQ4Bh4BDwCHgEHAIOAQcAg4Bh4BDwCHgEHAIOAQcAg4Bh4BDwCHgEHAIOAS2F4Hcn4Asy1OVeZ5jHsl1y9vMMj9bTaEAn5fmbrAp5GYh4dNz7mPJGviwPdPD+6wCcqCft245iB6xyM2w+GzaPKSvtK7Dw/zT/Xazz+RHAnc3xm3H1Kl5PTZ+nw6dU+3rAd0K6taXSvMKUevPFc23CnKDLidIaE+0+eZPdE+PbYXOSUAmNtuBDnZsMZjNpQW0rDrRD3Q0imb4p4JdUz14u952YJdBlwlSWFYVI4XiizW7Horu1ncdoOVRIH5//27p7wxrt5A/wuU6wzpiGrhYexydYR0xhlWsijjDKlZ7zK0N7wmLFJxhFak1jiBdtuOWOeg8vEsJv4W4MGoFWnQtXt2CJwmFwWibDMvYFv8FRnbEGJWtT551Izg5GESxJu+5GRZX3fksDe9EP3NhM4ow0LXGL4uuf1l0i0vnbIQcGiIiZMolV92DuuHbO/kGXdl8Elbxb8ArmdZo56ybWceas2y+dSK3XOdYgTvOTUs+SjHMtMI7mz7ubODcBGRgtA11859KlMv1DGosDWmuhrUTtc67gXdC5wejjKUzrN3yWEU3jqLhsnSGtSvjYNGtqoD6LZ1hYd5uJ7kFhHP3VCraFGEJDWt3Ju+7ZzJpJRcLlyU0rLRAO7rdRGAJDcsNhfEGUyxcls6winb3E9/Iu5HqhsLdQN3J3GEEls5jueWGeAsp2q3y0hlWPKwutWgdbukMq2g905l0PAJLZ1hFWwiMh3U3Ut1d4W6g7mTuMAJL57F2GJ+lEVe0ZZilM6yiAbg0lrfDii6dYRXt7meH2ytRXNHmnktnWG53Q6JtFSpjCQ2rUPg5ZRIQWDrDcnOs+JYsGi5LZ1hujhVvWG6OFY9LhtRiLQRmUHxbSZ3HWhjeYm0PWbg6RyiDpRsKj9B2OOKq5QzrCGnSos09l86w3O6G+J5QNFyWzrCK1jPjm3nnU4uGy9IZllt5TzLaYt0tL51hFe22OqmZdz69WHfLS2dYO99gTuI8CCydYRVtLjEP6A+GMktnWG6OlWSWbo6VhEyqdDfHioepaLgsnccq2sPW+Gbe+dSi4bJ0hoXv5bppVqzdFguXJTSsWFRdYsEQWDrDKtqji4K1Z2HUye1z3NtaI61WRKEP6HX8cOVCoWQ+5K2lQF8q7pdF7eEX8ResWlBedzcWQujBUrhodzt54n4k1y1PnBwvh4BDwCHgEHAIOAQcAg4Bh4BDwCHgEHAIpECAt9k4SjjKWr6ygnP0QLrJX3RtJ4U2jmQ7ENiRhqMB4SHpwFZAP0qvyb2HT5N+eb+U9NGwoWPwSyZ7YW8drBQeBt2PsGB4g2zdf7OSE9ssR0PjqWgPW6nbMge2TaA/seXvQeYSts2woLCyRoAfe3wR9lG9WWTtqf5PJHahPO3M/Aghn9LYg/oEB4oLHwxUcDS1rMrlUuldou4/9lDUUEFgDI/A6GrnJNH9K5D0UHDawjnPOnoQdBQ4flV1N54LPVYgs6+rzXMg53JokVvDQO0B4DkafN+vehtvCgzANL6uNJ4sSn0W+dSln62OhAO4a2kh0gSfH4t4wMv7ouruvQVpxHLMETAta9iWRzpQzBgVAP8Afhn1D41hQHMR43zCOrKWCQ1PW6Nd8DCni2TrmN8BqJuy0jobsHw7AQA8IpHjgM2xoge03gT+hmvGf/S6a6v4pVc2+ChoY/0PQUKOhsWet05Z64EgYxEmvlopy1bvOFTtKNhIxjqGn7ZyRqJPBZ9fQid+v64gT7XuEtX8TenIvybgO6r3lFiuD6FpUEbWCbIGA/iu6AqMqmUrPnS5oEEaPREx48FHd2vB2aYZ1ViWgXxX2cEQatKvf0uvNd4Hb8GfC7Z8mWcD6I0q/EdGOR0cjsmS3jQceG2SKIeRiDxDz/QMR4BlwDgsTfQW+FAXionKGl6nkGWwI344aHDAV+tjxav+i64075Nadx8FAGMjiPG0IXOBGYz9Rr639W4YzONFunDTw4Znd2BxLaXSu6XSfRh+P5q/IY2jhKMcnP00WS2fBvIv+AY35gloYAMZrF+sq403TBiXxtNqrWCdVYhaQ/2soYbPYEE94gPSa8gJ09t4LTBizBFN+JapUDwbm0oSDberNxHJeGAKIJx3Mlxt/s/+Z1Ti8DhNVgP50Imd21Ql7GkxinUhVx8jnnebrm2ebaYYo3acrUKeFNZb4VxBg1+D/xpeq4+DZx4DXfF4vohySTdNPvL91n9IZz/KbOlKK+DT5NnTlQHPN4MOWwMMv8BqzR3nqtFDboRzDx+aFgPOjff5+jXD+pFfoGPz+QHP2nh58uKA4f9WNc7G0KDbC6x+XmUz0NPUGXoTh9Zl5LdogDzjCHS9+RTMWzd1pU1ZwMJi3AzkNf85rSx9sq6iva7222YMD2CxRf43Qu5e8sM5RUfyJec2x4JVc0bISV9Pq8YdgT8IeQWC0sL1yt+iIk+VrvxptPKB4oFXMLN7kXuqN0tNnyJeCdtByuhZPVSOk4E+zqscKnvkQ/n2DD7ssQgH/NPov+Ud9NCQekMasFWBbLkafM62w/GQInNEe74BynXoLE+j7DjBYbZsQM/WKZwxPT5seJY3gZgm8TF5tyq4J32uVJrXwlOfLtKhfjRgHF3EawfkqPYT5LB8A2nkO0t3kPi3XSaS0z+/wVb0JbLVehZcw8PhcQNFTV3xj6OjXCKVwetRIYilDXTp7m+G4d2M5Ydbof+tolZv0G39TQNKR74PWnYCFHgXjrciagKQnHw7JS6N1OBBgQz27F9N/g/y747lP0memOI3sJIT9GrzDNw0YjJpGi6xAFSD7MGq1L3r0Zj3QedEw0hm4hsYy5LGnifpr6bB92Wtcxy60r7gRsnX2SdGHOp0ylwCyhRy81iUygY1QDTU3bh8hK43Pi799ZdjTkTjYmNZj4HeEEwdkIjACdGTQPJEzKZAR+/WL0lFERRkca7R+oQ8tPwO9aODt2o5AM944eKehJJzDoFR28ZBfXnDoV6M+T4OVp/1mRY8YLVRkm7reaDCMoDxHvPW1eoRFcr0Fdk442jda75WBgMsBTHgXsj3SrxAj1/HBsvG51R3z3cC44zyIV1soMvLNVhvAUVKqrXxCk7Ogc2Loe9NowkxxRrvAeUVXZatEJGnsYOAtsj1LnMniLO+SO6SWzjuS/W8P0ACjS53/cl3seB7iXEerB7rk+awljeXLdGQIaz8PM7tMGMYBIeHc/hA+qArvfJPgeKboJg1GGuIEF5DOzRvlu49v2HrYtvWXk87b0vDoMFpHHgscx0n0avS++nnpVf/GXsXKOXOPtwZvhoO7q9Qp38D7S04cJdi7754Ns7Uouv3MH/YxMLhyvswT/uhHI3FSgTIsIDwsmgBjca68O4rzYE1KgY99O7mMsM/YEHY2CG5Bpp0cMSgoRuPaPFjQU/UellKnT/Hwux+kceMzWFZIE0wrZeGcBYNG9cfCm+sSLXxKszjTxQ5FbVqQfvjoXDT02qzLd3e5ap97A9B/9fgyWMQ1xP0Xqygd9SlsMtXBvNzqwKA78G41k+Utrn7ORsZBMb2Oku3S2cz57MN5Q8n0vwL1au9cR6FgA0bO2sgFlPKGbiAI18h4M03zYBFMMfFExLVVeauMmhTY33IzBRyM6yR1AOoUAu366vPxlDGsczvgewJul6RmjqM6dXlSKchwkslhEPVHyD/VXhEcxls9nqQYx7msfZEBQdZywFdPfx4AMFlB6CU37MuMs8tBC9K7ICOMAKu3XX+E6PBQcBksQ91Oib1PRl4m/BVh2V15S7VVBgS/QAdbRmAPHljZOlmnXMzLCoBpfxnZ0JPUoJhme4QGm7bnnhrf4NV3fOkuvkaLOHdm6Qg+OEZ3KFT8Fjmk1hegFHx1te47aAIVNf9hvT2WB4h8JK4bn86MGCHGReEpV8mIH2u3h/wTFM/0BBufbd0169CZGgklD8KvFeii/o0nP8FY3yh4xRPN+IwK5abYVGQMQZ6jq76MOZAJ2O4eh28F7ySv9gJEtTaPC98gXRr53Op0fc8fUYCw6F75topMNH0SuhdvncKGShpy3iVS10Gmfeyl+UFCAQuFKAH62ItC/hyrlO6VFe6l2ZjjPZVnJO1Pgo8f4+dFhcpDVPZNTAAO89yRTZN46jDjRWXnzkNwGK8QkN3N16PB6hnAAvMs/gskMPesHPAatiJCTpvCtkQxgXjTOw4sRzmhXUEMfFdWcHk8lmqu/7RIhkVFEsIrBNH/SyHh3kkimDQSmBa6ORwo+Wm6NB7bNX/S/X2HI1V3YfiHvGf/JGRd3ymQxNtghYcxgWHro2FgYa0LGPc9w1YfD8LE2Elnc9fg0TkzuW6wde0F/6Z5Q57huEaQw96wPgwQXnxgUsnZv7HwuE6BHErIy4vnGbp7JkQxXgpzjqM3kbXQKYpg7hR3RSM13VnUnMdCqMqDxu9scF50EtwbdZE9Fr70QDg6XjI+UzgwH1T2AJCt6bauD6E0eQwPPiPMPe8VkreTaqt7rS84aFMZ5hzgTQwGHUbhtevQRa8qQd+NF62BeZAqleX0uA+K2/G2edXLt0j3uBq2BYbnGmm54zKBmJHCQkxSxcYFBYCMXm4NSC2mbD9FTxE7l8LjNjjaLyQZ/QfAMI9uP6foAwy5p+AWx7znCMAzMMiWxmO+Shh5eJ8dRA/O2iQq5Ft4mRswUSh/AAKjHOat45dAqFCcSGoU8JEOa5EpjTOl4yl2VIp5BEvGpwLDgGHgEPAIeAQcAg4BBwCDgGHgENgOgL/D5ycHAbAoC22AAAAAElFTkSuQmCC"},158:function(e,t,n){"use strict";n.r(t),t.default=n.p+"assets/images/auth1-04-350f5fb9ab327f3254e044f289409cab.png"},159:function(e,t,n){"use strict";n.r(t),t.default=n.p+"assets/images/12-d15746e9380cc15500789c8f73ffff3e.png"},160:function(e,t,n){"use strict";n.r(t),t.default=n.p+"assets/images/dataStore00-2f640196d21011b0ace821fa82299970.png"},276:function(e,t,n){"use strict";n.r(t),t.default=n.p+"assets/images/youtube-83cf986d72b536e7f67186e2362cbed6.gif"},277:function(e,t,n){"use strict";n.r(t),t.default=n.p+"assets/images/dataStore09-59f95c3aa526b757d6f508948685d18e.png"},278:function(e,t,n){"use strict";n.r(t),t.default=n.p+"assets/images/dataStore08-7fba3fbeb70c2e72dfb34b6aa667785e.png"},279:function(e,t,n){"use strict";n.r(t),t.default=n.p+"assets/images/dataStore07-0ba267cabf3e2d2587a05d0b5790ffe2.png"},280:function(e,t,n){"use strict";n.r(t),t.default=n.p+"assets/images/dataStore03-bbfdf24b0fc2fa986c6d2134d2a69a24.png"},281:function(e,t,n){"use strict";n.r(t),t.default=n.p+"assets/images/dataStore04-cfed3289db7338ce9b7223e93bf965cc.png"},282:function(e,t,n){"use strict";n.r(t),t.default=n.p+"assets/images/dataStore05-445fddc42db06b8f243360e179fc14e8.png"},283:function(e,t,n){"use strict";n.r(t),t.default=n.p+"assets/images/dataStore06-98cb811b239abd055844bed91d487b99.png"}}]);