Skip to content

Commit

Permalink
feat: add episode-ai-summary-footer
Browse files Browse the repository at this point in the history
  • Loading branch information
altaywtf committed Dec 16, 2023
1 parent f3e7174 commit ae1a9d6
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 36 deletions.
64 changes: 64 additions & 0 deletions components/episode-ai-summary/episode-ai-summary-footer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
'use client';

import type { Tables } from '@/types/supabase/database';

import { createSupabaseBrowserClient } from '@/lib/services/supabase/browser';
import { Avatar, Flex, Text } from '@radix-ui/themes';
import { useEffect, useRef, useState } from 'react';
import { CgProfile } from 'react-icons/cg';

type Props = {
id: Tables<'episode'>['id'];
};

const fetchData = async (id: Props['id']) => {
const supabase = createSupabaseBrowserClient();

const { data } = await supabase
.from('episode_content')
.select('id, user:account(id, display_name, avatar_url)')
.eq('episode', id)
.single();

return data?.user ? { user: data.user } : { user: null };
};

export function EpisodeAISummaryFooter(props: Props) {
const startedRef = useRef(false);
const [data, setData] = useState<Awaited<
ReturnType<typeof fetchData>
> | null>(null);

useEffect(() => {
if (!startedRef.current) {
startedRef.current = true;

void fetchData(props.id)
.then(setData)
.catch(() => null);
}
}, [props.id]);

if (data === null) {
return null;
}

return data.user ? (
<Flex align="center" gap="1">
<Avatar
fallback={<CgProfile />}
radius="full"
size="1"
src={data.user.avatar_url ?? ''}
/>

<Text color="gray" size="1">
Generated by <Text highContrast>{data.user.display_name}</Text>
</Text>
</Flex>
) : (
<Text color="gray" size="1">
Generated by a generous beecast user.
</Text>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,7 @@ export function EpisodeAISummaryGenerator({
);

case 'summarizing':
return (
<EpisodeAISummaryPanel>
<EpisodeAISummaryStreamer id={id} />
</EpisodeAISummaryPanel>
);
return <EpisodeAISummaryStreamer id={id} />;

case 'error':
return (
Expand Down
32 changes: 22 additions & 10 deletions components/episode-ai-summary/episode-ai-summary-streamer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,26 @@

import type { Tables } from '@/types/supabase/database';

import { Flex } from '@radix-ui/themes';
import { useChat } from 'ai/react';
import React, { useEffect, useRef } from 'react';
import React, { useEffect, useRef, useState } from 'react';

import { EpisodeAISummaryFooter } from './episode-ai-summary-footer';
import { EpisodeAISummaryPanel } from './episode-ai-summary-panel';

type Props = {
id: Tables<'episode'>['id'];
};

export function EpisodeAISummaryStreamer({ id }: Props) {
const startedRef = useRef(false);
const [finished, setFinished] = useState(false);

const { messages, reload, setMessages } = useChat({
api: `/api/ai/summarize/${id}`,
onFinish: () => {
setFinished(true);
},
});

useEffect(() => {
Expand All @@ -28,15 +36,19 @@ export function EpisodeAISummaryStreamer({ id }: Props) {

const assistantMessages = messages.filter((m) => m.role === 'assistant');

if (assistantMessages.length === 0) {
return 'Summarizing episode...';
}

return (
<>
{assistantMessages.map((message) => (
<React.Fragment key={message.id}>{message.content}</React.Fragment>
))}
</>
<Flex direction="column" gap="2">
<EpisodeAISummaryPanel>
{assistantMessages.length === 0
? 'Summarizing episode...'
: assistantMessages.map((message) => (
<React.Fragment key={message.id}>
{message.content}
</React.Fragment>
))}
</EpisodeAISummaryPanel>

{finished ? <EpisodeAISummaryFooter id={id} /> : null}
</Flex>
);
}
25 changes: 4 additions & 21 deletions components/episode-ai-summary/episode-ai-summary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ import type { Tables } from '@/types/supabase/database';
import { DatabaseError } from '@/lib/errors';
import { fetchAccountAICredits } from '@/lib/services/account';
import { createSupabaseServerClient } from '@/lib/services/supabase/server';
import { Avatar, Button, Flex, Text } from '@radix-ui/themes';
import { Button, Flex } from '@radix-ui/themes';
import { cookies } from 'next/headers';
import Link from 'next/link';
import { CgDollar, CgProfile } from 'react-icons/cg';
import { CgDollar } from 'react-icons/cg';

import { EpisodeAISummaryFooter } from './episode-ai-summary-footer';
import { EpisodeAISummaryGenerator } from './episode-ai-summary-generator';
import { EpisodeAISummaryPanel } from './episode-ai-summary-panel';
import { EpisodeAISummaryPlaceholder } from './episode-ai-summary-placeholder';
Expand Down Expand Up @@ -52,25 +53,7 @@ export async function EpisodeAISummary(props: Props) {
{episodeContent.text_summary}
</EpisodeAISummaryPanel>

{episodeContent.user ? (
<Flex align="center" gap="1">
<Avatar
fallback={<CgProfile />}
radius="full"
size="1"
src={episodeContent.user.avatar_url ?? ''}
/>

<Text color="gray" size="1">
Generated by{' '}
<Text highContrast>{episodeContent.user.display_name}</Text>
</Text>
</Flex>
) : (
<Text color="gray" size="1">
Generated by a generous beecast user.
</Text>
)}
<EpisodeAISummaryFooter id={props.id} />
</Flex>
);
}

0 comments on commit ae1a9d6

Please sign in to comment.