Skip to content

Commit

Permalink
Merge pull request #89 from bambu-group-03/feat/mentions
Browse files Browse the repository at this point in the history
Feat/mentions
  • Loading branch information
LuisParedes1 committed Nov 23, 2023
2 parents 98790db + 2c9c897 commit 3e8fcbb
Show file tree
Hide file tree
Showing 10 changed files with 334 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>

Check warning on line 47 in src/screens/notifications/mentions-view.tsx

View workflow job for this annotation

GitHub Actions / Lint TS (eslint, prettier)

'React' must be in scope when using JSX
<Text> Error Loading data </Text>

Check warning on line 48 in src/screens/notifications/mentions-view.tsx

View workflow job for this annotation

GitHub Actions / Lint TS (eslint, prettier)

'React' must be in scope when using JSX
</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

Check warning on line 61 in src/screens/notifications/mentions-view.tsx

View workflow job for this annotation

GitHub Actions / Lint TS (eslint, prettier)

'React' must be in scope when using JSX
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>

Check warning on line 83 in src/screens/notifications/mentions-view.tsx

View workflow job for this annotation

GitHub Actions / Lint TS (eslint, prettier)

'React' must be in scope when using JSX
<FocusAwareStatusBar />

Check warning on line 84 in src/screens/notifications/mentions-view.tsx

View workflow job for this annotation

GitHub Actions / Lint TS (eslint, prettier)

'React' must be in scope when using JSX

<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;
39 changes: 39 additions & 0 deletions src/screens/notifications/notification-card.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { Text, TouchableOpacity, View } from 'react-native';

import { Image } from '@/ui';

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

export default function NotificationCard({
notification,
}: {
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: notification?.user?.profile_photo_id
? notification?.user?.profile_photo_id
: '',
}}
/>
<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>
);
};
24 changes: 24 additions & 0 deletions src/screens/notifications/notification-screen.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from 'react';

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

import MentionScreen from './mentions-view';
import NotificationView from './notification-view';

const NotionficationScreen = () => {
return (
<>
<FocusAwareStatusBar />
<Text className="text-center text-2xl font-bold">Notifications</Text>
<View className="mt-1 py-3 text-center">
<NotificationView />
</View>
<View className="mt-1 border-t border-slate-200 py-3 text-center">
<Text className="text-center text-2xl font-bold">Mentions</Text>
<MentionScreen />
</View>
</>
);
};

export default NotionficationScreen;
86 changes: 86 additions & 0 deletions src/screens/notifications/notification-view.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import { useCallback, useEffect, useState } from 'react';
import { FlatList, RefreshControl, Text, View } from 'react-native';

import { useNotifications } from '@/api';
import { getUserState } from '@/core';
import { EmptyList, FocusAwareStatusBar } from '@/ui';

import NotificationCard from './notification-card';
import type { Notification } from './types';

const INCREMENT_RENDER = 10;
const INITIAL_RENDER = 20;

export default function NotificationView() {
const currentUser = getUserState();

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

const [notifications, setNotifications] = useState<any>([]);

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

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 renderItem = ({
item,
index,
}: {
item: Notification;
index: number;
}) => {
if (index < renderCount) {
return <NotificationCard notification={item} />;
}
return null;
};

const handleEndReached = () => {
if (renderCount < (data ? data.length : 0)) {
setRenderCount(renderCount + INCREMENT_RENDER);
}
};

return (
<View>
<FocusAwareStatusBar />

<FlatList
data={notifications}
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>
);
}
11 changes: 11 additions & 0 deletions src/screens/notifications/types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type { UserType } from '@/core/auth/utils';

export type Notification = {
id: number;
user_id: number;
type: string;
content: string;
created_at: string;
updated_at: string;
user: UserType;
};

0 comments on commit 3e8fcbb

Please sign in to comment.