note風WEBサービス

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title>MiniNote - Note風ブログ with フィルタ・いいね・検索機能</title>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <style>
    body { font-family: sans-serif; background: #f9f9f9; margin: 0; }
    header { background: #2c3e50; color: white; padding: 1em; text-align: center; }
    nav { background: #34495e; text-align: center; padding: 0.5em; }
    nav button { margin: 0 8px; padding: 8px 20px; cursor: pointer; background: #ecf0f1; border: none; border-radius: 5px; }
    #main { max-width: 900px; margin: 2em auto; padding: 1em; background: white; border-radius: 10px; box-shadow: 0 4px 8px rgba(0,0,0,0.1); }
    article { padding: 1em; border-bottom: 1px solid #ddd; }
    h2 { margin: 0.5em 0; }
    .meta { font-size: 0.9em; color: #999; margin-bottom: 0.5em; }
    textarea, input[type="text"] { width: 100%; padding: 10px; margin: 10px 0; border-radius: 5px; border: 1px solid #ccc; }
    button.submit {
      background: #3498db; color: white; border: none;
      padding: 10px 20px; border-radius: 6px;
      cursor: pointer; font-weight: bold;
    }
    .hidden { display: none; }
    .tag { color: #3498db; margin-right: 5px; font-size: 0.9em; cursor: pointer; }
    .actions button { margin-right: 10px; }
    .like { color: #e74c3c; cursor: pointer; margin-left: 10px; }
  </style>
</head>
<body>

<header><h1>📘 MiniNote - あなたのNote風ブログ</h1></header>

<nav>
  <button onclick="showView('home')">🏠 ホーム</button>
  <button onclick="showView('new')">✍ 新規投稿</button>
  <input type="text" id="searchInput" placeholder="検索" oninput="renderPosts()" style="padding:5px; width: 200px;">
</nav>

<div id="main">
  <div id="homeView">
    <div id="postList"></div>
  </div>

  <div id="newView" class="hidden">
    <h2>新しい投稿を作成</h2>
    <input type="text" id="titleInput" placeholder="タイトル">
    <textarea id="contentInput" rows="8" placeholder="本文"></textarea>
    <input type="text" id="tagInput" placeholder="タグ(カンマ区切り)">
    <button class="submit" onclick="addPost()">投稿する</button>
  </div>

  <div id="detailView" class="hidden">
    <article>
      <h2 id="detailTitle"></h2>
      <div class="meta" id="detailDate"></div>
      <p id="detailContent"></p>
      <div id="detailTags"></div>
      <div class="like" id="likeDisplay" onclick="likePost(currentIndex)">❤️ <span id="likeCount">0</span></div>
    </article>
    <div class="actions">
      <button onclick="editPost(currentIndex)">✏ 編集</button>
      <button onclick="deletePost(currentIndex)">🗑 削除</button>
      <button onclick="showView('home')">← 戻る</button>
    </div>
  </div>
</div>

<script>
  let posts = JSON.parse(localStorage.getItem("posts") || "[]");
  let currentIndex = null;
  let filterTag = null;

  function showView(view) {
    document.querySelectorAll('#main > div').forEach(div => div.classList.add('hidden'));
    document.getElementById(view + "View").classList.remove("hidden");
    if (view === "home") renderPosts();
  }

  function addPost() {
    const title = document.getElementById("titleInput").value;
    const content = document.getElementById("contentInput").value;
    const tags = document.getElementById("tagInput").value.split(',').map(tag => tag.trim()).filter(Boolean);
    if (!title || !content) return alert("タイトルと本文を入力してください");

    const date = new Date().toLocaleString();
    posts.unshift({ title, content, date, tags, likes: 0 });
    localStorage.setItem("posts", JSON.stringify(posts));
    clearForm();
    showView("home");
  }

  function renderPosts() {
    const list = document.getElementById("postList");
    const search = document.getElementById("searchInput").value.toLowerCase();
    list.innerHTML = "";
    posts.filter(post => {
      const inSearch = post.title.toLowerCase().includes(search) || post.content.toLowerCase().includes(search);
      const inTag = !filterTag || post.tags.includes(filterTag);
      return inSearch && inTag;
    }).forEach((post, index) => {
      const el = document.createElement("article");
      el.innerHTML = `
        <h2>${post.title}</h2>
        <div class="meta">${post.date}</div>
        <p>${post.content.substring(0, 80)}...</p>
        <div>${post.tags.map(tag => `<span class='tag' onclick='filterByTag("${tag}")'>#${tag}</span>`).join(' ')}</div>
        <div class="like">❤️ ${post.likes}</div>
        <button onclick="showDetail(${index})">📖 詳細</button>
      `;
      list.appendChild(el);
    });
  }

  function filterByTag(tag) {
    filterTag = tag;
    renderPosts();
  }

  function showDetail(index) {
    const post = posts[index];
    currentIndex = index;
    document.getElementById("detailTitle").innerText = post.title;
    document.getElementById("detailDate").innerText = post.date;
    document.getElementById("detailContent").innerText = post.content;
    document.getElementById("detailTags").innerHTML = post.tags.map(tag => `<span class='tag'>#${tag}</span>`).join(' ');
    document.getElementById("likeCount").innerText = post.likes;
    showView("detail");
  }

  function likePost(index) {
    posts[index].likes++;
    localStorage.setItem("posts", JSON.stringify(posts));
    document.getElementById("likeCount").innerText = posts[index].likes;
    renderPosts();
  }

  function editPost(index) {
    const post = posts[index];
    document.getElementById("titleInput").value = post.title;
    document.getElementById("contentInput").value = post.content;
    document.getElementById("tagInput").value = post.tags.join(', ');
    posts.splice(index, 1);
    localStorage.setItem("posts", JSON.stringify(posts));
    showView("new");
  }

  function deletePost(index) {
    if (!confirm("本当に削除しますか?")) return;
    posts.splice(index, 1);
    localStorage.setItem("posts", JSON.stringify(posts));
    showView("home");
  }

  function clearForm() {
    document.getElementById("titleInput").value = "";
    document.getElementById("contentInput").value = "";
    document.getElementById("tagInput").value = "";
  }

  showView("home");
</script>

</body>
</html>

投稿者: chosuke

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

コメントを残す

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