feat(projects): add project create edit and membership flows

This commit is contained in:
2026-04-24 22:22:46 +03:30
parent 790e5f1dba
commit c4d8379924
3 changed files with 1341 additions and 3 deletions

View File

@@ -5,6 +5,26 @@ export interface ProjectClient {
name: string;
}
export interface ProjectMemberPayload {
user_id: string;
role: "manager" | "member" | string;
}
export interface ProjectMembership {
id: string;
project: string;
user: string;
user_details: {
id: string;
first_name: string;
last_name: string;
phone_number: string;
avatar?: string;
};
role: "manager" | "member" | string;
is_active: boolean;
}
export interface Project {
id: string;
name: string;
@@ -13,10 +33,11 @@ export interface Project {
is_archived: boolean;
workspace: string;
client: ProjectClient | null;
my_role?: string;
members?: ProjectMembership[];
}
export interface ProjectPayload {
id: string;
name: string;
description: string;
color: string;
@@ -44,7 +65,23 @@ export const getProjects = async (
return response.json();
};
export const createProject = async (data: Partial<ProjectPayload> & { workspace: string; name: string }) => {
export const getProject = async (id: string) => {
const response = await authFetch(`/api/projects/${id}/`);
if (!response.ok) {
const errorData = await response.json().catch(() => null);
throw new Error(errorData?.detail || errorData?.message || "Failed to fetch project");
}
return response.json();
};
export const createProject = async (
data: Partial<ProjectPayload> & {
workspace: string;
name: string;
members?: ProjectMemberPayload[];
}
) => {
const response = await authFetch("/api/projects/", {
method: "POST",
body: JSON.stringify(data),
@@ -57,7 +94,10 @@ export const createProject = async (data: Partial<ProjectPayload> & { workspace:
return response.json();
};
export const updateProject = async (id: string, data: Partial<ProjectPayload>) => {
export const updateProject = async (
id: string,
data: Partial<ProjectPayload> & { members?: ProjectMemberPayload[] }
) => {
const response = await authFetch(`/api/projects/${id}/`, {
method: "PATCH",
body: JSON.stringify(data),
@@ -95,3 +135,49 @@ export const toggleArchiveProject = async (id: string) => {
}
return response.json();
};
export const getProjectMemberships = async (projectId: string) => {
const response = await authFetch(`/api/memberships/?project=${projectId}`);
if (!response.ok) throw new Error("Failed to fetch project memberships");
return response.json();
};
export const addProjectMembership = async (projectId: string, userId: string, role: string) => {
const response = await authFetch(`/api/memberships/`, {
method: "POST",
body: JSON.stringify({ project_id: projectId, user_id: userId, role }),
});
if (!response.ok) {
const errorData = await response.json().catch(() => null);
throw new Error(errorData?.detail || errorData?.message || "Failed to add project member");
}
return response.json();
};
export const updateProjectMembership = async (membershipId: string, role: string, isActive: boolean = true) => {
const response = await authFetch(`/api/memberships/${membershipId}/`, {
method: "PATCH",
body: JSON.stringify({ role, is_active: isActive }),
});
if (!response.ok) {
const errorData = await response.json().catch(() => null);
throw new Error(errorData?.detail || errorData?.message || "Failed to update project member");
}
return response.json();
};
export const removeProjectMembership = async (membershipId: string) => {
const response = await authFetch(`/api/memberships/${membershipId}/`, {
method: "DELETE",
});
if (!response.ok) {
const errorData = await response.json().catch(() => null);
throw new Error(errorData?.detail || errorData?.message || "Failed to remove member");
}
if (response.status === 204) return { success: true };
return response.json().catch(() => ({ success: true }));
};