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, ImageUploader, } from 'common-ui'; import { trpc } from '@/src/trpc-client'; import usePickImage from 'common-ui/src/components/use-pick-image'; interface User { id: number; name: string | null; mobile: string | null; isEligibleForNotif: boolean; } const extractKeyFromUrl = (url: string): string => { const u = new URL(url); const rawKey = u.pathname.replace(/^\/+/, ''); return decodeURIComponent(rawKey); }; export default function SendNotifications() { const router = useRouter(); const [selectedUserIds, setSelectedUserIds] = useState([]); const [title, setTitle] = useState(''); const [message, setMessage] = useState(''); const [selectedImage, setSelectedImage] = useState<{ blob: Blob; mimeType: string } | null>(null); const [displayImage, setDisplayImage] = useState<{ uri?: string } | null>(null); const [searchQuery, setSearchQuery] = useState(''); // Query users eligible for notifications const { data: usersData, isLoading: isLoadingUsers } = trpc.admin.user.getUsersForNotification.useQuery({ search: searchQuery, }); // Generate upload URLs mutation const generateUploadUrls = trpc.user.fileUpload.generateUploadUrls.useMutation(); // Send notification mutation const sendNotification = trpc.admin.user.sendNotification.useMutation({ onSuccess: () => { Alert.alert('Success', 'Notification sent successfully!'); // Reset form setSelectedUserIds([]); setTitle(''); setMessage(''); setSelectedImage(null); setDisplayImage(null); }, 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 handleImagePick = usePickImage({ setFile: async (assets: any) => { if (!assets || (Array.isArray(assets) && assets.length === 0)) { setSelectedImage(null); setDisplayImage(null); return; } const file = Array.isArray(assets) ? assets[0] : assets; const response = await fetch(file.uri); const blob = await response.blob(); setSelectedImage({ blob, mimeType: file.mimeType || 'image/jpeg' }); setDisplayImage({ uri: file.uri }); }, multiple: false, }); const handleRemoveImage = () => { setSelectedImage(null); setDisplayImage(null); }; 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; } if (selectedUserIds.length === 0) { Alert.alert('Error', 'Please select at least one user'); return; } try { let imageUrl: string | undefined; // Upload image if selected if (selectedImage) { const { uploadUrls } = await generateUploadUrls.mutateAsync({ contextString: 'notification', mimeTypes: [selectedImage.mimeType], }); if (uploadUrls.length > 0) { const uploadUrl = uploadUrls[0]; imageUrl = extractKeyFromUrl(uploadUrl); // Upload image const uploadResponse = await fetch(uploadUrl, { method: 'PUT', body: selectedImage.blob, headers: { 'Content-Type': selectedImage.mimeType, }, }); if (!uploadResponse.ok) { throw new Error(`Upload failed with status ${uploadResponse.status}`); } } } // Send notification await sendNotification.mutateAsync({ userIds: selectedUserIds, title: title.trim(), text: message.trim(), imageUrl, }); } catch (error: any) { Alert.alert('Error', error.message || 'Failed to send notification'); } }; const getDisplayText = () => { if (selectedUserIds.length === 0) return 'Select 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 {/* Image Upload - Hidden for now */} {/* Image (Optional) */} {/* User Selection */} Select Users (Optional) setSelectedUserIds(value as number[])} multiple={true} placeholder="Select users" onSearch={(query) => setSearchQuery(query)} /> {getDisplayText()} {/* Submit Button */} {sendNotification.isPending ? 'Sending...' : 'Send Notification'} ); }