ひとこと履歴書


<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>ひとこと履歴書 Ultra</title>
  <script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
  <style>
    body {
      font-family: "Helvetica Neue", sans-serif;
      background: #f0f0f0;
      padding: 30px;
      max-width: 900px;
      margin: auto;
    }
    h1 {
      text-align: center;
      margin-bottom: 20px;
    }
    textarea, input[type="date"], input[type="text"] {
      width: 100%;
      padding: 10px;
      font-size: 1rem;
      margin-bottom: 10px;
    }
    .emotion-btn {
      font-size: 20px;
      padding: 6px 12px;
      border: 2px solid #ccc;
      background: white;
      cursor: pointer;
      border-radius: 6px;
    }
    .emotion-btn.selected {
      border-color: #4caf50;
      background: #e8f5e9;
    }
    button.add {
      background: #4caf50;
      color: white;
      border: none;
      border-radius: 6px;
      padding: 10px 20px;
      cursor: pointer;
      font-size: 1rem;
      margin-top: 10px;
    }
    button.export {
      background: #2196f3;
      margin-left: 10px;
    }
    .entry {
      background: white;
      padding: 10px;
      border-left: 5px solid #ccc;
      margin: 10px 0;
      border-radius: 6px;
    }
    .section-date {
      font-weight: bold;
      margin-top: 30px;
    }
    .entry .meta {
      font-size: 0.8em;
      color: #666;
    }
    #stats {
      margin: 20px 0;
      background: #fff;
      padding: 10px;
      border-radius: 8px;
      box-shadow: 0 0 3px rgba(0,0,0,0.1);
    }
  </style>
</head>
<body>

<h1>ひとこと履歴書 Ultra</h1>

<textarea id="entryInput" placeholder="今日の一言を記録しよう!"></textarea>
<input type="date" id="entryDate">
<div>
  <button class="emotion-btn" data-emotion="😊">😊 喜</button>
  <button class="emotion-btn" data-emotion="😢">😢 哀</button>
  <button class="emotion-btn" data-emotion="😠">😠 怒</button>
  <button class="emotion-btn" data-emotion="😐">😐 中立</button>
</div>
<button class="add" onclick="addEntry()">記録</button>
<button class="add export" onclick="exportCSV()">CSVダウンロード</button>

<input type="text" id="searchBox" placeholder="キーワード検索(例:嬉しい、美術館)">
<div id="stats"></div>
<canvas id="emotionChart" height="200"></canvas>
<div id="entryList"></div>

<script>
const input = document.getElementById("entryInput");
const dateInput = document.getElementById("entryDate");
const searchBox = document.getElementById("searchBox");
const entryList = document.getElementById("entryList");
const stats = document.getElementById("stats");
const emotionButtons = document.querySelectorAll(".emotion-btn");
let selectedEmotion = "😊";
dateInput.valueAsDate = new Date();

emotionButtons.forEach(btn => {
  btn.addEventListener("click", () => {
    emotionButtons.forEach(b => b.classList.remove("selected"));
    btn.classList.add("selected");
    selectedEmotion = btn.dataset.emotion;
  });
});

function addEntry() {
  const text = input.value.trim();
  const date = dateInput.value;
  if (!text || !date || !selectedEmotion) return;
  const entries = JSON.parse(localStorage.getItem("entries") || "[]");
  entries.push({ text, date, emotion: selectedEmotion, timestamp: new Date().toISOString() });
  localStorage.setItem("entries", JSON.stringify(entries));
  input.value = "";
  renderEntries();
}

function exportCSV() {
  const entries = JSON.parse(localStorage.getItem("entries") || "[]");
  let csv = "日付,感情,テキスト,記録日時\n";
  entries.forEach(e => {
    csv += `${e.date},${e.emotion},"${e.text.replace(/"/g, '""')}",${e.timestamp}\n`;
  });
  const blob = new Blob([csv], { type: "text/csv" });
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url;
  a.download = "hitokoto_entries.csv";
  a.click();
  URL.revokeObjectURL(url);
}

function groupByDate(entries) {
  const grouped = {};
  entries.forEach(entry => {
    if (!grouped[entry.date]) grouped[entry.date] = [];
    grouped[entry.date].push(entry);
  });
  return grouped;
}

function renderEntries() {
  const entries = JSON.parse(localStorage.getItem("entries") || "[]").reverse();
  const keyword = searchBox.value.trim();
  const filtered = keyword
    ? entries.filter(e => e.text.includes(keyword))
    : entries;

  const grouped = groupByDate(filtered);
  const emotionCounts = { "😊": 0, "😢": 0, "😠": 0, "😐": 0 };

  entryList.innerHTML = "";
  let totalTextLength = 0;

  for (const date in grouped) {
    const section = document.createElement("div");
    section.innerHTML = `<div class="section-date">📅 ${date}</div>`;
    grouped[date].forEach(entry => {
      emotionCounts[entry.emotion]++;
      totalTextLength += entry.text.length;
      const div = document.createElement("div");
      div.className = "entry";
      div.innerHTML = `
        <div>${entry.emotion} ${entry.text}</div>
        <div class="meta">${new Date(entry.timestamp).toLocaleString()}</div>
      `;
      section.appendChild(div);
    });
    entryList.appendChild(section);
  }

  const total = filtered.length;
  const avgLen = total ? Math.round(totalTextLength / total) : 0;
  stats.innerHTML = `📌 総投稿数: ${total} 件|平均文字数: ${avgLen} 字`;

  renderChart(emotionCounts);
}

function renderChart(counts) {
  const ctx = document.getElementById("emotionChart").getContext("2d");
  if (window.myChart) window.myChart.destroy();
  window.myChart = new Chart(ctx, {
    type: "pie",
    data: {
      labels: ["😊 喜", "😢 哀", "😠 怒", "😐 中立"],
      datasets: [{
        data: [
          counts["😊"],
          counts["😢"],
          counts["😠"],
          counts["😐"]
        ],
        backgroundColor: ["gold", "skyblue", "tomato", "gray"]
      }]
    },
    options: {
      plugins: { legend: { position: "bottom" } }
    }
  });
}

searchBox.addEventListener("input", renderEntries);
renderEntries();
</script>

</body>
</html>

投稿者: chosuke

趣味はゲームやアニメや漫画などです

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です