Skip to content

Commit

Permalink
ft(#83)-real time notifications (#95)
Browse files Browse the repository at this point in the history
  • Loading branch information
aimeudoxie authored Nov 15, 2024
1 parent 3d57b3e commit 3562af1
Show file tree
Hide file tree
Showing 8 changed files with 497 additions and 92 deletions.
1 change: 1 addition & 0 deletions app/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import 'react-native-reanimated';
import { ToastProvider } from 'react-native-toast-notifications';
export { ErrorBoundary } from 'expo-router';
import '../internationalization/index';
import { NotificationProvider } from '@/hooks/useNotification';

export const unstable_settings = {
initialRouteName: '(onboarding)',
Expand Down
110 changes: 66 additions & 44 deletions app/dashboard/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,22 @@ import {
import Sidebar from '@/components/sidebar';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { Slot, useRouter } from 'expo-router';
import { useEffect, useState } from 'react';
import { useContext, useEffect, useState } from 'react';
import {
KeyboardAvoidingView,
Platform,
ScrollView,
TouchableOpacity,
View,
useColorScheme,
Text,
} from 'react-native';
import { useSafeAreaInsets } from 'react-native-safe-area-context';
import { SvgXml } from 'react-native-svg';
import UserProvider from '@/hooks/useAuth';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
import { NotificationProvider, NotificationContext } from '@/hooks/useNotification';
import ProfileDropdown from '@/components/ProfileDropdown';

export type ProfileType = {
firstName: string;
Expand Down Expand Up @@ -55,16 +58,14 @@ export type ProfileType = {
};
};

import ProfileDropdown from '@/components/ProfileDropdown';
export default function AuthLayout() {
export default function DashboardLayout() {
const router = useRouter();
const insets = useSafeAreaInsets();
const [isSidebarOpen, setIsSidebarOpen] = useState<boolean>(false);
const colorScheme = useColorScheme();
const [authToken, setAuthToken] = useState<string | null>(null);
const [user, setUser] = useState(null);
const toggleSidebar = () => setIsSidebarOpen(!isSidebarOpen);

useEffect(() => {
(async function () {
const cachedToken = await AsyncStorage.getItem('authToken');
Expand All @@ -78,8 +79,12 @@ export default function AuthLayout() {
})();
}, [authToken]);

if (!authToken) {
return null; // or a loading spinner
}

return (

<NotificationProvider>
<KeyboardAvoidingView
behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
style={{
Expand All @@ -93,53 +98,70 @@ export default function AuthLayout() {
className="bg-primary-light dark:bg-primary-dark"
>
<GestureHandlerRootView style={{ flex: 1 }}>
<View className={`bg-primary-light dark:bg-primary-dark h-full`}>
<View className="w-full h-[60px] relative bg-primary-light dark:bg-primary-dark flex justify-center px-3 ">
<View className="flex-row justify-between">
<View className="flex-row items-center">
<TouchableOpacity onPress={toggleSidebar}>
<SvgXml xml={menu} width={40} height={40} />
</TouchableOpacity>
<SvgXml
xml={colorScheme === 'dark' ? darkLogoIcon : lightLogoIcon}
width={110}
height={40}
/>
</View>

<UserProvider>
<View className="flex-row gap-5">
<TouchableOpacity
onPress={() => router.push('/dashboard/trainee/notifications' as any)}
>
<View className={`bg-primary-light dark:bg-primary-dark h-full`}>
<View className="w-full h-[60px] relative bg-primary-light dark:bg-primary-dark flex justify-center px-3 ">
<View className="flex-row justify-between">
<View className="flex-row items-center">
<TouchableOpacity onPress={toggleSidebar}>
<SvgXml xml={menu} width={40} height={40} />
</TouchableOpacity>
<SvgXml
xml={colorScheme === 'dark' ? darkNotifyIcon : lightNotifyIcon}
width={25}
xml={colorScheme === 'dark' ? darkLogoIcon : lightLogoIcon}
width={110}
height={40}
/>
</TouchableOpacity>
<ProfileDropdown />
</View>

<UserProvider>
<NotificationContent />
</UserProvider>
</View>
</UserProvider>
</View>
<ScrollView
contentContainerClassName="px-5 py-3"
contentContainerStyle={{ flexGrow: 1 }}
keyboardShouldPersistTaps="handled"
showsVerticalScrollIndicator={false}
>
<Slot />
</ScrollView>
</View>
<ScrollView
contentContainerClassName="px-5 py-3"
contentContainerStyle={{ flexGrow: 1 }}
keyboardShouldPersistTaps="handled"
showsVerticalScrollIndicator={false}
>
<Slot />
</ScrollView>
</View>

{isSidebarOpen && (
<View className="absolute top-0 left-0 bottom-0">
<Sidebar onClose={toggleSidebar} />
</View>
)}
{isSidebarOpen && (
<View className="absolute top-0 left-0 bottom-0">
<Sidebar onClose={toggleSidebar} />
</View>
)}
</GestureHandlerRootView>
</KeyboardAvoidingView>

</NotificationProvider>
);
}

function NotificationContent() {
const router = useRouter();
const colorScheme = useColorScheme();
const { unreadCount } = useContext(NotificationContext);

return (
<View className="flex-row gap-5">
<TouchableOpacity
onPress={() => router.push('/dashboard/trainee/notifications' as any)}
>
<SvgXml
xml={colorScheme === 'dark' ? darkNotifyIcon : lightNotifyIcon}
width={25}
height={40}
/>
</TouchableOpacity>
<View className="flex-row items-center">
{unreadCount > 0 && (
<View className="absolute top-0 right-[10] bg-red-500 rounded-full w-5 h-5 flex items-center justify-center">
<Text className="text-white text-xs">{unreadCount}</Text>
</View>
)}
</View>
<ProfileDropdown />
</View>
);
}
Loading

0 comments on commit 3562af1

Please sign in to comment.