From 03bf9b015f6e4add0927087566e0aebc0937d70b Mon Sep 17 00:00:00 2001 From: Andrew Parker Date: Wed, 23 Oct 2024 22:17:55 -0400 Subject: [PATCH] adding animation on box! --- apps/releaf/mobile/src/app/box/Box.tsx | 214 ------------------ .../mobile/src/app/box/components/Box.tsx | 114 ++++++++++ .../mobile/src/app/box/screens/Boxes.tsx | 117 ++++++++++ .../mobile/src/app/navigation/Navigation.tsx | 4 +- 4 files changed, 233 insertions(+), 216 deletions(-) delete mode 100644 apps/releaf/mobile/src/app/box/Box.tsx create mode 100644 apps/releaf/mobile/src/app/box/components/Box.tsx create mode 100644 apps/releaf/mobile/src/app/box/screens/Boxes.tsx diff --git a/apps/releaf/mobile/src/app/box/Box.tsx b/apps/releaf/mobile/src/app/box/Box.tsx deleted file mode 100644 index 09603a4..0000000 --- a/apps/releaf/mobile/src/app/box/Box.tsx +++ /dev/null @@ -1,214 +0,0 @@ -import { - View, - Text, - ScrollView, - StyleSheet, - TouchableOpacity, -} from 'react-native'; -import { SafeAreaView } from 'react-native-safe-area-context'; -import { createNativeStackNavigator } from '@react-navigation/native-stack'; -import { useCallback, useEffect, useState } from 'react'; -import { Loading } from '../shared/Loading'; -import { BoxDetailsScreen } from './screens/BoxDetails'; -import { BoxService } from '../infrastructure/services/box.service'; -import { SetupBox } from './screens/SetupBox'; -import { BoxItem } from '../infrastructure/entities/box'; -import { styled } from 'nativewind'; -import LinearGradient from 'react-native-linear-gradient'; -import { Edit } from '../../assets/images/edit'; -import { Logo } from '../../assets/images/logo' -import { selectTreeDefinitions } from '../store/slices/treeDefinitionSlice'; -import { useSelector } from 'react-redux'; - -const MAX_NAME_LENGTH = 7; -const styles = StyleSheet.create({ - font: { - fontFamily: 'Lato-Regular', - }, - fontBold: { - fontFamily: 'Lato-Bold', - }, - title: { - fontSize: 20, - fontWeight: '700', - color: '#2C4E3C', - }, - bottomSection: { - backgroundColor: '#FFFFFF', - flexDirection: 'row', - justifyContent: 'space-between', - borderRadius: 50, - padding: 10, - marginTop: 20, - }, - linearGradient: { - flex: 1, - borderRadius: 5, - marginBottom: 50, - // elevation: 0.1, - // transform: [{ rotateX: '7deg' }], - shadowColor: '#000000', - elevation: 6, - }, - borderBottom: { - borderRadius: 50, - }, -}); - -const SView = styled(View); -const SText = styled(Text); -const STouchableOpacity = styled(TouchableOpacity); -const SLinearGradient = styled(LinearGradient); - -export const Box = () => { - return ( - - - - - - - ); -}; - -const SettingsStack = createNativeStackNavigator(); - -function BoxScreen({ navigation }) { - const boxService = new BoxService(); - - const treeDefinitions = useSelector(selectTreeDefinitions); - const [isLoading, setIsLoading] = useState(true); - const [boxes, setBoxes] = useState([]); - - useEffect(() => { - if (treeDefinitions.length === 0) return; - if (boxes.length === 0) return; - boxes.forEach((box) => box.setTreeName(treeDefinitions)); - }, [treeDefinitions, boxes]) - - const fetchBoxes = useCallback(async () => { - setIsLoading(true); - try { - const allBoxes = await boxService.getAll(); - setBoxes(allBoxes.map((box) => new BoxItem(box))); - } catch (error) { - console.error(error); - } - setIsLoading(false); - }, []); - - useEffect((): void => { - void fetchBoxes(); - }, [fetchBoxes]); - - if (isLoading) { - return ; - } - - return ( - - - - - navigation.navigate('SetupBox')}> - - Mes Boîtes ({boxes?.length ?? 0}) - - - - - - - {boxes.map((box, boxIndex) => ( - - - - - - {box.treeName} - - - {box.dateSinceGermination} - jours - - - {box.seeds - .reduce((acc, curr, i) => { - if (i % 5 == 0) acc.push([]); - acc[acc.length - 1].push(curr); - return acc; - }, []) - .map((seeds, rowIndex) => ( - - {seeds.map((seed, i) => ( - - - - - - {(seed.name as string).substring( - 0, - MAX_NAME_LENGTH - )} - {seed.name.length > MAX_NAME_LENGTH ? '.' : ''} - - - - ))} - - ))} - - - - - - navigation.navigate('BoxDetails', { id: '11111' }) - } - > - {box.seedsAverageInchHeight} cm - {box.germinationDay} - - - - - - - ))} - - - - ); -} diff --git a/apps/releaf/mobile/src/app/box/components/Box.tsx b/apps/releaf/mobile/src/app/box/components/Box.tsx new file mode 100644 index 0000000..aecd44c --- /dev/null +++ b/apps/releaf/mobile/src/app/box/components/Box.tsx @@ -0,0 +1,114 @@ +import { styled } from "nativewind"; +import { TouchableOpacity, View, Text, GestureResponderEvent, Dimensions } from "react-native"; +import LinearGradient from "react-native-linear-gradient"; +import { BoxItem } from "../../infrastructure/entities/box"; +import { Edit } from '../../../assets/images/edit'; +import { Logo } from '../../../assets/images/logo' +import { useState } from "react"; + +const windowWidth = Dimensions.get('window').width; + +const SView = styled(View); +const SText = styled(Text); +const STouchableOpacity = styled(TouchableOpacity); +const SLinearGradient = styled(LinearGradient); + +const MAX_NAME_LENGTH = 7; + +export function Box({ box }: { box: BoxItem }) { + const [boxHoldPosition, setBoxHoldPosition] = useState(0); + const [boxPosition, setBoxPosition] = useState(0); + + const ontouchstart = (ev: GestureResponderEvent) => { + setBoxHoldPosition(ev.nativeEvent.locationX) + } + + const ontouchmove = (ev: GestureResponderEvent) => { + const diff = ev.nativeEvent.pageX - boxHoldPosition + const pagePercent = (diff / windowWidth) * 100 + if (pagePercent < -60 || pagePercent > 0) return + if (Math.abs(diff - boxPosition) < 0.5) return + setBoxPosition(diff) + } + + const ontouchend = (ev: GestureResponderEvent) => { + const pagePercent = (boxPosition / windowWidth) * 100 + const diff = ev.nativeEvent.pageX - boxHoldPosition + setBoxPosition(diff) + if (pagePercent < -20) { + setBoxPosition((-60 / 100) * windowWidth) + } else { + setBoxPosition(0) + } + } + + return ( + + + + + + + {box.treeName} + + + {box.dateSinceGermination} + jours + + + {box.seeds + .reduce((acc, curr, i) => { + if (i % 5 == 0) acc.push([]); + acc[acc.length - 1].push(curr); + return acc; + }, []) + .map((seeds, rowIndex) => ( + + {seeds.map((seed, i) => ( + + + + + + {(seed.name as string).substring( + 0, + MAX_NAME_LENGTH + )} + {seed.name.length > MAX_NAME_LENGTH ? '.' : ''} + + + + ))} + + ))} + + + + + + {box.seedsAverageInchHeight} cm + {box.germinationDay} + + + + + + + ); +} \ No newline at end of file diff --git a/apps/releaf/mobile/src/app/box/screens/Boxes.tsx b/apps/releaf/mobile/src/app/box/screens/Boxes.tsx new file mode 100644 index 0000000..db3d3ec --- /dev/null +++ b/apps/releaf/mobile/src/app/box/screens/Boxes.tsx @@ -0,0 +1,117 @@ +import { + View, + Text, + ScrollView, + StyleSheet, + TouchableOpacity, +} from 'react-native'; +import { SafeAreaView } from 'react-native-safe-area-context'; +import { createNativeStackNavigator } from '@react-navigation/native-stack'; +import { useCallback, useEffect, useState } from 'react'; +import { Loading } from '../../shared/Loading'; +import { BoxDetailsScreen } from './BoxDetails'; +import { BoxService } from '../../infrastructure/services/box.service'; +import { SetupBox } from './SetupBox'; +import { BoxItem } from '../../infrastructure/entities/box'; +import { styled } from 'nativewind'; +import { selectTreeDefinitions } from '../../store/slices/treeDefinitionSlice'; +import { useSelector } from 'react-redux'; +import { Box } from '../components/Box'; + +const styles = StyleSheet.create({ + title: { + fontSize: 20, + fontWeight: '700', + color: '#2C4E3C', + } +}); + +const SView = styled(View); + +export const Boxes = () => { + return ( + + + + + + + ); +}; + +const SettingsStack = createNativeStackNavigator(); + +function BoxScreen({ navigation }) { + const boxService = new BoxService(); + + const treeDefinitions = useSelector(selectTreeDefinitions); + const [isLoading, setIsLoading] = useState(true); + const [boxes, setBoxes] = useState([]); + + useEffect(() => { + if (treeDefinitions.length === 0) return; + if (boxes.length === 0) return; + boxes.forEach((box) => box.setTreeName(treeDefinitions)); + }, [treeDefinitions, boxes]) + + const fetchBoxes = useCallback(async () => { + setIsLoading(true); + try { + const allBoxes = await boxService.getAll(); + setBoxes(allBoxes.map((box) => new BoxItem(box))); + } catch (error) { + console.error(error); + } + setIsLoading(false); + }, []); + + useEffect((): void => { + void fetchBoxes(); + }, [fetchBoxes]); + + if (isLoading) { + return ; + } + + return ( + + + + + navigation.navigate('SetupBox')}> + + Mes Boîtes ({boxes?.length ?? 0}) + + + + + + + {boxes.map((box, boxIndex) => ( + + ))} + + + + ); +} diff --git a/apps/releaf/mobile/src/app/navigation/Navigation.tsx b/apps/releaf/mobile/src/app/navigation/Navigation.tsx index 10fc752..68089a7 100644 --- a/apps/releaf/mobile/src/app/navigation/Navigation.tsx +++ b/apps/releaf/mobile/src/app/navigation/Navigation.tsx @@ -7,7 +7,7 @@ import { Order } from '../order/Order'; import { Knowledge } from '../knowledge/Knowledge'; import { Profile } from '../profile/Profile'; import { Notifications } from '../notifications/Notifications'; -import { Box } from '../box/Box'; +import { Boxes } from '../box/screens/Boxes'; import { useDispatch } from 'react-redux'; import { load } from '../store/slices/treeDefinitionSlice'; @@ -63,7 +63,7 @@ export const Navigation = () => { />