Skip to content

Commit

Permalink
ft(#67): setup in-app notifications
Browse files Browse the repository at this point in the history
  • Loading branch information
fredshema committed Nov 25, 2024
1 parent 544afe7 commit d1d4259
Show file tree
Hide file tree
Showing 72 changed files with 4,772 additions and 7,561 deletions.
48 changes: 28 additions & 20 deletions app.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@
"slug": "devpulse",
"version": "1.0.1",
"orientation": "portrait",
"icon": "./assets/images/icon.png",
"scheme": "devpulse",
"scheme": "pulseapp",
"userInterfaceStyle": "automatic",
"newArchEnabled": false,
"icon": "./assets/images/icon.png",
"ios": {
"supportsTablet": true,
"bundleIdentifier": "com.atlp.pulseapp",
Expand Down Expand Up @@ -35,25 +36,32 @@
}
]
},
"plugins": ["expo-router", "expo-font", "expo-localization", [
"expo-image-picker",
{
"photosPermission": "The app needs access to your photos to let you upload a profile picture."
}
],
[
"expo-splash-screen",
{
"backgroundColor": "#E0E7FF",
"image": "./assets/images/icon.png",
"dark": {
"web": {
"bundler": "metro"
},
"plugins": [
"expo-router",
"expo-font",
"expo-localization",
[
"expo-splash-screen",
{
"backgroundColor": "#E0E7FF",
"image": "./assets/images/icon.png",
"backgroundColor": "#020917"
},
"imageWidth": 128
}
]
],
"dark": {
"image": "./assets/images/icon.png",
"backgroundColor": "#020917"
},
"imageWidth": 128
}
],
[
"expo-image-picker",
{
"photosPermission": "The app needs access to your photos to let you upload a profile picture."
}
]
],
"experiments": {
"typedRoutes": true
},
Expand Down
2 changes: 1 addition & 1 deletion app/+not-found.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export default function NotFoundScreen() {
{t('notFound.title')}
</Text>

<Link href="/" className="mt-12">
<Link href="/(onboarding)" className="mt-12">
<View className="px-6 py-4 rounded-full bg-action-500">
<Text className="text-lg text-white">{t('notFound.goHome')}</Text>
</View>
Expand Down
28 changes: 15 additions & 13 deletions app/_layout.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { useColorScheme } from '@/components/useColorScheme';
import '@/global.css';
import { client } from '@/graphql/client';
import NotificationsProvider from '@/providers/notifications';
import { ApolloProvider } from '@apollo/client';
import { useApolloClientDevTools } from '@dev-plugins/apollo-client';
import {
Inter_400Regular,
Inter_500Medium,
Expand All @@ -15,9 +15,7 @@ import { useFonts } from 'expo-font';
import { Stack } from 'expo-router';
import * as SplashScreen from 'expo-splash-screen';
import { useEffect } from 'react';
import 'react-native-reanimated';
import { ToastProvider } from 'react-native-toast-notifications';
export { ErrorBoundary } from 'expo-router';
import '../internationalization/index';
import { NotificationProvider } from '@/hooks/useNotification';

Expand All @@ -27,6 +25,11 @@ export const unstable_settings = {

SplashScreen.preventAutoHideAsync();

SplashScreen.setOptions({
duration: 1000,
fade: true,
});

export default function RootLayout() {
const [loaded, error] = useFonts({
Inter_400Regular,
Expand Down Expand Up @@ -55,21 +58,20 @@ export default function RootLayout() {

function RootLayoutNav() {
const colorScheme = useColorScheme();
useApolloClientDevTools(client);

return (

<ApolloProvider client={client}>
<ToastProvider placement="top" duration={5000}>
<ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
<Stack screenOptions={{ headerShown: false }}>
<Stack.Screen name="(onboarding)" options={{ headerShown: false }} />
<Stack.Screen name="auth" options={{ headerShown: false }} />
<Stack.Screen name="dashboard" options={{ headerShown: false }} />
</Stack>
</ThemeProvider>
<NotificationsProvider>
<ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
<Stack screenOptions={{ headerShown: false }}>
<Stack.Screen name="(onboarding)" />
<Stack.Screen name="auth" />
<Stack.Screen name="dashboard" />
</Stack>
</ThemeProvider>
</NotificationsProvider>
</ToastProvider>
</ApolloProvider>

);
}
4 changes: 3 additions & 1 deletion app/auth/forgot-password.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,9 @@ export default function ResetPassword() {
keyboardType="email-address"
/>
</View>
{formik.touched.email && formik.errors.email && <Text className="mb-4 text-error-500">{t('forgotPassword.errorEmail')}</Text>}
{formik.touched.email && formik.errors.email && (
<Text className="mb-4 text-error-500">{t('forgotPassword.errorEmail')}</Text>
)}
<TouchableOpacity
testID="submit-button"
onPress={() => formik.handleSubmit()}
Expand Down
44 changes: 12 additions & 32 deletions app/auth/login/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,15 @@ import UserLogin from '@/components/Login/UserLogin';
import { LOGIN_MUTATION, ORG_LOGIN_MUTATION } from '@/graphql/mutations/login.mutation';
import { ApolloError, useApolloClient, useMutation } from '@apollo/client';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { Href, useLocalSearchParams, useRouter } from 'expo-router';
import { useEffect,useState } from 'react';
import { useToast } from 'react-native-toast-notifications';
import {ToastAndroid } from 'react-native';
import { RelativePathString, useLocalSearchParams, useRouter } from 'expo-router';
import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';

class ErrorHandler {
static handleNetworkError() {
ToastAndroid.show('There was a problem contacting the server', ToastAndroid.LONG);
}

static handleInvalidCredentials() {
ToastAndroid.show('Error Invalid credentials',ToastAndroid.LONG);
}

static handleCustomError(message: string | undefined) {
ToastAndroid.show('Error:' + message,ToastAndroid.LONG);
}

static handleGeneralError() {
ToastAndroid.show('Error An unexpected error occurred.',ToastAndroid.LONG);
}
}
import { useToast } from 'react-native-toast-notifications';

export default function SignInOrganization() {
const toast = useToast();
const router = useRouter();
const {t} = useTranslation();
const { t } = useTranslation();
const [orgLoginSuccess, setOrgLoginSuccess] = useState(false);
const [orgLoginMutation] = useMutation(ORG_LOGIN_MUTATION);
const [LoginUser] = useMutation(LOGIN_MUTATION);
Expand Down Expand Up @@ -68,13 +49,13 @@ export default function SignInOrganization() {
setOrgLoginSuccess(true);
},
onError(err: any) {
toast.show(err.message,{
toast.show(err.message, {
type: 'fail',
placement : 'top',
duration : 5000,
animationType : 'slide-in',
placement: 'top',
duration: 5000,
animationType: 'slide-in',
style: { backgroundColor: 'red' },
})
});
},
});
} catch (err: any) {
Expand Down Expand Up @@ -106,9 +87,9 @@ export default function SignInOrganization() {
while (router.canGoBack()) {
router.back();
}

params.redirect
? router.push(`${params.redirect}` as Href<string | object>)
? router.push(`${params.redirect}` as RelativePathString)
: router.push('/dashboard');
return;
} else {
Expand All @@ -117,7 +98,6 @@ export default function SignInOrganization() {
});
return;
}

} else {
await AsyncStorage.setItem('authToken', data.loginUser.token);
router.push('/dashboard');
Expand All @@ -134,7 +114,7 @@ export default function SignInOrganization() {
},
});
} catch (error: any) {
toast.show(t('toasts.auth.generalError') , { type: 'danger' });
toast.show(t('toasts.auth.generalError'), { type: 'danger' });
}
};

Expand Down
9 changes: 2 additions & 7 deletions app/auth/register.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,7 @@ import { useFormik } from 'formik';
import { jwtDecode } from 'jwt-decode';
import { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import {
ActivityIndicator,
TextInput,
TouchableOpacity,
useColorScheme,
} from 'react-native';
import { ActivityIndicator, TextInput, TouchableOpacity, useColorScheme } from 'react-native';
import DropDownPicker from 'react-native-dropdown-picker';
import { SvgXml } from 'react-native-svg';
import { useToast } from 'react-native-toast-notifications';
Expand Down Expand Up @@ -316,7 +311,7 @@ export default function RegisterForm() {
<TouchableOpacity
onPress={() => {
if (!TCAccepted) {
toast.show(t('toasts.auth.acceptTerms'), {type:"Warning"});
toast.show(t('toasts.auth.acceptTerms'), { type: 'Warning' });
return;
}
formik.handleSubmit();
Expand Down
2 changes: 1 addition & 1 deletion app/auth/reset-password.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ type FormValues = {

const SetNewPassword = () => {
const { token } = useLocalSearchParams();
const {t} = useTranslation();
const { t } = useTranslation();
const originalToken = Array.isArray(token) ? token.join('.') : token?.replace(/\*/g, '.');
const [securePassword, setSecurePassword] = useState(true);
const [secureConfirmPassword, setSecureConfirmPassword] = useState(true);
Expand Down
22 changes: 13 additions & 9 deletions app/dashboard/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,31 @@ import {
lightNotifyIcon,
menu,
} from '@/assets/Icons/dashboard/Icons';
import ProfileAvatar from '@/components/ProfileAvatar';
import ProfileSidebar from '@/components/ProfileSidebar';
import Sidebar from '@/components/sidebar';
import { GET_PROFILE } from '@/graphql/queries/user';
import UserProvider from '@/hooks/useAuth';
import { NotificationContext, NotificationProvider } from '@/hooks/useNotification';
import { useQuery } from '@apollo/client';
import AsyncStorage from '@react-native-async-storage/async-storage';
import { Slot, useRouter } from 'expo-router';
import { useContext, useEffect, useState } from 'react';
import {
KeyboardAvoidingView,
Platform,
ScrollView,
Text,
TouchableOpacity,
View,
useColorScheme,
Text,
} from 'react-native';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
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 ProfileAvatar from '@/components/ProfileAvatar';
import { GET_PROFILE } from '@/graphql/queries/user';
import { useQuery } from '@apollo/client';
import ProfileSidebar from '@/components/ProfileSidebar';

export type ProfileType = {
id: string;
firstName: string;
lastName: string;
name: string;
Expand All @@ -42,10 +43,13 @@ export type ProfileType = {
githubUsername?: string;
resume?: string;
user: {
id: string;
organizations: string[];
email: string;
role: string;
pushNotificationTokens: string[];
team: {
id: string;
name: string;
cohort: {
name: string;
Expand Down Expand Up @@ -97,7 +101,7 @@ export default function DashboardLayout() {
}, []);

if (!authToken) {
return null;
return null;
}

const toggleSidebar = () => setIsSidebarOpen((prev) => !prev);
Expand Down
18 changes: 9 additions & 9 deletions app/dashboard/calendar/index.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { ScrollView } from 'react-native'
import { SafeAreaView } from 'react-native-safe-area-context'
import CalendarBody from '@/components/calendar/CalendarBody'
import { ScrollView } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import CalendarBody from '@/components/calendar/CalendarBody';

const Calendar = () => {
return (
<SafeAreaView>
<ScrollView>
<CalendarBody/>
</ScrollView>
<ScrollView>
<CalendarBody />
</ScrollView>
</SafeAreaView>
)
}
);
};

export default Calendar
export default Calendar;
6 changes: 3 additions & 3 deletions app/dashboard/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import React, { PropsWithChildren, useState } from 'react';
import FeedbackModal from '@/components/feedbackModel';
import PerformanceScores from '@/components/performanceStats';
import { PropsWithChildren, useState } from 'react';
import { StyleSheet, Text, useColorScheme, View } from 'react-native';
import TraineeRatings from '../../components/sprintRatings';
import PerformanceScores from '@/components/perfomanceStats';
import FeedbackModal from '@/components/feedbackModel';

export const CustomText = ({ children }: PropsWithChildren) => <Text>{children}</Text>;

Expand Down
Loading

0 comments on commit d1d4259

Please sign in to comment.