Ensure completed request view is readonly
This commit is contained in:
@@ -563,6 +563,10 @@ export const app = new Elysia()
|
|||||||
params: t.Object({ id: t.String() })
|
params: t.Object({ id: t.String() })
|
||||||
})
|
})
|
||||||
.post("/:id/request-action", async ({ params: { id }, body: { reviewerNotes, activityVerifications } }) => {
|
.post("/:id/request-action", async ({ params: { id }, body: { reviewerNotes, activityVerifications } }) => {
|
||||||
|
const verification = await s.Verifications.get(id);
|
||||||
|
if (!verification) throw new NotFoundError("Verification not found");
|
||||||
|
if (verification.status === "completed") throw status(409, { error: "Cannot modify a completed verification" });
|
||||||
|
|
||||||
const updated = await s.Verifications.requestAction(id, reviewerNotes ?? null, activityVerifications);
|
const updated = await s.Verifications.requestAction(id, reviewerNotes ?? null, activityVerifications);
|
||||||
if (!updated) throw new NotFoundError("Verification not found");
|
if (!updated) throw new NotFoundError("Verification not found");
|
||||||
}, {
|
}, {
|
||||||
@@ -573,6 +577,10 @@ export const app = new Elysia()
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
.post("/:id/complete", async ({ params: { id }, body: { activityVerifications }, accountId }) => {
|
.post("/:id/complete", async ({ params: { id }, body: { activityVerifications }, accountId }) => {
|
||||||
|
const verification = await s.Verifications.get(id);
|
||||||
|
if (!verification) throw new NotFoundError("Verification not found");
|
||||||
|
if (verification.status === "completed") throw status(409, { error: "Cannot modify a completed verification" });
|
||||||
|
|
||||||
const updated = await s.Verifications.complete(id, accountId, activityVerifications);
|
const updated = await s.Verifications.complete(id, accountId, activityVerifications);
|
||||||
if (!updated) throw new NotFoundError("Verification not found");
|
if (!updated) throw new NotFoundError("Verification not found");
|
||||||
}, {
|
}, {
|
||||||
|
|||||||
@@ -120,6 +120,7 @@
|
|||||||
ACTIVITIES.filter((a) => verf[a] !== "unset").length,
|
ACTIVITIES.filter((a) => verf[a] !== "unset").length,
|
||||||
);
|
);
|
||||||
const allReviewed = $derived(reviewedCount === ACTIVITIES.length);
|
const allReviewed = $derived(reviewedCount === ACTIVITIES.length);
|
||||||
|
const isReadOnly = $derived(verification?.status === "completed");
|
||||||
|
|
||||||
async function load() {
|
async function load() {
|
||||||
loading = true;
|
loading = true;
|
||||||
@@ -152,6 +153,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setVerf(activity: Activity, choice: VerfChoice) {
|
function setVerf(activity: Activity, choice: VerfChoice) {
|
||||||
|
if (isReadOnly) return;
|
||||||
verf[activity] = choice;
|
verf[activity] = choice;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -290,6 +292,7 @@
|
|||||||
class="btn btn-sm {verf[activity] === 'pass'
|
class="btn btn-sm {verf[activity] === 'pass'
|
||||||
? 'btn-success'
|
? 'btn-success'
|
||||||
: 'btn-outline btn-success'}"
|
: 'btn-outline btn-success'}"
|
||||||
|
disabled={isReadOnly}
|
||||||
onclick={() => setVerf(activity, "pass")}
|
onclick={() => setVerf(activity, "pass")}
|
||||||
>
|
>
|
||||||
Pass
|
Pass
|
||||||
@@ -298,13 +301,14 @@
|
|||||||
class="btn btn-sm {verf[activity] === 'fail'
|
class="btn btn-sm {verf[activity] === 'fail'
|
||||||
? 'btn-error'
|
? 'btn-error'
|
||||||
: 'btn-outline btn-error'}"
|
: 'btn-outline btn-error'}"
|
||||||
|
disabled={isReadOnly}
|
||||||
onclick={() => setVerf(activity, "fail")}
|
onclick={() => setVerf(activity, "fail")}
|
||||||
>
|
>
|
||||||
Fail
|
Fail
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="btn btn-sm btn-ghost"
|
class="btn btn-sm btn-ghost"
|
||||||
disabled={verf[activity] === "unset"}
|
disabled={isReadOnly || verf[activity] === "unset"}
|
||||||
onclick={() => setVerf(activity, "unset")}
|
onclick={() => setVerf(activity, "unset")}
|
||||||
>
|
>
|
||||||
Clear
|
Clear
|
||||||
@@ -396,6 +400,7 @@
|
|||||||
class="textarea textarea-bordered w-full"
|
class="textarea textarea-bordered w-full"
|
||||||
rows="3"
|
rows="3"
|
||||||
placeholder="What needs to be fixed?"
|
placeholder="What needs to be fixed?"
|
||||||
|
disabled={isReadOnly}
|
||||||
bind:value={notes}
|
bind:value={notes}
|
||||||
></textarea>
|
></textarea>
|
||||||
</label>
|
</label>
|
||||||
@@ -415,6 +420,11 @@
|
|||||||
← Previous
|
← Previous
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
{#if isReadOnly}
|
||||||
|
<span class="text-sm opacity-70"
|
||||||
|
>This verification is completed and read-only.</span
|
||||||
|
>
|
||||||
|
{:else}
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
{#if !allReviewed}
|
{#if !allReviewed}
|
||||||
<span class="text-xs text-warning"
|
<span class="text-xs text-warning"
|
||||||
@@ -440,6 +450,7 @@
|
|||||||
: "Complete"}
|
: "Complete"}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
Reference in New Issue
Block a user