Skip to content

Commit

Permalink
loading indicators
Browse files Browse the repository at this point in the history
  • Loading branch information
lcflight committed Feb 2, 2024
1 parent 8b684e8 commit 49fa19d
Show file tree
Hide file tree
Showing 6 changed files with 67 additions and 21 deletions.
7 changes: 5 additions & 2 deletions src/components/newTaskPopup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {addTask} from '../services/taskratchet/addTask';
import {styles} from '../styles/newTaskPopupStyle';
import useIsDarkMode from '../utils/checkDarkMode';
import DatePickerPopup from './datePickerPopup';
import PressableLoading from './pressableLoading';
import type {infoPopupProps} from './types';

export default function NewTaskPopup({
Expand Down Expand Up @@ -121,7 +122,9 @@ export default function NewTaskPopup({

<Text style={styles.failMessageTextStyle}>{failMessage}</Text>

<Pressable
<PressableLoading
loading={mutation.isPending}
loadingTextStyle={styles.buttonText}
style={({pressed}) => [
{
backgroundColor: pressed
Expand All @@ -141,7 +144,7 @@ export default function NewTaskPopup({
}
}}>
<Text style={styles.buttonText}>Create</Text>
</Pressable>
</PressableLoading>
<Pressable
style={({pressed}) => [
{
Expand Down
16 changes: 16 additions & 0 deletions src/components/pressableLoading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from 'react';
import {Pressable, Text} from 'react-native';

import {ButtonLoadingProps} from './types';

export default function PressableLoading(props: ButtonLoadingProps) {
return (
<Pressable disabled={props.loading} {...props}>
{props.loading ? (
<Text style={props.loadingTextStyle}>Loading...</Text>
) : (
props.children
)}
</Pressable>
);
}
43 changes: 30 additions & 13 deletions src/components/taskPopup.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,31 @@
import {useMutation, useQueryClient} from '@tanstack/react-query';
import React from 'react';
import {useQuery} from '@tanstack/react-query';
import React, {useMemo} from 'react';
import {Modal, Pressable, Text, View} from 'react-native';

import themeProvider from '../providers/themeProvider';
import {getTasks} from '../services/taskratchet/getTasks';
import {TaskInput, updateTask} from '../services/taskratchet/updateTask';
import {styles} from '../styles/taskPopupStyle';
import useIsDarkMode from '../utils/checkDarkMode';
import checkDate from '../utils/checkDate';
import PressableLoading from './pressableLoading';
import {TaskPopupProps} from './types';

export default function TaskPopup({
item,
id,
modalVisible,
setModalVisible,
}: TaskPopupProps): JSX.Element {
const {data: tasks} = useQuery({
queryKey: ['tasks'],
queryFn: getTasks,
});

const task = useMemo(() => {
return tasks?.find(t => t.id === id);
}, [tasks, id]);

const isDarkMode = useIsDarkMode();

const backgroundStyle = {
Expand Down Expand Up @@ -56,7 +68,7 @@ export default function TaskPopup({
}
}

const deadlineDetails = item && getDeadlineDetails(checkDate(item.due));
const deadlineDetails = task && getDeadlineDetails(checkDate(task.due));
const [stakesWidth, setStakesWidth] = React.useState(0);

return (
Expand All @@ -68,13 +80,13 @@ export default function TaskPopup({
onRequestClose={() => {
setModalVisible(!modalVisible);
}}>
{item ? (
{task ? (
<View style={styles.centeredView}>
<View style={[styles.modalView, backgroundStyle]}>
<View style={(styles.line, {paddingRight: stakesWidth + 10})}>
<View>
<Text style={[styles.title, textColorStyle]}>
{item.task}
{task.task}
</Text>
<Text style={deadlineDetails?.style}>
{deadlineDetails?.text}
Expand All @@ -86,11 +98,13 @@ export default function TaskPopup({
const {width} = event.nativeEvent.layout;
setStakesWidth(width);
}}>
${Number(item.cents / 100).toFixed(2)}
${Number(task.cents / 100).toFixed(2)}
</Text>
</View>
{checkDate(item.due) >= 0 ? (
<Pressable
{checkDate(task.due) >= 0 ? (
<PressableLoading
loading={mutation.isPending}
loadingTextStyle={styles.textStyle}
style={({pressed}) => [
{
backgroundColor: pressed
Expand All @@ -101,23 +115,26 @@ export default function TaskPopup({
styles.buttonComplete,
]}
onPress={() => {
if (id === undefined) {
throw new Error('Task ID is undefined');
}
mutation.mutate({
taskId: item.id,
data: {complete: !item.complete},
taskId: id,
data: {complete: !task.complete},
});
}}>
<Text style={styles.textStyle}>
{item.complete ? 'Mark Incomplete' : 'Mark Complete'}
{task.complete ? 'Mark Incomplete' : 'Mark Complete'}
</Text>
</Pressable>
</PressableLoading>
) : null}
<Pressable
style={({pressed}) => [
{
backgroundColor: pressed
? 'rgba(33, 150, 243, 0.5)'
: '#2196F3',
marginTop: checkDate(item.due) >= 0 ? 5 : 35,
marginTop: checkDate(task.due) >= 0 ? 5 : 35,
},
styles.button,
]}
Expand Down
9 changes: 8 additions & 1 deletion src/components/types.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {RouteProp} from '@react-navigation/native';
import {StackNavigationProp, StackScreenProps} from '@react-navigation/stack';
import {Dispatch, SetStateAction} from 'react';
import {PressableProps, StyleProp, TextStyle} from 'react-native';

export type tasksType = {
[key: string]: taskType;
Expand Down Expand Up @@ -33,7 +34,7 @@ export type Props = {

export type TaskPopupProps = {
testID?: string;
item?: taskType;
id?: string;
modalVisible: boolean;
setModalVisible: Dispatch<SetStateAction<boolean>>;
};
Expand All @@ -44,6 +45,12 @@ export type infoPopupProps = {
setModalVisible: Dispatch<SetStateAction<boolean>>;
};

export type ButtonLoadingProps = {
children?: React.ReactNode;
loading: boolean;
loadingTextStyle?: StyleProp<TextStyle> | undefined;
} & PressableProps;

export type DatePickerPopupProps = {
testID?: string;
dateModalVisible: boolean;
Expand Down
6 changes: 3 additions & 3 deletions src/screens/HomeScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ export default function HomeScreen({navigation}: Props): JSX.Element {
const [taskModalVisible, setTaskModalVisible] = useState(false);
const [infoModalVisible, setInfoModalVisible] = useState(false);
const [newTaskModalVisible, setNewTaskModalVisible] = useState(false);
const [clickedItem, setClickedItem] = useState<taskType>();
const [clickedId, setClickedId] = useState<string>();

const {data: tasks} = useQuery({
queryKey: ['tasks'],
Expand Down Expand Up @@ -75,7 +75,7 @@ export default function HomeScreen({navigation}: Props): JSX.Element {

function taskItemPress(item: taskType) {
setTaskModalVisible(!taskModalVisible);
setClickedItem(item);
setClickedId(item.id);
}

function handleNewTaskPress() {
Expand All @@ -96,7 +96,7 @@ export default function HomeScreen({navigation}: Props): JSX.Element {
/>
<TaskPopup
testID="taskPopup"
item={clickedItem}
id={clickedId}
modalVisible={taskModalVisible}
setModalVisible={setTaskModalVisible}
/>
Expand Down
7 changes: 5 additions & 2 deletions src/screens/LoginScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import helpIconBlack from '../../assets/icons/help_circle(black).png';
import helpIconWhite from '../../assets/icons/help_circle(white).png';
import logoBordered from '../../assets/images/logo_taskratchet_512_bordered.png';
import logo from '../../assets/images/[email protected]';
import PressableLoading from '../components/pressableLoading';
import {Props} from '../components/types';
import themeProvider from '../providers/themeProvider';
import {login} from '../services/taskratchet/login';
Expand Down Expand Up @@ -114,14 +115,16 @@ export default function LoginScreen({navigation}: Props): JSX.Element {
/>
</View>
</View>
<Pressable
<PressableLoading
testID="loginButton"
loading={mutation.isPending}
loadingTextStyle={styles.loginText}
style={styles.login}
onPress={() => {
mutation.mutate();
}}>
<Text style={styles.loginText}>Login</Text>
</Pressable>
</PressableLoading>
<Pressable
testID="registerButton"
style={styles.register}
Expand Down

0 comments on commit 49fa19d

Please sign in to comment.