Skip to content

Commit

Permalink
Items being added
Browse files Browse the repository at this point in the history
  • Loading branch information
ineshbose committed Feb 3, 2022
1 parent 262fc01 commit 702b38f
Show file tree
Hide file tree
Showing 9 changed files with 226 additions and 86 deletions.
22 changes: 21 additions & 1 deletion src/app/api/items.ts
@@ -1,5 +1,11 @@
import { axiosInstance } from '.';
import { CreateData, FetchData, TrackItem, UpdateData } from '../types/api';
import {
CreateData,
FetchData,
PortionItem,
TrackItem,
UpdateData,
} from '../types/api';

const API_PATH = '/trackitem/';

Expand All @@ -12,6 +18,20 @@ export const getTrackItems = async () => {
}
};

export const createPortionItem = async (
props: CreateData<PortionItem, 'name'>
) => {
try {
const response = await axiosInstance.post<PortionItem>(
'/portionitems/',
props
);
return response.data;
} catch (e) {
// unable to create
}
};

export const createTrackItem = async (props: CreateData<TrackItem, 'item'>) => {
try {
const response = await axiosInstance.post<TrackItem>(API_PATH, props);
Expand Down
35 changes: 19 additions & 16 deletions src/app/components/FAB/MainButton.tsx
Expand Up @@ -24,22 +24,22 @@ const DEFAULT_SHADOW_PROPS = {

export default function MainButton(Props: MainButtonProps) {
const {
color,
shadow,
actions,
visible,
position,
animated,
iconHeight,
iconWidth,
iconColor,
buttonSize,
color = 'red',
shadow = {},
actions = [],
visible = true,
position = 'right',
animated = true,
iconHeight = 15,
iconWidth = 15,
iconColor = '#fff',
buttonSize = 56,
floatingIcon,
overlayColor,
showBackground,
distanceToEdge,
mainVerticalDistance,
actionsPaddingTopBottom,
overlayColor = 'rgba(68, 68, 68, 0.6)',
showBackground = 'true',
distanceToEdge = 30,
mainVerticalDistance = 0,
actionsPaddingTopBottom = 8,
onPressMain,
onPressAction,
} = Props;
Expand Down Expand Up @@ -144,7 +144,10 @@ export default function MainButton(Props: MainButtonProps) {
return (
<Animated.View
pointerEvents="box-none"
style={[styles.overlay, { backgroundColor: 'transparent' }]}
style={[
styles.overlay,
{ backgroundColor: 'transparent', display: visible ? 'flex' : 'none' },
]}
>
{active && showBackground && (
<Pressable
Expand Down
35 changes: 9 additions & 26 deletions src/app/navigation/BottomTabNavigator.tsx
Expand Up @@ -88,7 +88,6 @@ export default function BottomTabNavigator({
headerAction,
helpers: { signOut, setHeaderAction },
} = useAppContext();
const isNotInAction = getFocusedRouteNameFromRoute(route) !== 'Action';
const [modalVisible, setModalVisible] = React.useState<boolean>(false);

const navigationLeftAccessory = (props: {} | undefined) => (
Expand Down Expand Up @@ -224,35 +223,19 @@ export default function BottomTabNavigator({
))}
</BottomTab.Navigator>
<FAB
actions={
isNotInAction
? [
{
icon: 'library-add',
name: 'Item',
text: 'Food Item',
},
]
: []
}
floatingIcon={isNotInAction ? 'add' : 'check'}
actions={[
{
icon: 'library-add',
name: 'Item',
text: 'Food Item',
},
]}
floatingIcon="add"
onPressAction={(name) =>
navigation.navigate('Action', { screen: name })
}
onPressMain={() => (isNotInAction ? {} : {})}
actionsPaddingTopBottom={8}
color={isNotInAction ? 'red' : 'green'}
overlayColor="rgba(68, 68, 68, 0.6)"
position="right"
distanceToEdge={{ vertical: 80, horizontal: 30 }}
buttonSize={56}
iconHeight={15}
iconWidth={15}
iconColor="#fff"
mainVerticalDistance={0}
showBackground
animated
visible
visible={getFocusedRouteNameFromRoute(route) !== 'Action'}
/>
</>
);
Expand Down
124 changes: 116 additions & 8 deletions src/app/screens/Action/AddItem.tsx
@@ -1,19 +1,127 @@
import * as React from 'react';
import { Layout } from '@ui-kitten/components';
import { SafeAreaView, StyleSheet } from 'react-native';
import {
Button,
IndexPath,
Input,
Layout,
Select,
SelectItem,
TopNavigation,
} from '@ui-kitten/components';
import { KeyboardAvoidingView, StyleSheet, View } from 'react-native';
import { FAB } from '../../components/FAB';
import { NavProps, RootActionParamList } from '../../types/navigation';
import { createTrackItem } from '../../api/items';
import { useAppContext } from '../../contexts/AppContext';
import { FormError, FrequencyDisplay } from '../../types/api';

const FREQUENCY_OPTIONS: { [f in FrequencyDisplay]: number } = {
DAILY: 1,
WEEKLY: 7,
MONTHLY: 30,
};

export default function AddItem({
navigation,
}: NavProps<RootActionParamList, 'Item'>) {
const {
items = [],
helpers: { setItems },
} = useAppContext();
const [name, setName] = React.useState<string>('');
const [target, setTarget] = React.useState<number>(1);
const [selectedFrequency, setSelectedFrequency] = React.useState<IndexPath>(
new IndexPath(0)
);
const [error, setError] = React.useState<FormError | any>();
const frequencies = Object.keys(FREQUENCY_OPTIONS) as FrequencyDisplay[];

const strToNum = (val: string) =>
parseInt(val.match(/\d+/g)?.join('') || '0');

const goBack = () => navigation.goBack();

const renderCancelAccessory = (props: {} | undefined) => (
<Button appearance="ghost" status="basic" {...props} onPress={goBack}>
Cancel
</Button>
);

const createItem = async () => {
const newItem = await createTrackItem({
item: { name },
target,
frequency: FREQUENCY_OPTIONS[frequencies[selectedFrequency.row]],
});
setItems([...items, newItem]);
goBack();
};

export default function AddItem() {
return (
<SafeAreaView style={{ flex: 1 }}>
<Layout style={styles.container}></Layout>
</SafeAreaView>
<KeyboardAvoidingView style={{ flex: 1 }}>
<Layout style={styles.container}>
<TopNavigation
alignment="start"
title="New Item"
accessoryRight={renderCancelAccessory}
/>
<View
style={{
alignItems: 'center',
justifyContent: 'center',
}}
>
<View
style={{
maxWidth: 500,
marginTop: 100,
}}
>
<Input
placeholder="Enter name"
onChangeText={setName}
style={{ margin: 2 }}
caption={error?.name}
status={error?.name ? 'danger' : 'basic'}
size="large"
/>
<View style={{ flexDirection: 'row' }}>
<Input
placeholder="target"
value={`${target}`}
onChangeText={(t) => setTarget(strToNum(t))}
style={{ flex: 1, margin: 2 }}
size="large"
/>
<Select
value={frequencies[selectedFrequency.row].toLowerCase()}
selectedIndex={selectedFrequency}
onSelect={(index) => setSelectedFrequency(index as IndexPath)}
style={{ flex: 1, margin: 2 }}
size="large"
disabled
>
{frequencies.map((frequency) => (
<SelectItem key={frequency} title={frequency} />
))}
</Select>
</View>
</View>
</View>
</Layout>
<FAB
floatingIcon="check"
color="green"
onPressMain={() =>
name ? createItem() : setError({ name: 'This field is required.' })
}
/>
</KeyboardAvoidingView>
);
}

const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
});
28 changes: 14 additions & 14 deletions src/app/types/FAB.ts
Expand Up @@ -26,26 +26,26 @@ export type ActionItem = {
};

export type MainButtonProps = {
actions: ActionItem[];
animated: boolean;
color: string;
distanceToEdge:
actions?: ActionItem[];
animated?: boolean;
color?: string;
distanceToEdge?:
| number
| {
vertical: number;
horizontal: number;
};
mainVerticalDistance: number;
visible: boolean;
overlayColor: string;
position: 'right' | 'left' | 'center';
showBackground: boolean;
actionsPaddingTopBottom: number;
buttonSize: number;
mainVerticalDistance?: number;
visible?: boolean;
overlayColor?: string;
position?: 'right' | 'left' | 'center';
showBackground?: boolean;
actionsPaddingTopBottom?: number;
buttonSize?: number;
floatingIcon?: IconOptions;
iconHeight: number;
iconWidth: number;
iconColor: string;
iconHeight?: number;
iconWidth?: number;
iconColor?: string;
shadow?: Shadow;
onPressAction?: (itemName: Actions) => void;
onPressMain?: (isActive: boolean) => void;
Expand Down
34 changes: 20 additions & 14 deletions src/app/types/api.ts
Expand Up @@ -25,18 +25,28 @@ export type PaginationData<T> = {

export type FetchData<T> = PaginationData<T> | T[];

export type CreateData<T, R extends keyof T> = Partial<Omit<T, 'id'>> & {
[P in R]: T[R];
export type CreateData<
T extends GenericModel | ModelID,
R extends keyof T | string = 'name'
> = Partial<Omit<T, 'id' | R>> & {
[P in R]: R extends keyof T
? NonNullable<T[R]> extends GenericModel | ModelID
? CreateData<NonNullable<T[R]>> | ModelID
: T[R]
: any;
};

export type UpdateData<T extends { id: ModelID }> = Partial<T> & {
export type UpdateData<T extends GenericModel> = Partial<T> & {
id: T['id'];
};

export type ModelID = number | string;

export type User = {
id: ModelID;
export type FrequencyDisplay = 'DAILY' | 'WEEKLY' | 'MONTHLY';

export type GenericModel = { id: ModelID };

export type User = GenericModel & {
email: string;
forename: string | null;
surname: string | null;
Expand All @@ -47,14 +57,12 @@ export type User = {
items?: TrackItems;
};

export type PortionItem = {
id: ModelID;
export type PortionItem = GenericModel & {
name: string;
is_default: boolean;
is_default?: boolean;
};

export type TrackItem = {
id: ModelID;
export type TrackItem = GenericModel & {
item?: PortionItem | ModelID;
user?: User | ModelID;
target: number;
Expand All @@ -65,16 +73,14 @@ export type TrackItem = {

export type TrackItems = TrackItem[];

export type UserLog = {
id: ModelID;
export type UserLog = GenericModel & {
item?: TrackItem | ModelID;
timestamp: string | Date;
};

export type UserLogs = UserLog[];

export type Resource = {
id: ModelID;
export type Resource = GenericModel & {
title: string;
author: string;
link: string;
Expand Down

0 comments on commit 702b38f

Please sign in to comment.