What You'll Build
A complete React frontend: text input, three analysis buttons, loading spinner, and a results panel that displays summary, key points, and generated questions in a clean layout.
1
Section 1 · 10 min
React + Axios Setup
javascriptsrc/App.js
import { useState } from 'react';
import axios from 'axios';
const API = 'http://localhost:8000';
function App() {
const [text, setText] = useState('');
const [result, setResult] = useState(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const callAPI = async (endpoint) => {
setLoading(true); setError(null);
try {
const res = await axios.post(`${API}/${endpoint}`, { text });
setResult(res.data);
} catch (e) {
setError(e.response?.data?.detail || 'Something went wrong');
} finally {
setLoading(false);
}
};2
Section 2 · 15 min
The JSX Template
javascriptsrc/App.js (continued)
return (
<div style={{maxWidth:'760px',margin:'0 auto',padding:'40px 20px'}}>
<h1>AI Document Analyzer</h1>
<textarea
value={text}
onChange={e => setText(e.target.value)}
placeholder="Paste your text here..."
rows={8}
style={{width:'100%',padding:'12px',fontSize:'15px'}}
/>
<div style={{display:'flex',gap:'10px',marginTop:'12px'}}>
{['analyze', 'summarize', 'questions'].map(ep => (
<button key={ep} onClick={() => callAPI(ep)}
disabled={loading || !text}
style={{padding:'10px 20px',textTransform:'capitalize'}}>
{loading ? 'Loading...' : ep}
</button>
))}
</div>
{error && <p style={{color:'red'}}>{error}</p>}
{result && <pre>{JSON.stringify(result, null, 2)}</pre>}
</div>
);
}
export default App;3
Section 3 · 20 min
Better Results Display
Replace the raw JSON display with a proper UI that renders each result type correctly:
javascriptsrc/ResultPanel.js
function ResultPanel({ result }) {
if (!result) return null;
return (
<div style={{marginTop:'24px',padding:'20px',border:'1px solid #e0e0e0',borderRadius:'8px'}}>
{result.summary &&
<div><h3>Summary</h3><p>{result.summary}</p></div>}
{result.key_points?.length > 0 &&
<div><h3>Key Points</h3>
<ul>{result.key_points.map((pt,i) =>
<li key={i}>{pt}</li>
)}</ul></div>}
{result.sentiment &&
<p>Sentiment: <strong>{result.sentiment}</strong></p>}
</div>
);
}
export default ResultPanel;What You Learned Today
- How React state management works: useState for text, result, loading, and error
- The callAPI pattern: setLoading → try/catch axios → setResult/setError → finally setLoading(false)
- How to render different result shapes conditionally using optional chaining (?.)
- Why disabling buttons during loading prevents double-submission bugs
Your Challenge
Go Further on Your Own
- Add a character counter below the textarea that shows current length and max allowed
- Add a 'Clear' button that resets text and result to empty
- Build a tabbed results view: when the user runs multiple analyses on the same text, show each result in a separate tab
Day 3 Complete
Nice work. Keep going.
Day 4 is ready when you are.
Continue to Day 4Want live instruction and hands-on projects? Join the AI bootcamp — 3 days, 5 cities.