Skip to content

Commit

Permalink
Refresh
Browse files Browse the repository at this point in the history
  • Loading branch information
koredefashokun committed Nov 29, 2024
1 parent 5d68f61 commit 0b26d45
Show file tree
Hide file tree
Showing 10 changed files with 191 additions and 34 deletions.
4 changes: 1 addition & 3 deletions apps/app/src/components/product/CartButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,7 @@ const CartButton: React.FC<CartButtonProps> = ({
}, [storeId, productId]);

const goToCart = React.useCallback(() => {
if (cartId) {
navigate('Cart', { cartId });
}
if (cartId) navigate('Cart', { cartId });
}, [cartId]);

const isNotInCart = !cartId || (cartId && !inCart);
Expand Down
9 changes: 4 additions & 5 deletions apps/dashboard/src/components/order/OrderActions.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Button } from '@habiti/components';
import { Button, HoldableButton, Spacer } from '@habiti/components';
import React from 'react';
import { Alert, StyleSheet, View } from 'react-native';

Expand Down Expand Up @@ -39,16 +39,15 @@ const OrderActions: React.FC<OrderActionsProps> = ({ orderId, status }) => {
return (
<View style={styles.container}>
{status !== OrderStatus.Completed && (
<Button
<HoldableButton
text='Mark as fulfilled'
loading={fetching}
onPress={updateOrderStatus(OrderStatus.Completed)}
style={styles.button}
onComplete={updateOrderStatus(OrderStatus.Completed)}
/>
)}
<Spacer y={8} />
{status !== OrderStatus.Cancelled && (
<Button
style={styles.button}
loading={fetching}
variant='destructive'
onPress={confirmCancel}
Expand Down
3 changes: 2 additions & 1 deletion apps/dashboard/src/components/store/StoreMenuRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ const styles = StyleSheet.create({
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
paddingHorizontal: 16,
paddingLeft: 16,
paddingRight: 12,
paddingVertical: 8
}
});
Expand Down
5 changes: 3 additions & 2 deletions apps/dashboard/src/screens/EditCategory.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,13 @@ const EditCategoryMain: React.FC<EditCategoryMainProps> = ({
<FormInput
label='Description'
name='description'
placeholder='Describe your category'
control={methods.control}
textArea
/>
<Spacer y={8} />
<Spacer y={16} />
<Button
text='Edit profile'
text='Edit Category'
onPress={methods.handleSubmit(onSubmit)}
loading={fetching}
/>
Expand Down
7 changes: 6 additions & 1 deletion apps/dashboard/src/screens/Inventory.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
import { Screen } from '@habiti/components';
import React from 'react';
import { View } from 'react-native';

const Inventory = () => {
return <Screen />;
return (
<Screen>
<View style={{ flex: 1 }} />
</Screen>
);
};

export default Inventory;
44 changes: 27 additions & 17 deletions apps/dashboard/src/screens/Managers.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Icon, ScrollableScreen, useTheme } from '@habiti/components';
import { Icon, ScrollableScreen, Screen, useTheme } from '@habiti/components';
import { NavigationProp, useNavigation } from '@react-navigation/native';
import React from 'react';
import { View, StyleSheet, Pressable, RefreshControl } from 'react-native';
Expand All @@ -11,12 +11,22 @@ import { AppStackParamList } from '../types/navigation';

const Managers = () => {
const [{ data, fetching }, refetch] = useManagersQuery();
const [refreshing, setRefreshing] = React.useState(false);
useGoBack();
const userId = useStore(({ userId }) => userId);
const { navigate, setOptions } =
useNavigation<NavigationProp<AppStackParamList>>();
const { theme } = useTheme();

const refresh = React.useCallback(() => {
setRefreshing(true);
refetch();
}, [refetch]);

React.useEffect(() => {
if (!fetching && refreshing) setRefreshing(false);
}, [fetching, refreshing]);

React.useLayoutEffect(() => {
setOptions({
headerRight: () => (
Expand All @@ -32,22 +42,22 @@ const Managers = () => {
}

return (
<ScrollableScreen
style={styles.container}
refreshControl={
<RefreshControl
refreshing={fetching}
onRefresh={() => {
refetch({ requestPolicy: 'network-only' });
}}
tintColor={theme.text.secondary}
/>
}
>
{data.currentStore.managers.map(({ id, manager }) => (
<ManagerRow key={id} manager={manager} you={userId === manager.id} />
))}
</ScrollableScreen>
<Screen>
<ScrollableScreen
style={styles.container}
refreshControl={
<RefreshControl
refreshing={refreshing}
onRefresh={refresh}
tintColor={theme.text.secondary}
/>
}
>
{data.currentStore.managers.map(({ id, manager }) => (
<ManagerRow key={id} manager={manager} you={userId === manager.id} />
))}
</ScrollableScreen>
</Screen>
);
};

Expand Down
29 changes: 25 additions & 4 deletions apps/dashboard/src/screens/Order.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ScrollableScreen } from '@habiti/components';
import { ScrollableScreen, useTheme } from '@habiti/components';
import { useRoute, RouteProp } from '@react-navigation/native';
import React from 'react';
import { View } from 'react-native';
import { View, RefreshControl } from 'react-native';

import CustomerDetails from '../components/order/CustomerDetails';
import OrderActions from '../components/order/OrderActions';
Expand All @@ -16,15 +16,36 @@ const Order: React.FC = () => {
const {
params: { orderId }
} = useRoute<RouteProp<OrdersStackParamList, 'Order'>>();
const [{ data, fetching }] = useOrderQuery({ variables: { id: orderId } });
const [{ data, fetching }, refetch] = useOrderQuery({
variables: { id: orderId }
});
const [refreshing, setRefreshing] = React.useState(false);
const { theme } = useTheme();
useGoBack();

const handleRefresh = React.useCallback(() => {
setRefreshing(true);
refetch();
}, [refetch]);

React.useEffect(() => {
if (!fetching && refreshing) setRefreshing(false);
}, [fetching, refreshing]);

if (fetching || !data?.order) {
return <View />;
}

return (
<ScrollableScreen>
<ScrollableScreen
refreshControl={
<RefreshControl
refreshing={refreshing}
onRefresh={handleRefresh}
tintColor={theme.text.secondary}
/>
}
>
<OrderOverview order={data.order} />
<CustomerDetails user={data.order.user} />
<OrderProducts products={data.order.products} />
Expand Down
1 change: 0 additions & 1 deletion apps/dashboard/src/screens/SearchProducts.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ const SearchProducts = () => {
showsVerticalScrollIndicator={false}
renderItem={renderProduct}
estimatedItemSize={60}
contentContainerStyle={{ paddingTop: 8 }}
/>
)}
</Screen>
Expand Down
122 changes: 122 additions & 0 deletions packages/components/src/HoldableButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import React from 'react';
import {
Pressable,
StyleSheet,
ViewStyle,
ActivityIndicator,
PressableProps
} from 'react-native';
import Animated, {
useAnimatedStyle,
withTiming,
useSharedValue,
runOnJS,
withSequence
} from 'react-native-reanimated';

import { useTheme } from './Theme';
import Typography from './Typography';
import { ThemeObject } from './styles/theme';

interface HoldableButtonProps extends PressableProps {
onComplete: () => void;
duration?: number;
style?: ViewStyle;
variant?: keyof ThemeObject['button'];
text?: string;
loading?: boolean;
children?: React.ReactNode;
disabled?: boolean;
}

const HoldableButton: React.FC<HoldableButtonProps> = ({
onComplete,
duration = 2000,
style,
variant = 'primary',
text,
loading,
children,
disabled = false,
...props
}) => {
const progress = useSharedValue(0);
const { theme } = useTheme();
const colors = theme.button[disabled ? 'disabled' : variant];

const handlePressIn = () => {
if (!disabled && !loading) {
progress.value = withTiming(1, { duration }, finished => {
if (finished) {
runOnJS(onComplete)();
}
});
}
};

const handlePressOut = () => {
progress.value = withSequence(
withTiming(progress.value, { duration: 0 }), // Freeze at current value
withTiming(0, { duration: 100 }) // Animate back to 0
);
};

const animatedStyle = useAnimatedStyle(() => ({
width: `${progress.value * 100}%`
}));

return (
<Pressable
onPressIn={handlePressIn}
onPressOut={handlePressOut}
style={[styles.container, { backgroundColor: colors.background }, style]}
disabled={disabled || loading}
{...props}
>
<Animated.View
style={[
styles.progressBar,
{ backgroundColor: colors.text },
animatedStyle
]}
/>
{loading ? (
<ActivityIndicator color={colors.text} />
) : text ? (
<Typography
weight='medium'
style={[styles.text, { color: colors.text }]}
>
{text}
</Typography>
) : (
children
)}
</Pressable>
);
};

const styles = StyleSheet.create({
container: {
position: 'relative',
justifyContent: 'center',
alignItems: 'center',
height: 44,
borderRadius: 6,
overflow: 'hidden'
},
text: {
fontSize: 17,
zIndex: 1
},
progressBar: {
position: 'absolute',
top: 0,
left: 0,
height: '100%',
opacity: 0.15,
zIndex: 0
}
});

export default HoldableButton;
1 change: 1 addition & 0 deletions packages/components/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export { default as Dialog } from './Dialog';
export { default as CustomImage } from './CustomImage';
export { default as EmptyState } from './EmptyState';
export { default as FormInput } from './FormInput';
export { default as HoldableButton } from './HoldableButton';
export { Icon, IconType } from './Icon';
export { default as IconButton } from './IconButton';
export { default as Input } from './Input';
Expand Down

0 comments on commit 0b26d45

Please sign in to comment.