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 a826617..4bffdde 100644 --- a/api/src/services/db/rankService.ts +++ b/api/src/services/db/rankService.ts @@ -2,7 +2,7 @@ import { BatchPromotion, BatchPromotionMember } from "@app/shared/schemas/promot import { PromotionDetails, PromotionSummary } from "@app/shared/types/rank" import pool from "../../db"; import { PagedData } from "@app/shared/types/pagination"; -import { toDateTime } from "@app/shared/utils/time"; +import { toDate, toDateIgnoreZone, toDateTime } from "@app/shared/utils/time"; export async function getAllRanks() { const rows = await pool.query( @@ -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", toDateTime(new Date(p.start_date))]) + con.query(`CALL sp_update_member_rank(?, ?, ?, ?, ?, ?)`, [p.member_id, p.rank_id, approver, author, "Rank Change", toDateIgnoreZone(new Date(p.start_date))]) }); con.commit(); @@ -91,8 +91,10 @@ export async function getPromotionsOnDay(day: Date): Promise // SQL query to fetch all records from members_unit for the specified day let sql = ` SELECT - mr.member_id, + mr.id AS promo_id, + mr.member_id, mr.created_by_id, + mr.authorized_by_id, r.short_name FROM members_ranks AS mr LEFT JOIN ranks AS r ON r.id = mr.rank_id 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/shared/types/rank.ts b/shared/types/rank.ts index 6ec4f3a..91899b1 100644 --- a/shared/types/rank.ts +++ b/shared/types/rank.ts @@ -11,7 +11,9 @@ export interface PromotionSummary { } export interface PromotionDetails { + promo_id: number; member_id: number; short_name: string; created_by_id: number; + authorized_by_id: number; } \ No newline at end of file diff --git a/shared/utils/time.ts b/shared/utils/time.ts index e1b5ea8..58ab991 100644 --- a/shared/utils/time.ts +++ b/shared/utils/time.ts @@ -3,12 +3,34 @@ export function toDateTime(date: Date): string { date = new Date(date); } // This produces a CST-local time because server runs in CST - const year = date.getFullYear(); - const month = (date.getMonth() + 1).toString().padStart(2, "0"); - const day = date.getDate().toString().padStart(2, "0"); - const hour = date.getHours().toString().padStart(2, "0"); + const year = date.getFullYear(); + const month = (date.getMonth() + 1).toString().padStart(2, "0"); + const day = date.getDate().toString().padStart(2, "0"); + const hour = date.getHours().toString().padStart(2, "0"); const minute = date.getMinutes().toString().padStart(2, "0"); const second = date.getSeconds().toString().padStart(2, "0"); return `${year}-${month}-${day} ${hour}:${minute}:${second}`; } + +export function toDateIgnoreZone(date: Date): string { + if (typeof date === 'string') { + date = new Date(date); + } + return date.toISOString().split('T')[0]; +} + +export function toDate(date: Date): string { + if (typeof date === 'string') { + date = new Date(date); + } + console.log(date); + // This produces a CST-local date because server runs in CST + const year = date.getFullYear(); + const month = (date.getMonth() + 1).toString().padStart(2, "0"); + const day = date.getDate().toString().padStart(2, "0"); + let out = `${year}-${month}-${day}`; + + console.log(out); + return out; +} \ No newline at end of file diff --git a/ui/src/components/promotions/promotionForm.vue b/ui/src/components/promotions/promotionForm.vue index dc7b10f..a6708f6 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, }) @@ -38,6 +38,7 @@ const submitForm = handleSubmit( output.promotions.map(p => p.start_date = new Date(p.start_date).toISOString()) await submitRankChange(output); formSubmitted.value = true; + emit("submitted"); } catch (error) { submitError.value = error; console.error(error); @@ -45,6 +46,10 @@ const submitForm = handleSubmit( } ); +const emit = defineEmits<{ + submitted: [void] +}>(); + const submitError = ref(null); const formSubmitted = ref(false); @@ -123,21 +128,15 @@ function setAllToday() {