Skip to content

Commit

Permalink
Airtable refactor, bug fixes, Auth overhaul (#48)
Browse files Browse the repository at this point in the history
* Add material UI. Changing error states.

* Error working, but working on better UI.

* Update prettier rules to match clerk repo, and no longer conflict with VSCode format on save

* Update packages - upgrade generator version

* Update Airtable schema

* Refactor MapScreen and related components

* Refactor News and related components

* Clean up AppNavigator.js

* Refactor Resources

* Replace getUser

* Refactor Rewards and related components.

 - Deprecated: removed pull-to-refresh implementation to declutter the file. We can add it back from a different trigger if necessary. Removed deprecated props which were not being used in `RewardsHome` and `PointsHistory` components.
- Cleanup: Made `Overline` components normally-cased (since the styled component uses `text-transform`)
- Cleanup: Added `isLoading` to `DrawerContent` and `RewardsScreen`. This is probably the most crucial place to add a loading screen (@ace) imo; it's noticeably laggy here.

* Use constants/Rewards.js for reward point value

* Error working with both signup and login. Styling not done.

* Overhaul Signup

* Undo prettier width change and cleanup

* Add workspace-specific shared settings (format and run eslint on save)

* Update prettier config

* Update prettier config and run prettier on all ours

* Update schema with changed fields

* Add workspace-specific color

* Small fixes

* Add back filter for Clerk Training, enforce ordering on location update and stores loading

* Update login code

* Bugfix

* Remove .eslintignore

* Bump version, run generator to update schema

* Update schema again

* Updated error message for login and added styling

* Handle permissions on text change in Signup

* Remove deprecated Airtable code in common.js

* Support base change to development Airtable base

* Add rewardDollarValue

* Filter out clerk training in dev as well

* Cleanup .env.example

* Fix typo

* Update login and logout

* Remove permissions from state and calculate in render. Update SignUp so unable to submit twice

* Update line widths

* Display duplicate customer error

Co-authored-by: Tommy Poa <[email protected]>
  • Loading branch information
annieyro and tommypoa authored Apr 3, 2020
1 parent 836d077 commit b4dc7be
Show file tree
Hide file tree
Showing 45 changed files with 1,404 additions and 3,304 deletions.
11 changes: 9 additions & 2 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
AIRTABLE_BASE_ID='your-base-id-here'
AIRTABLE_API_KEY='your-API-key-here'
AIRTABLE_BASE_ID='appYfW7a2loPD26Vg'

## Named to conform to airtable-schema-generator's expectations
REACT_APP_AIRTABLE_API_KEY='YOUR-API-KEY-HERE'

## Needed for airtable-schema-generator if using auto mode
AIRTABLE_EMAIL='YOUR-EMAIL-HERE'
AIRTABLE_PASSWORD='YOUR-PASSWORD-HERE'

IMG_API_KEY='image-API-key-here'
2 changes: 0 additions & 2 deletions .eslintignore

This file was deleted.

24 changes: 12 additions & 12 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
module.exports = {
env: {
es6: true
es6: true,
},
extends: ['eslint:recommended', 'airbnb', 'plugin:prettier/recommended'],
parser: 'babel-eslint',
parserOptions: {
ecmaFeatures: {
jsx: true
jsx: true,
},
ecmaVersion: 2018,
sourceType: 'module'
sourceType: 'module',
},
plugins: ['react-native', 'prettier'],
rules: {
Expand All @@ -19,22 +19,22 @@ module.exports = {
paths: [
{
name: 'airtable',
message: 'Do not use the airtable module outside of airtable.js'
message: 'Do not use the airtable module outside of airtable.js',
},
{
name: './airtable',
message: 'Do not use airtable.js outside of request.js'
message: 'Do not use airtable.js outside of request.js',
},
{
name: '../../lib/airtable',
message: 'Do not use airtable.js outside of request.js'
message: 'Do not use airtable.js outside of request.js',
},
{
name: '../../../lib/airtable',
message: 'Do not use airtable.js outside of request.js'
}
]
}
message: 'Do not use airtable.js outside of request.js',
},
],
},
],
'no-underscore-dangle': ['error', { allowAfterThis: true }],
'no-use-before-define': ['error', { variables: false }],
Expand All @@ -47,6 +47,6 @@ module.exports = {
'valid-typeof': 'warn',
'react/jsx-filename-extension': [1, { extensions: ['.js', '.jsx'] }],
'prettier/prettier': ['error'],
'react/destructuring-assignment': ['enabled', 'never']
}
'react/destructuring-assignment': 'off',
},
};
10 changes: 8 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
.expo/*
node_modules/**/*

# Deprecated env file
# Deprecated env files
environment.js
.airtable-schema-generator.env

# Ignore schemaRaw.json (only used for manual mode)
schemaRaw.json

# env files
.env.development
.env.production
.airtable-schema-generator.env


package-lock.json
*.DS_Store

Expand Down
54 changes: 24 additions & 30 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,31 +1,25 @@
{
"files.associations": {
"*.js": "javascriptreact"
},
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode",
},
"eslint.enable": true,
"eslint.options": {
"extensions": [
".js",
".jsx"
]
},
"eslint.validate": [
"javascript",
"javascriptreact"
],
"eslint.alwaysShowStatus": true,
"editor.formatOnPaste": false,
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": true,
"source.fixAll.eslint": true
},
"javascript.suggest.completeFunctionCalls": true,
"javascript.implicitProjectConfig.checkJs": true,
}
"files.associations": {
"*.js": "javascriptreact"
},
"[javascript]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"[javascriptreact]": {
"editor.defaultFormatter": "esbenp.prettier-vscode"
},
"eslint.enable": true,
"eslint.options": {
"extensions": [".js", ".jsx"]
},
"eslint.validate": ["javascript", "javascriptreact"],
"eslint.alwaysShowStatus": true,
"editor.formatOnPaste": false,
"editor.formatOnSave": true,
"editor.codeActionsOnSave": {
"source.organizeImports": true,
"source.fixAll.eslint": true
},
"javascript.suggest.completeFunctionCalls": true,
"javascript.implicitProjectConfig.checkJs": true
}
45 changes: 18 additions & 27 deletions components/AuthTextField.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,7 @@
import React from 'react';
import { TextField } from 'react-native-materialui-textfield';
import Colors from '../constants/Colors';
import { fieldStateColors } from '../lib/authUtils';
import {
InputNoticeContainer,
TextField,
TextFieldContainer,
} from '../styled/auth';
import { TextFieldContainer } from '../styled/auth';
import { Caption } from './BaseComponents';

/**
Expand All @@ -14,42 +10,37 @@ import { Caption } from './BaseComponents';

function AuthTextField({
fieldType,
color,
value,
onBlurCallback,
onFocusCallback,
changeTextCallback,
error,
onBlurCallback = null,
}) {
return (
<TextFieldContainer>
<Caption color={color}>{fieldType}</Caption>
<TextField
onBlur={onBlurCallback}
onFocus={onFocusCallback}
onBlur={onBlurCallback ? () => onBlurCallback(value) : null}
autoCapitalize="words"
placeholder={fieldType}
autoCorrect={false}
label={fieldType}
labelTextStyle={{ fontFamily: 'poppins-regular' }}
lineWidth={1.75}
activeLineWidth={1.75}
onChangeText={changeTextCallback}
value={value}
borderColor={color}
baseColor={Colors.activeText}
tintColor={Colors.primaryGreen}
error={error}
errorColor={Colors.error}
returnKeyType="done"
keyboardType={fieldType === 'Phone Number' ? 'numeric' : 'default'}
maxLength={fieldType === 'Phone Number' ? 10 : null}
secureTextEntry={fieldType === 'Password'}
/>
<InputNoticeContainer>
{fieldType === 'Name' && (
<Caption color={Colors.secondaryText}>
Note: this is how clerks will greet you!
</Caption>
)}
{color === fieldStateColors.ERROR && fieldType === 'Phone Number' && (
<Caption color={color}>Must be a valid phone number</Caption>
)}
{color === fieldStateColors.ERROR && fieldType === 'Password' && (
<Caption color={color}>Must be 8-20 characters long</Caption>
)}
</InputNoticeContainer>
{fieldType === 'Name' && !error && (
<Caption color={Colors.activeText}>
Note: this is how clerks will greet you!
</Caption>
)}
</TextFieldContainer>
);
}
Expand Down
2 changes: 1 addition & 1 deletion components/news/NewsItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ class NewsItem extends React.Component {
}>
<Card>
<DateContainer>
<DateText>{this.props.newsItem.date.toDateString()}</DateText>
<DateText>{this.props.newsItem.postDate.toDateString()}</DateText>
</DateContainer>
<ContentContainer>
<DateText>{this.props.newsItem.title}</DateText>
Expand Down
5 changes: 3 additions & 2 deletions components/product/ProductCard.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import Colors from '../../constants/Colors';
import { displayDollarValue } from '../../lib/common';
import { ColumnContainer, RowContainer } from '../../styled/shared';
import { Body, ButtonContainer, Caption } from '../BaseComponents';

/**
* @prop
* */
Expand All @@ -20,7 +21,7 @@ function ProductCard({ product, store, navigation, displayPoints }) {
}>
<ColumnContainer>
<Image
source={{ uri: product.image }}
source={{ uri: product.imageUrl }}
style={{ height: 86, width: 86, borderRadius: 12 }}
/>
<Body>{product.name}</Body>
Expand All @@ -29,7 +30,7 @@ function ProductCard({ product, store, navigation, displayPoints }) {
)}
<RowContainer>
<Caption color={Colors.secondaryText}>
{displayDollarValue(product.customerCost)} ea
{`${displayDollarValue(product.customerCost)} ea`}
</Caption>
{displayPoints && (
<Caption color={Colors.secondaryText}>
Expand Down
2 changes: 1 addition & 1 deletion components/product/ProductInfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { Body, Caption, Title } from '../BaseComponents';
* */

function ProductInfo({ product }) {
const { name, id, category, points, customerCost } = product;
const { name, points, customerCost } = product;
return (
<ProductInfoContainer>
<Title>{name}</Title>
Expand Down
5 changes: 2 additions & 3 deletions components/rewards/PointsHistory.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@ import { FlatList, View } from 'react-native';
import Colors from '../../constants/Colors';
import { Body, Overline } from '../BaseComponents';
import Transaction from './Transaction';

/**
* @prop
* */

function PointsHistory({ transactions, user, updates, navigation }) {
// Only display if transactions have mounted
// TODO @kennethlien fix spacing at line 44
function PointsHistory({ transactions }) {
return (
<View>
<FlatList
Expand Down
9 changes: 7 additions & 2 deletions components/rewards/RewardsCard.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import Colors from '../../constants/Colors';
import { rewardDollarValue, rewardPointValue } from '../../constants/Rewards';
import {
RewardDescriptionContainer,
RewardsCardContainer,
Expand All @@ -17,8 +18,12 @@ class RewardsCard extends React.Component {
circleColor={Colors.lightest}
/>
<RewardDescriptionContainer>
<Subhead color={Colors.darkerGreen}>$5 Reward</Subhead>
<Caption color={Colors.darkerGreen}>1000 points</Caption>
<Subhead color={Colors.darkerGreen}>
{`$${rewardDollarValue} Reward`}
</Subhead>
<Caption color={Colors.darkerGreen}>
{`${rewardPointValue} points`}
</Caption>
</RewardDescriptionContainer>
</RewardsCardContainer>
);
Expand Down
21 changes: 12 additions & 9 deletions components/rewards/RewardsHome.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React from 'react';
import { FlatList, ScrollView, View } from 'react-native';
import { ProgressBar } from 'react-native-paper';
import Colors from '../../constants/Colors';
import { rewardDollarValue, rewardPointValue } from '../../constants/Rewards';
import {
AvailableRewardsContainer,
RewardsProgressContainer,
Expand All @@ -14,23 +15,25 @@ import RewardsCard from './RewardsCard';
* @prop
* */

function createList(N) {
function createList(n) {
const list = [];
for (let i = 1; i <= N; i++) {
for (let i = 1; i <= n; i += 1) {
list.push(i);
}
return list;
}

function RewardsHome({ user }) {
function RewardsHome({ customer }) {
const rewardsAvailable = parseInt(customer.points, 10) / rewardPointValue;
const pointsToNext = parseInt(customer.points, 10) % rewardPointValue;
return (
<ScrollView style={{ marginLeft: 16, paddingRight: 16 }}>
<RewardsProgressContainer>
<Overline style={{ marginTop: 24, marginBottom: 12 }}>
Reward Progress
</Overline>
<Title style={{ marginBottom: 2 }}>
{parseInt(user.points) % 1000} / 1000
{`${pointsToNext} / ${rewardPointValue}`}
</Title>
<ProgressBar
style={{
Expand All @@ -39,20 +42,20 @@ function RewardsHome({ user }) {
borderRadius: 20,
marginBottom: 15,
}}
progress={(parseInt(user.points) % 1000) / 1000}
progress={pointsToNext / rewardPointValue}
color={Colors.primaryGreen}
/>
<Body style={{ marginBottom: 28 }}>
Earn {`${1000 - (parseInt(user.points) % 1000)}`} points to unlock
your next $5 reward.
{`Earn ${rewardPointValue -
pointsToNext} points to unlock your next $${rewardDollarValue} reward`}
</Body>
<Overline style={{ marginBottom: 8 }}>
Available Rewards ({Math.floor(parseInt(user.points) / 1000)})
{`Available Rewards (${Math.floor(rewardsAvailable)})`}
</Overline>
</RewardsProgressContainer>
<AvailableRewardsContainer>
<FlatList
data={createList(Math.floor(parseInt(user.points) / 1000))}
data={createList(Math.floor(rewardsAvailable))}
renderItem={() => <RewardsCard />}
keyExtractor={(item, index) => index.toString()}
numColumns={2}
Expand Down
Loading

0 comments on commit b4dc7be

Please sign in to comment.