import React, { useState } from "react";
// ダミーデータ
const initialPosts = [
{
id: 1,
name: "あい",
grade: "一年",
sp: "SONY",
birthday: "01-15",
mbti: "INTJ",
tags: ["静か", "分析好き"],
image: "https://via.placeholder.com/300",
updatedAt: Date.now()
}
];
export default function App() {
const [posts, setPosts] = useState(initialPosts);
const [search, setSearch] = useState("");
const [sort, setSort] = useState("name");
const filtered = posts
.filter(p =>
p.name.includes(search) ||
p.tags.some(tag => tag.includes(search))
)
.sort((a, b) => {
if (sort === "name") return a.name.localeCompare(b.name, "ja");
if (sort === "birthday") return a.birthday.localeCompare(b.birthday);
if (sort === "updated") return b.updatedAt - a.updatedAt;
return 0;
});
return (
画像投稿アプリ
{/* 検索・ソート */}
<div className="flex gap-2 mb-4">
<input
className="border rounded-2xl p-2 flex-1"
placeholder="名前・タグ検索"
value={search}
onChange={e => setSearch(e.target.value)}
/>
<select
className="border rounded-2xl p-2"
value={sort}
onChange={e => setSort(e.target.value)}
>
<option value="name">名前順</option>
<option value="birthday">誕生日順</option>
<option value="updated">更新順</option>
</select>
</div>
{/* 投稿一覧 */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
{filtered.map(post => (
<PostCard key={post.id} post={post} setPosts={setPosts} posts={posts} />
))}
</div>
</div>
);
}
function PostCard({ post, posts, setPosts }) {
const [newTag, setNewTag] = useState("");
const addTag = () => {
if (!newTag || post.tags.length >= 10) return;
const updated = posts.map(p =>
p.id === post.id
? { ...p, tags: [...p.tags, newTag], updatedAt: Date.now() }
: p
);
setPosts(updated);
setNewTag("");
};
return (
{/* 名前 */}
{post.name}
{/* タグ */}
<div className="flex flex-wrap gap-2 my-2">
{[post.grade, post.sp, post.birthday, post.mbti, ...post.tags].map((tag, i) => (
<span key={i} className="text-sm border px-2 py-1 rounded-full">
#{tag}
</span>
))}
</div>
{/* 画像 */}
<img src={post.image} alt="" className="rounded-xl w-full" />
{/* タグ追加 */}
<div className="flex gap-2 mt-2">
<input
className="border rounded-2xl p-1 flex-1"
value={newTag}
onChange={e => setNewTag(e.target.value)}
placeholder="タグ追加"
/>
<button
className="bg-black text-white px-3 rounded-2xl"
onClick={addTag}
>
追加
</button>
</div>
</div>
);
}
import React, { useState } from "react";
// ダミーデータ
const initialPosts = [
{
id: 1,
name: "あい",
grade: "一年",
sp: "SONY",
birthday: "01-15",
mbti: "INTJ",
tags: ["静か", "分析好き"],
image: "https://via.placeholder.com/300",
updatedAt: Date.now()
}
];
export default function App() {
const [posts, setPosts] = useState(initialPosts);
const [search, setSearch] = useState("");
const [sort, setSort] = useState("name");
const filtered = posts
.filter(p =>
p.name.includes(search) ||
p.tags.some(tag => tag.includes(search))
)
.sort((a, b) => {
if (sort === "name") return a.name.localeCompare(b.name, "ja");
if (sort === "birthday") return a.birthday.localeCompare(b.birthday);
if (sort === "updated") return b.updatedAt - a.updatedAt;
return 0;
});
return (
画像投稿アプリ
);
}
function PostCard({ post, posts, setPosts }) {
const [newTag, setNewTag] = useState("");
const addTag = () => {
if (!newTag || post.tags.length >= 10) return;
const updated = posts.map(p =>
p.id === post.id
? { ...p, tags: [...p.tags, newTag], updatedAt: Date.now() }
: p
);
setPosts(updated);
setNewTag("");
};
return (
{/* 名前 */}
{post.name}
);
}