<!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>