import React, { useState, useCallback } from 'react'; import { View, TouchableOpacity, ActivityIndicator, ScrollView, Alert, } from 'react-native'; import { useRouter } from 'expo-router'; import MaterialIcons from '@expo/vector-icons/MaterialIcons'; import { AppContainer, MyText, tw, MyTextInput, BottomDropdown, } from 'common-ui'; import { trpc } from '@/src/trpc-client'; import type { UserMiniInfo } from '@packages/shared'; // Notification recipient = shared mini user + eligibility flag type User = Omit & { name: string | null; isEligibleForNotif: boolean; } export default function SendNotifications() { const router = useRouter(); const [selectedUserIds, setSelectedUserIds] = useState([]); const [title, setTitle] = useState(''); const [message, setMessage] = useState(''); const [searchQuery, setSearchQuery] = useState(''); // Query users eligible for notifications const { data: usersData, isLoading: isLoadingUsers } = trpc.admin.user.getUsersForNotification.useQuery({ search: searchQuery, }); // Send notification mutation const sendNotification = trpc.admin.user.sendNotification.useMutation({ onSuccess: () => { Alert.alert('Success', 'Notification sent successfully!'); // Reset form setSelectedUserIds([]); setTitle(''); setMessage(''); }, onError: (error: any) => { Alert.alert('Error', error.message || 'Failed to send notification'); }, }); const eligibleUsers = usersData?.users.filter((u: User) => u.isEligibleForNotif) || []; const dropdownOptions = eligibleUsers.map((user: User) => ({ label: `${user.mobile || 'No Mobile'}${user.name ? ` - ${user.name}` : ''}`, value: user.id, })); const handleSend = async () => { if (title.trim().length === 0) { Alert.alert('Error', 'Please enter a title'); return; } if (message.trim().length === 0) { Alert.alert('Error', 'Please enter a message'); return; } // Check if sending to all users const isSendingToAll = selectedUserIds.length === 0; if (isSendingToAll) { const confirmed = await new Promise((resolve) => { Alert.alert( 'Send to All Users?', 'This will send the notification to all users with push tokens. Continue?', [ { text: 'Cancel', style: 'cancel', onPress: () => resolve(false) }, { text: 'Send', style: 'default', onPress: () => resolve(true) }, ] ); }); if (!confirmed) return; } try { // Send notification await sendNotification.mutateAsync({ userIds: selectedUserIds, title: title.trim(), text: message.trim(), }); } catch (error: any) { Alert.alert('Error', error.message || 'Failed to send notification'); } }; const getDisplayText = () => { if (selectedUserIds.length === 0) return 'All Users'; if (selectedUserIds.length === 1) { const user = eligibleUsers.find((u: User) => u.id === selectedUserIds[0]); return user ? `${user.mobile}${user.name ? ` - ${user.name}` : ''}` : '1 user selected'; } return `${selectedUserIds.length} users selected`; }; if (isLoadingUsers) { return ( Loading users... ); } return ( {/* Header */} router.back()} style={tw`p-2 -ml-4`} > Send Notifications {/* Title Input */} Title {/* Message Input */} Message {/* User Selection */} Select Users (Optional) setSelectedUserIds(value as number[])} multiple={true} placeholder="Select users" onSearch={(query) => setSearchQuery(query)} /> {getDisplayText()} Leave empty to send to all users {/* Submit Button */} {sendNotification.isPending ? 'Sending...' : selectedUserIds.length === 0 ? 'Send to All Users' : 'Send Notification'} ); }