Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Points History and Rewards tab bar styling + Rewards navigation animations #46

Merged
merged 13 commits into from
Mar 26, 2020
11 changes: 11 additions & 0 deletions components/BaseComponents.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,17 @@ export const NavButton = styled.TouchableOpacity`
justify-content: center;
`;

export const CircleIconContainer = styled.View`
display: flex;
align-items: center;
justify-content: center;
height: 40px;
width: 40px;
padding: 8px;
border-radius: 20px;
background-color: ${props => props.color || Colors.lighterGreen};
`;

export const ButtonContainer = styled.TouchableOpacity``;
Comment on lines +27 to 38
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

style thing? i think a lot of our other stuff has the icon vertically centered so maybe we should change this to match that, but @12aschen should chime in

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure what you mean—vertically centered to what? Lines 29 & 30 should make it centered.

// TODO @tommypoa Replace top / bottom 25%
export const ButtonLabel = styled(TextButton)`
Expand Down
19 changes: 19 additions & 0 deletions components/CircleIcon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { FontAwesome5 } from '@expo/vector-icons';
import React from 'react';
import { CircleIconContainer } from './BaseComponents';

export default class CircleIcon extends React.Component {
render() {
return (
<CircleIconContainer color={this.props.circleColor}>
<FontAwesome5
name={this.props.icon}
size={22}
solid
color={this.props.iconColor}
style={{ paddingTop: 1 }}
/>
</CircleIconContainer>
);
}
}
19 changes: 8 additions & 11 deletions components/resources/ResourceCategoryBar.js
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
import React from 'react';

import {
CategoryCard,
CategoryIcon,
HeadingContainer
} from '../../styled/resources';
import Colors from '../../assets/Colors';
import { CategoryCard, HeadingContainer } from '../../styled/resources';
import { Title } from '../BaseComponents';
import { FontAwesome5 } from '@expo/vector-icons';
import CircleIcon from '../CircleIcon';

class ResourceCategoryBar extends React.Component {
render() {
return (
<CategoryCard>
<CategoryIcon>
<FontAwesome5 name={this.props.icon} size={20} solid color={'#fff'} />
</CategoryIcon>

<CircleIcon
icon={this.props.icon}
iconColor={Colors.lightest}
circleColor={Colors.lighterGreen}
/>
<HeadingContainer>
<Title>{this.props.title}</Title>
</HeadingContainer>
Expand Down
39 changes: 16 additions & 23 deletions components/rewards/PointsHistory.js
Original file line number Diff line number Diff line change
@@ -1,38 +1,31 @@
import React from 'react';
import { Button, ScrollView, StyleSheet, Text, View } from 'react-native';
import { ScrollView, View } from 'react-native';
import { Overline } from '../BaseComponents';
import Transaction from './Transaction';
/**
* @prop
* */

const styles = StyleSheet.create({
signOutButton: {
fontSize: 20,
paddingVertical: 15
}
});

function PointsHistory({ transactions, user, updates, navigation }) {
// Only display if transactions have mounted
// TODO @kennethlien fix spacing at line 44
if (transactions) {
return (
<View>
<View>
<ScrollView>
<Overline style={{ marginTop: 24 }}>Recent Transactions</Overline>
{transactions.map(transaction => (
<Transaction
key={transaction.id}
date={transaction.date}
points={transaction.points}
storeName={transaction.storeName}
/>
))}
</ScrollView>
</View>
</View>
<ScrollView style={{ marginLeft: 16, paddingRight: 16 }}>
<Overline style={{ marginTop: 24, marginBottom: 12 }}>
Recent Transactions
</Overline>
{transactions.map(transaction => (
<Transaction
key={transaction.id}
date={transaction.date}
pointsEarned={transaction.pointsEarned}
storeName={transaction.storeName}
subtotal={transaction.subtotal}
totalSale={transaction.totalSale}
/>
))}
</ScrollView>
);
}
// else return
Expand Down
22 changes: 9 additions & 13 deletions components/rewards/RewardsCard.js
Original file line number Diff line number Diff line change
@@ -1,25 +1,21 @@
import React from 'react';
import Colors from '../../assets/Colors';
import {
RewardsCardContainer,
RewardDescriptionContainer,
StarIcon
RewardsCardContainer
} from '../../styled/rewards';
import { Subhead, Caption } from '../BaseComponents';
import { FontAwesome5 } from '@expo/vector-icons';
import Colors from '../../assets/Colors';
import { Caption, Subhead } from '../BaseComponents';
import CircleIcon from '../CircleIcon';

class RewardsCard extends React.Component {
render() {
return (
<RewardsCardContainer>
<StarIcon>
<FontAwesome5
name="star"
solid
size={24}
color={Colors.primaryGreen}
/>
</StarIcon>
<CircleIcon
icon="star"
iconColor={Colors.primaryGreen}
circleColor={Colors.lightest}
/>
Comment on lines +14 to +18
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ty for the fix here, it was so jank before LOL

<RewardDescriptionContainer>
<Subhead color={Colors.darkerGreen}>$5 Reward</Subhead>
<Caption color={Colors.darkerGreen}>1000 points</Caption>
Expand Down
73 changes: 38 additions & 35 deletions components/rewards/RewardsHome.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import React from 'react';
import { View, ScrollView } from 'react-native';
import { Body, Overline, Title } from '../BaseComponents';
import { ScrollView } from 'react-native';
import { ProgressBar } from 'react-native-paper';
import Colors from '../../assets/Colors';
import {
RewardsProgressContainer,
AvailiableRewardsContainer
AvailableRewardsContainer,
RewardsProgressContainer
} from '../../styled/rewards';
import { ProgressBar } from 'react-native-paper';
import { Body, Overline, Title } from '../BaseComponents';
import RewardsCard from './RewardsCard';
import Colors from '../../assets/Colors';

/**
* @prop
Expand All @@ -23,35 +23,38 @@ function createList(N) {

function RewardsHome({ user }) {
return (
<View>
<ScrollView>
<RewardsProgressContainer>
<Overline style={{ marginTop: 24, marginBottom: 15 }}>
REWARD PROGRESS
</Overline>
<Title style={{ marginBottom: 2 }}>
{parseInt(user.points) % 1000} / 1000
</Title>
<ProgressBar
style={{ height: 20, borderRadius: 20, marginBottom: 15 }}
progress={(parseInt(user.points) % 1000) / 1000}
color={Colors.primaryGreen}
/>
<Body style={{ marginBottom: 28 }}>
Earn {`${1000 - (parseInt(user.points) % 1000)}`} points to unlock
your next $5 reward
</Body>
<Overline style={{ marginBottom: 8 }}>
AVAILIABLE REWARDS ({Math.floor(parseInt(user.points) / 1000)})
</Overline>
</RewardsProgressContainer>
<AvailiableRewardsContainer>
{createList(Math.floor(parseInt(user.points) / 1000)).map(a => (
<RewardsCard></RewardsCard>
))}
</AvailiableRewardsContainer>
</ScrollView>
</View>
<ScrollView style={{ marginLeft: 16, paddingRight: 16 }}>
<RewardsProgressContainer>
<Overline style={{ marginTop: 24, marginBottom: 12 }}>
Reward Progress
</Overline>
<Title style={{ marginBottom: 2 }}>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Figma has the first number in BigTitle 😅

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think Kenneth and I agreed on abandoning that when the alignment of 2 different line heights was getting really annoying 😶

{parseInt(user.points) % 1000} / 1000
</Title>
<ProgressBar
style={{
height: 20,
width: '100%',
borderRadius: 20,
marginBottom: 15
}}
progress={(parseInt(user.points) % 1000) / 1000}
color={Colors.primaryGreen}
/>
<Body style={{ marginBottom: 28 }}>
Earn {`${1000 - (parseInt(user.points) % 1000)}`} points to unlock
your next $5 reward
</Body>
<Overline style={{ marginBottom: 8 }}>
Available Rewards ({Math.floor(parseInt(user.points) / 1000)})
</Overline>
</RewardsProgressContainer>
<AvailableRewardsContainer>
{createList(Math.floor(parseInt(user.points) / 1000)).map(a => (
<RewardsCard></RewardsCard>
))}
</AvailableRewardsContainer>
</ScrollView>
);
}

Expand Down
51 changes: 29 additions & 22 deletions components/rewards/Transaction.js
Original file line number Diff line number Diff line change
@@ -1,33 +1,40 @@
import { FontAwesome5 } from '@expo/vector-icons';
import React from 'react';
import { TouchableOpacity } from 'react-native';
import {
Card,
ContentContainer,
IconContainer
} from '../../styled/transaction';
import { Caption, Body } from '../../components/BaseComponents';
import Colors from '../../assets/Colors';
import { displayDollarValue } from '../../lib/rewardsUtils';
import { Card, ContentContainer } from '../../styled/transaction';
import { Caption, Subhead } from '../BaseComponents';
import CircleIcon from '../CircleIcon';

/**
* @prop
* */

function Transaction(props) {
const { date, storeName, points } = props;
const { date, storeName, pointsEarned, totalSale } = props;
const options = {
weekday: 'short',
year: 'numeric',
month: 'short',
day: 'numeric'
};
return (
<TouchableOpacity>
<Card>
<IconContainer>
<FontAwesome5 name="check" size={32} color="green" />
</IconContainer>
<ContentContainer>
<Body>
{date.toLocaleDateString()} @ {storeName}
</Body>
<Caption>{points} Points Redeemed</Caption>
</ContentContainer>
</Card>
</TouchableOpacity>
<Card>
<CircleIcon
icon="check"
iconColor={Colors.primaryGreen}
circleColor={Colors.lightestGreen}
/>
<ContentContainer>
<Caption color={Colors.secondaryText}>
{date.toLocaleDateString('en-US', options)} • {storeName}
</Caption>
<Subhead>{pointsEarned} points earned</Subhead>
<Caption color={Colors.secondaryText}>
for {displayDollarValue(totalSale ? totalSale : 0)} of healthy
products
</Caption>
</ContentContainer>
</Card>
);
}

Expand Down
11 changes: 9 additions & 2 deletions lib/rewardsUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,23 @@ function createTransactionData(record) {
customer: transaction.Customer,
// TODO not entirely sure why this was converted to a Date object
date: new Date(transaction.Date),
points: transaction['Points Rewarded'],
pointsEarned: transaction['Points Earned'],
storeName: transaction['Store Name'],
productsPurchased: transaction['Products Purchased'],
phone: transaction['Customer Lookup (Phone #)'],
clerk: transaction.Clerk,
itemsRedeemed: transaction['Items Redeemed'],
customerName: transaction['Customer Name'],
receipts: transaction.Receipts
totalSale: transaction['Total Price']
};
}
export function displayDollarValue(amount, positive = true) {
const dollarValue = '$'.concat(amount.toFixed(2).toString());
if (positive) {
return dollarValue;
}
return '-'.concat(dollarValue);
}

// Calls Airtable API to return a promise that
// will resolve to be a user record.
Expand Down
22 changes: 15 additions & 7 deletions navigation/AppNavigator.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
import React from 'react';
import { AsyncStorage, View, TouchableOpacity, Linking } from 'react-native';
import { AsyncStorage, Linking, TouchableOpacity, View } from 'react-native';
import { createAppContainer, createSwitchNavigator } from 'react-navigation';
import { createDrawerNavigator, DrawerItems } from 'react-navigation-drawer';
import { createStackNavigator } from 'react-navigation-stack';
import WelcomeScreen from '../screens/auth/WelcomeScreen';
import Colors from '../assets/Colors';
import { Title } from '../components/BaseComponents';
import { getUser } from '../lib/rewardsUtils';
import LoginScreen from '../screens/auth/LoginScreen';
import SignUpScreen from '../screens/auth/SignUpScreen';
import Colors from '../assets/Colors';
import { getUser } from '../lib/rewardsUtils';
import { RewardsStack, StoresStack, ResourcesStack } from './StackNavigators';
import WelcomeScreen from '../screens/auth/WelcomeScreen';
import RewardsScreen from '../screens/rewards/RewardsScreen';
import { ResourcesStack, RootStack, StoresStack } from './StackNavigators';

const AuthStack = createStackNavigator({
Welcome: WelcomeScreen,
Expand Down Expand Up @@ -119,16 +120,23 @@ export class DrawerContent extends React.Component {

const MyDrawerNavigator = createDrawerNavigator(
{
Root: {
screen: RootStack,
navigationOptions: () => ({
title: 'Root',
drawerLabel: () => null
})
},
Stores: {
screen: StoresStack,
navigationOptions: () => ({
title: 'Stores'
})
},
Rewards: {
screen: RewardsStack,
screen: props => <RewardsScreen {...props} tab={1} />,
navigationOptions: () => ({
title: 'Your Profile',
title: 'Points History',
drawerLockMode: 'locked-closed'
})
},
Expand Down
Loading