From 69f1ee64fb9455c33289fd30628cab8195385f8a Mon Sep 17 00:00:00 2001 From: Manu Date: Fri, 22 May 2026 14:47:03 +0530 Subject: [PATCH] update till 22/05/2026 update till 22/05/2026 --- src/config/env.js | 2 +- src/navigation/AppNav.js | 2 + src/screens/AddOpportunityScreen.js | 10 +- src/screens/CallLogsScreen.js | 2 +- src/screens/ExpenseScreen.js | 144 +++++++++++++++++++++++++++- src/screens/FeedbackScreen.js | 140 +++++++++++++++++++++++++++ src/screens/LogActivityScreen.js | 16 +++- src/screens/PipelineScreen.js | 7 +- src/screens/TasksScreen.js | 35 +++++-- 9 files changed, 332 insertions(+), 26 deletions(-) create mode 100644 src/screens/FeedbackScreen.js diff --git a/src/config/env.js b/src/config/env.js index 97ac92d..8ba1ad8 100644 --- a/src/config/env.js +++ b/src/config/env.js @@ -1,7 +1,7 @@ // Environment Configuration const ENV = { dev: { - API_URL: 'http://192.168.29.100:3000', // Local Dev IP + API_URL: 'http://192.168.65.3:3000', // Local Dev IP }, prod: { API_URL: 'https://crmapi.ignosimoney.in', // Change this to your public IP/Domain diff --git a/src/navigation/AppNav.js b/src/navigation/AppNav.js index 7769427..0cc7dc9 100644 --- a/src/navigation/AppNav.js +++ b/src/navigation/AppNav.js @@ -24,6 +24,7 @@ import MyTargetScreen from '../screens/MyTargetScreen'; import TasksScreen from '../screens/TasksScreen'; import CallLogsScreen from '../screens/CallLogsScreen'; import ChangePasswordScreen from '../screens/ChangePasswordScreen'; +import FeedbackScreen from '../screens/FeedbackScreen'; const Stack = createNativeStackNavigator(); const Tab = createBottomTabNavigator(); @@ -84,6 +85,7 @@ const AppNav = () => { + ) : ( diff --git a/src/screens/AddOpportunityScreen.js b/src/screens/AddOpportunityScreen.js index 1b2f169..95e8cd7 100644 --- a/src/screens/AddOpportunityScreen.js +++ b/src/screens/AddOpportunityScreen.js @@ -10,10 +10,10 @@ import { AuthContext } from '../context/AuthContext'; import Colors from '../constants/Colors'; const STAGES = [ - { id: 'NEW', label: 'New', color: '#6366f1' }, + { id: 'LEAD', label: 'Lead', color: '#6366f1' }, { id: 'QUALIFIED', label: 'Qualified', color: '#3b82f6' }, - { id: 'PROPOSITION', label: 'Proposition', color: '#f59e0b' }, - { id: 'WON', label: 'Won', color: '#10b981' }, + { id: 'POTENTIAL', label: 'Potential', color: '#f59e0b' }, + { id: 'SALES', label: 'Sales', color: '#10b981' }, { id: 'LOST', label: 'Lost', color: '#ef4444' }, ]; @@ -37,7 +37,7 @@ const AddOpportunityScreen = ({ navigation, route }) => { const [form, setForm] = useState({ title: '', value: '', - stage: 'NEW', + stage: 'LEAD', expectedClosingDate: '', notes: '', }); @@ -102,7 +102,7 @@ const AddOpportunityScreen = ({ navigation, route }) => { notes: form.notes || null, }); Alert.alert('✅ Deal Created!', `"${form.title}" has been added to your pipeline.`, [ - { text: 'Add Another', onPress: () => { setForm({ title: '', value: '', stage: 'NEW', expectedClosingDate: '', notes: '' }); setSelectedClient(null); } }, + { text: 'Add Another', onPress: () => { setForm({ title: '', value: '', stage: 'LEAD', expectedClosingDate: '', notes: '' }); setSelectedClient(null); } }, { text: 'View Pipeline', onPress: () => navigation.navigate('Pipeline') }, ]); } catch (e) { diff --git a/src/screens/CallLogsScreen.js b/src/screens/CallLogsScreen.js index 21f43f4..59dba7a 100644 --- a/src/screens/CallLogsScreen.js +++ b/src/screens/CallLogsScreen.js @@ -72,7 +72,7 @@ const CallLogsScreen = ({ navigation }) => { ); const STATUS_MAP = { - QUALITY: { label: 'Quality Lead', color: '#16a34a', bg: '#dcfce7' }, + QUALIFIED: { label: 'Qualified Lead', color: '#16a34a', bg: '#dcfce7' }, POTENTIAL: { label: 'Potential', color: '#eab308', bg: '#fef9c3' }, DEMO: { label: 'Demo', color: '#a855f7', bg: '#f3e8ff' }, SALES: { label: 'Sales', color: '#0ea5e9', bg: '#e0f2fe' }, diff --git a/src/screens/ExpenseScreen.js b/src/screens/ExpenseScreen.js index d2fb759..dd0d487 100644 --- a/src/screens/ExpenseScreen.js +++ b/src/screens/ExpenseScreen.js @@ -1,8 +1,10 @@ import React, { useState, useContext, useEffect } from 'react'; -import { View, Text, TextInput, Button, StyleSheet, Alert, ScrollView } from 'react-native'; +import { View, Text, TextInput, Button, StyleSheet, Alert, ScrollView, TouchableOpacity, ActivityIndicator, Image, Platform } from 'react-native'; +import { pick } from '@react-native-documents/picker'; import api from '../services/api'; import { AuthContext } from '../context/AuthContext'; import Colors from '../constants/Colors'; +import { Camera, Image as ImageIcon, X } from 'lucide-react-native'; const ExpenseScreen = ({ navigation }) => { const { userInfo } = useContext(AuthContext); @@ -11,6 +13,8 @@ const ExpenseScreen = ({ navigation }) => { const [loading, setLoading] = useState(false); const [expenses, setExpenses] = useState([]); const [fetching, setFetching] = useState(true); + const [selectedImage, setSelectedImage] = useState(null); + const [uploading, setUploading] = useState(false); useEffect(() => { fetchExpenses(); @@ -28,6 +32,40 @@ const ExpenseScreen = ({ navigation }) => { } }; + const handlePickImage = async () => { + try { + const results = await pick({ + multiple: false, + }); + if (results && results.length > 0) { + setSelectedImage(results[0]); + } + } catch (err) { + console.error(err); + } + }; + + const uploadImage = async () => { + if (!selectedImage) return null; + + const formData = new FormData(); + formData.append('file', { + uri: Platform.OS === 'ios' ? selectedImage.uri.replace('file://', '') : selectedImage.uri, + type: selectedImage.type || 'image/jpeg', + name: selectedImage.name || 'bill.jpg', + }); + + try { + const response = await api.post('/upload', formData, { + headers: { 'Content-Type': 'multipart/form-data' }, + }); + return response.data.url; + } catch (error) { + console.error('Upload failed', error); + throw new Error('Failed to upload bill image'); + } + }; + const handleSubmit = async () => { if (!amount || !description) { Alert.alert("Error", "Amount and Description are required"); @@ -42,21 +80,31 @@ const ExpenseScreen = ({ navigation }) => { setLoading(true); try { + let imageUrl = null; + if (selectedImage) { + setUploading(true); + imageUrl = await uploadImage(); + setUploading(false); + } + await api.post('/expenses', { userId: userInfo.id, amount: parsedAmount, description, + imageUrl, status: 'PENDING' }); Alert.alert("Success", "Expense Submitted Successfully"); setAmount(''); setDescription(''); + setSelectedImage(null); fetchExpenses(); } catch (error) { console.error(error); - Alert.alert("Error", "Failed to submit expense"); + Alert.alert("Error", error.message || "Failed to submit expense"); } finally { setLoading(false); + setUploading(false); } }; @@ -84,7 +132,38 @@ const ExpenseScreen = ({ navigation }) => { placeholder="Lunch, Travel, etc." /> -