| import { z } from "@hono/zod-openapi"; |
|
|
| export const getTrackerProjectsSchema = z.object({ |
| cursor: z |
| .string() |
| .nullable() |
| .optional() |
| .openapi({ |
| description: |
| "Cursor for pagination, representing the last item from the previous page", |
| example: "eyJpZCI6IjEyMyJ9", |
| param: { |
| in: "query", |
| }, |
| }), |
| pageSize: z.coerce |
| .number() |
| .min(1) |
| .max(100) |
| .optional() |
| .openapi({ |
| description: "Number of projects to return per page (1-100)", |
| example: 20, |
| param: { |
| in: "query", |
| }, |
| }), |
| q: z |
| .string() |
| .nullable() |
| .optional() |
| .openapi({ |
| description: |
| "Search query string to filter projects by name or description", |
| example: "website", |
| param: { |
| in: "query", |
| }, |
| }), |
| start: z |
| .string() |
| .nullable() |
| .optional() |
| .openapi({ |
| description: |
| "Start date for filtering projects by creation date in YYYY-MM-DD format", |
| example: "2024-04-01", |
| param: { |
| in: "query", |
| }, |
| }), |
| end: z |
| .string() |
| .nullable() |
| .optional() |
| .openapi({ |
| description: |
| "End date for filtering projects by creation date in YYYY-MM-DD format", |
| example: "2024-04-30", |
| param: { |
| in: "query", |
| }, |
| }), |
| status: z |
| .enum(["in_progress", "completed"]) |
| .nullable() |
| .optional() |
| .openapi({ |
| description: "Filter projects by status", |
| example: "in_progress", |
| param: { |
| in: "query", |
| }, |
| }), |
| customers: z |
| .array(z.string()) |
| .nullable() |
| .optional() |
| .openapi({ |
| description: |
| "Array of customer IDs to filter projects by specific customers", |
| example: ["customer-1", "customer-2"], |
| param: { |
| in: "query", |
| }, |
| }), |
| tags: z |
| .array(z.string()) |
| .nullable() |
| .optional() |
| .openapi({ |
| description: "Array of tag IDs to filter projects by specific tags", |
| example: ["tag-1", "tag-2"], |
| param: { |
| in: "query", |
| }, |
| }), |
| sort: z |
| .array(z.string()) |
| .nullable() |
| .optional() |
| .openapi({ |
| description: |
| "Sorting order as an array of field names. Prefix with '-' for descending order", |
| example: ["-createdAt", "name"], |
| param: { |
| in: "query", |
| }, |
| }), |
| }); |
|
|
| export const upsertTrackerProjectSchema = z |
| .object({ |
| id: z.string().uuid().optional().openapi({ |
| description: |
| "Unique identifier for the project. Required for updates, omit for new projects", |
| example: "b7e6c8e2-1f2a-4c3b-9e2d-1a2b3c4d5e6f", |
| }), |
| name: z.string().min(1).openapi({ |
| description: "Name of the project", |
| example: "Website Redesign", |
| }), |
| description: z.string().nullable().optional().openapi({ |
| description: "Detailed description of the project", |
| example: |
| "Complete redesign of the company website with modern UI/UX and improved performance", |
| }), |
| estimate: z.number().nullable().optional().openapi({ |
| description: "Estimated total hours required to complete the project", |
| example: 120, |
| }), |
| billable: z.boolean().nullable().optional().default(false).openapi({ |
| description: "Whether the project is billable to the customer", |
| example: true, |
| }), |
| rate: z.number().min(1).nullable().optional().openapi({ |
| description: "Hourly rate for the project in the specified currency", |
| example: 75.0, |
| }), |
| currency: z.string().nullable().optional().openapi({ |
| description: "Currency code for the project rate in ISO 4217 format", |
| example: "USD", |
| }), |
| status: z.enum(["in_progress", "completed"]).optional().openapi({ |
| description: "Current status of the project", |
| example: "in_progress", |
| }), |
| customerId: z.string().uuid().nullable().optional().openapi({ |
| description: |
| "Unique identifier of the customer associated with this project", |
| example: "a1b2c3d4-e5f6-7890-abcd-1234567890ef", |
| }), |
| tags: z |
| .array( |
| z.object({ |
| id: z.string().uuid().openapi({ |
| description: "Unique identifier of the tag", |
| example: "f1e2d3c4-b5a6-7890-1234-567890abcdef", |
| }), |
| value: z.string().openapi({ |
| description: "Display value of the tag", |
| example: "Design", |
| }), |
| }), |
| ) |
| .optional() |
| .nullable() |
| .openapi({ |
| description: "Array of tags to associate with the project", |
| example: [ |
| { id: "f1e2d3c4-b5a6-7890-1234-567890abcdef", value: "Design" }, |
| { id: "e2d3c4b5-a6f1-7890-1234-567890abcdef", value: "Frontend" }, |
| ], |
| }), |
| }) |
| .openapi("UpsertTrackerProject"); |
|
|
| export const deleteTrackerProjectSchema = z.object({ |
| id: z.string().uuid().openapi({ |
| description: "Unique identifier of the project to delete", |
| example: "b7e6c8e2-1f2a-4c3b-9e2d-1a2b3c4d5e6f", |
| }), |
| }); |
|
|
| export const getTrackerProjectByIdSchema = z.object({ |
| id: z.string().uuid().openapi({ |
| description: "Unique identifier of the project to retrieve", |
| example: "b7e6c8e2-1f2a-4c3b-9e2d-1a2b3c4d5e6f", |
| }), |
| }); |
|
|
| export const trackerProjectResponseSchema = z |
| .object({ |
| id: z.string().uuid().openapi({ |
| description: "Unique identifier of the project", |
| example: "b7e6c8e2-1f2a-4c3b-9e2d-1a2b3c4d5e6f", |
| }), |
| name: z.string().openapi({ |
| description: "Name of the project", |
| example: "Website Redesign", |
| }), |
| description: z.string().nullable().openapi({ |
| description: "Detailed description of the project", |
| example: |
| "Complete redesign of the company website with modern UI/UX and improved performance", |
| }), |
| status: z.enum(["in_progress", "completed"]).openapi({ |
| description: "Current status of the project", |
| example: "in_progress", |
| }), |
| estimate: z.number().nullable().openapi({ |
| description: "Estimated total hours required to complete the project", |
| example: 120, |
| }), |
| currency: z.string().nullable().openapi({ |
| description: "Currency code for the project rate in ISO 4217 format", |
| example: "USD", |
| }), |
| createdAt: z.string().openapi({ |
| description: |
| "Date and time when the project was created in ISO 8601 format", |
| example: "2024-05-01T12:00:00.000Z", |
| }), |
| totalDuration: z.number().nullable().openapi({ |
| description: "Total tracked time for the project in seconds", |
| example: 43200, |
| }), |
| totalAmount: z.number().openapi({ |
| description: "Total monetary amount earned from the project", |
| example: 3600.0, |
| }), |
| customer: z |
| .object({ |
| id: z.string().uuid().openapi({ |
| description: "Unique identifier of the customer", |
| example: "a1b2c3d4-e5f6-7890-abcd-1234567890ef", |
| }), |
| name: z.string().openapi({ |
| description: "Name of the customer or organization", |
| example: "Acme Corporation", |
| }), |
| website: z.string().openapi({ |
| description: "Website URL of the customer", |
| example: "https://acme.com", |
| }), |
| }) |
| .nullable() |
| .openapi({ |
| description: "Customer information associated with the project", |
| }), |
| tags: z |
| .array( |
| z.object({ |
| id: z.string().uuid().openapi({ |
| description: "Unique identifier of the tag", |
| example: "d1e2f3a4-b5c6-7890-abcd-1234567890ef", |
| }), |
| name: z.string().openapi({ |
| description: "Display name of the tag", |
| example: "Design", |
| }), |
| }), |
| ) |
| .openapi({ |
| description: "Array of tags associated with the project", |
| }), |
| users: z |
| .array( |
| z.object({ |
| id: z.string().uuid().openapi({ |
| description: "Unique identifier of the user", |
| example: "f1e2d3c4-b5a6-7890-abcd-1234567890ef", |
| }), |
| fullName: z.string().openapi({ |
| description: "Full name of the user", |
| example: "Jane Doe", |
| }), |
| avatarUrl: z.string().url().openapi({ |
| description: "URL to the user's avatar image", |
| example: "https://cdn.midday.ai/avatar.jpg", |
| }), |
| }), |
| ) |
| .nullable() |
| .openapi({ |
| description: "Array of users assigned to work on the project", |
| }), |
| }) |
| .openapi("TrackerProjectResponse"); |
|
|
| export const trackerProjectsResponseSchema = z |
| .object({ |
| meta: z |
| .object({ |
| hasNextPage: z.boolean().openapi({ |
| description: |
| "Whether there are more projects available on the next page", |
| example: true, |
| }), |
| hasPreviousPage: z.boolean().openapi({ |
| description: |
| "Whether there are more projects available on the previous page", |
| example: false, |
| }), |
| }) |
| .openapi({ |
| description: "Pagination metadata for the projects response", |
| }), |
| data: z.array(trackerProjectResponseSchema).openapi({ |
| description: "Array of tracker projects matching the query criteria", |
| }), |
| }) |
| .openapi("TrackerProjectsResponse"); |
|
|