Files
Momento/architectural-grid1/src/components/TemporalView.tsx
Antigravity f46654f574 feat: editor improvements and architectural grid prototype
Multiple feature additions and improvements across the application:

- NextGen Editor: drag handles, smart paste, block actions
- Structured views: Kanban and table layouts for notes
- Architectural Grid: new brainstorming/agent interface prototype
- Flashcards: SM-2 revision algorithm with AI generation
- MCP server: robustness improvements
- Graph/PDF chat: fix click propagation and copy behavior
- Various UI/UX enhancements and bug fixes

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 19:45:15 +00:00

170 lines
8.4 KiB
TypeScript

import React, { useMemo } from 'react';
import { motion } from 'motion/react';
import {
Clock,
Calendar,
TrendingUp,
Zap,
History,
ArrowRight,
Sparkles,
PieChart
} from 'lucide-react';
import { Note, NoteAccessLog, NotePrediction } from '../types';
import { predictNextAccess, detectAccessCycle } from '../services/temporalService';
interface TemporalViewProps {
notes: Note[];
accessLogs: NoteAccessLog[];
onNoteSelect: (id: string) => void;
}
export const TemporalView: React.FC<TemporalViewProps> = ({ notes, accessLogs, onNoteSelect }) => {
const predictions = useMemo(() => {
return notes
.map(note => {
const noteLogs = accessLogs.filter(l => l.noteId === note.id);
const prediction = predictNextAccess(note, noteLogs);
return { note, prediction };
})
.filter(p => p.prediction !== null) as { note: Note; prediction: NotePrediction }[];
}, [notes, accessLogs]);
const cyclicalNotes = useMemo(() => {
return notes
.map(note => {
const noteLogs = accessLogs.filter(l => l.noteId === note.id);
const cycle = detectAccessCycle(noteLogs);
return { note, cycle };
})
.filter(p => p.cycle !== null) as { note: Note; cycle: number }[];
}, [notes, accessLogs]);
return (
<div className="h-full flex flex-col bg-paper dark:bg-[#0A0A0A] overflow-hidden">
<div className="p-8 border-b border-border/40 backdrop-blur-xl bg-white/40 dark:bg-black/20 z-10">
<div className="flex items-center gap-3 mb-1">
<div className="w-8 h-8 rounded-lg bg-rose-500/10 flex items-center justify-center text-rose-500">
<Clock size={18} />
</div>
<h1 className="text-2xl font-serif font-medium text-ink dark:text-dark-ink">Temporal Forecast</h1>
</div>
<p className="text-[11px] text-concrete tracking-[0.2em] uppercase font-bold">Predicting the recurrence of insight</p>
</div>
<div className="flex-1 overflow-y-auto custom-scrollbar p-8">
<div className="max-w-5xl mx-auto space-y-12">
{/* Daily Briefing / Predictions */}
<section>
<div className="flex items-center gap-2 mb-6">
<Sparkles size={16} className="text-rose-400" />
<h3 className="text-sm font-bold uppercase tracking-widest text-ink dark:text-dark-ink">Intelligence Briefing</h3>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{predictions.map(({ note, prediction }) => (
<motion.div
key={note.id}
whileHover={{ y: -4 }}
onClick={() => onNoteSelect(note.id)}
className="p-6 rounded-2xl bg-white dark:bg-white/5 border border-border/60 hover:border-rose-400/40 transition-all cursor-pointer shadow-sm relative overflow-hidden group"
>
<div className="absolute top-0 right-0 p-3">
<TrendingUp size={14} className="text-rose-400 opacity-40 group-hover:opacity-100 transition-opacity" />
</div>
<div className="flex items-center gap-2 mb-4">
<span className="px-2 py-1 bg-rose-500/10 text-rose-500 text-[10px] font-bold rounded-full uppercase tracking-widest">
Coming Up
</span>
<span className="text-[10px] text-concrete font-medium">
{new Date(prediction.predictedRelevanceDate).toLocaleDateString(undefined, { month: 'short', day: 'numeric' })}
</span>
</div>
<h4 className="text-lg font-serif font-medium text-ink dark:text-dark-ink mb-2 group-hover:text-rose-500 transition-colors uppercase tracking-tight">{note.title}</h4>
<p className="text-xs text-muted-ink leading-relaxed mb-6 italic">
"{prediction.reason}"
</p>
<div className="pt-4 border-t border-border/40 flex items-center justify-between">
<span className="text-[10px] font-bold text-concrete uppercase tracking-widest">Confidence {Math.round(prediction.confidence * 100)}%</span>
<ArrowRight size={14} className="text-concrete group-hover:text-ink" />
</div>
</motion.div>
))}
{predictions.length === 0 && (
<div className="col-span-full p-12 text-center bg-paper dark:bg-white/5 border-2 border-dashed border-border rounded-3xl">
<Calendar size={40} className="mx-auto text-concrete/40 mb-4" />
<h5 className="text-ink dark:text-dark-ink font-medium mb-1">No upcoming predictions</h5>
<p className="text-xs text-concrete">The system needs more usage data to find cyclical patterns in your research.</p>
</div>
)}
</div>
</section>
{/* Cyclical Patterns */}
<section>
<div className="flex items-center gap-2 mb-6">
<History size={16} className="text-indigo-400" />
<h3 className="text-sm font-bold uppercase tracking-widest text-ink dark:text-dark-ink">Detected Cycles</h3>
</div>
<div className="space-y-3">
{cyclicalNotes.map(({ note, cycle }) => (
<div key={note.id} className="flex items-center gap-4 p-4 rounded-xl bg-slate-50 dark:bg-white/5 border border-border/40">
<div className="w-12 h-12 rounded-xl bg-white dark:bg-black/20 border border-border flex items-center justify-center flex-col shadow-sm">
<span className="text-xs font-bold text-ink dark:text-dark-ink">{Math.round(cycle)}</span>
<span className="text-[8px] font-bold text-concrete uppercase">days</span>
</div>
<div className="flex-1">
<h5 className="text-sm font-medium text-ink dark:text-dark-ink">{note.title}</h5>
<div className="flex items-center gap-3">
<span className="text-[10px] text-concrete">Recurring theme in your architectural process</span>
<div className="h-1 w-24 bg-border/40 rounded-full overflow-hidden">
<div className="h-full bg-rose-400" style={{ width: '65%' }}></div>
</div>
</div>
</div>
<button onClick={() => onNoteSelect(note.id)} className="p-2 hover:bg-black/5 rounded-full">
<ArrowRight size={16} className="text-concrete" />
</button>
</div>
))}
</div>
</section>
{/* Productivity Stats */}
<section className="bg-ink dark:bg-white/5 rounded-3xl p-8 text-paper relative overflow-hidden">
<div className="relative z-10 grid grid-cols-1 md:grid-cols-3 gap-8">
<div>
<h6 className="text-[10px] font-bold uppercase tracking-[0.2em] opacity-60 mb-2">Memory Strength</h6>
<div className="text-4xl font-serif">84%</div>
<p className="text-[10px] opacity-60 mt-2">Active connections in your semantic network</p>
</div>
<div>
<h6 className="text-[10px] font-bold uppercase tracking-[0.2em] opacity-60 mb-2">Peak Cycle</h6>
<div className="text-4xl font-serif">28 Days</div>
<p className="text-[10px] opacity-60 mt-2">The rhythm of your creative output</p>
</div>
<div className="flex flex-col justify-center">
<div className="flex items-center gap-2 mb-4">
<div className="w-2 h-2 rounded-full bg-rose-400"></div>
<span className="text-xs font-medium">4 Notes resurfacing this week</span>
</div>
<button className="w-full py-2 bg-paper text-ink rounded-xl text-[10px] font-bold uppercase tracking-widest hover:scale-105 transition-transform">
Build Morning Briefing
</button>
</div>
</div>
<div className="absolute top-0 right-0 w-64 h-64 bg-rose-500/10 blur-[80px] rounded-full -mr-20 -mt-20"></div>
</section>
</div>
</div>
</div>
);
};