mirror of
https://github.com/maybe-finance/maybe.git
synced 2025-08-09 15:35:22 +02:00
feat: remove Intercom usage
This commit is contained in:
parent
d59484a537
commit
361d07cd79
19 changed files with 18 additions and 255 deletions
|
@ -1,28 +1,9 @@
|
||||||
import { useAuth0 } from '@auth0/auth0-react'
|
import { useAuth0 } from '@auth0/auth0-react'
|
||||||
import { useIntercom } from '@maybe-finance/client/shared'
|
|
||||||
import { useRouter } from 'next/router'
|
|
||||||
import { useEffect } from 'react'
|
import { useEffect } from 'react'
|
||||||
import * as Sentry from '@sentry/react'
|
import * as Sentry from '@sentry/react'
|
||||||
|
|
||||||
export default function APM() {
|
export default function APM() {
|
||||||
const { user } = useAuth0()
|
const { user } = useAuth0()
|
||||||
const router = useRouter()
|
|
||||||
const intercom = useIntercom()
|
|
||||||
|
|
||||||
// Boot intercom
|
|
||||||
useEffect(() => {
|
|
||||||
const isBooted = intercom.boot()
|
|
||||||
|
|
||||||
const handleRouteChange = () => {
|
|
||||||
if (isBooted) {
|
|
||||||
intercom.update()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
router.events.on('routeChangeComplete', handleRouteChange)
|
|
||||||
|
|
||||||
return () => router.events.off('routeChangeComplete', handleRouteChange)
|
|
||||||
}, [intercom, router.events])
|
|
||||||
|
|
||||||
// Identify Sentry user
|
// Identify Sentry user
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
|
|
|
@ -48,15 +48,6 @@ export default function Meta() {
|
||||||
href="https://cdn.jsdelivr.net/npm/remixicon@2.5.0/fonts/remixicon.css"
|
href="https://cdn.jsdelivr.net/npm/remixicon@2.5.0/fonts/remixicon.css"
|
||||||
rel="stylesheet"
|
rel="stylesheet"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Intercom */}
|
|
||||||
<script
|
|
||||||
type="text/javascript"
|
|
||||||
dangerouslySetInnerHTML={{
|
|
||||||
__html: `window.INTERCOM_APP_ID='${env.NEXT_PUBLIC_INTERCOM_APP_ID}';(function(){var w=window;var ic=w.Intercom;if(typeof ic==="function"){ic('reattach_activator');ic('update',w.intercomSettings);}else{var d=document;var i=function(){i.c(arguments);};i.q=[];i.c=function(args){i.q.push(args);};w.Intercom=i;var l=function(){var s=d.createElement('script');s.type='text/javascript';s.async=true;s.src='https://widget.intercom.io/widget/' + window.INTERCOM_APP_ID;var x=d.getElementsByTagName('script')[0];x.parentNode.insertBefore(s, x);};if(document.readyState==='complete'){l();}else if(w.attachEvent){w.attachEvent('onload',l);}else{w.addEventListener('load',l,false);}}})();`,
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{/* End Intercom */}
|
|
||||||
</Head>
|
</Head>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ const env = {
|
||||||
process.env.NEXT_PUBLIC_LD_CLIENT_SIDE_ID || 'REPLACE_THIS',
|
process.env.NEXT_PUBLIC_LD_CLIENT_SIDE_ID || 'REPLACE_THIS',
|
||||||
NEXT_PUBLIC_SENTRY_DSN: process.env.NEXT_PUBLIC_SENTRY_DSN,
|
NEXT_PUBLIC_SENTRY_DSN: process.env.NEXT_PUBLIC_SENTRY_DSN,
|
||||||
NEXT_PUBLIC_SENTRY_ENV: process.env.NEXT_PUBLIC_SENTRY_ENV,
|
NEXT_PUBLIC_SENTRY_ENV: process.env.NEXT_PUBLIC_SENTRY_ENV,
|
||||||
NEXT_PUBLIC_INTERCOM_APP_ID: process.env.NEXT_PUBLIC_INTERCOM_APP_ID || 'REPLACE_THIS',
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default env
|
export default env
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { BrowserUtil, usePlaid } from '@maybe-finance/client/shared'
|
import { usePlaid } from '@maybe-finance/client/shared'
|
||||||
import { Disclosure, Transition } from '@headlessui/react'
|
import { Disclosure, Transition } from '@headlessui/react'
|
||||||
import { RiArrowUpSFill } from 'react-icons/ri'
|
import { RiArrowUpSFill } from 'react-icons/ri'
|
||||||
import { Button, LoadingSpinner } from '@maybe-finance/design-system'
|
import { Button, LoadingSpinner } from '@maybe-finance/design-system'
|
||||||
|
@ -56,14 +56,9 @@ export default function OAuth() {
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
Still not working?{' '}
|
Still not working?{' '}
|
||||||
<button
|
<a className="underline text-cyan" href="mailto:hello@maybe.co">
|
||||||
onClick={() =>
|
|
||||||
BrowserUtil.showIntercom()
|
|
||||||
}
|
|
||||||
className="underline text-cyan"
|
|
||||||
>
|
|
||||||
Let us know!
|
Let us know!
|
||||||
</button>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</Disclosure.Panel>
|
</Disclosure.Panel>
|
||||||
|
|
|
@ -145,19 +145,6 @@ router.get(
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
router.get(
|
|
||||||
'/intercom',
|
|
||||||
endpoint.create({
|
|
||||||
resolve: async ({ ctx }) => {
|
|
||||||
if (!ctx.user || !ctx.user.id) {
|
|
||||||
throw new Error('User not found')
|
|
||||||
}
|
|
||||||
|
|
||||||
return ctx.userService.getIntercomMetadata(ctx.user.id, env.NX_INTERCOM_SECRET)
|
|
||||||
},
|
|
||||||
})
|
|
||||||
)
|
|
||||||
|
|
||||||
router.put(
|
router.put(
|
||||||
'/',
|
'/',
|
||||||
endpoint.create({
|
endpoint.create({
|
||||||
|
|
|
@ -65,8 +65,6 @@ const envSchema = z.object({
|
||||||
.string()
|
.string()
|
||||||
.default(process.env.NODE_ENV === 'development' ? 'dev' : 'combined'),
|
.default(process.env.NODE_ENV === 'development' ? 'dev' : 'combined'),
|
||||||
|
|
||||||
NX_INTERCOM_SECRET: z.string().optional(),
|
|
||||||
|
|
||||||
NX_STRIPE_SECRET_KEY: z.string().default('REPLACE_THIS'),
|
NX_STRIPE_SECRET_KEY: z.string().default('REPLACE_THIS'),
|
||||||
NX_STRIPE_WEBHOOK_SECRET: z.string().default('whsec_REPLACE_THIS'),
|
NX_STRIPE_WEBHOOK_SECRET: z.string().default('whsec_REPLACE_THIS'),
|
||||||
NX_STRIPE_PREMIUM_MONTHLY_PRICE_ID: z.string().default('price_REPLACE_THIS'),
|
NX_STRIPE_PREMIUM_MONTHLY_PRICE_ID: z.string().default('price_REPLACE_THIS'),
|
||||||
|
|
|
@ -179,15 +179,6 @@ export class ServerStack extends Stack {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
NX_INTERCOM_SECRET: ECSSecret.fromSsmParameter(
|
|
||||||
StringParameter.fromSecureStringParameterAttributes(
|
|
||||||
this,
|
|
||||||
'IntercomSecretParam',
|
|
||||||
{
|
|
||||||
parameterName: '/providers/NX_INTERCOM_SECRET',
|
|
||||||
}
|
|
||||||
)
|
|
||||||
),
|
|
||||||
NX_STRIPE_SECRET_KEY: ECSSecret.fromSsmParameter(
|
NX_STRIPE_SECRET_KEY: ECSSecret.fromSsmParameter(
|
||||||
StringParameter.fromSecureStringParameterAttributes(
|
StringParameter.fromSecureStringParameterAttributes(
|
||||||
this,
|
this,
|
||||||
|
|
|
@ -13,7 +13,6 @@ import {
|
||||||
RiMore2Fill,
|
RiMore2Fill,
|
||||||
} from 'react-icons/ri'
|
} from 'react-icons/ri'
|
||||||
import { HiOutlineSparkles } from 'react-icons/hi'
|
import { HiOutlineSparkles } from 'react-icons/hi'
|
||||||
import { BrowserUtil } from '@maybe-finance/client/shared'
|
|
||||||
import Link from 'next/link'
|
import Link from 'next/link'
|
||||||
import { AnimatePresence, motion } from 'framer-motion'
|
import { AnimatePresence, motion } from 'framer-motion'
|
||||||
|
|
||||||
|
@ -399,13 +398,11 @@ export function SidebarOnboarding({ onClose, onHide }: Props) {
|
||||||
</Disclosure>
|
</Disclosure>
|
||||||
|
|
||||||
<p className="text-sm text-gray-100">
|
<p className="text-sm text-gray-100">
|
||||||
If you have any issues with connecting accounts, please let us know{' '}
|
If you have any issues with connecting accounts,{' '}
|
||||||
<button
|
<a className="text-cyan underline" href="mailto:hello@maybe.co">
|
||||||
onClick={() => BrowserUtil.showIntercom()}
|
please let us know
|
||||||
className="text-cyan cursor-pointer hover:underline"
|
</a>
|
||||||
>
|
.
|
||||||
via live chat
|
|
||||||
</button>
|
|
||||||
</p>
|
</p>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { useAuth0 } from '@auth0/auth0-react'
|
import { useAuth0 } from '@auth0/auth0-react'
|
||||||
import { BoxIcon, BrowserUtil, linkAuth0AccountCtx, useUserApi } from '@maybe-finance/client/shared'
|
import { BoxIcon, linkAuth0AccountCtx, useUserApi } from '@maybe-finance/client/shared'
|
||||||
import { Button, DialogV2 } from '@maybe-finance/design-system'
|
import { Button, DialogV2 } from '@maybe-finance/design-system'
|
||||||
import { useQueryClient } from '@tanstack/react-query'
|
import { useQueryClient } from '@tanstack/react-query'
|
||||||
import { useState } from 'react'
|
import { useState } from 'react'
|
||||||
|
@ -253,12 +253,9 @@ function LinkError({ onClose, error }: { onClose(): void; error: string }) {
|
||||||
|
|
||||||
<p className="mb-2 text-gray-50 text-base">{error}</p>
|
<p className="mb-2 text-gray-50 text-base">{error}</p>
|
||||||
|
|
||||||
<button
|
<a className="underline text-cyan text-base mb-6" href="mailto:hello@maybe.co">
|
||||||
className="underline text-cyan text-base mb-6"
|
|
||||||
onClick={BrowserUtil.showIntercom}
|
|
||||||
>
|
|
||||||
Please contact us.
|
Please contact us.
|
||||||
</button>
|
</a>
|
||||||
|
|
||||||
<div className="flex w-full gap-4">
|
<div className="flex w-full gap-4">
|
||||||
<Button fullWidth onClick={onClose}>
|
<Button fullWidth onClick={onClose}>
|
||||||
|
|
|
@ -8,10 +8,9 @@ import type {
|
||||||
} from '@tanstack/react-query'
|
} from '@tanstack/react-query'
|
||||||
|
|
||||||
import { useMemo } from 'react'
|
import { useMemo } from 'react'
|
||||||
import sumBy from 'lodash/sumBy'
|
|
||||||
import toast from 'react-hot-toast'
|
import toast from 'react-hot-toast'
|
||||||
import { useInfiniteQuery, useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
import { useInfiniteQuery, useMutation, useQuery, useQueryClient } from '@tanstack/react-query'
|
||||||
import { useAxiosWithAuth, useIntercom } from '..'
|
import { useAxiosWithAuth } from '..'
|
||||||
import { invalidateAccountQueries } from '../utils'
|
import { invalidateAccountQueries } from '../utils'
|
||||||
|
|
||||||
const AccountApi = (axios: AxiosInstance) => ({
|
const AccountApi = (axios: AxiosInstance) => ({
|
||||||
|
@ -135,7 +134,6 @@ export function useAccountApi() {
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const { axios } = useAxiosWithAuth()
|
const { axios } = useAxiosWithAuth()
|
||||||
const api = useMemo(() => AccountApi(axios), [axios])
|
const api = useMemo(() => AccountApi(axios), [axios])
|
||||||
const { update: updateIntercom } = useIntercom()
|
|
||||||
|
|
||||||
const useAccounts = (
|
const useAccounts = (
|
||||||
options?: Omit<
|
options?: Omit<
|
||||||
|
@ -152,13 +150,6 @@ export function useAccountApi() {
|
||||||
staleTime: staleTimes.accounts,
|
staleTime: staleTimes.accounts,
|
||||||
onSuccess: (...args) => {
|
onSuccess: (...args) => {
|
||||||
if (options?.onSuccess) options.onSuccess(...args)
|
if (options?.onSuccess) options.onSuccess(...args)
|
||||||
|
|
||||||
const [{ accounts, connections }] = args
|
|
||||||
updateIntercom({
|
|
||||||
'Manual Accounts': accounts.length,
|
|
||||||
'Connected Accounts': sumBy(connections, (c) => c.accounts.length),
|
|
||||||
Connections: connections.length,
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
...options,
|
...options,
|
||||||
})
|
})
|
||||||
|
|
|
@ -38,11 +38,6 @@ const UserApi = (
|
||||||
return data
|
return data
|
||||||
},
|
},
|
||||||
|
|
||||||
async getIntercomMetadata() {
|
|
||||||
const { data } = await axios.get<SharedType.UserIntercomMetadata>('/users/intercom')
|
|
||||||
return data
|
|
||||||
},
|
|
||||||
|
|
||||||
async update(userData: SharedType.UpdateUser) {
|
async update(userData: SharedType.UpdateUser) {
|
||||||
const { data } = await axios.put<SharedType.User>('/users', userData)
|
const { data } = await axios.put<SharedType.User>('/users', userData)
|
||||||
return data
|
return data
|
||||||
|
@ -254,22 +249,6 @@ export function useUserApi() {
|
||||||
staleTime: staleTimes.insights,
|
staleTime: staleTimes.insights,
|
||||||
})
|
})
|
||||||
|
|
||||||
const useIntercomMetadata = (
|
|
||||||
options?: Omit<
|
|
||||||
UseQueryOptions<
|
|
||||||
SharedType.UserIntercomMetadata,
|
|
||||||
unknown,
|
|
||||||
SharedType.UserIntercomMetadata,
|
|
||||||
any[]
|
|
||||||
>,
|
|
||||||
'queryKey' | 'queryFn'
|
|
||||||
>
|
|
||||||
) =>
|
|
||||||
useQuery(['users', 'intercom-metadata'], api.getIntercomMetadata, {
|
|
||||||
refetchOnWindowFocus: false,
|
|
||||||
...options,
|
|
||||||
})
|
|
||||||
|
|
||||||
const useProfile = (
|
const useProfile = (
|
||||||
options?: Omit<
|
options?: Omit<
|
||||||
UseQueryOptions<SharedType.User, unknown, SharedType.User, any[]>,
|
UseQueryOptions<SharedType.User, unknown, SharedType.User, any[]>,
|
||||||
|
@ -471,7 +450,6 @@ export function useUserApi() {
|
||||||
useNetWorthSeries,
|
useNetWorthSeries,
|
||||||
useInsights,
|
useInsights,
|
||||||
useCurrentNetWorth,
|
useCurrentNetWorth,
|
||||||
useIntercomMetadata,
|
|
||||||
useProfile,
|
useProfile,
|
||||||
useUpdateProfile,
|
useUpdateProfile,
|
||||||
useAuth0Profile,
|
useAuth0Profile,
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
export * from './useAxiosWithAuth'
|
export * from './useAxiosWithAuth'
|
||||||
export * from './useDebounce'
|
export * from './useDebounce'
|
||||||
export * from './useFinicity'
|
export * from './useFinicity'
|
||||||
export * from './useIntercom'
|
|
||||||
export * from './useInterval'
|
export * from './useInterval'
|
||||||
export * from './useLastUpdated'
|
export * from './useLastUpdated'
|
||||||
export * from './useLocalStorage'
|
export * from './useLocalStorage'
|
||||||
|
|
|
@ -5,12 +5,10 @@ import type {
|
||||||
ConnectCancelEvent,
|
ConnectCancelEvent,
|
||||||
ConnectDoneEvent,
|
ConnectDoneEvent,
|
||||||
ConnectErrorEvent,
|
ConnectErrorEvent,
|
||||||
ConnectRouteEvent,
|
|
||||||
} from '@finicity/connect-web-sdk'
|
} from '@finicity/connect-web-sdk'
|
||||||
import { useFinicityApi } from '../api'
|
import { useFinicityApi } from '../api'
|
||||||
import { useAccountContext, useUserAccountContext } from '../providers'
|
import { useAccountContext, useUserAccountContext } from '../providers'
|
||||||
import { useLogger } from './useLogger'
|
import { useLogger } from './useLogger'
|
||||||
import { BrowserUtil } from '..'
|
|
||||||
|
|
||||||
export function useFinicity() {
|
export function useFinicity() {
|
||||||
const logger = useLogger()
|
const logger = useLogger()
|
||||||
|
@ -35,9 +33,6 @@ export function useFinicity() {
|
||||||
FinicityConnect.launch(link, {
|
FinicityConnect.launch(link, {
|
||||||
onDone(evt: ConnectDoneEvent) {
|
onDone(evt: ConnectDoneEvent) {
|
||||||
logger.debug(`Finicity Connect onDone event`, evt)
|
logger.debug(`Finicity Connect onDone event`, evt)
|
||||||
BrowserUtil.trackIntercomEvent('FINICITY_CONNECT_DONE', {
|
|
||||||
...evt,
|
|
||||||
})
|
|
||||||
setExpectingAccounts(true)
|
setExpectingAccounts(true)
|
||||||
},
|
},
|
||||||
onError(evt: ConnectErrorEvent) {
|
onError(evt: ConnectErrorEvent) {
|
||||||
|
@ -50,25 +45,15 @@ export function useFinicity() {
|
||||||
'finicity.error.reason': evt.reason,
|
'finicity.error.reason': evt.reason,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
BrowserUtil.trackIntercomEvent('FINICITY_CONNECT_ERROR', {
|
|
||||||
...evt,
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
onCancel(evt: ConnectCancelEvent) {
|
onCancel(evt: ConnectCancelEvent) {
|
||||||
logger.debug(`Finicity Connect onCancel event`, evt)
|
logger.debug(`Finicity Connect onCancel event`, evt)
|
||||||
BrowserUtil.trackIntercomEvent('FINICITY_CONNECT_CANCEL', {
|
|
||||||
...evt,
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
onUser(evt: any) {
|
onUser() {
|
||||||
BrowserUtil.trackIntercomEvent('FINICITY_CONNECT_USER_ACTION', {
|
// ...
|
||||||
...evt,
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
onRoute(evt: ConnectRouteEvent) {
|
onRoute() {
|
||||||
BrowserUtil.trackIntercomEvent('FINICITY_CONNECT_ROUTE_EVENT', {
|
// ...
|
||||||
...evt,
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
import { useCallback } from 'react'
|
|
||||||
import { useAuth0 } from '@auth0/auth0-react'
|
|
||||||
import type { SharedType } from '@maybe-finance/shared'
|
|
||||||
import { useUserApi } from '../api'
|
|
||||||
import { BrowserUtil } from '..'
|
|
||||||
|
|
||||||
export function useIntercom() {
|
|
||||||
const { user, isAuthenticated } = useAuth0<SharedType.Auth0ReactUser>()
|
|
||||||
|
|
||||||
const { useIntercomMetadata } = useUserApi()
|
|
||||||
const { data: intercomMetadata } = useIntercomMetadata({ enabled: isAuthenticated })
|
|
||||||
|
|
||||||
const boot = useCallback(
|
|
||||||
(data?: BrowserUtil.IntercomData) => {
|
|
||||||
if (!user?.sub || !intercomMetadata?.hash) return false
|
|
||||||
|
|
||||||
BrowserUtil.bootIntercom({
|
|
||||||
user_id: user.sub,
|
|
||||||
user_hash: intercomMetadata.hash,
|
|
||||||
email: user.email,
|
|
||||||
name: user.name,
|
|
||||||
last_request_at: Math.floor(new Date().getTime() / 1000),
|
|
||||||
...data,
|
|
||||||
})
|
|
||||||
|
|
||||||
return true
|
|
||||||
},
|
|
||||||
[user, intercomMetadata]
|
|
||||||
)
|
|
||||||
|
|
||||||
const update = useCallback(
|
|
||||||
(data?: BrowserUtil.IntercomData, updateLastRequestAt = true) => {
|
|
||||||
if (!user?.sub || !intercomMetadata?.hash) return
|
|
||||||
|
|
||||||
BrowserUtil.updateIntercom({
|
|
||||||
user_id: user.sub,
|
|
||||||
user_hash: intercomMetadata.hash,
|
|
||||||
email: user.email,
|
|
||||||
name: user.name,
|
|
||||||
last_request_at: updateLastRequestAt
|
|
||||||
? Math.floor(new Date().getTime() / 1000)
|
|
||||||
: undefined,
|
|
||||||
...data,
|
|
||||||
})
|
|
||||||
},
|
|
||||||
[user, intercomMetadata]
|
|
||||||
)
|
|
||||||
|
|
||||||
return { boot, update }
|
|
||||||
}
|
|
|
@ -2,7 +2,6 @@ import * as Sentry from '@sentry/react'
|
||||||
import { DateTime } from 'luxon'
|
import { DateTime } from 'luxon'
|
||||||
import { useEffect, useState } from 'react'
|
import { useEffect, useState } from 'react'
|
||||||
import { usePlaidLink } from 'react-plaid-link'
|
import { usePlaidLink } from 'react-plaid-link'
|
||||||
import { BrowserUtil } from '..'
|
|
||||||
import { usePlaidApi } from '../api'
|
import { usePlaidApi } from '../api'
|
||||||
import { useAccountContext } from '../providers'
|
import { useAccountContext } from '../providers'
|
||||||
import { useLogger } from './useLogger'
|
import { useLogger } from './useLogger'
|
||||||
|
@ -68,22 +67,8 @@ export function usePlaid(mode: 'default' | 'oauth' = 'default') {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// https://plaid.com/docs/link/web/#onexit
|
// https://plaid.com/docs/link/web/#onexit
|
||||||
onExit: (error, metadata) => {
|
onExit: () => {
|
||||||
if (error) {
|
// ...
|
||||||
const { error_code, error_type, error_message, display_message } = error
|
|
||||||
BrowserUtil.trackIntercomEvent(`PLAID_LINK_EXIT_ERROR`, {
|
|
||||||
error_type,
|
|
||||||
error_code,
|
|
||||||
error_message,
|
|
||||||
display_message,
|
|
||||||
reference: 'https://plaid.com/docs/errors/',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
BrowserUtil.trackIntercomEvent('PLAID_EXIT_EVENT', {
|
|
||||||
...error,
|
|
||||||
...metadata,
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
// https://plaid.com/docs/link/web/#onevent
|
// https://plaid.com/docs/link/web/#onevent
|
||||||
onEvent: (event, metadata) => {
|
onEvent: (event, metadata) => {
|
||||||
|
@ -97,9 +82,6 @@ export function usePlaid(mode: 'default' | 'oauth' = 'default') {
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
// Capture all events to Intercom
|
|
||||||
BrowserUtil.trackIntercomEvent(event, metadata)
|
|
||||||
|
|
||||||
logger.debug(
|
logger.debug(
|
||||||
`Plaid link event: ${event} for session ID ${metadata.link_session_id}`,
|
`Plaid link event: ${event} for session ID ${metadata.link_session_id}`,
|
||||||
metadata
|
metadata
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
export * from './image-loaders'
|
export * from './image-loaders'
|
||||||
export * from './intercom'
|
|
||||||
export * from './browser-utils'
|
export * from './browser-utils'
|
||||||
export * from './account-utils'
|
export * from './account-utils'
|
||||||
export * from './agreement-utils'
|
export * from './agreement-utils'
|
||||||
|
|
|
@ -1,36 +0,0 @@
|
||||||
export type IntercomData = {
|
|
||||||
user_id?: string
|
|
||||||
user_hash?: string
|
|
||||||
email?: string
|
|
||||||
name?: string
|
|
||||||
|
|
||||||
last_request_at?: number
|
|
||||||
|
|
||||||
'Manual Accounts'?: number
|
|
||||||
'Connected Accounts'?: number
|
|
||||||
Connections?: number
|
|
||||||
}
|
|
||||||
|
|
||||||
export function bootIntercom(data?: IntercomData) {
|
|
||||||
const w = window as any
|
|
||||||
w.Intercom('boot', {
|
|
||||||
app_id: w.INTERCOM_APP_ID,
|
|
||||||
...data,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function updateIntercom(data?: IntercomData) {
|
|
||||||
;(window as any).Intercom('update', {
|
|
||||||
...data,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function trackIntercomEvent(name: string, data: Record<string, any>) {
|
|
||||||
;(window as any).Intercom('trackEvent', name, {
|
|
||||||
...data,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function showIntercom() {
|
|
||||||
;(window as any).Intercom('show')
|
|
||||||
}
|
|
|
@ -20,7 +20,6 @@ import type { IAccountQueryService } from '../account'
|
||||||
import type { SharedType } from '@maybe-finance/shared'
|
import type { SharedType } from '@maybe-finance/shared'
|
||||||
import { CopyObjectCommand, MetadataDirective } from '@aws-sdk/client-s3'
|
import { CopyObjectCommand, MetadataDirective } from '@aws-sdk/client-s3'
|
||||||
import { DateTime } from 'luxon'
|
import { DateTime } from 'luxon'
|
||||||
import crypto from 'crypto'
|
|
||||||
import { DbUtil } from '@maybe-finance/server/shared'
|
import { DbUtil } from '@maybe-finance/server/shared'
|
||||||
import { DateUtil } from '@maybe-finance/shared'
|
import { DateUtil } from '@maybe-finance/shared'
|
||||||
import { flatten } from 'lodash'
|
import { flatten } from 'lodash'
|
||||||
|
@ -279,22 +278,6 @@ export class UserService implements IUserService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async getIntercomMetadata(
|
|
||||||
userId: User['id'],
|
|
||||||
secret?: string
|
|
||||||
): Promise<SharedType.UserIntercomMetadata> {
|
|
||||||
const { auth0Id } = await this.prisma.user.findUniqueOrThrow({
|
|
||||||
select: { auth0Id: true },
|
|
||||||
where: { id: userId },
|
|
||||||
})
|
|
||||||
|
|
||||||
return {
|
|
||||||
hash: secret
|
|
||||||
? crypto.createHmac('sha256', secret).update(auth0Id).digest('hex')
|
|
||||||
: undefined,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async getSignedAgreements(userId: User['id']) {
|
async getSignedAgreements(userId: User['id']) {
|
||||||
return this.prisma.agreement.findMany({
|
return this.prisma.agreement.findMany({
|
||||||
distinct: 'type',
|
distinct: 'type',
|
||||||
|
|
|
@ -227,10 +227,6 @@ export type UserSubscription = {
|
||||||
currentPeriodEnd: DateTime | null
|
currentPeriodEnd: DateTime | null
|
||||||
}
|
}
|
||||||
|
|
||||||
export type UserIntercomMetadata = {
|
|
||||||
hash?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export type UserMemberCardDetails = {
|
export type UserMemberCardDetails = {
|
||||||
memberNumber: number
|
memberNumber: number
|
||||||
name: string
|
name: string
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue