refactor(api): extract holiday calendar catalog reads
This commit is contained in:
@@ -0,0 +1,203 @@
|
|||||||
|
import { TRPCError } from "@trpc/server";
|
||||||
|
import { z } from "zod";
|
||||||
|
import { findUniqueOrThrow } from "../db/helpers.js";
|
||||||
|
import { adminProcedure } from "../trpc.js";
|
||||||
|
import { asHolidayCalendarDb, type HolidayReadContext } from "./holiday-calendar-shared.js";
|
||||||
|
|
||||||
|
const HolidayCalendarCatalogInputSchema = z.object({
|
||||||
|
includeInactive: z.boolean().optional(),
|
||||||
|
countryCode: z.string().trim().min(1).optional(),
|
||||||
|
scopeType: z.enum(["COUNTRY", "STATE", "CITY"]).optional(),
|
||||||
|
stateCode: z.string().trim().min(1).optional(),
|
||||||
|
metroCity: z.string().trim().min(1).optional(),
|
||||||
|
}).optional();
|
||||||
|
|
||||||
|
function formatIsoDate(value: Date): string {
|
||||||
|
return value.toISOString().slice(0, 10);
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatHolidayCalendarEntryDetail(entry: {
|
||||||
|
id: string;
|
||||||
|
date: Date;
|
||||||
|
name: string;
|
||||||
|
isRecurringAnnual?: boolean | null;
|
||||||
|
source?: string | null;
|
||||||
|
}) {
|
||||||
|
return {
|
||||||
|
id: entry.id,
|
||||||
|
date: formatIsoDate(entry.date),
|
||||||
|
name: entry.name,
|
||||||
|
isRecurringAnnual: entry.isRecurringAnnual ?? false,
|
||||||
|
source: entry.source ?? null,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatHolidayCalendarDetail(calendar: {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
scopeType: string;
|
||||||
|
stateCode?: string | null;
|
||||||
|
isActive?: boolean | null;
|
||||||
|
priority?: number | null;
|
||||||
|
country?: { id: string; code: string; name: string } | null;
|
||||||
|
metroCity?: { id: string; name: string } | null;
|
||||||
|
_count?: { entries?: number | null } | null;
|
||||||
|
entries?: Array<{
|
||||||
|
id: string;
|
||||||
|
date: Date;
|
||||||
|
name: string;
|
||||||
|
isRecurringAnnual?: boolean | null;
|
||||||
|
source?: string | null;
|
||||||
|
}> | null;
|
||||||
|
}) {
|
||||||
|
const entries = calendar.entries?.map(formatHolidayCalendarEntryDetail) ?? [];
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: calendar.id,
|
||||||
|
name: calendar.name,
|
||||||
|
scopeType: calendar.scopeType,
|
||||||
|
stateCode: calendar.stateCode ?? null,
|
||||||
|
isActive: calendar.isActive ?? true,
|
||||||
|
priority: calendar.priority ?? 0,
|
||||||
|
country: calendar.country
|
||||||
|
? {
|
||||||
|
id: calendar.country.id,
|
||||||
|
code: calendar.country.code,
|
||||||
|
name: calendar.country.name,
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
metroCity: calendar.metroCity
|
||||||
|
? {
|
||||||
|
id: calendar.metroCity.id,
|
||||||
|
name: calendar.metroCity.name,
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
entryCount: calendar._count?.entries ?? entries.length,
|
||||||
|
entries,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async function readCalendarsSnapshot(
|
||||||
|
ctx: HolidayReadContext,
|
||||||
|
input?: z.infer<typeof HolidayCalendarCatalogInputSchema>,
|
||||||
|
) {
|
||||||
|
const db = asHolidayCalendarDb(ctx.db);
|
||||||
|
const where = {
|
||||||
|
...(input?.includeInactive ? {} : { isActive: true }),
|
||||||
|
...(input?.countryCode
|
||||||
|
? {
|
||||||
|
country: { code: { equals: input.countryCode.trim().toUpperCase(), mode: "insensitive" as const } },
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
...(input?.scopeType ? { scopeType: input.scopeType } : {}),
|
||||||
|
...(input?.stateCode ? { stateCode: input.stateCode.trim().toUpperCase() } : {}),
|
||||||
|
...(input?.metroCity
|
||||||
|
? {
|
||||||
|
metroCity: { name: { contains: input.metroCity.trim(), mode: "insensitive" as const } },
|
||||||
|
}
|
||||||
|
: {}),
|
||||||
|
};
|
||||||
|
|
||||||
|
return db.holidayCalendar.findMany({
|
||||||
|
where,
|
||||||
|
include: {
|
||||||
|
country: { select: { id: true, code: true, name: true } },
|
||||||
|
metroCity: { select: { id: true, name: true } },
|
||||||
|
_count: { select: { entries: true } },
|
||||||
|
entries: { orderBy: [{ date: "asc" }, { name: "asc" }] },
|
||||||
|
},
|
||||||
|
orderBy: [
|
||||||
|
{ country: { name: "asc" } },
|
||||||
|
{ scopeType: "asc" },
|
||||||
|
{ priority: "desc" },
|
||||||
|
{ name: "asc" },
|
||||||
|
],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function readCalendarByIdentifierSnapshot(ctx: HolidayReadContext, identifier: string) {
|
||||||
|
const db = asHolidayCalendarDb(ctx.db);
|
||||||
|
const trimmedIdentifier = identifier.trim();
|
||||||
|
|
||||||
|
let calendar = await db.holidayCalendar.findUnique({
|
||||||
|
where: { id: trimmedIdentifier },
|
||||||
|
include: {
|
||||||
|
country: { select: { id: true, code: true, name: true } },
|
||||||
|
metroCity: { select: { id: true, name: true } },
|
||||||
|
entries: { orderBy: [{ date: "asc" }, { name: "asc" }] },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!calendar) {
|
||||||
|
calendar = await db.holidayCalendar.findFirst({
|
||||||
|
where: { name: { equals: trimmedIdentifier, mode: "insensitive" } },
|
||||||
|
include: {
|
||||||
|
country: { select: { id: true, code: true, name: true } },
|
||||||
|
metroCity: { select: { id: true, name: true } },
|
||||||
|
entries: { orderBy: [{ date: "asc" }, { name: "asc" }] },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!calendar) {
|
||||||
|
calendar = await db.holidayCalendar.findFirst({
|
||||||
|
where: { name: { contains: trimmedIdentifier, mode: "insensitive" } },
|
||||||
|
include: {
|
||||||
|
country: { select: { id: true, code: true, name: true } },
|
||||||
|
metroCity: { select: { id: true, name: true } },
|
||||||
|
entries: { orderBy: [{ date: "asc" }, { name: "asc" }] },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!calendar) {
|
||||||
|
throw new TRPCError({ code: "NOT_FOUND", message: `Holiday calendar not found: ${trimmedIdentifier}` });
|
||||||
|
}
|
||||||
|
|
||||||
|
return calendar;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const holidayCalendarCatalogReadProcedures = {
|
||||||
|
listCalendars: adminProcedure
|
||||||
|
.input(HolidayCalendarCatalogInputSchema)
|
||||||
|
.query(async ({ ctx, input }) => readCalendarsSnapshot(ctx, input)),
|
||||||
|
|
||||||
|
listCalendarsDetail: adminProcedure
|
||||||
|
.input(HolidayCalendarCatalogInputSchema)
|
||||||
|
.query(async ({ ctx, input }) => {
|
||||||
|
const calendars = await readCalendarsSnapshot(ctx, input);
|
||||||
|
return {
|
||||||
|
count: calendars.length,
|
||||||
|
calendars: calendars.map(formatHolidayCalendarDetail),
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
|
||||||
|
getCalendarByIdentifier: adminProcedure
|
||||||
|
.input(z.object({ identifier: z.string().trim().min(1) }))
|
||||||
|
.query(async ({ ctx, input }) => readCalendarByIdentifierSnapshot(ctx, input.identifier)),
|
||||||
|
|
||||||
|
getCalendarByIdentifierDetail: adminProcedure
|
||||||
|
.input(z.object({ identifier: z.string().trim().min(1) }))
|
||||||
|
.query(async ({ ctx, input }) => {
|
||||||
|
const calendar = await readCalendarByIdentifierSnapshot(ctx, input.identifier);
|
||||||
|
return formatHolidayCalendarDetail(calendar);
|
||||||
|
}),
|
||||||
|
|
||||||
|
getCalendarById: adminProcedure
|
||||||
|
.input(z.object({ id: z.string() }))
|
||||||
|
.query(async ({ ctx, input }) => {
|
||||||
|
const db = asHolidayCalendarDb(ctx.db);
|
||||||
|
|
||||||
|
return findUniqueOrThrow(
|
||||||
|
db.holidayCalendar.findUnique({
|
||||||
|
where: { id: input.id },
|
||||||
|
include: {
|
||||||
|
country: { select: { id: true, code: true, name: true } },
|
||||||
|
metroCity: { select: { id: true, name: true } },
|
||||||
|
entries: { orderBy: [{ date: "asc" }, { name: "asc" }] },
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
"Holiday calendar",
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
};
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
import type { TRPCContext } from "../trpc.js";
|
||||||
|
|
||||||
|
export type HolidayReadContext = Pick<TRPCContext, "db" | "dbUser">;
|
||||||
|
|
||||||
|
export type HolidayCalendarDb = TRPCContext["db"] & {
|
||||||
|
holidayCalendar: {
|
||||||
|
findFirst: (args: unknown) => Promise<{ id: string } | null>;
|
||||||
|
findMany: (args: unknown) => Promise<any[]>;
|
||||||
|
findUnique: (args: unknown) => Promise<any | null>;
|
||||||
|
create: (args: unknown) => Promise<any>;
|
||||||
|
update: (args: unknown) => Promise<any>;
|
||||||
|
delete: (args: unknown) => Promise<any>;
|
||||||
|
};
|
||||||
|
holidayCalendarEntry: {
|
||||||
|
findFirst: (args: unknown) => Promise<{ id: string } | null>;
|
||||||
|
findUnique: (args: unknown) => Promise<any | null>;
|
||||||
|
create: (args: unknown) => Promise<any>;
|
||||||
|
update: (args: unknown) => Promise<any>;
|
||||||
|
delete: (args: unknown) => Promise<any>;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export function asHolidayCalendarDb(db: TRPCContext["db"]): HolidayCalendarDb {
|
||||||
|
return db as unknown as HolidayCalendarDb;
|
||||||
|
}
|
||||||
@@ -11,10 +11,11 @@ import { z } from "zod";
|
|||||||
import { findUniqueOrThrow } from "../db/helpers.js";
|
import { findUniqueOrThrow } from "../db/helpers.js";
|
||||||
import { createAuditEntry } from "../lib/audit.js";
|
import { createAuditEntry } from "../lib/audit.js";
|
||||||
import { asHolidayResolverDb, getResolvedCalendarHolidays } from "../lib/holiday-availability.js";
|
import { asHolidayResolverDb, getResolvedCalendarHolidays } from "../lib/holiday-availability.js";
|
||||||
import { createTRPCRouter, adminProcedure, protectedProcedure, type TRPCContext } from "../trpc.js";
|
import { createTRPCRouter, adminProcedure, protectedProcedure } from "../trpc.js";
|
||||||
|
import { holidayCalendarCatalogReadProcedures } from "./holiday-calendar-catalog-read.js";
|
||||||
|
import { asHolidayCalendarDb, type HolidayCalendarDb, type HolidayReadContext } from "./holiday-calendar-shared.js";
|
||||||
|
|
||||||
type HolidayCalendarScope = HolidayCalendarScopeInput;
|
type HolidayCalendarScope = HolidayCalendarScopeInput;
|
||||||
type HolidayReadContext = Pick<TRPCContext, "db" | "dbUser">;
|
|
||||||
|
|
||||||
const HOLIDAY_SCOPE = {
|
const HOLIDAY_SCOPE = {
|
||||||
COUNTRY: "COUNTRY",
|
COUNTRY: "COUNTRY",
|
||||||
@@ -22,28 +23,6 @@ const HOLIDAY_SCOPE = {
|
|||||||
CITY: "CITY",
|
CITY: "CITY",
|
||||||
} as const satisfies Record<HolidayCalendarScope, HolidayCalendarScope>;
|
} as const satisfies Record<HolidayCalendarScope, HolidayCalendarScope>;
|
||||||
|
|
||||||
type HolidayCalendarDb = TRPCContext["db"] & {
|
|
||||||
holidayCalendar: {
|
|
||||||
findFirst: (args: unknown) => Promise<{ id: string } | null>;
|
|
||||||
findMany: (args: unknown) => Promise<any[]>;
|
|
||||||
findUnique: (args: unknown) => Promise<any | null>;
|
|
||||||
create: (args: unknown) => Promise<any>;
|
|
||||||
update: (args: unknown) => Promise<any>;
|
|
||||||
delete: (args: unknown) => Promise<any>;
|
|
||||||
};
|
|
||||||
holidayCalendarEntry: {
|
|
||||||
findFirst: (args: unknown) => Promise<{ id: string } | null>;
|
|
||||||
findUnique: (args: unknown) => Promise<any | null>;
|
|
||||||
create: (args: unknown) => Promise<any>;
|
|
||||||
update: (args: unknown) => Promise<any>;
|
|
||||||
delete: (args: unknown) => Promise<any>;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
function asHolidayCalendarDb(db: TRPCContext["db"]): HolidayCalendarDb {
|
|
||||||
return db as unknown as HolidayCalendarDb;
|
|
||||||
}
|
|
||||||
|
|
||||||
function clampDate(date: Date): Date {
|
function clampDate(date: Date): Date {
|
||||||
const value = new Date(date);
|
const value = new Date(date);
|
||||||
value.setUTCHours(0, 0, 0, 0);
|
value.setUTCHours(0, 0, 0, 0);
|
||||||
@@ -54,71 +33,6 @@ function fmtDate(value: Date | null | undefined): string | null {
|
|||||||
return value ? value.toISOString().slice(0, 10) : null;
|
return value ? value.toISOString().slice(0, 10) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function formatIsoDate(value: Date): string {
|
|
||||||
return value.toISOString().slice(0, 10);
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatHolidayCalendarEntryDetail(entry: {
|
|
||||||
id: string;
|
|
||||||
date: Date;
|
|
||||||
name: string;
|
|
||||||
isRecurringAnnual?: boolean | null;
|
|
||||||
source?: string | null;
|
|
||||||
}) {
|
|
||||||
return {
|
|
||||||
id: entry.id,
|
|
||||||
date: formatIsoDate(entry.date),
|
|
||||||
name: entry.name,
|
|
||||||
isRecurringAnnual: entry.isRecurringAnnual ?? false,
|
|
||||||
source: entry.source ?? null,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function formatHolidayCalendarDetail(calendar: {
|
|
||||||
id: string;
|
|
||||||
name: string;
|
|
||||||
scopeType: string;
|
|
||||||
stateCode?: string | null;
|
|
||||||
isActive?: boolean | null;
|
|
||||||
priority?: number | null;
|
|
||||||
country?: { id: string; code: string; name: string } | null;
|
|
||||||
metroCity?: { id: string; name: string } | null;
|
|
||||||
_count?: { entries?: number | null } | null;
|
|
||||||
entries?: Array<{
|
|
||||||
id: string;
|
|
||||||
date: Date;
|
|
||||||
name: string;
|
|
||||||
isRecurringAnnual?: boolean | null;
|
|
||||||
source?: string | null;
|
|
||||||
}> | null;
|
|
||||||
}) {
|
|
||||||
const entries = calendar.entries?.map(formatHolidayCalendarEntryDetail) ?? [];
|
|
||||||
|
|
||||||
return {
|
|
||||||
id: calendar.id,
|
|
||||||
name: calendar.name,
|
|
||||||
scopeType: calendar.scopeType,
|
|
||||||
stateCode: calendar.stateCode ?? null,
|
|
||||||
isActive: calendar.isActive ?? true,
|
|
||||||
priority: calendar.priority ?? 0,
|
|
||||||
country: calendar.country
|
|
||||||
? {
|
|
||||||
id: calendar.country.id,
|
|
||||||
code: calendar.country.code,
|
|
||||||
name: calendar.country.name,
|
|
||||||
}
|
|
||||||
: null,
|
|
||||||
metroCity: calendar.metroCity
|
|
||||||
? {
|
|
||||||
id: calendar.metroCity.id,
|
|
||||||
name: calendar.metroCity.name,
|
|
||||||
}
|
|
||||||
: null,
|
|
||||||
entryCount: calendar._count?.entries ?? entries.length,
|
|
||||||
entries,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function canManageHolidayResourceReads(ctx: { dbUser: { systemRole: string } | null }): boolean {
|
function canManageHolidayResourceReads(ctx: { dbUser: { systemRole: string } | null }): boolean {
|
||||||
const role = ctx.dbUser?.systemRole;
|
const role = ctx.dbUser?.systemRole;
|
||||||
return role === "ADMIN" || role === "MANAGER";
|
return role === "ADMIN" || role === "MANAGER";
|
||||||
@@ -243,92 +157,6 @@ const ResolveResourceHolidaysInputSchema = z.object({
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
async function readCalendarsSnapshot(
|
|
||||||
ctx: HolidayReadContext,
|
|
||||||
input?: {
|
|
||||||
includeInactive?: boolean | undefined;
|
|
||||||
countryCode?: string | undefined;
|
|
||||||
scopeType?: "COUNTRY" | "STATE" | "CITY" | undefined;
|
|
||||||
stateCode?: string | undefined;
|
|
||||||
metroCity?: string | undefined;
|
|
||||||
},
|
|
||||||
) {
|
|
||||||
const db = asHolidayCalendarDb(ctx.db);
|
|
||||||
const where = {
|
|
||||||
...(input?.includeInactive ? {} : { isActive: true }),
|
|
||||||
...(input?.countryCode
|
|
||||||
? {
|
|
||||||
country: { code: { equals: input.countryCode.trim().toUpperCase(), mode: "insensitive" as const } },
|
|
||||||
}
|
|
||||||
: {}),
|
|
||||||
...(input?.scopeType ? { scopeType: input.scopeType } : {}),
|
|
||||||
...(input?.stateCode ? { stateCode: input.stateCode.trim().toUpperCase() } : {}),
|
|
||||||
...(input?.metroCity
|
|
||||||
? {
|
|
||||||
metroCity: { name: { contains: input.metroCity.trim(), mode: "insensitive" as const } },
|
|
||||||
}
|
|
||||||
: {}),
|
|
||||||
};
|
|
||||||
|
|
||||||
return db.holidayCalendar.findMany({
|
|
||||||
where,
|
|
||||||
include: {
|
|
||||||
country: { select: { id: true, code: true, name: true } },
|
|
||||||
metroCity: { select: { id: true, name: true } },
|
|
||||||
_count: { select: { entries: true } },
|
|
||||||
entries: { orderBy: [{ date: "asc" }, { name: "asc" }] },
|
|
||||||
},
|
|
||||||
orderBy: [
|
|
||||||
{ country: { name: "asc" } },
|
|
||||||
{ scopeType: "asc" },
|
|
||||||
{ priority: "desc" },
|
|
||||||
{ name: "asc" },
|
|
||||||
],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function readCalendarByIdentifierSnapshot(ctx: HolidayReadContext, identifier: string) {
|
|
||||||
const db = asHolidayCalendarDb(ctx.db);
|
|
||||||
const trimmedIdentifier = identifier.trim();
|
|
||||||
|
|
||||||
let calendar = await db.holidayCalendar.findUnique({
|
|
||||||
where: { id: trimmedIdentifier },
|
|
||||||
include: {
|
|
||||||
country: { select: { id: true, code: true, name: true } },
|
|
||||||
metroCity: { select: { id: true, name: true } },
|
|
||||||
entries: { orderBy: [{ date: "asc" }, { name: "asc" }] },
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!calendar) {
|
|
||||||
calendar = await db.holidayCalendar.findFirst({
|
|
||||||
where: { name: { equals: trimmedIdentifier, mode: "insensitive" } },
|
|
||||||
include: {
|
|
||||||
country: { select: { id: true, code: true, name: true } },
|
|
||||||
metroCity: { select: { id: true, name: true } },
|
|
||||||
entries: { orderBy: [{ date: "asc" }, { name: "asc" }] },
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!calendar) {
|
|
||||||
calendar = await db.holidayCalendar.findFirst({
|
|
||||||
where: { name: { contains: trimmedIdentifier, mode: "insensitive" } },
|
|
||||||
include: {
|
|
||||||
country: { select: { id: true, code: true, name: true } },
|
|
||||||
metroCity: { select: { id: true, name: true } },
|
|
||||||
entries: { orderBy: [{ date: "asc" }, { name: "asc" }] },
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!calendar) {
|
|
||||||
throw new TRPCError({ code: "NOT_FOUND", message: `Holiday calendar not found: ${trimmedIdentifier}` });
|
|
||||||
}
|
|
||||||
|
|
||||||
return calendar;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function readPreviewResolvedHolidaysSnapshot(
|
async function readPreviewResolvedHolidaysSnapshot(
|
||||||
ctx: HolidayReadContext,
|
ctx: HolidayReadContext,
|
||||||
input: z.infer<typeof PreviewResolvedHolidaysSchema>,
|
input: z.infer<typeof PreviewResolvedHolidaysSchema>,
|
||||||
@@ -589,60 +417,7 @@ async function assertScopeConsistency(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const holidayCalendarRouter = createTRPCRouter({
|
export const holidayCalendarRouter = createTRPCRouter({
|
||||||
listCalendars: adminProcedure
|
...holidayCalendarCatalogReadProcedures,
|
||||||
.input(z.object({
|
|
||||||
includeInactive: z.boolean().optional(),
|
|
||||||
countryCode: z.string().trim().min(1).optional(),
|
|
||||||
scopeType: z.enum(["COUNTRY", "STATE", "CITY"]).optional(),
|
|
||||||
stateCode: z.string().trim().min(1).optional(),
|
|
||||||
metroCity: z.string().trim().min(1).optional(),
|
|
||||||
}).optional())
|
|
||||||
.query(async ({ ctx, input }) => readCalendarsSnapshot(ctx, input)),
|
|
||||||
|
|
||||||
listCalendarsDetail: adminProcedure
|
|
||||||
.input(z.object({
|
|
||||||
includeInactive: z.boolean().optional(),
|
|
||||||
countryCode: z.string().trim().min(1).optional(),
|
|
||||||
scopeType: z.enum(["COUNTRY", "STATE", "CITY"]).optional(),
|
|
||||||
stateCode: z.string().trim().min(1).optional(),
|
|
||||||
metroCity: z.string().trim().min(1).optional(),
|
|
||||||
}).optional())
|
|
||||||
.query(async ({ ctx, input }) => {
|
|
||||||
const calendars = await readCalendarsSnapshot(ctx, input);
|
|
||||||
return {
|
|
||||||
count: calendars.length,
|
|
||||||
calendars: calendars.map(formatHolidayCalendarDetail),
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
|
|
||||||
getCalendarByIdentifier: adminProcedure
|
|
||||||
.input(z.object({ identifier: z.string().trim().min(1) }))
|
|
||||||
.query(async ({ ctx, input }) => readCalendarByIdentifierSnapshot(ctx, input.identifier)),
|
|
||||||
|
|
||||||
getCalendarByIdentifierDetail: adminProcedure
|
|
||||||
.input(z.object({ identifier: z.string().trim().min(1) }))
|
|
||||||
.query(async ({ ctx, input }) => {
|
|
||||||
const calendar = await readCalendarByIdentifierSnapshot(ctx, input.identifier);
|
|
||||||
return formatHolidayCalendarDetail(calendar);
|
|
||||||
}),
|
|
||||||
|
|
||||||
getCalendarById: adminProcedure
|
|
||||||
.input(z.object({ id: z.string() }))
|
|
||||||
.query(async ({ ctx, input }) => {
|
|
||||||
const db = asHolidayCalendarDb(ctx.db);
|
|
||||||
|
|
||||||
return findUniqueOrThrow(
|
|
||||||
db.holidayCalendar.findUnique({
|
|
||||||
where: { id: input.id },
|
|
||||||
include: {
|
|
||||||
country: { select: { id: true, code: true, name: true } },
|
|
||||||
metroCity: { select: { id: true, name: true } },
|
|
||||||
entries: { orderBy: [{ date: "asc" }, { name: "asc" }] },
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
"Holiday calendar",
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
|
|
||||||
createCalendar: adminProcedure
|
createCalendar: adminProcedure
|
||||||
.input(CreateHolidayCalendarSchema)
|
.input(CreateHolidayCalendarSchema)
|
||||||
|
|||||||
Reference in New Issue
Block a user