notes / index.html
Lanskik's picture
Cabron pero no está el pinche block de notas - Initial Deployment
d8595a1 verified
Raw
History Blame Contribute Delete
29.1 kB
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>CalcNote - Calculator & Secret Notes</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/2.5.1/jspdf.umd.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
@keyframes float {
0% { transform: translateY(0px); }
50% { transform: translateY(-10px); }
100% { transform: translateY(0px); }
}
.floating {
animation: float 3s ease-in-out infinite;
}
.note-card:hover {
transform: translateY(-5px);
box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1);
}
.bg-glass {
background: rgba(255, 255, 255, 0.25);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
border: 1px solid rgba(255, 255, 255, 0.18);
}
.custom-scrollbar::-webkit-scrollbar {
width: 6px;
}
.custom-scrollbar::-webkit-scrollbar-track {
background: rgba(0, 0, 0, 0.05);
}
.custom-scrollbar::-webkit-scrollbar-thumb {
background: rgba(0, 0, 0, 0.2);
border-radius: 3px;
}
.btn-calculator {
transition: all 0.2s;
box-shadow: inset 0 -2px 0 rgba(0, 0, 0, 0.1);
}
.btn-calculator:active {
transform: translateY(2px);
box-shadow: none;
}
.slide-fade-enter-active, .slide-fade-leave-active {
transition: all 0.3s ease;
}
.slide-fade-enter-from, .slide-fade-leave-to {
transform: translateX(20px);
opacity: 0;
}
.fade-enter-active, .fade-leave-active {
transition: opacity 0.2s ease;
}
.fade-enter-from, .fade-leave-to {
opacity: 0;
}
</style>
</head>
<body class="bg-gradient-to-br from-indigo-100 to-purple-100 min-h-screen flex items-center justify-center p-4 font-sans">
<div class="relative w-full max-w-md h-[600px] rounded-2xl overflow-hidden shadow-2xl bg-white/90 backdrop-blur-sm transition-all duration-300">
<!-- Calculator -->
<div id="calculator" class="h-full flex flex-col">
<!-- Header -->
<div class="px-6 pt-6 pb-4 flex items-center justify-between">
<div class="flex items-center">
<div class="w-10 h-10 rounded-lg bg-gradient-to-r from-indigo-500 to-purple-500 flex items-center justify-center text-white font-bold mr-3">CN</div>
<h1 class="text-xl font-bold text-gray-800">CalcNote</h1>
</div>
<button onclick="showNotepad()" class="w-10 h-10 rounded-full bg-indigo-100 text-indigo-600 hover:bg-indigo-200 transition-colors flex items-center justify-center">
<i class="fas fa-key"></i>
</button>
</div>
<!-- Display -->
<div class="px-6 mb-5">
<div class="bg-gray-50 rounded-xl p-4 text-right">
<div id="display" class="text-3xl font-semibold text-gray-800 truncate">0</div>
</div>
</div>
<!-- Keypad -->
<div class="px-4 flex-1 grid grid-cols-4 gap-3 p-4">
<button onclick="clearDisplay()" class="btn-calculator bg-red-100 text-red-600 rounded-xl text-xl font-medium">AC</button>
<button onclick="appendToDisplay('(')" class="btn-calculator bg-gray-200 text-gray-700 rounded-xl text-xl font-medium">(</button>
<button onclick="appendToDisplay(')')" class="btn-calculator bg-gray-200 text-gray-700 rounded-xl text-xl font-medium">)</button>
<button onclick="appendToDisplay('/')" class="btn-calculator bg-indigo-500 text-white rounded-xl text-xl font-medium">÷</button>
<button onclick="appendToDisplay('7')" class="btn-calculator bg-gray-100 hover:bg-gray-200 text-gray-800 rounded-xl text-xl font-medium">7</button>
<button onclick="appendToDisplay('8')" class="btn-calculator bg-gray-100 hover:bg-gray-200 text-gray-800 rounded-xl text-xl font-medium">8</button>
<button onclick="appendToDisplay('9')" class="btn-calculator bg-gray-100 hover:bg-gray-200 text-gray-800 rounded-xl text-xl font-medium">9</button>
<button onclick="appendToDisplay('*')" class="btn-calculator bg-indigo-500 text-white rounded-xl text-xl font-medium">×</button>
<button onclick="appendToDisplay('4')" class="btn-calculator bg-gray-100 hover:bg-gray-200 text-gray-800 rounded-xl text-xl font-medium">4</button>
<button onclick="appendToDisplay('5')" class="btn-calculator bg-gray-100 hover:bg-gray-200 text-gray-800 rounded-xl text-xl font-medium">5</button>
<button onclick="appendToDisplay('6')" class="btn-calculator bg-gray-100 hover:bg-gray-200 text-gray-800 rounded-xl text-xl font-medium">6</button>
<button onclick="appendToDisplay('-')" class="btn-calculator bg-indigo-500 text-white rounded-xl text-xl font-medium"></button>
<button onclick="appendToDisplay('1')" class="btn-calculator bg-gray-100 hover:bg-gray-200 text-gray-800 rounded-xl text-xl font-medium">1</button>
<button onclick="appendToDisplay('2')" class="btn-calculator bg-gray-100 hover:bg-gray-200 text-gray-800 rounded-xl text-xl font-medium">2</button>
<button onclick="appendToDisplay('3')" class="btn-calculator bg-gray-100 hover:bg-gray-200 text-gray-800 rounded-xl text-xl font-medium">3</button>
<button onclick="appendToDisplay('+')" class="btn-calculator bg-indigo-500 text-white rounded-xl text-xl font-medium">+</button>
<button onclick="appendToDisplay('0')" class="btn-calculator bg-gray-100 hover:bg-gray-200 text-gray-800 rounded-xl text-xl font-medium col-span-2">0</button>
<button onclick="appendToDisplay('.')" class="btn-calculator bg-gray-100 hover:bg-gray-200 text-gray-800 rounded-xl text-xl font-medium">.</button>
<button onclick="calculate()" class="btn-calculator bg-gradient-to-r from-indigo-500 to-purple-500 text-white rounded-xl text-xl font-medium">=</button>
</div>
</div>
<!-- Notepad -->
<div id="notepad" class="hidden absolute inset-0 bg-white flex flex-col p-0">
<!-- Header -->
<div class="px-6 pt-6 pb-4 flex items-center justify-between bg-gradient-to-r from-indigo-500 to-purple-500 text-white">
<div class="flex items-center">
<button id="back-btn" class="mr-4 w-10 h-10 rounded-full flex items-center justify-center hover:bg-white/20 transition-colors">
<i class="fas fa-arrow-left"></i>
</button>
<h2 class="text-xl font-bold">Notas Secretas</h2>
</div>
<button id="new-note-btn" class="w-10 h-10 rounded-full bg-white/20 hover:bg-white/30 transition-colors flex items-center justify-center">
<i class="fas fa-plus"></i>
</button>
</div>
<!-- Empty State -->
<div id="empty-state" class="flex-1 flex flex-col items-center justify-center px-6 text-center text-gray-500" style="display: none;">
<div class="w-24 h-24 mb-4 rounded-full bg-indigo-50 flex items-center justify-center text-indigo-300">
<i class="fas fa-clipboard text-3xl"></i>
</div>
<h3 class="text-lg font-medium mb-2 text-gray-600">No hay notas</h3>
<p class="mb-6">Toca el botón + para crear tu primera nota secreta</p>
<button id="create-first-note" class="px-6 py-2 rounded-full bg-gradient-to-r from-indigo-500 to-purple-500 text-white font-medium hover:opacity-90 transition-opacity">
Crear Nota
</button>
</div>
<!-- Notes List -->
<div id="notes-list" class="flex-1 overflow-y-auto custom-scrollbar p-6 space-y-4" style="display: none;">
<!-- Notes will be rendered here -->
</div>
<!-- Editor -->
<div id="editor-container" class="hidden flex-1 flex flex-col bg-white">
<div class="bg-indigo-50 p-4 flex justify-between items-center border-b">
<input type="text" id="note-title" placeholder="Título"
class="bg-transparent outline-none font-semibold text-indigo-700 placeholder-indigo-300 w-full text-lg">
<div class="relative">
<button id="menu-btn" class="w-10 h-10 rounded-full hover:bg-indigo-100 flex items-center justify-center text-indigo-500">
<i class="fas fa-ellipsis-v"></i>
</button>
<div id="dropdown-menu" class="hidden absolute right-0 mt-2 w-48 bg-white rounded-lg shadow-xl z-10 border overflow-hidden">
<button id="save-btn" class="block px-4 py-3 text-left text-gray-700 hover:bg-gray-100 w-full text-sm font-medium">
<i class="fas fa-save mr-2 text-indigo-500"></i> Guardar
</button>
<button id="download-txt-btn" class="block px-4 py-3 text-left text-gray-700 hover:bg-gray-100 w-full text-sm font-medium">
<i class="fas fa-file-alt mr-2 text-indigo-500"></i> Exportar TXT
</button>
<button id="download-pdf-btn" class="block px-4 py-3 text-left text-gray-700 hover:bg-gray-100 w-full text-sm font-medium">
<i class="fas fa-file-pdf mr-2 text-indigo-500"></i> Exportar PDF
</button>
<div class="border-t">
<button id="edit-btn" class="hidden px-4 py-3 text-left text-gray-700 hover:bg-gray-100 w-full text-sm font-medium">
<i class="fas fa-edit mr-2 text-indigo-500"></i> Editar
</button>
<button id="delete-btn" class="hidden px-4 py-3 text-left text-red-600 hover:bg-gray-100 w-full text-sm font-medium">
<i class="fas fa-trash-alt mr-2"></i> Eliminar
</button>
</div>
</div>
</div>
</div>
<textarea id="note-content" placeholder="Escribe tu nota secreta aquí..."
class="flex-1 p-4 outline-none resize-none w-full text-gray-700 leading-relaxed"></textarea>
</div>
<!-- Viewer -->
<div id="note-viewer" class="hidden flex-1 flex flex-col bg-white">
<div class="bg-indigo-50 p-4 border-b flex justify-between items-center">
<h3 id="viewer-title" class="text-lg font-semibold text-indigo-700 truncate max-w-xs"></h3>
<button id="back-to-list-btn" class="text-indigo-600 hover:text-indigo-800 text-sm font-medium flex items-center">
<i class="fas fa-arrow-left mr-2"></i> Volver
</button>
</div>
<div id="viewer-content" class="flex-1 p-4 overflow-y-auto custom-scrollbar text-gray-700 leading-relaxed whitespace-pre-line"></div>
</div>
</div>
<!-- Hidden code input for notes access -->
<div id="code-input-modal" class="hidden absolute inset-0 bg-black/50 flex items-center justify-center p-6 z-10">
<div class="bg-white rounded-xl p-6 w-full max-w-xs shadow-xl">
<div class="text-center mb-4">
<div class="w-12 h-12 bg-indigo-100 rounded-full flex items-center justify-center text-indigo-500 mx-auto mb-3">
<i class="fas fa-lock"></i>
</div>
<h3 class="text-lg font-semibold text-gray-800">Acceso Secreto</h3>
<p class="text-gray-500 text-sm mt-1">Ingresa el código de acceso</p>
</div>
<div class="flex gap-2 justify-center mb-4">
<input type="password" maxlength="1" class="w-12 h-12 text-center border-2 border-gray-200 rounded-lg text-xl font-semibold focus:border-indigo-500 focus:outline-none">
<input type="password" maxlength="1" class="w-12 h-12 text-center border-2 border-gray-200 rounded-lg text-xl font-semibold focus:border-indigo-500 focus:outline-none">
<input type="password" maxlength="1" class="w-12 h-12 text-center border-2 border-gray-200 rounded-lg text-xl font-semibold focus:border-indigo-500 focus:outline-none">
<input type="password" maxlength="1" class="w-12 h-12 text-center border-2 border-gray-200 rounded-lg text-xl font-semibold focus:border-indigo-500 focus:outline-none">
</div>
<button id="verify-code-btn" class="w-full py-3 bg-gradient-to-r from-indigo-500 to-purple-500 text-white rounded-lg font-medium hover:opacity-90 transition-opacity">
Verificar
</button>
<p id="code-error" class="text-red-500 text-sm mt-2 text-center hidden">Código incorrecto</p>
</div>
</div>
</div>
<script>
// Calculator functionality
const display = document.getElementById('display');
let currentInput = '0';
function appendToDisplay(value) {
if (currentInput === '0' && value !== '.' && !'+-*/'.includes(value)) {
currentInput = value;
} else {
currentInput += value;
}
display.textContent = currentInput;
}
function clearDisplay() {
currentInput = '0';
display.textContent = currentInput;
}
function calculate() {
try {
// Check for secret code (1414)
if (currentInput === '1414') {
showCodeInputModal();
clearDisplay();
return;
}
// Replace ÷ with / and × with * for eval
const sanitizedInput = currentInput.replace(/÷/g, '/').replace(/×/g, '*');
const result = eval(sanitizedInput);
currentInput = result.toString();
display.textContent = currentInput;
} catch (error) {
display.textContent = 'Error';
setTimeout(() => {
clearDisplay();
}, 1000);
}
}
// Notepad functionality
const calculator = document.getElementById('calculator');
const notepad = document.getElementById('notepad');
const backBtn = document.getElementById('back-btn');
const newNoteBtn = document.getElementById('new-note-btn');
const createFirstNoteBtn = document.getElementById('create-first-note');
const notesList = document.getElementById('notes-list');
const emptyState = document.getElementById('empty-state');
const notesContainer = notesList; // Using notesList as container now
const editorContainer = document.getElementById('editor-container');
const noteTitle = document.getElementById('note-title');
const noteContent = document.getElementById('note-content');
const viewerContainer = document.getElementById('note-viewer');
const viewerTitle = document.getElementById('viewer-title');
const viewerContent = document.getElementById('viewer-content');
const backToListBtn = document.getElementById('back-to-list-btn');
const menuBtn = document.getElementById('menu-btn');
const dropdownMenu = document.getElementById('dropdown-menu');
const saveBtn = document.getElementById('save-btn');
const downloadTxtBtn = document.getElementById('download-txt-btn');
const downloadPdfBtn = document.getElementById('download-pdf-btn');
const editBtn = document.getElementById('edit-btn');
const deleteBtn = document.getElementById('delete-btn');
const codeInputModal = document.getElementById('code-input-modal');
const verifyCodeBtn = document.getElementById('verify-code-btn');
const codeError = document.getElementById('code-error');
const codeInputs = document.querySelectorAll('#code-input-modal input');
let notes = JSON.parse(localStorage.getItem('secretNotes')) || [];
let currentNoteId = null;
const secretCode = '1414';
function showCodeInputModal() {
document.querySelectorAll('#code-input-modal input').forEach(input => input.value = '');
codeError.classList.add('hidden');
codeInputModal.classList.remove('hidden');
codeInputs[0].focus();
}
function hideCodeInputModal() {
codeInputModal.classList.add('hidden');
}
function verifyCode() {
const enteredCode = Array.from(codeInputs).map(input => input.value).join('');
if (enteredCode === secretCode) {
hideCodeInputModal();
showNotepad();
} else {
codeError.classList.remove('hidden');
codeInputs[0].focus();
}
}
function showNotepad() {
calculator.classList.add('hidden');
notepad.classList.remove('hidden');
loadNotes();
}
function showCalculator() {
notepad.classList.add('hidden');
calculator.classList.remove('hidden');
clearDisplay();
}
function showEditor(clear = false) {
if (clear) {
noteTitle.value = '';
noteContent.value = '';
currentNoteId = null;
editBtn.classList.add('hidden');
deleteBtn.classList.add('hidden');
}
editorContainer.classList.remove('hidden');
viewerContainer.classList.add('hidden');
notesList.classList.add('hidden');
emptyState.classList.add('hidden');
dropdownMenu.classList.add('hidden');
}
function showViewer() {
editorContainer.classList.add('hidden');
viewerContainer.classList.remove('hidden');
notesList.classList.add('hidden');
emptyState.classList.add('hidden');
}
function showNotesList() {
editorContainer.classList.add('hidden');
viewerContainer.classList.add('hidden');
dropdownMenu.classList.add('hidden');
if (notes.length === 0) {
notesList.classList.add('hidden');
emptyState.classList.remove('hidden');
} else {
notesList.classList.remove('hidden');
emptyState.classList.add('hidden');
}
}
function loadNotes() {
notesContainer.innerHTML = '';
if (notes.length === 0) {
showNotesList();
return;
}
// Sort notes by updatedAt (newest first)
const sortedNotes = [...notes].sort((a, b) => b.updatedAt - a.updatedAt);
sortedNotes.forEach(note => {
const date = new Date(note.updatedAt);
const formattedDate = date.toLocaleDateString('es-ES', {
day: '2-digit',
month: 'short',
year: date.getFullYear() !== new Date().getFullYear() ? 'numeric' : undefined
});
const noteElement = document.createElement('div');
noteElement.className = 'note-card p-4 bg-white rounded-xl shadow-sm hover:shadow-md border border-gray-100 transition-all cursor-pointer';
noteElement.innerHTML = `
<div class="flex justify-between items-start mb-2">
<h3 class="font-medium text-gray-800 truncate max-w-[220px]">${note.title || 'Sin título'}</h3>
<span class="text-xs text-gray-400 whitespace-nowrap ml-2">${formattedDate}</span>
</div>
<p class="text-sm text-gray-500 line-clamp-2">${note.content.replace(/\n/g, ' ')}</p>
<div class="mt-3 pt-2 border-t border-gray-100 flex items-center">
<div class="w-6 h-6 rounded-full bg-gradient-to-r from-indigo-300 to-purple-300 flex items-center justify-center text-white text-xs">
<i class="fas fa-lock"></i>
</div>
<span class="ml-2 text-xs text-gray-400">Secreto</span>
</div>
`;
noteElement.addEventListener('click', () => {
viewerTitle.textContent = note.title || 'Sin título';
viewerContent.textContent = note.content;
currentNoteId = note.id;
// Show edit/delete buttons if this is the viewer
editBtn.classList.remove('hidden');
deleteBtn.classList.remove('hidden');
showViewer();
});
notesContainer.appendChild(noteElement);
});
showNotesList();
}
function saveNote() {
const title = noteTitle.value.trim();
const content = noteContent.value.trim();
if (!content) {
alert('El contenido no puede estar vacío');
return;
}
const now = new Date();
const id = now.getTime();
if (currentNoteId) {
// Update existing note
const index = notes.findIndex(note => note.id === currentNoteId);
if (index !== -1) {
notes[index] = {
id: currentNoteId,
title,
content,
updatedAt: id
};
}
} else {
// Add new note
notes.push({
id,
title,
content,
createdAt: id,
updatedAt: id
});
}
localStorage.setItem('secretNotes', JSON.stringify(notes));
loadNotes();
}
function deleteNote() {
if (currentNoteId && confirm('¿Estás seguro de que quieres eliminar esta nota para siempre?')) {
notes = notes.filter(note => note.id !== currentNoteId);
localStorage.setItem('secretNotes', JSON.stringify(notes));
loadNotes();
}
}
function downloadAsTxt() {
const title = noteTitle.value.trim() || 'nota-sin-titulo';
const content = noteContent.value.trim();
const blob = new Blob([content], { type: 'text/plain' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = `${title}.txt`;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
function downloadAsPdf() {
const title = noteTitle.value.trim() || 'Nota sin título';
const content = noteContent.value.trim();
const { jsPDF } = window.jspdf;
const doc = new jsPDF();
doc.setFont('helvetica');
doc.setFontSize(20);
doc.setTextColor(79, 70, 229);
doc.text(title, 105, 20, null, null, 'center');
doc.setFontSize(12);
doc.setTextColor(0, 0, 0);
const lines = doc.splitTextToSize(content, 180);
doc.text(lines, 15, 30);
// Add watermark
doc.setFontSize(8);
doc.setTextColor(200, 200, 200);
doc.text('Created with CalcNote', 105, 285, null, null, 'center');
doc.save(`${title}.pdf`);
}
// Event listeners
backBtn.addEventListener('click', showCalculator);
newNoteBtn.addEventListener('click', () => {
showEditor(true);
});
createFirstNoteBtn.addEventListener('click', () => {
showEditor(true);
});
backToListBtn.addEventListener('click', () => {
showNotesList();
});
menuBtn.addEventListener('click', (e) => {
e.stopPropagation();
dropdownMenu.classList.toggle('hidden');
});
saveBtn.addEventListener('click', () => {
saveNote();
dropdownMenu.classList.add('hidden');
});
downloadTxtBtn.addEventListener('click', () => {
downloadAsTxt();
dropdownMenu.classList.add('hidden');
});
downloadPdfBtn.addEventListener('click', () => {
downloadAsPdf();
dropdownMenu.classList.add('hidden');
});
editBtn.addEventListener('click', () => {
if (currentNoteId) {
const note = notes.find(n => n.id === currentNoteId);
if (note) {
noteTitle.value = note.title || '';
noteContent.value = note.content;
showEditor();
}
}
dropdownMenu.classList.add('hidden');
});
deleteBtn.addEventListener('click', () => {
deleteNote();
dropdownMenu.classList.add('hidden');
});
// Close dropdown when clicking outside
document.addEventListener('click', (e) => {
if (!menuBtn.contains(e.target) && !dropdownMenu.contains(e.target)) {
dropdownMenu.classList.add('hidden');
}
});
// Code input handling
codeInputs.forEach((input, index) => {
input.addEventListener('input', () => {
if (input.value.length === 1 && index < codeInputs.length - 1) {
codeInputs[index + 1].focus();
}
});
input.addEventListener('keydown', (e) => {
if (e.key === 'Backspace' && input.value.length === 0 && index > 0) {
codeInputs[index - 1].focus();
} else if (e.key === 'Enter') {
verifyCode();
}
});
});
verifyCodeBtn.addEventListener('click', verifyCode);
// Initialize
loadNotes();
// Auto-focus first code input when modal shown
codeInputModal.addEventListener('shown', () => {
codeInputs[0].focus();
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=Lanskik/notes" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>