diff --git a/web/src/app/mapfixes/[mapfixId]/_reviewButtons.tsx b/web/src/app/mapfixes/[mapfixId]/_reviewButtons.tsx index 24d75c4..e62d42c 100644 --- a/web/src/app/mapfixes/[mapfixId]/_reviewButtons.tsx +++ b/web/src/app/mapfixes/[mapfixId]/_reviewButtons.tsx @@ -1,8 +1,11 @@ +import { Roles, RolesConstants } from "@/app/ts/Roles"; +import { MapfixStatus } from "@/app/ts/Mapfix"; import { Button, ButtonOwnProps } from "@mui/material"; +import { useState, useEffect } from "react"; type Actions = "Completed" | "Submit" | "Reject" | "Revoke" -type ApiActions = Lowercase<Actions> | "trigger-validate" | "retry-validate" | "trigger-upload" | "reset-uploading" | "reset-validating" -type Review = Actions | "Accept" | "Validate" | "Upload" | "Reset Uploading (fix softlocked status)" | "Reset Validating (fix softlocked status)" | "Request Changes" +type ApiActions = Lowercase<Actions> | "request-changes" | "trigger-validate" | "retry-validate" | "trigger-upload" | "reset-uploading" | "reset-validating" +type Review = Actions | "Request Changes" | "Accept" | "Validate" | "Upload" | "Reset Uploading (fix softlocked status)" | "Reset Validating (fix softlocked status)" | "Request Changes" interface ReviewButton { name: Review, @@ -12,7 +15,9 @@ interface ReviewButton { } interface ReviewId { - mapfixId: string + mapfixId: string, + mapfixStatus: number, + mapfixSubmitter: number, } async function ReviewButtonClicked(action: ApiActions, mapfixId: string) { @@ -45,7 +50,6 @@ function ReviewButton(props: ReviewButton) { } export default function ReviewButtons(props: ReviewId) { - const mapfixId = props.mapfixId // When is each button visible? // Multiple buttons can be visible at once. // Action | Role | When Current Status is One of: @@ -59,16 +63,82 @@ export default function ReviewButtons(props: ReviewId) { // RequestChanges | Reviewer | Validated, Accepted, Submitted // Upload | MapAdmin | Validated // ResetUploading | MapAdmin | Uploading + const { mapfixId, mapfixStatus } = props; + const [user, setUser] = useState<number|null>(null); + const [roles, setRoles] = useState<Roles>(RolesConstants.Empty); + const [loading, setLoading] = useState(true); + + useEffect(() => { + async function fetchData() { + try { + const [rolesData, userData] = await Promise.all([ + fetch("/api/session/roles").then(rolesResponse => rolesResponse.json()), + fetch("/api/session/user").then(userResponse => userResponse.json()) + ]); + + setRoles(rolesData.Roles); + setUser(userData.UserID); + } catch (error) { + console.error("Error fetching data:", error); + } finally { + setLoading(false); + } + } + + fetchData(); + }, [mapfixId]); + + if (loading) return <p>Loading...</p>; + + const visibleButtons: ReviewButton[] = []; + + const is_submitter = user === props.mapfixSubmitter; + if (is_submitter) { + if ([MapfixStatus.UnderConstruction, MapfixStatus.ChangesRequested].includes(mapfixStatus!)) { + visibleButtons.push({ name: "Submit", action: "submit", color: "info", mapfixId }); + } + if ([MapfixStatus.Submitted, MapfixStatus.ChangesRequested].includes(mapfixStatus!)) { + visibleButtons.push({ name: "Revoke", action: "revoke", color: "info", mapfixId }); + } + } + + if (roles&RolesConstants.MapfixReview) { + // you can't review your own mapfix! + // note that this means there needs to be more than one person with MapfixReview + if (!is_submitter && mapfixStatus === MapfixStatus.Submitted) { + visibleButtons.push({ name: "Accept", action: "trigger-validate", color: "info", mapfixId }); + visibleButtons.push({ name: "Reject", action: "reject", color: "error", mapfixId }); + } + if (mapfixStatus === MapfixStatus.Accepted) { + visibleButtons.push({ name: "Validate", action: "retry-validate", color: "info", mapfixId }); + } + if (mapfixStatus === MapfixStatus.Validating) { + visibleButtons.push({ name: "Reset Validating (fix softlocked status)", action: "reset-validating", color: "error", mapfixId }); + } + // this button serves the same purpose as Revoke if you are both + // the map submitter and have MapfixReview when status is Submitted + if ( + [MapfixStatus.Validated, MapfixStatus.Accepted].includes(mapfixStatus!) + || !is_submitter && mapfixStatus == MapfixStatus.Submitted + ) { + visibleButtons.push({ name: "Request Changes", action: "request-changes", color: "error", mapfixId }); + } + } + + if (roles&RolesConstants.MapfixUpload) { + if (mapfixStatus === MapfixStatus.Validated) { + visibleButtons.push({ name: "Upload", action: "trigger-upload", color: "info", mapfixId }); + } + if (mapfixStatus === MapfixStatus.Uploading) { + visibleButtons.push({ name: "Reset Uploading (fix softlocked status)", action: "reset-uploading", color: "error", mapfixId }); + } + } + return ( <section className="review-set"> - <ReviewButton color="info" name="Submit" action="submit" mapfixId={mapfixId}/> - <ReviewButton color="info" name="Revoke" action="revoke" mapfixId={mapfixId}/> - <ReviewButton color="info" name="Accept" action="trigger-validate" mapfixId={mapfixId}/> - <ReviewButton color="info" name="Validate" action="retry-validate" mapfixId={mapfixId}/> - <ReviewButton color="error" name="Reject" action="reject" mapfixId={mapfixId}/> - <ReviewButton color="info" name="Upload" action="trigger-upload" mapfixId={mapfixId}/> - <ReviewButton color="error" name="Reset Uploading (fix softlocked status)" action="reset-uploading" mapfixId={mapfixId}/> - <ReviewButton color="error" name="Reset Validating (fix softlocked status)" action="reset-validating" mapfixId={mapfixId}/> + {visibleButtons.map((btn) => ( + <ReviewButton key={btn.action} {...btn} /> + ))} </section> - ) + ); }