react-native-srschat 0.1.41 → 0.1.43

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.
@@ -1,23 +1,39 @@
1
- import React, { useState, useContext } from "react";
2
- import { View, Text, TextInput, TouchableOpacity, ActivityIndicator, Alert, StyleSheet, ScrollView } from "react-native";
1
+ import React, { useState, useContext, useRef } from "react";
2
+ import {
3
+ View,
4
+ Text,
5
+ TextInput,
6
+ TouchableOpacity,
7
+ ActivityIndicator,
8
+ StyleSheet,
9
+ Platform,
10
+ findNodeHandle
11
+ } from "react-native";
3
12
  import Ionicons from "react-native-vector-icons/Ionicons";
4
13
  import axios from "axios";
5
14
  import { AppContext } from "../contexts/AppContext";
6
15
  import { Header } from "./header";
16
+ import { KeyboardAwareScrollView } from "react-native-keyboard-aware-scroll-view";
7
17
 
8
18
  export const EmailForm = ({ panHandlers }) => {
9
19
  const { data, BASE_URL, setShowModal, messages, formatChatHistory, conversationStartTime } = useContext(AppContext);
10
20
  const [subject, setSubject] = useState("");
11
21
  const [message, setMessage] = useState("");
12
22
  const [userEmail, setUserEmail] = useState("");
13
- const [branchEmail, setBranchEmail] = useState(data.branch_email || "");
23
+ const [branchEmail, setBranchEmail] = useState((data?.branch_email) || "");
14
24
  const [isLoading, setIsLoading] = useState(false);
15
25
  const [error, setError] = useState("");
16
26
  const [success, setSuccess] = useState(false);
17
27
  const [isComposing, setIsComposing] = useState(false);
18
28
 
29
+ // Refs for the scroll view and inputs
30
+ const scrollViewRef = useRef(null);
31
+ const subjectInputRef = useRef(null);
32
+ const messageInputRef = useRef(null);
33
+ const emailInputRef = useRef(null);
34
+
19
35
  const handleComposeEmail = async () => {
20
- setIsComposing(true);
36
+ setIsComposing(true);
21
37
  setError("");
22
38
 
23
39
  try {
@@ -25,7 +41,7 @@ export const EmailForm = ({ panHandlers }) => {
25
41
  const payload = {
26
42
  chat_history: chatHistory,
27
43
  conversation_start_time: conversationStartTime,
28
- customer_name: '',
44
+ customer_name: "",
29
45
  branch_email: branchEmail,
30
46
  };
31
47
 
@@ -60,7 +76,7 @@ export const EmailForm = ({ panHandlers }) => {
60
76
  message,
61
77
  chat_history: chatHistory,
62
78
  conversation_start_time: conversationStartTime,
63
- customer_name: '',
79
+ customer_name: "",
64
80
  branch_email: branchEmail,
65
81
  });
66
82
 
@@ -76,50 +92,92 @@ export const EmailForm = ({ panHandlers }) => {
76
92
  }
77
93
  };
78
94
 
79
- return (
80
- <View style={styles.container}>
81
- <View>
82
- <Header />
83
- </View>
95
+ return (
96
+ <View style={styles.container}>
97
+ <Header />
98
+ <KeyboardAwareScrollView
99
+ ref={scrollViewRef}
100
+ style={styles.content}
101
+ contentContainerStyle={{ flexGrow: 1, paddingBottom: 50 }}
102
+ keyboardShouldPersistTaps="handled"
103
+ showsVerticalScrollIndicator={true}
104
+ enableOnAndroid={true}
105
+ extraScrollHeight={40}
106
+ keyboardDismissMode="interactive"
107
+ bounces={false}
108
+ >
84
109
  <View style={styles.topBar}>
85
- <TouchableOpacity onPress={() => setShowModal("ChatWindow")} style={styles.backButton}>
110
+ <TouchableOpacity onPress={() => setShowModal("ChatWindow")} style={styles.backButton}>
86
111
  <Ionicons name="arrow-back" size={20} color="#000" />
87
- </TouchableOpacity>
88
- <Text style={styles.topBarTitle}>Contact Us</Text>
112
+ </TouchableOpacity>
113
+ <Text style={styles.topBarTitle}>Contact Us</Text>
89
114
  </View>
90
- <ScrollView
91
- style={styles.content}
92
- contentContainerStyle={{ paddingBottom: 100 }} // Add padding to bottom
93
- keyboardShouldPersistTaps="handled"
94
- showsVerticalScrollIndicator={true}
95
- >
96
-
97
- <Text style={styles.infoText}>
98
- Our AI assistant can help draft a professional email based on your chat conversation. The email will capture your main points and maintain a conversational tone. You can review and modify before sending.
99
- </Text>
100
-
101
- <TouchableOpacity style={styles.composeButton} onPress={handleComposeEmail} disabled={isComposing}>
102
- {isComposing ? (
103
- <ActivityIndicator size="small" color="#FFFFFF" />
104
- ) : (
105
- <Text style={styles.buttonText}>Draft My Email</Text>
106
- )}
107
- </TouchableOpacity>
108
-
109
- <TextInput style={styles.input} value={branchEmail} editable={false} placeholder="Branch Email" />
110
- <TextInput style={styles.input} value={userEmail} onChangeText={setUserEmail} placeholder="Your Email" />
111
- <TextInput style={styles.input} value={subject} onChangeText={setSubject} placeholder="Subject" />
112
- <TextInput style={styles.textArea} value={message} onChangeText={setMessage} placeholder="Message" multiline />
113
-
114
- {error ? <Text style={styles.errorText}>{error}</Text> : null}
115
- {success ? <Text style={styles.successText}>Email sent successfully!</Text> : null}
116
-
117
- <TouchableOpacity style={styles.sendButton} onPress={handleSubmit} disabled={isLoading}>
118
- {isLoading ? <ActivityIndicator size="small" color="#FFFFFF" /> : <Text style={styles.buttonText}>Send Email</Text>}
119
- </TouchableOpacity>
120
- </ScrollView>
121
- </View>
122
- );
115
+
116
+ <Text style={styles.infoText}>
117
+ Our AI assistant can help draft a professional email based on your chat conversation. The email will capture your main points and maintain a conversational tone. You can review and modify before sending.
118
+ </Text>
119
+
120
+ <TouchableOpacity style={styles.composeButton} onPress={handleComposeEmail} disabled={isComposing}>
121
+ {isComposing ? (
122
+ <ActivityIndicator size="small" color="#FFFFFF" />
123
+ ) : (
124
+ <Text style={styles.buttonText}>Draft My Email</Text>
125
+ )}
126
+ </TouchableOpacity>
127
+
128
+ <TextInput
129
+ style={styles.input}
130
+ value={branchEmail}
131
+ editable={false}
132
+ placeholder="Branch Email"
133
+ />
134
+ <TextInput
135
+ ref={emailInputRef}
136
+ style={styles.input}
137
+ value={userEmail}
138
+ onChangeText={setUserEmail}
139
+ placeholder="Your Email"
140
+ onFocus={() =>
141
+ scrollViewRef.current?.scrollToFocusedInput(
142
+ findNodeHandle(emailInputRef.current)
143
+ )
144
+ }
145
+ />
146
+ <TextInput
147
+ ref={subjectInputRef}
148
+ style={styles.input}
149
+ value={subject}
150
+ onChangeText={setSubject}
151
+ placeholder="Subject"
152
+ onFocus={() =>
153
+ scrollViewRef.current?.scrollToFocusedInput(
154
+ findNodeHandle(subjectInputRef.current)
155
+ )
156
+ }
157
+ />
158
+ <TextInput
159
+ ref={messageInputRef}
160
+ style={styles.textArea}
161
+ value={message}
162
+ onChangeText={setMessage}
163
+ placeholder="Message"
164
+ multiline
165
+ onFocus={() =>
166
+ scrollViewRef.current?.scrollToFocusedInput(
167
+ findNodeHandle(messageInputRef.current)
168
+ )
169
+ }
170
+ />
171
+
172
+ {error ? <Text style={styles.errorText}>{error}</Text> : null}
173
+ {success ? <Text style={styles.successText}>Email sent successfully!</Text> : null}
174
+
175
+ <TouchableOpacity style={styles.sendButton} onPress={handleSubmit} disabled={isLoading}>
176
+ {isLoading ? <ActivityIndicator size="small" color="#FFFFFF" /> : <Text style={styles.buttonText}>Send Email</Text>}
177
+ </TouchableOpacity>
178
+ </KeyboardAwareScrollView>
179
+ </View>
180
+ );
123
181
  };
124
182
 
125
183
  const styles = StyleSheet.create({
@@ -129,24 +187,22 @@ const styles = StyleSheet.create({
129
187
  content: {
130
188
  padding: 20,
131
189
  paddingTop: 5,
132
- paddingBottom: 40,
133
- marginBottom: 40
190
+ flex: 1,
134
191
  },
135
192
  topBar: {
136
- flexDirection: 'row',
137
- alignItems: 'center',
193
+ flexDirection: "row",
194
+ alignItems: "center",
138
195
  paddingVertical: 10,
139
- paddingHorizontal: 16,
140
- marginTop: 10
196
+ marginTop: 10,
141
197
  },
142
198
  backButton: {
143
199
  padding: 8,
144
200
  borderRadius: 20,
145
- backgroundColor: '#FFF',
201
+ backgroundColor: "#FFF",
146
202
  },
147
203
  topBarTitle: {
148
204
  fontSize: 18,
149
- fontWeight: 'medium',
205
+ fontWeight: "500",
150
206
  marginLeft: 12,
151
207
  },
152
208
  infoText: {
@@ -208,3 +264,5 @@ const styles = StyleSheet.create({
208
264
  marginTop: 10,
209
265
  },
210
266
  });
267
+
268
+ export default EmailForm;
@@ -2,7 +2,6 @@ import React, { useContext } from 'react';
2
2
  import { View, Text, TouchableOpacity, StyleSheet, Image } from 'react-native';
3
3
  import { AppContext } from '../contexts/AppContext';
4
4
  import Ionicons from 'react-native-vector-icons/Ionicons';
5
- import { SvgCssUri } from 'react-native-svg/css';
6
5
  import CloudinaryImage from '../utils/cloudinary';
7
6
  // import { PoseidonLogo } from './PoseidonLogo';
8
7
 
@@ -24,7 +24,8 @@ export const ProductCard = ({ prod, onFocusQuantityInput }) => {
24
24
  const grossPrice = uomInfo.gross_price || 0;
25
25
  const netPrice = uomInfo.net_price || 0;
26
26
  const isOnSale = uomInfo.is_on_sale || false;
27
- const discounts = uomInfo.discounts || [];
27
+ const discounts = Array.isArray(uomInfo.discounts) ? uomInfo.discounts : [];
28
+
28
29
 
29
30
 
30
31
  const maxQuantity = Math.floor(prod.inventory_info?.info_by_uom?.EA?.quantity_available || 0);
@@ -201,7 +202,6 @@ export const ProductCard = ({ prod, onFocusQuantityInput }) => {
201
202
  disabled={!valid}
202
203
  >
203
204
  <Text style={styles.dropdownButtonText}>{selectedUom}</Text>
204
- <Ionicons name="close" size={26} color="rgba(0, 0, 0, 0.6)" />
205
205
  </TouchableOpacity>
206
206
  </View>
207
207
  ) : null}
@@ -1,14 +1,11 @@
1
1
  // Welcome.js
2
2
  import React, { useContext } from 'react';
3
- import { View, Text, Image, TouchableOpacity, ScrollView, StyleSheet } from 'react-native';
3
+ import { View, Text, TouchableOpacity, ScrollView, StyleSheet } from 'react-native';
4
4
  import Ionicons from 'react-native-vector-icons/Ionicons';
5
5
  import { AppContext } from '../contexts/AppContext';
6
6
  import { WelcomeInput } from '../components/welcomeInput';
7
7
  import ButtonComponent from '../components/welcomeButton';
8
- import { Testing } from '../components/testing';
9
- import { SvgCssUri } from 'react-native-svg/css';
10
8
  import CloudinaryImage from '../utils/cloudinary';
11
- // import { PoseidonLogo } from '../components/PoseidonLogo';
12
9
 
13
10
  export const Welcome = ({ panHandlers }) => {
14
11
  const { setShowModal, uiConfig, onProductCardClick, onAddToCartClick } = useContext(AppContext);
@@ -20,30 +17,25 @@ export const Welcome = ({ panHandlers }) => {
20
17
  setShowModal("Icon");
21
18
  }
22
19
 
23
- // Reset toggleChat in the parent component
24
20
  if (typeof uiConfig.setToggleChat === 'function') {
25
21
  uiConfig.setToggleChat(false);
26
22
  }
27
23
  };
28
24
 
29
25
  return (
30
- <View contentContainerStyle={styles.container}>
26
+ <View style={styles.container}>
31
27
  <View style={styles.parentContainer}>
32
-
33
28
  {/* Top section */}
34
29
  <View style={styles.topContainer}>
35
30
  <View style={styles.topHeader}>
36
- {/* <PoseidonLogo width={150} height={35} color="white" /> */}
37
- {/* <SvgCssUri
38
- uri="https://media.heritageplus.com/image/upload/v1743632330/MobileApp/posiden.svg"
39
- width={150}
40
- height={35}
41
- /> */}
42
- <CloudinaryImage
43
- cldImg="posiden"
44
- imageStyle={{ width: 150, height: 35 }}
45
- />
46
- <TouchableOpacity onPress={() => handleClick()} style={styles.collapseButton}>
31
+ {/* Logo container with absolute positioning */}
32
+ <View style={styles.logoContainer}>
33
+ <CloudinaryImage
34
+ cldImg="posiden"
35
+ imageStyle={{ width: 150, height: 35 }}
36
+ />
37
+ </View>
38
+ <TouchableOpacity onPress={handleClick} style={styles.collapseButton}>
47
39
  <Ionicons name="close" size={26} color="white" />
48
40
  </TouchableOpacity>
49
41
  </View>
@@ -51,8 +43,7 @@ export const Welcome = ({ panHandlers }) => {
51
43
  <View style={styles.blueContainer}>
52
44
  <Text style={styles.welcomeHeader}>Hi 👋</Text>
53
45
  <Text style={styles.welcomeBody2}>
54
- I'm Poseidon, your Heritage Pool+ AI Agent. I can help you during your online
55
- visit with Product and Account information.
46
+ I'm Poseidon, your Heritage Pool+ AI Agent. I can help you during your online visit with Product and Account information.
56
47
  </Text>
57
48
  <WelcomeInput />
58
49
  <Text style={styles.textBeta}>Beta version. Poseidon is learning!</Text>
@@ -76,7 +67,7 @@ const styles = StyleSheet.create({
76
67
  parentContainer: {
77
68
  flexGrow: 1,
78
69
  backgroundColor: '#004687',
79
- paddingTop: 60
70
+ paddingTop: 60,
80
71
  },
81
72
  topContainer: {
82
73
  backgroundColor: '#004687',
@@ -84,14 +75,19 @@ const styles = StyleSheet.create({
84
75
  },
85
76
  topHeader: {
86
77
  flexDirection: 'row',
87
- justifyContent: 'flex-end',
88
78
  alignItems: 'center',
89
79
  paddingHorizontal: 15,
90
80
  paddingTop: 10,
81
+ justifyContent: 'flex-end',
82
+ position: 'relative',
91
83
  },
92
- logo: {
93
- width: 120,
94
- height: 50,
84
+ logoContainer: {
85
+ position: 'absolute',
86
+ left: 15,
87
+ top: 10,
88
+ // left: '50%',
89
+ // transform: [{ translateX: -65 }],
90
+ // top: 10,
95
91
  },
96
92
  collapseButton: {
97
93
  paddingHorizontal: 15,
@@ -122,12 +118,12 @@ const styles = StyleSheet.create({
122
118
  fontSize: 11,
123
119
  color: '#f6f6f6',
124
120
  fontWeight: '400',
125
- marginTop: 5
121
+ marginTop: 5,
126
122
  },
127
123
  bottomContainer: {
128
124
  paddingHorizontal: 25,
129
125
  backgroundColor: "#f6f6f6",
130
- paddingTop: 30
126
+ paddingTop: 30,
131
127
  },
132
128
  welcomeBody: {
133
129
  fontSize: 13,
@@ -138,3 +134,4 @@ const styles = StyleSheet.create({
138
134
  },
139
135
  });
140
136
 
137
+ export default Welcome;