Skip to content

Commit

Permalink
feat: conversation screen POC
Browse files Browse the repository at this point in the history
  • Loading branch information
Nicolas Burtey committed Mar 28, 2024
1 parent 0077722 commit baaaf16
Show file tree
Hide file tree
Showing 18 changed files with 807 additions and 21 deletions.
1 change: 1 addition & 0 deletions .storybook/storybook.requires.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ const getStories = () => {
"./app/screens/authentication-screen/authentication-check-screen.stories.tsx": require("../app/screens/authentication-screen/authentication-check-screen.stories.tsx"),
"./app/screens/authentication-screen/authentication-screen.stories.tsx": require("../app/screens/authentication-screen/authentication-screen.stories.tsx"),
"./app/screens/authentication-screen/pin-screen.stories.tsx": require("../app/screens/authentication-screen/pin-screen.stories.tsx"),
"./app/screens/conversation/conversation.stories.tsx": require("../app/screens/conversation/conversation.stories.tsx"),
"./app/screens/conversion-flow/conversion-success-screen.stories.tsx": require("../app/screens/conversion-flow/conversion-success-screen.stories.tsx"),
"./app/screens/earns-map-screen/earns-map-screen.stories.tsx": require("../app/screens/earns-map-screen/earns-map-screen.stories.tsx"),
"./app/screens/earns-screen/earns-quiz.stories.tsx": require("../app/screens/earns-screen/earns-quiz.stories.tsx"),
Expand Down
4 changes: 2 additions & 2 deletions .storybook/storybook.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ import { NotificationsProvider } from "../app/components/notifications"
RNBootSplash.hide({ fade: true })

const StorybookUI = getStorybookUI({
enableWebsockets: true, // for @storybook/react-native-server
enableWebsockets: true,
onDeviceUI: true,
initialSelection: { kind: "Notification Card UI", name: "Default" },
initialSelection: { kind: "Conversation Screen", name: "Default" },
shouldPersistSelection: false,
})

Expand Down
15 changes: 15 additions & 0 deletions app/components/contact-modal/contact-modal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import ReactNativeModal from "react-native-modal"

import { CONTACT_EMAIL_ADDRESS, WHATSAPP_CONTACT_NUMBER } from "@app/config"
import { useI18nContext } from "@app/i18n/i18n-react"
import { RootStackParamList } from "@app/navigation/stack-param-lists"
import { openWhatsApp } from "@app/utils/external"
import { useNavigation } from "@react-navigation/native"
import { StackNavigationProp } from "@react-navigation/stack"
import { Icon, ListItem, makeStyles, useTheme } from "@rneui/themed"

import TelegramOutline from "./telegram.svg"
Expand All @@ -16,6 +19,7 @@ export const SupportChannels = {
StatusPage: "statusPage",
Mattermost: "mattermost",
Faq: "faq",
Chatbot: "chatbot",
} as const

export type SupportChannels = (typeof SupportChannels)[keyof typeof SupportChannels]
Expand Down Expand Up @@ -44,7 +48,18 @@ const ContactModal: React.FC<Props> = ({
theme: { colors },
} = useTheme()

const { navigate } = useNavigation<StackNavigationProp<RootStackParamList>>()

const contactOptionList = [
{
id: SupportChannels.Chatbot,
name: LL.support.chatbot(),
icon: <Icon name={"chatbubbles-outline"} type="ionicon" />,
action: () => {
navigate("chatbot")
toggleModal()
},
},
{
id: SupportChannels.StatusPage,
name: LL.support.statusPage(),
Expand Down
31 changes: 31 additions & 0 deletions app/graphql/generated.gql
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,23 @@ mutation quizClaim($input: QuizClaimInput!) {
}
}

mutation supportChatMessageAdd($input: SupportChatMessageAddInput!) {
supportChatMessageAdd(input: $input) {
errors {
message
__typename
}
supportMessage {
id
message
role
timestamp
__typename
}
__typename
}
}

mutation userContactUpdateAlias($input: UserContactUpdateAliasInput!) {
userContactUpdateAlias(input: $input) {
errors {
Expand Down Expand Up @@ -1458,6 +1475,20 @@ query settingsScreen {
}
}

query supportChat {
me {
id
supportChat {
id
message
role
timestamp
__typename
}
__typename
}
}

query supportedCountries {
globals {
supportedCountries {
Expand Down
149 changes: 149 additions & 0 deletions app/graphql/generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1034,6 +1034,7 @@ export type Mutation = {
readonly onChainUsdPaymentSendAsBtcDenominated: PaymentSendPayload;
readonly onboardingFlowStart: OnboardingFlowStartResult;
readonly quizClaim: QuizClaimPayload;
readonly supportChatMessageAdd: SupportChatMessageAddPayload;
/** @deprecated will be moved to AccountContact */
readonly userContactUpdateAlias: UserContactUpdateAliasPayload;
readonly userEmailDelete: UserEmailDeletePayload;
Expand Down Expand Up @@ -1259,6 +1260,11 @@ export type MutationQuizClaimArgs = {
};


export type MutationSupportChatMessageAddArgs = {
input: SupportChatMessageAddInput;
};


export type MutationUserContactUpdateAliasArgs = {
input: UserContactUpdateAliasInput;
};
Expand Down Expand Up @@ -1808,6 +1814,30 @@ export type SuccessPayload = {
readonly success?: Maybe<Scalars['Boolean']['output']>;
};

export type SupportChatMessageAddInput = {
readonly message: Scalars['String']['input'];
};

export type SupportChatMessageAddPayload = {
readonly __typename: 'SupportChatMessageAddPayload';
readonly errors: ReadonlyArray<Error>;
readonly supportMessage?: Maybe<ReadonlyArray<Maybe<SupportMessage>>>;
};

export type SupportMessage = {
readonly __typename: 'SupportMessage';
readonly id: Scalars['ID']['output'];
readonly message: Scalars['String']['output'];
readonly role: SupportRole;
readonly timestamp: Scalars['Timestamp']['output'];
};

export const SupportRole = {
Assistant: 'ASSISTANT',
User: 'USER'
} as const;

export type SupportRole = typeof SupportRole[keyof typeof SupportRole];
/**
* Give details about an individual transaction.
* Galoy have a smart routing system which is automatically
Expand Down Expand Up @@ -1992,6 +2022,7 @@ export type User = {
readonly language: Scalars['Language']['output'];
/** Phone number with international calling code. */
readonly phone?: Maybe<Scalars['Phone']['output']>;
readonly supportChat: ReadonlyArray<SupportMessage>;
/** Whether TOTP is enabled for this user. */
readonly totpEnabled: Scalars['Boolean']['output'];
/**
Expand Down Expand Up @@ -2418,6 +2449,18 @@ export type UserLogoutMutationVariables = Exact<{

export type UserLogoutMutation = { readonly __typename: 'Mutation', readonly userLogout: { readonly __typename: 'SuccessPayload', readonly success?: boolean | null } };

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


export type SupportChatQuery = { readonly __typename: 'Query', readonly me?: { readonly __typename: 'User', readonly id: string, readonly supportChat: ReadonlyArray<{ readonly __typename: 'SupportMessage', readonly id: string, readonly message: string, readonly role: SupportRole, readonly timestamp: number }> } | null };

export type SupportChatMessageAddMutationVariables = Exact<{
input: SupportChatMessageAddInput;
}>;


export type SupportChatMessageAddMutation = { readonly __typename: 'Mutation', readonly supportChatMessageAdd: { readonly __typename: 'SupportChatMessageAddPayload', readonly errors: ReadonlyArray<{ readonly __typename: 'GraphQLApplicationError', readonly message: string }>, readonly supportMessage?: ReadonlyArray<{ readonly __typename: 'SupportMessage', readonly id: string, readonly message: string, readonly role: SupportRole, readonly timestamp: number } | null> | null } };

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


Expand Down Expand Up @@ -3926,6 +3969,87 @@ export function useUserLogoutMutation(baseOptions?: Apollo.MutationHookOptions<U
export type UserLogoutMutationHookResult = ReturnType<typeof useUserLogoutMutation>;
export type UserLogoutMutationResult = Apollo.MutationResult<UserLogoutMutation>;
export type UserLogoutMutationOptions = Apollo.BaseMutationOptions<UserLogoutMutation, UserLogoutMutationVariables>;
export const SupportChatDocument = gql`
query supportChat {
me {
id
supportChat {
id
message
role
timestamp
}
}
}
`;

/**
* __useSupportChatQuery__
*
* To run a query within a React component, call `useSupportChatQuery` and pass it any options that fit your needs.
* When your component renders, `useSupportChatQuery` 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 } = useSupportChatQuery({
* variables: {
* },
* });
*/
export function useSupportChatQuery(baseOptions?: Apollo.QueryHookOptions<SupportChatQuery, SupportChatQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useQuery<SupportChatQuery, SupportChatQueryVariables>(SupportChatDocument, options);
}
export function useSupportChatLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<SupportChatQuery, SupportChatQueryVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useLazyQuery<SupportChatQuery, SupportChatQueryVariables>(SupportChatDocument, options);
}
export type SupportChatQueryHookResult = ReturnType<typeof useSupportChatQuery>;
export type SupportChatLazyQueryHookResult = ReturnType<typeof useSupportChatLazyQuery>;
export type SupportChatQueryResult = Apollo.QueryResult<SupportChatQuery, SupportChatQueryVariables>;
export const SupportChatMessageAddDocument = gql`
mutation supportChatMessageAdd($input: SupportChatMessageAddInput!) {
supportChatMessageAdd(input: $input) {
errors {
message
}
supportMessage {
id
message
role
timestamp
}
}
}
`;
export type SupportChatMessageAddMutationFn = Apollo.MutationFunction<SupportChatMessageAddMutation, SupportChatMessageAddMutationVariables>;

/**
* __useSupportChatMessageAddMutation__
*
* To run a mutation, you first call `useSupportChatMessageAddMutation` within a React component and pass it any options that fit your needs.
* When your component renders, `useSupportChatMessageAddMutation` 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 [supportChatMessageAddMutation, { data, loading, error }] = useSupportChatMessageAddMutation({
* variables: {
* input: // value for 'input'
* },
* });
*/
export function useSupportChatMessageAddMutation(baseOptions?: Apollo.MutationHookOptions<SupportChatMessageAddMutation, SupportChatMessageAddMutationVariables>) {
const options = {...defaultOptions, ...baseOptions}
return Apollo.useMutation<SupportChatMessageAddMutation, SupportChatMessageAddMutationVariables>(SupportChatMessageAddDocument, options);
}
export type SupportChatMessageAddMutationHookResult = ReturnType<typeof useSupportChatMessageAddMutation>;
export type SupportChatMessageAddMutationResult = Apollo.MutationResult<SupportChatMessageAddMutation>;
export type SupportChatMessageAddMutationOptions = Apollo.BaseMutationOptions<SupportChatMessageAddMutation, SupportChatMessageAddMutationVariables>;
export const ConversionScreenDocument = gql`
query conversionScreen {
me {
Expand Down Expand Up @@ -7403,6 +7527,10 @@ export type ResolversTypes = {
SignedDisplayMajorAmount: ResolverTypeWrapper<Scalars['SignedDisplayMajorAmount']['output']>;
Subscription: ResolverTypeWrapper<{}>;
SuccessPayload: ResolverTypeWrapper<SuccessPayload>;
SupportChatMessageAddInput: SupportChatMessageAddInput;
SupportChatMessageAddPayload: ResolverTypeWrapper<SupportChatMessageAddPayload>;
SupportMessage: ResolverTypeWrapper<SupportMessage>;
SupportRole: SupportRole;
Timestamp: ResolverTypeWrapper<Scalars['Timestamp']['output']>;
TotpCode: ResolverTypeWrapper<Scalars['TotpCode']['output']>;
TotpRegistrationId: ResolverTypeWrapper<Scalars['TotpRegistrationId']['output']>;
Expand Down Expand Up @@ -7616,6 +7744,9 @@ export type ResolversParentTypes = {
SignedDisplayMajorAmount: Scalars['SignedDisplayMajorAmount']['output'];
Subscription: {};
SuccessPayload: SuccessPayload;
SupportChatMessageAddInput: SupportChatMessageAddInput;
SupportChatMessageAddPayload: SupportChatMessageAddPayload;
SupportMessage: SupportMessage;
Timestamp: Scalars['Timestamp']['output'];
TotpCode: Scalars['TotpCode']['output'];
TotpRegistrationId: Scalars['TotpRegistrationId']['output'];
Expand Down Expand Up @@ -8180,6 +8311,7 @@ export type MutationResolvers<ContextType = any, ParentType extends ResolversPar
onChainUsdPaymentSendAsBtcDenominated?: Resolver<ResolversTypes['PaymentSendPayload'], ParentType, ContextType, RequireFields<MutationOnChainUsdPaymentSendAsBtcDenominatedArgs, 'input'>>;
onboardingFlowStart?: Resolver<ResolversTypes['OnboardingFlowStartResult'], ParentType, ContextType, RequireFields<MutationOnboardingFlowStartArgs, 'input'>>;
quizClaim?: Resolver<ResolversTypes['QuizClaimPayload'], ParentType, ContextType, RequireFields<MutationQuizClaimArgs, 'input'>>;
supportChatMessageAdd?: Resolver<ResolversTypes['SupportChatMessageAddPayload'], ParentType, ContextType, RequireFields<MutationSupportChatMessageAddArgs, 'input'>>;
userContactUpdateAlias?: Resolver<ResolversTypes['UserContactUpdateAliasPayload'], ParentType, ContextType, RequireFields<MutationUserContactUpdateAliasArgs, 'input'>>;
userEmailDelete?: Resolver<ResolversTypes['UserEmailDeletePayload'], ParentType, ContextType>;
userEmailRegistrationInitiate?: Resolver<ResolversTypes['UserEmailRegistrationInitiatePayload'], ParentType, ContextType, RequireFields<MutationUserEmailRegistrationInitiateArgs, 'input'>>;
Expand Down Expand Up @@ -8487,6 +8619,20 @@ export type SuccessPayloadResolvers<ContextType = any, ParentType extends Resolv
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};

export type SupportChatMessageAddPayloadResolvers<ContextType = any, ParentType extends ResolversParentTypes['SupportChatMessageAddPayload'] = ResolversParentTypes['SupportChatMessageAddPayload']> = {
errors?: Resolver<ReadonlyArray<ResolversTypes['Error']>, ParentType, ContextType>;
supportMessage?: Resolver<Maybe<ReadonlyArray<Maybe<ResolversTypes['SupportMessage']>>>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};

export type SupportMessageResolvers<ContextType = any, ParentType extends ResolversParentTypes['SupportMessage'] = ResolversParentTypes['SupportMessage']> = {
id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>;
message?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
role?: Resolver<ResolversTypes['SupportRole'], ParentType, ContextType>;
timestamp?: Resolver<ResolversTypes['Timestamp'], ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
};

export interface TimestampScalarConfig extends GraphQLScalarTypeConfig<ResolversTypes['Timestamp'], any> {
name: 'Timestamp';
}
Expand Down Expand Up @@ -8568,6 +8714,7 @@ export type UserResolvers<ContextType = any, ParentType extends ResolversParentT
id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>;
language?: Resolver<ResolversTypes['Language'], ParentType, ContextType>;
phone?: Resolver<Maybe<ResolversTypes['Phone']>, ParentType, ContextType>;
supportChat?: Resolver<ReadonlyArray<ResolversTypes['SupportMessage']>, ParentType, ContextType>;
totpEnabled?: Resolver<ResolversTypes['Boolean'], ParentType, ContextType>;
username?: Resolver<Maybe<ResolversTypes['Username']>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
Expand Down Expand Up @@ -8808,6 +8955,8 @@ export type Resolvers<ContextType = any> = {
SignedDisplayMajorAmount?: GraphQLScalarType;
Subscription?: SubscriptionResolvers<ContextType>;
SuccessPayload?: SuccessPayloadResolvers<ContextType>;
SupportChatMessageAddPayload?: SupportChatMessageAddPayloadResolvers<ContextType>;
SupportMessage?: SupportMessageResolvers<ContextType>;
Timestamp?: GraphQLScalarType;
TotpCode?: GraphQLScalarType;
TotpRegistrationId?: GraphQLScalarType;
Expand Down
1 change: 1 addition & 0 deletions app/i18n/en/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2705,6 +2705,7 @@ const en: BaseTranslation = {
faq: "FAQ",
enjoyingApp: "Enjoying the app?",
statusPage: "Status Page",
chatbot: "Chatbot",
telegram: "Telegram",
mattermost: "Mattermost",
thankYouText: "Thank you for the feedback, would you like to suggest an improvement?",
Expand Down
8 changes: 8 additions & 0 deletions app/i18n/i18n-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8459,6 +8459,10 @@ type RootTranslation = {
* S​t​a​t​u​s​ ​P​a​g​e
*/
statusPage: string
/**
* C​h​a​t​b​o​t
*/
chatbot: string
/**
* T​e​l​e​g​r​a​m
*/
Expand Down Expand Up @@ -17292,6 +17296,10 @@ export type TranslationFunctions = {
* Status Page
*/
statusPage: () => LocalizedString
/**
* Chatbot
*/
chatbot: () => LocalizedString
/**
* Telegram
*/
Expand Down
1 change: 1 addition & 0 deletions app/i18n/raw-i18n/source/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -2599,6 +2599,7 @@
"faq": "FAQ",
"enjoyingApp": "Enjoying the app?",
"statusPage": "Status Page",
"chatbot": "Chatbot",
"telegram": "Telegram",
"mattermost": "Mattermost",
"thankYouText": "Thank you for the feedback, would you like to suggest an improvement?",
Expand Down
8 changes: 8 additions & 0 deletions app/navigation/root-navigator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import LearnIcon from "@app/assets/icons/learn.svg"
import MapIcon from "@app/assets/icons/map.svg"
import { useIsAuthed } from "@app/graphql/is-authed-context"
import { useI18nContext } from "@app/i18n/i18n-react"
import { ConversationScreen } from "@app/screens/conversation/conversation"
import {
ConversionConfirmationScreen,
ConversionDetailsScreen,
Expand Down Expand Up @@ -409,6 +410,13 @@ export const RootStack = () => {
title: LL.FullOnboarding.title(),
}}
/>
<RootNavigator.Screen
name="chatbot"
component={ConversationScreen}
options={{
title: LL.support.chatbot(),
}}
/>
</RootNavigator.Navigator>
)
}
Expand Down
Loading

0 comments on commit baaaf16

Please sign in to comment.