import { AddMemberInfo } from "../Components/AddMember"; import { ProjectRoleChange } from "../Components/ChangeRole"; import { projectTimes } from "../Components/GetProjectTimes"; import { ProjectMember } from "../Components/GetUsersInProject"; import { UpdateWeeklyReport, NewWeeklyReport, NewUser, User, Project, NewProject, WeeklyReport, StrNameChange, } from "../Types/goTypes"; /** * Response object returned by API methods. */ export interface APIResponse { /** Indicates whether the API call was successful */ success: boolean; /** Optional message providing additional information or error description */ message?: string; /** Optional data returned by the API method */ data?: T; } /** * Interface defining methods that an instance of the API must implement. */ interface API { /** * Register a new user * @param {NewUser} user The user object to be registered * @returns {Promise>} A promise containing the API response with the user data. */ registerUser(user: NewUser): Promise>; /** * Removes a user. * @param {string} username The username of the user to be removed. * @param {string} token The authentication token. * @returns {Promise>} A promise containing the API response with the removed user data. */ removeUser(username: string, token: string): Promise>; /** * Check if user is project manager. * @param {string} username The username of the user. * @param {string} projectName The name of the project. * @param {string} token The authentication token. * @returns {Promise>} A promise containing the API response indicating if the user is a project manager. */ checkIfProjectManager( projectName: string, token: string, ): Promise>; /** Logs in a user with the provided credentials. * @param {NewUser} NewUser The user object containing username and password. * @returns {Promise>} A promise resolving to an API response with a token. */ login(NewUser: NewUser): Promise>; /** * Renew the token * @param {string} token The current authentication token. * @returns {Promise>} A promise resolving to an API response with a renewed token. */ renewToken(token: string): Promise>; /** Promote user to admin */ /** Creates a new project. * @param {NewProject} project The project object containing name and description. * @param {string} token The authentication token. * @returns {Promise>} A promise resolving to an API response with the created project. */ createProject(project: NewProject, token: string): Promise>; /** Submits a weekly report * @param {NewWeeklyReport} weeklyReport The weekly report object. * @param {string} token The authentication token. * @returns {Promise>} A promise resolving to an API response with the submitted report. */ submitWeeklyReport( weeklyReport: NewWeeklyReport, token: string, ): Promise>; /** * Updates a weekly report. * @param {UpdateWeeklyReport} weeklyReport The updated weekly report object. * @param {string} token The authentication token. * @returns {Promise>} A promise containing the API response with the updated report. */ updateWeeklyReport( weeklyReport: UpdateWeeklyReport, token: string, ): Promise>; /** Gets a weekly report for a specific user, project and week. * Keep in mind that the user within the token needs to be PM * of the project to get the report, unless the user is the target user. * @param {string} projectName The name of the project. * @param {string} week The week number. * @param {string} token The authentication token. * @param {string} targetUser The username of the target user. Defaults to token user. * @returns {Promise>} A promise resolving to an API response with the retrieved report. */ getWeeklyReport( projectName: string, week: string, token: string, targetUser?: string, ): Promise>; /** * Returns all the weekly reports for a user in a particular project * The username is derived from the token * @param {string} projectName The name of the project * @param {string} token The token of the user * @returns {APIResponse} A list of weekly reports */ getAllWeeklyReportsForUser( projectName: string, token: string, targetUser?: string, ): Promise>; /** Gets all the projects of a user * @param {string} username - The authentication token. * @param {string} token - The authentication token. * @returns {Promise>} A promise containing the API response with the user's projects. */ getUserProjects( username: string, token: string, ): Promise>; /** Gets a project by its id. * @param {number} id The id of the project to retrieve. * @returns {Promise>} A promise resolving to an API response containing the project data. */ getProject(id: number): Promise>; /** Gets a projects reported time * @param {string} projectName The name of the project. * @param {string} token The usertoken. * @returns {Promise>} A promise resolving to an API response containing the project times. */ getProjectTimes( projectName: string, token: string, ): Promise>; /** Gets a list of all users. * @param {string} token The authentication token of the requesting user. * @returns {Promise>} A promise resolving to an API response containing the list of users. */ getAllUsers(token: string): Promise>; /** Gets all users in a project from name*/ getAllUsersProject( projectName: string, token: string, ): Promise>; /** Gets all unsigned reports in a project. * @param {string} projectName The name of the project. * @param {string} token The authentication token. * @returns {Promise>} A promise resolving to an API response containing the list of unsigned reports. */ getUnsignedReportsInProject( projectName: string, token: string, ): Promise>; /** * Changes the username of a user in the database. * @param {StrNameChange} data The object containing the previous and new username. * @param {string} token The authentication token. * @returns {Promise>} A promise resolving to an API response. */ changeUserName( data: StrNameChange, token: string, ): Promise>; /** * Changes the role of a user in the database. * @param {RoleChange} roleInfo The object containing the previous and new username. * @param {string} token The authentication token. * @returns {Promise>} A promise resolving to an API response. */ changeUserRole( roleInfo: ProjectRoleChange, token: string, ): Promise>; addUserToProject( addMemberInfo: AddMemberInfo, token: string, ): Promise>; removeUserFromProject( user: string, project: string, token: string, ): Promise>; removeProject( projectName: string, token: string, ): Promise>; /** * Signs a report. Keep in mind that the user which the token belongs to must be * the project manager of the project the report belongs to. * * @param {number} reportId The id of the report to sign * @param {string} token The authentication token */ signReport(reportId: number, token: string): Promise>; /** * Unsigns a report. Keep in mind that the user which the token belongs to must be * the project manager of the project the report belongs to. * * @param {number} reportId The id of the report to sign * @param {string} token The authentication token */ unsignReport(reportId: number, token: string): Promise>; /** * Promotes a user to project manager within a project. * * @param {string} userName The username of the user to promote * @param {string} projectName The name of the project to promote the user in * @returns {Promise} A promise resolving to an API response. */ promoteToPm( userName: string, projectName: string, token: string, ): Promise>; /** * Get the username from the id * @param {number} id The id of the user * @param {string} token Your token */ getUsername(id: number, token: string): Promise>; } /** An instance of the API */ export const api: API = { async registerUser(user: NewUser): Promise> { try { const response = await fetch("/api/register", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(user), }); if (!response.ok) { return { success: false, message: "Failed to register user: " + response.status, }; } else { // const data = (await response.json()) as User; // The API does not currently return the user return { success: true }; } } catch (e) { return { success: false, message: "Unknown error while registering user", }; } }, async removeUser( username: string, token: string, ): Promise> { try { const response = await fetch(`/api/userdelete/${username}`, { method: "DELETE", headers: { "Content-Type": "application/json", Authorization: "Bearer " + token, }, body: JSON.stringify(username), }); if (!response.ok) { return { success: false, message: "Could not remove user" }; } else { return { success: true }; } } catch (e) { return { success: false, message: "Failed to remove user" }; } }, async checkIfProjectManager( projectName: string, token: string, ): Promise> { try { const response = await fetch( `/api/checkIfProjectManager/${projectName}`, { method: "GET", headers: { "Content-Type": "application/json", Authorization: "Bearer " + token, }, }, ); if (!response.ok) { return { success: false, message: "Failed to check if project manager", }; } else { const data = (await response.json()) as boolean; return { success: true, data }; } } catch (e) { return { success: false, message: "Failed to check if project manager" }; } }, async createProject( project: NewProject, token: string, ): Promise> { try { const response = await fetch("/api/project", { method: "POST", headers: { "Content-Type": "application/json", Authorization: "Bearer " + token, }, body: JSON.stringify(project), }); if (!response.ok) { return { success: false, message: "Failed to create project" }; } else { return { success: true }; } } catch (e) { return { success: false, message: "Failed to create project!" }; } }, async addUserToProject( addMemberInfo: AddMemberInfo, token: string, ): Promise> { try { const response = await fetch( `/api/addUserToProject/${addMemberInfo.projectName}/?userName=${addMemberInfo.userName}`, { method: "PUT", headers: { "Content-Type": "application/json", Authorization: "Bearer " + token, }, }, ); if (!response.ok) { return { success: false, message: "Failed to add member" }; } else { return { success: true, message: "Added member" }; } } catch (e) { return { success: false, message: "Failed to add member" }; } }, async removeUserFromProject( user: string, project: string, token: string, ): Promise> { try { const response = await fetch( `/api/removeUserFromProject/${project}?userName=${user}`, { method: "DELETE", headers: { "Content-Type": "application/json", Authorization: "Bearer " + token, }, }, ); if (!response.ok) { return { success: false, message: "Failed to remove member" }; } } catch (e) { return { success: false, message: "Failed to remove member" }; } return { success: true, message: "Removed member" }; }, async renewToken(token: string): Promise> { try { const response = await fetch("/api/loginrenew", { method: "POST", headers: { "Content-Type": "application/json", Authorization: "Bearer " + token, }, }); if (!response.ok) { return { success: false, message: "Failed to renew token" }; } else { const data = (await response.json()) as string; return { success: true, data }; } } catch (e) { return { success: false, message: "Failed to renew token" }; } }, async changeUserRole( roleInfo: ProjectRoleChange, token: string, ): Promise> { try { const response = await fetch("/api/ProjectRoleChange", { method: "POST", headers: { "Content-Type": "application/json", Authorization: "Bearer " + token, }, body: JSON.stringify(roleInfo), }); if (!response.ok) { if (response.status === 403) { return { success: false, message: "Cannot change your own role" }; } return { success: false, message: "Could not change role" }; } else { return { success: true }; } } catch (e) { return { success: false, message: "Could not change role" }; } }, async getUserProjects( username: string, token: string, ): Promise> { try { const response = await fetch(`/api/getUserProjects/${username}`, { method: "GET", headers: { "Content-Type": "application/json", Authorization: "Bearer " + token, }, }); if (!response.ok) { return Promise.resolve({ success: false, message: "Failed to get user projects", }); } else { const data = (await response.json()) as Project[]; return Promise.resolve({ success: true, data }); } } catch (e) { return Promise.resolve({ success: false, message: "API fucked", }); } }, async getProjectTimes( projectName: string, token: string, ): Promise> { try { const response = await fetch(`/api/getProjectTimes/${projectName}`, { method: "GET", headers: { "Content-Type": "application/json", Authorization: "Bearer " + token, }, }); if (!response.ok) { return Promise.resolve({ success: false, message: "Fetch error: " + response.status + ", failed to get project times", }); } else { const data = (await response.json()) as projectTimes; return Promise.resolve({ success: true, data }); } } catch (e) { return Promise.resolve({ success: false, message: "API error! Could not get times.", }); } }, async submitWeeklyReport( weeklyReport: NewWeeklyReport, token: string, ): Promise> { try { const response = await fetch("/api/submitWeeklyReport", { method: "POST", headers: { "Content-Type": "application/json", Authorization: "Bearer " + token, }, body: JSON.stringify(weeklyReport), }); if (!response.ok) { return { success: false, message: "Failed to submit weekly report", }; } const data = await response.text(); return { success: true, message: data }; } catch (e) { return { success: false, message: "Failed to submit weekly report", }; } }, async updateWeeklyReport( weeklyReport: UpdateWeeklyReport, token: string, ): Promise> { try { const response = await fetch("/api/updateWeeklyReport", { method: "PUT", headers: { "Content-Type": "application/json", Authorization: "Bearer " + token, }, body: JSON.stringify(weeklyReport), }); if (!response.ok) { return { success: false, message: "Failed to update weekly report", }; } const data = await response.text(); return { success: true, message: data }; } catch (e) { return { success: false, message: "Failed to update weekly report", }; } }, async getWeeklyReport( projectName: string, week: string, token: string, targetUser?: string, ): Promise> { try { const response = await fetch( `/api/getWeeklyReport?projectName=${projectName}&week=${week}&targetUser=${targetUser ?? ""}`, { method: "GET", headers: { "Content-Type": "application/json", Authorization: "Bearer " + token, }, }, ); if (!response.ok) { return { success: false, message: "Failed to get weekly report" }; } else { const data = (await response.json()) as WeeklyReport; return { success: true, data }; } } catch (e) { return { success: false, message: "Failed to get weekly report" }; } }, async getAllWeeklyReportsForUser( projectName: string, token: string, targetUser?: string, ): Promise> { try { const response = await fetch( `/api/getAllWeeklyReports/${projectName}?targetUser=${targetUser ?? ""}`, { method: "GET", headers: { "Content-Type": "application/json", Authorization: "Bearer " + token, }, }, ); if (!response.ok) { return { success: false, message: "Failed to get weekly reports for project: Response code " + response.status, }; } else { const data = (await response.json()) as WeeklyReport[]; return { success: true, data }; } } catch (e) { return { success: false, message: "Failed to get weekly reports for project, unknown error", }; } }, async login(NewUser: NewUser): Promise> { try { const response = await fetch("/api/login", { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(NewUser), }); if (!response.ok) { return { success: false, message: "Failed to login" }; } else { const data = (await response.json()) as { token: string }; // Update the type of 'data' return { success: true, data: data.token }; } } catch (e) { return Promise.resolve({ success: false, message: "Failed to login" }); } }, async getProject(id: number): Promise> { try { const response = await fetch(`/api/project/${id}`, { method: "GET", }); if (!response.ok) { return { success: false, message: "Failed to get project: Response code " + response.status, }; } else { const data = (await response.json()) as Project; return { success: true, data }; } // The code below is garbage but satisfies the linter // This needs fixing, do not copy this pattern } catch (e: unknown) { return { success: false, message: "Failed to get project: " + (e as Error).toString(), }; } }, async getAllUsers(token: string): Promise> { try { const response = await fetch("/api/users/all", { method: "GET", headers: { "Content-Type": "application/json", Authorization: "Bearer " + token, }, }); if (!response.ok) { return Promise.resolve({ success: false, message: "Failed to get users", }); } else { const data = (await response.json()) as string[]; return Promise.resolve({ success: true, data }); } } catch (e) { return Promise.resolve({ success: false, message: "API is not ok", }); } }, //Gets all users in a project async getAllUsersProject( projectName: string, token: string, ): Promise> { try { const response = await fetch(`/api/getUsersProject/${projectName}`, { method: "GET", headers: { "Content-Type": "application/json", Authorization: "Bearer " + token, }, }); if (!response.ok) { return Promise.resolve({ success: false, message: "Failed to get users", }); } else { const data = (await response.json()) as ProjectMember[]; return Promise.resolve({ success: true, data }); } } catch (e) { return Promise.resolve({ success: false, message: "API is not ok", }); } }, async getUnsignedReportsInProject( projectName: string, token: string, ): Promise> { try { const response = await fetch(`/api/getUnsignedReports/${projectName}`, { method: "GET", headers: { "Content-Type": "application/json", Authorization: "Bearer " + token, }, }); if (!response.ok) { return { success: false, message: "Failed to get unsigned reports for project: Response code " + response.status, }; } else { const data = (await response.json()) as WeeklyReport[]; return { success: true, data }; } } catch (e) { return { success: false, message: "Failed to get unsigned reports for project, unknown error", }; } }, async changeUserName( data: StrNameChange, token: string, ): Promise> { try { const response = await fetch("/api/changeUserName", { method: "PUT", headers: { "Content-Type": "application/json", Authorization: "Bearer " + token, }, body: JSON.stringify(data), }); if (!response.ok) { return { success: false, message: "Failed to change username" }; } else { return { success: true }; } } catch (e) { return { success: false, message: "Failed to change username" }; } }, async removeProject( projectName: string, token: string, ): Promise> { try { const response = await fetch(`/api/removeProject/${projectName}`, { method: "DELETE", headers: { "Content-Type": "application/json", Authorization: "Bearer " + token, }, }); if (!response.ok) { return Promise.resolve({ success: false, message: "Failed to remove project", }); } else { const data = await response.text(); return Promise.resolve({ success: true, message: data }); } } catch (e) { return Promise.resolve({ success: false, message: "Failed to remove project", }); } }, async signReport( reportId: number, token: string, ): Promise> { try { const response = await fetch(`/api/signReport/${reportId}`, { method: "PUT", headers: { "Content-Type": "application/json", Authorization: "Bearer " + token, }, }); if (!response.ok) { return { success: false, message: "Failed to sign report" }; } else { return { success: true, message: "Report signed" }; } } catch (e) { return { success: false, message: "Failed to sign report" }; } }, async unsignReport( reportId: number, token: string, ): Promise> { try { const response = await fetch(`/api/unsignReport/${reportId}`, { method: "PUT", headers: { "Content-Type": "application/json", Authorization: "Bearer " + token, }, }); if (!response.ok) { return { success: false, message: "Failed to unsign report" }; } else { return { success: true, message: "Report unsigned" }; } } catch (e) { return { success: false, message: "Failed to unsign report" }; } }, async promoteToPm( userName: string, projectName: string, token: string, ): Promise> { try { const response = await fetch( `/api/promoteToPm/${projectName}?userName=${userName}`, { method: "PUT", headers: { "Content-Type": "application/json", Authorization: "Bearer " + token, }, }, ); if (!response.ok) { return { success: false, message: "Failed to promote user to project manager", }; } } catch (e) { return { success: false, message: "Failed to promote user to project manager", }; } return { success: true, message: "User promoted to project manager" }; }, async getUsername(id: number, token: string): Promise> { try { const response = await fetch(`/api/username?userId=${id}`, { method: "GET", headers: { "Content-Type": "application/json", Authorization: "Bearer " + token, }, }); if (!response.ok) { return { success: false, message: "Failed to get username" }; } else { const data = (await response.json()) as string; return { success: true, data }; } } catch (e) { return { success: false, message: "Failed to get username" }; } }, };