From 9e9a184b67102e79440bb4de239cc8f2a14241a7 Mon Sep 17 00:00:00 2001 From: Nathanael Liu Date: Thu, 2 May 2024 18:38:56 -0700 Subject: [PATCH 1/5] fix(masterbots.ai): fix css details on ThreadDoubleAccordion (#206) --- .../shared/thread-accordion.client.tsx | 15 +++-- .../shared/thread-accordion.server.tsx | 4 +- .../shared/thread-list-accordion.tsx | 62 +++++++++++++++---- .../masterbots.ai/components/ui/accordion.tsx | 17 +++-- 4 files changed, 69 insertions(+), 29 deletions(-) diff --git a/apps/masterbots.ai/components/shared/thread-accordion.client.tsx b/apps/masterbots.ai/components/shared/thread-accordion.client.tsx index 32b4696c..8c308a52 100644 --- a/apps/masterbots.ai/components/shared/thread-accordion.client.tsx +++ b/apps/masterbots.ai/components/shared/thread-accordion.client.tsx @@ -1,20 +1,19 @@ 'use client' -import { useEffect } from 'react' -import { useQuery } from '@tanstack/react-query' -import { usePathname, useRouter } from 'next/navigation' -import { MB } from '@repo/supabase' +import { getMessagePairs } from '@/app/actions' import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/components/ui/accordion' +import { getThreadLink } from '@/lib/threads' import { cn } from '@/lib/utils' -import { getMessagePairs } from '@/app/actions' -import { ThreadHeading } from './thread-heading' +import { MB } from '@repo/supabase' +import { useQuery } from '@tanstack/react-query' +import { usePathname, useRouter } from 'next/navigation' +import { useEffect } from 'react' import { BrowseChatMessage } from './thread-message' -import { getThreadLink } from '@/lib/threads' export function ThreadAccordionClient({ thread, @@ -56,7 +55,7 @@ export function ThreadAccordionClient({ return (
diff --git a/apps/masterbots.ai/components/shared/thread-list-accordion.tsx b/apps/masterbots.ai/components/shared/thread-list-accordion.tsx index 432e9ea2..15c24233 100644 --- a/apps/masterbots.ai/components/shared/thread-list-accordion.tsx +++ b/apps/masterbots.ai/components/shared/thread-list-accordion.tsx @@ -1,25 +1,62 @@ -import { DialogProps } from '@radix-ui/react-dialog' -import type { MB } from '@repo/supabase' -import { cn } from '@/lib/utils' +'use client' + import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from '@/components/ui/accordion' +import { createMessagePairs } from '@/lib/threads' +import { cn, sleep } from '@/lib/utils' +import { DialogProps } from '@radix-ui/react-dialog' +import type { MB } from '@repo/supabase' +import { useSearchParams } from 'next/navigation' +import { useEffect, useRef } from 'react' +import { useSetState } from 'react-use' import { ThreadAccordionClient } from './thread-accordion.client' import { ThreadHeading } from './thread-heading' -import { createMessagePairs } from '@/lib/threads' export function ThreadListAccordion({ thread, - chat = false + chat = false, + isUser = false, + isBot = false }: ThreadListAccordionProps) { + const [state, setState] = useSetState({ + isOpen: false, + firstQuestion: + thread.messages.find(m => m.role === 'user')?.content || 'not found', + firstResponse: + thread.messages.find(m => m.role === 'assistant')?.content || 'not found' + }) + const searchParams = useSearchParams(); + const threadRef = useRef(null) + const handleThreadIdChange = async () => { + if (searchParams.get('threadId') === thread.threadId) { + await sleep(300) // animation time + threadRef.current?.scrollIntoView({ behavior: 'smooth', block: 'start' }) + } else if (state.isOpen && searchParams.get('threadId')) { + setState({ isOpen: false }) + } + } + + useEffect(() => { + handleThreadIdChange() + }, [searchParams]) + return ( - - + { + setState({ isOpen: v[0] === 'pair-1' }) + }} + type="multiple" + > + {/* Frist level question and excerpt visible on lists */} +
@@ -50,6 +84,8 @@ export function ThreadListAccordion({ } interface ThreadListAccordionProps extends DialogProps { - thread: MB.ThreadFull + thread: MB.Thread chat?: boolean + isUser?: boolean + isBot?: boolean } diff --git a/apps/masterbots.ai/components/ui/accordion.tsx b/apps/masterbots.ai/components/ui/accordion.tsx index 74fabea5..e4881c5a 100644 --- a/apps/masterbots.ai/components/ui/accordion.tsx +++ b/apps/masterbots.ai/components/ui/accordion.tsx @@ -1,12 +1,16 @@ 'use client' -import * as React from 'react' +import { cn } from '@/lib/utils' import * as AccordionPrimitive from '@radix-ui/react-accordion' import { ChevronDown } from 'lucide-react' -import { cn } from '@/lib/utils' +import * as React from 'react' const Accordion = AccordionPrimitive.Root +interface AccordionTriggerProps extends React.ComponentPropsWithoutRef { + isSticky?: boolean +} + const AccordionItem = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef @@ -21,12 +25,12 @@ AccordionItem.displayName = 'AccordionItem' const AccordionTrigger = React.forwardRef< React.ElementRef, - React.ComponentPropsWithoutRef + AccordionTriggerProps >(({ className, children, ...props }, ref) => ( svg]:rotate-180', + 'flex flex-1 items-center justify-between py-4 font-medium transition-all [&[data-state=open]>svg]:rotate-180', className )} ref={ref} @@ -48,10 +52,11 @@ const AccordionContent = React.forwardRef< ref={ref} {...props} > -
{children}
+
{children}
)) AccordionContent.displayName = AccordionPrimitive.Content.displayName -export { Accordion, AccordionItem, AccordionTrigger, AccordionContent } +export { Accordion, AccordionContent, AccordionItem, AccordionTrigger } + From 2e1b9351b84e9f8821accd882ee6ef86692c1fc2 Mon Sep 17 00:00:00 2001 From: Nathanael Liu Date: Tue, 7 May 2024 08:44:03 -0700 Subject: [PATCH 2/5] fix(masterbots.ai): infinite scroll issue on bot view (#212) --- .../components/shared/thread-list.tsx | 91 ++++++++++++++++++- 1 file changed, 90 insertions(+), 1 deletion(-) diff --git a/apps/masterbots.ai/components/shared/thread-list.tsx b/apps/masterbots.ai/components/shared/thread-list.tsx index 6c1c409f..8ff0cfd1 100644 --- a/apps/masterbots.ai/components/shared/thread-list.tsx +++ b/apps/masterbots.ai/components/shared/thread-list.tsx @@ -1,14 +1,101 @@ +import { getThreads } from '@/app/actions' import { MB } from '@repo/supabase' +import { useInfiniteQuery, useQueryClient } from '@tanstack/react-query' +import { usePathname, useSearchParams } from 'next/navigation' +import { useEffect, useRef, useState } from 'react' import { ThreadDialog } from './thread-dialog' import { ThreadListAccordion } from './thread-list-accordion' import { ThreadListChatItem } from './thread-list-chat-item' import { ThreadListReload } from './thread-list-reload' +const limit = 20 export function ThreadList({ initialThreads, chat = false, - dialog = false + dialog = false, + isUser = false, + isBot = false }: ThreadListProps) { + const searchParams = useSearchParams() + const query = searchParams.get('query') + const loadMoreRef = useRef(null) + const queryClient = useQueryClient() + const [showSkeleton, setShowSkeleton] = useState(false) + + const queryKey = [usePathname(), query] + const [lastQueryKey, setLastQueryKey] = useState(queryKey) + const { isFetchingNextPage, fetchNextPage, data, refetch } = useInfiniteQuery( + { + queryKey, + queryFn: async (props) => { + const query = await getThreads({ + page: props.pageParam - 1, + }) + return query.data + }, + initialData: { pages: [initialThreads], pageParams: [1] }, + initialPageParam: 2, + getNextPageParam: ((_a, _b, lastPageParam) => { + return lastPageParam + 1 + }), + enabled: false + } + ) + + useEffect(() => { + refetch() + }, [refetch, query]) + + // load mare item when it gets to the end + // TODO: read count from database + useEffect(() => { + // only load add observer if we get at least iquals to limit on initialThreads + // TODO: get thread count from server db query + if ( + !loadMoreRef.current || + data.pages[data.pages.length - 1].length < limit + ) + return + const observer = new IntersectionObserver(([entry]) => { + if (entry.isIntersecting && !isFetchingNextPage) { + setTimeout(() => { + fetchNextPage() + }, 150) + observer.unobserve(entry.target) + } + }) + + observer.observe(loadMoreRef.current) + + return () => { + // always unsubscribe on component unmount + observer.disconnect() + } + }, [isFetchingNextPage, fetchNextPage]) + + useEffect(() => { + const queryKeyString = JSON.stringify(queryKey) + const lastQueryKeyString = JSON.stringify(lastQueryKey) + console.log( + queryKeyString === lastQueryKeyString, + queryKeyString, + lastQueryKeyString + ) + if (queryKeyString === lastQueryKeyString) return + console.log('queryKey changed, resetting query client ...') + // Invalidate and refetch the query to reset state + // we need this cos nextjs wont hydrate this client component, only src + setShowSkeleton(true) + setLastQueryKey(queryKey) + + queryClient.invalidateQueries({ queryKey }).then(() => { + queryClient.refetchQueries({ queryKey }).then(() => { + setShowSkeleton(false) + refetch() + }) + }) + }, [queryKey, setLastQueryKey, lastQueryKey, setShowSkeleton, refetch]) + // ThreadList can displays the rigth list item based on the context // ThreadListChatItem is next shallow link for chat ui lists // ThreadDialog is user preference @@ -42,4 +129,6 @@ interface ThreadListProps { initialThreads: MB.ThreadFull[] chat?: boolean dialog?: boolean + isUser?: boolean + isBot?: boolean } From 958d296972be06e76eb6b1773e1391f5536d3130 Mon Sep 17 00:00:00 2001 From: Roberto Lucas Date: Tue, 21 May 2024 15:34:33 -0600 Subject: [PATCH 3/5] fix: infinite scroll loop + notes --- .../components/shared/thread-list-reload.tsx | 11 +++++--- .../components/shared/thread-list.tsx | 24 ++++++++++++------ bun.lockb | Bin 393136 -> 393136 bytes 3 files changed, 24 insertions(+), 11 deletions(-) diff --git a/apps/masterbots.ai/components/shared/thread-list-reload.tsx b/apps/masterbots.ai/components/shared/thread-list-reload.tsx index b5aa4888..0027bd73 100644 --- a/apps/masterbots.ai/components/shared/thread-list-reload.tsx +++ b/apps/masterbots.ai/components/shared/thread-list-reload.tsx @@ -1,8 +1,13 @@ 'use client' -import React, { useEffect, useRef, useState } from 'react' -import { useSearchParams, useRouter } from 'next/navigation' - +import { useRouter, useSearchParams } from 'next/navigation' +import { useEffect, useRef, useState } from 'react' + +// ! This component is not necessary to be split this way, only functionality. +// ! Though functionality looks correct, this causes an error in the app, a infinite loop very easy +// ! I suggest to only split the code in the same file, or use a different approach to split the code. +// * Search params might look fine but if an user goes (or saves) a link with a page number, it will be lost the first items that are on smaller page number +// * E.g.: If I go to /?page=2, I will lose the first items that are on page 1... This is not a good user experience export function ThreadListReload() { const params = useSearchParams() const router = useRouter() diff --git a/apps/masterbots.ai/components/shared/thread-list.tsx b/apps/masterbots.ai/components/shared/thread-list.tsx index 8ff0cfd1..8e700a62 100644 --- a/apps/masterbots.ai/components/shared/thread-list.tsx +++ b/apps/masterbots.ai/components/shared/thread-list.tsx @@ -1,12 +1,12 @@ import { getThreads } from '@/app/actions' import { MB } from '@repo/supabase' import { useInfiniteQuery, useQueryClient } from '@tanstack/react-query' +import { flatten, uniq } from 'lodash' import { usePathname, useSearchParams } from 'next/navigation' import { useEffect, useRef, useState } from 'react' import { ThreadDialog } from './thread-dialog' import { ThreadListAccordion } from './thread-list-accordion' import { ThreadListChatItem } from './thread-list-chat-item' -import { ThreadListReload } from './thread-list-reload' const limit = 20 export function ThreadList({ @@ -105,22 +105,30 @@ export function ThreadList({ : dialog ? ThreadDialog : ThreadListAccordion + const threads = uniq(flatten(data.pages)) return (
- {!initialThreads.length ? ( -
No threads founds
- ) : ( - initialThreads.map(thread => ( + {!threads.length ?
No threads founds
: null} + {showSkeleton ? ' Loading ...' : ''} + {!showSkeleton && + threads.map((thread: MB.ThreadFull) => ( - )) - )} - + ))} +
+ {isFetchingNextPage && ( +
+
+
+ )} +
) } diff --git a/bun.lockb b/bun.lockb index 5ab3f7727ccbbce4fb8cd38e5b0a7da927f3bb47..74964c5353febafe56cac31dfe6c50d5647c55fe 100755 GIT binary patch delta 6706 zcmXBWclfPz0mpHFSEXfWS=gja!#Yh*o2Imk%8J{hjT<*^+_-UGt`n~d=Ort{CT-fM zecGo@n>KCi*XR8Q-`Deb!+$&v54Ya2%dL0pa>8wEyG3hjo9EHm#&vS&!QD%-fC0R{ z6-yYw-$${634(nUYcTfH3ZVgWf5iw|untg+p#wWsOke@dfr=?CVRn#W1}m5!te8U& z?jec=4B#EASi%VYVTu(@5FD;pgOO;3(13Y_VgxN%M=Hk9fqj%>0t;}CR!m_Dvttx9 zSi$^Q#T;2*D8!34nxiZvJ~ zYK72%d6HrTEm$Wj#?XO%iedr_a86ZBVF|NLF@qJ%PgBgH2lsTv0tWETP%L2t|4hXS zCJ4?_tid>2D})Bja}*2fqkiB0t;|1Q%qqAv&$7TSi$@X#TcGs;JimM zg(b}1tC+zG=I>L?p$GRi#R3NK-mh4~2!5kj!34qWiZvJ?&m_rZlw-gH)z*{PoFoOSW z#R?_}zN1)!@m;MD8Zf`77(olx_Z4I4!2W?^0t;|{sF=bMW-G-ERxtmOVh%mHKUOSY z0PiP?C5+(zRI!2yf}bhYVEkMwga*uCC`QnN)hou(f&ELx1Qy`@N->2c%zmwy!3yTT zQOuzS_qU1#4B-7vv4j!)-z!!yK`PYMLkISM z6%$y1GbyI9gxMX68LY&n`G)m>%T2k?{{QD@cTE&9fVV-hgc1C06)Tt^*iNwqV|%R- z8ZZsT2wJf2q!>d7_MH_ISb%dE#T1q>yQ^XbE12I+F^3-99TW=~z`MI*2_yKXVg(Zf zJ1W*-?4%V!1Li#xBWS_8r(z5p*gGpGumI;?iYY8%c5lTDRxq~|bLhd{MX`VZy!$AY zFoJ(y#R?_}?x$FTaeu848ZaNA7(olx0~KTFz_t|=Sb*~&#T1q>d$3{#E0{k-F^3-9 zhbk5@fcG%P5=QVJu2{hY!6OuFFdVHA8ZaNJ7(olxqZDK4z<#u10t;{+qnN@HX1gk8 zu!8wx6?5ppeVk$e19&sV5=QVJuUNqZ!4ni~FrKItLIdWL6eDQCda_~+9oSD%Oke@d zZi*=^VWtns<_uOaf2y9$p$GSAiUkbdJzcSc5&UN;Rxm;EOvM_EXK97dfcb322wJdQ z#TYuUpQD(-0-Wb6rm%$B^As~!!TkA(IrQMZK(T-Uyca5#FoM6kVg(Zfo?;Egi?l*$ zzd%I!=E117SF^3-9 zcPbVzfcGxN5=QVN#R?_}_EN0D*jp=v2F!gFBWS_eS22bT?EMrISb(#?VhT%`9iW)O z3g)q54n4RBDi$z+caUNUBlrg^Rxm+uh++-Kp;{p{U>>FzK?~O5iZOIxCyEIyz&S!O zg(b|6RLo!n^P?1V=)pZ&v48=*V-!mm!9P~9f(e4-6l*Y2tq>Y8k5`PK1?vRG7&@>| zR7_w2&Pj?XEMa!CVg@UipQ4yU5ALao1q|S2iY1KTpQc#B1i|TwH5g}Th0uU`reXvw zSZ685(1CrnVgd_r&QVNZ3A0==gB8rrRm`CW_dLY{2Jp^TEMWxy0>ug@2rg8t!MI2( zga*t_iV?J66^b!*U~g7TU;)m>iYY8%c8OvJE0|xZm_rZlWr_t1;9ag*!U+BqiWN){ zl!`SNS89dOfVo96f)=c+6l3VXzFIMX1vu9zrm%$BwTc<6V1Auq4n4S)VgUnq*DIDV zf`5Zz1rr1}D%N1!q!mH~=FN%`v|!z$7()m4)(smspSbgeT~FJxb;J6#?fSLd?OV2P Iztf)o130Bv^8f$< delta 6721 zcmY+{SJdQm0fzDY7KjZ4hz4sE%UIB{GB%8r*n^;Ct+9t5dg!5t9_r?!hNXqN5fuZr z*kd2DjXn0*M{H3nf#rR?;Uf8+_c@cR`JXwNoA280=DW5#?v|Au!<99wvv6hICNk*3 z*+VghCAfPk7BGOfmtqMc_VC=;iXk*$?WY()3wER!!yG32D<-gj=>du< zbTB(mF@qkQgA{XEf_t!H0Rwo4D3&mSf2d*wMywS;4d!8rAv9net{6cJ_7RFP%wck* zVgd`89;KK<2eYFUGw8uNW@X)$Yu2n;Su<`muB=(J^Xm4ut=(nyj$>AK-}GI(i5@9n z0Pk4E5=QWkQ>?%^UMqka%o7wtXuvvAF@hHClN4i^!{lVe1Qsw&6;tS7c8X#KJvgT- z=CB0!G{pi2@J?4OVFdpS#R`lwwF0QYJWDZz2CPgmf)?zv6=Rsgz{# z6&SZ^1yF#|BS^?BxeqJ$z2COeAM$m%YD#kE}$rlw9Sitm4iYat3`?6vNJvd)c z%wY-cR}~8w!26nF2_yJlSFFI8YXwk)`3=Po8nA9xjGzVkn~E{aVe&1-1Qsy;wqgn$ z%)XC5+&IU$Fw?2U-EtVE#}sga)i1DMrwO{bR)#<}mq* zVgd`8c8V!=96hmmh`mbUHE!h84jA0IwQ89r9Oz%=mp%d$8Yd8I&SfAdQjDMld)u}5diB3^b=NI6 z+hz6kZP(uO>OXm~9!X#U(}yUg(80`7%%BHnJH;H9;67BbfC0RRDV8vT|8T_$j7Mk% zP=onM#Sj{>9;FyT3%0Eo!yG1$R!m?4)5j>L(7|kb#SD6I9;=wc65Pir7BGPKc*PP% z@SmVqfickvpa%1aiXk*$JxMWw7VIZ0#xRG;Qxp?ez;p-26grqaRWXAeoTn+~umpFi zSik_@(-lh?!GDHg1;#VA0;s`!mSPAESkG3BpauImiZRS#vZG=G3z+H`Wi^EkX3y0p zGw8v2o?;G5aG$SOzyRJ06iXPvf1zRp#!gxR)L_0yF@y#zM=^pH>=!G>Fo(%Y6cbp$ z^rea^bTE6FVg@}pFIUWA3GOQt3mCxLS+Rr>d{?moW0=FlS4?05({+j|bTE6fVg@}pZ&A!)3GQ1J3mCwAn_>wg_-|LNz<7sN z05zC_Vh9ab?^KMS1^Zo!G0b7|Zp8!^Fny0=3LVVetC&F#&ifQ|Sc3b0#R3NKLd6nB z@b^%xz}QnOfEvub6hmmh+FLP#7VLc#W0=EaU&RC#Fx^ivg$`zsVg@}p`zz+K1or^N z0tWC7R4icx{~*N*jDxiTsKGo$F@y%JLlq-v!HyMUn8V~S#RL{GJzOz`4rWIvX3&Fk zq+$+BaF0?fU;yuE#S%vFk5R0^NVEc|!8}$mga)kR6eDQCK3*|~IZRGaOke@i6BSeF zV0MyX20b_@E9S5SH&rZP0PhsV5=QV(Rjj}`O)G#J%+nP^Xuvu{F@hHCGZkZ)!{jW* z1QsyO6jSJ6cD7;$Jviqm=CB0!T*U$g@Xk{#VFdqt#R`lIv;wHXT(1~H16HmWK@0Y( zVhnSbT&S490;U%!rqIFcV#N%4a4u2IVF~V~iUkbdU8Y#V2!5ehfpNK305zB!6hmmh zxw8JSIHm==tZMNy!{MHQ{x7d2Oy8#SeS-SuL From 627f141a8c4952f9e486344664e4c08910d479aa Mon Sep 17 00:00:00 2001 From: Nathanael Liu Date: Tue, 7 May 2024 17:12:14 -0700 Subject: [PATCH 4/5] feat(masterbots.ai): google analytics tag (#213) * feat: setup google analytics tag * wip: rm comment --- apps/masterbots.ai/app/layout.tsx | 23 ++++++++++++------ .../shared/category-tabs/category-tabs.tsx | 24 +++++++++++++++++++ apps/masterbots.ai/package.json | 1 + 3 files changed, 41 insertions(+), 7 deletions(-) diff --git a/apps/masterbots.ai/app/layout.tsx b/apps/masterbots.ai/app/layout.tsx index 7c027b76..16efce49 100644 --- a/apps/masterbots.ai/app/layout.tsx +++ b/apps/masterbots.ai/app/layout.tsx @@ -3,15 +3,17 @@ import { GeistSans } from 'geist/font/sans' import { Toaster } from 'react-hot-toast' import '@/app/globals.css' -import { cookies } from 'next/headers' -import dynamic from 'next/dynamic' -import { Metadata } from 'next/types' -import { objectToCamel } from 'ts-case-convert' import { Header } from '@/components/layout/header' import { Providers } from '@/components/layout/providers' -import { cn } from '@/lib/utils' import { GlobalStoreProvider } from '@/hooks/use-global-store' +import { cn } from '@/lib/utils' import { createSupabaseServerClient } from '@/services/supabase' +import { GoogleAnalytics } from '@next/third-parties/google' +import { MB } from '@repo/supabase' +import dynamic from 'next/dynamic' +import { cookies } from 'next/headers' +import { Metadata } from 'next/types' +import { objectToCamel } from 'ts-case-convert' async function getCookieData(): Promise<{ userProfile }> { const userProfile = cookies().get('userProfile')?.value || null @@ -41,7 +43,7 @@ export default async function RootLayout({ children }: RootLayoutProps) { + + + ) @@ -70,7 +75,11 @@ async function getGlobalData() { const categories = await supabase.from('category').select() const chatbot = await supabase.from('chatbot').select(`*, prompt(*)`) - return objectToCamel({ categories: categories.data, chatbots: chatbot.data }) + return objectToCamel({ + categories: categories.data, + // TODO: fix type... it shouldn't be unknown. Moving forward on other places. + chatbots: chatbot.data as unknown as MB.ChatbotWithPrompts[] + }) } export const viewport = { diff --git a/apps/masterbots.ai/components/shared/category-tabs/category-tabs.tsx b/apps/masterbots.ai/components/shared/category-tabs/category-tabs.tsx index c1fc0993..24a273af 100644 --- a/apps/masterbots.ai/components/shared/category-tabs/category-tabs.tsx +++ b/apps/masterbots.ai/components/shared/category-tabs/category-tabs.tsx @@ -1,4 +1,8 @@ +'use client' + +import { toSlug } from '@/lib/url-params' import { MB } from '@repo/supabase' +import { useEffect } from 'react' import { CategoryLink } from './category-link' export function CategoryTabs({ @@ -8,6 +12,26 @@ export function CategoryTabs({ categories: MB.Category[] initialCategory?: string }) { + useEffect(() => { + if (document) { + const element = document.getElementById( + `browse-category-tab__${initialCategory === 'all' + ? 'all' + : categories.filter(c => toSlug(c.name) === initialCategory)[0] + ?.categoryId + }` + ) + + if (element) { + element.scrollIntoView({ + behavior: 'smooth', + block: 'center', + inline: 'center' + }) + } + } + }, [initialCategory]) + return (
diff --git a/apps/masterbots.ai/package.json b/apps/masterbots.ai/package.json index 8c26c901..787ac927 100644 --- a/apps/masterbots.ai/package.json +++ b/apps/masterbots.ai/package.json @@ -16,6 +16,7 @@ "dependencies": { "@blockmatic/hooks-utils": "^3.0.0", "@hookform/resolvers": "^3.3.4", + "@next/third-parties": "^14.2.3", "@radix-ui/react-accordion": "^1.1.2", "@radix-ui/react-alert-dialog": "^1.0.5", "@radix-ui/react-avatar": "^1.0.4", From f4bef582572433df4480a0c994efc905e723e2ad Mon Sep 17 00:00:00 2001 From: Nathanael Liu Date: Thu, 9 May 2024 15:36:48 -0700 Subject: [PATCH 5/5] hotfix(masterbots.ai): google analytics gaid (#214) --- apps/masterbots.ai/app/layout.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/masterbots.ai/app/layout.tsx b/apps/masterbots.ai/app/layout.tsx index 16efce49..fe00e494 100644 --- a/apps/masterbots.ai/app/layout.tsx +++ b/apps/masterbots.ai/app/layout.tsx @@ -62,7 +62,7 @@ export default async function RootLayout({ children }: RootLayoutProps) { - +