Skip to content

Commit eb602bb

Browse files
author
Mikhail
committed
finished screens
1 parent d669c8c commit eb602bb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

66 files changed

+2342
-29
lines changed

App.tsx

+12-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,20 @@
11
import React from 'react';
2-
import { StatusBar, Text, View } from 'react-native';
2+
import { StatusBar, View } from 'react-native';
3+
import { Provider } from 'react-redux';
4+
import Home from './Home';
5+
import store from './redux/store';
6+
import 'react-native-gesture-handler';
7+
import { GestureHandlerRootView } from 'react-native-gesture-handler';
38

49
const App = () => {
510
return (
6-
<View style={{ flex: 1 }} >
11+
12+
<Provider store={store} >
13+
<GestureHandlerRootView style={{ flex: 1 }}>
714
<StatusBar barStyle='dark-content' backgroundColor="transparent" translucent />
8-
</View>
15+
<Home />
16+
</GestureHandlerRootView>
17+
</Provider>
918
);
1019
};
1120

Home.tsx

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import React from 'react';
2+
import { NavigationContainer } from '@react-navigation/native';
3+
import { View } from 'react-native';
4+
import NavigationTabs from './navigator/NavigationTabs';
5+
6+
const Home = () => {
7+
return (
8+
<View style={{ flex: 1 }}>
9+
<NavigationContainer >
10+
<NavigationTabs />
11+
</NavigationContainer>
12+
</View>
13+
);
14+
}
15+
export default Home;

android/app/build.gradle

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
apply plugin: "com.android.application"
2+
apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"
23

34
import com.android.build.OutputFile
45
import org.apache.tools.ant.taskdefs.condition.Os

api/index.ts

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import axios from 'axios';
2+
3+
const api = 'https://jsonplaceholder.typicode.com';
4+
5+
const getAxiosRequest = () => axios.create({
6+
headers: {
7+
'Content-Type': 'application/json; charset=utf-8',
8+
Accept: 'application/json',
9+
'Cache-Control': 'no-store, no-cache, must-revalidate',
10+
},
11+
});
12+
13+
export default {
14+
getPosts() {
15+
const request = getAxiosRequest();
16+
17+
return request.get(`${api}/posts`);
18+
},
19+
};

assets/images/bridge.jpg

52 KB
Loading

assets/images/bulldog.jpg

74.1 KB
Loading

assets/images/cat.jpg

34.8 KB
Loading

assets/images/hyacinth.jpg

57.6 KB
Loading

assets/images/man.jpg

3.53 MB
Loading

assets/images/morning.jpg

28.6 KB
Loading

babel.config.js

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
module.exports = {
22
presets: ['module:metro-react-native-babel-preset'],
3+
plugins: ['react-native-reanimated/plugin']
34
};

components/AnimationsScreen/Card.tsx

+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import React from 'react';
2+
import {
3+
StyleSheet, TouchableOpacity,
4+
} from 'react-native';
5+
import Animated, {
6+
SlideInLeft, Layout, ZoomOut, useAnimatedStyle, useSharedValue, withTiming, useAnimatedGestureHandler, withSpring,
7+
} from 'react-native-reanimated';
8+
import MaterialIcon from 'react-native-vector-icons/MaterialIcons';
9+
import FontAwesomeIcon from 'react-native-vector-icons/FontAwesome';
10+
import {
11+
PanGestureHandler,
12+
PanGestureHandlerGestureEvent,
13+
} from 'react-native-gesture-handler';
14+
15+
const generateColor = () => {
16+
const randomColor = Math.floor(Math.random() * 16777215)
17+
.toString(16)
18+
.padStart(6, '0');
19+
return `#${randomColor}`;
20+
};
21+
22+
type Props = {
23+
deleteCard: () => void;
24+
};
25+
26+
type ContextType = {
27+
translateX: number;
28+
translateY: number;
29+
};
30+
31+
function Card({ deleteCard }: Props) {
32+
const rotation = useSharedValue(0);
33+
const translateX = useSharedValue(0);
34+
const translateY = useSharedValue(0);
35+
36+
const animatedStyle = useAnimatedStyle(() => ({
37+
transform: [{
38+
rotateZ: `${rotation.value}deg`,
39+
},
40+
{
41+
translateX: translateX.value,
42+
},
43+
{
44+
translateY: translateY.value,
45+
}],
46+
}));
47+
48+
const panGestureEvent = useAnimatedGestureHandler<
49+
PanGestureHandlerGestureEvent,
50+
ContextType
51+
>({
52+
onStart: (event, context) => {
53+
context.translateX = translateX.value;
54+
context.translateY = translateY.value;
55+
},
56+
onActive: (event, context) => {
57+
translateX.value = event.translationX + context.translateX;
58+
translateY.value = event.translationY + context.translateY;
59+
},
60+
onEnd: () => {
61+
translateX.value = withSpring(0);
62+
translateY.value = withSpring(0);
63+
},
64+
});
65+
66+
return (
67+
<PanGestureHandler onGestureEvent={panGestureEvent}>
68+
<Animated.View
69+
layout={Layout.springify()}
70+
style={[styles.container, animatedStyle, { backgroundColor: generateColor() }]}
71+
entering={SlideInLeft}
72+
exiting={ZoomOut}
73+
>
74+
75+
<TouchableOpacity
76+
onPress={() => { rotation.value = withTiming(rotation.value + 360, { duration: 550 }); }}
77+
>
78+
<FontAwesomeIcon name="rotate-right" size={20} color="gray" />
79+
</TouchableOpacity>
80+
<TouchableOpacity
81+
style={styles.deleteButtonContainer}
82+
onPress={deleteCard}
83+
>
84+
<MaterialIcon name="delete" size={20} color="gray" />
85+
</TouchableOpacity>
86+
</Animated.View>
87+
</PanGestureHandler>
88+
);
89+
} export default Card;
90+
91+
const styles = StyleSheet.create({
92+
container: {
93+
margin: 10,
94+
padding: 16,
95+
height: 200,
96+
borderRadius: 16,
97+
overflow: 'hidden',
98+
shadowColor: '#000',
99+
shadowOffset: {
100+
width: 0,
101+
height: 2,
102+
},
103+
shadowOpacity: 0.25,
104+
shadowRadius: 3.84,
105+
106+
elevation: 5,
107+
},
108+
deleteButtonContainer: {
109+
backgroundColor: 'white',
110+
position: 'absolute',
111+
bottom: 10,
112+
right: 10,
113+
padding: 8,
114+
borderRadius: 8,
115+
},
116+
});

components/NewsScreen/NewsCard.tsx

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import React from 'react';
2+
import {
3+
StyleSheet, View, Text, TouchableOpacity, Image,
4+
} from 'react-native';
5+
import { StackNavigationProp } from '@react-navigation/stack/lib/typescript/src/types';
6+
import { StackParamList } from '../../navigator/types';
7+
8+
type Props = {
9+
item: {
10+
title: string,
11+
body: string,
12+
}
13+
photo: any,
14+
navigation: StackNavigationProp<StackParamList, 'NewsScreen'>
15+
};
16+
17+
export default function NewsCard(props: Props) {
18+
const { item, photo, navigation } = props;
19+
return (
20+
<TouchableOpacity
21+
style={styles.container}
22+
onPress={() => navigation.navigate('CurrentNewsScreen', { item, photo })}
23+
>
24+
<View style={{ flex: 1, padding: 16 }}>
25+
<Text
26+
numberOfLines={2}
27+
style={styles.titleContainer}
28+
>
29+
{item.title}
30+
31+
</Text>
32+
<Text
33+
numberOfLines={3}
34+
style={styles.bodyContainer}
35+
>
36+
{item.body}
37+
38+
</Text>
39+
</View>
40+
<Image
41+
style={styles.imageContainer}
42+
source={photo}
43+
/>
44+
45+
</TouchableOpacity>
46+
);
47+
}
48+
49+
const styles = StyleSheet.create({
50+
container: {
51+
backgroundColor: 'white',
52+
borderRadius: 16,
53+
marginVertical: 8,
54+
marginHorizontal: 16,
55+
shadowColor: '#000',
56+
flexDirection: 'row',
57+
shadowOffset: {
58+
width: 0,
59+
height: 2,
60+
},
61+
shadowOpacity: 0.25,
62+
shadowRadius: 3.84,
63+
64+
elevation: 5,
65+
},
66+
imageContainer: {
67+
flex: 1,
68+
width: '100%',
69+
height: '100%',
70+
borderTopRightRadius: 16,
71+
borderBottomRightRadius: 16,
72+
},
73+
titleContainer: {
74+
fontSize: 18,
75+
fontWeight: '700',
76+
paddingBottom: 8,
77+
},
78+
bodyContainer: {
79+
fontSize: 12,
80+
fontWeight: '400',
81+
},
82+
});
+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import React from 'react';
2+
import {
3+
StyleSheet, View, Text,
4+
} from 'react-native';
5+
6+
type Props = {
7+
title: string,
8+
content: string | undefined,
9+
};
10+
11+
export default function ProfileField(props: Props) {
12+
const { title, content } = props;
13+
const hideInfo = () => {
14+
switch (title) {
15+
case 'Password': {
16+
return content?.replace(content, '*********');
17+
}
18+
case 'Email': {
19+
return content?.replace(/(\w{3})[\w.-]+@([\w.]+\w)/, '$1***@$2');
20+
}
21+
default: {
22+
return content;
23+
}
24+
}
25+
};
26+
27+
return (
28+
<View style={{ marginVertical: 8 }}>
29+
<Text style={styles.titleText}>{title}</Text>
30+
<Text style={styles.contentText}>{hideInfo()}</Text>
31+
</View>
32+
);
33+
}
34+
35+
const styles = StyleSheet.create({
36+
titleText: {
37+
fontSize: 14,
38+
fontWeight: '700',
39+
color: '#748D63',
40+
},
41+
contentText: {
42+
fontSize: 14,
43+
fontWeight: '500',
44+
color: 'black',
45+
},
46+
});

components/common/DefaultButton.tsx

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import React from 'react';
2+
import {
3+
StyleSheet, TouchableOpacity, Text,
4+
} from 'react-native';
5+
6+
type Props = {
7+
title: string,
8+
icon: any,
9+
onPress?: () => void;
10+
errors?: boolean
11+
};
12+
13+
export default function DefaultButton(props: Props) {
14+
const {
15+
title, icon, onPress, errors,
16+
} = props;
17+
return (
18+
<TouchableOpacity
19+
style={[styles.buttonContainer, { opacity: errors ? 0.5 : 1 }]}
20+
disabled={errors}
21+
onPress={onPress}
22+
>
23+
<Text style={styles.buttonText}>
24+
{ title }
25+
</Text>
26+
{ icon }
27+
</TouchableOpacity>
28+
);
29+
}
30+
31+
DefaultButton.defaultProps = {
32+
errors: false,
33+
onPress: undefined,
34+
};
35+
const styles = StyleSheet.create({
36+
37+
buttonText: {
38+
fontSize: 16,
39+
fontWeight: '400',
40+
color: '#748D63',
41+
paddingRight: 10,
42+
},
43+
buttonContainer: {
44+
justifyContent: 'center',
45+
alignItems: 'center',
46+
paddingVertical: 16,
47+
borderRadius: 16,
48+
flexDirection: 'row',
49+
borderColor: '#748D63',
50+
borderWidth: 2,
51+
marginTop: 16,
52+
},
53+
imageContainer: {
54+
borderWidth: 4,
55+
borderRadius: 125,
56+
borderColor: '#748D63',
57+
margin: 16,
58+
alignSelf: 'center',
59+
},
60+
backgroundDataContainer: {
61+
backgroundColor: 'white',
62+
borderRadius: 16,
63+
padding: 16,
64+
shadowColor: '#000',
65+
shadowOffset: {
66+
width: 0,
67+
height: 2,
68+
},
69+
shadowOpacity: 0.25,
70+
shadowRadius: 3.84,
71+
72+
elevation: 5,
73+
},
74+
});

0 commit comments

Comments
 (0)