diff --git a/packages/api/src/lib/webhook-events.test.ts b/packages/api/src/lib/webhook-events.test.ts index c2dcddf0..1ebe16e1 100644 --- a/packages/api/src/lib/webhook-events.test.ts +++ b/packages/api/src/lib/webhook-events.test.ts @@ -476,6 +476,11 @@ describe("Webhook Events", () => { parentId: region.id, isActive: true, email: null, + description: null, + website: null, + twitter: null, + facebook: null, + instagram: null, }); if (result.org) { @@ -516,6 +521,11 @@ describe("Webhook Events", () => { parentId: region.id, isActive: true, email: null, + description: null, + website: null, + twitter: null, + facebook: null, + instagram: null, }); // Verify notifyWebhooks was called with correct payload diff --git a/packages/api/src/router/org.test.ts b/packages/api/src/router/org.test.ts index 1fcd2f71..fea911ae 100644 --- a/packages/api/src/router/org.test.ts +++ b/packages/api/src/router/org.test.ts @@ -209,6 +209,11 @@ describe("Org Router", () => { parentId: f3Nation.id, isActive: true, email: "test@example.com", + description: null, + website: null, + twitter: null, + facebook: null, + instagram: null, }); expect(result).toHaveProperty("org"); @@ -233,6 +238,11 @@ describe("Org Router", () => { orgType: "region", isActive: true, email: "test@example.com", + description: null, + website: null, + twitter: null, + facebook: null, + instagram: null, }), ).rejects.toThrow("Parent ID or ID is required"); }); @@ -269,6 +279,11 @@ describe("Org Router", () => { parentId: f3Nation.id, isActive: true, email: "test@example.com", + description: null, + website: null, + twitter: null, + facebook: null, + instagram: null, }); expect(result.org?.id).toBe(testOrg.id); @@ -294,6 +309,11 @@ describe("Org Router", () => { parentId: f3Nation.id, isActive: true, email: "test@example.com", + description: null, + website: null, + twitter: null, + facebook: null, + instagram: null, }), ).rejects.toThrow(); }); diff --git a/packages/validators/src/index.ts b/packages/validators/src/index.ts index f37a6467..27f9b5d2 100644 --- a/packages/validators/src/index.ts +++ b/packages/validators/src/index.ts @@ -3,9 +3,12 @@ import { z } from "zod"; import { events, + eventTags, eventTypes, locations, orgs, + slackSpaces, + slackUsers, updateRequests, users, } from "@acme/db/schema/schema"; @@ -52,6 +55,10 @@ export const EventTypeInsertSchema = createInsertSchema(eventTypes, { }); export const EventTypeSelectSchema = createSelectSchema(eventTypes); +// EVENT TAG SCHEMA +export const EventTagInsertSchema = createInsertSchema(eventTags); +export const EventTagSelectSchema = createSelectSchema(eventTags); + // EVENT SCHEMA export const EventInsertSchema = createInsertSchema(events, { name: (s: z.ZodString) => s.min(1, { message: "Name is required" }), @@ -77,6 +84,7 @@ export const EventInsertSchema = createInsertSchema(events, { .number() .array() .min(1, { message: "Event type is required" }), + eventTagIds: z.number().array().optional(), }) .omit({ orgId: true, @@ -94,7 +102,12 @@ export type EventInsertType = z.infer; export const NationInsertSchema = createInsertSchema(orgs, { name: (s: z.ZodString) => s.min(1, { message: "Name is required" }), email: (s: z.ZodString) => - s.email({ message: "Invalid email format" }).or(z.literal("")), + s.email({ message: "Invalid email format" }).or(z.literal("")).nullable(), + description: (s: z.ZodString) => s.nullable(), + website: (s: z.ZodString) => s.nullable(), + twitter: (s: z.ZodString) => s.nullable(), + facebook: (s: z.ZodString) => s.nullable(), + instagram: (s: z.ZodString) => s.nullable(), parentId: z.null({ message: "Must not have a parent" }).optional(), }).omit({ orgType: true }); export const NationSelectSchema = createSelectSchema(orgs); @@ -106,7 +119,12 @@ export const SectorInsertSchema = createInsertSchema(orgs, { .number({ message: "Must have a parent" }) .nonnegative({ message: "Invalid selection" }), email: (s: z.ZodString) => - s.email({ message: "Invalid email format" }).or(z.literal("")), + s.email({ message: "Invalid email format" }).or(z.literal("")).nullable(), + description: (s: z.ZodString) => s.nullable(), + website: (s: z.ZodString) => s.nullable(), + twitter: (s: z.ZodString) => s.nullable(), + facebook: (s: z.ZodString) => s.nullable(), + instagram: (s: z.ZodString) => s.nullable(), }).omit({ orgType: true }); export const SectorSelectSchema = createSelectSchema(orgs); @@ -117,7 +135,12 @@ export const AreaInsertSchema = createInsertSchema(orgs, { .number({ message: "Must have a parent" }) .nonnegative({ message: "Invalid selection" }), email: (s: z.ZodString) => - s.email({ message: "Invalid email format" }).or(z.literal("")), + s.email({ message: "Invalid email format" }).or(z.literal("")).nullable(), + description: (s: z.ZodString) => s.nullable(), + website: (s: z.ZodString) => s.nullable(), + twitter: (s: z.ZodString) => s.nullable(), + facebook: (s: z.ZodString) => s.nullable(), + instagram: (s: z.ZodString) => s.nullable(), }).omit({ orgType: true }); export const AreaSelectSchema = createSelectSchema(orgs); @@ -128,7 +151,12 @@ export const RegionInsertSchema = createInsertSchema(orgs, { .number({ message: "Must have a parent" }) .nonnegative({ message: "Invalid selection" }), email: (s: z.ZodString) => - s.email({ message: "Invalid email format" }).or(z.literal("")), + s.email({ message: "Invalid email format" }).or(z.literal("")).nullable(), + description: (s: z.ZodString) => s.nullable(), + website: (s: z.ZodString) => s.nullable(), + twitter: (s: z.ZodString) => s.nullable(), + facebook: (s: z.ZodString) => s.nullable(), + instagram: (s: z.ZodString) => s.nullable(), }).omit({ orgType: true }); export const RegionSelectSchema = createSelectSchema(orgs); @@ -139,7 +167,12 @@ export const AOInsertSchema = createInsertSchema(orgs, { .number({ message: "Must have a parent" }) .nonnegative({ message: "Invalid selection" }), email: (s: z.ZodString) => - s.email({ message: "Invalid email format" }).or(z.literal("")), + s.email({ message: "Invalid email format" }).or(z.literal("")).nullable(), + description: (s: z.ZodString) => s.nullable(), + website: (s: z.ZodString) => s.nullable(), + twitter: (s: z.ZodString) => s.nullable(), + facebook: (s: z.ZodString) => s.nullable(), + instagram: (s: z.ZodString) => s.nullable(), }).omit({ orgType: true }); export const AOSelectSchema = createSelectSchema(orgs); @@ -148,9 +181,15 @@ export const OrgInsertSchema = createInsertSchema(orgs, { name: (s: z.ZodString) => s.min(1, { message: "Name is required" }), parentId: z .number({ message: "Must have a parent" }) - .nonnegative({ message: "Invalid selection" }), + .nonnegative({ message: "Invalid selection" }) + .nullable(), + description: (s: z.ZodString) => s.nullable(), email: (s: z.ZodString) => - s.email({ message: "Invalid email format" }).or(z.literal("")), + s.email({ message: "Invalid email format" }).or(z.literal("")).nullable(), + website: (s: z.ZodString) => s.nullable(), + twitter: (s: z.ZodString) => s.nullable(), + facebook: (s: z.ZodString) => s.nullable(), + instagram: (s: z.ZodString) => s.nullable(), }); export const OrgSelectSchema = createSelectSchema(orgs); @@ -258,6 +297,51 @@ export const DeleteRequestResponseSchema = z.object({ export type DeleteRequestResponse = z.infer; +// SLACK SCHEMA +export const CustomFieldSchema = z.object({ + name: z.string(), + type: z.enum(["text", "select", "multi_select", "user_select"]), + options: z.array(z.string()).optional(), + enabled: z.boolean(), +}); + +export const SlackSettingsSchema = z.object({ + welcome_dm_enable: z.boolean().optional(), + welcome_dm_template: z.string().optional(), + welcome_channel_enable: z.boolean().optional(), + welcome_channel: z.string().optional(), + editing_locked: z.boolean().optional(), + default_backblast_destination: z.string().optional(), + backblast_destination_channel: z.string().optional(), + default_preblast_destination: z.string().optional(), + preblast_destination_channel: z.string().optional(), + backblast_moleskin_template: z.string().optional(), + preblast_moleskin_template: z.string().optional(), + strava_enabled: z.boolean().optional(), + preblast_reminder_days: z.number().optional(), + backblast_reminder_days: z.number().optional(), + automated_preblast_option: z.string().optional(), + automated_preblast_hour_cst: z.number().optional(), + custom_fields: z.array(CustomFieldSchema).optional(), +}); + +export const SlackSpaceSelectSchema = createSelectSchema(slackSpaces); +export const SlackSpaceInsertSchema = createInsertSchema(slackSpaces); + +export const SlackUserSelectSchema = createSelectSchema(slackUsers); +export const SlackUserInsertSchema = createInsertSchema(slackUsers); + +export const SlackUserUpsertSchema = z.object({ + slackId: z.string(), + userName: z.string(), + email: z.string().email().optional(), + teamId: z.string(), + userId: z.number().optional(), + isAdmin: z.boolean().default(false), + isOwner: z.boolean().default(false), + isBot: z.boolean().default(false), +}); + // POSITION SCHEMA import { positions, positionsXOrgsXUsers } from "@acme/db/schema/schema";