Personal Journal App

import React, { useState, useEffect } from 'react';
import * as jose from 'jose';

// Componente Principal de Diario Personal
const PersonalJournalApp = () => {
  const [entries, setEntries] = useState([]);
  const [currentEntry, setCurrentEntry] = useState('');
  const [mood, setMood] = useState('neutral');
  const [isEncrypted, setIsEncrypted] = useState(false);
  const [encryptionKey, setEncryptionKey] = useState(null);

  // Emociones para seguimiento
  const moods = [
    { value: 'muy_feliz', label: '😄 Muy Feliz', color: 'bg-green-200' },
    { value: 'feliz', label: '🙂 Feliz', color: 'bg-green-100' },
    { value: 'neutral', label: '😐 Neutral', color: 'bg-gray-200' },
    { value: 'triste', label: '😔 Triste', color: 'bg-blue-100' },
    { value: 'muy_triste', label: '😢 Muy Triste', color: 'bg-blue-200' }
  ];

  // Generar clave de encriptación
  const generateEncryptionKey = async () => {
    const key = await jose.generateKeyPair('ES256');
    setEncryptionKey(key);
    setIsEncrypted(true);
  };

  // Encriptar entrada
  const encryptEntry = async (entry) => {
    if (!encryptionKey) {
      await generateEncryptionKey();
    }
    
    const jwt = await new jose.SignJWT({ entry, mood })
      .setProtectedHeader({ alg: 'ES256' })
      .setIssuedAt()
      .sign(encryptionKey.privateKey);

    return jwt;
  };

  // Guardar entrada
  const saveEntry = async () => {
    if (!currentEntry.trim()) return;

    const encryptedEntry = await encryptEntry(currentEntry);
    
    const newEntry = {
      id: Date.now(),
      content: encryptedEntry,
      date: new Date().toLocaleString(),
      mood: mood
    };

    const updatedEntries = [...entries, newEntry];
    setEntries(updatedEntries);
    
    // Guardar en localStorage
    localStorage.setItem('journalEntries', JSON.stringify(updatedEntries));
    
    // Limpiar campos
    setCurrentEntry('');
    setMood('neutral');
  };

  // Cargar entradas guardadas
  useEffect(() => {
    const savedEntries = localStorage.getItem('journalEntries');
    if (savedEntries) {
      setEntries(JSON.parse(savedEntries));
    }
  }, []);

  // Renderizado de la aplicación
  return (
    <div className="max-w-2xl mx-auto p-6 bg-white shadow-lg rounded-lg">
      <h1 className="text-3xl font-bold mb-6 text-center">Mi Diario Personal</h1>
      
      {/* Selector de Estado de Ánimo */}
      <div className="mb-4">
        <label className="block mb-2">Estado de Ánimo</label>
        <div className="flex space-x-2">
          {moods.map((moodOption) => (
            <button
              key={moodOption.value}
              onClick={() => setMood(moodOption.value)}
              className={`
                ${moodOption.color} 
                ${mood === moodOption.value ? 'ring-2 ring-blue-500' : ''}
                px-3 py-2 rounded-lg text-sm
              `}
            >
              {moodOption.label}
            </button>
          ))}
        </div>
      </div>

      {/* Área de Escritura */}
      <textarea
        value={currentEntry}
        onChange={(e) => setCurrentEntry(e.target.value)}
        placeholder="Escribe tu entrada del diario..."
        className="w-full h-40 p-3 border rounded-lg mb-4"
      />

      {/* Botón de Guardar */}
      <button 
        onClick={saveEntry}
        className="w-full bg-blue-500 text-white py-2 rounded-lg hover:bg-blue-600 transition"
      >
        Guardar Entrada
      </button>

      {/* Lista de Entradas */}
      <div className="mt-6">
        <h2 className="text-xl font-semibold mb-4">Mis Entradas</h2>
        {entries.map((entry) => (
          <div 
            key={entry.id} 
            className="bg-gray-100 p-4 rounded-lg mb-3"
          >
            <p className="text-sm text-gray-600">{entry.date}</p>
            <p>Entrada Encriptada</p>
          </div>
        ))}
      </div>
    </div>
  );
};

export default PersonalJournalApp;

How to:

Características Técnicas Destacadas

Seguridad

  • Encriptación de entradas usando JWT (JSON Web Tokens)
  • Generación de claves criptográficas con biblioteca jose
  • Almacenamiento local seguro

Funcionalidades

  • Seguimiento de estado de ánimo
  • Guardado local de entradas
  • Interfaz minimalista y moderna
  • Selector de emociones con emojis

Tecnologías

  • React
  • Tailwind CSS para diseño
  • Encriptación con librería jose

Beneficios Personales

  • Práctica de desarrollo web
  • Herramienta de autoconocimiento
  • Espacio seguro para registro emocional

Próximos Pasos Sugeridos

  1. Implementar descifrado de entradas
  2. Añadir exportación/importación
  3. Integrar análisis de sentimientos
  4. Implementar sincronización en la nube