import React, { useState, useEffect } from 'react';
import { ChevronLeft, Pin, Clock, Archive, Trash2, Plus, Palette, Type, MoreVertical, Search, Tag, X, Bell, Check } from 'lucide-react';
export default function GoogleKeepApp() {
const [view, setView] = useState('home'); // home, note-view, archive, trash
const [notes, setNotes] = useState([]);
const [selectedNote, setSelectedNote] = useState(null);
const [searchQuery, setSearchQuery] = useState('');
const [showColorPicker, setShowColorPicker] = useState(false);
const [showLabelPicker, setShowLabelPicker] = useState(false);
const [editTitle, setEditTitle] = useState('');
const [editContent, setEditContent] = useState('');
const [editColor, setEditColor] = useState('dark-brown');
const [editLabels, setEditLabels] = useState([]);
const [newLabel, setNewLabel] = useState('');
const [reminder, setReminder] = useState({ date: '', time: '' });
const [allLabels, setAllLabels] = useState([]);
const [selectedLabelFilter, setSelectedLabelFilter] = useState(null);
const themes = {
'dark-brown': {
name: 'Dark Brown',
bg: 'linear-gradient(135deg, #5d4e37 0%, #3d2817 100%)',
text: '#fff',
card: '#4a3f33',
},
black: {
name: 'Black',
bg: 'linear-gradient(135deg, #1a1a1a 0%, #0d0d0d 100%)',
text: '#fff',
card: '#2d2d2d',
},
white: {
name: 'White',
bg: 'linear-gradient(135deg, #f5f5f5 0%, #e8e8e8 100%)',
text: '#000',
card: '#fff',
},
'light-yellow': {
name: 'Light Yellow',
bg: 'linear-gradient(135deg, #fff8dc 0%, #ffeaa7 100%)',
text: '#333',
card: '#fffaf0',
},
'sky-blue': {
name: 'Sky Blue',
bg: 'linear-gradient(135deg, #87ceeb 0%, #4da6d6 100%)',
text: '#fff',
card: '#b0e0e6',
},
pink: {
name: 'Pink',
bg: 'linear-gradient(135deg, #ffb6c1 0%, #ff69b4 100%)',
text: '#fff',
card: '#ffc0cb',
},
purple: {
name: 'Purple',
bg: 'linear-gradient(135deg, #9370db 0%, #6a4c93 100%)',
text: '#fff',
card: '#b19cd9',
},
green: {
name: 'Green',
bg: 'linear-gradient(135deg, #90ee90 0%, #3cb371 100%)',
text: '#fff',
card: '#a8e6a1',
},
orange: {
name: 'Orange',
bg: 'linear-gradient(135deg, #ffa500 0%, #ff8c00 100%)',
text: '#fff',
card: '#ffb84d',
},
red: {
name: 'Red',
bg: 'linear-gradient(135deg, #ff6b6b 0%, #c92a2a 100%)',
text: '#fff',
card: '#ff8787',
},
'sunset': {
name: 'Gradient Sunset',
bg: 'linear-gradient(135deg, #ff6b6b 0%, #ffa94d 50%, #ffd93d 100%)',
text: '#fff',
card: '#ffb366',
},
'ocean': {
name: 'Gradient Ocean',
bg: 'linear-gradient(135deg, #0ea5e9 0%, #06b6d4 50%, #10b981 100%)',
text: '#fff',
card: '#38bdf8',
},
'dark-purple': {
name: 'Gradient Dark Purple',
bg: 'linear-gradient(135deg, #7c3aed 0%, #6d28d9 50%, #3f0f5c 100%)',
text: '#fff',
card: '#a78bfa',
},
'glassmorphism': {
name: 'Glassmorphism',
bg: 'rgba(255, 255, 255, 0.1)',
text: '#fff',
card: 'rgba(255, 255, 255, 0.15)',
backdrop: 'blur(10px)',
},
'neon': {
name: 'Blur Neon',
bg: 'linear-gradient(135deg, #1a1a2e 0%, #16213e 100%)',
text: '#00ff88',
card: '#0f3460',
neon: true,
},
};
// Load notes from localStorage
useEffect(() => {
const savedNotes = localStorage.getItem('googleKeepNotes');
if (savedNotes) {
try {
const parsed = JSON.parse(savedNotes);
setNotes(parsed);
// Extract all labels
const labels = new Set();
parsed.forEach(note => {
note.labels?.forEach(label => labels.add(label));
});
setAllLabels(Array.from(labels));
} catch (e) {
console.error('Error loading notes:', e);
}
}
}, []);
// Save notes to localStorage
useEffect(() => {
localStorage.setItem('googleKeepNotes', JSON.stringify(notes));
}, [notes]);
// Check reminders
useEffect(() => {
const interval = setInterval(() => {
notes.forEach(note => {
if (note.reminder && !note.reminderShown) {
const reminderDate = new Date(note.reminder);
const now = new Date();
if (reminderDate <= now && reminderDate > new Date(now.getTime() - 60000)) {
if ('Notification' in window && Notification.permission === 'granted') {
new Notification('Note Reminder', {
body: note.title || 'Untitled Note',
tag: note.id,
});
}
setNotes(notes.map(n => n.id === note.id ? { ...n, reminderShown: true } : n));
}
}
});
}, 10000);
return () => clearInterval(interval);
}, [notes]);
const createNote = () => {
const newNote = {
id: Date.now(),
title: '',
content: '',
color: 'dark-brown',
pinned: false,
archived: false,
deleted: false,
labels: [],
reminder: null,
reminderShown: false,
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
};
setNotes([newNote, ...notes]);
setSelectedNote(newNote);
setEditTitle('');
setEditContent('');
setEditColor('dark-brown');
setEditLabels([]);
setReminder({ date: '', time: '' });
setView('note-view');
};
const updateNote = (id, updates) => {
setNotes(notes.map(n =>
n.id === id ? { ...n, ...updates, updatedAt: new Date().toISOString() } : n
));
};
const deleteNote = (id) => {
updateNote(id, { deleted: true, archived: false });
};
const archiveNote = (id) => {
updateNote(id, { archived: !notes.find(n => n.id === id)?.archived });
};
const pinNote = (id) => {
updateNote(id, { pinned: !notes.find(n => n.id === id)?.pinned });
};
const permanentlyDelete = (id) => {
setNotes(notes.filter(n => n.id !== id));
};
const restoreNote = (id) => {
updateNote(id, { deleted: false });
};
const openNote = (note) => {
setSelectedNote(note);
setEditTitle(note.title);
setEditContent(note.content);
setEditColor(note.color);
setEditLabels(note.labels || []);
setReminder(note.reminder ? {
date: note.reminder.split('T')[0],
time: note.reminder.split('T')[1]?.substring(0, 5) || ''
} : { date: '', time: '' });
setView('note-view');
};
const saveNote = () => {
if (selectedNote) {
const reminderDateTime = reminder.date && reminder.time
? `${reminder.date}T${reminder.time}`
: null;
updateNote(selectedNote.id, {
title: editTitle || 'Untitled Note',
content: editContent,
color: editColor,
labels: editLabels,
reminder: reminderDateTime,
reminderShown: false,
});
}
};
const closeNote = () => {
saveNote();
setView('home');
setSelectedNote(null);
};
const getFilteredNotes = () => {
let filtered = notes.filter(n => {
if (view === 'archive') return n.archived && !n.deleted;
if (view === 'trash') return n.deleted;
return !n.archived && !n.deleted;
});
// Filter by selected label
if (selectedLabelFilter) {
filtered = filtered.filter(n => n.labels?.includes(selectedLabelFilter));
}
// Filter by search
if (searchQuery) {
const query = searchQuery.toLowerCase();
filtered = filtered.filter(n =>
n.title.toLowerCase().includes(query) ||
n.content.toLowerCase().includes(query)
);
}
// Sort by pinned and date
return filtered.sort((a, b) => {
if (a.pinned !== b.pinned) return a.pinned ? -1 : 1;
return new Date(b.updatedAt) - new Date(a.updatedAt);
});
};
const pinnedNotes = getFilteredNotes().filter(n => n.pinned);
const unpinnedNotes = getFilteredNotes().filter(n => !n.pinned);
const archivedNotesCount = notes.filter(n => n.archived && !n.deleted).length;
const trashedNotesCount = notes.filter(n => n.deleted).length;
const currentTheme = themes[editColor] || themes['dark-brown'];
return (
{/* Note View */}
{view === 'note-view' && selectedNote && (
{/* Header */}
{/* Content Area */}
{
setEditTitle(e.target.value);
saveNote();
}}
placeholder="Title"
style={{
background: 'transparent',
border: 'none',
color: currentTheme.text,
fontSize: '28px',
fontWeight: 'bold',
outline: 'none',
marginBottom: '12px',
textShadow: currentTheme.neon ? '0 0 10px rgba(0, 255, 136, 0.5)' : 'none',
}}
/>
{/* Bottom Toolbar */}
{/* Color Picker */}
{showColorPicker && (
{Object.entries(themes).map(([key, theme]) => (
)}
{/* Label Picker */}
{showLabelPicker && (
setNewLabel(e.target.value)}
onKeyPress={(e) => {
if (e.key === 'Enter' && newLabel) {
setEditLabels([...new Set([...editLabels, newLabel])]);
if (!allLabels.includes(newLabel)) {
setAllLabels([...allLabels, newLabel]);
}
setNewLabel('');
saveNote();
}
}}
placeholder="Add label..."
style={{
width: '100%',
padding: '8px',
background: `${currentTheme.text}20`,
border: 'none',
color: currentTheme.text,
borderRadius: '6px',
outline: 'none',
}}
/>
{allLabels.map(label => (
{
setEditLabels(editLabels.includes(label)
? editLabels.filter(l => l !== label)
: [...editLabels, label]
);
saveNote();
}}
style={{
padding: '8px',
cursor: 'pointer',
background: editLabels.includes(label) ? `${currentTheme.text}30` : 'transparent',
borderRadius: '4px',
marginBottom: '4px',
display: 'flex',
alignItems: 'center',
gap: '8px',
}}
>
{editLabels.includes(label) && }
{label}
))}
)}
)}
{/* Home View */}
{view === 'home' && (
{/* Header */}
Google Keep
{/* Search */}
{/* Labels Filter */}
{allLabels.length > 0 && (
{allLabels.map(label => (
))}
)}
{/* Navigation */}
{/* Notes Grid */}
{pinnedNotes.length > 0 && (
Pinned
{pinnedNotes.map(note => (
))}
)}
{unpinnedNotes.length > 0 && (
{pinnedNotes.length > 0 && (
Others
)}
{unpinnedNotes.map(note => (
))}
)}
{getFilteredNotes().length === 0 && (
No notes yet. Create one to get started!
)}
{/* Trash View */}
{view === 'trash' && (
{getFilteredNotes().map(note => (
{
e.currentTarget.style.background = 'rgba(255,255,255,0.15)';
e.currentTarget.style.transform = 'translateY(-4px)';
}}
onMouseOut={(e) => {
e.currentTarget.style.background = 'rgba(255,255,255,0.1)';
e.currentTarget.style.transform = 'translateY(0)';
}}
>
{note.title}
{note.content}
))}
)}
)}
{/* Archive View */}
{view === 'archive' && (
{getFilteredNotes().map(note => (
))}
)}
{/* Floating Action Button */}
);
}
// Note Card Component
function NoteCard({ note, onOpen, onPin, onDelete, onArchive }) {
const themes = {
'dark-brown': 'linear-gradient(135deg, #5d4e37 0%, #3d2817 100%)',
black: 'linear-gradient(135deg, #1a1a1a 0%, #0d0d0d 100%)',
white: 'linear-gradient(135deg, #f5f5f5 0%, #e8e8e8 100%)',
'light-yellow': 'linear-gradient(135deg, #fff8dc 0%, #ffeaa7 100%)',
'sky-blue': 'linear-gradient(135deg, #87ceeb 0%, #4da6d6 100%)',
pink: 'linear-gradient(135deg, #ffb6c1 0%, #ff69b4 100%)',
purple: 'linear-gradient(135deg, #9370db 0%, #6a4c93 100%)',
green: 'linear-gradient(135deg, #90ee90 0%, #3cb371 100%)',
orange: 'linear-gradient(135deg, #ffa500 0%, #ff8c00 100%)',
red: 'linear-gradient(135deg, #ff6b6b 0%, #c92a2a 100%)',
'sunset': 'linear-gradient(135deg, #ff6b6b 0%, #ffa94d 50%, #ffd93d 100%)',
'ocean': 'linear-gradient(135deg, #0ea5e9 0%, #06b6d4 50%, #10b981 100%)',
'dark-purple': 'linear-gradient(135deg, #7c3aed 0%, #6d28d9 50%, #3f0f5c 100%)',
'glassmorphism': 'rgba(255, 255, 255, 0.1)',
'neon': 'linear-gradient(135deg, #1a1a2e 0%, #16213e 100%)',
};
const getTextColor = (colorKey) => {
if (colorKey === 'white') return '#000';
if (colorKey === 'light-yellow') return '#333';
return '#fff';
};
return (
onOpen(note)}
style={{
background: themes[note.color],
padding: '16px',
borderRadius: '12px',
cursor: 'pointer',
transition: 'all 0.3s',
minHeight: '160px',
display: 'flex',
flexDirection: 'column',
color: getTextColor(note.color),
backdropFilter: note.color === 'glassmorphism' ? 'blur(10px)' : 'none',
border: note.color === 'glassmorphism' ? '1px solid rgba(255,255,255,0.2)' : 'none',
}}
onMouseOver={(e) => {
e.currentTarget.style.transform = 'translateY(-4px)';
e.currentTarget.style.boxShadow = '0 12px 28px rgba(0,0,0,0.3)';
}}
onMouseOut={(e) => {
e.currentTarget.style.transform = 'translateY(0)';
e.currentTarget.style.boxShadow = 'none';
}}
>
{note.title || 'Untitled'}
{note.content || 'No description'}
{note.reminder && (
🔔 {new Date(note.reminder).toLocaleDateString()}
)}
{note.labels && note.labels.length > 0 && (
{note.labels.slice(0, 2).map(label => (
{label}
))}
{note.labels.length > 2 && (
+{note.labels.length - 2}
)}
)}
);
}