feat(Nextjs): Stream scroll in outline stream

This commit is contained in:
shiva raj badu 2025-07-16 21:08:05 +05:45
parent e6b69229e3
commit f4775fecc1
6 changed files with 26 additions and 9 deletions

View file

@ -6,6 +6,7 @@ import { useDispatch, useSelector } from "react-redux"
import { deleteSlideOutline, setOutlines, SlideOutline } from "@/store/slices/presentationGeneration"
import ToolTip from "@/components/ToolTip"
import MarkdownEditor from "../../components/MarkdownEditor"
import { useEffect } from "react"
interface OutlineItemProps {
@ -24,6 +25,19 @@ export function OutlineItem({
} = useSelector((state: RootState) => state.presentationGeneration);
const dispatch = useDispatch()
useEffect(() => {
if (isStreaming && slideOutline.body) {
const outlineItem = document.getElementById(`outline-item-${index}`);
if (outlineItem) {
outlineItem.scrollIntoView({
behavior: "smooth",
block: "center",
inline: "nearest",
});
}
}
}, [outlines.length]);
const handleSlideChange = (newOutline: SlideOutline) => {
if (isStreaming) return;
const newData = outlines?.map((each, idx) => {
@ -60,6 +74,8 @@ export function OutlineItem({
}
return (
<div className="mb-2 bg-[#F9F9F9]">
{/* Main Title Row */}
@ -84,7 +100,7 @@ export function OutlineItem({
</div>
{/* Main Title Input - Add onFocus handler */}
<div className="flex flex-col basis-full gap-2">
<div id={`outline-item-${index}`} className="flex flex-col basis-full gap-2">
<input
type="text"
value={slideOutline.title || ''}

View file

@ -242,12 +242,15 @@ const OutlinePage = () => {
if (!presentation_id) {
return (
<Wrapper>
<div className="max-w-[1000px] mx-auto px-4 sm:px-6 pb-6">
<div className="max-w-[1000px] min-h-screen flex justify-center items-center mx-auto px-4 sm:px-6 pb-6">
<div className="mt-4 sm:mt-8 font-instrument_sans text-center">
<h4 className="text-lg sm:text-xl font-medium mb-4">
No Presentation ID Found
</h4>
<p className="text-gray-600">Please start a new presentation.</p>
<p className="text-gray-600 mb-4">Please start a new presentation.</p>
<Button onClick={() => router.push("/upload")} className="bg-[#5146E5] w-full rounded-xl text-base sm:text-lg py-4 sm:py-6 transition-all duration-300 font-roboto font-semibold hover:bg-[#5146E5]/80 text-white mt-4 disabled:opacity-50 disabled:cursor-not-allowed">
Start New Presentation
</Button>
</div>
</div>
</Wrapper>

View file

@ -18,7 +18,6 @@ import NewSlide from "../../components/slide_layouts/NewSlide";
import { getEmptySlideContent } from "../../utils/NewSlideContent";
import useLayoutSchema from "../../hooks/useLayoutSchema";
import dynamic from "next/dynamic";
import FirstSlideLayout from "@/components/layouts/FirstSlideLayout";
interface SlideContentProps {
slide: Slide;
@ -117,7 +116,7 @@ const SlideContent = ({
const renderLayout = (slide: any) => {
const layoutName = idMapFileNames[slide.layoutId];
const Layout = dynamic(() => import(`@/components/layouts/${layoutName}.tsx`));
const Layout = dynamic(() => import(`@/components/layouts/${layoutName}`)) as React.ComponentType<{ data: any }>;
return <Layout data={slide.content} />
};

View file

@ -39,7 +39,6 @@ const bulletPointSlideSchema = z.object({
})
export const Schema = bulletPointSlideSchema
console.log(z.toJSONSchema(Schema))
export type BulletPointSlideData = z.infer<typeof bulletPointSlideSchema>

View file

@ -24,7 +24,7 @@ const conclusionSlideSchema = z.object({
description: "Optional call to action or next steps",
}),
contactInfo: z.object({
email: z.string().email().optional().meta({
email: z.email().optional().meta({
description: "Contact email",
}),
phone: z.string().min(5).max(50).optional().meta({

View file

@ -25,10 +25,10 @@ const teamSlideSchema = z.object({
bio: z.string().min(10).max(300).optional().meta({
description: "Brief biography or description",
}),
email: z.email().optional().meta({
email: z.string().email().optional().meta({
description: "Contact email",
}),
linkedin: z.url().optional().meta({
linkedin: z.string().url().optional().meta({
description: "LinkedIn profile URL",
})
})).min(1).max(6).default([