feat(dashboard): tableau de bord Second Brain configurable avec chargement progressif
Briefing granulaire, pistes rapides puis enrichissement async, layout persisté v5, suggestions agents, intégration Gmail et navigation sidebar alignée sur /home. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -6,6 +6,7 @@ import { NoteChart } from './note-chart'
|
||||
import { suggestCharts, chartSuggestionToMarkdown, type ChartSuggestion, type SuggestChartsResponse } from '@/lib/ai/services/chart-suggestion.service'
|
||||
import { BarChart3, X, Search, AlertCircle, Sparkles } from 'lucide-react'
|
||||
import { cn } from '@/lib/utils'
|
||||
import { useLanguage } from '@/lib/i18n'
|
||||
|
||||
// Chart type to color mapping for visual variety
|
||||
const CHART_TYPE_COLORS: Record<string, string> = {
|
||||
@@ -36,6 +37,7 @@ export function ChartSuggestionsDialog({
|
||||
onClose,
|
||||
onSelectChart,
|
||||
}: ChartSuggestionsDialogProps) {
|
||||
const { t } = useLanguage()
|
||||
const [response, setResponse] = useState<SuggestChartsResponse | null>(null)
|
||||
const [loading, setLoading] = useState(false)
|
||||
const [selectedIndex, setSelectedIndex] = useState<number | null>(null)
|
||||
@@ -127,12 +129,12 @@ export function ChartSuggestionsDialog({
|
||||
{loading ? (
|
||||
<span className="flex items-center gap-2">
|
||||
<Search className="w-3 h-3 animate-spin" />
|
||||
Analyzing {isAnalyzingSelection ? 'selection' : 'note'} ({wordCount} words)...
|
||||
{isAnalyzingSelection ? t('chart.analyzingSelection') : t('chart.analyzingNote')} ({wordCount} {t('chart.words')})...
|
||||
</span>
|
||||
) : response?.hasData ? (
|
||||
`Found ${response?.detectedData || 'data'}`
|
||||
`${t('chart.found')} ${response?.detectedData || ''}`
|
||||
) : (
|
||||
'No data detected'
|
||||
t('chart.noDataDetected')
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
@@ -140,7 +142,7 @@ export function ChartSuggestionsDialog({
|
||||
<button
|
||||
onClick={onClose}
|
||||
className="p-2 hover:bg-muted rounded-lg transition-colors"
|
||||
aria-label="Close"
|
||||
aria-label={t('common.close')}
|
||||
>
|
||||
<X className="w-5 h-5" />
|
||||
</button>
|
||||
@@ -152,7 +154,7 @@ export function ChartSuggestionsDialog({
|
||||
<div className="flex items-center justify-center py-12">
|
||||
<div className="text-center">
|
||||
<Search className="w-12 h-12 mx-auto mb-4 text-muted-foreground animate-pulse" />
|
||||
<p className="text-muted-foreground">Analyzing your content for chart data...</p>
|
||||
<p className="text-muted-foreground">{t('chart.analyzing')}</p>
|
||||
</div>
|
||||
</div>
|
||||
) : response?.quotaExceeded ? (
|
||||
@@ -167,7 +169,7 @@ export function ChartSuggestionsDialog({
|
||||
className="px-4 py-2 bg-blue-500 text-white rounded-lg hover:bg-blue-600 transition-colors"
|
||||
onClick={() => (window.location.href = '/settings/billing')}
|
||||
>
|
||||
Upgrade Plan
|
||||
{t('ai.featureLocked')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -175,10 +177,10 @@ export function ChartSuggestionsDialog({
|
||||
<div className="flex items-center justify-center py-12">
|
||||
<div className="text-center max-w-md">
|
||||
<AlertCircle className="w-12 h-12 mx-auto mb-4 text-destructive" />
|
||||
<h3 className="text-lg font-semibold mb-2">Error</h3>
|
||||
<h3 className="text-lg font-semibold mb-2">{t('common.error')}</h3>
|
||||
<p className="text-sm text-muted-foreground mb-2">{response.error}</p>
|
||||
<details className="text-left text-xs text-muted-foreground mt-4">
|
||||
<summary className="cursor-pointer hover:text-foreground">Debug info</summary>
|
||||
<summary className="cursor-pointer hover:text-foreground">{t('chart.debugInfo')}</summary>
|
||||
<pre className="mt-2 bg-muted p-2 rounded overflow-auto max-h-32">
|
||||
analyzedText: {response.analyzedText}
|
||||
{'\n'}detectedData: {response.detectedData}
|
||||
@@ -190,20 +192,20 @@ export function ChartSuggestionsDialog({
|
||||
<div className="flex items-center justify-center py-12">
|
||||
<div className="text-center max-w-md">
|
||||
<AlertCircle className="w-12 h-12 mx-auto mb-4 text-muted-foreground" />
|
||||
<h3 className="text-lg font-semibold mb-2">No Data Detected</h3>
|
||||
<h3 className="text-lg font-semibold mb-2">{t('chart.noDataDetected')}</h3>
|
||||
<p className="text-muted-foreground mb-4">
|
||||
Try adding numerical data to your note. Charts work best with:
|
||||
{t('chart.noDataHint')}
|
||||
</p>
|
||||
<ul className="text-sm text-muted-foreground text-left inline-block">
|
||||
<li>• Sales figures, metrics, or measurements</li>
|
||||
<li>• Lists with values (e.g., "Jan: 5000, Feb: 7500")</li>
|
||||
<li>• Percentages or proportions</li>
|
||||
<li>• Time-series data</li>
|
||||
<li>{t('chart.dataHint1')}</li>
|
||||
<li>{t('chart.dataHint2')}</li>
|
||||
<li>{t('chart.dataHint3')}</li>
|
||||
<li>{t('chart.dataHint4')}</li>
|
||||
</ul>
|
||||
<div className="mt-4 pt-4 border-t border-border/50">
|
||||
<details className="text-left">
|
||||
<summary className="text-xs text-muted-foreground cursor-pointer hover:text-foreground">
|
||||
Debug: Show what was analyzed
|
||||
{t('chart.debugShowAnalyzed')}
|
||||
</summary>
|
||||
<pre className="mt-2 text-xs bg-muted p-2 rounded overflow-auto max-h-32">
|
||||
{textToAnalyze.substring(0, 500)}
|
||||
@@ -276,7 +278,7 @@ export function ChartSuggestionsDialog({
|
||||
{/* Data preview */}
|
||||
<div className="mt-2 pt-2 border-t border-border/50">
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{suggestion.data.length} data points
|
||||
{suggestion.data.length} {t('chart.dataPoints')}
|
||||
</p>
|
||||
</div>
|
||||
</button>
|
||||
@@ -286,9 +288,9 @@ export function ChartSuggestionsDialog({
|
||||
|
||||
{/* Keyboard hint */}
|
||||
<div className="flex items-center justify-center gap-4 pt-4 text-xs text-muted-foreground">
|
||||
<span>← → Navigate</span>
|
||||
<span>↵ Select</span>
|
||||
<span>Esc Cancel</span>
|
||||
<span>{t('chart.navigateHint')}</span>
|
||||
<span>{t('chart.selectHint')}</span>
|
||||
<span>{t('chart.escCancel')}</span>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user