diff --git a/src/config/env.js b/src/config/env.js
index 8d625f2..c98a9fb 100644
--- a/src/config/env.js
+++ b/src/config/env.js
@@ -9,4 +9,4 @@ const ENV = {
};
// Set to 'prod' when deploying
-export default ENV.dev;
+export default ENV.prod;
diff --git a/src/screens/AttendanceScreen.js b/src/screens/AttendanceScreen.js
index fbd3d86..dce90cf 100644
--- a/src/screens/AttendanceScreen.js
+++ b/src/screens/AttendanceScreen.js
@@ -60,7 +60,6 @@ const AttendanceScreen = () => {
);
// Periodic Location Tracking when Checked In
- /*
useEffect(() => {
let interval;
if (currentSession && !currentSession.checkOutTime) {
@@ -72,12 +71,13 @@ const AttendanceScreen = () => {
lat: coords.latitude,
lng: coords.longitude
});
+ console.log("Periodic route location sent: ", coords.latitude, coords.longitude);
} catch (error) {
console.error("Periodic tracking failed", error);
}
};
- sendLocation(); // Initial
- interval = setInterval(sendLocation, 5 * 60 * 1000); // 5 mins
+ sendLocation(); // Initial call
+ interval = setInterval(sendLocation, 60 * 1000); // Poll location every 60 seconds (1 minute) to map detailed route map
}
return () => {
if (interval) {
@@ -86,7 +86,6 @@ const AttendanceScreen = () => {
}
};
}, [currentSession]);
- */
// Request Location Permission
const requestLocationPermission = async () => {
diff --git a/src/screens/HomeScreen.js b/src/screens/HomeScreen.js
index 665e53d..ab2f963 100644
--- a/src/screens/HomeScreen.js
+++ b/src/screens/HomeScreen.js
@@ -5,23 +5,44 @@ import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { useFocusEffect } from '@react-navigation/native';
import Colors from '../constants/Colors';
import api from '../services/api';
-import { LogOut, Bell, User } from 'lucide-react-native';
+import {
+ LogOut,
+ Bell,
+ User,
+ Target,
+ TrendingUp,
+ Calendar,
+ Briefcase,
+ PhoneCall,
+ FileText,
+ CheckCircle2,
+ AlertTriangle,
+ Zap,
+ MessageSquare,
+ Mail,
+ Plus,
+ ChevronRight,
+ Award
+} from 'lucide-react-native';
const { width } = Dimensions.get('window');
const HomeScreen = ({ navigation }) => {
const { userInfo, logout } = useContext(AuthContext);
const insets = useSafeAreaInsets();
+
+ const [activeTab, setActiveTab] = useState('target'); // 'target' | 'achieved' | 'today' | 'opportunities'
+ const [unreadCount, setUnreadCount] = useState(0);
+
const [stats, setStats] = useState({
pipelineCount: 0,
monthlyRevenue: 0,
performance: null,
target: null,
- overdueCount: 0,
- todayCount: 0,
- newCount: 0
+ overdueCount: 8,
+ todayCount: 12,
+ newCount: 3
});
- const [unreadCount, setUnreadCount] = useState(0);
const fetchStats = async () => {
try {
@@ -32,9 +53,9 @@ const HomeScreen = ({ navigation }) => {
monthlyRevenue: response.data.kpis.monthlyRevenue,
performance: response.data.performance,
target: response.data.target,
- overdueCount: response.data.kpis.overdueCount,
- todayCount: response.data.kpis.todayCount,
- newCount: response.data.kpis.newCount
+ overdueCount: response.data.kpis.overdueCount || 8,
+ todayCount: response.data.kpis.todayCount || 12,
+ newCount: response.data.kpis.newCount || 3
});
}
const notifRes = await api.get('/notifications/unread-count');
@@ -63,38 +84,79 @@ const HomeScreen = ({ navigation }) => {
}, [])
);
- const StatCard = ({ title, value, color }) => (
-
- {value}
- {title}
-
- );
-
- const MenuCard = ({ title, icon, color, onPress }) => (
-
-
- {icon}
-
- {title}
-
- );
-
const formatCurrency = (value) => {
+ if (typeof value === 'string') return value;
+ if (value >= 100000) {
+ return `₹${(value / 100000).toFixed(2)}L`;
+ }
if (value >= 1000) {
return `₹${(value / 1000).toFixed(1)}k`;
}
return `₹${value}`;
};
+ // Preset Data
+ const targetSummary = [
+ { stage: 'Lead', targetNo: 230, actualNo: 120, targetValue: 6000000, actualValue: 4500000, pct: '52%' },
+ { stage: 'Qualified', targetNo: 45, actualNo: 45, targetValue: 2500000, actualValue: 1800000, pct: '100%' },
+ { stage: 'Potential', targetNo: 15, actualNo: 15, targetValue: 1200000, actualValue: 800000, pct: '100%' },
+ { stage: 'SALES', targetNo: 3, actualNo: '-', targetValue: 200000, actualValue: 100000, pct: '50%' },
+ { stage: 'Closed', targetNo: '-', actualNo: '-', targetValue: '-', actualValue: 175000, pct: '-' },
+ ];
+
+ const weeklyPerformance = [
+ { week: 'Week 1', targetVal: 100000, achievedVal: 85000, pct: '85%' },
+ { week: 'Week 2', targetVal: 100000, achievedVal: 40000, pct: '40%' },
+ { week: 'Week 3', targetVal: 100000, achievedVal: 'Pending', pct: '-' },
+ { week: 'Week 4', targetVal: 100000, achievedVal: 'Pending', pct: '-' },
+ ];
+
+ const salesContribution = {
+ own: { value: 120000, count: 10, pct: 68 },
+ shared: { value: 55000, count: 2, pct: 32 }
+ };
+
+ const conversionFunnel = [
+ { step: 'Call → Qualified', actual: 32, expected: 40, light: 'amber' },
+ { step: 'Qualified → Potential', actual: 25, expected: 30, light: 'amber' },
+ { step: 'Potential → Demo', actual: 48, expected: 50, light: 'green' },
+ { step: 'Demo → Closed', actual: 20, expected: 40, light: 'red' },
+ ];
+
+ const todayActions = [
+ { text: '5 Calls Pending', type: 'call' },
+ { text: '3 Quotes Pending', type: 'quote' },
+ { text: '2 Demo Scheduled', type: 'demo' },
+ { text: '1 Visit Scheduled', type: 'visit' },
+ { text: '1 Manager Help Required', type: 'manager' }
+ ];
+
+ const expiredActions = [
+ { text: '2 Demo Follow-ups' },
+ { text: '1 Quote Pending' },
+ { text: '1 Visit Pending' }
+ ];
+
+ const upcomingClosures = [
+ { client: 'ABC Finance', value: 100000, prob: '85%' },
+ { client: 'XYZ Chitty', value: 30000, prob: '90%' },
+ { client: 'Star Jewellery', value: 35000, prob: '80%' }
+ ];
+
+ const todayTomorrowProbability = [
+ { type: 'TODAYS VISIT', total: 5, below80: 3, above80: 2 },
+ { type: 'TODAYS DEMO', total: 2, below80: 0, above80: 2 },
+ { type: 'TODAYS QUOTE', total: 10, below80: 5, above80: 5 },
+ { type: 'TOMORROW’S VISIT', total: 7, below80: 4, above80: 3 },
+ { type: 'TOMORROW’S DEMO', total: 4, below80: 2, above80: 2 },
+ { type: 'TOMORROW’S QUOTE', total: 12, below80: 7, above80: 5 }
+ ];
+
return (
-
+
{/* Header Section */}
@@ -103,11 +165,11 @@ const HomeScreen = ({ navigation }) => {
- Good morning,
+ IgCRM Mobile
{userInfo?.name || 'User'}
navigation.navigate('MyTarget')} style={styles.bellButton}>
-
+
{unreadCount > 0 && (
{unreadCount}
@@ -122,86 +184,262 @@ const HomeScreen = ({ navigation }) => {
- {/* Smart Priority Cards */}
-
-
- {stats.overdueCount}
- Overdue
-
-
- {stats.todayCount}
- Today
-
-
- {stats.newCount}
- New
-
-
-
- {/* Score & Target Section */}
-
-
- PERFORMANCE SCORE
- 80 ? '#27ae60' : stats.performance?.score > 50 ? '#f39c12' : '#e74c3c' }]}>
- {stats.performance ? Math.round(stats.performance.score) : '--'}
-
- {stats.performance?.tag.replace('_', ' ') || 'NO DATA'}
-
-
- navigation.navigate('MyTarget')}
- activeOpacity={0.8}
+ {/* THE 4 CORE QUESTIONS SELECTION TILES (Horizontal Scroll for Quick Access) */}
+
+ Select a Question to answer:
+
-
- MONTHLY TARGET
- ↗️
-
- {stats.target ? (
- <>
-
-
-
-
- ₹{(stats.target.achieved / 1000).toFixed(1)}k
- / ₹{(stats.target.monthly / 1000).toFixed(0)}k
-
- >
- ) : (
- No target assigned
- )}
-
+ {/* Tab 1 */}
+ setActiveTab('target')}
+ >
+
+
+ 1. What is my target?
+
+
+
+ {/* Tab 2 */}
+ setActiveTab('achieved')}
+ >
+
+
+ 2. What have I achieved?
+
+
+
+ {/* Tab 3 */}
+ setActiveTab('today')}
+ >
+
+
+ 3. What should I do today?
+
+
+
+ {/* Tab 4 */}
+ setActiveTab('opportunities')}
+ >
+
+
+ 4. Which opportunities to focus?
+
+
+
- {/* Quick Actions */}
+ {/* VIEWPORT CONTROLLER */}
+
+
+ {/* TAB 1: What is my Target? */}
+ {activeTab === 'target' && (
+
+
+ 🎯 My Target Overview
+
+
+ {/* Monthly Target Stage-wise breakdown */}
+ MONTHLY TARGET SUMMARY
+
+ {targetSummary.map((item, idx) => (
+
+
+
+ {item.stage}
+
+
+ No: {item.targetNo} (Act: {item.actualNo})
+ {formatCurrency(item.actualValue)} / {formatCurrency(item.targetValue)}
+
+
+ ))}
+
+
+ {/* Conversion Funnel */}
+ CONVERSION PERFORMANCE
+
+ {conversionFunnel.map((item, idx) => (
+
+
+ {item.step}
+
+ Act: {item.actual}% (Exp: {item.expected}%)
+
+
+
+
+
+
+
+ ))}
+
+
+ )}
+
+ {/* TAB 2: What have I achieved? */}
+ {activeTab === 'achieved' && (
+
+
+ 🏆 Achievements & Contributions
+
+
+ {/* Weekly breakdown */}
+ WEEK-WISE ACHIEVEMENT
+
+ {weeklyPerformance.map((row, idx) => (
+
+ {row.week}
+
+ {formatCurrency(row.achievedVal)} / {formatCurrency(row.targetVal)}
+ Sales%: {row.pct}
+
+
+ ))}
+
+
+ {/* Sales Split Contribution */}
+ SALES CONTRIBUTION SPLIT
+
+
+ Own Sales
+ {formatCurrency(salesContribution.own.value)}
+ {salesContribution.own.count} Deals • {salesContribution.own.pct}%
+
+
+
+ Shared Sales
+ {formatCurrency(salesContribution.shared.value)}
+ {salesContribution.shared.count} Deals • {salesContribution.shared.pct}%
+
+
+
+ )}
+
+ {/* TAB 3: What should I do today? */}
+ {activeTab === 'today' && (
+
+
+ 📅 Actions & Checklist Tasks
+
+
+ {/* Alert Center */}
+
+
+
+
+ Missed: {stats.overdueCount} items ({formatCurrency(350000)})
+
+
+
+
+
+ Target Gap: {formatCurrency(225000)}
+
+
+
+
+ {/* Action List */}
+ TODAY'S FOLLOW-UPS
+
+ {todayActions.map((item, idx) => (
+
+
+ {item.text}
+
+ ))}
+
+
+ EXPIRED ACTIVITIES
+
+ {expiredActions.map((item, idx) => (
+
+
+ {item.text}
+
+ ))}
+
+
+ {/* Probability Table */}
+ PROBABILITY MATRIX
+
+ {todayTomorrowProbability.map((item, idx) => (
+
+ {item.type}
+ Total: {item.total} ( <80%: {item.below80} | >80%: {item.above80} )
+
+ ))}
+
+
+ )}
+
+ {/* TAB 4: Which opportunities to focus? */}
+ {activeTab === 'opportunities' && (
+
+
+ ⚡ High Probability Closures
+
+
+ {upcomingClosures.map((closure, idx) => (
+
+
+ {closure.client}
+
+ {closure.prob} Probable
+
+
+ {formatCurrency(closure.value)}
+
+ ))}
+
+ )}
+
+
+ {/* BOTTOM QUICK ACTIONS BAR */}
Quick Actions
-
+
navigation.navigate('LogActivity', { tab: 'call' })}
>
📞
- Log Call
+ Call
navigation.navigate('CallLogs')}
+ onPress={() => navigation.navigate('LogActivity', { tab: 'demo' })}
>
- 📜
- Call Logs
+ 📹
+ Demo
navigation.navigate('LogActivity', { tab: 'followup' })}
+ onPress={() => navigation.navigate('LogActivity', { tab: 'visit' })}
>
- 📅
- Follow-up
+ 🚗
+ Visit
+
+ navigation.navigate('AddOpportunity')}
+ >
+ 💼
+ Deal
- {/* Dashboard Grid */}
+ {/* Navigation Menu */}
Main Activities
@@ -212,10 +450,10 @@ const HomeScreen = ({ navigation }) => {
onPress={() => navigation.navigate('Attendance')}
/>
navigation.navigate('AddOpportunity')}
+ onPress={() => navigation.navigate('ClientList')}
/>
{
color={Colors.secondary}
onPress={() => navigation.navigate('Incentive')}
/>
- navigation.navigate('LogActivity')}
- />
-
-
-
- {/* Odoo Promo/Tip Section */}
-
-
- 💡
-
-
- Sales Tip
- Follow up on your proposition deals to increase won rate by 20%.
@@ -260,27 +481,27 @@ const styles = StyleSheet.create({
},
header: {
backgroundColor: Colors.primary,
- paddingBottom: 40,
- paddingHorizontal: 24,
+ paddingBottom: 30,
+ paddingHorizontal: 20,
flexDirection: 'row',
alignItems: 'center',
},
avatarContainer: {
- marginRight: 15,
+ marginRight: 12,
},
avatar: {
- width: 50,
- height: 50,
- borderRadius: 25,
+ width: 44,
+ height: 44,
+ borderRadius: 22,
backgroundColor: 'rgba(255,255,255,0.2)',
justifyContent: 'center',
alignItems: 'center',
- borderWidth: 2,
+ borderWidth: 1.5,
borderColor: 'rgba(255,255,255,0.3)',
},
avatarText: {
color: 'white',
- fontSize: 20,
+ fontSize: 18,
fontWeight: 'bold',
},
headerTextContainer: {
@@ -288,16 +509,16 @@ const styles = StyleSheet.create({
},
greeting: {
color: 'rgba(255,255,255,0.7)',
- fontSize: 14,
+ fontSize: 12,
},
userName: {
color: 'white',
- fontSize: 22,
+ fontSize: 18,
fontWeight: 'bold',
},
bellButton: {
padding: 5,
- marginRight: 10,
+ marginRight: 8,
position: 'relative',
},
badge: {
@@ -305,9 +526,9 @@ const styles = StyleSheet.create({
top: 0,
right: 0,
backgroundColor: '#ef4444',
- borderRadius: 10,
- minWidth: 16,
- height: 16,
+ borderRadius: 8,
+ minWidth: 14,
+ height: 14,
justifyContent: 'center',
alignItems: 'center',
borderWidth: 1,
@@ -315,180 +536,338 @@ const styles = StyleSheet.create({
},
badgeText: {
color: 'white',
- fontSize: 9,
+ fontSize: 8,
fontWeight: 'bold',
- paddingHorizontal: 4,
+ paddingHorizontal: 3,
},
settingsButton: {
padding: 5,
},
- settingsIcon: {
- fontSize: 20,
- },
profileButton: {
padding: 5,
- marginRight: 10,
+ marginRight: 8,
},
- statsRow: {
- flexDirection: 'row',
- paddingHorizontal: 20,
- marginTop: -25,
- justifyContent: 'space-between',
+ tabSection: {
+ paddingTop: 16,
+ paddingHorizontal: 16,
},
- priorityCard: {
- width: (width - 60) / 3,
- paddingVertical: 12,
- borderRadius: 12,
- alignItems: 'center',
- shadowColor: '#000',
- shadowOffset: { width: 0, height: 4 },
- shadowOpacity: 0.15,
- shadowRadius: 6,
- elevation: 5,
- },
- priorityValue: {
- color: 'white',
- fontSize: 18,
- fontWeight: 'bold',
- },
- priorityLabel: {
- color: 'rgba(255,255,255,0.8)',
- fontSize: 10,
+ sectionSubtitle: {
+ fontSize: 11,
+ color: Colors.textMuted,
fontWeight: 'bold',
textTransform: 'uppercase',
+ marginBottom: 8,
+ letterSpacing: 0.5,
},
- focusContainer: {
+ horizontalTabsContainer: {
+ gap: 10,
+ paddingRight: 16,
+ },
+ questionTile: {
flexDirection: 'row',
- paddingHorizontal: 20,
- marginTop: 20,
- justifyContent: 'space-between',
- },
- scoreBox: {
- backgroundColor: 'white',
- width: '40%',
- padding: 16,
- borderRadius: 16,
alignItems: 'center',
- borderWidth: 1,
- borderColor: Colors.border,
- },
- targetBox: {
backgroundColor: 'white',
- width: '56%',
- padding: 16,
- borderRadius: 16,
- justifyContent: 'center',
+ paddingHorizontal: 14,
+ paddingVertical: 10,
+ borderRadius: 12,
borderWidth: 1,
borderColor: Colors.border,
+ gap: 8,
},
- focusLabel: {
- fontSize: 9,
+ questionTileActive: {
+ backgroundColor: Colors.primary,
+ borderColor: Colors.primary,
+ },
+ questionTileText: {
+ fontSize: 12,
+ fontWeight: 'bold',
+ color: Colors.text,
+ },
+ questionTileTextActive: {
+ color: 'white',
+ },
+ viewPort: {
+ padding: 16,
+ },
+ contentContainer: {
+ backgroundColor: 'white',
+ borderRadius: 16,
+ padding: 16,
+ borderWidth: 1,
+ borderColor: Colors.border,
+ shadowColor: '#000',
+ shadowOffset: { width: 0, height: 2 },
+ shadowOpacity: 0.05,
+ shadowRadius: 6,
+ elevation: 2,
+ },
+ contentHeader: {
+ borderBottomWidth: 1,
+ borderBottomColor: Colors.borderLight,
+ paddingBottom: 10,
+ marginBottom: 12,
+ },
+ viewPortTitle: {
+ fontSize: 14,
+ fontWeight: 'bold',
+ color: Colors.primary,
+ },
+ sectionHeader: {
+ fontSize: 10,
fontWeight: '900',
color: Colors.textMuted,
- letterSpacing: 1,
+ letterSpacing: 0.8,
+ marginTop: 14,
marginBottom: 8,
},
- scoreText: {
- fontSize: 32,
- fontWeight: '900',
+ tableCard: {
+ borderWidth: 1,
+ borderColor: Colors.borderLight,
+ borderRadius: 10,
+ backgroundColor: '#fafafa',
+ overflow: 'hidden',
},
- tagText: {
- fontSize: 8,
+ tableRow: {
+ flexDirection: 'row',
+ justifyContent: 'space-between',
+ padding: 10,
+ borderBottomWidth: 1,
+ borderBottomColor: Colors.borderLight,
+ alignItems: 'center',
+ },
+ rowLead: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ gap: 8,
+ },
+ stageDot: {
+ width: 8,
+ height: 8,
+ borderRadius: 4,
+ },
+ stageName: {
+ fontSize: 12,
fontWeight: 'bold',
- color: Colors.textMuted,
- marginTop: 4,
+ color: Colors.text,
},
- progressBarBg: {
- height: 6,
- backgroundColor: '#f1f3f5',
- borderRadius: 3,
+ rowRight: {
+ alignItems: 'flex-end',
+ },
+ rowDetail: {
+ fontSize: 10,
+ color: Colors.textMuted,
+ },
+ rowValue: {
+ fontSize: 11,
+ fontWeight: 'bold',
+ color: Colors.text,
+ },
+ funnelItem: {
+ padding: 10,
+ borderBottomWidth: 1,
+ borderBottomColor: Colors.borderLight,
+ },
+ funnelName: {
+ fontSize: 11,
+ fontWeight: 'bold',
+ color: Colors.text,
+ },
+ funnelStat: {
+ fontSize: 10,
+ color: Colors.textMuted,
+ },
+ statusIndicator: {
+ width: 8,
+ height: 8,
+ borderRadius: 4,
+ },
+ progressBg: {
+ height: 4,
+ backgroundColor: '#e2e8f0',
+ borderRadius: 2,
+ marginTop: 6,
width: '100%',
overflow: 'hidden',
},
- progressBarFill: {
+ progressFill: {
height: '100%',
- backgroundColor: Colors.primary,
- borderRadius: 3,
+ borderRadius: 2,
},
- targetRow: {
+ weeklyRow: {
flexDirection: 'row',
- alignItems: 'baseline',
- marginTop: 8,
+ justifyContent: 'space-between',
+ padding: 10,
+ borderBottomWidth: 1,
+ borderBottomColor: Colors.borderLight,
+ alignItems: 'center',
},
- targetValue: {
- fontSize: 14,
- fontWeight: 'bold',
- color: Colors.text,
- },
- targetGoal: {
- fontSize: 10,
- color: Colors.textMuted,
- marginLeft: 2,
- },
- noTargetText: {
- fontSize: 10,
- color: Colors.textMuted,
- fontStyle: 'italic',
- },
- statCard: {
- backgroundColor: 'white',
- width: (width - 56) / 2,
- padding: 16,
- borderRadius: 12,
- borderLeftWidth: 4,
- shadowColor: '#000',
- shadowOffset: { width: 0, height: 2 },
- shadowOpacity: 0.1,
- shadowRadius: 4,
- elevation: 4,
- },
- statValue: {
- fontSize: 18,
- fontWeight: 'bold',
- color: Colors.text,
- },
- statLabel: {
+ weekLabel: {
fontSize: 12,
+ fontWeight: 'bold',
+ color: Colors.text,
+ },
+ weekAchieved: {
+ fontSize: 12,
+ fontWeight: 'bold',
+ color: Colors.text,
+ },
+ weekPct: {
+ fontSize: 10,
+ color: Colors.secondary,
+ fontWeight: 'bold',
+ },
+ contributionCard: {
+ flexDirection: 'row',
+ backgroundColor: '#fafafa',
+ borderWidth: 1,
+ borderColor: Colors.borderLight,
+ borderRadius: 10,
+ padding: 12,
+ },
+ contributionBlock: {
+ flex: 1,
+ alignItems: 'center',
+ },
+ contribTitle: {
+ fontSize: 11,
+ fontWeight: 'bold',
+ color: Colors.textMuted,
+ },
+ contribValue: {
+ fontSize: 15,
+ fontWeight: 'bold',
+ color: Colors.text,
+ marginVertical: 2,
+ },
+ contribSub: {
+ fontSize: 9,
+ color: Colors.textMuted,
+ },
+ contributionDivider: {
+ width: 1,
+ backgroundColor: Colors.borderLight,
+ marginHorizontal: 8,
+ },
+ alertContainer: {
+ gap: 8,
+ marginBottom: 12,
+ },
+ alertBox: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ padding: 10,
+ borderRadius: 10,
+ borderWidth: 1,
+ gap: 8,
+ },
+ alertText: {
+ fontSize: 11,
+ fontWeight: 'bold',
+ color: Colors.text,
+ },
+ todoCard: {
+ backgroundColor: '#fafafa',
+ borderRadius: 10,
+ padding: 10,
+ gap: 8,
+ borderWidth: 1,
+ borderColor: Colors.borderLight,
+ marginBottom: 12,
+ },
+ todoRow: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ gap: 8,
+ },
+ todoText: {
+ fontSize: 12,
+ color: Colors.text,
+ fontWeight: '500',
+ },
+ probabilityRow: {
+ padding: 10,
+ borderBottomWidth: 1,
+ borderBottomColor: Colors.borderLight,
+ },
+ probType: {
+ fontSize: 11,
+ fontWeight: 'bold',
+ color: Colors.text,
+ },
+ probDetails: {
+ fontSize: 10,
color: Colors.textMuted,
marginTop: 2,
},
- gridContainer: {
- padding: 20,
- paddingTop: 10,
+ closureCard: {
+ backgroundColor: '#fafafa',
+ borderRadius: 12,
+ padding: 14,
+ borderWidth: 1,
+ borderColor: Colors.borderLight,
+ marginBottom: 10,
+ },
+ closureClient: {
+ fontSize: 12,
+ fontWeight: 'bold',
+ color: Colors.text,
+ },
+ probBadge: {
+ backgroundColor: '#ecfdf5',
+ paddingHorizontal: 8,
+ paddingVertical: 2,
+ borderRadius: 6,
+ },
+ probBadgeText: {
+ fontSize: 9,
+ color: '#059669',
+ fontWeight: 'bold',
+ },
+ closureValue: {
+ fontSize: 16,
+ fontWeight: '900',
+ color: Colors.text,
+ marginTop: 6,
},
quickActionsContainer: {
paddingHorizontal: 20,
marginTop: 10,
},
- quickActionsRow: {
+ quickActionsGrid: {
flexDirection: 'row',
- gap: 12,
+ flexWrap: 'wrap',
+ justifyContent: 'space-between',
marginTop: 8,
+ gap: 8,
},
quickActionBtn: {
- flex: 1,
+ width: (width - 48) / 2,
flexDirection: 'row',
alignItems: 'center',
- padding: 14,
- borderRadius: 16,
- gap: 10,
+ padding: 12,
+ borderRadius: 12,
+ gap: 8,
borderWidth: 1,
- borderColor: 'rgba(0,0,0,0.05)',
+ borderColor: 'rgba(0,0,0,0.03)',
},
quickActionIcon: {
- fontSize: 20,
+ fontSize: 16,
},
quickActionLabel: {
- fontSize: 14,
- fontWeight: '900',
+ fontSize: 12,
+ fontWeight: 'bold',
},
sectionTitle: {
- fontSize: 14,
- fontWeight: 'bold',
+ fontSize: 11,
+ fontWeight: '900',
color: Colors.primary,
textTransform: 'uppercase',
- letterSpacing: 1,
- marginBottom: 16,
+ letterSpacing: 0.8,
+ marginBottom: 12,
+ },
+ gridContainer: {
+ padding: 20,
+ paddingTop: 10,
},
grid: {
flexDirection: 'row',
@@ -496,65 +875,30 @@ const styles = StyleSheet.create({
justifyContent: 'space-between',
},
card: {
- width: (width - 64) / 2,
+ width: (width - 52) / 2,
backgroundColor: 'white',
- padding: 20,
- borderRadius: 16,
- marginBottom: 16,
+ padding: 14,
+ borderRadius: 12,
+ marginBottom: 12,
alignItems: 'center',
borderWidth: 1,
borderColor: Colors.border,
},
iconContainer: {
- width: 50,
- height: 50,
- borderRadius: 25,
- justifyContent: 'center',
- alignItems: 'center',
- marginBottom: 12,
- },
- cardIcon: {
- fontSize: 24,
- },
- cardTitle: {
- fontSize: 14,
- fontWeight: 'bold',
- color: Colors.textMuted,
- },
- tipCard: {
- marginHorizontal: 24,
- backgroundColor: Colors.accent,
- borderRadius: 15,
- padding: 16,
- flexDirection: 'row',
- alignItems: 'center',
- borderWidth: 1,
- borderColor: `${Colors.secondary}20`,
- },
- tipIconContainer: {
width: 40,
height: 40,
borderRadius: 20,
- backgroundColor: `${Colors.secondary}20`,
justifyContent: 'center',
alignItems: 'center',
- marginRight: 15,
+ marginBottom: 8,
},
- tipIcon: {
- fontSize: 20,
+ cardIcon: {
+ fontSize: 18,
},
- tipTextContainer: {
- flex: 1,
- },
- tipTitle: {
- fontSize: 15,
- fontWeight: 'bold',
- color: Colors.secondary,
- },
- tipDescription: {
+ cardTitle: {
fontSize: 12,
- color: '#4a5568',
- lineHeight: 18,
+ fontWeight: 'bold',
+ color: Colors.textMuted,
},
});
diff --git a/src/screens/TasksScreen.js b/src/screens/TasksScreen.js
index aefdf0a..a4986ec 100644
--- a/src/screens/TasksScreen.js
+++ b/src/screens/TasksScreen.js
@@ -94,10 +94,15 @@ const TasksScreen = ({ navigation }) => {
const [activeCategory, setActiveCategory] = useState('today');
const [inlineRemarks, setInlineRemarks] = useState({});
const [submitting, setSubmitting] = useState(null); // holds activity id being submitted
+ const [selectedTypeFilter, setSelectedTypeFilter] = useState(null);
const fetchTasks = async () => {
try {
- const params = new URLSearchParams({ userId: userInfo.id, status: 'PENDING' });
+ const queryObj = { status: 'PENDING' };
+ if (userInfo && userInfo.role !== 'ADMIN') {
+ queryObj.userId = userInfo.id;
+ }
+ const params = new URLSearchParams(queryObj);
const res = await api.get(`/followups?${params.toString()}`);
setAllActivities(res.data);
setCategorized(categorizeActivities(res.data));
@@ -143,7 +148,11 @@ const TasksScreen = ({ navigation }) => {
};
const currentCat = CATEGORIES.find(c => c.key === activeCategory);
- const currentItems = categorized[activeCategory] || [];
+ const currentCategoryTotalCount = (categorized[activeCategory] || []).length;
+ const currentItems = (categorized[activeCategory] || []).filter(item => {
+ if (!selectedTypeFilter) return true;
+ return item.type === selectedTypeFilter;
+ });
const renderItem = ({ item }) => {
const type = item.type || 'FOLLOWUP';
@@ -253,7 +262,7 @@ const TasksScreen = ({ navigation }) => {
styles.catBtn,
isActive && { backgroundColor: 'white' },
]}
- onPress={() => setActiveCategory(cat.key)}
+ onPress={() => { setActiveCategory(cat.key); setSelectedTypeFilter(null); }}
>
{cat.label}
@@ -267,6 +276,54 @@ const TasksScreen = ({ navigation }) => {
+ {/* Event Type Filter Row */}
+
+
+ setSelectedTypeFilter(null)}
+ >
+
+ All ({currentCategoryTotalCount})
+
+
+ {Object.entries(TYPE_ICONS).map(([type, icon]) => {
+ const count = (categorized[activeCategory] || []).filter(item => item.type === type).length;
+ if (count === 0) return null;
+ const isActive = selectedTypeFilter === type;
+ return (
+ setSelectedTypeFilter(isActive ? null : type)}
+ >
+ {icon}
+
+ {type.replace(/_/g, ' ')}
+
+
+
+ {count}
+
+
+
+ );
+ })}
+
+
+
{/* Section Header */}
@@ -387,6 +444,25 @@ const styles = StyleSheet.create({
emptyIcon: { fontSize: 52, marginBottom: 14 },
emptyTitle: { fontSize: 18, fontWeight: '900', color: '#1e293b' },
emptySub: { fontSize: 13, color: '#64748b', marginTop: 6, textAlign: 'center' },
+
+ // Type filters
+ typeFilterScroll: { paddingHorizontal: 16, marginBottom: 4 },
+ typeFilterScrollContent: { gap: 8, paddingRight: 32 },
+ typeFilterBtn: {
+ flexDirection: 'row', alignItems: 'center', gap: 6,
+ paddingHorizontal: 12, paddingVertical: 6,
+ borderRadius: 20, backgroundColor: 'white',
+ borderWidth: 1, borderColor: '#e2e8f0',
+ },
+ typeFilterBtnActive: {
+ borderColor: Colors.primary,
+ backgroundColor: '#fff7ed',
+ },
+ typeFilterIcon: { fontSize: 13 },
+ typeFilterBtnText: { fontSize: 11, fontWeight: '700', color: '#64748b', textTransform: 'capitalize' },
+ typeFilterBtnTextActive: { color: '#1e293b', fontWeight: '800' },
+ typeFilterCount: { minWidth: 16, height: 16, borderRadius: 8, alignItems: 'center', justifyContent: 'center', paddingHorizontal: 4 },
+ typeFilterCountText: { fontSize: 9, fontWeight: '900', color: '#475569' },
});
export default TasksScreen;