feat(m4): project & member management with tests and e2e

- ProjectRepository, ProjectMemberRepository, minimal NotificationRepository
- ProjectService: create/update/archive/delete project, add/remove member,
  permission checks (isMember/admin), member-added notification, getDashboard
  skeleton, getMyProjects, getMemberRole
- projectValidator, API services factory
- API routes: projects CRUD, members list/add/remove
- Screens: dashboard (project list + create form), project overview, members,
  settings; layout (Header/Sidebar/ProjectNav) and project components
- Unit tests (Project/ProjectMember repositories, ProjectService),
  integration project-member-permission, e2e project-management
This commit is contained in:
Ken Yasue
2026-06-25 01:02:10 +02:00
parent 8a67523c0e
commit 9eb391ea8d
30 changed files with 2230 additions and 14 deletions

View File

@ -0,0 +1,41 @@
'use client';
import { useState } from 'react';
import { useRouter } from 'next/navigation';
export function RemoveMemberButton({
projectId,
userId,
label,
disabled = false,
}: {
projectId: number;
userId: number;
label: string;
disabled?: boolean;
}) {
const router = useRouter();
const [busy, setBusy] = useState(false);
async function onRemove() {
setBusy(true);
const res = await fetch(`/api/projects/${projectId}/members/${userId}`, {
method: 'DELETE',
});
setBusy(false);
if (res.ok) {
router.refresh();
}
}
return (
<button
type="button"
onClick={onRemove}
disabled={disabled || busy}
className="text-xs text-red-600 hover:underline disabled:opacity-50"
>
{busy ? '削除中...' : label}
</button>
);
}