From 19eb2be252452d02d93522d34ca2a988ea8b63c9 Mon Sep 17 00:00:00 2001 From: ajdj100 Date: Fri, 16 Jan 2026 16:26:20 -0500 Subject: [PATCH] Added "approved by" system --- api/src/routes/ranks.ts | 3 +- api/src/services/db/rankService.ts | 4 +- shared/schemas/promotionSchema.ts | 2 +- .../components/promotions/promotionForm.vue | 70 ++++++++++++++----- 4 files changed, 56 insertions(+), 23 deletions(-) diff --git a/api/src/routes/ranks.ts b/api/src/routes/ranks.ts index 8ba4afc..e1cce00 100644 --- a/api/src/routes/ranks.ts +++ b/api/src/routes/ranks.ts @@ -16,10 +16,11 @@ ur.use(requireLogin) ur.post('/', [requireRole(["17th Command", "17th Administrator", "17th HQ"]), requireMemberState(MemberState.Member)], async (req: express.Request, res: express.Response) => { try { const change = req.body.promotions as BatchPromotionMember[]; + const approver = req.body.approver as number; const author = req.user.id; if (!change) res.sendStatus(400); - await batchInsertMemberRank(change, author); + await batchInsertMemberRank(change, author, approver); logger.info('app', 'Promotion batch submitted', { author: author }) res.sendStatus(201); } catch (error) { diff --git a/api/src/services/db/rankService.ts b/api/src/services/db/rankService.ts index b806235..193a197 100644 --- a/api/src/services/db/rankService.ts +++ b/api/src/services/db/rankService.ts @@ -36,11 +36,11 @@ export async function insertMemberRank(member_id: number, rank_id: number, date? } -export async function batchInsertMemberRank(promos: BatchPromotionMember[], author: number) { +export async function batchInsertMemberRank(promos: BatchPromotionMember[], author: number, approver: number) { try { var con = await pool.getConnection(); promos.forEach(p => { - con.query(`CALL sp_update_member_rank(?, ?, ?, ?, ?, ?)`, [p.member_id, p.rank_id, author, author, "Rank Change", toDateIgnoreZone(new Date(p.start_date))]) + con.query(`CALL sp_update_member_rank(?, ?, ?, ?, ?, ?)`, [p.member_id, p.rank_id, author, approver, "Rank Change", toDateIgnoreZone(new Date(p.start_date))]) }); con.commit(); diff --git a/shared/schemas/promotionSchema.ts b/shared/schemas/promotionSchema.ts index 6c78b75..988f2f8 100644 --- a/shared/schemas/promotionSchema.ts +++ b/shared/schemas/promotionSchema.ts @@ -10,7 +10,7 @@ export const batchPromotionMemberSchema = z.object({ export const batchPromotionSchema = z.object({ promotions: z.array(batchPromotionMemberSchema, { message: "At least one promotion is required" }).nonempty({ message: "At least one promotion is required" }), - + approver: z.number({ invalid_type_error: "Must select a member" }).int().positive() }) .superRefine((data, ctx) => { // optional: check for duplicate member_ids diff --git a/ui/src/components/promotions/promotionForm.vue b/ui/src/components/promotions/promotionForm.vue index 3250ffb..c529a37 100644 --- a/ui/src/components/promotions/promotionForm.vue +++ b/ui/src/components/promotions/promotionForm.vue @@ -26,7 +26,7 @@ import { error } from 'console'; import Input from '../ui/input/Input.vue'; import Field from '../ui/field/Field.vue'; -const { handleSubmit, errors, values, resetForm, setFieldValue } = useForm({ +const { handleSubmit, errors, values, resetForm, setFieldValue, submitCount } = useForm({ validationSchema: toTypedSchema(batchPromotionSchema), validateOnMount: false, }) @@ -96,7 +96,7 @@ function filterRanks(query: string): Rank[] { r.name.toLowerCase().includes(q) || r.short_name.toLowerCase().includes(q) ); -} +} onMounted(async () => { allmembers.value = await getAllLightMembers() @@ -123,21 +123,15 @@ function setAllToday() {