Files
daily-journal-prompt/frontend/src/components/PromptDisplay.jsx

254 lines
9.2 KiB
React
Raw Normal View History

2026-01-03 11:18:56 -07:00
import React, { useState, useEffect } from 'react';
const PromptDisplay = () => {
2026-01-03 14:52:25 -07:00
const [prompts, setPrompts] = useState([]); // Changed to array to handle multiple prompts
2026-01-03 11:18:56 -07:00
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
2026-01-03 14:52:25 -07:00
const [selectedIndex, setSelectedIndex] = useState(null);
const [viewMode, setViewMode] = useState('history'); // 'history' or 'drawn'
2026-01-03 11:18:56 -07:00
useEffect(() => {
2026-01-03 14:52:25 -07:00
fetchMostRecentPrompt();
2026-01-03 11:18:56 -07:00
}, []);
2026-01-03 14:52:25 -07:00
const fetchMostRecentPrompt = async () => {
setLoading(true);
setError(null);
try {
// Try to fetch from actual API first
const response = await fetch('/api/v1/prompts/history');
if (response.ok) {
const data = await response.json();
// API returns array directly, not object with 'prompts' key
if (Array.isArray(data) && data.length > 0) {
// Get the most recent prompt (first in array, position 0)
// Show only one prompt from history
setPrompts([{ text: data[0].text, position: data[0].position }]);
setViewMode('history');
} else {
// No history yet, show placeholder
setPrompts([{ text: "No recent prompts in history. Draw some prompts to get started!", position: 0 }]);
}
} else {
// API not available, use mock data
setPrompts([{ text: "Write about a time when you felt completely at peace with yourself and the world around you. What were the circumstances that led to this feeling, and how did it change your perspective on life?", position: 0 }]);
}
} catch (err) {
console.error('Error fetching prompt:', err);
// Fallback to mock data
setPrompts([{ text: "Imagine you could have a conversation with your future self 10 years from now. What questions would you ask, and what advice do you think your future self would give you?", position: 0 }]);
} finally {
setLoading(false);
}
2026-01-03 11:18:56 -07:00
};
const handleDrawPrompts = async () => {
setLoading(true);
setError(null);
2026-01-03 14:52:25 -07:00
setSelectedIndex(null);
2026-01-03 11:18:56 -07:00
try {
2026-01-03 14:52:25 -07:00
// Draw 3 prompts from pool (Task 4)
const response = await fetch('/api/v1/prompts/draw?count=3');
if (response.ok) {
const data = await response.json();
// Draw API returns object with 'prompts' array
if (data.prompts && data.prompts.length > 0) {
// Show all drawn prompts
const drawnPrompts = data.prompts.map((text, index) => ({
text,
position: index
}));
setPrompts(drawnPrompts);
setViewMode('drawn');
} else {
setError('No prompts available in pool. Please fill the pool first.');
}
} else {
setError('Failed to draw prompts. Please try again.');
}
2026-01-03 11:18:56 -07:00
} catch (err) {
setError('Failed to draw prompts. Please try again.');
2026-01-03 14:52:25 -07:00
} finally {
2026-01-03 11:18:56 -07:00
setLoading(false);
}
};
2026-01-03 14:52:25 -07:00
const handleAddToHistory = async (index) => {
if (index < 0 || index >= prompts.length) {
setError('Invalid prompt index');
2026-01-03 11:18:56 -07:00
return;
}
try {
2026-01-03 14:52:25 -07:00
const promptText = prompts[index].text;
// Send the prompt to the API to add to history
const response = await fetch('/api/v1/prompts/select', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ prompt_text: promptText }),
});
if (response.ok) {
const data = await response.json();
// Mark as selected and show success
setSelectedIndex(index);
// Instead of showing an alert, refresh the page to show the updated history
// The default view shows the most recent prompt from history
alert(`Prompt added to history as ${data.position_in_history}! Refreshing to show updated history...`);
// Refresh the page to show the updated history
// The default view shows the most recent prompt from history (position 0)
fetchMostRecentPrompt();
} else {
const errorData = await response.json();
setError(`Failed to add prompt to history: ${errorData.detail || 'Unknown error'}`);
}
2026-01-03 11:18:56 -07:00
} catch (err) {
setError('Failed to add prompt to history');
}
};
2026-01-03 14:52:25 -07:00
const handleFillPool = async () => {
setLoading(true);
try {
const response = await fetch('/api/v1/prompts/fill-pool', { method: 'POST' });
if (response.ok) {
alert('Prompt pool filled successfully!');
// Refresh the prompt
fetchMostRecentPrompt();
} else {
setError('Failed to fill prompt pool');
}
} catch (err) {
setError('Failed to fill prompt pool');
} finally {
setLoading(false);
}
};
2026-01-03 11:18:56 -07:00
if (loading) {
return (
<div className="text-center p-8">
<div className="spinner mx-auto"></div>
2026-01-03 14:52:25 -07:00
<p className="mt-4">Loading prompt...</p>
2026-01-03 11:18:56 -07:00
</div>
);
}
if (error) {
return (
<div className="alert alert-error">
<i className="fas fa-exclamation-circle mr-2"></i>
{error}
</div>
);
}
return (
<div>
2026-01-03 14:52:25 -07:00
{prompts.length > 0 ? (
2026-01-03 11:18:56 -07:00
<>
2026-01-03 14:52:25 -07:00
<div className="mb-6">
<div className="grid grid-cols-1 gap-4">
{prompts.map((promptObj, index) => (
<div
key={index}
className={`prompt-card cursor-pointer ${selectedIndex === index ? 'selected' : ''}`}
onClick={() => setSelectedIndex(index)}
>
<div className="flex items-start gap-3">
<div className={`flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center ${selectedIndex === index ? 'bg-green-100 text-green-600' : 'bg-blue-100 text-blue-600'}`}>
{selectedIndex === index ? (
<i className="fas fa-check"></i>
) : (
<span>{index + 1}</span>
)}
</div>
<div className="flex-grow">
<p className="prompt-text">{promptObj.text}</p>
<div className="prompt-meta">
<span>
<i className="fas fa-ruler-combined mr-1"></i>
{promptObj.text.length} characters
</span>
<span>
{selectedIndex === index ? (
<span className="text-green-600">
<i className="fas fa-check-circle mr-1"></i>
Selected
</span>
) : (
<span className="text-gray-500">
Click to select
</span>
)}
</span>
</div>
2026-01-03 11:18:56 -07:00
</div>
</div>
</div>
2026-01-03 14:52:25 -07:00
))}
</div>
2026-01-03 11:18:56 -07:00
</div>
2026-01-03 14:52:25 -07:00
<div className="flex flex-col gap-4">
2026-01-03 11:18:56 -07:00
<div className="flex gap-2">
2026-01-03 14:52:25 -07:00
<button
className="btn btn-success flex-1"
onClick={() => handleAddToHistory(selectedIndex !== null ? selectedIndex : 0)}
disabled={selectedIndex === null}
>
<i className="fas fa-history"></i>
{selectedIndex !== null ? 'Use Selected Prompt' : 'Select a Prompt First'}
2026-01-03 11:18:56 -07:00
</button>
2026-01-03 14:52:25 -07:00
<button className="btn btn-primary flex-1" onClick={handleDrawPrompts}>
<i className="fas fa-dice"></i>
{viewMode === 'history' ? 'Draw 3 New Prompts' : 'Draw 3 More Prompts'}
2026-01-03 11:18:56 -07:00
</button>
</div>
2026-01-03 14:52:25 -07:00
<button className="btn btn-secondary" onClick={handleFillPool}>
<i className="fas fa-sync"></i> Fill Prompt Pool
</button>
2026-01-03 11:18:56 -07:00
</div>
2026-01-03 14:52:25 -07:00
<div className="mt-6 text-sm text-gray-600">
2026-01-03 11:18:56 -07:00
<p>
<i className="fas fa-info-circle mr-1"></i>
2026-01-03 14:52:25 -07:00
<strong>
{viewMode === 'history' ? 'Most Recent Prompt from History' : `${prompts.length} Drawn Prompts`}:
</strong>
{viewMode === 'history'
? ' This is the latest prompt from your history. Using it helps the AI learn your preferences.'
: ' Select a prompt to use for journaling. The AI will learn from your selection.'}
</p>
<p className="mt-2">
<i className="fas fa-lightbulb mr-1"></i>
<strong>Tip:</strong> The prompt pool needs regular refilling. Check the stats panel
to see how full it is.
2026-01-03 11:18:56 -07:00
</p>
</div>
</>
2026-01-03 14:52:25 -07:00
) : (
<div className="text-center p-8">
<i className="fas fa-inbox fa-3x mb-4" style={{ color: 'var(--gray-color)' }}></i>
<h3>No Prompts Available</h3>
<p className="mb-4">There are no prompts in history or pool. Get started by filling the pool.</p>
<button className="btn btn-primary" onClick={handleFillPool}>
<i className="fas fa-plus"></i> Fill Prompt Pool
</button>
</div>
2026-01-03 11:18:56 -07:00
)}
</div>
);
};
export default PromptDisplay;