react-native-salespanda 0.7.7 → 0.7.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -5
- package/src/NativeSalespanda.ts +0 -7
- package/src/SalespandaApp.tsx +0 -141
- package/src/assets/images/bottomtabs/analytics.png +0 -0
- package/src/assets/images/bottomtabs/analyticsactive.png +0 -0
- package/src/assets/images/bottomtabs/crm.png +0 -0
- package/src/assets/images/bottomtabs/crmactive.png +0 -0
- package/src/assets/images/bottomtabs/diary.png +0 -0
- package/src/assets/images/bottomtabs/diaryactive.png +0 -0
- package/src/assets/images/bottomtabs/home.png +0 -0
- package/src/assets/images/bottomtabs/homeactive.png +0 -0
- package/src/assets/images/bottomtabs/notification.png +0 -0
- package/src/assets/images/bottomtabs/notificationactive.png +0 -0
- package/src/assets/images/index.js +0 -11
- package/src/assets/images/index.ts +0 -40
- package/src/components/BottomSheet.tsx +0 -146
- package/src/components/ContactViaModal.tsx +0 -80
- package/src/components/Loader.tsx +0 -48
- package/src/components/ScreenHeader.tsx +0 -57
- package/src/components/SearchBar.tsx +0 -59
- package/src/components/TabsHeader.tsx +0 -72
- package/src/components/index.ts +0 -5
- package/src/config/FlavorConfig.ts +0 -55
- package/src/config/SalespandaConfig.ts +0 -142
- package/src/constants/Colors.ts +0 -17
- package/src/constants/GetPlatorm.ts +0 -29
- package/src/index.tsx +0 -31
- package/src/navigation/AppNavigator.tsx +0 -24
- package/src/navigation/BottomTabNavigator.tsx +0 -181
- package/src/navigation/DrawerNavigator.tsx +0 -306
- package/src/navigation/StackNavigator.tsx +0 -32
- package/src/screens/CRM/AddContactModal.tsx +0 -57
- package/src/screens/CRM/CategoryTabs.tsx +0 -109
- package/src/screens/CRM/ContactItem.tsx +0 -168
- package/src/screens/CRM/FilterDropdown.tsx +0 -34
- package/src/screens/CRM/FunnelChart.tsx +0 -103
- package/src/screens/CRM/InfoCard.tsx +0 -51
- package/src/screens/CRM/LeadCard.tsx +0 -69
- package/src/screens/CRM/LogCallScreen.tsx +0 -318
- package/src/screens/CRM/TopTabs.tsx +0 -95
- package/src/screens/CRM/index.ts +0 -10
- package/src/screens/ReportsScreen.tsx +0 -37
- package/src/screens/Tabs/ActivityAnalytics.tsx +0 -25
- package/src/screens/Tabs/CRMScreen.tsx +0 -381
- package/src/screens/Tabs/DigitalDiary.tsx +0 -35
- package/src/screens/Tabs/HomeScreen.tsx +0 -379
- package/src/screens/Tabs/NotificationsScreen.tsx +0 -25
- package/src/screens/contentliberary/contentliberary.tsx +0 -268
- package/src/services/api.ts +0 -173
- package/src/services/authService.ts +0 -75
- package/src/store/index.ts +0 -16
package/package.json
CHANGED
|
@@ -1,19 +1,17 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-salespanda",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.8",
|
|
4
4
|
"description": "React Native SDK for multi-tenant enterprise applications with product flavors support",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
|
-
"types": "
|
|
6
|
+
"types": "lib/typescript/src/index.d.ts",
|
|
7
7
|
"exports": {
|
|
8
8
|
".": {
|
|
9
|
-
"source": "./src/index.tsx",
|
|
10
9
|
"types": "./lib/typescript/src/index.d.ts",
|
|
11
10
|
"default": "./lib/module/index.js"
|
|
12
11
|
},
|
|
13
12
|
"./package.json": "./package.json"
|
|
14
13
|
},
|
|
15
14
|
"files": [
|
|
16
|
-
"src",
|
|
17
15
|
"lib",
|
|
18
16
|
"android",
|
|
19
17
|
"ios",
|
|
@@ -59,7 +57,6 @@
|
|
|
59
57
|
"registry": "https://registry.npmjs.org/"
|
|
60
58
|
},
|
|
61
59
|
"devDependencies": {
|
|
62
|
-
"@babel/core": "^7.28.5",
|
|
63
60
|
"@commitlint/config-conventional": "^19.8.1",
|
|
64
61
|
"@eslint/compat": "^1.3.2",
|
|
65
62
|
"@eslint/eslintrc": "^3.3.1",
|
package/src/NativeSalespanda.ts
DELETED
package/src/SalespandaApp.tsx
DELETED
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { NavigationContainer, DefaultTheme } from '@react-navigation/native';
|
|
3
|
-
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
|
4
|
-
import { StyleSheet } from 'react-native';
|
|
5
|
-
import StackNavigator from './navigation/StackNavigator';
|
|
6
|
-
import { Provider } from 'react-redux';
|
|
7
|
-
import { store } from './store';
|
|
8
|
-
import {
|
|
9
|
-
SafeAreaProvider,
|
|
10
|
-
initialWindowMetrics,
|
|
11
|
-
} from 'react-native-safe-area-context';
|
|
12
|
-
import { Colors } from './constants/Colors';
|
|
13
|
-
|
|
14
|
-
export interface SalespandaAppProps {
|
|
15
|
-
/**
|
|
16
|
-
* Custom navigation container ref for external navigation control
|
|
17
|
-
*/
|
|
18
|
-
navigationRef?: React.RefObject<any>;
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Optional theme configuration
|
|
22
|
-
*/
|
|
23
|
-
theme?: {
|
|
24
|
-
primaryColor?: string;
|
|
25
|
-
backgroundColor?: string;
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* If true, the app will not render NavigationContainer
|
|
30
|
-
* (useful when embedding in an existing navigation structure)
|
|
31
|
-
*/
|
|
32
|
-
standalone?: boolean;
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Callback when app is ready
|
|
36
|
-
*/
|
|
37
|
-
onReady?: () => void;
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Navigation type configuration
|
|
41
|
-
* - 'drawer': Drawer navigation only
|
|
42
|
-
* - 'tabs': Bottom tabs only
|
|
43
|
-
* - 'both': Drawer wrapping bottom tabs (default)
|
|
44
|
-
* @default 'both'
|
|
45
|
-
*/
|
|
46
|
-
navigationType?: 'drawer' | 'tabs' | 'both';
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* @deprecated Use navigationType instead
|
|
50
|
-
* If true, uses drawer navigation, otherwise uses bottom tabs only
|
|
51
|
-
*/
|
|
52
|
-
useDrawer?: boolean;
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* If false, will not wrap with GestureHandlerRootView
|
|
56
|
-
* Set to false if your app already has gesture handler imported at the entry point
|
|
57
|
-
* @default true
|
|
58
|
-
*/
|
|
59
|
-
wrapWithGestureHandler?: boolean;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/**
|
|
63
|
-
* Render appropriate navigation based on type
|
|
64
|
-
*/
|
|
65
|
-
const AppContent: React.FC = () => {
|
|
66
|
-
// Always wrap with StackNavigator to support modal screens like LogCall
|
|
67
|
-
return <StackNavigator />;
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Main Salespanda App Component
|
|
72
|
-
* Can be used as a standalone app or embedded in another React Native app
|
|
73
|
-
*/
|
|
74
|
-
const SalespandaApp: React.FC<SalespandaAppProps> = ({
|
|
75
|
-
navigationRef,
|
|
76
|
-
theme: _customTheme,
|
|
77
|
-
standalone = false,
|
|
78
|
-
onReady,
|
|
79
|
-
wrapWithGestureHandler = true,
|
|
80
|
-
} = {}) => {
|
|
81
|
-
// TODO: Apply custom theme to app (future enhancement)
|
|
82
|
-
// Currently theme is managed through SalespandaConfig
|
|
83
|
-
// _customTheme is reserved for future use
|
|
84
|
-
|
|
85
|
-
// If standalone mode, don't wrap with NavigationContainer
|
|
86
|
-
// (parent app will provide it)
|
|
87
|
-
if (standalone) {
|
|
88
|
-
return (
|
|
89
|
-
<Provider store={store}>
|
|
90
|
-
<AppContent />
|
|
91
|
-
</Provider>
|
|
92
|
-
);
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Navigation content with SafeAreaProvider
|
|
96
|
-
const navTheme = {
|
|
97
|
-
...DefaultTheme,
|
|
98
|
-
colors: {
|
|
99
|
-
...DefaultTheme.colors,
|
|
100
|
-
background: Colors.background,
|
|
101
|
-
primary: Colors.primary,
|
|
102
|
-
card: Colors.white,
|
|
103
|
-
text: Colors.black,
|
|
104
|
-
border: Colors.border,
|
|
105
|
-
},
|
|
106
|
-
};
|
|
107
|
-
|
|
108
|
-
const NavigationContent = (
|
|
109
|
-
<Provider store={store}>
|
|
110
|
-
<SafeAreaProvider initialMetrics={initialWindowMetrics}>
|
|
111
|
-
<NavigationContainer
|
|
112
|
-
ref={navigationRef}
|
|
113
|
-
onReady={onReady}
|
|
114
|
-
theme={navTheme}
|
|
115
|
-
>
|
|
116
|
-
<AppContent />
|
|
117
|
-
</NavigationContainer>
|
|
118
|
-
</SafeAreaProvider>
|
|
119
|
-
</Provider>
|
|
120
|
-
);
|
|
121
|
-
|
|
122
|
-
// Wrap with GestureHandlerRootView only if requested
|
|
123
|
-
// (default is false since most apps already have gesture handler imported)
|
|
124
|
-
if (wrapWithGestureHandler) {
|
|
125
|
-
return (
|
|
126
|
-
<GestureHandlerRootView style={styles.container}>
|
|
127
|
-
{NavigationContent}
|
|
128
|
-
</GestureHandlerRootView>
|
|
129
|
-
);
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
return NavigationContent;
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
export default SalespandaApp;
|
|
136
|
-
|
|
137
|
-
const styles = StyleSheet.create({
|
|
138
|
-
container: {
|
|
139
|
-
flex: 1,
|
|
140
|
-
},
|
|
141
|
-
});
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
// Bottom Tab Icons
|
|
2
|
-
export const homeIcon = require('./bottomtabs/home.png');
|
|
3
|
-
export const homeIconActive = require('./bottomtabs/homeactive.png');
|
|
4
|
-
export const analyticsIcon = require('./bottomtabs/analytics.png');
|
|
5
|
-
export const analyticsIconActive = require('./bottomtabs/analyticsactive.png');
|
|
6
|
-
export const crmIcon = require('./bottomtabs/crm.png');
|
|
7
|
-
export const crmIconActive = require('./bottomtabs/crmactive.png');
|
|
8
|
-
export const diaryIcon = require('./bottomtabs/diary.png');
|
|
9
|
-
export const diaryIconActive = require('./bottomtabs/diaryactive.png');
|
|
10
|
-
export const notificationIcon = require('./bottomtabs/notification.png');
|
|
11
|
-
export const notificationIconActive = require('./bottomtabs/notificationactive.png');
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import type { ImageSourcePropType } from 'react-native';
|
|
2
|
-
|
|
3
|
-
export const homeIcon: ImageSourcePropType = require('./bottomtabs/home.png');
|
|
4
|
-
export const homeIconActive: ImageSourcePropType = require('./bottomtabs/homeactive.png');
|
|
5
|
-
export const analyticsIcon: ImageSourcePropType = require('./bottomtabs/analytics.png');
|
|
6
|
-
export const analyticsIconActive: ImageSourcePropType = require('./bottomtabs/analyticsactive.png');
|
|
7
|
-
export const crmIcon: ImageSourcePropType = require('./bottomtabs/crm.png');
|
|
8
|
-
export const crmIconActive: ImageSourcePropType = require('./bottomtabs/crmactive.png');
|
|
9
|
-
export const diaryIcon: ImageSourcePropType = require('./bottomtabs/diary.png');
|
|
10
|
-
export const diaryIconActive: ImageSourcePropType = require('./bottomtabs/diaryactive.png');
|
|
11
|
-
export const notificationIcon: ImageSourcePropType = require('./bottomtabs/notification.png');
|
|
12
|
-
export const notificationIconActive: ImageSourcePropType = require('./bottomtabs/notificationactive.png');
|
|
13
|
-
|
|
14
|
-
export type IconPair = {
|
|
15
|
-
default: ImageSourcePropType;
|
|
16
|
-
active: ImageSourcePropType;
|
|
17
|
-
};
|
|
18
|
-
|
|
19
|
-
export const bottomTabIcons: Record<string, IconPair> = {
|
|
20
|
-
home: {
|
|
21
|
-
default: homeIcon,
|
|
22
|
-
active: homeIconActive,
|
|
23
|
-
},
|
|
24
|
-
analytics: {
|
|
25
|
-
default: analyticsIcon,
|
|
26
|
-
active: analyticsIconActive,
|
|
27
|
-
},
|
|
28
|
-
crm: {
|
|
29
|
-
default: crmIcon,
|
|
30
|
-
active: crmIconActive,
|
|
31
|
-
},
|
|
32
|
-
diary: {
|
|
33
|
-
default: diaryIcon,
|
|
34
|
-
active: diaryIconActive,
|
|
35
|
-
},
|
|
36
|
-
notification: {
|
|
37
|
-
default: notificationIcon,
|
|
38
|
-
active: notificationIconActive,
|
|
39
|
-
},
|
|
40
|
-
};
|
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
View,
|
|
3
|
-
Text,
|
|
4
|
-
StyleSheet,
|
|
5
|
-
Modal,
|
|
6
|
-
TouchableOpacity,
|
|
7
|
-
TouchableWithoutFeedback,
|
|
8
|
-
} from 'react-native';
|
|
9
|
-
import { scale, verticalScale, moderateScale } from 'react-native-size-matters';
|
|
10
|
-
import { Colors } from '../constants/Colors';
|
|
11
|
-
|
|
12
|
-
interface BottomSheetProps {
|
|
13
|
-
visible: boolean;
|
|
14
|
-
onClose: () => void;
|
|
15
|
-
title: string;
|
|
16
|
-
children: React.ReactNode;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export const BottomSheet: React.FC<BottomSheetProps> = ({
|
|
20
|
-
visible,
|
|
21
|
-
onClose,
|
|
22
|
-
title,
|
|
23
|
-
children,
|
|
24
|
-
}) => {
|
|
25
|
-
return (
|
|
26
|
-
<Modal
|
|
27
|
-
visible={visible}
|
|
28
|
-
transparent
|
|
29
|
-
animationType="slide"
|
|
30
|
-
onRequestClose={onClose}
|
|
31
|
-
>
|
|
32
|
-
<TouchableWithoutFeedback onPress={onClose}>
|
|
33
|
-
<View style={styles.overlay}>
|
|
34
|
-
<TouchableWithoutFeedback>
|
|
35
|
-
<View style={styles.bottomSheet}>
|
|
36
|
-
<View style={styles.header}>
|
|
37
|
-
<Text style={styles.title}>{title}</Text>
|
|
38
|
-
<TouchableOpacity onPress={onClose} style={styles.closeButton}>
|
|
39
|
-
<Text style={styles.closeIcon}>✕</Text>
|
|
40
|
-
</TouchableOpacity>
|
|
41
|
-
</View>
|
|
42
|
-
<View style={styles.content}>{children}</View>
|
|
43
|
-
</View>
|
|
44
|
-
</TouchableWithoutFeedback>
|
|
45
|
-
</View>
|
|
46
|
-
</TouchableWithoutFeedback>
|
|
47
|
-
</Modal>
|
|
48
|
-
);
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
interface BottomSheetOptionProps {
|
|
52
|
-
icon: string;
|
|
53
|
-
label: string;
|
|
54
|
-
onPress: () => void;
|
|
55
|
-
iconColor?: string;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export const BottomSheetOption: React.FC<BottomSheetOptionProps> = ({
|
|
59
|
-
icon,
|
|
60
|
-
label,
|
|
61
|
-
onPress,
|
|
62
|
-
iconColor,
|
|
63
|
-
}) => {
|
|
64
|
-
return (
|
|
65
|
-
<TouchableOpacity style={styles.option} onPress={onPress}>
|
|
66
|
-
<View
|
|
67
|
-
style={[
|
|
68
|
-
styles.iconContainer,
|
|
69
|
-
iconColor && { backgroundColor: iconColor },
|
|
70
|
-
]}
|
|
71
|
-
>
|
|
72
|
-
<Text style={styles.optionIcon}>{icon}</Text>
|
|
73
|
-
</View>
|
|
74
|
-
<Text style={styles.optionLabel}>{label}</Text>
|
|
75
|
-
<Text style={styles.arrow}>›</Text>
|
|
76
|
-
</TouchableOpacity>
|
|
77
|
-
);
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
const styles = StyleSheet.create({
|
|
81
|
-
overlay: {
|
|
82
|
-
flex: 1,
|
|
83
|
-
backgroundColor: 'rgba(0, 0, 0, 0.5)',
|
|
84
|
-
justifyContent: 'flex-end',
|
|
85
|
-
},
|
|
86
|
-
bottomSheet: {
|
|
87
|
-
backgroundColor: Colors.white,
|
|
88
|
-
borderTopLeftRadius: moderateScale(20),
|
|
89
|
-
borderTopRightRadius: moderateScale(20),
|
|
90
|
-
paddingBottom: verticalScale(30),
|
|
91
|
-
},
|
|
92
|
-
header: {
|
|
93
|
-
flexDirection: 'row',
|
|
94
|
-
justifyContent: 'space-between',
|
|
95
|
-
alignItems: 'center',
|
|
96
|
-
padding: scale(20),
|
|
97
|
-
borderBottomWidth: 1,
|
|
98
|
-
borderBottomColor: '#E0E0E0',
|
|
99
|
-
},
|
|
100
|
-
title: {
|
|
101
|
-
fontSize: moderateScale(20),
|
|
102
|
-
fontWeight: '700',
|
|
103
|
-
color: Colors.black,
|
|
104
|
-
},
|
|
105
|
-
closeButton: {
|
|
106
|
-
padding: scale(4),
|
|
107
|
-
},
|
|
108
|
-
closeIcon: {
|
|
109
|
-
fontSize: moderateScale(24),
|
|
110
|
-
color: Colors.black,
|
|
111
|
-
},
|
|
112
|
-
content: {
|
|
113
|
-
padding: scale(16),
|
|
114
|
-
},
|
|
115
|
-
option: {
|
|
116
|
-
flexDirection: 'row',
|
|
117
|
-
alignItems: 'center',
|
|
118
|
-
padding: scale(16),
|
|
119
|
-
backgroundColor: Colors.white,
|
|
120
|
-
borderWidth: 1,
|
|
121
|
-
borderColor: '#E0E0E0',
|
|
122
|
-
borderRadius: moderateScale(12),
|
|
123
|
-
marginBottom: verticalScale(12),
|
|
124
|
-
},
|
|
125
|
-
iconContainer: {
|
|
126
|
-
width: scale(30),
|
|
127
|
-
height: scale(30),
|
|
128
|
-
borderRadius: moderateScale(20),
|
|
129
|
-
justifyContent: 'center',
|
|
130
|
-
alignItems: 'center',
|
|
131
|
-
marginRight: scale(12),
|
|
132
|
-
},
|
|
133
|
-
optionIcon: {
|
|
134
|
-
fontSize: moderateScale(16),
|
|
135
|
-
},
|
|
136
|
-
optionLabel: {
|
|
137
|
-
flex: 1,
|
|
138
|
-
fontSize: moderateScale(12),
|
|
139
|
-
fontWeight: '600',
|
|
140
|
-
color: Colors.black,
|
|
141
|
-
},
|
|
142
|
-
arrow: {
|
|
143
|
-
fontSize: moderateScale(24),
|
|
144
|
-
color: '#999',
|
|
145
|
-
},
|
|
146
|
-
});
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import { BottomSheet, BottomSheetOption } from './BottomSheet';
|
|
2
|
-
|
|
3
|
-
interface ContactViaModalProps {
|
|
4
|
-
visible: boolean;
|
|
5
|
-
onClose: () => void;
|
|
6
|
-
onCall?: () => void;
|
|
7
|
-
onWhatsapp?: () => void;
|
|
8
|
-
onEmail?: () => void;
|
|
9
|
-
onSMS?: () => void;
|
|
10
|
-
onAddTask?: () => void;
|
|
11
|
-
onAddNote?: () => void;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export const ContactViaModal: React.FC<ContactViaModalProps> = ({
|
|
15
|
-
visible,
|
|
16
|
-
onClose,
|
|
17
|
-
onCall,
|
|
18
|
-
onWhatsapp,
|
|
19
|
-
onEmail,
|
|
20
|
-
onSMS,
|
|
21
|
-
onAddTask,
|
|
22
|
-
onAddNote,
|
|
23
|
-
}) => {
|
|
24
|
-
return (
|
|
25
|
-
<BottomSheet visible={visible} onClose={onClose} title="Contact Via">
|
|
26
|
-
<BottomSheetOption
|
|
27
|
-
icon="📞"
|
|
28
|
-
label="Call"
|
|
29
|
-
iconColor="#FF6B6B"
|
|
30
|
-
onPress={() => {
|
|
31
|
-
onClose();
|
|
32
|
-
onCall?.();
|
|
33
|
-
}}
|
|
34
|
-
/>
|
|
35
|
-
<BottomSheetOption
|
|
36
|
-
icon="💬"
|
|
37
|
-
label="Whatsapp"
|
|
38
|
-
iconColor="#25D366"
|
|
39
|
-
onPress={() => {
|
|
40
|
-
onClose();
|
|
41
|
-
onWhatsapp?.();
|
|
42
|
-
}}
|
|
43
|
-
/>
|
|
44
|
-
<BottomSheetOption
|
|
45
|
-
icon="✉️"
|
|
46
|
-
label="E-mail"
|
|
47
|
-
iconColor="#9B59B6"
|
|
48
|
-
onPress={() => {
|
|
49
|
-
onClose();
|
|
50
|
-
onEmail?.();
|
|
51
|
-
}}
|
|
52
|
-
/>
|
|
53
|
-
<BottomSheetOption
|
|
54
|
-
icon="💬"
|
|
55
|
-
label="SMS"
|
|
56
|
-
iconColor="#3498DB"
|
|
57
|
-
onPress={() => {
|
|
58
|
-
onClose();
|
|
59
|
-
onSMS?.();
|
|
60
|
-
}}
|
|
61
|
-
/>
|
|
62
|
-
<BottomSheetOption
|
|
63
|
-
icon="📋"
|
|
64
|
-
label="Add Task"
|
|
65
|
-
onPress={() => {
|
|
66
|
-
onClose();
|
|
67
|
-
onAddTask?.();
|
|
68
|
-
}}
|
|
69
|
-
/>
|
|
70
|
-
<BottomSheetOption
|
|
71
|
-
icon="📝"
|
|
72
|
-
label="Add Note"
|
|
73
|
-
onPress={() => {
|
|
74
|
-
onClose();
|
|
75
|
-
onAddNote?.();
|
|
76
|
-
}}
|
|
77
|
-
/>
|
|
78
|
-
</BottomSheet>
|
|
79
|
-
);
|
|
80
|
-
};
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
|
-
import { View, Text, ActivityIndicator, StyleSheet } from 'react-native';
|
|
3
|
-
import type { ViewStyle } from 'react-native';
|
|
4
|
-
import { Colors } from '../constants/Colors';
|
|
5
|
-
import { verticalScale, moderateScale, scale } from 'react-native-size-matters';
|
|
6
|
-
|
|
7
|
-
type LoaderProps = {
|
|
8
|
-
message?: string;
|
|
9
|
-
overlay?: boolean;
|
|
10
|
-
color?: string;
|
|
11
|
-
style?: ViewStyle;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
const Loader: React.FC<LoaderProps> = ({
|
|
15
|
-
message = 'Loading...',
|
|
16
|
-
overlay = false,
|
|
17
|
-
color = Colors.primary,
|
|
18
|
-
style,
|
|
19
|
-
}) => {
|
|
20
|
-
return (
|
|
21
|
-
<View style={[styles.container, overlay ? styles.overlay : null, style]}>
|
|
22
|
-
<ActivityIndicator size="large" color={color} />
|
|
23
|
-
{message ? <Text style={styles.text}>{message}</Text> : null}
|
|
24
|
-
</View>
|
|
25
|
-
);
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
export default Loader;
|
|
29
|
-
|
|
30
|
-
const styles = StyleSheet.create({
|
|
31
|
-
container: {
|
|
32
|
-
paddingVertical: verticalScale(16),
|
|
33
|
-
paddingHorizontal: scale(12),
|
|
34
|
-
alignItems: 'center',
|
|
35
|
-
justifyContent: 'center',
|
|
36
|
-
backgroundColor: Colors.white,
|
|
37
|
-
},
|
|
38
|
-
overlay: {
|
|
39
|
-
...StyleSheet.absoluteFillObject,
|
|
40
|
-
zIndex: 10,
|
|
41
|
-
backgroundColor: Colors.white50,
|
|
42
|
-
},
|
|
43
|
-
text: {
|
|
44
|
-
marginTop: verticalScale(8),
|
|
45
|
-
fontSize: moderateScale(12),
|
|
46
|
-
color: Colors.black,
|
|
47
|
-
},
|
|
48
|
-
});
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
|
|
2
|
-
import { scale, verticalScale, moderateScale } from 'react-native-size-matters';
|
|
3
|
-
import { Colors } from '../constants/Colors';
|
|
4
|
-
|
|
5
|
-
interface ScreenHeaderProps {
|
|
6
|
-
title?: string;
|
|
7
|
-
onBackPress: () => void;
|
|
8
|
-
showCrossOnLeft?: boolean; // If true, shows cross icon instead of back arrow on left
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export const ScreenHeader: React.FC<ScreenHeaderProps> = ({
|
|
12
|
-
title,
|
|
13
|
-
onBackPress,
|
|
14
|
-
showCrossOnLeft = false,
|
|
15
|
-
}) => {
|
|
16
|
-
return (
|
|
17
|
-
<View style={styles.header}>
|
|
18
|
-
<TouchableOpacity onPress={onBackPress} style={styles.iconButton}>
|
|
19
|
-
<Text style={styles.icon}>{showCrossOnLeft ? '✕' : '←'}</Text>
|
|
20
|
-
</TouchableOpacity>
|
|
21
|
-
{title && <Text style={styles.title}>{title}</Text>}
|
|
22
|
-
<TouchableOpacity onPress={onBackPress} style={styles.iconButton}>
|
|
23
|
-
<Text style={styles.icon}>✕</Text>
|
|
24
|
-
</TouchableOpacity>
|
|
25
|
-
</View>
|
|
26
|
-
);
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const styles = StyleSheet.create({
|
|
30
|
-
header: {
|
|
31
|
-
flexDirection: 'row',
|
|
32
|
-
alignItems: 'center',
|
|
33
|
-
justifyContent: 'space-between',
|
|
34
|
-
paddingHorizontal: scale(16),
|
|
35
|
-
paddingVertical: verticalScale(12),
|
|
36
|
-
backgroundColor: Colors.white,
|
|
37
|
-
borderBottomWidth: 1,
|
|
38
|
-
borderBottomColor: '#e0e0e0',
|
|
39
|
-
},
|
|
40
|
-
iconButton: {
|
|
41
|
-
width: scale(40),
|
|
42
|
-
height: scale(40),
|
|
43
|
-
justifyContent: 'center',
|
|
44
|
-
alignItems: 'center',
|
|
45
|
-
},
|
|
46
|
-
icon: {
|
|
47
|
-
fontSize: moderateScale(24),
|
|
48
|
-
color: Colors.black,
|
|
49
|
-
},
|
|
50
|
-
title: {
|
|
51
|
-
fontSize: moderateScale(18),
|
|
52
|
-
fontWeight: '600',
|
|
53
|
-
color: Colors.black,
|
|
54
|
-
flex: 1,
|
|
55
|
-
textAlign: 'center',
|
|
56
|
-
},
|
|
57
|
-
});
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import { View, Text, StyleSheet, TextInput } from 'react-native';
|
|
2
|
-
import { scale, verticalScale, moderateScale } from 'react-native-size-matters';
|
|
3
|
-
import { Colors } from '../constants/Colors';
|
|
4
|
-
|
|
5
|
-
interface SearchBarProps {
|
|
6
|
-
placeholder?: string;
|
|
7
|
-
onChangeText?: (text: string) => void;
|
|
8
|
-
value?: string;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export const SearchBar: React.FC<SearchBarProps> = ({
|
|
12
|
-
placeholder = 'Search by name',
|
|
13
|
-
onChangeText,
|
|
14
|
-
value,
|
|
15
|
-
}) => {
|
|
16
|
-
return (
|
|
17
|
-
<View style={styles.searchContainer}>
|
|
18
|
-
<View style={styles.searchBar}>
|
|
19
|
-
<Text style={styles.searchIcon}>🔍</Text>
|
|
20
|
-
<TextInput
|
|
21
|
-
style={styles.searchInput}
|
|
22
|
-
placeholder={placeholder}
|
|
23
|
-
placeholderTextColor="#ccc"
|
|
24
|
-
onChangeText={onChangeText}
|
|
25
|
-
value={value}
|
|
26
|
-
/>
|
|
27
|
-
</View>
|
|
28
|
-
</View>
|
|
29
|
-
);
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
const styles = StyleSheet.create({
|
|
33
|
-
searchContainer: {
|
|
34
|
-
backgroundColor: Colors.white,
|
|
35
|
-
paddingHorizontal: scale(16),
|
|
36
|
-
paddingVertical: verticalScale(12),
|
|
37
|
-
},
|
|
38
|
-
searchBar: {
|
|
39
|
-
flexDirection: 'row',
|
|
40
|
-
alignItems: 'center',
|
|
41
|
-
backgroundColor: Colors.white,
|
|
42
|
-
borderWidth: 1,
|
|
43
|
-
borderColor: '#E0E0E0',
|
|
44
|
-
borderRadius: moderateScale(8),
|
|
45
|
-
paddingHorizontal: scale(12),
|
|
46
|
-
paddingVertical: verticalScale(8),
|
|
47
|
-
},
|
|
48
|
-
searchIcon: {
|
|
49
|
-
fontSize: moderateScale(18),
|
|
50
|
-
marginRight: scale(8),
|
|
51
|
-
color: '#999',
|
|
52
|
-
},
|
|
53
|
-
searchInput: {
|
|
54
|
-
flex: 1,
|
|
55
|
-
fontSize: moderateScale(16),
|
|
56
|
-
color: Colors.black,
|
|
57
|
-
padding: 0,
|
|
58
|
-
},
|
|
59
|
-
});
|