changes till 24/06/2026
main
Manu Krishna 2026-06-24 15:26:06 +05:30
parent 7e735e3e7d
commit 6360b9c2e3
4 changed files with 713 additions and 294 deletions

View File

@ -9,4 +9,4 @@ const ENV = {
};
// Set to 'prod' when deploying
export default ENV.dev;
export default ENV.prod;

View File

@ -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 () => {

File diff suppressed because it is too large Load Diff

View File

@ -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); }}
>
<Text style={[styles.catBtnText, isActive && { color: cat.color }]}>
{cat.label}
@ -267,6 +276,54 @@ const TasksScreen = ({ navigation }) => {
</ScrollView>
</View>
{/* Event Type Filter Row */}
<View style={{ backgroundColor: '#f8fafc', paddingTop: 8, paddingBottom: 4 }}>
<ScrollView
horizontal
showsHorizontalScrollIndicator={false}
style={styles.typeFilterScroll}
contentContainerStyle={styles.typeFilterScrollContent}
>
<TouchableOpacity
style={[
styles.typeFilterBtn,
!selectedTypeFilter && styles.typeFilterBtnActive
]}
onPress={() => setSelectedTypeFilter(null)}
>
<Text style={[styles.typeFilterBtnText, !selectedTypeFilter && styles.typeFilterBtnTextActive]}>
All ({currentCategoryTotalCount})
</Text>
</TouchableOpacity>
{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 (
<TouchableOpacity
key={type}
style={[
styles.typeFilterBtn,
isActive && styles.typeFilterBtnActive,
isActive && { borderColor: TYPE_COLORS[type] || '#64748b' }
]}
onPress={() => setSelectedTypeFilter(isActive ? null : type)}
>
<Text style={styles.typeFilterIcon}>{icon}</Text>
<Text style={[styles.typeFilterBtnText, isActive && styles.typeFilterBtnTextActive]}>
{type.replace(/_/g, ' ')}
</Text>
<View style={[styles.typeFilterCount, isActive ? { backgroundColor: TYPE_COLORS[type] || '#64748b' } : { backgroundColor: '#e2e8f0' }]}>
<Text style={[styles.typeFilterCountText, isActive && { color: 'white' }]}>
{count}
</Text>
</View>
</TouchableOpacity>
);
})}
</ScrollView>
</View>
{/* Section Header */}
<View style={[styles.sectionBanner, { backgroundColor: currentCat.bg, borderLeftColor: currentCat.color }]}>
<Text style={[styles.sectionBannerTitle, { color: currentCat.color }]}>
@ -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;