149 lines
4.2 KiB
TypeScript
149 lines
4.2 KiB
TypeScript
import React, { useState, useCallback, useEffect } from 'react';
|
|
import {TextInput, FlatList, TouchableOpacity, StyleSheet, ActivityIndicator } from 'react-native';
|
|
import { ThemedView } from '@/components/ThemedView';
|
|
import { ThemedText } from '@/components/ThemedText';
|
|
import { getUserData } from '@/components/services/securestorage/UserData';
|
|
import { Colors } from '@/constants/Colors';
|
|
import { useColorScheme } from '@/hooks/useColorScheme';
|
|
import debounce from 'lodash.debounce';
|
|
|
|
type UserData = {
|
|
id: number;
|
|
appleId: string | null;
|
|
appleEmail: string | null;
|
|
fullName: string;
|
|
pfpURL: string | null;
|
|
pushToken: string;
|
|
createdAt: Date;
|
|
};
|
|
|
|
type RelationshipData = {
|
|
relationship: {
|
|
id: number;
|
|
title: string;
|
|
status: "pending" | "accepted" | "rejected";
|
|
relationshipStartDate: Date;
|
|
createdAt: Date;
|
|
};
|
|
partner: UserData;
|
|
};
|
|
|
|
const RequestRelationship: React.FC<{ onRequestSent: (data: RelationshipData) => void }> = ({ onRequestSent }) => {
|
|
const scheme = useColorScheme() ?? 'light';
|
|
const [searchTerm, setSearchTerm] = useState('');
|
|
const [searchResults, setSearchResults] = useState<UserData[]>([]);
|
|
const [isLoading, setIsLoading] = useState(false);
|
|
const [currentUserId, setCurrentUserId] = useState<number | null>(null);
|
|
|
|
useEffect(() => {
|
|
const fetchCurrentUser = async () => {
|
|
const userData = await getUserData();
|
|
if (userData) {
|
|
setCurrentUserId(userData.id);
|
|
}
|
|
};
|
|
fetchCurrentUser();
|
|
}, []);
|
|
|
|
const searchUsers = useCallback(
|
|
debounce(async (term: string) => {
|
|
if (term.length < 3) {
|
|
setSearchResults([]);
|
|
return;
|
|
}
|
|
setIsLoading(true);
|
|
try {
|
|
const response = await fetch(`${process.env.EXPO_PUBLIC_API_URL}/users/getUserByName?usersName=${encodeURIComponent(term)}`, {
|
|
headers: {
|
|
'x-api-key': process.env.EXPO_PUBLIC_API_KEY ?? '',
|
|
},
|
|
});
|
|
if (!response.ok) throw new Error('Search failed');
|
|
const data = await response.json();
|
|
setSearchResults(data);
|
|
} catch (error) {
|
|
console.error('Error searching users:', error);
|
|
} finally {
|
|
setIsLoading(false);
|
|
}
|
|
}, 300),
|
|
[]
|
|
);
|
|
|
|
const handleSearch = (text: string) => {
|
|
setSearchTerm(text);
|
|
searchUsers(text);
|
|
};
|
|
|
|
const sendRequest = async (targetUserId: number) => {
|
|
if (!currentUserId) return;
|
|
try {
|
|
const response = await fetch(`${process.env.EXPO_PUBLIC_API_URL}/relationships/createRequest`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'x-api-key': process.env.EXPO_PUBLIC_API_KEY ?? '',
|
|
},
|
|
body: JSON.stringify({ userId: currentUserId, targetUserId }),
|
|
});
|
|
if (!response.ok) throw new Error('Request failed');
|
|
const data: RelationshipData = await response.json();
|
|
onRequestSent(data);
|
|
} catch (error) {
|
|
console.error('Error sending relationship request:', error);
|
|
}
|
|
};
|
|
|
|
const renderUserItem = ({ item }: { item: UserData }) => (
|
|
<TouchableOpacity style={styles.userItem} onPress={() => sendRequest(item.id)}>
|
|
<ThemedText>{item.fullName}</ThemedText>
|
|
<ThemedText>{item.appleEmail}</ThemedText>
|
|
</TouchableOpacity>
|
|
);
|
|
|
|
return (
|
|
<ThemedView style={styles.container}>
|
|
<TextInput
|
|
style={[
|
|
styles.searchInput,
|
|
{color: Colors[scheme].text}
|
|
]}
|
|
placeholder="Search users..."
|
|
value={searchTerm}
|
|
onChangeText={handleSearch}
|
|
/>
|
|
{isLoading ? (
|
|
<ActivityIndicator />
|
|
) : (
|
|
<FlatList
|
|
data={searchResults}
|
|
renderItem={renderUserItem}
|
|
keyExtractor={(item) => item.id.toString()}
|
|
ListEmptyComponent={<ThemedText>No users found</ThemedText>}
|
|
/>
|
|
)}
|
|
</ThemedView>
|
|
);
|
|
};
|
|
|
|
const styles = StyleSheet.create({
|
|
container: {
|
|
flex: 1,
|
|
padding: 20,
|
|
},
|
|
searchInput: {
|
|
height: 40,
|
|
borderColor: 'gray',
|
|
borderWidth: 1,
|
|
marginBottom: 20,
|
|
paddingHorizontal: 10,
|
|
},
|
|
userItem: {
|
|
padding: 10,
|
|
borderBottomWidth: 1,
|
|
borderBottomColor: 'gray',
|
|
},
|
|
});
|
|
|
|
export default RequestRelationship;
|