Rank change system UI first pass

This commit is contained in:
2025-12-16 18:47:56 -05:00
parent 7990c86a86
commit e0d9eeae92
5 changed files with 349 additions and 52 deletions

View File

@@ -0,0 +1,29 @@
import { z } from "zod";
export const batchPromotionMemberSchema = z.object({
member_id: z.number({ invalid_type_error: "Must select a member" }).int().positive(),
rank_id: z.number({ invalid_type_error: "Must select a rank" }).int().positive(),
start_date: z.string().refine((val) => !isNaN(Date.parse(val)), {
message: "Must be a valid date",
}),
reason: z.string({ required_error: "Reason is required" }).max(50, "Reason too long"),
});
export const batchPromotionSchema = z.object({
promotions: z.array(batchPromotionMemberSchema).nonempty({ message: "At least one promotion is required" }),
})
.superRefine((data, ctx) => {
// optional: check for duplicate member_ids
const memberCounts = new Map<number, number>();
data.promotions.forEach((p, index) => {
memberCounts.set(p.member_id, (memberCounts.get(p.member_id) ?? 0) + 1);
if (memberCounts.get(p.member_id)! > 1) {
ctx.addIssue({
code: z.ZodIssueCode.custom,
path: ["promotions", index, "member_id"],
message: "Duplicate member in batch is not allowed",
});
}
});
});

7
shared/types/rank.ts Normal file
View File

@@ -0,0 +1,7 @@
export type Rank = {
id: number
name: string
short_name: string
category: string
sortOrder: number
}