diff --git a/Back-end/vessel_app/authAPI.py b/Back-end/vessel_app/authAPI.py deleted file mode 100644 index 3debc8a..0000000 --- a/Back-end/vessel_app/authAPI.py +++ /dev/null @@ -1,141 +0,0 @@ - -import os -from os import environ, path -from dotenv import load_dotenv -import json -import requests - -# basedir = os.path.abspath(os.path.dirname(__file__)) -basedir = r'D:\L_pipe\vessel_app_celery\Vessel-app\Back-end' -pathtoenv = path.join(basedir,'.flaskenv') -print(pathtoenv) -load_dotenv(pathtoenv) - -## Call company API key from Authenticating SDK -AUTHKEY = os.environ.get("AUTH_COMPANY_ADMIN_KEY_GOES_HERE") -print(AUTHKEY) - - -def CreateAcessCode(mockAPI): - - # - if mockAPI == True: - - # fake mockAPI - appDict = { - "firstName":"Jonathan", - "middleName":"Gob", - "lastName":"Zinx", - "dob":"22-05-1990", - "email":"jonathan@authenticating.com", - "houseNumber":"504", - "streetName":"121, 9th ST", - "address":"121, 9th ST, APT 12111", - "city":"Santa Monica", - "state":"CA", - "zipCode":"90411" - } - - headers = { - 'content-type': 'application/json', - } - - print(headers) - resp = requests.post(url = 'https://api-v3-stage.authenticating.com/mock/user/create', headers=headers, json=appDict) - print(resp) - - if resp.status_code == 200: - statement = resp.json() - print(statement) - - # Produciton - if mockAPI == False: - # Fake data - appDict = { - "firstName":"Patrick", - "middleName":"", - "lastName":"Lastnameson", - "dob":"29-05-1980", - "ssn":"123456789", - "email":"email@email.com", - "address":"House Number 3, Street Name", - "houseNumber":"123", - "streetName":"Hollywood Boulevard", - "city":"Los Angeles", - "state":"LA", - "zipCode":"90210" - } - # app_json = json.dumps(appDict) - - headers = { 'Authorization': f'Bearer {AUTHKEY}', - 'Content-Type': 'application/json' } - print(headers) - resp = requests.post(url = 'https://api-v3-stage.authenticating.com/mock/user/create', headers=headers, data=appDict) - print(resp) - - if resp.status_code == 200: - statement = resp.json() - print(statement) - - #new data JSON request - ## sent new request with API key - ## - - return 'AccessCode Reterived' - -# We create user - -## we call create user endpoint -# Please note that this is not included within the Android and IOS SDKs. - -# So basically we can only verify after -# First Name Last Name DateOfBirth and email is requires - - - -## Boolean is triggered after a check is done on the database to see if -## a user has sumbitted all the required data, verification has to be done -# in a 24 hour to 48 period -# This is either celery gevent solution or asyncio solution and APSscheduler solution -# https://stackoverflow.com/questions/21214270/how-to-schedule-a-function-to-run-every-hour-on-flask -# https://blog.gevent.org/ -# https://docs.python.org/3.4/library/asyncio.html -# https://pypi.org/project/APScheduler/ - - -## so we call query ReactUser, ContactInfo, Verify -## for information of FirstName,LastName, DOB to return AccessCode -## - - - - -## We make another datatable with user_id, First Name + LastName for easy query and date_uploaded -## we wait for access code to be used for every call and given to (user) - -# curl --location --request POST 'https://api-v3-stage.authenticating.com/mock/user/consent' \ -# --header 'Content-Type: application/json' \ -# --data-raw '{ -# "userAccessCode":"USER_ACCESS_CODE", -# "GLBPurposeAndDPPAPurpose":1, -# "FCRAPurpose":1, -# "isBackgroundDisclosureAccepted":1, -# "fullName":"Jonathan Doe" -# }' - -# we need update functionality - -# To provide "UserConset" we have to match the name in the User Object to this name in the API - -# We can only do this after SSN verification, phone number verification -# So we need to wait for Upload ID or Upload Passport -# to check the status on the upload id endpoint, you can make a call to Check Upload ID or Check Upload Passport -# https://docs.authenticating.com/#upload-id -# https://docs.authenticating.com/#upload-passport - - -# if it requires retry or not - -if __name__ == "__main__": - mockAPI = True - CreateAcessCode(mockAPI) \ No newline at end of file diff --git a/Back-end/vessel_app/global_api/authAPI.py b/Back-end/vessel_app/global_api/authAPI.py new file mode 100644 index 0000000..bda4ccc --- /dev/null +++ b/Back-end/vessel_app/global_api/authAPI.py @@ -0,0 +1,340 @@ + +import os +from os import environ, path +from dotenv import load_dotenv +import json +import requests +import numpy as np +from vessel_app.models import UserReact, ContactInfo, Verify, Checkpoint, AuthTable +# basedir = os.path.abspath(os.path.dirname(__file__)) +basedir = r'D:\L_pipe\vessel_app_celery\Vessel-app\Back-end' +pathtoenv = path.join(basedir,'.flaskenv') +print(pathtoenv) +load_dotenv(pathtoenv) + +## Call company API key from Authenticating SDK +AUTHKEY = os.environ.get("AUTH_COMPANY_ADMIN_KEY_GOES_HERE") +print(AUTHKEY) + +## Core parameter is username +## CreateAccessCode reutrn code to insert +## Sumbit UserConset with AccessCode +## + +def CreateAccessCode(username, mockAPI): + + # + if mockAPI == True: + + # fake mockAPI + appDict = { + "firstName":"Jonathan", + "middleName":"Gob", + "lastName":"Zinx", + "dob":"22-05-1990", + "email":"jonathan@authenticating.com", + "houseNumber":"504", + "streetName":"121, 9th ST", + "address":"121, 9th ST, APT 12111", + "city":"Santa Monica", + "state":"CA", + "zipCode":"90411" + } + + headers = { + 'content-type': 'application/json', + } + + print(headers) + resp = requests.post(url = 'https://api-v3-stage.authenticating.com/mock/user/create', headers=headers, json=appDict) + print(resp) + + if resp.status_code == 200: + statement = resp.json() + print(statement) + + #imagine we insert data into datatable AuthenticateTable + + # Produciton + if mockAPI == False: + + #every time this function is called its pararmeter is username and MockAPI = False + username=username + UserQuery = UserReact.query.filter_by(username=username).first() + ContactInfoQuery = ContactInfo.query.filter_by(username=username).first() + VerifyQuery = Verify.query.filter_by(username=username).first() + + # FirstName, LastName, DateOfBirth and Email fields listed here are required + # not required should be entered as null if not available. + headers = { 'Authorization': f'Bearer {AUTHKEY}', + 'Content-Type': 'application/json' } + + appDict = { + "firstName":UserQuery.firstname, + "middleName":None, + "lastName":UserQuery.lastname, + "dob":VerifyQuery.dob, + "ssn":VerifyQuery.ssn, + "email":UserQuery.email, + "address":ContactInfoQuery.residentialaddress, + "houseNumber":None, + "streetName":None, + "city":ContactInfoQuery.city, + "state":ContactInfoQuery.state, + "zipCode":ContactInfoQuery.zipcode + } + json_object = json.dumps(appDict) + print(headers) + print(json_object) + resp = requests.post(url = 'https://api-v3-stage.authenticating.com/user/create', headers=headers, data=json_object) + print(resp) + + if resp.status_code == 401: + print(resp) + statement = resp.json() + print(statement) + + # + if resp.status_code == 400: + print(resp) + statement = resp.json() + print(statement) + + + if resp.status_code == 200: + statement = resp.json() + print(statement) + + return 'AccessCode Reterived', statement + +def SubmitUserConsent(userAccessCode, production): + global statement + production = False + + # MockAPI + if(production == False): + + appDict = { + "userAccessCode":userAccessCode, + "GLBPurposeAndDPPAPurpose":1, + "FCRAPurpose":1, + "isBackgroundDisclosureAccepted":1, + "fullName":"Jonathan Doe" + } + + headers = { + 'content-type': 'application/json', + } + + print(headers) + resp = requests.post(url = 'https://api-v3-stage.authenticating.com/mock/user/consent', headers=headers, json=appDict) + print(resp) + + if resp.status_code == 401: + print(resp) + statement = resp.json() + print(statement) + + # + if resp.status_code == 400: + print(resp) + statement = resp.json() + print(statement) + + if resp.status_code == 200: + statement = resp.json() + print(statement) + + return 'Successful Consent' + + if(production == True): + + # How to capture user consent?> + Auth = AuthTable.query.filter_by(AccessCode=userAccessCode).first() + username = Auth.username + UserQuery = UserReact.query.filter_by(username=username).first() + Auth.userAccessCode + + FullName = UserQuery.firstname + UserQuery.lastname + + headers = { 'Authorization': f'Bearer {AUTHKEY}', + 'Content-Type': 'application/json' } + + appDict = { + "userAccessCode":Auth.userAccessCode, + "GLBPurposeAndDPPAPurpose":1, + "FCRAPurpose":1, + "isBackgroundDisclosureAccepted":1, + "fullName":FullName + } + + print(headers) + resp = requests.post( + url = 'https://api-v3-stage.authenticating.com/mock/user/consent', + headers=headers, json=appDict) + print(resp) + + + if resp.status_code == 401: + print(resp) + statement = resp.json() + print(statement) + + # + if resp.status_code == 400: + print(resp) + statement = resp.json() + print(statement) + + if resp.status_code == 200: + statement = resp.json() + print(statement) + + return 'Successful Consent' + +# We create user + +def VerifyPhone(username): + # Production Only + # query AccessCode + Auth = AuthTable.query.filter_by(username=username).first() + # + data = np.random.randint(100,size=(12)) + + headers = { 'Authorization': f'Bearer {AUTHKEY}', + 'Content-Type': 'application/json' } + # -H 'cache-control: no-cache' \ + appDict = { + "userAccessCode":Auth.userAccessCode, + } + + # + resp = requests.post( + url = 'https://api-v3.authenticating.com/user/verifyPhone', + headers=headers, json=appDict) + + return 'pass' + +def SMSPhoneCode(username): + # Production Only + # VerifyPhoneCode + # query AccessCode + Auth = AuthTable.query.filter_by(username=username).first() + # + data = np.random.randint(100,size=(12)) + + headers = { 'Authorization': f'Bearer {AUTHKEY}', + 'Content-Type': 'application/json' } + + appDict = { + "userAccessCode":Auth.userAccessCode, + "code":data + } + + # + resp = requests.post( + url = 'https://api-v3.authenticating.com/user/verifyPhoneCode', + headers=headers, json=appDict) + + return 'pass' + + +def VerifyEmail(username): + Auth = AuthTable.query.filter_by(username=username).first() + + headers = { 'Authorization': f'Bearer {AUTHKEY}', + 'Content-Type': 'application/json' } + # -H 'cache-control: no-cache' \ + appDict = { + "userAccessCode":Auth.userAccessCode, + } + + # + resp = requests.post( + url = 'https://api-v3.authenticating.com/user/verifyEmail', + headers=headers, json=appDict) + + # we expect a true or false back + return 'pass' + +## we call create user endpoint + +# So basically we can only verify after +# First Name Last Name DateOfBirth and email is requires + +def UploadID(username): + + # OCR scan + # compared to and corrected with data extracted from barcode + # AAMVA standards? + + Auth = AuthTable.query.filter_by(username=username).first() + + headers = { 'Authorization': f'Bearer {AUTHKEY}', + 'Content-Type': 'application/json' } + # -H 'cache-control: no-cache' \ + # we need user upload functionality only + # pnly JPEG or PNG + appDict = { + "userAccessCode":Auth.userAccessCode, + "idFront": "BASE_64_ENCODED_ID_FRONT", + "idBack": "BASE_64_ENCODED_ID_BACK", + "country": "COUNTRY_CODE" + } + + # + resp = requests.post( + url = 'https://api-v3.authenticating.com/identity/document/scan', + headers=headers, json=appDict) + + return 'pass' + +## Boolean is triggered after a check is done on the database to see if +## a user has sumbitted all the required data, verification has to be done +# in a 24 hour to 48 period +# This is either celery gevent solution or asyncio solution and APSscheduler solution +# https://stackoverflow.com/questions/21214270/how-to-schedule-a-function-to-run-every-hour-on-flask +# https://blog.gevent.org/ +# https://docs.python.org/3.4/library/asyncio.html +# https://pypi.org/project/APScheduler/ + + +## so we call query ReactUser, ContactInfo, Verify +## for information of FirstName,LastName, DOB to return AccessCode +## + + + + +## We make another datatable with user_id, First Name + LastName for easy query and date_uploaded +## we wait for access code to be used for every call and given to (user) + +# curl --location --request POST 'https://api-v3-stage.authenticating.com/mock/user/consent' \ +# --header 'Content-Type: application/json' \ +# --data-raw '{ +# "userAccessCode":"USER_ACCESS_CODE", +# "GLBPurposeAndDPPAPurpose":1, +# "FCRAPurpose":1, +# "isBackgroundDisclosureAccepted":1, +# "fullName":"Jonathan Doe" +# }' + +# we need update functionality + +# To provide "UserConset" we have to match the name in the User Object to this name in the API + +# We can only do this after SSN verification, phone number verification +# So we need to wait for Upload ID or Upload Passport +# to check the status on the upload id endpoint, you can make a call to Check Upload ID or Check Upload Passport +# https://docs.authenticating.com/#upload-id +# https://docs.authenticating.com/#upload-passport + + +# if it requires retry or not + +if __name__ == "__main__": + username = 'test' + mockAPI = True + msg, value = CreateAccessCode(username, mockAPI) + print(value) + SubmitUserConsent(value["userAccessCode"], mockAPI) \ No newline at end of file diff --git a/Back-end/vessel_app/global_api/routes.py b/Back-end/vessel_app/global_api/routes.py index 32ccf8f..e3de730 100644 --- a/Back-end/vessel_app/global_api/routes.py +++ b/Back-end/vessel_app/global_api/routes.py @@ -18,8 +18,9 @@ # from .models import db # from .admin import setup_admin from flask_login import login_user, current_user, logout_user, login_required -from vessel_app.models import UserReact, ContactInfo, Verify +from vessel_app.models import UserReact, ContactInfo, Verify, Checkpoint, AuthTable from .connector_redis import save_csrf, check_csrf_token +from .authAPI import CreateAccessCode, SubmitUserConsent ## routes are for your endpoints ## Request notes @@ -241,13 +242,18 @@ def register(): try: db.session.commit() print('Your account has been created! You are now able to log in', 'success') + # when user account is created we make Checkpoint table response_pay_load = { "message":"Your account has been created! You are now able to log in", "firstname":firstname, "username":username } - + # the checkpoint table or the VerificatioStatus is created when user is created + VerificationStatus = Checkpoint(username=username, userMade=True, userContactInfo=False, userVerify=False) + db.session.add(VerificationStatus) + db.session.commit() + return jsonify(response_pay_load), 200 except: @@ -316,6 +322,7 @@ def contactInfo(): username=username_pass, phonenumber=phonenumber, residentialaddress=residentialaddress, + state=state, city=city, zipcode=zipcode ) @@ -330,7 +337,13 @@ def contactInfo(): "message":"ContactInfo, You are now able to log in", "username":username_pass, } - + + # we update the verification status of the user + VerificationStatus = Checkpoint.query.filter_by(username=username_pass).first() + VerificationStatus.userContactInfo = True + db.session.add(VerificationStatus) + db.session.commit() + return jsonify(response_pay_load), 200 except: @@ -352,9 +365,7 @@ def contactInfo(): def Verification(): json_obj = request.json token_id = json_obj['token_id'] - # username_pass = json_obj['username'] - username_pass = 'test' - print(username_pass) + username_pass = json_obj['username'] user = UserReact.query.filter_by(username=username_pass).first() if request.method == 'POST': @@ -363,15 +374,6 @@ def Verification(): print("Tokens Match approved") print(request.json) - - # "token_id":token_id, - # "csrf_token":csrf_token, - # "username":username, - # "ssn":ssn, - # "DOB":DOB, - # "citizenship":citizenship, - # "submit":"Verification" - ## bcrypt ssn = json_obj['ssn'] citizenship = json_obj['citizenship'] DOB = json_obj['DOB'] @@ -382,19 +384,19 @@ def Verification(): print(user.id) pass_id = user.id if submit == 'Verification': - print("hello?") - - print("hello?") + # db.session.add(dbVerify) # db.session.commit() - Verify( + verification = Verify( user_id=user.id, username=username_pass, ssn=ssn, dob=DOB, citizenship=citizenship) - + db.session.add(verification) + try: + # db.session.commit() db.session.commit() print('Verification has been created! You are now able to log in', 'success') response_pay_load = { @@ -402,7 +404,14 @@ def Verification(): "message":"Verification, You are now able to log in", "username":username_pass, } - + + # update Checkpoint + VerificationStatus = Checkpoint.query.filter_by(username=username_pass).first() + VerificationStatus.userVerify = True + db.session.add(VerificationStatus) + db.session.commit() + + return jsonify(response_pay_load), 200 except: @@ -420,6 +429,90 @@ def Verification(): } return jsonify(response_pay_load), 200 +# After user logins its automatically checks VerificationStatus +@bp.route('/verificationcheck', methods=['POST','GET']) +def VerificationCheck(): + json_obj = request.json + print(request.json) + token_id = json_obj['token_id'] + username_pass = json_obj['username'] + user = UserReact.query.filter_by(username=username_pass).first() + if username_pass == 'null': + + return 'no verification check' + + ## does user exist alread? + # Contact infocheck + + if request.method == 'POST': + token = check_csrf_token(token_id, True) + if json_obj['csrf_token'] == token: + print("Tokens Match approved") + print(request.json) + + #VerificationStatus + # 1 checkpoint table + CheckTable = Checkpoint.query.filter_by(username=username_pass).first() + print("userMade Status?", CheckTable.userMade) + print("userContactInfo Status?", CheckTable.userContactInfo) + print("userVerify Status?", CheckTable.userVerify) + + + userMade = CheckTable.userMade + + + # do have ContactInfo no? redirect user to ContactInfoPage + userContactInfo = CheckTable.userContactInfo + + # do we have VerificationID no? redirect user to IDVerification + userVerify = CheckTable.userVerify + + + + #do we have userconset? + + #Great now lets get UserAccessCode from Authanticing.com + if(userMade == True and userContactInfo == True and userVerify == True): + ## we create access code for user + msg, value = CreateAccessCode(username_pass, False) + #we insert accessCode into the data table + print(value) + #we capture userconsent here we need UserAccessCode + + + + + # check do we have all checkpoint table TRUE and UserAccessCodeTrue? + # redirect to test upload Passport + # if all Sign up completes send redirect back to user to upload ID or Passport + + try: + print('Verification Status You are now able to log in', 'success') + + response_pay_load = { + "message":"Verification Check Succes", + "username":username_pass, + "userMade":userMade, + "userContactInfo":userContactInfo, + "userVerify":userVerify + } + + + # VerificationStatus = Checkpoint.query.filter_by(username=username_pass).first() + # VerificationStatus.userVerify = True + # db.session.add(VerificationStatus) + # db.session.commit() + return jsonify(response_pay_load), 200 + + except: + print("Verification Status return failed") + response_pay_load = { + "message":"Failed Verification Check" + } + return jsonify(response_pay_load), 200 + + # Check the Verifcaiton table + # Plaid intergration ## for our user we buy Candrano for them @@ -430,6 +523,27 @@ def Verification(): @bp.route('/PlaidEntryPoint', methods=['POST','GET']) def PlaidEntryPoint(): + json_obj = request.json + print(request.json) + token_id = json_obj['token_id'] + username_pass = json_obj['username'] + if username_pass == 'null': + + return 'no verification check' + + if request.method == 'POST': + # redis + token = check_csrf_token(token_id, True) + if json_obj['csrf_token'] == token: + print("Tokens Match approved") + print(request.json) + + # Plaid speical "Link Access Token Token" + # trigger another web request to plaid for the Link token + # create_link_token_for_payment() + # CALL PLAID + # link return this has to be sent back to React + return 'pass' @@ -566,6 +680,7 @@ def account(): user.name = 'New Name' db.session.commit() + ## did usuer change emaiL? ## did user change username? # picture data uploaded passed to diff --git a/Back-end/vessel_app/global_api/web3API.py b/Back-end/vessel_app/global_api/web3API.py new file mode 100644 index 0000000..e69de29 diff --git a/Back-end/vessel_app/models.py b/Back-end/vessel_app/models.py index 4b2c5a9..f3573b8 100644 --- a/Back-end/vessel_app/models.py +++ b/Back-end/vessel_app/models.py @@ -48,6 +48,7 @@ class ContactInfo(db.Model, UserMixin): username = db.Column(db.String(30), unique=True, nullable=False ) phonenumber = db.Column(db.String(120), unique=True, nullable=False) residentialaddress = db.Column(db.String(120), unique=False, nullable=False ) + state = db.Column(db.String(120), unique=False, nullable=False ) city = db.Column(db.String(120), unique=False, nullable=False ) zipcode = db.Column(db.Integer, nullable=False) user_id = db.Column(db.Integer, db.ForeignKey('UserReact.id'), nullable=False) @@ -71,6 +72,34 @@ class Verify(db.Model, UserMixin): def __repr__(self): return f"Verify('{self.date_uploaded}')" + +class Checkpoint(db.Model): + + __tablename__ = 'Checkpoint' + + id = db.Column(db.Integer, primary_key=True) + username = db.Column(db.String(30), unique=True, nullable=False ) + userMade = db.Column(db.Boolean, default=False, nullable=False) + userContactInfo = db.Column(db.Boolean, default=False, nullable=False) + userVerify = db.Column(db.Boolean, default=False, nullable=False) + def __repr__(self): + return f"Checkpoint('{self.username}')" + + +class AuthTable(db.Model): + + __tablename__ = 'AuthTable' + + id = db.Column(db.Integer, primary_key=True) + username = db.Column(db.String(30), unique=True, nullable=False ) + AccessCode = db.Column(db.Boolean, default=False, nullable=False) + userconsent = db.Column(db.Boolean, default=False, nullable=False) + ssnReal = db.Column(db.Boolean, default=False, nullable=False) + idReal = db.Column(db.Boolean, default=False, nullable=False) + passportReal = db.Column(db.Boolean, default=False, nullable=False) + def __repr__(self): + return f"AuthTable('{self.username}')" + class DicomMetaData(db.Model): __tablename__ = 'DicomMetaData' @@ -120,6 +149,9 @@ class Dicom2(db.Model): def __repr__(self): return f"Dicom('{self.date_uploaded}')" + + + class DicomFormData(db.Model): __tablename__ = 'DicomFormData' id = db.Column(db.Integer, primary_key=True) diff --git a/Front-end/vessel-app/package-lock.json b/Front-end/vessel-app/package-lock.json index 9d91b9b..912121d 100644 --- a/Front-end/vessel-app/package-lock.json +++ b/Front-end/vessel-app/package-lock.json @@ -21,9 +21,11 @@ "react-dom": "^17.0.2", "react-dotenv": "^0.1.3", "react-file-dropzone": "^0.4.1", + "react-icons": "^4.2.0", "react-places-autocomplete": "^7.3.0", "react-router-dom": "^5.2.0", "react-scripts": "4.0.3", + "styled-components": "^5.3.1", "web-vitals": "^1.0.1" } }, @@ -1316,6 +1318,29 @@ "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" }, + "node_modules/@emotion/is-prop-valid": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", + "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", + "dependencies": { + "@emotion/memoize": "0.7.4" + } + }, + "node_modules/@emotion/memoize": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", + "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==" + }, + "node_modules/@emotion/stylis": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz", + "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==" + }, + "node_modules/@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" + }, "node_modules/@eslint/eslintrc": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.3.0.tgz", @@ -3524,6 +3549,25 @@ "@babel/helper-define-polyfill-provider": "^0.2.2" } }, + "node_modules/babel-plugin-styled-components": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-1.13.2.tgz", + "integrity": "sha512-Vb1R3d4g+MUfPQPVDMCGjm3cDocJEUTR7Xq7QS95JWWeksN1wdFRYpD2kulDgI3Huuaf1CZd+NK4KQmqUFh5dA==", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-module-imports": "^7.0.0", + "babel-plugin-syntax-jsx": "^6.18.0", + "lodash": "^4.17.11" + }, + "peerDependencies": { + "styled-components": ">= 2" + } + }, + "node_modules/babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=" + }, "node_modules/babel-plugin-syntax-object-rest-spread": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", @@ -4249,6 +4293,11 @@ "node": ">=10" } }, + "node_modules/camelize": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz", + "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=" + }, "node_modules/caniuse-api": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", @@ -5144,6 +5193,14 @@ "node": ">=6.0.0" } }, + "node_modules/css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU=", + "engines": { + "node": ">=4" + } + }, "node_modules/css-color-names": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", @@ -5255,6 +5312,16 @@ "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==" }, + "node_modules/css-to-react-native": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.0.0.tgz", + "integrity": "sha512-Ro1yETZA813eoyUp2GDBhG2j+YggidUmzO1/v9eYBKR2EHVEniE2MI/NqpTQ954BMpTPZFsGNPm46qFB9dpaPQ==", + "dependencies": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" + } + }, "node_modules/css-tree": { "version": "1.0.0-alpha.37", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", @@ -13914,6 +13981,14 @@ "attr-accept": "^1.0.3" } }, + "node_modules/react-icons": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.2.0.tgz", + "integrity": "sha512-rmzEDFt+AVXRzD7zDE21gcxyBizD/3NqjbX6cmViAgdqfJ2UiLer8927/QhhrXQV7dEj/1EGuOTPp7JnLYVJKQ==", + "peerDependencies": { + "react": "*" + } + }, "node_modules/react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -15205,6 +15280,11 @@ "sha.js": "bin.js" } }, + "node_modules/shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, "node_modules/shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", @@ -15938,6 +16018,46 @@ "node": ">= 8.9.0" } }, + "node_modules/styled-components": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.1.tgz", + "integrity": "sha512-JThv2JRzyH0NOIURrk9iskdxMSAAtCfj/b2Sf1WJaCUsloQkblepy1jaCLX/bYE+mhYo3unmwVSI9I5d9ncSiQ==", + "dependencies": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/traverse": "^7.4.5", + "@emotion/is-prop-valid": "^0.8.8", + "@emotion/stylis": "^0.8.4", + "@emotion/unitless": "^0.7.4", + "babel-plugin-styled-components": ">= 1.12.0", + "css-to-react-native": "^3.0.0", + "hoist-non-react-statics": "^3.0.0", + "shallowequal": "^1.1.0", + "supports-color": "^5.5.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/styled-components" + }, + "peerDependencies": { + "react": ">= 16.8.0", + "react-dom": ">= 16.8.0", + "react-is": ">= 16.8.0" + } + }, + "node_modules/styled-components/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/stylehacks": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz", @@ -19984,6 +20104,29 @@ "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==" }, + "@emotion/is-prop-valid": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz", + "integrity": "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==", + "requires": { + "@emotion/memoize": "0.7.4" + } + }, + "@emotion/memoize": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz", + "integrity": "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==" + }, + "@emotion/stylis": { + "version": "0.8.5", + "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz", + "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==" + }, + "@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" + }, "@eslint/eslintrc": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.3.0.tgz", @@ -21820,6 +21963,22 @@ "@babel/helper-define-polyfill-provider": "^0.2.2" } }, + "babel-plugin-styled-components": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-1.13.2.tgz", + "integrity": "sha512-Vb1R3d4g+MUfPQPVDMCGjm3cDocJEUTR7Xq7QS95JWWeksN1wdFRYpD2kulDgI3Huuaf1CZd+NK4KQmqUFh5dA==", + "requires": { + "@babel/helper-annotate-as-pure": "^7.0.0", + "@babel/helper-module-imports": "^7.0.0", + "babel-plugin-syntax-jsx": "^6.18.0", + "lodash": "^4.17.11" + } + }, + "babel-plugin-syntax-jsx": { + "version": "6.18.0", + "resolved": "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz", + "integrity": "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=" + }, "babel-plugin-syntax-object-rest-spread": { "version": "6.13.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz", @@ -22479,6 +22638,11 @@ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz", "integrity": "sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg==" }, + "camelize": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz", + "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=" + }, "caniuse-api": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", @@ -23218,6 +23382,11 @@ "postcss": "^7.0.5" } }, + "css-color-keywords": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz", + "integrity": "sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU=" + }, "css-color-names": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz", @@ -23301,6 +23470,16 @@ "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz", "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==" }, + "css-to-react-native": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.0.0.tgz", + "integrity": "sha512-Ro1yETZA813eoyUp2GDBhG2j+YggidUmzO1/v9eYBKR2EHVEniE2MI/NqpTQ954BMpTPZFsGNPm46qFB9dpaPQ==", + "requires": { + "camelize": "^1.0.0", + "css-color-keywords": "^1.0.0", + "postcss-value-parser": "^4.0.2" + } + }, "css-tree": { "version": "1.0.0-alpha.37", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz", @@ -30453,6 +30632,12 @@ "attr-accept": "^1.0.3" } }, + "react-icons": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.2.0.tgz", + "integrity": "sha512-rmzEDFt+AVXRzD7zDE21gcxyBizD/3NqjbX6cmViAgdqfJ2UiLer8927/QhhrXQV7dEj/1EGuOTPp7JnLYVJKQ==", + "requires": {} + }, "react-is": { "version": "16.13.1", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", @@ -31546,6 +31731,11 @@ "safe-buffer": "^5.0.1" } }, + "shallowequal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz", + "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + }, "shebang-command": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", @@ -32183,6 +32373,33 @@ "schema-utils": "^2.7.0" } }, + "styled-components": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.1.tgz", + "integrity": "sha512-JThv2JRzyH0NOIURrk9iskdxMSAAtCfj/b2Sf1WJaCUsloQkblepy1jaCLX/bYE+mhYo3unmwVSI9I5d9ncSiQ==", + "requires": { + "@babel/helper-module-imports": "^7.0.0", + "@babel/traverse": "^7.4.5", + "@emotion/is-prop-valid": "^0.8.8", + "@emotion/stylis": "^0.8.4", + "@emotion/unitless": "^0.7.4", + "babel-plugin-styled-components": ">= 1.12.0", + "css-to-react-native": "^3.0.0", + "hoist-non-react-statics": "^3.0.0", + "shallowequal": "^1.1.0", + "supports-color": "^5.5.0" + }, + "dependencies": { + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, "stylehacks": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz", diff --git a/Front-end/vessel-app/package.json b/Front-end/vessel-app/package.json index 800f26c..39fc3d0 100644 --- a/Front-end/vessel-app/package.json +++ b/Front-end/vessel-app/package.json @@ -16,9 +16,11 @@ "react-dom": "^17.0.2", "react-dotenv": "^0.1.3", "react-file-dropzone": "^0.4.1", + "react-icons": "^4.2.0", "react-places-autocomplete": "^7.3.0", "react-router-dom": "^5.2.0", "react-scripts": "4.0.3", + "styled-components": "^5.3.1", "web-vitals": "^1.0.1" }, "scripts": { diff --git a/Front-end/vessel-app/src/App.js b/Front-end/vessel-app/src/App.js index a5fded9..4fdfd14 100644 --- a/Front-end/vessel-app/src/App.js +++ b/Front-end/vessel-app/src/App.js @@ -21,6 +21,9 @@ import Buy from './pages/Buy' import Emf from './pages/EMF' import injectContext from './appContext/UserContext'; +import { HashRouter } from 'react-router-dom' +import Settings from './components/settingsComponents/Settings' +import SubNavBar from './components/settingsComponents/SubNavBar' import "./css/theme_skeleton.css" import "./css/normalize.css" @@ -58,14 +61,28 @@ function App() { + + - - + {/* */} + + {/* preferences + security + financials-services + account_activity + privacy rights + Linked-accounts + account-levels + cryptoaddress */} + + + + diff --git a/Front-end/vessel-app/src/appContext/flux.js b/Front-end/vessel-app/src/appContext/flux.js index 1789cc8..2e82906 100644 --- a/Front-end/vessel-app/src/appContext/flux.js +++ b/Front-end/vessel-app/src/appContext/flux.js @@ -60,6 +60,15 @@ const getState = ({ getStore, getActions, setStore }) => { username:null, return_msg:null, firstname:null, + plaidToken:null, + + VerificationStatus: [{ + username:null, + userMade:null, + userContactInfo:null, + userVerify:null, + }], + demo: [ { title: "FIRST", @@ -126,11 +135,103 @@ const getState = ({ getStore, getActions, setStore }) => { }, + VerificationCheck: async (token_id, csrf_token, username) => { + const opts = { + method:'POST', + headers:{ + "Content-Type":"application/json" + }, + body: JSON.stringify({ + "token_id":token_id, + "csrf_token":csrf_token, + "username":username, + "submit":"VerificationCheck" + }) + }; + // basically allowing the react user to register via API + try{ + const resp = await fetch('http://127.0.0.1:5000/api/verificationcheck', opts) + if(resp.status !== 200){ + alert("There has been some error"); + return false; + } + + const data = await resp.json(); + console.log("this came from the backend", data); + sessionStorage.setItem("return_msg",data.return_msg) + sessionStorage.setItem("username",data.username) + sessionStorage.setItem("userMade",data.userMade) + sessionStorage.setItem("userContactInfo",data.userContactInfo) + sessionStorage.setItem("userVerify",data.userVerify) + // setStore({return_msg: data.message, firstname:data.firstname, username:data.username}); + // setStore({VerificationStatus:[{ + // username:data.username, + // userMade:data.userMade, + // userContactInfo:data.userContactInfo, + // userVerify:data.userVerify, + // }]}) + //setStore login view refresh its hooked to COntext + return true; + + } + catch(error){ + console.error("There has been an error with login"); + } + }, + + + PlaidEntryPoint: async (token_id, csrf_token, username) => { + // csrfTokenState set to default + const url = '/api/PlaidEntryPoint'; + // const data = 'A$1;,BOimZ7i+_t**]Nq3El)!#bG|K' + let fetchGetResponse = await fetch(`${domainUrl}${url}`, { + method: 'POST', + headers: { + // Accept: "application/json", + "Content-Type": "application/json", + + }, + credentials: "include", + referrerPolicy: 'no-referrer', + mode: 'cors', + body: JSON.stringify({ + "token_id":token_id, + "csrf_token":csrf_token, + "username":username + }) + }); + + try{ + const data = await fetchGetResponse.json(); + console.log("backend_csrf_token_for_single_user", data); + // setStore({csrf_token: data.csrf_token}); //setStore login view refresh its hooked to COntext + sessionStorage.setItem("plaidToken", data.plaidToken); + setStore({ plaidToken: data.token_id}); + // console.log(csrf_token) + + // call this if statement after the token has been put into session + // if(csrf_token && csrf_token !== "" && csrf_token !== undefined) setStore({ csrf_token: data.data}); + + return true; + + } + catch(error){ + console.error("There has been an error with PlaidEntryPoint"); + } + + }, + logout: () => { sessionStorage.removeItem("token"); // takes token from session storage and stores it in the store console.log("Logging Out") setStore({ token:null }); + sessionStorage.setItem("return_msg",null) + sessionStorage.setItem("username",null) + sessionStorage.setItem("userMade",null) + sessionStorage.setItem("userContactInfo",null) + sessionStorage.setItem("userVerify",null) + }, @@ -162,7 +263,8 @@ const getState = ({ getStore, getActions, setStore }) => { sessionStorage.setItem("token", data.access_token); sessionStorage.setItem("username", data.username); sessionStorage.setItem("email", data.email); - setStore({token: data.access_token, username: data.username, email: data.email }); //setStore login view refresh its hooked to COntext + setStore({token: data.access_token, username: data.username, email: data.email }); + //setStore login view refresh its hooked to Context return true; diff --git a/Front-end/vessel-app/src/components/Deposit.js b/Front-end/vessel-app/src/components/Deposit.js index 36855fa..b485a02 100644 --- a/Front-end/vessel-app/src/components/Deposit.js +++ b/Front-end/vessel-app/src/components/Deposit.js @@ -1,12 +1,29 @@ -import React from 'react' +import React, {useContext} from 'react' +import {Context} from "../appContext/UserContext" -const deposit = () => { +const Deposit = () => { + const{store, actions } = useContext(Context); + const userName = window.sessionStorage.getItem("username") + function handleClick(e) { + e.preventDefault(); + console.log('The link was clicked.'); + + // generate and save a Link token is sessionstore + // flask API call to + actions.PlaidEntryPoint(store.token, store.csrf_token, userName); + } + // user's Action around the direct click + // So when the user clicks depoist we need to do a seriers of checks // We need code that checks the flask app to see if the user is Verified table // verify phonenumber (ture or False) // ID or passport (true or False) // verify existence (True ) - // We need to query Plaid API to see if their bank is connect (ping flask app server) + + // when page loads POST /link/token/create initilized plaid link + + // We need to query Plaid API to see if their bank is connect (ping flask app server) + // Plaid Dialog box // connect their bussines account // paypal @@ -14,9 +31,9 @@ const deposit = () => { return ( ) } -export default deposit +export default Deposit diff --git a/Front-end/vessel-app/src/components/FormInput.js b/Front-end/vessel-app/src/components/FormInput.js index acf8354..e543550 100644 --- a/Front-end/vessel-app/src/components/FormInput.js +++ b/Front-end/vessel-app/src/components/FormInput.js @@ -1,19 +1,22 @@ -import React, {useContext, useState} from 'react' +import React, {useContext} from 'react' import {Context} from "../appContext/UserContext" import useForm from '../formCode/useForm' import validate from '../validateInfo'; import { Link } from 'react-router-dom'; +import SignUpBtn from '../components/SignUpButtton' const FormInput = ({submitForm}) => { - const {store, actions} = useContext(Context); - - const { handleChange, handleSubmit, values, errors } = useForm( + const {store} = useContext(Context); + + const { handleChange, handleSubmit, values, errors, moveOn } = useForm( submitForm, validate ); - + + + return (
-
+ {/* we can GET csrf from flask store local session */} @@ -50,7 +53,7 @@ const FormInput = ({submitForm}) => { {
- + + {/* */} + + + Already have an account? Login here diff --git a/Front-end/vessel-app/src/components/Login_Header.js b/Front-end/vessel-app/src/components/Login_Header.js index 27c4414..943aeff 100644 --- a/Front-end/vessel-app/src/components/Login_Header.js +++ b/Front-end/vessel-app/src/components/Login_Header.js @@ -1,4 +1,4 @@ -import React, {useContext, useState} from 'react' +import React, {useContext, useState, useEffect} from 'react' // import Button from './Button' import {Link} from "react-router-dom"; import {Context} from "../appContext/UserContext" @@ -7,11 +7,29 @@ import NavBar from "../components/NavBar.js" const Login_Header = (props) => { const{store, actions } = useContext(Context); + console.log("this is your token", store.VerificationStatus) const history = useHistory(); // so if user clicks logut it sets token null via actions.logout action if (store.token || store.token === "" || store.token === undefined) history.push("/"); let title = 'OpenVessel' + + console.log(store.userContactInfo) + if(store.userContactInfo == false || store.userContactInfo == null){ + console.log(store.username) + console.log(store.VerificationStatus) + setTimeout(() => { + actions.VerificationCheck( + window.sessionStorage.getItem("token_id"), + window.sessionStorage.getItem("csrf_token"), + window.sessionStorage.getItem("username")); + }, 5000); + + + } + + + const handleClick = () => { actions.logout(); diff --git a/Front-end/vessel-app/src/components/Logout_Header.js b/Front-end/vessel-app/src/components/Logout_Header.js index a8c03d1..ecd1259 100644 --- a/Front-end/vessel-app/src/components/Logout_Header.js +++ b/Front-end/vessel-app/src/components/Logout_Header.js @@ -24,8 +24,4 @@ const Logout_Header = (props) => { } -const headingStyle = { - color:'red', backgroundColor: 'black', -} - export default Logout_Header diff --git a/Front-end/vessel-app/src/components/SignUpButtton.js b/Front-end/vessel-app/src/components/SignUpButtton.js new file mode 100644 index 0000000..9b617f4 --- /dev/null +++ b/Front-end/vessel-app/src/components/SignUpButtton.js @@ -0,0 +1,32 @@ +import React, { Component } from "react"; +import ReactDOM from "react-dom"; +import { Link, Redirect} from "react-router-dom"; + +class ChangeInput extends Component { + + + handleEvent = event => { + + console.log("handles work?") + console.log( "State condition" , this.props.moveOn) + if( this.props.moveOn == true){ + console.log("test") + // return + setTimeout(function(){ + const WorkPlz = true + }, 2000);//wait 2 seconds + } + }; + render() { + if (this.WorkPlz) { + return + } + return( + + ) + } +} + +export default ChangeInput; \ No newline at end of file diff --git a/Front-end/vessel-app/src/components/settingsComponents/AccountLevels.js b/Front-end/vessel-app/src/components/settingsComponents/AccountLevels.js new file mode 100644 index 0000000..0102c4e --- /dev/null +++ b/Front-end/vessel-app/src/components/settingsComponents/AccountLevels.js @@ -0,0 +1,21 @@ +import React from 'react' + +const AccountLevels = () => { + return ( +
+
+ {/* Two sections left hadside */} +
+
+

Verification Status

+ +

Account Limits

+
+
Upload Feature
+
+
+
+ ) +} + +export default AccountLevels diff --git a/Front-end/vessel-app/src/components/settingsComponents/CryptoAddress.js b/Front-end/vessel-app/src/components/settingsComponents/CryptoAddress.js new file mode 100644 index 0000000..e4bf0dd --- /dev/null +++ b/Front-end/vessel-app/src/components/settingsComponents/CryptoAddress.js @@ -0,0 +1,21 @@ +import React from 'react' + +const CryptoAddress = () => { + return ( +
+
+

Crypto Addresses

+

When your accoutn is created we generate Cardano, DAI, StableCoin Addresses + with your OpenVessel Account.

+

Addresses don't expire and are asset specific. You can use them to withdraw money and + move to to other address or other types of finanical products

+ +

We need a compoenent table to list out generate user addresses

+

Asset Address Label Created Look into Details Button

+ +
+
+ ) +} + +export default CryptoAddress diff --git a/Front-end/vessel-app/src/components/settingsComponents/FinancialServicies.js b/Front-end/vessel-app/src/components/settingsComponents/FinancialServicies.js new file mode 100644 index 0000000..33a0c2b --- /dev/null +++ b/Front-end/vessel-app/src/components/settingsComponents/FinancialServicies.js @@ -0,0 +1,36 @@ +import React from 'react' + +const FinancialServicies = () => { + return ( +
+
+

Phone Numbers

+

Unique Box Component manage button

+ {/* pop up feature to change exit button at the top*/} + {/* Country Dropdown of all Countries*/} + {/* Input for new number unqiue? */} + + {/* SMS 2-step verificcation code */} + {/* Enter the 2-tep verification code we texted to your phone */} + {/* Secure your account by texting a short + confirmation code to your phone when logging in */} + {/* Send Code button */} +

2-step Verification

+

Select your 2-step verification method

+ +
Current
+ +
Verification Options
+

Authenticator

+ +

user 2-step verification to secure every transaction

+

Any amount of transaction

+

Never Least Secure

+ {/* Save button component */} + +
+
+ ) +} + +export default FinancialServicies diff --git a/Front-end/vessel-app/src/components/settingsComponents/LinkedAccounts.js b/Front-end/vessel-app/src/components/settingsComponents/LinkedAccounts.js new file mode 100644 index 0000000..a367372 --- /dev/null +++ b/Front-end/vessel-app/src/components/settingsComponents/LinkedAccounts.js @@ -0,0 +1,16 @@ +import React from 'react' + +const LinkedAccounts = () => { + return ( +
+
+

Payments Methods

+ + +

Component list out avabile payment methods [Remove button]

+
+
+ ) +} + +export default LinkedAccounts diff --git a/Front-end/vessel-app/src/components/settingsComponents/NavbarElements.js b/Front-end/vessel-app/src/components/settingsComponents/NavbarElements.js new file mode 100644 index 0000000..9fc589d --- /dev/null +++ b/Front-end/vessel-app/src/components/settingsComponents/NavbarElements.js @@ -0,0 +1,86 @@ +import { FaBars } from 'react-icons/fa'; +import { NavLink as Link } from 'react-router-dom'; +import styled from 'styled-components'; + +export const Nav = styled.nav` + background: #f5f5f5; + height: 85px; + display: flex; + justify-content: space-between; + padding: 0.2rem calc((100vw - 1000px) / 2); + z-index: 12; + /* Third Nav */ + /* justify-content: flex-start; */ +`; + +export const NavLink = styled(Link)` + color: #808080; + display: flex; + align-items: center; + text-decoration: none; + padding: 0 1rem; + height: 100%; + cursor: pointer; + &.active { + color: #000000; + } +`; + +export const Bars = styled(FaBars)` + display: none; + color: #808080; + @media screen and (max-width: 768px) { + display: block; + position: absolute; + top: 0; + right: 0; + transform: translate(-100%, 75%); + font-size: 1.2rem; + cursor: pointer; + } +`; + +export const NavMenu = styled.div` + display: flex; + align-items: left; + margin-right: -24px; + /* Second Nav */ + /* margin-right: 24px; */ + /* Third Nav */ + /* width: 100vw; + white-space: nowrap; */ + @media screen and (max-width: 768px) { + display: none; + } +`; + +export const NavBtn = styled.nav` + display: flex; + align-items: center; + margin-right: 24px; + /* Third Nav */ + /* justify-content: flex-end; + width: 100vw; */ + @media screen and (max-width: 768px) { + display: none; + } +`; + +export const NavBtnLink = styled(Link)` + border-radius: 4px; + background: #808080; + padding: 10px 22px; + color: #000000; + outline: none; + border: none; + cursor: pointer; + transition: all 0.2s ease-in-out; + text-decoration: none; + /* Second Nav */ + margin-left: 24px; + &:hover { + transition: all 0.2s ease-in-out; + background: #fff; + color: #808080; + } +`; \ No newline at end of file diff --git a/Front-end/vessel-app/src/components/settingsComponents/Preferences.js b/Front-end/vessel-app/src/components/settingsComponents/Preferences.js new file mode 100644 index 0000000..a9325ab --- /dev/null +++ b/Front-end/vessel-app/src/components/settingsComponents/Preferences.js @@ -0,0 +1,20 @@ +import React from 'react' + +const Preferences = () => { + return ( +
+
+

Preferences

+ +

Local currency Drop Down

+

Time Zone Drop Down

+ + {/* we need a save component */} + + +
+
+ ) +} + +export default Preferences diff --git a/Front-end/vessel-app/src/components/settingsComponents/PrivacyRights.js b/Front-end/vessel-app/src/components/settingsComponents/PrivacyRights.js new file mode 100644 index 0000000..328acf7 --- /dev/null +++ b/Front-end/vessel-app/src/components/settingsComponents/PrivacyRights.js @@ -0,0 +1,30 @@ +import React from 'react' + +const PrivacyRights = () => { + return ( +
+
+ +

Privacy options

+ +
Request Data
+

Recevie a copy of personal data held by OpenVessel

+ {/* component button */} +
Request Deletion of Data
+

Delete specific data or all of my data

+ +
Request Export of Data
+

Export of my data in machine-readable form

+ +
Request Correction of Data
+

Correct, modify, or complete Data

+ +
Manage Cookies
+

Preferences for cookies

+ +
+
+ ) +} + +export default PrivacyRights diff --git a/Front-end/vessel-app/src/components/settingsComponents/Settings.js b/Front-end/vessel-app/src/components/settingsComponents/Settings.js new file mode 100644 index 0000000..4d238e5 --- /dev/null +++ b/Front-end/vessel-app/src/components/settingsComponents/Settings.js @@ -0,0 +1,109 @@ +import React, {useContext, useState} from 'react' +import {Context} from "../../appContext/UserContext" +import profileImg from '../../images/default_user.png' + +const Settings = () => { + + const{store, actions } = useContext(Context); + const[email, setEmail] = useState(""); + const Webpage = 'Account' + const username = store.username + const DisplayEmail = store.email + + const [image, setImage] = useState({ preview: profileImg, raw: "" }); + + const handleChange = e => { + console.log(e.target.files[0]); + if (e.target.files.length) { + setImage({ + preview: URL.createObjectURL(e.target.files[0]), + raw: e.target.files[0] + }); + } + }; + + + const handleClick = () => { + console.log("Hello World") + + + actions.changeAccount( store.token_id, + store.csrf_token, + username, + email, + Webpage, + image + ); + // we need a function from actions to send post request to flask to update account information + // history.push("/login"); + }; + + + return ( +
+ {/* */} +
+

My Profile

+ +

Display name

+ + +

Email address

+ + + + + {/* We need component to send saved data to backend */} + + + +

Personal Detials

+
+

Legal name

+ + +

Date of Birth

+ {/* https://bootsnipp.com/snippets/MaKa3 */} +

Scrollable Dropdown Menu

+ +

Street Address

+ + +

Unit#

+ + +

City/town

State

+ + + +

Postal Code

Country

+ + + {/* We need component to send saved data to backend */} + +
+ + +
+
+ + ) +} + +export default Settings diff --git a/Front-end/vessel-app/src/components/settingsComponents/SubNavBar.js b/Front-end/vessel-app/src/components/settingsComponents/SubNavBar.js new file mode 100644 index 0000000..e7ffbd0 --- /dev/null +++ b/Front-end/vessel-app/src/components/settingsComponents/SubNavBar.js @@ -0,0 +1,47 @@ +import React from 'react' +import { + Nav, + NavLink, + Bars, + NavMenu, + NavBtn, + NavBtnLink, + } from './NavbarElements'; +// src\components\settingsComponents\SettingsNavBarElements +const SubNavBar = () => { + return ( +
+ +
+ ) +} + +export default SubNavBar diff --git a/Front-end/vessel-app/src/components/settingsComponents/SubRender.js b/Front-end/vessel-app/src/components/settingsComponents/SubRender.js new file mode 100644 index 0000000..5b26783 --- /dev/null +++ b/Front-end/vessel-app/src/components/settingsComponents/SubRender.js @@ -0,0 +1,115 @@ +import React from 'react' +import SubNavBar from './SubNavBar' +import Settings from './Settings' +import Preferences from './Preferences' +import FinancialServicies from './FinancialServicies' +import AccountLevels from './AccountLevels' +import PrivacyRights from './PrivacyRights' +import LinkedAccounts from './LinkedAccounts' +import CryptoAddress from './CryptoAddress' + +class SubRender extends React.Component { + + render(){ + if(this.props.localurl ==='/settings'){ + return ( + +
+
+ +

{this.props.localurl}

+ + +
+
+ ) + } + if(this.props.localurl ==='/'){ + return ( + +
+
+ +

{this.props.localurl}

+ + +
+
+ ) + } + if(this.props.localurl ==='/account-levels'){ + return ( + +
+
+ +

{this.props.localurl}

+ +
+
+ ) + } + if(this.props.localurl ==='/preferences'){ + return ( + +
+
+ +

{this.props.localurl}

+ +
+
+ ) + } + if(this.props.localurl ==='/Financial-services'){ + return ( + +
+
+ +

{this.props.localurl}

+ +
+
+ ) + } + if(this.props.localurl ==='/privacy-rights'){ + return ( + +
+
+ +

{this.props.localurl}

+ +
+
+ ) + } + if(this.props.localurl ==='/Linked-accounts'){ + return ( + +
+
+ +

{this.props.localurl}

+ +
+
+ ) + } + if(this.props.localurl ==='/crypto-address'){ + return ( + +
+
+ +

{this.props.localurl}

+ +
+
+ ) + } + + } +} +export default SubRender \ No newline at end of file diff --git a/Front-end/vessel-app/src/css/theme_skeleton.css b/Front-end/vessel-app/src/css/theme_skeleton.css index 362506c..cf68d3d 100644 --- a/Front-end/vessel-app/src/css/theme_skeleton.css +++ b/Front-end/vessel-app/src/css/theme_skeleton.css @@ -137,9 +137,18 @@ img { /* card login right had side */ .card_login2 { - background: #06007A; - margin:3%; - padding:10px; + background-size: cover; + background-position: center center; + height: 100%; + background-repeat: no-repeat; + background-image: + linear-gradient(180deg, + rgba( 145, 146, 122, 0.62), + rgb(27, 120, 229)), url( +'../images/shutterstock_1771500629.jpg'); + width: 100%; + padding:20px; + } /* card login text */ .card_login2 p { @@ -195,6 +204,35 @@ height: 100%; font-size:25px; } +.PostionImg { + text-align: left; + +} + +.SubNavStyle a { + + font-size:18px !important; +} + + +/* TextBoxCenter */ +.TextBoxCenter { + + margin:3%; + padding:10px; + color:#fff; + text-align: center; +} +.TextBoxCenter h1 { + color:#fff; +} +.TextBoxCenter p { + font-size: 5 px; +} +.TextBoxCenter img { + width: 155px; /* width of image (px or % or auto) */ + height: auto; /* height of image (px or % or auto) */ +} /* https://css-tricks.com/snippets/css/a-guide-to-flexbox/ */ .nav-menu { display:grid; @@ -547,15 +585,15 @@ a:active { .btn-main { - color: #2A3C3A !important; - background-color: whitesmoke; + color: #fff !important; + background-color: #1B78E5; border-radius: 5px; outline-width: 0px; display: inline-block; border: none; padding: 10px 20px; margin: 5px; - border-radius: 0px; + border-radius: 3px; cursor: pointer; text-decoration: none; font-size: 15px; diff --git a/Front-end/vessel-app/src/formCode/useForm.js b/Front-end/vessel-app/src/formCode/useForm.js index b4d5f17..024ec47 100644 --- a/Front-end/vessel-app/src/formCode/useForm.js +++ b/Front-end/vessel-app/src/formCode/useForm.js @@ -31,6 +31,7 @@ const useForm = (callback, validate) => { setErrors(validate(values)); setIsSubmitting(true); + if(isSubmitting && errors.ValidateRequest === true) { console.log(isSubmitting, "test") actions.registration( @@ -42,13 +43,25 @@ const useForm = (callback, validate) => { values.email, values.password, values.confirmpassword); + + console.log(window.sessionStorage.getItem("return_msg")) + // submit on request Success this triggers redirect? + // setReturnMsg(window.sessionStorage.getItem("return_msg")) + // if(msg === 'Your account has been created! You are now able to log in'){ + // console.log + // + // } + const moveOn = false + console.log(errors.ValidateRequest) + if(errors.ValidateRequest === true) { + console.log("hello movOn Trigger") + if(window.sessionStorage.getItem("return_msg") === 'Your account has been created! You are now able to log in') { + const moveOn = true + } + } + + } - - setReturnMsg(window.sessionStorage.getItem("return_msg")) - if(msg === 'Your account has been created! You are now able to log in'){ - actions.redirect(msg) - } - }; useEffect( @@ -60,7 +73,7 @@ const useForm = (callback, validate) => { [errors] ); - return { handleChange, handleSubmit, values, errors }; + return { handleChange, handleSubmit, values, errors}; }; export default useForm; \ No newline at end of file diff --git a/Front-end/vessel-app/src/pages/Account.js b/Front-end/vessel-app/src/pages/Account.js index 413ada8..be07370 100644 --- a/Front-end/vessel-app/src/pages/Account.js +++ b/Front-end/vessel-app/src/pages/Account.js @@ -1,121 +1,23 @@ -import React, {useContext, useState} from 'react' -import {Context} from "../appContext/UserContext" -import profileImg from '../images/default_user.png' +import React from 'react' +import {useLocation } from 'react-router-dom'; +import SubRender from '../components/settingsComponents/SubRender'; const Account = () => { - - const{store, actions } = useContext(Context); - const[email, setEmail] = useState(""); - const Webpage = 'Account' - const username = store.username - const DisplayEmail = store.email - - const [image, setImage] = useState({ preview: profileImg, raw: "" }); - - const handleChange = e => { - console.log(e.target.files[0]); - if (e.target.files.length) { - setImage({ - preview: URL.createObjectURL(e.target.files[0]), - raw: e.target.files[0] - }); + const location2 = useLocation() + console.log(location2.pathname) + // if url changes we conditional render SubNavBar + if([ + '/account-levels','/Linked-accounts', + '/privacy-rights','/Financial-services', + '/preferences','/crypto-address','/settings','/'].includes(location2.pathname)) { + const localPass = location2.pathname + return } - }; - - - // const handleUpload = async e => { - // e.preventDefault(); - // const formData = new FormData(); - // formData.append("image", image.raw); - // return formData - // }; - const handleClick = () => { - console.log("Hello World") - - - actions.changeAccount( store.token_id, - store.csrf_token, - username, - email, - Webpage, - image - ); - // we need a function from actions to send post request to flask to update account information - // history.push("/login"); - }; return (
- - {/* */} - -
-
-
-
-
- Account Image -

{username }

-

{ DisplayEmail }

-
-
-
- - {/* ACCOUNT INFO */} - -
- -
- Account info - {/* EMAIL */} -
- - setEmail(e.target.value)} /> - {/* */} -
- {/* IMAGE UPLOAD */} -
- - - -
- - -
-
- -
- - - - -
-
- -
+
) } diff --git a/Front-end/vessel-app/src/pages/EMF.js b/Front-end/vessel-app/src/pages/EMF.js index e5a551d..efc7c1a 100644 --- a/Front-end/vessel-app/src/pages/EMF.js +++ b/Front-end/vessel-app/src/pages/EMF.js @@ -1,7 +1,11 @@ -import React from 'react' +import React, {useContext} from 'react' import ProgressBar from '../components/ProgressBar' import Deposit from '../components/Deposit' +import {Context} from "../appContext/UserContext" const EMF = () => { + + + const{store, actions } = useContext(Context); return (
diff --git a/Front-end/vessel-app/src/pages/Login.js b/Front-end/vessel-app/src/pages/Login.js index 4ff412a..d0864de 100644 --- a/Front-end/vessel-app/src/pages/Login.js +++ b/Front-end/vessel-app/src/pages/Login.js @@ -19,7 +19,7 @@ const Login = () => { console.log("loggin") actions.login(username, password); }; - + // this is the redirect push to another webpage after login is successfull if (store.token && store.token !== "" && store.token !== undefined) history.push("/Account"); return (
@@ -30,6 +30,21 @@ const Login = () => { ):(
+
+
+
+ OpenVessel Logo +
+
+ +

Get Started today.

+

Insurance is about spreading risk to the greater community + if it’s a business or if it’s someone’s Health, Blockchain has + a lot of spread and future growth but this doesn’t impact + our healthcare system or people’s lives

+
+
+
{/* We have component controller component */} @@ -56,9 +71,7 @@ const Login = () => {
-
-

Hello

-
+
)}
diff --git a/Front-end/vessel-app/yarn.lock b/Front-end/vessel-app/yarn.lock index 843465a..ea177d9 100644 --- a/Front-end/vessel-app/yarn.lock +++ b/Front-end/vessel-app/yarn.lock @@ -59,7 +59,7 @@ "jsesc" "^2.5.1" "source-map" "^0.5.0" -"@babel/helper-annotate-as-pure@^7.10.4", "@babel/helper-annotate-as-pure@^7.12.13": +"@babel/helper-annotate-as-pure@^7.0.0", "@babel/helper-annotate-as-pure@^7.10.4", "@babel/helper-annotate-as-pure@^7.12.13": "integrity" "sha512-7YXfX5wQ5aYM/BOlbSccHDbuXXFPxeoUmfWtz8le2yTkTZc+BxsiEnENFoi2SlmA8ewDkG2LgIMIVzzn2h8kfw==" "resolved" "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.13.tgz" "version" "7.12.13" @@ -1160,7 +1160,7 @@ "@babel/parser" "^7.12.13" "@babel/types" "^7.12.13" -"@babel/traverse@^7.1.0", "@babel/traverse@^7.12.1", "@babel/traverse@^7.13.0", "@babel/traverse@^7.13.15", "@babel/traverse@^7.14.0", "@babel/traverse@^7.14.2", "@babel/traverse@^7.7.0": +"@babel/traverse@^7.1.0", "@babel/traverse@^7.12.1", "@babel/traverse@^7.13.0", "@babel/traverse@^7.13.15", "@babel/traverse@^7.14.0", "@babel/traverse@^7.14.2", "@babel/traverse@^7.4.5", "@babel/traverse@^7.7.0": "integrity" "sha512-TsdRgvBFHMyHOOzcP9S6QU0QQtjxlRpEYOy3mcCO5RgmC305ki42aSAmfZEMSSYBla2oZ9BMqYlncBaKmD/7iA==" "resolved" "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.2.tgz" "version" "7.14.2" @@ -1210,6 +1210,28 @@ "resolved" "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz" "version" "0.8.0" +"@emotion/is-prop-valid@^0.8.8": + "integrity" "sha512-u5WtneEAr5IDG2Wv65yhunPSMLIpuKsbuOktRojfrEiEvRyC85LgPMZI63cr7NUqT8ZIGdSVg8ZKGxIug4lXcA==" + "resolved" "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-0.8.8.tgz" + "version" "0.8.8" + dependencies: + "@emotion/memoize" "0.7.4" + +"@emotion/memoize@0.7.4": + "integrity" "sha512-Ja/Vfqe3HpuzRsG1oBtWTHk2PGZ7GR+2Vz5iYGelAw8dx32K0y7PjVuxK6z1nMpZOqAFsRUPCkK1YjJ56qJlgw==" + "resolved" "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.7.4.tgz" + "version" "0.7.4" + +"@emotion/stylis@^0.8.4": + "integrity" "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==" + "resolved" "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz" + "version" "0.8.5" + +"@emotion/unitless@^0.7.4": + "integrity" "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==" + "resolved" "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz" + "version" "0.7.5" + "@eslint/eslintrc@^0.3.0": "integrity" "sha512-1JTKgrOKAHVivSvOYw+sJOunkBjUOvjqWk1DPja7ZFhIS2mX/4EgTT8M7eTK9jrKhL/FvXXEbQwIs3pg1xp3dg==" "resolved" "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.3.0.tgz" @@ -2765,6 +2787,21 @@ dependencies: "@babel/helper-define-polyfill-provider" "^0.2.2" +"babel-plugin-styled-components@>= 1.12.0": + "integrity" "sha512-Vb1R3d4g+MUfPQPVDMCGjm3cDocJEUTR7Xq7QS95JWWeksN1wdFRYpD2kulDgI3Huuaf1CZd+NK4KQmqUFh5dA==" + "resolved" "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-1.13.2.tgz" + "version" "1.13.2" + dependencies: + "@babel/helper-annotate-as-pure" "^7.0.0" + "@babel/helper-module-imports" "^7.0.0" + "babel-plugin-syntax-jsx" "^6.18.0" + "lodash" "^4.17.11" + +"babel-plugin-syntax-jsx@^6.18.0": + "integrity" "sha1-CvMqmm4Tyno/1QaeYtew9Y0NiUY=" + "resolved" "https://registry.npmjs.org/babel-plugin-syntax-jsx/-/babel-plugin-syntax-jsx-6.18.0.tgz" + "version" "6.18.0" + "babel-plugin-syntax-object-rest-spread@^6.8.0": "integrity" "sha1-/WU28rzhODb/o6VFjEkDpZe7O/U=" "resolved" "https://registry.npmjs.org/babel-plugin-syntax-object-rest-spread/-/babel-plugin-syntax-object-rest-spread-6.13.0.tgz" @@ -3247,6 +3284,11 @@ "resolved" "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz" "version" "5.3.1" +"camelize@^1.0.0": + "integrity" "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=" + "resolved" "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz" + "version" "1.0.0" + "caniuse-api@^3.0.0": "integrity" "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==" "resolved" "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz" @@ -3865,6 +3907,11 @@ dependencies: "postcss" "^7.0.5" +"css-color-keywords@^1.0.0": + "integrity" "sha1-/qJhbcZ2spYmhrOvjb2+GAskTgU=" + "resolved" "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz" + "version" "1.0.0" + "css-color-names@^0.0.4", "css-color-names@0.0.4": "integrity" "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=" "resolved" "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz" @@ -3937,6 +3984,15 @@ "domutils" "^2.6.0" "nth-check" "^2.0.0" +"css-to-react-native@^3.0.0": + "integrity" "sha512-Ro1yETZA813eoyUp2GDBhG2j+YggidUmzO1/v9eYBKR2EHVEniE2MI/NqpTQ954BMpTPZFsGNPm46qFB9dpaPQ==" + "resolved" "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.0.0.tgz" + "version" "3.0.0" + dependencies: + "camelize" "^1.0.0" + "css-color-keywords" "^1.0.0" + "postcss-value-parser" "^4.0.2" + "css-tree@^1.1.2": "integrity" "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==" "resolved" "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz" @@ -5735,7 +5791,7 @@ "minimalistic-assert" "^1.0.0" "minimalistic-crypto-utils" "^1.0.1" -"hoist-non-react-statics@^3.1.0", "hoist-non-react-statics@^3.3.2": +"hoist-non-react-statics@^3.0.0", "hoist-non-react-statics@^3.1.0", "hoist-non-react-statics@^3.3.2": "integrity" "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==" "resolved" "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz" "version" "3.3.2" @@ -9448,7 +9504,7 @@ "strip-ansi" "6.0.0" "text-table" "0.2.0" -"react-dom@^16.8.0 || ^17.0.0", "react-dom@^17.0.2", "react-dom@>=16.6.0": +"react-dom@^16.8.0 || ^17.0.0", "react-dom@^17.0.2", "react-dom@>= 16.8.0", "react-dom@>=16.6.0": "integrity" "sha512-s4h96KtLDUQlsENhMn1ar8t2bEa+q/YAtj8pPPdIjPDGBDIVNsrD9aXNWqspUe6AzKCIG0C1HZZLqLV7qpOBGA==" "resolved" "https://registry.npmjs.org/react-dom/-/react-dom-17.0.2.tgz" "version" "17.0.2" @@ -9479,7 +9535,12 @@ dependencies: "attr-accept" "^1.0.3" -"react-is@^16.6.0", "react-is@^16.7.0", "react-is@^16.8.0 || ^17.0.0", "react-is@^16.8.1": +"react-icons@^4.2.0": + "integrity" "sha512-rmzEDFt+AVXRzD7zDE21gcxyBizD/3NqjbX6cmViAgdqfJ2UiLer8927/QhhrXQV7dEj/1EGuOTPp7JnLYVJKQ==" + "resolved" "https://registry.npmjs.org/react-icons/-/react-icons-4.2.0.tgz" + "version" "4.2.0" + +"react-is@^16.6.0", "react-is@^16.7.0", "react-is@^16.8.0 || ^17.0.0", "react-is@^16.8.1", "react-is@>= 16.8.0": "integrity" "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" "resolved" "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz" "version" "16.13.1" @@ -9607,7 +9668,7 @@ "loose-envify" "^1.4.0" "prop-types" "^15.6.2" -"react@^16.8.0 || ^17.0.0", "react@^17.0.2", "react@>=0.14.7", "react@>=16.6.0": +"react@*", "react@^16.8.0 || ^17.0.0", "react@^17.0.2", "react@>= 16.8.0", "react@>=0.14.7", "react@>=16.6.0": "integrity" "sha512-gnhPt75i/dq/z3/6q/0asP78D0u592D5L1pd7M8P+dck6Fu/jJeL6iVVK23fptSUZj8Vjf++7wXA8UNclGQcbA==" "resolved" "https://registry.npmjs.org/react/-/react-17.0.2.tgz" "version" "17.0.2" @@ -10388,6 +10449,11 @@ "inherits" "^2.0.1" "safe-buffer" "^5.0.1" +"shallowequal@^1.1.0": + "integrity" "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==" + "resolved" "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz" + "version" "1.1.0" + "shebang-command@^1.2.0": "integrity" "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=" "resolved" "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz" @@ -10908,6 +10974,22 @@ "loader-utils" "^2.0.0" "schema-utils" "^2.7.0" +"styled-components@^5.3.1", "styled-components@>= 2": + "integrity" "sha512-JThv2JRzyH0NOIURrk9iskdxMSAAtCfj/b2Sf1WJaCUsloQkblepy1jaCLX/bYE+mhYo3unmwVSI9I5d9ncSiQ==" + "resolved" "https://registry.npmjs.org/styled-components/-/styled-components-5.3.1.tgz" + "version" "5.3.1" + dependencies: + "@babel/helper-module-imports" "^7.0.0" + "@babel/traverse" "^7.4.5" + "@emotion/is-prop-valid" "^0.8.8" + "@emotion/stylis" "^0.8.4" + "@emotion/unitless" "^0.7.4" + "babel-plugin-styled-components" ">= 1.12.0" + "css-to-react-native" "^3.0.0" + "hoist-non-react-statics" "^3.0.0" + "shallowequal" "^1.1.0" + "supports-color" "^5.5.0" + "stylehacks@^4.0.0": "integrity" "sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g==" "resolved" "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz" @@ -10924,6 +11006,13 @@ dependencies: "has-flag" "^3.0.0" +"supports-color@^5.5.0": + "integrity" "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==" + "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" + "version" "5.5.0" + dependencies: + "has-flag" "^3.0.0" + "supports-color@^6.1.0": "integrity" "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==" "resolved" "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz"