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:
126
memento-note/components/dashboard-action-strip.tsx
Normal file
126
memento-note/components/dashboard-action-strip.tsx
Normal file
@@ -0,0 +1,126 @@
|
||||
'use client'
|
||||
|
||||
import { motion } from 'motion/react'
|
||||
import { Inbox, GraduationCap, Bell, Sparkles, Layers } from 'lucide-react'
|
||||
import { useLanguage } from '@/lib/i18n'
|
||||
|
||||
export interface DashboardActionStripProps {
|
||||
inboxCount: number
|
||||
dueFlashcards: number
|
||||
reminderCount: number
|
||||
discoveryCount: number
|
||||
themeCount: number
|
||||
inboxPulse?: number
|
||||
onInbox: () => void
|
||||
onReview: () => void
|
||||
onReminders: () => void
|
||||
onDiscoveries: () => void
|
||||
onThemes: () => void
|
||||
prefersReducedMotion?: boolean
|
||||
}
|
||||
|
||||
export function DashboardActionStrip({
|
||||
inboxCount,
|
||||
dueFlashcards,
|
||||
reminderCount,
|
||||
discoveryCount,
|
||||
themeCount,
|
||||
inboxPulse = 0,
|
||||
onInbox,
|
||||
onReview,
|
||||
onReminders,
|
||||
onDiscoveries,
|
||||
onThemes,
|
||||
prefersReducedMotion,
|
||||
}: DashboardActionStripProps) {
|
||||
const { t } = useLanguage()
|
||||
|
||||
const items = [
|
||||
{
|
||||
key: 'inbox',
|
||||
icon: Inbox,
|
||||
label: t('homeDashboard.inbox'),
|
||||
value: inboxCount,
|
||||
onClick: onInbox,
|
||||
accent: inboxCount > 0,
|
||||
pulse: inboxPulse > 0,
|
||||
},
|
||||
{
|
||||
key: 'review',
|
||||
icon: GraduationCap,
|
||||
label: t('homeDashboard.review'),
|
||||
value: dueFlashcards,
|
||||
onClick: onReview,
|
||||
accent: dueFlashcards > 0,
|
||||
},
|
||||
{
|
||||
key: 'reminders',
|
||||
icon: Bell,
|
||||
label: t('homeDashboard.reminders'),
|
||||
value: reminderCount,
|
||||
onClick: onReminders,
|
||||
accent: reminderCount > 0,
|
||||
},
|
||||
{
|
||||
key: 'discoveries',
|
||||
icon: Sparkles,
|
||||
label: t('homeDashboard.aiFound'),
|
||||
value: discoveryCount,
|
||||
onClick: onDiscoveries,
|
||||
accent: discoveryCount > 0,
|
||||
},
|
||||
{
|
||||
key: 'themes',
|
||||
icon: Layers,
|
||||
label: t('homeDashboard.themes'),
|
||||
value: themeCount,
|
||||
onClick: onThemes,
|
||||
accent: themeCount > 0,
|
||||
},
|
||||
]
|
||||
|
||||
return (
|
||||
<div className="flex gap-2 overflow-x-auto custom-scrollbar pb-0.5 -mx-0.5 px-0.5">
|
||||
{items.map(item => {
|
||||
const Icon = item.icon
|
||||
const Wrapper = item.pulse && !prefersReducedMotion ? motion.button : 'button'
|
||||
const motionProps = item.pulse && !prefersReducedMotion
|
||||
? {
|
||||
key: `inbox-pulse-${inboxPulse}`,
|
||||
animate: { scale: [1, 1.03, 1] },
|
||||
transition: { duration: 0.45 },
|
||||
}
|
||||
: {}
|
||||
return (
|
||||
<Wrapper
|
||||
key={item.key}
|
||||
type="button"
|
||||
onClick={item.onClick}
|
||||
{...motionProps}
|
||||
className={`shrink-0 flex items-center gap-2.5 px-3.5 py-2.5 rounded-xl border transition-all text-start min-w-[108px] ${
|
||||
item.accent
|
||||
? 'border-brand-accent/30 bg-brand-accent/[0.06] hover:border-brand-accent/50 hover:bg-brand-accent/10 shadow-sm'
|
||||
: 'border-border/25 bg-white/60 dark:bg-zinc-900/40 hover:border-border/50'
|
||||
}`}
|
||||
>
|
||||
<div className={`w-7 h-7 rounded-lg flex items-center justify-center shrink-0 ${
|
||||
item.accent ? 'bg-brand-accent/15 text-brand-accent' : 'bg-stone-100 dark:bg-zinc-800 text-concrete'
|
||||
}`}>
|
||||
<Icon size={13} strokeWidth={2} />
|
||||
</div>
|
||||
<div className="min-w-0">
|
||||
<p className={`text-lg font-serif font-bold leading-none ${
|
||||
item.accent ? 'text-ink dark:text-dark-ink' : 'text-concrete/80'
|
||||
}`}>
|
||||
{item.value}
|
||||
</p>
|
||||
<p className="text-[8px] font-mono font-bold uppercase tracking-wider text-concrete truncate mt-0.5">
|
||||
{item.label}
|
||||
</p>
|
||||
</div>
|
||||
</Wrapper>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user