Skip to content

Commit

Permalink
feat: notifications and mentions screen
Browse files Browse the repository at this point in the history
  • Loading branch information
LuisParedes1 committed Nov 23, 2023
1 parent 98790db commit 6882ea3
Show file tree
Hide file tree
Showing 10 changed files with 396 additions and 0 deletions.
34 changes: 34 additions & 0 deletions src/api/snaps/use-snaps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,37 @@ export const userReplySnaps = createQuery<Response, ReplyVariable, AxiosError>({
}
},
});

export const useMentions = createQuery<Response, Variables, AxiosError>({
primaryKey: '/api/interactions/mentions',
queryFn: async ({ queryKey: [primaryKey, variables] }) => {
try {
const limit = 100;
const offset = 0;
const response = await client.get(
`${primaryKey}/?user_id=${variables.user_id}&limit=${limit}&offset=${offset}`
);
console.log('response.data.mentions', response.data.mentions); // response.data is an array of posts
return response.data.mentions;
} catch (e) {
console.log('error', e);
}
},
});

export const useNotifications = createQuery<Response, Variables, AxiosError>({
primaryKey: '/api/interactions/notifications',
queryFn: async ({ queryKey: [primaryKey, variables] }) => {
try {
const limit = 100;
const offset = 0;
const response = await client.get(
`${primaryKey}/?user_id=${variables.user_id}&limit=${limit}&offset=${offset}`
);
console.log('response.data.notifications', response.data.notifications); // response.data is an array of posts
return response.data.notifications;
} catch (e) {
console.log('error', e);
}
},
});
8 changes: 8 additions & 0 deletions src/navigation/tab-data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ import type { IconDefinition } from '@fortawesome/free-solid-svg-icons';
import {
faFeed,
faMessage,
faPersonDigging,
faPowerOff,
faSearch,
} from '@fortawesome/free-solid-svg-icons';

import { ChatNavigator } from '@/screens/chat/chat-navigator';
import { NotificationNavigator } from '@/screens/notifications/notification-navigator';
import { ProfileNavigator } from '@/screens/profile/profile-navigator';
import { SearchNavigator } from '@/screens/search/search-navigator';

Expand Down Expand Up @@ -48,6 +50,12 @@ export const tabs: TabType[] = [
label: 'Chat',
icon: faMessage,
},
{
name: 'NotificationsNavigator',
component: NotificationNavigator, // React Profile component screen
label: 'Notifications',
icon: faPersonDigging,
},
{
name: 'ProfileNavigator',
component: ProfileNavigator, // React Profile component screen
Expand Down
2 changes: 2 additions & 0 deletions src/navigation/types.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { RouteProp as NRouteProp } from '@react-navigation/native';

import type { ChatStackParamList } from '@/screens/chat/chat-navigator';
import type { NotificationStackParamList } from '@/screens/notifications/notification-navigator';
import type { SearchStackParamList } from '@/screens/search/search-navigator';
import type { UserStackParamList } from '@/screens/users/user-navigate';

Expand All @@ -14,6 +15,7 @@ export type RootStackParamList = AuthStackParamList &
ChatStackParamList &
ProfileStackParamList &
UserStackParamList &
NotificationStackParamList &
SearchStackParamList; // & FooStackParamList & BarStackParamList
// very important to type check useNavigation hook
declare global {
Expand Down
1 change: 1 addition & 0 deletions src/screens/notifications/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './notification-screen';
106 changes: 106 additions & 0 deletions src/screens/notifications/mentions-view.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { useNavigation } from '@react-navigation/native';
import axios from 'axios';
import { useCallback, useEffect, useState } from 'react';
import { FlatList, RefreshControl } from 'react-native';

import type { Snap } from '@/api';
import { useMentions } from '@/api';
import { getUserState } from '@/core';
import { EmptyList, FocusAwareStatusBar, Text, View } from '@/ui';

import { Card } from '../feed/card';

const INCREMENT_RENDER = 10;
const INITIAL_RENDER = 20;

const BASE_INTERACTION_URL =
'https://api-content-discovery-luiscusihuaman.cloud.okteto.net/api/interactions/';

const MentionScreen = () => {
const currentUser = getUserState();

const { data, isLoading, isError, refetch } = useMentions({
variables: { user_id: currentUser?.id },
});

const [mentionSnaps, setMentionSnaps] = useState<Snap[]>([]);

useEffect(() => {
setMentionSnaps(data ? data : []);
}, [data]);

const { navigate } = useNavigation();

// State to track the number of items to render
const [renderCount, setRenderCount] = useState(INITIAL_RENDER);
const [refresh, setRefresh] = useState(false);

// The useCallback hook
const onRefresh = useCallback(() => {
setRefresh(true);
refetch().then(() => setRefresh(false));
}, [refetch]);

// Early return in case of error
if (isError) {
return (
<View>
<Text> Error Loading data </Text>
</View>
);
}

const client = axios.create({
baseURL: BASE_INTERACTION_URL,
});

// Corrected renderItem function
const renderItem = ({ item, index }: { item: Snap; index: number }) => {
if (index < renderCount) {
return (
<Card
snap={item}
client={client}
onPress={() => navigate('Snap', { snap: item })}
/>
);
}
return null;
};

const handleEndReached = () => {
console.log(`handleEndReached before: ${renderCount}`);

// Load more items when the user reaches the end
if (renderCount < (data ? data.length : 0)) {
setRenderCount(renderCount + INCREMENT_RENDER);
}

// console.log(`handleEndReached after: ${renderCount}`);
};

return (
<View>
<FocusAwareStatusBar />

<FlatList
data={mentionSnaps}
renderItem={renderItem}
keyExtractor={(_, index) => `item-${index}`}
ListEmptyComponent={<EmptyList isLoading={isLoading} />}
onEndReached={handleEndReached}
onEndReachedThreshold={0.1}
refreshControl={
<RefreshControl refreshing={refresh} onRefresh={onRefresh} />
}
getItemLayout={(_data, index) => ({
length: 100,
offset: 100 * index,
index,
})}
/>
</View>
);
};

export default MentionScreen;
106 changes: 106 additions & 0 deletions src/screens/notifications/notification-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
import { Text, TouchableOpacity, View } from 'react-native';

import { Image } from '@/ui';

import type { Notification } from './types';

export type NotificationCardProps = {
uri: string;
title: string;
description: string;
onPress: () => void;
};

export default function NotificationCard({}: {
notification: Notification | null;
}) {
return (
<View className="max-w-md flex-1 overflow-hidden rounded-lg bg-white shadow-black">
<View style={{ width: 2, backgroundColor: 'gray-800' }} />
<View style={{ flexDirection: 'row', alignItems: 'center', padding: 6 }}>
<Image
style={{ width: 48, height: 48, borderRadius: 24 }}
source={{
uri: 'https://images.unsplash.com/photo-1477118476589-bff2c5c4cfbb?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60',
}}
/>
<View style={{ marginLeft: 9 }}>
<Text style={{ fontSize: 18, fontWeight: '600', color: 'gray-800' }}>
Hello john
</Text>
<Text style={{ color: 'gray-600' }}>
Sara was replied on the{' '}
<TouchableOpacity>
<Text style={{ color: 'blue-500' }}>Upload Image</Text>
</TouchableOpacity>
.
</Text>
</View>
</View>

<View style={{ width: 2, backgroundColor: 'gray-800' }} />
<View style={{ flexDirection: 'row', alignItems: 'center', padding: 6 }}>
<Image
style={{ width: 48, height: 48, borderRadius: 24 }}
source={{
uri: 'https://images.unsplash.com/photo-1477118476589-bff2c5c4cfbb?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60',
}}
/>
<View style={{ marginLeft: 9 }}>
<Text style={{ fontSize: 18, fontWeight: '600', color: 'gray-800' }}>
Hello john
</Text>
<Text style={{ color: 'gray-600' }}>
Sara was replied on the{' '}
<TouchableOpacity>
<Text style={{ color: 'blue-500' }}>Upload Image</Text>
</TouchableOpacity>
.
</Text>
</View>
</View>
<View style={{ width: 2, backgroundColor: 'gray-800' }} />
<View style={{ flexDirection: 'row', alignItems: 'center', padding: 6 }}>
<Image
style={{ width: 48, height: 48, borderRadius: 24 }}
source={{
uri: 'https://images.unsplash.com/photo-1477118476589-bff2c5c4cfbb?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60',
}}
/>
<View style={{ marginLeft: 9 }}>
<Text style={{ fontSize: 18, fontWeight: '600', color: 'gray-800' }}>
Hello john
</Text>
<Text style={{ color: 'gray-600' }}>
Sara was replied on the{' '}
<TouchableOpacity>
<Text style={{ color: 'blue-500' }}>Upload Image</Text>
</TouchableOpacity>
.
</Text>
</View>
</View>
<View style={{ width: 2, backgroundColor: 'gray-800' }} />
<View style={{ flexDirection: 'row', alignItems: 'center', padding: 6 }}>
<Image
style={{ width: 48, height: 48, borderRadius: 24 }}
source={{
uri: 'https://images.unsplash.com/photo-1477118476589-bff2c5c4cfbb?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=500&q=60',
}}
/>
<View style={{ marginLeft: 9 }}>
<Text style={{ fontSize: 18, fontWeight: '600', color: 'gray-800' }}>
Hello john
</Text>
<Text style={{ color: 'gray-600' }}>
Sara was replied on the{' '}
<TouchableOpacity>
<Text style={{ color: 'blue-500' }}>Upload Image</Text>
</TouchableOpacity>
.
</Text>
</View>
</View>
</View>
);
}
23 changes: 23 additions & 0 deletions src/screens/notifications/notification-navigator.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import * as React from 'react';

import type { Snap as SnapType } from '@/api';
import { Snap } from '@/screens';

import NotionficationScreen from './notification-screen';

export type NotificationStackParamList = {
Notifications: {};
Snap: { snap: SnapType };
};

const Stack = createNativeStackNavigator<NotificationStackParamList>();

export const NotificationNavigator = () => {
return (
<Stack.Navigator>
<Stack.Screen name="Notifications" component={NotionficationScreen} />
<Stack.Screen name="Snap" component={Snap} />
</Stack.Navigator>
);
};
22 changes: 22 additions & 0 deletions src/screens/notifications/notification-screen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import React from 'react';

import { FocusAwareStatusBar, View } from '@/ui';

import NotificationView from './notification-view';

const NotionficationScreen = () => {
return (
<>
<FocusAwareStatusBar />
<View>
<NotificationView />
</View>
{/* <View>
<Text>Mentions</Text>
<MentionScreen />
</View> */}
</>
);
};

export default NotionficationScreen;
Loading

0 comments on commit 6882ea3

Please sign in to comment.