apps2innovate:
Any ideas?
Below is my Complete App.jsx
Where I use firebase Login, User Profile Creation and Logout.
import React from 'react';
import { Device } from 'framework7/framework7-lite.esm.bundle.js';
import {
App,
Panel,
Views,
View,
Popup,
Page,
Navbar,
Toolbar,
NavRight,
Link,
Block,
BlockTitle,
LoginScreen,
LoginScreenTitle,
List,
ListItem,
ListInput,
ListButton,
BlockFooter
} from 'framework7-react';
import cordovaApp from '../js/cordova-app';
import routes from '../js/routes';
import StyledFirebaseAuth from 'react-firebaseui/StyledFirebaseAuth';
import firebase from 'firebase/app';
import 'firebase/auth';
import 'firebase/firestore';
// Configure Firebase.
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
apiKey: "XXXXXXXXXXXXX-XXXXXXXXXXXXX",
authDomain: "my-sample-react-app.firebaseapp.com",
projectId: "my-sample-react-app",
storageBucket: "my-sample-react-app.appspot.com",
messagingSenderId: "XXXXXXXXXXX",
appId: "XXXXXXXXXXXXXX",
measurementId: "G-XXXXXXXXXXX"
};
firebase.initializeApp(firebaseConfig);
//secondaryFireApp
// var secondaryFireApp = firebase.initializeApp(firebaseConfig, "Secondary");
// Configure FirebaseUI.
// firebase.auth.EmailAuthProvider.PROVIDER_ID, firebase.auth.GoogleAuthProvider.PROVIDER_ID, firebase.auth.FacebookAuthProvider.PROVIDER_ID
// FirebaseUI config.
const uiConfig = {
// Popup signin flow rather than redirect flow.
signInFlow: 'popup',
signInSuccessUrl: '/',
signInOptions: [
{
provider: firebase.auth.PhoneAuthProvider.PROVIDER_ID,
recaptchaParameters: {
type: 'image', // 'audio'
size: 'invisible', // 'invisible' or 'compact'
badge: 'bottomleft' //' bottomright' or 'inline' applies to invisible.
},
defaultCountry: 'LK',
},
{
provider: firebase.auth.EmailAuthProvider.PROVIDER_ID,
requireDisplayName: false
},
{
provider: firebase.auth.GoogleAuthProvider.PROVIDER_ID
}
],
// tosUrl and privacyPolicyUrl accept either url string or a callback
// function.
// Terms of service url/callback.
tosUrl: '<your-tos-url>',
// Privacy policy url/callback.
privacyPolicyUrl: function () {
window.location.assign('<your-privacy-policy-url>');
},
callbacks: {
// Avoid redirects after sign-in.
signInSuccessWithAuthResult: () => true,
// signInFailure callback must be provided to handle merge conflicts which
// occur when an existing credential is linked to an anonymous user.
signInFailure: function (error) {
console.log("signInFailure :: ", error);
// For merge conflicts, the error.code will be
// 'firebaseui/anonymous-upgrade-merge-conflict'.
if (error.code != 'firebaseui/anonymous-upgrade-merge-conflict') {
return Promise.resolve();
}
// The credential the user tried to sign in with.
var cred = error.credential;
// Copy data from anonymous user to permanent user and delete anonymous
// user.
// ...
// Finish sign-in after data is copied.
return firebase.auth().signInWithCredential(cred);
}
}
};
export default class extends React.Component {
constructor() {
super();
this.state = {
// Framework7 Parameters
f7params: {
version: '1.0.0',
id: 'Org.My-React.WebApp', // App bundle ID
name: 'My React', // App name
theme: 'auto', // Automatic theme detection
// App root data
data: function () {
return {
// Demo products for Catalog section
products: [
{
id: '1',
title: 'Apple iPhone 8',
description: 'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Nisi tempora similique reiciendis, error nesciunt vero, blanditiis pariatur dolor, minima sed sapiente rerum, dolorem corrupti hic modi praesentium unde saepe perspiciatis.'
},
{
id: '2',
title: 'Apple iPhone 8 Plus',
description: 'Velit odit autem modi saepe ratione totam minus, aperiam, labore quia provident temporibus quasi est ut aliquid blanditiis beatae suscipit odio vel! Nostrum porro sunt sint eveniet maiores, dolorem itaque!'
},
{
id: '3',
title: 'Apple iPhone X',
description: 'Expedita sequi perferendis quod illum pariatur aliquam, alias laboriosam! Vero blanditiis placeat, mollitia necessitatibus reprehenderit. Labore dolores amet quos, accusamus earum asperiores officiis assumenda optio architecto quia neque, quae eum.'
},
],
user: {},
isSignedIn: false
};
},
// App root methods
methods: {
updateFirebaseUser: function (currentUser, rootSelf) {
// console.log('updateFirebaseUser :: init');
// console.log('updateFirebaseUser :: rootSelf', rootSelf);
const self = rootSelf;
//updateProfile
currentUser.updateProfile({
displayName: self.state.userDisplayName,
photoURL: '../static/icons/128x128.png'
}).then(function () {
// Update successful.
}).catch(function () {
// An error happened.
});
},
saveLoggedInUser: function (rootSelf) {
// console.log('saveLoggedInUser :: init');
// console.log('saveLoggedInUser :: rootSelf', rootSelf);
const self = rootSelf;
const isValid = this.input.validateInputs('#userForm');
if (isValid) {
this.preloader.show();
var currentUser = firebase.auth().currentUser;
var db = firebase.firestore();
//update firebase user profile
this.methods.updateFirebaseUser(currentUser, self);
if (!self.state.userProfile) {
//create new user in db
db.collection("users").doc(currentUser.uid).set({
userDisplayName: self.state.userDisplayName,
userMob: self.state.userMob,
userDocument: self.state.userDocument,
userAddressLine1: self.state.userAddressLine1,
userAddressLine2: self.state.userAddressLine2,
userCity: self.state.userCity,
userPostalCode: self.state.userPostalCode,
userCountry: self.state.userCountry,
userPoints: 1000,
userGuide: false,
}).then(function () {
self.$f7.preloader.hide();
console.log("Document Successfully Written.");
self.$f7.dialog.alert("Account Created Successfully.", "Success!", () => {
self.$f7.popup.close('#my-popup');
self.setState({
userProfile: true,
});
self.$f7.methods.updateAppUser(currentUser, self);
});
}).catch(function (error) {
self.$f7.preloader.hide();
console.error("Error writing document: ", error);
self.$f7.dialog.alert("Error on Account Creation.", "Error!");
});
} else {
//update user in db
db.collection("users").doc(currentUser.uid).update({
userDisplayName: self.state.userDisplayName,
userMob: self.state.userMob,
userDocument: self.state.userDocument,
userAddressLine1: self.state.userAddressLine1,
userAddressLine2: self.state.userAddressLine2,
userCity: self.state.userCity,
userPostalCode: self.state.userPostalCode,
userCountry: self.state.userCountry,
}).then(function () {
self.$f7.preloader.hide();
console.log("Document Successfully written.");
self.$f7.dialog.alert("Account Updated Successfully.", "Success!", () => {
self.$f7.popup.close('#my-popup');
self.setState({
userProfile: true,
});
self.$f7.methods.updateAppUser(currentUser, self);
});
}).catch(function (error) {
self.$f7.preloader.hide();
console.error("Error writing document: ", error);
self.$f7.dialog.alert("Error on Account Update.", "Error!");
});
}
}
},
updateAppUser: function (currentUser, rootSelf) {
// console.log('updateAppUser :: init');
// console.log('updateAppUser :: rootSelf', rootSelf);
const self = rootSelf;
var db = firebase.firestore();
//update localStorage
if (!currentUser) {
this.data.isSignedIn = false;
this.data.user = [];
self.setState({
isSignedIn: false,
userProfile: false,
});
let requiredLoginToast = this.toast.create({
text: 'Please sign in.',
closeTimeout: 3000,
});
requiredLoginToast.open();
} else {
//get user info from db
var docRef = db.collection("users").doc(currentUser.uid);
docRef.get().then(function (doc) {
if (doc.exists) {
var userData = doc.data();
console.log("Document data:", userData);
self.$f7.data.isSignedIn = true;
self.$f7.data.user.displayName = currentUser.displayName;
self.$f7.data.user.photoURL = currentUser.photoURL;
self.$f7.data.user.phoneNumber = userData.userMob;
//tour guide boolean
self.$f7.data.user.tourGuide = userData.userGuide;
//user info
self.$f7.data.user.userDisplayName = userData.userDisplayName;
self.$f7.data.user.userMob = userData.userMob;
self.$f7.data.user.userDocument = userData.userDocument;
self.$f7.data.user.userAddressLine1 = userData.userAddressLine1;
self.$f7.data.user.userAddressLine2 = userData.userAddressLine2;
self.$f7.data.user.userCity = userData.userCity;
self.$f7.data.user.userPostalCode = userData.userPostalCode;
self.$f7.data.user.userCountry = userData.userCountry;
self.$f7.data.user.userPoints = userData.userPoints;
//set States
self.setState({
isSignedIn: true,
userProfile: true,
userDisplayName: self.$f7.data.user.userDisplayName,
userMob: self.$f7.data.user.userMob,
userDocument: self.$f7.data.user.userDocument,
userAddressLine1: self.$f7.data.user.userAddressLine1,
userAddressLine2: self.$f7.data.user.userAddressLine2,
userCity: self.$f7.data.user.userCity,
userPostalCode: self.$f7.data.user.userPostalCode,
userCountry: self.$f7.data.user.userCountry,
userPoints: self.$f7.data.user.userPoints,
});
let userLoggedInToast = self.$f7.toast.create({
text: 'Logged In Successfully.',
closeTimeout: 3000,
});
userLoggedInToast.open();
//check user Account Code
// if (!userData.userAccountCode) {
// self.popup.open('#my-popup');
// }
} else {
// doc.data() will be undefined in this case
console.log("No such user!");
}
}).catch(function (error) {
console.log("Error getting user:", error);
});
}
this.preloader.hide();
},
userLogout: function (rootSelf) {
console.log('userLogout :: init');
const self = rootSelf;
firebase.auth().signOut().then(() => {
// Sign-out successful.
var toast_SuccessLogOut = self.$f7.toast.create({
text: 'Logged Out Successfully.',
closeTimeout: 3000,
});
setTimeout(() => {
window.location.href = "/";
}, 3000);
toast_SuccessLogOut.open();
}).catch((error) => {
// Handle Errors here.
let toast_AppError = self.$f7.toast.create({
text: 'Connectivity Problem!',
closeTimeout: 3000,
});
toast_AppError.open();
});
},
},
// App view
view: {
pushState: true,
stackPages: true,
},
// App routes
routes: routes,
// Register service worker
serviceWorker: Device.cordova ? {} : {
path: '/service-worker.js',
},
// Input settings
input: {
scrollIntoViewOnFocus: Device.cordova && !Device.electron,
scrollIntoViewCentered: Device.cordova && !Device.electron,
},
// Cordova Statusbar settings
statusbar: {
iosOverlaysWebView: true,
androidOverlaysWebView: false,
},
},
// Login screen demo data
userProfile: false,
userGuide: false,
userDisplayName: '',
userMob: '',
userDocument: '',
userEmail: '',
userAddressLine1: '',
userAddressLine2: '',
userCity: '',
userPostalCode: '',
userCountry: '',
userPoints: 0,
}
}
render() {
return (
<App params={this.state.f7params} >
{/* Left panel with cover effect*/}
<Panel left cover themeDark>
<View>
<Page>
<Navbar title="Left Panel" />
<Block>Left panel content goes here</Block>
</Page>
</View>
</Panel>
{/* Right panel with reveal effect*/}
<Panel right reveal>
<View>
<Page>
<Navbar title={this.state.isSignedIn ? firebase.auth().currentUser.displayName !== null ? firebase.auth().currentUser.displayName : 'My Account' : 'Login'} />
{/* Toolbar */}
<Toolbar bottom>
<Link className="width-100">All Rights Reserved</Link>
</Toolbar>
{
this.state.isSignedIn ? (
<Block>
<p>Welcome, {firebase.auth().currentUser.displayName} ! You are now signed-in.</p>
<List>
<ListItem link="/settings/" title="Settings" view=".view-main" panelClose>
<Icon slot="media" f7="gear_alt" color="primary"></Icon>
</ListItem>
<ListItem link="#" title="Logout" onClick={() => this.$f7.methods.userLogout(this)} view=".view-main" panelClose>
<Icon slot="media" f7="power" color="primary"></Icon>
</ListItem>
</List>
</Block>
) : (
<Block>
<p>Please login to your account.</p>
<List>
<ListItem link="#" title="Login" loginScreenOpen="#my-login-screen" panelClose>
<Icon slot="media" f7="person" color="primary"></Icon>
</ListItem>
</List>
</Block>
)
}
</Page>
</View>
</Panel>
{/* Your main view, should have "view-main" class */}
<View main className="safe-areas" url="/" />
{/* Popup */}
<Popup id="my-popup">
<View>
<Page>
<Navbar title="My Account">
{
<NavRight>
{this.state.userProfile ? <Link popupClose iconF7="xmark_circle"></Link> : ''}
</NavRight>
}
</Navbar>
<BlockTitle>Update Your Account</BlockTitle>
<Block noHairlines>
<List form id="userForm">
<ListInput
label="Display Name"
type="text"
placeholder="Jemmy Jackson"
inputId="userDisplayName"
defaultValue={this.state.userDisplayName}
onInput={(e) => this.setState({ userDisplayName: e.target.value })}
required
validate
></ListInput>
<ListInput
label="Mobile"
type="tel"
placeholder="0716576789"
inputId="userMob"
disabled
value={this.state.userMob}
onInput={(e) => this.setState({ userMob: e.target.value })}
required
validate
></ListInput>
<ListInput
label="NIC / Passport"
type="text"
placeholder="896785142V"
inputId="userDocument"
minlength="10"
maxlength="13"
defaultValue={this.state.userDocument}
onInput={(e) => this.setState({ userDocument: e.target.value })}
// required
// validate
></ListInput>
<ListInput
inputId="userAddressLine1"
defaultValue={this.state.userAddressLine1}
onInput={(e) => this.setState({ userAddressLine1: e.target.value })}
label="Address Line 1"
type="text"
placeholder="477"
required
validate
></ListInput>
<ListInput
inputId="userAddressLine2"
defaultValue={this.state.userAddressLine2}
onInput={(e) => this.setState({ userAddressLine2: e.target.value })}
label="Address Line 2" type="text"
placeholder="Flower Park Road, Kattuwa"
// required
// validate
></ListInput>
<ListInput
inputId="userCity"
defaultValue={this.state.userCity}
onInput={(e) => this.setState({ userCity: e.target.value })}
label="City"
type="text"
placeholder="Negombo"
required validate
></ListInput>
<ListInput
inputId="userPostalCode"
defaultValue={this.state.userPostalCode}
onInput={(e) => this.setState({ userPostalCode: e.target.value })}
label="Postal Code"
type="text"
placeholder="11500"
// required
// validate
></ListInput>
<ListInput
inputId="userCountry"
defaultValue={this.state.userCountry}
onInput={(e) => this.setState({ userCountry: e.target.value })}
label="Country"
type="text"
placeholder="Sri Lanka"
// required
// validate
></ListInput>
</List>
<Button text={this.state.userProfile ? 'Update' : 'Save'} className="width-100" fill raised round onClick={() => this.$f7.methods.saveLoggedInUser(this)} ></Button>
</Block>
</Page>
</View>
</Popup>
<LoginScreen id="my-login-screen">
<View>
<Page loginScreen>
<List form>
<StyledFirebaseAuth uiConfig={uiConfig} firebaseAuth={firebase.auth()} />
</List>
</Page>
</View>
</LoginScreen>
</App>
)
}
onPanelBreakpoint() {
// console.log('App - onPanelBreakpoint :: init');
const self = this;
}
alertLoginData() {
this.$f7.dialog.alert('Username: ' + this.state.username + '<br>Password: ' + this.state.password, () => {
this.$f7.loginScreen.close();
});
}
componentWillUnmount() {
// console.log('App - componentWillUnmount :: init');
// Make sure we un-register Firebase observers when the component unmounts.
this.unregisterAuthObserver();
}
componentDidMount() {
// console.log('App - componentDidMount :: init');
const self = this;
this.$f7.preloader.show();
this.unregisterAuthObserver = firebase.auth().onAuthStateChanged(user => {
var theUser;
if (user) {
// User is signed in.
theUser = user;
console.log('onAuthStateChanged :: login', theUser);
//set phoneNumber
this.setState({
userMob: theUser.phoneNumber,
});
if (!theUser.displayName) {
this.$f7.popup.open('#my-popup');
this.$f7.preloader.hide();
} else {
this.$f7.methods.updateAppUser(theUser, self);
}
// localStorage.setItem('userInfo', JSON.stringify(this.$f7.data.user));
// let userInfo = JSON.parse(localStorage.getItem("userInfo"));
// console.log("userInfo :: ", userInfo);
// this.$f7.preloader.hide();
} else {
// No user is signed in.
theUser = null;
console.log('onAuthStateChanged :: no-login');
this.$f7.methods.updateAppUser(theUser, self);
// localStorage.setItem('userInfo', JSON.stringify(this.$f7.data.user));
// let userInfo = JSON.parse(localStorage.getItem("userInfo"));
// console.log("userInfo :: ", userInfo);
// this.$f7.preloader.hide();
}
console.log("onAuthStateChanged :: data :: ", this.$f7.data);
});
//
this.$f7ready((f7) => {
// Call F7 APIs here
});
}
}
Required below dependencies.
"dependencies": {
"dom7": "^2.1.5",
"firebase": "^7.24.0",
"framework7": "^5.7.14",
"framework7-icons": "^3.0.1",
"framework7-react": "^5.7.14",
"prop-types": "^15.7.2",
"react": "^16.14.0",
"react-dom": "^16.14.0",
"react-firebaseui": "^4.1.0",
"react-joyride": "^2.2.1",
"template7": "^1.4.2"
},
Update accordingly. Happy Coding!