@mac777/project-pinecone-schema 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/events/events.schema.d.ts +55 -0
- package/dist/events/utils/ticket.schema.d.ts +3 -0
- package/dist/events/utils/ticket.schema.js +1 -0
- package/package.json +2 -5
- package/src/auth/auth.constants.ts +9 -0
- package/src/auth/auth.schema.ts +65 -0
- package/src/auth/auth.type.ts +42 -0
- package/src/auth/index.ts +3 -0
- package/src/auth/utils/password.schema.ts +18 -0
- package/src/events/events.constants.ts +182 -0
- package/src/events/events.schema.ts +158 -0
- package/src/events/events.type.ts +59 -0
- package/src/events/events.utils.schema.ts +5 -0
- package/{dist/events/events.d.ts → src/events/index.ts} +4 -3
- package/src/events/utils/admin.schema.ts +77 -0
- package/src/events/utils/age.restriction.schema.ts +3 -0
- package/src/events/utils/document.schema.ts +8 -0
- package/src/events/utils/event.type.schema.ts +3 -0
- package/src/events/utils/media.schema.ts +36 -0
- package/src/events/utils/organizer.schema.ts +14 -0
- package/src/events/utils/schedule.schema.ts +10 -0
- package/src/events/utils/ticket.schema.ts +33 -0
- package/src/events/utils/venue.schema.ts +22 -0
- package/src/index.ts +5 -0
- package/src/media/index.ts +2 -0
- package/src/media/media.schema.ts +37 -0
- package/src/media/media.type.ts +18 -0
- package/src/media/utils/backblaze.schema.ts +8 -0
- package/src/media/utils/imagekit.schema.ts +20 -0
- package/src/orders/index.ts +6 -0
- package/src/orders/orders.schema.ts +106 -0
- package/src/orders/orders.type.ts +85 -0
- package/src/orders/payments.schema.ts +81 -0
- package/src/orders/payments.type.ts +87 -0
- package/src/orders/ticket.schema.ts +78 -0
- package/src/orders/ticket.type.ts +103 -0
- package/tsconfig.json +13 -0
- package/dist/auth.d.ts +0 -1
- package/dist/auth.js +0 -18
- package/dist/events/admin.schema.d.ts +0 -208
- package/dist/events/admin.schema.js +0 -70
- package/dist/events/age.restriction.schema.d.ts +0 -2
- package/dist/events/age.restriction.schema.js +0 -5
- package/dist/events/document.schema.d.ts +0 -17
- package/dist/events/document.schema.js +0 -10
- package/dist/events/event.schema.d.ts +0 -0
- package/dist/events/event.schema.js +0 -1
- package/dist/events/event.type.schema.d.ts +0 -2
- package/dist/events/event.type.schema.js +0 -5
- package/dist/events/events.constant.d.ts +0 -9
- package/dist/events/events.constant.js +0 -12
- package/dist/events/events.js +0 -19
- package/dist/events/media.schema.d.ts +0 -77
- package/dist/events/media.schema.js +0 -36
- package/dist/events/organizer.schema.d.ts +0 -55
- package/dist/events/organizer.schema.js +0 -15
- package/dist/events/schedule.schema.d.ts +0 -20
- package/dist/events/schedule.schema.js +0 -11
- package/dist/events/step.schema.d.ts +0 -0
- package/dist/events/step.schema.js +0 -1
- package/dist/events/ticket.schema.d.ts +0 -113
- package/dist/events/ticket.schema.js +0 -29
- package/dist/events/utils.schema.d.ts +0 -6
- package/dist/events/utils.schema.js +0 -22
- package/dist/events/venue.schema.d.ts +0 -75
- package/dist/events/venue.schema.js +0 -22
- package/dist/events.constant.d.ts +0 -9
- package/dist/events.constant.js +0 -12
- package/dist/events.constants.d.ts +0 -9
- package/dist/events.constants.js +0 -12
- package/dist/events.d.ts +0 -39
- package/dist/events.js +0 -2
- package/dist/events.schema.d.ts +0 -229
- package/dist/events.schema.js +0 -95
- package/dist/events.type.d.ts +0 -42
- package/dist/events.type.js +0 -2
- package/dist/events.utils.schema.d.ts +0 -6
- package/dist/events.utils.schema.js +0 -22
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import { EventType, DraftEventData, AgeRestriction, VenueType, DisplayTicket } from "./events.type";
|
|
2
|
+
|
|
3
|
+
export const MAX_TAGLINE_LENGTH = 150;
|
|
4
|
+
export const MAX_CATEGORIES = 3;
|
|
5
|
+
export const MAX_DESCRIPTION_LENGTH = 2000;
|
|
6
|
+
export const MAX_DOCUMENTS = 5;
|
|
7
|
+
export const SUPPORTED_IMAGE_TYPES = ['image/jpeg', 'image/jpg', 'image/png', 'image/gif', 'image/webp'];
|
|
8
|
+
export const MAX_FILE_SIZE_MB = 10;
|
|
9
|
+
export const MAX_FILE_SIZE_BYTES = MAX_FILE_SIZE_MB * 1024 * 1024;
|
|
10
|
+
export const ALLOWED_FILE_TYPES = ['image/jpeg', 'image/png', 'application/pdf'];
|
|
11
|
+
export const ALLOWED_FILE_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.pdf'];
|
|
12
|
+
|
|
13
|
+
export const CATEGORIES_BY_TYPE: Record<string, string[]> = {
|
|
14
|
+
concert: ['Rock', 'Pop', 'Jazz', 'Electronic', 'Indie', 'Metal', 'Acoustic', 'Classical'],
|
|
15
|
+
festival: ['Music', 'Food & Drink', 'Arts', 'Film', 'Culture', 'Tech', 'Family'],
|
|
16
|
+
conference: ['Technology', 'Business', 'Design', 'Marketing', 'Leadership', 'Startup', 'AI'],
|
|
17
|
+
theater: ['Drama', 'Comedy', 'Musical', 'Dance', 'Improv', 'Classical', 'Opera'],
|
|
18
|
+
sports: ['Football', 'Basketball', 'Tennis', 'Yoga', 'Fitness', 'Running', 'eSports'],
|
|
19
|
+
other: ['Community', 'Networking', 'Workshop', 'Meetup', 'Charity', 'Social', 'Party']
|
|
20
|
+
} as const;
|
|
21
|
+
|
|
22
|
+
export const EVENT_TYPES: Array<{
|
|
23
|
+
type: EventType;
|
|
24
|
+
icon: string;
|
|
25
|
+
label: string;
|
|
26
|
+
}> = [
|
|
27
|
+
{ type: 'concert', icon: 'Music', label: 'Concert' },
|
|
28
|
+
{ type: 'festival', icon: 'Tent', label: 'Festival' },
|
|
29
|
+
{ type: 'conference', icon: 'Mic2', label: 'Seminar' },
|
|
30
|
+
{ type: 'theater', icon: 'Theater', label: 'Performance' },
|
|
31
|
+
{ type: 'sports', icon: 'Trophy', label: 'Gala' },
|
|
32
|
+
{ type: 'other', icon: 'MoreHorizontal', label: 'Other' }
|
|
33
|
+
] as const;
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
export const SUPPORTED_LANGUAGES = [
|
|
37
|
+
'English',
|
|
38
|
+
'Bangla'
|
|
39
|
+
] as const;
|
|
40
|
+
|
|
41
|
+
// Age restriction options with value (for form state) and label (for display)
|
|
42
|
+
export const AGE_RESTRICTIONS: Array<{
|
|
43
|
+
value: AgeRestriction;
|
|
44
|
+
label: string;
|
|
45
|
+
}> = [
|
|
46
|
+
{ value: 'all_ages', label: 'All Ages' },
|
|
47
|
+
{ value: '18+', label: '18+' },
|
|
48
|
+
{ value: '21+', label: '21+' },
|
|
49
|
+
] as const;
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
export const IMAGE_PLACEHOLDER_TEXT = {
|
|
54
|
+
dropzone: 'Drop your image here',
|
|
55
|
+
formats: 'Supports JPG, PNG, GIF (Max 5MB)',
|
|
56
|
+
change: 'Change Image'
|
|
57
|
+
} as const;
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
export const HOURS = Array.from({ length: 12 }, (_, i) => i + 1);
|
|
63
|
+
export const MINUTES = Array.from({ length: 60 }, (_, i) => i.toString().padStart(2, '0'));
|
|
64
|
+
export const AMPM = ['AM', 'PM'] as const;
|
|
65
|
+
export const TIME_PRESETS = [
|
|
66
|
+
{ label: '9 am', h: 9, m: '00', p: 'AM' },
|
|
67
|
+
{ label: '12 pm', h: 12, m: '00', p: 'PM' },
|
|
68
|
+
{ label: '4 pm', h: 4, m: '00', p: 'PM' },
|
|
69
|
+
{ label: '6 pm', h: 6, m: '00', p: 'PM' }
|
|
70
|
+
] as const;
|
|
71
|
+
|
|
72
|
+
export const VENUE_TYPES: Array<{
|
|
73
|
+
value: VenueType;
|
|
74
|
+
label: string;
|
|
75
|
+
icon: string;
|
|
76
|
+
}> = [
|
|
77
|
+
{ value: 'indoor', label: 'Indoor', icon: 'Building' },
|
|
78
|
+
{ value: 'outdoor', label: 'Outdoor', icon: 'Mountain' },
|
|
79
|
+
{ value: 'hybrid', label: 'Hybrid', icon: 'Building2' }
|
|
80
|
+
] as const;
|
|
81
|
+
|
|
82
|
+
export const TICKET_PRESETS: Array<{
|
|
83
|
+
id: string;
|
|
84
|
+
label: string;
|
|
85
|
+
tier: DisplayTicket['tier'];
|
|
86
|
+
styleKey: DisplayTicket['id'];
|
|
87
|
+
desc: string;
|
|
88
|
+
}> = [
|
|
89
|
+
{ id: 'regular', label: 'Regular', tier: 'regular', styleKey: "regular", desc: 'General admission ticket' },
|
|
90
|
+
{ id: 'vip', label: 'VIP', tier: 'vip', styleKey: "vip", desc: 'Premium perks & seating' },
|
|
91
|
+
{ id: 'early_bird', label: 'Early Bird', tier: 'early_bird', styleKey: "early_bird", desc: 'Discounted ticket for early purchase' },
|
|
92
|
+
] as const;
|
|
93
|
+
|
|
94
|
+
export const STEPS = [
|
|
95
|
+
{ id: 1, label: 'Basics', description: 'Event Basics' },
|
|
96
|
+
{ id: 2, label: 'Details', description: 'Event Details' },
|
|
97
|
+
{ id: 3, label: 'Logistics', description: 'Date & Venue' },
|
|
98
|
+
{ id: 4, label: 'Verify', description: 'Verification' },
|
|
99
|
+
{ id: 5, label: 'Tickets', description: 'Ticket Setup' },
|
|
100
|
+
{ id: 6, label: 'Review', description: 'Review & Publish' },
|
|
101
|
+
];
|
|
102
|
+
|
|
103
|
+
export const PREDEFINED_BENEFITS = [
|
|
104
|
+
'Early entry',
|
|
105
|
+
'Access to general area',
|
|
106
|
+
'VIP seating',
|
|
107
|
+
'Meet & greet',
|
|
108
|
+
'Backstage access',
|
|
109
|
+
'Complimentary drink',
|
|
110
|
+
'Priority parking',
|
|
111
|
+
'Exclusive merchandise'
|
|
112
|
+
] as const;
|
|
113
|
+
|
|
114
|
+
// Helper function to get tomorrow's date in ISO format
|
|
115
|
+
const getTomorrowISOString = (): string => {
|
|
116
|
+
const tomorrow = new Date();
|
|
117
|
+
tomorrow.setDate(tomorrow.getDate() + 1);
|
|
118
|
+
tomorrow.setHours(18, 0, 0, 0); // Default to 6 PM tomorrow
|
|
119
|
+
return tomorrow.toISOString();
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
const getDayAfterTomorrowISOString = (): string => {
|
|
123
|
+
const dayAfterTomorrow = new Date();
|
|
124
|
+
dayAfterTomorrow.setDate(dayAfterTomorrow.getDate() + 2);
|
|
125
|
+
dayAfterTomorrow.setHours(18, 0, 0, 0); // Default to 6 PM day after tomorrow
|
|
126
|
+
return dayAfterTomorrow.toISOString();
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
export const INITIAL_DATA: DraftEventData = {
|
|
130
|
+
title: '',
|
|
131
|
+
tagline: '',
|
|
132
|
+
type: 'concert',
|
|
133
|
+
categories: [],
|
|
134
|
+
description: '',
|
|
135
|
+
media: {
|
|
136
|
+
coverImage: {
|
|
137
|
+
url: '',
|
|
138
|
+
thumbnailUrl: '',
|
|
139
|
+
alt: ''
|
|
140
|
+
},
|
|
141
|
+
gallery: []
|
|
142
|
+
},
|
|
143
|
+
language: 'English',
|
|
144
|
+
ageRestriction: 'all_ages',
|
|
145
|
+
dressCode: 'casual',
|
|
146
|
+
schedule: {
|
|
147
|
+
startDate: getTomorrowISOString(),
|
|
148
|
+
endDate: getDayAfterTomorrowISOString(),
|
|
149
|
+
},
|
|
150
|
+
venue: {
|
|
151
|
+
name: '',
|
|
152
|
+
type: 'indoor',
|
|
153
|
+
address: {
|
|
154
|
+
street: '',
|
|
155
|
+
city: '',
|
|
156
|
+
country: '',
|
|
157
|
+
},
|
|
158
|
+
coordinates: {
|
|
159
|
+
type: 'Point',
|
|
160
|
+
coordinates: [0, 0],
|
|
161
|
+
},
|
|
162
|
+
capacity: 100,
|
|
163
|
+
parking: false,
|
|
164
|
+
publicTransit: ''
|
|
165
|
+
},
|
|
166
|
+
organizer: {
|
|
167
|
+
role: 'event_organizer',
|
|
168
|
+
contactPerson: {
|
|
169
|
+
name: '',
|
|
170
|
+
email: '',
|
|
171
|
+
phone: '',
|
|
172
|
+
},
|
|
173
|
+
companyName: ''
|
|
174
|
+
},
|
|
175
|
+
verification: {
|
|
176
|
+
documents: [],
|
|
177
|
+
},
|
|
178
|
+
tickets: [],
|
|
179
|
+
termsAccepted: false,
|
|
180
|
+
legalPermissionAccepted: false,
|
|
181
|
+
platformTermsAccepted: false,
|
|
182
|
+
};
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { eventTypeSchema } from './utils/event.type.schema';
|
|
3
|
+
import { mediaSchema } from './utils/media.schema';
|
|
4
|
+
import { scheduleSchema } from './utils/schedule.schema';
|
|
5
|
+
import { venueSchema } from './utils/venue.schema';
|
|
6
|
+
import { organizerSchema } from './utils/organizer.schema';
|
|
7
|
+
import { documentSchema } from './utils/document.schema';
|
|
8
|
+
import { displayTicketSchema } from './utils/ticket.schema';
|
|
9
|
+
import { MAX_TAGLINE_LENGTH, MAX_CATEGORIES, MAX_DESCRIPTION_LENGTH, MAX_DOCUMENTS } from './events.constants';
|
|
10
|
+
import { ageRestrictionSchema } from './utils/age.restriction.schema';
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
// =============================================================================
|
|
14
|
+
// STEP SCHEMAS
|
|
15
|
+
// =============================================================================
|
|
16
|
+
|
|
17
|
+
// Step 1: Basics
|
|
18
|
+
export const stepBasicsSchema = z.object({
|
|
19
|
+
title: z.string({ required_error: 'Event title is required' }).min(10, 'Event title must be at least 10 characters').max(100, 'Title must be less than 100 characters'),
|
|
20
|
+
tagline: z.string().min(5, 'Tagline must be at least 5 characters').max(MAX_TAGLINE_LENGTH, `Tagline cannot exceed ${MAX_TAGLINE_LENGTH} characters`).optional(),
|
|
21
|
+
type: eventTypeSchema,
|
|
22
|
+
categories: z.array(z.string()).max(MAX_CATEGORIES, `Maximum ${MAX_CATEGORIES} categories allowed`).optional(),
|
|
23
|
+
}).passthrough();
|
|
24
|
+
|
|
25
|
+
// Step 2: Details
|
|
26
|
+
export const stepDetailsSchema = z.object({
|
|
27
|
+
media: mediaSchema,
|
|
28
|
+
description: z.string({ required_error: 'Event description is required' }).min(50, 'Description must be at least 50 characters').max(MAX_DESCRIPTION_LENGTH, `Description cannot exceed ${MAX_DESCRIPTION_LENGTH} characters`),
|
|
29
|
+
highlights: z.array(z.string().max(100, 'Each highlight cannot exceed 100 characters'), { required_error: 'Highlights must be an array of strings' }).max(10, 'Cannot have more than 10 highlights').optional(),
|
|
30
|
+
language: z.string({ required_error: 'Language is required' }),
|
|
31
|
+
ageRestriction: ageRestrictionSchema,
|
|
32
|
+
dressCode: z.enum(['casual', 'formal', 'semi-formal', 'other'], {required_error: "Dress code is required"}).optional(),
|
|
33
|
+
}).passthrough();
|
|
34
|
+
|
|
35
|
+
// Step 3: Logistics
|
|
36
|
+
export const stepLogisticsSchema = z.object({
|
|
37
|
+
schedule: scheduleSchema,
|
|
38
|
+
venue: venueSchema
|
|
39
|
+
}).passthrough().refine((data) => {
|
|
40
|
+
if (data.schedule.startDate && data.schedule.endDate) {
|
|
41
|
+
return new Date(data.schedule.endDate) > new Date(data.schedule.startDate);
|
|
42
|
+
}
|
|
43
|
+
return true;
|
|
44
|
+
}, {
|
|
45
|
+
message: "End date and time must be after start date and time",
|
|
46
|
+
path: ["schedule", "endDate"]
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// Step 4: Verification
|
|
50
|
+
export const stepVerifySchema = z.object({
|
|
51
|
+
organizer: organizerSchema,
|
|
52
|
+
verification: z.object({
|
|
53
|
+
documents: z.array(documentSchema).min(1, 'At least one document is required').max(MAX_DOCUMENTS, `Maximum ${MAX_DOCUMENTS} documents allowed`)
|
|
54
|
+
})
|
|
55
|
+
}).passthrough();
|
|
56
|
+
|
|
57
|
+
// Step 5: Tickets
|
|
58
|
+
export const stepTicketsSchema = z.object({
|
|
59
|
+
tickets: z.array(displayTicketSchema).min(1, 'At least one ticket type is required')
|
|
60
|
+
}).passthrough().refine((data) => {
|
|
61
|
+
return data.tickets.length >= 1;
|
|
62
|
+
}, {
|
|
63
|
+
message: "At least one ticket type is required",
|
|
64
|
+
path: ["tickets"]
|
|
65
|
+
}).refine(data=> {
|
|
66
|
+
for (const ticket of data.tickets) {
|
|
67
|
+
if (ticket.salesWindow?.startDate && ticket.salesWindow?.endDate) {
|
|
68
|
+
if (new Date(ticket.salesWindow.endDate) <= new Date(ticket.salesWindow.startDate)) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return true;
|
|
74
|
+
}, {
|
|
75
|
+
message: "End date and time must be after start date and time",
|
|
76
|
+
path: ["tickets", "salesWindow", "endDate"]
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Step 6: Review
|
|
80
|
+
export const stepReviewSchema = z.object({
|
|
81
|
+
termsAccepted: z.boolean().refine(val => val === true, {
|
|
82
|
+
message: 'You must accept all terms and conditions to publish this event'
|
|
83
|
+
}),
|
|
84
|
+
legalPermissionAccepted: z.boolean().refine(val => val === true, {
|
|
85
|
+
message: 'Legal permission confirmation is required'
|
|
86
|
+
}),
|
|
87
|
+
platformTermsAccepted: z.boolean().refine(val => val === true, {
|
|
88
|
+
message: 'Platform terms acceptance is required'
|
|
89
|
+
})
|
|
90
|
+
}).passthrough();
|
|
91
|
+
|
|
92
|
+
export const getEventSchema = z.object({
|
|
93
|
+
eventId: z.string().regex(/^[0-9a-fA-F]{24}$/, 'Event not found').optional(),
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
export const protectedEventSchema = z.object({
|
|
97
|
+
eventId: z.string().regex(/^[0-9a-fA-F]{24}$/, 'Event not found'),
|
|
98
|
+
hostId: z.string().regex(/^[0-9a-fA-F]{24}$/, 'Unauthorized'),
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
export const pendingApprovalEditSchema = z.object({
|
|
102
|
+
eventId: z.string({ required_error: 'Event not found' }).regex(/^[0-9a-fA-F]{24}$/, 'Event not found'),
|
|
103
|
+
hostId: z.string({ required_error: 'Unauthorized' }).regex(/^[0-9a-fA-F]{24}$/, 'Unauthorized'),
|
|
104
|
+
media: mediaSchema,
|
|
105
|
+
description: z.string({ required_error: 'Event description is required' }).min(50, 'Description must be at least 50 characters').max(MAX_DESCRIPTION_LENGTH, `Description cannot exceed ${MAX_DESCRIPTION_LENGTH} characters`),
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
export const approvedEventEditSchema = z.object({
|
|
109
|
+
eventId: z.string({ required_error: 'Event not found' }).regex(/^[0-9a-fA-F]{24}$/, 'Event not found'),
|
|
110
|
+
hostId: z.string({ required_error: 'Unauthorized' }).regex(/^[0-9a-fA-F]{24}$/, 'Unauthorized'),
|
|
111
|
+
media: mediaSchema,
|
|
112
|
+
description: z.string({ required_error: 'Event description is required' }).min(50, 'Description must be at least 50 characters').max(MAX_DESCRIPTION_LENGTH, `Description cannot exceed ${MAX_DESCRIPTION_LENGTH} characters`),
|
|
113
|
+
tickets: z.array(displayTicketSchema).min(1, 'At least one ticket type is required'),
|
|
114
|
+
}).refine(data=> {
|
|
115
|
+
for (const ticket of data.tickets) {
|
|
116
|
+
if (ticket.salesWindow?.startDate && ticket.salesWindow?.endDate) {
|
|
117
|
+
if (new Date(ticket.salesWindow.endDate) <= new Date(ticket.salesWindow.startDate)) {
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return true;
|
|
123
|
+
}, {
|
|
124
|
+
message: "End date and time must be after start date and time",
|
|
125
|
+
path: ["tickets", "salesWindow", "endDate"]
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
// =============================================================================
|
|
129
|
+
// COMPOSITE SCHEMAS
|
|
130
|
+
// =============================================================================
|
|
131
|
+
|
|
132
|
+
export const submitEventSchema = stepBasicsSchema
|
|
133
|
+
.merge(stepDetailsSchema)
|
|
134
|
+
.merge(stepLogisticsSchema._def.schema)
|
|
135
|
+
.merge(stepVerifySchema)
|
|
136
|
+
.merge(stepTicketsSchema._def.schema._def.schema)
|
|
137
|
+
.merge(stepReviewSchema)
|
|
138
|
+
.extend({
|
|
139
|
+
eventId: z.string().regex(/^[0-9a-fA-F]{24}$/, 'Event not found').optional(),
|
|
140
|
+
hostId: z.string().regex(/^[0-9a-fA-F]{24}$/, 'Unauthorized').optional(),
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
export const clientGetEventSchema = stepBasicsSchema
|
|
144
|
+
.merge(stepDetailsSchema)
|
|
145
|
+
.merge(stepLogisticsSchema._def.schema)
|
|
146
|
+
.merge(stepVerifySchema)
|
|
147
|
+
.merge(stepTicketsSchema._def.schema._def.schema)
|
|
148
|
+
.merge(stepReviewSchema)
|
|
149
|
+
.extend({
|
|
150
|
+
_id: z.string().regex(/^[0-9a-fA-F]{24}$/, 'Event not found'),
|
|
151
|
+
status: z.enum(['draft', 'pending_approval', 'approved', 'rejected', 'published', 'live', 'ended', 'cancelled'], { required_error: 'Event status is required' }).default('draft'),
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
export const draftEventSchema = submitEventSchema
|
|
155
|
+
.partial()
|
|
156
|
+
.extend({
|
|
157
|
+
title: stepBasicsSchema.shape.title,
|
|
158
|
+
});
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { mediaSchema } from './utils/media.schema';
|
|
3
|
+
import { scheduleSchema } from './utils/schedule.schema';
|
|
4
|
+
import { venueSchema } from './utils/venue.schema';
|
|
5
|
+
import { organizerSchema } from './utils/organizer.schema';
|
|
6
|
+
import { documentSchema } from './utils/document.schema';
|
|
7
|
+
import { displayTicketSchema } from './utils/ticket.schema';
|
|
8
|
+
import { eventTypeSchema } from './utils/event.type.schema';
|
|
9
|
+
import { ageRestrictionSchema } from './utils/age.restriction.schema';
|
|
10
|
+
import { stepBasicsSchema, getEventSchema, protectedEventSchema, clientGetEventSchema, stepDetailsSchema, stepLogisticsSchema, stepVerifySchema, stepTicketsSchema, stepReviewSchema, submitEventSchema, draftEventSchema, pendingApprovalEditSchema, approvedEventEditSchema } from './events.schema';
|
|
11
|
+
|
|
12
|
+
// =============================================================================
|
|
13
|
+
// TYPE EXPORTS
|
|
14
|
+
// =============================================================================
|
|
15
|
+
|
|
16
|
+
// Document type is now imported from media module
|
|
17
|
+
export type Media = z.infer<typeof mediaSchema>;
|
|
18
|
+
export type CoverImage = z.infer<typeof mediaSchema.shape.coverImage>;
|
|
19
|
+
export type Gallery = z.infer<typeof mediaSchema.shape.gallery>;
|
|
20
|
+
export type Organizer = z.infer<typeof organizerSchema>;
|
|
21
|
+
export type ContactPerson = z.infer<typeof organizerSchema.shape.contactPerson>;
|
|
22
|
+
export type Schedule = z.infer<typeof scheduleSchema>;
|
|
23
|
+
export type DisplayTicket = z.infer<typeof displayTicketSchema>;
|
|
24
|
+
export type Price = z.infer<typeof displayTicketSchema.shape.price>;
|
|
25
|
+
export type SalesWindow = z.infer<typeof displayTicketSchema.shape.salesWindow>;
|
|
26
|
+
export type Limits = z.infer<typeof displayTicketSchema.shape.limits>;
|
|
27
|
+
export type Venue = z.infer<typeof venueSchema>;
|
|
28
|
+
export type VenueType = z.infer<typeof venueSchema.shape.type>;
|
|
29
|
+
export type Address = z.infer<typeof venueSchema.shape.address>;
|
|
30
|
+
export type Document = z.infer<typeof documentSchema>;
|
|
31
|
+
|
|
32
|
+
// Shared enum types
|
|
33
|
+
export type EventType = z.infer<typeof eventTypeSchema>;
|
|
34
|
+
export type AgeRestriction = z.infer<typeof ageRestrictionSchema>;
|
|
35
|
+
|
|
36
|
+
// Step data types
|
|
37
|
+
export type StepBasicsData = z.infer<typeof stepBasicsSchema>;
|
|
38
|
+
export type StepDetailsData = z.infer<typeof stepDetailsSchema>;
|
|
39
|
+
export type StepLogisticsData = z.infer<typeof stepLogisticsSchema>;
|
|
40
|
+
export type StepVerifyData = z.infer<typeof stepVerifySchema>;
|
|
41
|
+
export type StepTicketsData = z.infer<typeof stepTicketsSchema>;
|
|
42
|
+
export type StepReviewData = z.infer<typeof stepReviewSchema>;
|
|
43
|
+
|
|
44
|
+
// Composite types
|
|
45
|
+
export type SubmitEventData = z.infer<typeof submitEventSchema>;
|
|
46
|
+
export type DraftEventData = z.infer<typeof draftEventSchema>;
|
|
47
|
+
export interface Event {
|
|
48
|
+
id: string;
|
|
49
|
+
title: string;
|
|
50
|
+
location: string;
|
|
51
|
+
category: string;
|
|
52
|
+
date: string;
|
|
53
|
+
image?: string;
|
|
54
|
+
}
|
|
55
|
+
export type GetEventData = z.infer<typeof getEventSchema>;
|
|
56
|
+
export type ProtectedEventData = z.infer<typeof protectedEventSchema>;
|
|
57
|
+
export type ClientGetEventData = z.infer<typeof clientGetEventSchema>;
|
|
58
|
+
export type PendingApprovalEditData = z.infer<typeof pendingApprovalEditSchema>;
|
|
59
|
+
export type ApprovedEventEditData = z.infer<typeof approvedEventEditSchema>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export * from './events.schema';
|
|
2
|
-
export * from './events.type';
|
|
3
|
-
export * from './events.utils.schema';
|
|
1
|
+
export * from './events.schema';
|
|
2
|
+
export * from './events.type';
|
|
3
|
+
export * from './events.utils.schema';
|
|
4
|
+
export * from './events.constants';
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
// Metrics schema
|
|
4
|
+
export const metricsSchema = z.object({
|
|
5
|
+
views: z.number({ required_error: 'Views must be a number' }).int('Views must be an integer').min(0, 'Views cannot be negative').default(0),
|
|
6
|
+
ticketsSold: z.number({ required_error: 'Tickets sold must be a number' }).int('Tickets sold must be an integer').min(0, 'Tickets sold cannot be negative').default(0),
|
|
7
|
+
revenue: z.number({ required_error: 'Revenue must be a number' }).min(0, 'Revenue cannot be negative').default(0),
|
|
8
|
+
checkIns: z.number({ required_error: 'Check-ins must be a number' }).int('Check-ins must be an integer').min(0, 'Check-ins cannot be negative').default(0),
|
|
9
|
+
averageRating: z.number().min(0, 'Rating must be at least 0').max(5, 'Rating cannot exceed 5').optional(),
|
|
10
|
+
reviewCount: z.number({ required_error: 'Review count must be a number' }).int('Review count must be an integer').min(0, 'Review count cannot be negative').default(0),
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
// Business schemas
|
|
14
|
+
export const pricingSchema = z.object({
|
|
15
|
+
platformFee: z.number({ required_error: 'Platform fee must be a number' }).min(0, 'Platform fee cannot be negative').default(5),
|
|
16
|
+
paymentProcessingFee: z.number().min(0, 'Payment processing fee cannot be negative').optional(),
|
|
17
|
+
currency: z.string().optional(),
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
export const payoutSchema = z.object({
|
|
21
|
+
status: z.enum(['pending', 'scheduled', 'completed'], { required_error: 'Payout status must be pending, scheduled, or completed' }).optional(),
|
|
22
|
+
amount: z.number().min(0, 'Payout amount cannot be negative').optional(),
|
|
23
|
+
scheduledDate: z.string().datetime('Payout scheduled date must be a valid ISO datetime string').optional(),
|
|
24
|
+
paidAt: z.string().datetime('Payout paid date must be a valid ISO datetime string').optional(),
|
|
25
|
+
stripePayoutId: z.string().optional(),
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// Policies schemas
|
|
29
|
+
export const cancellationSchema = z.object({
|
|
30
|
+
allowed: z.boolean({ required_error: 'Cancellation allowed must be true or false' }).default(true),
|
|
31
|
+
refundPercentage: z.number({ required_error: 'Refund percentage must be a number' }).min(0, 'Refund percentage cannot be less than 0').max(100, 'Refund percentage cannot exceed 100').default(100),
|
|
32
|
+
deadlineHours: z.number().min(0, 'Deadline hours cannot be negative').optional(),
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
export const policiesSchema = z.object({
|
|
36
|
+
cancellation: cancellationSchema.optional(),
|
|
37
|
+
transferable: z.boolean({ required_error: 'Transferable must be true or false' }).default(false),
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
// Moderation schemas
|
|
41
|
+
export const flagSchema = z.object({
|
|
42
|
+
reportedBy: z.string({ required_error: 'Reported by user ID is required' }), // ObjectId as string
|
|
43
|
+
reason: z.string({ required_error: 'Report reason is required' }),
|
|
44
|
+
description: z.string({ required_error: 'Report description is required' }),
|
|
45
|
+
createdAt: z.string().datetime('Report created date must be a valid ISO datetime string').optional(),
|
|
46
|
+
status: z.enum(['pending', 'resolved', 'dismissed'], { required_error: 'Report status must be pending, resolved, or dismissed' }).default('pending'),
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
export const moderationSchema = z.object({
|
|
50
|
+
isFlagged: z.boolean({ required_error: 'Is flagged must be true or false' }).default(false),
|
|
51
|
+
flags: z.array(flagSchema, { required_error: 'Flags must be an array' }).optional(),
|
|
52
|
+
suspendedUntil: z.string().datetime('Suspension date must be a valid ISO datetime string').optional(),
|
|
53
|
+
banReason: z.string().optional(),
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
// SEO schema
|
|
57
|
+
export const seoSchema = z.object({
|
|
58
|
+
metaTitle: z.string().optional(),
|
|
59
|
+
metaDescription: z.string().optional(),
|
|
60
|
+
keywords: z.array(z.string(), { required_error: 'SEO keywords must be an array of strings' }).optional(),
|
|
61
|
+
ogImage: z.string().optional(),
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
// Features schema
|
|
65
|
+
export const featuresSchema = z.object({
|
|
66
|
+
isFeatured: z.boolean({ required_error: 'Is featured must be true or false' }).default(false),
|
|
67
|
+
isPremium: z.boolean({ required_error: 'Is premium must be true or false' }).default(false),
|
|
68
|
+
badges: z.array(z.string(), { required_error: 'Badges must be an array of strings' }).optional(),
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// History schema
|
|
72
|
+
export const historySchema = z.object({
|
|
73
|
+
action: z.string({ required_error: 'History action is required' }),
|
|
74
|
+
performedBy: z.string({ required_error: 'Performed by user ID is required' }), // ObjectId as string
|
|
75
|
+
timestamp: z.string().datetime('History timestamp must be a valid ISO datetime string').optional(),
|
|
76
|
+
changes: z.record(z.any()).optional(),
|
|
77
|
+
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
export const documentSchema = z.object({
|
|
4
|
+
type: z.enum(['venue_booking', 'permit', 'insurance', 'license', 'portfolio', 'other'], { required_error: 'Document type is required' }).optional(),
|
|
5
|
+
url: z.string({ required_error: 'Document URL is required' }).url('Document URL must be valid').optional(),
|
|
6
|
+
filename: z.string({ required_error: 'Document filename is required' }),
|
|
7
|
+
objectKey: z.string({ required_error: 'Document object key is required' }),
|
|
8
|
+
});
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export const coverImageSchema = z.object({
|
|
4
|
+
alt: z.string({
|
|
5
|
+
required_error: 'Alt text is required',
|
|
6
|
+
invalid_type_error: 'Alt text must be a string'
|
|
7
|
+
}),
|
|
8
|
+
thumbnailUrl: z.string({
|
|
9
|
+
required_error: 'Thumbnail URL is required',
|
|
10
|
+
invalid_type_error: 'Thumbnail URL must be a string'
|
|
11
|
+
}),
|
|
12
|
+
url: z.string({
|
|
13
|
+
required_error: 'URL is required',
|
|
14
|
+
invalid_type_error: 'URL must be a string'
|
|
15
|
+
})
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
export const gallerySchema = z.array(z.object({
|
|
19
|
+
alt: z.string({
|
|
20
|
+
required_error: 'Alt text is required',
|
|
21
|
+
invalid_type_error: 'Alt text must be a string'
|
|
22
|
+
}),
|
|
23
|
+
thumbnailUrl: z.string({
|
|
24
|
+
required_error: 'Thumbnail URL is required',
|
|
25
|
+
invalid_type_error: 'Thumbnail URL must be a string'
|
|
26
|
+
}),
|
|
27
|
+
url: z.string({
|
|
28
|
+
required_error: 'URL is required',
|
|
29
|
+
invalid_type_error: 'URL must be a string'
|
|
30
|
+
})
|
|
31
|
+
}));
|
|
32
|
+
|
|
33
|
+
export const mediaSchema = z.object({
|
|
34
|
+
coverImage: coverImageSchema,
|
|
35
|
+
gallery: gallerySchema.optional()
|
|
36
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
export const contactPersonSchema = z.object({
|
|
4
|
+
name: z.string({ required_error: 'Contact person name is required' }),
|
|
5
|
+
phone: z.string({ required_error: 'Contact person phone is required' }).min(11, 'Phone number must be 11 digits 11 digits'),
|
|
6
|
+
email: z.string({ required_error: 'Contact person email is required' }).email('Contact person email must be valid'),
|
|
7
|
+
designation: z.string().optional(),
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
export const organizerSchema = z.object({
|
|
11
|
+
role: z.enum(['event_organizer', 'venue_owner', 'authorized_rep', 'artist'], { required_error: 'Organizer role must be event_organizer, venue_owner, authorized_rep, or artist' }).optional(),
|
|
12
|
+
companyName: z.string().optional(),
|
|
13
|
+
contactPerson: contactPersonSchema,
|
|
14
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
export const scheduleSchema = z.object({
|
|
4
|
+
startDate: z.string({ required_error: 'Event start date is required' }).datetime('Start date must be a valid ISO datetime string'),
|
|
5
|
+
endDate: z.string({ required_error: 'Event end date is required' }).datetime('End date must be a valid ISO datetime string'),
|
|
6
|
+
timezone: z.string().optional(),
|
|
7
|
+
isMultiDay: z.boolean().optional(),
|
|
8
|
+
doors: z.string().optional(),
|
|
9
|
+
});
|
|
10
|
+
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
export const priceSchema = z.object({
|
|
4
|
+
amount: z.number({ required_error: 'Ticket price amount is required' }).min(0, 'Ticket price cannot be negative'),
|
|
5
|
+
currency: z.string({ required_error: 'Ticket currency is required' }).default('BDT'),
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
export const salesWindowSchema = z.object({
|
|
9
|
+
startDate: z.string().datetime('Sales start date must be a valid ISO datetime string').optional(),
|
|
10
|
+
endDate: z.string().datetime('Sales end date must be a valid ISO datetime string').optional(),
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
export const limitsSchema = z.object({
|
|
14
|
+
minPerOrder: z.number({ required_error: 'Min per order must be a number' }).int('Min per order must be an integer').min(1, 'Min per order must be at least 1').default(1),
|
|
15
|
+
maxPerOrder: z.number({ required_error: 'Max per order must be a number' }).int('Max per order must be an integer').min(1, 'Max per order must be at least 1').default(10),
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
export const displayTicketSchema = z.object({
|
|
19
|
+
id: z.string().optional(),
|
|
20
|
+
name: z.string({ required_error: 'Ticket name is required' }),
|
|
21
|
+
description: z.string().optional(),
|
|
22
|
+
price: priceSchema,
|
|
23
|
+
quantity: z.number({ required_error: 'Ticket quantity is required' }).int('Quantity must be an integer').positive('Quantity must be positive'),
|
|
24
|
+
salesWindow: salesWindowSchema.optional(),
|
|
25
|
+
limits: limitsSchema.optional(),
|
|
26
|
+
remaining: z.number().optional(),
|
|
27
|
+
sold: z.number().optional(),
|
|
28
|
+
reserved: z.number().optional(),
|
|
29
|
+
visibility: z.enum(['public', 'hidden', 'invite_only'], { required_error: 'Ticket visibility must be public, hidden, or invite_only' }).default('public').optional(),
|
|
30
|
+
status: z.enum(['active', 'inactive'], { required_error: 'Ticket status must be active or inactive' }).default('active').optional(),
|
|
31
|
+
benefits: z.array(z.string(), { required_error: 'Benefits must be an array of strings' }).optional(),
|
|
32
|
+
tier: z.enum(['early_bird', 'regular', 'vip'], { required_error: 'Ticket tier must be early_bird, regular or vip' }).default('regular')
|
|
33
|
+
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
|
|
3
|
+
export const venueTypeSchema = z.enum(['indoor', 'outdoor', 'hybrid'], { required_error: 'Venue type must be indoor, outdoor, or hybrid' }).optional();
|
|
4
|
+
|
|
5
|
+
export const addressSchema = z.object({
|
|
6
|
+
street: z.string({ required_error: 'Street is required' }).min(1, 'Street is required'),
|
|
7
|
+
city: z.string({ required_error: 'City is required' }).min(1, 'City is required'),
|
|
8
|
+
country: z.string({ required_error: 'Country is required' }).min(1, 'Country is required'),
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
export const venueSchema = z.object({
|
|
12
|
+
name: z.string({ required_error: 'Venue name is required' }).min(1, 'Venue name is required'),
|
|
13
|
+
address: addressSchema,
|
|
14
|
+
coordinates: z.object({
|
|
15
|
+
type: z.literal('Point', { required_error: 'Coordinates type must be Point' }),
|
|
16
|
+
coordinates: z.tuple([z.number({ required_error: 'Longitude is required' }), z.number({ required_error: 'Latitude is required' })], { required_error: 'Coordinates array [lng, lat] is required' }), // [lng, lat]
|
|
17
|
+
}).optional(),
|
|
18
|
+
capacity: z.number({ required_error: 'Venue capacity is required' }).int('Capacity must be an integer').positive('Capacity must be positive').min(10, 'Capacity must be at least 10'),
|
|
19
|
+
type: venueTypeSchema,
|
|
20
|
+
parking: z.boolean().optional(),
|
|
21
|
+
publicTransit: z.string().optional(),
|
|
22
|
+
});
|
package/src/index.ts
ADDED