Skip to content

レポート2 #20

@kmc2629

Description

@kmc2629

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>

);
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions