262 lines
6.9 KiB
JavaScript
262 lines
6.9 KiB
JavaScript
|
import React, { useState, useEffect } from 'react';
|
||
|
import { View, Text, Button, ScrollView, RefreshControl, ActivityIndicator } from 'react-native';
|
||
|
import { useTailwind } from 'tailwind-rn'
|
||
|
import AsyncStorage from '@react-native-async-storage/async-storage';
|
||
|
import Icon from 'react-native-vector-icons/FontAwesome'
|
||
|
import { TouchableOpacity } from 'react-native';
|
||
|
import { HeaderButtons, Item } from 'react-navigation-header-buttons';
|
||
|
import CreateSwitButton from './components/Create';
|
||
|
// import date
|
||
|
import moment from 'moment';
|
||
|
import { FAB } from 'react-native-paper';
|
||
|
|
||
|
function Swit({ swit, navigation, userId, setSwits, swits }) {
|
||
|
const [isLiked, setIsLiked] = useState(swit.likes.some(like => like === userId));
|
||
|
const tailwind = useTailwind();
|
||
|
const [errorMessage, setErrorMessage] = useState('');
|
||
|
const [isReposted, setIsReposted] = useState('');
|
||
|
const [repostCount, setRepostCount] = useState(null);
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
function formatTime(time) {
|
||
|
const duration = moment.duration(moment().diff(time));
|
||
|
|
||
|
const years = duration.years();
|
||
|
if (years > 0) {
|
||
|
return `${years}y`;
|
||
|
}
|
||
|
|
||
|
const months = duration.months();
|
||
|
if (months > 0) {
|
||
|
return `${months}m`;
|
||
|
}
|
||
|
|
||
|
const days = duration.days();
|
||
|
if (days > 0) {
|
||
|
return `${days}d`;
|
||
|
}
|
||
|
|
||
|
const hours = duration.hours();
|
||
|
if (hours > 0) {
|
||
|
return `${hours}h`;
|
||
|
}
|
||
|
|
||
|
const minutes = duration.minutes();
|
||
|
if (minutes > 0) {
|
||
|
return `${minutes}m`;
|
||
|
}
|
||
|
|
||
|
return 'Just now';
|
||
|
}
|
||
|
|
||
|
|
||
|
const handleLikePress = async (id) => {
|
||
|
setIsLiked(!isLiked);
|
||
|
const apiUrl = await AsyncStorage.getItem('apiEndpoint')
|
||
|
|
||
|
const url = `${apiUrl}/api/v1/app/swit/swits/${id}/${isLiked ? 'unlike' : 'like'}`;
|
||
|
const token = await AsyncStorage.getItem('token');
|
||
|
|
||
|
try {
|
||
|
const response = await fetch(url, {
|
||
|
method: 'POST',
|
||
|
headers: {
|
||
|
'Authorization': token,
|
||
|
'Content-Type': 'application/json',
|
||
|
},
|
||
|
});
|
||
|
|
||
|
if (!response.ok) {
|
||
|
setIsLiked(!isLiked);
|
||
|
console.warn(response)
|
||
|
} else {
|
||
|
// Fetch the updated swit
|
||
|
|
||
|
const switResponse = await fetch(`${apiUrl}/api/v1/app/swit/swits/${id}`, {
|
||
|
headers: { 'Authorization': token },
|
||
|
});
|
||
|
|
||
|
if (switResponse.ok) {
|
||
|
const updatedSwit = await switResponse.json();
|
||
|
// Update the swit in the swits array
|
||
|
setSwits(swits.map(s => s._id === id ? updatedSwit : s));
|
||
|
}
|
||
|
}
|
||
|
} catch (error) {
|
||
|
console.error('Error:', error);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
const handleRepostPress = async (id) => {
|
||
|
setIsReposted(!isReposted);
|
||
|
const apiUrl = await AsyncStorage.getItem('apiEndpoint')
|
||
|
const url = `${apiUrl}/api/v1/app/swit/swits/${id}/${isReposted ? 'unrepost' : 'repost'}`;
|
||
|
const token = await AsyncStorage.getItem('token');
|
||
|
|
||
|
try {
|
||
|
const response = await fetch(url, {
|
||
|
method: 'POST',
|
||
|
headers: {
|
||
|
'Authorization': token,
|
||
|
'Content-Type': 'application/json',
|
||
|
},
|
||
|
});
|
||
|
|
||
|
if (!response.ok) {
|
||
|
setIsReposted(!isReposted);
|
||
|
throw new Error('Network response was not ok');
|
||
|
}
|
||
|
|
||
|
const data = response.json()
|
||
|
setRepostCount(data.count)
|
||
|
|
||
|
} catch (error) {
|
||
|
console.error('Error:', error);
|
||
|
}
|
||
|
};
|
||
|
|
||
|
useEffect(() => {
|
||
|
setIsLiked(swit.likes.some(like => like === userId));
|
||
|
}, [swit, userId]);
|
||
|
|
||
|
|
||
|
|
||
|
return (
|
||
|
<TouchableOpacity key={swit._id} onPress={() => navigation.navigate('SwitDetail', { switId: swit._id, userId: userId })}>
|
||
|
<View key={swit._id} style={tailwind('border border-gray-500 p-2 mb-4')}>
|
||
|
<Text
|
||
|
style={tailwind('font-bold mb-2')}
|
||
|
onPress={() => {
|
||
|
navigation.navigate('Profile', { userId: swit.user })
|
||
|
}}
|
||
|
>
|
||
|
{swit.username} - <Text style={tailwind('text-gray-400')}>{formatTime(swit.createdAt)}</Text>
|
||
|
</Text>
|
||
|
|
||
|
<Text>{swit.text}</Text>
|
||
|
<Icon name="heart" size={24} color={isLiked ? 'red' : 'black'} onPress={() => handleLikePress(swit._id)} />
|
||
|
<Text>{swit.likes.length}</Text>
|
||
|
<Icon name="rotate-right" size={24} color={isReposted ? 'green' : 'black'} onPress={() => handleRepostPress(swit._id)} />
|
||
|
<Text>{swit.reposts.length}</Text>
|
||
|
|
||
|
</View>
|
||
|
</TouchableOpacity>
|
||
|
);
|
||
|
}
|
||
|
|
||
|
|
||
|
function HomeScreen({ navigation }) {
|
||
|
const [swits, setSwits] = useState([]);
|
||
|
const [refreshing, setRefreshing] = useState(false);
|
||
|
const [isLoading, setIsLoading] = useState(false);
|
||
|
const [errorMessage, setErrorMessage] = useState('');
|
||
|
const [userId, setUserId] = useState('');
|
||
|
|
||
|
async function fetchSwits() {
|
||
|
setIsLoading(true)
|
||
|
const token = await AsyncStorage.getItem('token');
|
||
|
const apiUrl = await AsyncStorage.getItem('apiEndpoint')
|
||
|
setErrorMessage('');
|
||
|
try {
|
||
|
setErrorMessage('');
|
||
|
const response = await fetch(`${apiUrl}/api/v1/app/swit/swits/`, {
|
||
|
headers: { 'Authorization': token },
|
||
|
});
|
||
|
|
||
|
if (!response.ok) {
|
||
|
const errorText = await response.text();
|
||
|
setErrorMessage(errorText);
|
||
|
return;
|
||
|
}
|
||
|
const swits = await response.json();
|
||
|
setSwits(swits);
|
||
|
} catch (error) {
|
||
|
console.log(error);
|
||
|
setErrorMessage('Something went wrong');
|
||
|
}
|
||
|
setIsLoading(false)
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
useEffect(() => {
|
||
|
const unsubscribe = navigation.addListener('focus', fetchSwits);
|
||
|
return unsubscribe;
|
||
|
}, [navigation]);
|
||
|
|
||
|
useEffect(() => {
|
||
|
async function fetchUserId() {
|
||
|
const id = await AsyncStorage.getItem('userID');
|
||
|
setUserId(id);
|
||
|
}
|
||
|
fetchUserId();
|
||
|
}, []);
|
||
|
|
||
|
useEffect(() => {
|
||
|
navigation.setOptions({
|
||
|
headerRight: () => (
|
||
|
<HeaderButtons HeaderButtonComponent={CreateSwitButton}>
|
||
|
<Item
|
||
|
title="Add"
|
||
|
iconName="ios-add"
|
||
|
onPress={() => {
|
||
|
navigation.navigate('Swit');
|
||
|
}}
|
||
|
/>
|
||
|
</HeaderButtons>
|
||
|
),
|
||
|
});
|
||
|
}, [navigation]);
|
||
|
|
||
|
|
||
|
const tailwind = useTailwind();
|
||
|
|
||
|
if (isLoading) {
|
||
|
return (
|
||
|
<View style={{flex: 1, justifyContent: 'center', alignItems: 'center'}}>
|
||
|
<ActivityIndicator size="large" color="#0000ff" />
|
||
|
</View>
|
||
|
)
|
||
|
}
|
||
|
|
||
|
return (
|
||
|
<View style={tailwind('p-4')}>
|
||
|
{errorMessage ? <Text style={tailwind('text-red-500 mb-2 text-center')}>{errorMessage}</Text> : null}
|
||
|
<ScrollView
|
||
|
refreshControl={
|
||
|
<RefreshControl
|
||
|
refreshing={refreshing}
|
||
|
onRefresh={async () => {
|
||
|
setRefreshing(true);
|
||
|
await fetchSwits();
|
||
|
setRefreshing(false);
|
||
|
}}
|
||
|
/>
|
||
|
}
|
||
|
>
|
||
|
{swits.map(swit => (
|
||
|
<Swit swit={swit} navigation={navigation} userId={userId} setSwits={setSwits} swits={swits}/>
|
||
|
))}
|
||
|
|
||
|
</ScrollView>
|
||
|
|
||
|
<FAB
|
||
|
style={{
|
||
|
position: 'absolute',
|
||
|
margin: 16,
|
||
|
right: 0,
|
||
|
bottom: 0,
|
||
|
}}
|
||
|
icon="plus"
|
||
|
onPress={() => navigation.navigate('Swit')}
|
||
|
/>
|
||
|
</View>
|
||
|
);
|
||
|
|
||
|
}
|
||
|
|
||
|
export default HomeScreen;
|
||
|
export { Swit };
|