Published: Apr 30, 2025, 10:43 AM
Technical documentation of AI ChatBot for movie recommendations.
The ChatBox folder contains a complete implementation of the chat interface, focusing on movie recommendations. The component is built on React and TypeScript, using modern React features such as hooks and context.
The folder is well organised and the components are divided by functionality:
ChatBox.tsx
: the main chat interface container.MessageList.tsx
: the message list display.InputArea.tsx
: user input areaScrollableArea.tsx: auto-scrollable
areaMovieSearchProvider.tsx
: movie search function providerInitialRecommendationProvider.tsx
: Initial Movie Recommendation ProviderThinkingIndicator.tsx
: thinking/generating indicatorInitialRecommendation.tsx
: initial recommendation presentation componenttypes.ts
: type definitionsindex.ts
: export all componentsThinkingIndicator.module.css
: style fileRole: ChatBox is the main container component of the entire chat interface, responsible for coordinating the various sub-components and managing the chat state.
Implementation principle:
useChat
hook to handle chat logic, connect to /api/chat
API endpoint.isGenerating
state to differentiate between loaded and generating replies.MessageList
, ScrollableArea
and InputArea
to create a complete chat experience.Key Code:
const { messages, input, handleInputChange, handleSubmit, isLoading } = useChat({
api: '/api/chat',
})
<MovieSearchProvider messages={messages}>
{({ movieSearches, loadingMovies }) => (
<InitialRecommendationProvider messages={messages}>
{/* Rendering message lists and input fields */}
</InitialRecommendationProvider>
)}
</MovieSearchProvider>
What it does: Displays a list of chat messages, including user and helper messages, and embedded movie search results.
Implementation Principle:
[MOVIE_SEARCH:Movie name]
.Key Logic:
// Formatting Message Content
const formatMessageContent = (content: string) => {
const cleanedContent = content.replace(/\\n\\nRecommended Movies:[\\s\\S]*/, '')
return cleanedContent.replace(MOVIE_SEARCH_REGEX, '')
}
// Rendering Movie Cards
const renderMovieCards = (content: string) => {
// Finds all [MOVIE_SEARCH:Movie Name] modes and renders the corresponding movie cards
}
Purpose: Provides the user input area, including the text input box and submit button.
Implementation Principle:
useRef
and useEffect
to automatically adjust the height of the input area.Key Code:
// Adjust the height of the text box
useEffect(() => {
const textarea = textareaRef.current
if (textarea) {
textarea.style.height = 'auto'
const newHeight = Math.min(Math.max(textarea.scrollHeight, 40), 200)
textarea.style.height = `${newHeight}px`
}
}, [input])
Function: Provides movie search function, parses movie search request in chat message and gets movie data.
Implementation Principle:
Key Logic:
// Extract movie search mode
for (const message of messages) {
if (message.role === 'assistant' && message.content) {
let match
const regex = new RegExp(MOVIE_SEARCH_REGEX)
while ((match = regex.exec(message.content)) !== null) {
const movieTitle = match[1].trim()
// Get movie data
}
}
}
Role: Provide initial movie recommendation before the conversation starts.
Implementation Principle:
getTopRatedMovies()
to get the top movies.Key Code:
// Random selection of movies using the Fisher-Yates shuffle algorithm
for (let i = movies.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1))
;[movies[i], movies[j]] = [movies[j], movies[i]]
}
const top5Movies = movies.slice(0, 5)
What it does: Creates a scrollable area that automatically scrolls to the latest news.
Implementation Principle:
ScrollArea
componentuseRef
and useEffect
to track content changes.Key Code:
useEffect(() => {
const timer = setTimeout(() => {
const scrollAreaElement = scrollAreaRef.current
if (scrollAreaElement) {
const viewport = scrollAreaElement.querySelector<HTMLDivElement>(
'[data-radix-scroll-area-viewport]'
)
if (viewport) {
viewport.scrollTo({ top: viewport.scrollHeight, behavior: 'smooth' })
}
}
}, 50)
return () => clearTimeout(timer)
}, [children])
Purpose: Display the initial movie recommendation list.
Implementation principle:
Purpose: Animated indicator showing the thinking/generating state of the AI.
Implementation Principle:
isGenerating
propertyKey Code:
.dot {
animation: pulse 1.5s infinite ease-in-out;
}
.dot:nth-child(2) {
animation-delay: 0.3s;
}
.dot:nth-child(3) {
animation-delay: 0.6s;
}
What it does: Defines the shared types interface.
Implementation:
export interface MovieResult {
id: number
title: string
poster_path: string | null
release_date: string
overview: string
original_title: string
}
ChatBox is a React and TypeScript based chat interface component that focuses on movie recommendations. It allows users to chat with an AI assistant, get movie recommendations, and display movie info cards. The component uses modern React features and design patterns such as Hooks, Context APIs, and component composition.
ChatBox adopts component combination and Context Provider pattern to realize clear separation of functions and state sharing:
ChatBox
├── MovieSearchProvider
│ └── InitialRecommendationProvider
│ ├── ScrollableArea
│ │ └── MessageList
│ │ └── MovieHorizontalCard(s)
│ └── InputArea
│ └── ThinkingIndicator
└── InitialRecommendation
└── MovieHorizontalCard(s)
[MOVIE_SEARCH:MovieName]
tagstop rated
movies via getTopRatedMovies()
To use ChatBox components in your project:
import { ChatBox } from '@/components/home/ChatBox'
export default function HomePage() {
return (
<div>
<ChatBox />
</div>
)
}