removed strict mode, rendering row titles
This commit is contained in:
parent
8bbdcf3673
commit
6e6176af7f
4 changed files with 88 additions and 41 deletions
|
|
@ -27,7 +27,6 @@ body {
|
|||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: "Russo One", sans-serif !important;
|
||||
font-size:1.2rem;
|
||||
}
|
||||
/* App theme containers */
|
||||
.app-dark {
|
||||
|
|
@ -59,7 +58,6 @@ h1, h2, h3, h4, h5, h6 {
|
|||
flex-grow: 2;
|
||||
}
|
||||
.widget-row.condensed {
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-evenly;
|
||||
}
|
||||
.news-widget img {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { useState, useEffect } from 'react';
|
||||
import { useState, useEffect, useRef } from 'react';
|
||||
import { Box, Container, CircularProgress, IconButton, Alert } from '@mui/material';
|
||||
import { Brightness4, Brightness7, Refresh } from '@mui/icons-material';
|
||||
import { fetchAllSources } from '../services/dataFetcher';
|
||||
|
|
@ -18,15 +18,27 @@ function Dashboard({ themeToggle, isDark }) {
|
|||
const [refreshing, setRefreshing] = useState(false);
|
||||
const [tokenUsage, setTokenUsage] = useState(null);
|
||||
const [cacheInfo, setCacheInfo] = useState(null);
|
||||
const isLoadingRef = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
console.log('=== Dashboard mounting, calling loadDashboard ===');
|
||||
loadDashboard();
|
||||
}, []);
|
||||
|
||||
async function loadDashboard(forceRefresh = false) {
|
||||
// Prevent concurrent requests using ref for immediate check
|
||||
if (isLoadingRef.current) {
|
||||
console.log('=== loadDashboard SKIPPED - already in progress ===');
|
||||
console.log('Attempted at:', new Date().toISOString());
|
||||
return;
|
||||
}
|
||||
|
||||
isLoadingRef.current = true;
|
||||
|
||||
try {
|
||||
console.log('=== loadDashboard called ===');
|
||||
console.log('Force refresh:', forceRefresh);
|
||||
console.log('Request timestamp:', new Date().toISOString());
|
||||
setError(null);
|
||||
|
||||
// Check if we already have today's briefing (unless forcing refresh)
|
||||
|
|
@ -126,11 +138,15 @@ function Dashboard({ themeToggle, isDark }) {
|
|||
} finally {
|
||||
setLoading(false);
|
||||
setRefreshing(false);
|
||||
isLoadingRef.current = false;
|
||||
console.log('=== loadDashboard completed at:', new Date().toISOString(), '===');
|
||||
}
|
||||
}
|
||||
|
||||
const handleRefresh = () => {
|
||||
setRefreshing(true);
|
||||
setLoading(true);
|
||||
setLoadingStatus('Refreshing your dashboard...');
|
||||
loadDashboard(true);
|
||||
};
|
||||
|
||||
|
|
@ -221,17 +237,28 @@ function Dashboard({ themeToggle, isDark }) {
|
|||
/>
|
||||
</Box>
|
||||
|
||||
{/* Render rows based on the new data structure */}
|
||||
{/* Render rows based on the data structure */}
|
||||
{Object.entries(sourceData).map(([key, data]) => {
|
||||
// Skip special entries like weather and legacy flat entries
|
||||
if (key === 'weather' || key.startsWith('reddit_') || key.startsWith('rss_') || key.startsWith('source_')) {
|
||||
|
||||
// Skip non-array entries (like weather)
|
||||
if (!Array.isArray(data) || data.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Only process row entries (row1, row2, etc.)
|
||||
if (key.startsWith('row') && Array.isArray(data)) {
|
||||
return (
|
||||
<Box key={key} className="widget-row condensed">
|
||||
return (
|
||||
<Box key={key} sx={{ mb: 2 }}>
|
||||
{/* Display row header if not using legacy row naming */}
|
||||
{!key.startsWith('row') && (
|
||||
<h1 style={{
|
||||
marginBottom: '12px',
|
||||
marginTop: '20px',
|
||||
color: 'inherit',
|
||||
fontWeight: 600
|
||||
}}>
|
||||
{key}
|
||||
</h1>
|
||||
)}
|
||||
<Box className="widget-row condensed">
|
||||
{data.map((widgetData, index) => (
|
||||
<NewsWidget
|
||||
key={`${key}-${index}`}
|
||||
|
|
@ -239,26 +266,9 @@ function Dashboard({ themeToggle, isDark }) {
|
|||
/>
|
||||
))}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
</Box>
|
||||
);
|
||||
})}
|
||||
|
||||
{/* Fallback for legacy format - if no rows detected, render flat structure */}
|
||||
{!Object.keys(sourceData).some(k => k.startsWith('row')) && (
|
||||
<Box className="widget-row condensed">
|
||||
{Object.entries(sourceData).map(([key, data]) => {
|
||||
if (key === 'weather' || !data) return null;
|
||||
return (
|
||||
<NewsWidget
|
||||
key={key}
|
||||
data={data}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</Container>
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,5 @@ import ReactDOM from 'react-dom/client'
|
|||
import App from './App.jsx'
|
||||
|
||||
ReactDOM.createRoot(document.getElementById('root')).render(
|
||||
<React.StrictMode>
|
||||
<App />
|
||||
</React.StrictMode>,
|
||||
)
|
||||
<App />
|
||||
)
|
||||
|
|
|
|||
|
|
@ -123,7 +123,15 @@ CURRENT DATA:
|
|||
- Includes relevant weather information if available
|
||||
- Ends with something engaging or thought-provoking
|
||||
|
||||
Focus on the most newsworthy and interesting items. Don't try to mention everything.`;
|
||||
Focus on the most newsworthy and interesting items. Don't try to mention everything.
|
||||
|
||||
IMPORTANT: Provide your response as valid JSON with exactly two fields:
|
||||
{
|
||||
"fullBriefing": "Your complete 300-400 word friendly briefing text here",
|
||||
"condensedSummary": "A 50-75 word ultra-condensed summary of the key topics and main stories for historical context"
|
||||
}
|
||||
|
||||
The JSON must be properly formatted with escaped quotes where necessary.`;
|
||||
|
||||
return prompt;
|
||||
}
|
||||
|
|
@ -171,13 +179,46 @@ export async function generateBriefing(currentData, previousBriefing) {
|
|||
const prompt = buildBriefingPrompt(currentData, previousBriefing);
|
||||
const result = await callClaude(prompt);
|
||||
|
||||
// Generate condensed summary for historical storage
|
||||
const condensedSummary = await generateCondensedSummary(result.text);
|
||||
|
||||
return {
|
||||
...result,
|
||||
condensedSummary: condensedSummary
|
||||
};
|
||||
// Parse JSON response that now includes both fullBriefing and condensedSummary
|
||||
try {
|
||||
// Strip markdown code blocks if present
|
||||
let jsonText = result.text;
|
||||
if (jsonText.includes('```json')) {
|
||||
jsonText = jsonText.replace(/```json\s*/g, '').replace(/```\s*/g, '');
|
||||
} else if (jsonText.includes('```')) {
|
||||
jsonText = jsonText.replace(/```\s*/g, '');
|
||||
}
|
||||
jsonText = jsonText.trim();
|
||||
|
||||
const parsed = JSON.parse(jsonText);
|
||||
|
||||
// Validate the JSON structure
|
||||
if (!parsed.fullBriefing || !parsed.condensedSummary) {
|
||||
throw new Error('Invalid response structure from Claude');
|
||||
}
|
||||
|
||||
console.log('Successfully parsed briefing with condensed summary');
|
||||
console.log('Condensed summary:', parsed.condensedSummary.substring(0, 100) + '...');
|
||||
|
||||
return {
|
||||
text: parsed.fullBriefing,
|
||||
condensedSummary: parsed.condensedSummary,
|
||||
usage: result.usage
|
||||
};
|
||||
} catch (parseError) {
|
||||
console.error('Failed to parse JSON response, attempting fallback:', parseError);
|
||||
|
||||
// Fallback: if JSON parsing fails, use the raw text and generate summary separately
|
||||
// This maintains backward compatibility but should rarely happen
|
||||
console.warn('Using fallback: generating condensed summary separately');
|
||||
const condensedSummary = await generateCondensedSummary(result.text);
|
||||
|
||||
return {
|
||||
text: result.text,
|
||||
condensedSummary: condensedSummary,
|
||||
usage: result.usage
|
||||
};
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error generating briefing:', error);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue