Skip to content

Commit

Permalink
feat: notifications history
Browse files Browse the repository at this point in the history
  • Loading branch information
sandipndev committed Apr 29, 2024
1 parent 7db2d6a commit 6ddc20c
Show file tree
Hide file tree
Showing 12 changed files with 382 additions and 1 deletion.
35 changes: 35 additions & 0 deletions app/graphql/generated.gql
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,16 @@ fragment TransactionList on TransactionConnection {
__typename
}

mutation StatefulNotificationAcknowledge($input: StatefulNotificationAcknowledgeInput!) {
statefulNotificationAcknowledge(input: $input) {
notification {
acknowledgedAt
__typename
}
__typename
}
}

mutation accountDelete {
accountDelete {
errors {
Expand Down Expand Up @@ -840,6 +850,31 @@ query SettingsScreen {
}
}

query StatefulNotifications($after: String) {
me {
statefulNotifications(first: 10, after: $after) {
nodes {
id
title
body
deepLink
createdAt
acknowledgedAt
__typename
}
pageInfo {
endCursor
hasNextPage
hasPreviousPage
startCursor
__typename
}
__typename
}
__typename
}
}

query accountDefaultWallet($walletCurrency: WalletCurrency, $username: Username!) {
accountDefaultWallet(walletCurrency: $walletCurrency, username: $username) {
id
Expand Down
104 changes: 104 additions & 0 deletions app/graphql/generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2615,6 +2615,20 @@ export type BusinessMapMarkersQueryVariables = Exact<{ [key: string]: never; }>;

export type BusinessMapMarkersQuery = { readonly __typename: 'Query', readonly businessMapMarkers: ReadonlyArray<{ readonly __typename: 'MapMarker', readonly username: string, readonly mapInfo: { readonly __typename: 'MapInfo', readonly title: string, readonly coordinates: { readonly __typename: 'Coordinates', readonly longitude: number, readonly latitude: number } } }> };

export type StatefulNotificationsQueryVariables = Exact<{
after?: InputMaybe<Scalars['String']['input']>;
}>;


export type StatefulNotificationsQuery = { readonly __typename: 'Query', readonly me?: { readonly __typename: 'User', readonly statefulNotifications: { readonly __typename: 'StatefulNotificationConnection', readonly nodes: ReadonlyArray<{ readonly __typename: 'StatefulNotification', readonly id: string, readonly title: string, readonly body: string, readonly deepLink?: string | null, readonly createdAt: number, readonly acknowledgedAt?: number | null }>, readonly pageInfo: { readonly __typename: 'PageInfo', readonly endCursor?: string | null, readonly hasNextPage: boolean, readonly hasPreviousPage: boolean, readonly startCursor?: string | null } } } | null };

export type StatefulNotificationAcknowledgeMutationVariables = Exact<{
input: StatefulNotificationAcknowledgeInput;
}>;


export type StatefulNotificationAcknowledgeMutation = { readonly __typename: 'Mutation', readonly statefulNotificationAcknowledge: { readonly __typename: 'StatefulNotificationAcknowledgePayload', readonly notification: { readonly __typename: 'StatefulNotification', readonly acknowledgedAt?: number | null } } };

export type CirclesQueryVariables = Exact<{ [key: string]: never; }>;


Expand Down Expand Up @@ -4790,6 +4804,96 @@ export type BusinessMapMarkersQueryHookResult = ReturnType<typeof useBusinessMap
export type BusinessMapMarkersLazyQueryHookResult = ReturnType<typeof useBusinessMapMarkersLazyQuery>;
export type BusinessMapMarkersSuspenseQueryHookResult = ReturnType<typeof useBusinessMapMarkersSuspenseQuery>;
export type BusinessMapMarkersQueryResult = Apollo.QueryResult<BusinessMapMarkersQuery, BusinessMapMarkersQueryVariables>;
export const StatefulNotificationsDocument = gql`
query StatefulNotifications($after: String) {
me {
statefulNotifications(first: 10, after: $after) {
nodes {
id
title
body
deepLink
createdAt
acknowledgedAt
}
pageInfo {
endCursor
hasNextPage
hasPreviousPage
startCursor
}
}
}
}
`;

/**
* __useStatefulNotificationsQuery__
*
* To run a query within a React component, call `useStatefulNotificationsQuery` and pass it any options that fit your needs.
* When your component renders, `useStatefulNotificationsQuery` returns an object from Apollo Client that contains loading, error, and data properties
* you can use to render your UI.
*
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
*
* @example
* const { data, loading, error } = useStatefulNotificationsQuery({
* variables: {
* after: // value for 'after'
* },
* });
*/
export function useStatefulNotificationsQuery(baseOptions?: Apollo.QueryHookOptions<StatefulNotificationsQuery, StatefulNotificationsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<StatefulNotificationsQuery, StatefulNotificationsQueryVariables>(StatefulNotificationsDocument, options);
}
export function useStatefulNotificationsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<StatefulNotificationsQuery, StatefulNotificationsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<StatefulNotificationsQuery, StatefulNotificationsQueryVariables>(StatefulNotificationsDocument, options);
}
export function useStatefulNotificationsSuspenseQuery(baseOptions?: Apollo.SuspenseQueryHookOptions<StatefulNotificationsQuery, StatefulNotificationsQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useSuspenseQuery<StatefulNotificationsQuery, StatefulNotificationsQueryVariables>(StatefulNotificationsDocument, options);
}
export type StatefulNotificationsQueryHookResult = ReturnType<typeof useStatefulNotificationsQuery>;
export type StatefulNotificationsLazyQueryHookResult = ReturnType<typeof useStatefulNotificationsLazyQuery>;
export type StatefulNotificationsSuspenseQueryHookResult = ReturnType<typeof useStatefulNotificationsSuspenseQuery>;
export type StatefulNotificationsQueryResult = Apollo.QueryResult<StatefulNotificationsQuery, StatefulNotificationsQueryVariables>;
export const StatefulNotificationAcknowledgeDocument = gql`
mutation StatefulNotificationAcknowledge($input: StatefulNotificationAcknowledgeInput!) {
statefulNotificationAcknowledge(input: $input) {
notification {
acknowledgedAt
}
}
}
`;
export type StatefulNotificationAcknowledgeMutationFn = Apollo.MutationFunction<StatefulNotificationAcknowledgeMutation, StatefulNotificationAcknowledgeMutationVariables>;

/**
* __useStatefulNotificationAcknowledgeMutation__
*
* To run a mutation, you first call `useStatefulNotificationAcknowledgeMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useStatefulNotificationAcknowledgeMutation` returns a tuple that includes:
* - A mutate function that you can call at any time to execute the mutation
* - An object with fields that represent the current status of the mutation's execution
*
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
*
* @example
* const [statefulNotificationAcknowledgeMutation, { data, loading, error }] = useStatefulNotificationAcknowledgeMutation({
* variables: {
* input: // value for 'input'
* },
* });
*/
export function useStatefulNotificationAcknowledgeMutation(baseOptions?: Apollo.MutationHookOptions<StatefulNotificationAcknowledgeMutation, StatefulNotificationAcknowledgeMutationVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useMutation<StatefulNotificationAcknowledgeMutation, StatefulNotificationAcknowledgeMutationVariables>(StatefulNotificationAcknowledgeDocument, options);
}
export type StatefulNotificationAcknowledgeMutationHookResult = ReturnType<typeof useStatefulNotificationAcknowledgeMutation>;
export type StatefulNotificationAcknowledgeMutationResult = Apollo.MutationResult<StatefulNotificationAcknowledgeMutation>;
export type StatefulNotificationAcknowledgeMutationOptions = Apollo.BaseMutationOptions<StatefulNotificationAcknowledgeMutation, StatefulNotificationAcknowledgeMutationVariables>;
export const CirclesDocument = gql`
query Circles {
me {
Expand Down
4 changes: 4 additions & 0 deletions app/i18n/en/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2893,6 +2893,10 @@ const en: BaseTranslation = {
PROCESSING: "Processing",
REVIEW: "Review",
},
NotificationHistory: {
title: "Notifications",
noNotifications: "You don't have any notifications right now"
}
}

export default en
20 changes: 20 additions & 0 deletions app/i18n/i18n-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9121,6 +9121,16 @@ type RootTranslation = {
*/
REVIEW: string
}
NotificationHistory: {
/**
* N​o​t​i​f​i​c​a​t​i​o​n​s
*/
title: string
/**
* Y​o​u​ ​d​o​n​'​t​ ​h​a​v​e​ ​a​n​y​ ​n​o​t​i​f​i​c​a​t​i​o​n​s​ ​r​i​g​h​t​ ​n​o​w
*/
noNotifications: string
}
}

export type TranslationFunctions = {
Expand Down Expand Up @@ -18125,6 +18135,16 @@ export type TranslationFunctions = {
*/
REVIEW: () => LocalizedString
}
NotificationHistory: {
/**
* Notifications
*/
title: () => LocalizedString
/**
* You don't have any notifications right now
*/
noNotifications: () => LocalizedString
}
}

export type Formatters = {
Expand Down
4 changes: 4 additions & 0 deletions app/i18n/raw-i18n/source/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -2773,5 +2773,9 @@
"ERROR": "Error",
"PROCESSING": "Processing",
"REVIEW": "Review"
},
"NotificationHistory": {
"title": "Notifications",
"noNotifications": "You don't have any notifications right now"
}
}
6 changes: 6 additions & 0 deletions app/navigation/root-navigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ import { LanguageScreen } from "../screens/settings-screen/language-screen"
import { SecurityScreen } from "../screens/settings-screen/security-screen"
import { TransactionDetailScreen } from "../screens/transaction-detail-screen"
import { TransactionHistoryScreen } from "../screens/transaction-history/transaction-history-screen"
import { NotificationHistoryScreen } from "@app/screens/notification-history-screen/notification-history-screen"
import {
PeopleStackParamList,
PhoneValidationStackParamList,
Expand Down Expand Up @@ -425,6 +426,11 @@ export const RootStack = () => {
title: LL.support.chatbot(),
}}
/>
<RootNavigator.Screen
name="notificationHistory"
component={NotificationHistoryScreen}
options={{ title: LL.NotificationHistory.title() }}
/>
</RootNavigator.Navigator>
)
}
Expand Down
1 change: 1 addition & 0 deletions app/navigation/stack-param-lists.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ export type RootStackParamList = {
webView: { url: string; initialTitle?: string }
fullOnboardingFlow: undefined
chatbot: undefined
notificationHistory: undefined
}

export type PeopleStackParamList = {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
import { gql } from "@apollo/client"
import { Screen } from "@app/components/screen"
import { useStatefulNotificationsQuery } from "@app/graphql/generated"
import { useIsAuthed } from "@app/graphql/is-authed-context"
import { useI18nContext } from "@app/i18n/i18n-react"
import { testProps } from "@app/utils/testProps"
import { useIsFocused } from "@react-navigation/native"
import { Text, makeStyles, useTheme } from "@rneui/themed"
import { FlatList, RefreshControl } from "react-native-gesture-handler"
import { Notification } from "./notification"

gql`
query StatefulNotifications($after: String) {
me {
statefulNotifications(first: 10, after: $after) {
nodes {
id
title
body
deepLink
createdAt
acknowledgedAt
}
pageInfo {
endCursor
hasNextPage
hasPreviousPage
startCursor
}
}
}
}
`

export const NotificationHistoryScreen = () => {
const styles = useStyles()
const {
theme: { colors },
} = useTheme()
const isFocused = useIsFocused()

const { LL } = useI18nContext()

const { data, fetchMore, refetch, loading } = useStatefulNotificationsQuery({
skip: !useIsAuthed(),
})
const notifications = data?.me?.statefulNotifications

const fetchNextNotificationsPage = () => {
const pageInfo = notifications?.pageInfo

if (pageInfo?.hasNextPage) {
fetchMore({
variables: {
after: pageInfo.endCursor,
},
})
}
}

return (
<Screen>
<FlatList
{...testProps("notification-screen")}
contentContainerStyle={styles.scrollViewContainer}
refreshControl={
<RefreshControl
refreshing={loading && isFocused}
onRefresh={refetch}
colors={[colors.primary]} // Android refresh indicator colors
tintColor={colors.primary} // iOS refresh indicator color
/>
}
data={notifications?.nodes}
renderItem={({ item }) => <Notification {...item} />}
onEndReached={fetchNextNotificationsPage}
onEndReachedThreshold={0.5}
onRefresh={refetch}
refreshing={loading}
ListEmptyComponent={
loading ? <></> : <Text>{LL.NotificationHistory.noNotifications()}</Text>
}
></FlatList>
</Screen>
)
}

const useStyles = makeStyles(() => ({
scrollViewContainer: {},
}))
Loading

0 comments on commit 6ddc20c

Please sign in to comment.