Skip to content
Permalink
Browse files

major cleanup

  • Loading branch information...
thomas shellberg
thomas shellberg committed Jun 25, 2019
1 parent d301368 commit 7f2c4301dbbef23e7b394575a836f77eaee24826
@@ -63,8 +63,6 @@ export default class App extends React.Component<Props, State> {
Font.loadAsync({
// This is the font that we are using for our tab bar
...Icon.Ionicons.font,
// We include SpaceMono because we use it in HomeScreen.js. Feel free
// to remove this if you are not using it in your app
'Roboto_medium': require('native-base/Fonts/Roboto_medium.ttf'),
}),
]);
@@ -36,7 +36,6 @@ export const sortBirthdaysThirtyDays = ( contacts ) => ({
/* take in the object representing a new contact and create a new one
* @param object contact
* @param string userId
* @todo - figure out structure of the payload, a new object with contact and userId, right?
*/
export const addNewContact = ( contact:Contact, userId ) => ({
type: 'ADD_NEW_CONTACT',
@@ -89,9 +88,4 @@ export const getProfileData = ( userId ) => ({
payload: {
userId
}
})

// @todo - where do we tell the app to subscribe to our firebase db changes using .on()?
// remember that .on() will pull the contacts from the db when initially called so it can't be just be done within a normal lifecycle method.
// If it's done within a normal lifecycle method it will render loading from cache useless.
// do we compare the contacts within the .on() method to cached and skip updating state if they're equal?
})
@@ -21,11 +21,6 @@ export default class CustomDatePicker extends Component<Props, State> {
this.setState({ chosenDate: newDate });
}

componentDidMount() {
console.log('selected date in datepicker:')
console.log(this.props.selectedDate)
}

componentDidUpdate( prevProps: Props, prevState: State ) {
// compare old and prev state, if date is changed, call the callback
if ( prevState.chosenDate !== this.state.chosenDate ) {
@@ -24,8 +24,6 @@ describe('Test contactsReducer', () => {
userId: 'userId',
dbRef: null
}
//@todo - is this the wrong way to do this assignment? Are we just setting expectedState to a reference of state?
// this could cause problems with equality testing.
const expectedState = state
const newState = contactsReducer(state, action)
expect(newState).toEqual(expectedState)
@@ -84,7 +82,6 @@ describe('Test UPDATE_CONTACTS in contactsReducer', () => {

describe('Test ADD_NEW_CONTACT in contactsReducer', () => {

// @todo - should probably add actions to a constants file now.
const type='ADD_NEW_CONTACT'
const newContact = {
address: "new address",
@@ -1,7 +1,3 @@
import { combineReducers } from 'redux'
import { Cache } from "react-native-cache";
import { AsyncStorage } from 'react-native';

import moment from 'moment'
import _ from 'lodash'

@@ -35,15 +31,6 @@ const INITIAL_STATE = {
me: {}
}

// init local cache
const shellCache = new Cache({
namespace: "shellCRM",
policy: {
maxEntries: 50000
},
backend: AsyncStorage
})

export function contactsReducer ( state:State=INITIAL_STATE, action:Action ) {
switch(action.type) {

@@ -56,10 +43,7 @@ export function contactsReducer ( state:State=INITIAL_STATE, action:Action ) {
} )

case 'GET_CONTACTS':
// @todo - this should only retrieve cached contacts.
//const cachedContacts = getContactsFromCache()
let contacts:Array<object> = getContactsFromDB( action.payload.userId )

// implement caching later
return Object.assign( {}, state, {
contacts
} )
@@ -75,25 +59,19 @@ export function contactsReducer ( state:State=INITIAL_STATE, action:Action ) {
})

case 'ADD_NEW_CONTACT':
// @todo - we want to add the new object to the state.contacts array.

const oldContacts:Array<object> = state.contacts
if( !action.payload ) return state
const newContact = {
...action.payload.contact,
id: oldContacts.length + 1
}
// take in a single contact and a userId(for firebase auth purposes)
// @todo: existing plan - add the contact to state regardless of response from addNewContact().
// this means we figure out a way to handle out of sync local cache and db data.
//addNewContact(action.payload.contact, action.payload.userId)
return { ...state,
contacts: [...oldContacts, newContact],
userId: action.payload.userId
}

case 'SORT_BIRTHDAYS':
// if we don't send any payload or contacts return state w/ empty upcomingBirthdays array
const emptyBirthdays = []
if ( !action.payload || !action.payload.contacts ) return { ...state, upcomingBirthdays: emptyBirthdays }
const upcomingBirthdays = sortBirthdaysThirtyDays( action.payload.contacts )
@@ -110,7 +88,6 @@ export function contactsReducer ( state:State=INITIAL_STATE, action:Action ) {
return { ...state, contacts: reAddContact }

case 'DELETE_CONTACT':
// @todo - we might need a better way to do this if findIndex() is too slow to find the index based on the ID
if ( !action.payload || !action.payload.contactId) return state
const deleteContact = () => {
const contacts = state.contacts
@@ -121,17 +98,11 @@ export function contactsReducer ( state:State=INITIAL_STATE, action:Action ) {
]
return newContacts
}
// @todo - we don't want to override the existing contacts[] array.
// @todo - we just want to overwrite the relevant object within the contacts[] array and return back state.
return { ...state, contacts: deleteContact() }

case 'GET_PROFILE_DATA':
if ( !action.payload || !action.payload.userId ) return state
const myProfileData = getProfileData( action.payload.userId )
// we want to grab the profile data either from cache or from the database.
// then, return that profile data as part of new state.
// the incoming payload is an object called 'me' which represents my profile data.

return { ...state, me: myProfileData }

case 'UPDATE_PROFILE':
@@ -143,26 +114,11 @@ export function contactsReducer ( state:State=INITIAL_STATE, action:Action ) {
}
}

const getContactsFromCache = () => {
const contacts = shellCache.getItem( "contacts", (err, entries) => {

if(err) return console.log('there is an error')
return entries
})
return contacts
}

const getContactsFromDB = (userId) => {

}

// take a list of total contacts and filter by birthdays within next 30 days.
// @param array contacts
// return array sortedContacts
// @todo rework this without mutating the contacts object. No more tempbirthday!

const sortBirthdaysThirtyDays = ( contacts ) => {
console.log('calling sortbirthdays function')
const now = moment()
const nextMonth = moment(now).add(1, 'M')
const filteredContactsArray = contacts
@@ -188,7 +144,6 @@ const getProfileData = (userId) => {
const val = child.val()
obj[key] = val
})
// do we call updateProfile here and move the me.on() call to somewhere else?
})
return obj
}
@@ -80,8 +80,6 @@ class AddContactScreen extends React.Component<Props, State> {
}

componentDidUpdate () {
// TODO: make more performant by comparing prevState and new state.
// TODO: put validation in here.
const {isValidfirstName, isValidlastName, isValidphone, isValidemail, isValidaddress, disableSubmit } = this.state
if ( disableSubmit && isValidfirstName && isValidlastName && isValidphone && isValidemail && isValidaddress) {
this.setState({disableSubmit: false})
@@ -119,11 +117,9 @@ class AddContactScreen extends React.Component<Props, State> {
}

handleFormSubmit = () => {
// When the button is submitted, add a new record.
const {birthday, address, phone, firstName, lastName, email} = this.state
let contactObj = { birthday, address, phone, firstName, lastName, email}
this.props.addNewContact( contactObj, this.props.userId )
// @todo - send a message to the Home screen so we can show a modal that says "success!"
this.props.navigation.navigate('Home')
}

@@ -272,7 +268,6 @@ class AddContactScreen extends React.Component<Props, State> {
}
}

// @todo - we don't need the full contacts list here. just the FB userId
const mapStateToProps = (state) => {
const { userId } = state
return { userId }
@@ -25,7 +25,6 @@ class BirthdayScreen extends React.Component<Props, State> {
renderListItem = (contact) => {
const { firstName, lastName, birthday } = contact
return (
// @todo - just send contact or object with contact? { contact }?
<ListItem onPress={() =>this.props.navigation.navigate('Profile', { contact } )}>
<Text>{`${firstName} ${lastName} - ${this.getFormattedBirthday(birthday)}`}</Text>
</ListItem>
@@ -63,7 +62,6 @@ class BirthdayScreen extends React.Component<Props, State> {
}
}

// @todo - do we have all of the items from state we need?
const mapStateToProps = (state) => {
const { contacts } = state
const { upcomingBirthdays } = state
@@ -73,7 +73,6 @@ class HomeScreen extends React.Component<Props, State> {
contactsRef.on('value', snapshot => {
contacts = []
snapshot.forEach( (child) => {
// @todo - do we just use the key here like normal(loaded from FB)? Or use our own special key(index)?
contacts.push({
...child.val(),
id: child.key
@@ -82,7 +81,6 @@ class HomeScreen extends React.Component<Props, State> {
if (init) init = false
contacts = _.sortBy( contacts, [ (o) => o.firstName ] )
this.props.updateContacts(contacts)
// @todo - getting all this stuff should first come from cache
this.props.sortBirthdaysThirtyDays(contacts)
this.setState({
loading: false
@@ -92,25 +90,15 @@ class HomeScreen extends React.Component<Props, State> {
}
if( !init && this.props.me !== prevProps.me ) {
const me = this.props.me
console.log('this is what me looks like')
console.log(me)
meRef.set(me)
}
}

componentWillMount() {
// @todo - if there is a userId but no object at /users/userid we need to create one with their email.

}

componentDidMount() {
const userId = firebase.auth().currentUser.uid;
this.props.setUserId(userId)
this.props.getDbRef()
this.props.getProfileData(userId)

//this.props.getContacts(userId)
// @todo - dispatch an action to get cached contacts
}

renderListItem = (contact) => {
@@ -121,8 +109,6 @@ class HomeScreen extends React.Component<Props, State> {
)
}

// @todo: move checkLoginStatus() higher up in the app to force them out of main screen back to auth.

checkLoginStatus() {
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
@@ -134,7 +120,6 @@ class HomeScreen extends React.Component<Props, State> {
});
}

// @todo: do we bother with the pull to refresh since FB does it? Or good to have a backup force refresh?
refreshData = () => {
this.props.getContacts(this.props.userId)
}
@@ -160,9 +145,6 @@ class HomeScreen extends React.Component<Props, State> {
}

_keyExtractor = (item, index) => {
// @todo - the home page items loaded from FB have a different structure than items created from AddNewContact.
// @todo - item.id refers here to the key generated by FB. We should probably use our generated ID? Or the random ID from FB?
// @todo if the latter it means we need to bring in our props properly.
return item.id.toString()
};

@@ -21,7 +21,6 @@ interface Props {
userId: string
}

// @todo - remove loading from internal state and load from this.props
interface State {
firstName: string,
lastName: string,
@@ -73,19 +72,11 @@ componentWillMount() {
this.props.navigation.setParams({ logOut: this.logOut });
}

componentDidUpdate() {
}

// @todo - this should be loaded from cache initially if possible.
// We then need to figure out how to use the .on() method without needing to overwrite the data or update state unnecessarily.
// actually, we don't need the .on() method at all. we don't need to listen for changes as we control how changes are made.

handleTextUpdate = (text, prop) => {
this.setState({[prop]: text})
}

handleSubmit = () => {
// @todo - pass in the proper information to updateProfile()
const contactInfo = {
firstName: this.state.firstName,
lastName: this.state.lastName,
@@ -111,8 +102,6 @@ componentDidUpdate() {
const shareState = this.state
shareState.birthday = moment(this.state.birthday).format("MMMM Do YYYY")
const result = await Share.share({
// TODO: Prettyify or leave as JSON to allow importing?
//

message: JSON.stringify(this.state),
title: `Contact information for ${this.state.firstName} ${this.state.lastName}`
@@ -139,7 +128,6 @@ componentDidUpdate() {
return (
<KeyboardAwareScrollView extraScrollHeight={100} enableOnAndroid={true} keyboardShouldPersistTaps='handled'>
{
// @todo - change to this.props.loading
this.state.loading && <Spinner/>
}
<Button style={styles.button} full onPress={this.onShare}>
@@ -248,8 +236,6 @@ componentDidUpdate() {
}
}

// @todo - we don't need all contacts here. state should just be our own data + userId
// @todo - after we clean up the state object(get rid of the extra contacts property within it) clean this up.
const mapStateToProps = (state) => {
const {userId} = state
const {me} = state
@@ -45,15 +45,12 @@ class ProfileScreen extends React.Component<Props, State> {
id: this.props.navigation.state.params.contact.id
}

// @todo - the logic should be copied and moved into contactsReducer.tsx within the deleteContact function.
// we will instead call the deleteContact action in contactsActions.tsx
static navigationOptions = ({navigation}) => {
return {
title: 'Profile',
headerRight: (
<View>
<Button style={{ backgroundColor: 'transparent' }} transparent onPress={ () => {
// @todo - call delete contact action instead of direct db call.
const contactId = navigation.state.params.contact.id
const deleteContact = navigation.getParam('deleteContact')
deleteContact(contactId)
@@ -70,7 +67,6 @@ class ProfileScreen extends React.Component<Props, State> {
this.props.navigation.setParams({
deleteContact: this.props.deleteContact,
});
console.log(this.state.birthday)
}

handleTextUpdate = (text, prop) => {
@@ -101,10 +97,8 @@ class ProfileScreen extends React.Component<Props, State> {
onShare = async () => {
try {
const shareState = this.state
// TODO: birthday is of type Date but moment.format() returns string. what to do here?
shareState.birthday = moment(this.state.birthday).format("MMMM Do YYYY")
const result = await Share.share({
// TODO: Prettyify or leave as JSON to allow importing?

message: JSON.stringify(this.state),
title: `Contact information for ${this.state.firstName} ${this.state.lastName}`
@@ -232,7 +226,6 @@ class ProfileScreen extends React.Component<Props, State> {
}
}

// @todo - we don't need all contacts, just THIS contact and the userId for updating.
const mapStateToProps = (state) => {
const { userId } = state
return { userId }

0 comments on commit 7f2c430

Please sign in to comment.
You can’t perform that action at this time.