import {z} from 'zod' export type GetApiV1PublicEventsArgs = {fromDate: string, toDate: string, forTeamIds?: Array | undefined, forTeamCodes?: Array | undefined, forMemberIds?: Array | undefined, forMemberCodes?: Array | undefined, forLocationIds?: Array | undefined, forLocationCodes?: Array | undefined, forSkillIds?: Array | undefined, forSkillCodes?: Array | undefined, forConditionCodes?: (Array<'REGULAR_SHIFTS' | 'STANDBY_SHIFTS' | 'REPLACEMENTS' | 'UNFILLED_SHIFTS' | 'ASSIGNMENTS_TO_APPROVE' | 'REPLACEMENT_REQUESTS' | 'SWAP_REQUESTS' | 'REGULAR_SHIFTS_TO_APPROVE' | 'REPLACEMENTS_TO_APPROVE' | 'SWAPS_TO_APPROVE' | 'DRAFTS' | 'CANCELLED' | 'UNFILLED_SHIFTS_AND_DRAFT' | 'AUTO_SCHEDULED' | 'OPEN_EVENT_ASSIGNED' | 'EVENT_NOT_CONFIRMED' | 'RECURRENT_SHIFTS' | 'UNIQUE_SHIFTS'>) | undefined, locale?: string | undefined, withOpenShifts?: boolean | undefined, includeRelationships?: boolean | undefined}; export type GetApiV1PublicEventsOptions = {baseUrl?: string | undefined, basic?: {username: string, password: string} | undefined, fetch?: typeof fetch | undefined}; export const publicEventClockingEntry = z.object({at: z.string().optional(), originalAt: z.string().optional()}); export const publicBreak = z.object({paid: z.boolean(), durationInM: z.number(), startInM: z.number().optional()}); export const publicEventClocking = z.object({in: publicEventClockingEntry, out: publicEventClockingEntry, clockedBreaks: z.array(z.string()), paidDurationInM: z.number(), updatedByMemberId: z.string().optional(), updatedByMemberCode: z.string().optional(), updatedAt: z.string().optional(), validatedBy: z.enum(["MEMBER", "SMART_PUNCH"]).optional(), validatedByMemberId: z.string().optional(), validatedByMemberCode: z.string().optional(), validatedAt: z.string().optional(), paidBreaks: z.array(z.string()).optional(), unpaidBreak: publicBreak.optional(), paidAmount: z.number().optional(), locked: z.boolean().optional(), lockedByMemberId: z.string().optional(), lockedByMemberCode: z.string().optional(), lockedAt: z.string().optional()}); export const publicEventPremium = z.object({uid: z.string(), adHoc: z.boolean().optional(), names: z.record(z.string(), z.string()), calculationType: z.enum(["AMOUNT", "HOURS", "HOURLY_MULTIPLIER", "HOURLY_BONUS"]), calculationAmount: z.number(), paidAmount: z.number().optional(), plannedPaidAmount: z.number().optional(), paidDurationInM: z.number().optional(), plannedPaidDurationInM: z.number().optional(), code: z.string().optional()}); export const publicEventApproval = z.object({status: z.enum(["NEEDS_APPROVAL", "APPROVED", "REFUSED"]), updatedAt: z.string().optional(), updatedByMemberId: z.string().optional(), refusalReason: z.string().optional()}); export const publicEventRequest = z.object({type: z.enum(["REPLACEMENT", "SWAP", "OPEN_SHIFT"]), reason: z.string().optional(), memberId: z.string().optional(), createdAt: z.string(), updatedAt: z.string().optional(), approval: publicEventApproval.optional(), openShiftCount: z.number().optional(), swapEventIds: z.array(z.string()).optional()}); export const publicEventInitialRequest = z.object({type: z.enum(["REPLACEMENT", "SWAP", "OPEN_SHIFT"]), memberId: z.string().optional(), reason: z.string().optional(), createdAt: z.string(), acceptedAt: z.string().optional(), swapEventId: z.string().optional(), approval: publicEventApproval.optional()}); export const publicEvent = z.object({uid: z.string(), externalId: z.string().optional(), startsAt: z.string(), endsAt: z.string(), hideEndsAt: z.boolean(), timeZone: z.string(), memberFirstName: z.string().optional(), memberLastName: z.string().optional(), memberId: z.string().optional(), memberCode: z.string().optional(), memberHourlyWage: z.number().optional(), openShiftCount: z.number().optional(), skillId: z.string(), skillName: z.string(), skillCode: z.string().optional(), locationId: z.string().optional(), locationName: z.string().optional(), locationCode: z.string().optional(), subLocationId: z.string().optional(), subLocationName: z.string().optional(), subLocationCode: z.string().optional(), divisionId: z.string().optional(), teamId: z.string(), teamCode: z.string().optional(), teamName: z.string().optional(), isStandby: z.boolean().optional(), isCancelled: z.boolean().optional(), cancelledReason: z.string().optional(), isDraft: z.boolean(), note: z.string().optional(), internalNote: z.string().optional(), paidPreparationTimeInM: z.number(), assignedBy: z.object({}), assignedAt: z.string(), splitFromEventId: z.string(), clocking: publicEventClocking.optional(), premiums: z.array(publicEventPremium).optional(), request: z.array(publicEventRequest).optional(), initialRequest: z.array(publicEventInitialRequest).optional()}); export const address = z.object({line1: z.string(), line2: z.string().optional(), city: z.string().optional(), state: z.string().optional(), postalCode: z.string().optional(), country: z.string().optional(), latitude: z.string().optional(), longitude: z.string().optional()}); export const publicUserActivity = z.object({lastActiveAt: z.string().optional()}); export const publicMember = z.object({uid: z.string(), createdAt: z.string(), updatedAt: z.string().optional(), deactivatedAt: z.string().optional(), status: z.enum(["active", "inactive", "deleted", "needs_approval"]), firstName: z.string(), lastName: z.string(), code: z.string().nullable().optional(), maxHoursPerWeek: z.number().nullable().optional(), maxHoursPerPayPeriod: z.number().nullable().optional(), hourlyWage: z.number().nullable().optional(), hourlyWageBySkillCodes: z.record(z.string(), z.number()).optional(), hourlyWageBySkillIds: z.record(z.string(), z.number()).optional(), pin: z.string(), type: z.object({}).optional(), typeId: z.object({}), typeCode: z.object({}), email: z.string().nullable().optional(), phone: z.string().nullable().optional(), hiringDate: z.number().nullable().optional(), teamIds: z.array(z.string()).nullable().optional(), teamCodes: z.array(z.string()).nullable().optional(), skillIds: z.array(z.string()).nullable().optional(), skillCodes: z.array(z.string()).nullable().optional(), locationIds: z.array(z.string()).nullable().optional(), locationCodes: z.array(z.string()).nullable().optional(), custom: z.record(z.string(), z.string().nullable()).nullable().optional(), isAdmin: z.boolean().optional(), gender: z.enum(["M", "F", "X", "P"]).optional(), emailNotification: z.boolean().optional(), pushNotification: z.boolean().optional(), birthdate: z.string().optional(), homeAddress: address.optional(), primaryEmergencyContactName: z.string().optional(), primaryEmergencyContactPhone: z.string().optional(), primaryEmergencyContactNote: z.string().optional(), secondaryEmergencyContactName: z.string().optional(), secondaryEmergencyContactPhone: z.string().optional(), secondaryEmergencyContactNote: z.string().optional(), activity: publicUserActivity.optional()}); export const publicLocation = z.object({uid: z.string(), status: z.enum(["deleted", "active"]), name: z.string(), abbrev: z.string().optional(), code: z.string().optional(), externalId: z.string().optional(), address: z.string().optional(), coordinates: z.array(z.string()).optional(), subLocationIds: z.array(z.string()).optional(), subLocations: z.array(z.string()).optional(), custom: z.record(z.string(), z.string().nullable()).nullable().optional()}); export const publicSubLocation = z.object({uid: z.string(), names: z.object({}), abbrev: z.string().optional(), code: z.string().optional(), parentLocationId: z.string(), parentLocationCode: z.string()}); export const publicSkill = z.object({uid: z.string(), status: z.enum(["active", "deleted"]), names: z.record(z.string(), z.string()), abbrev: z.string().optional(), code: z.string().optional(), externalId: z.string().optional(), colorIndex: z.number(), custom: z.record(z.string(), z.string().nullable()).nullable().optional()}); export const publicTeam = z.object({uid: z.string(), status: z.enum(["active", "deleted"]), names: z.record(z.string(), z.string()), code: z.string().optional(), externalId: z.string().optional(), locationIds: z.array(z.string()), skillIds: z.array(z.string()), custom: z.record(z.string(), z.string().nullable()).nullable().optional()}); export const getPublicEvents = z.object({events: z.array(publicEvent), members: z.array(publicMember), locations: z.array(publicLocation), subLocations: z.array(publicSubLocation), skills: z.array(publicSkill), teams: z.array(publicTeam)}); export const validateResponse = async ( schema: { readonly '~standard': { readonly validate: (value: unknown) => ({ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }) | Promise<{ readonly value: Output; readonly issues?: undefined } | { readonly issues: ReadonlyArray<{ readonly message: string; readonly path?: ReadonlyArray | undefined }> }> } }, value: unknown ): Promise => { const result = await schema['~standard'].validate(value) if (result.issues !== undefined) { const detail = result.issues .map(({ message, path }) => path?.length ? `${path.map((segment) => String(typeof segment === 'object' ? segment.key : segment)).join('.')}: ${message}` : message ) .join('; ') throw new Error(`Response does not match the schema: ${detail}`, { cause: { issues: result.issues } }) } return result.value }; /** * Get events (shifts) * * GET /v1/public/events */ export const getApiV1PublicEvents = async (args: GetApiV1PublicEventsArgs, options?: GetApiV1PublicEventsOptions) => { const {baseUrl = "https://api.evolia.com", fetch: fetchFn = fetch, basic} = options ?? {} const query = new URLSearchParams() const headers = new Headers() headers.set('accept', "application/json") if (args.fromDate != null) query.append("fromDate", String(args.fromDate)) if (args.toDate != null) query.append("toDate", String(args.toDate)) for (const item of args.forTeamIds ?? []) query.append("forTeamIds", String(item)) for (const item of args.forTeamCodes ?? []) query.append("forTeamCodes", String(item)) for (const item of args.forMemberIds ?? []) query.append("forMemberIds", String(item)) for (const item of args.forMemberCodes ?? []) query.append("forMemberCodes", String(item)) for (const item of args.forLocationIds ?? []) query.append("forLocationIds", String(item)) for (const item of args.forLocationCodes ?? []) query.append("forLocationCodes", String(item)) for (const item of args.forSkillIds ?? []) query.append("forSkillIds", String(item)) for (const item of args.forSkillCodes ?? []) query.append("forSkillCodes", String(item)) for (const item of args.forConditionCodes ?? []) query.append("forConditionCodes", String(item)) if (args.locale != null) query.append("locale", String(args.locale)) if (args.withOpenShifts != null) query.append("withOpenShifts", String(args.withOpenShifts)) if (args.includeRelationships != null) query.append("includeRelationships", String(args.includeRelationships)) if (basic !== undefined) headers.set('authorization', `Basic ${btoa(`${basic.username}:${basic.password}`)}`) const url = `${baseUrl.replace(/\/+$/, '')}/v1/public/events${query.size > 0 ? `?${query}` : ''}` const res = await fetchFn(url, {method: "GET", headers}) if (!res.ok) throw new Error(`Request failed with status ${res.status}`, {cause: {status: res.status, body: await res.text()}}) return validateResponse(getPublicEvents, await res.json()) };