import React, { FC, useCallback, useMemo, useState } from 'react'; import { useUser } from '@gitroom/frontend/components/layout/user.context'; import { useRouter } from 'next/navigation'; import { deleteDialog } from '@gitroom/react/helpers/delete.dialog'; import { useModals } from '@mantine/modals'; import { FormProvider, SubmitHandler, useForm } from 'react-hook-form'; import { classValidatorResolver } from '@hookform/resolvers/class-validator'; import { GeneratorDto } from '@gitroom/nestjs-libraries/dtos/generator/generator.dto'; import { Button } from '@gitroom/react/form/button'; import { useFetch } from '@gitroom/helpers/utils/custom.fetch'; import { Textarea } from '@gitroom/react/form/textarea'; import { Checkbox } from '@gitroom/react/form/checkbox'; import clsx from 'clsx'; import { CalendarWeekProvider, useCalendar, } from '@gitroom/frontend/components/launches/calendar.context'; import dayjs from 'dayjs'; import { Select } from '@gitroom/react/form/select'; import { useT } from '@gitroom/react/translation/get.transation.service.client'; import { AddEditModal } from '@gitroom/frontend/components/new-launch/add.edit.modal'; const FirstStep: FC = (props) => { const { integrations, reloadCalendarView } = useCalendar(); const modal = useModals(); const fetch = useFetch(); const [loading, setLoading] = useState(false); const [showStep, setShowStep] = useState(''); const t = useT(); const resolver = useMemo(() => { return classValidatorResolver(GeneratorDto); }, []); const form = useForm({ mode: 'all', resolver, values: { research: '', isPicture: false, format: 'one_short', tone: 'personal', }, }); const [research] = form.watch(['research']); const generateStep = useCallback( async (reader: ReadableStreamDefaultReader) => { const decoder = new TextDecoder('utf-8'); let lastResponse = {} as any; // eslint-disable-next-line no-constant-condition while (true) { const { done, value } = await reader.read(); if (done) return lastResponse.data.output; // Convert chunked binary data to string const chunkStr = decoder.decode(value, { stream: true, }); for (const chunk of chunkStr .split('\n') .filter((f) => f && f.indexOf('{') > -1)) { try { const data = JSON.parse(chunk); switch (data.name) { case 'agent': setShowStep(t('agent_starting', 'Agent starting')); break; case 'research': setShowStep( t('researching_your_content', 'Researching your content...') ); break; case 'find-category': setShowStep( t( 'understanding_the_category', 'Understanding the category...' ) ); break; case 'find-topic': setShowStep(t('finding_the_topic', 'Finding the topic...')); break; case 'find-popular-posts': setShowStep( t( 'finding_popular_posts_to_match_with', 'Finding popular posts to match with...' ) ); break; case 'generate-hook': setShowStep(t('generating_hook', 'Generating hook...')); break; case 'generate-content': setShowStep(t('generating_content', 'Generating content...')); break; case 'generate-picture': setShowStep(t('generating_pictures', 'Generating pictures...')); break; case 'upload-pictures': setShowStep(t('uploading_pictures', 'Uploading pictures...')); break; case 'post-time': setShowStep( t('finding_time_to_post', 'Finding time to post...') ); break; } lastResponse = data; } catch (e) { /** don't do anything **/ } } } }, [t] ); const onSubmit: SubmitHandler<{ research: string; }> = useCallback( async (value) => { setLoading(true); const response = await fetch('/posts/generator', { method: 'POST', body: JSON.stringify(value), }); if (!response.body) { return; } const reader = response.body.getReader(); const load = await generateStep(reader); const messages = load.content.map((p: any, index: number) => { if (index === 0) { return { content: load.hook + '\n' + p.content, ...(p?.image?.path ? { image: [p.image], } : {}), }; } return { content: p.content, ...(p?.image?.path ? { image: [p.image], } : {}), }; }); setShowStep(''); modal.openModal({ closeOnClickOutside: false, closeOnEscape: false, withCloseButton: false, classNames: { modal: 'w-[100%] max-w-[1400px] bg-transparent text-textColor', }, children: ( ({ ...p, }))} integrations={integrations.slice(0).map((p) => ({ ...p, }))} mutate={reloadCalendarView} date={dayjs.utc(load.date).local()} reopenModal={() => ({})} onlyValues={messages} /> ), size: '80%', }); setLoading(false); }, [integrations, reloadCalendarView] ); return (
{!showStep ? (
 
) : (
{showStep}
)}