feat : Création de toutes les entités
This commit is contained in:
17
src/models/_shared.ts
Normal file
17
src/models/_shared.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
export const uuidSchema = z.string().uuid();
|
||||
|
||||
export const timestampSchema = z.coerce.date();
|
||||
|
||||
export const sqlDateSchema = z
|
||||
.string()
|
||||
.regex(/^\d{4}-\d{2}-\d{2}$/, 'Expected date format YYYY-MM-DD');
|
||||
|
||||
export const nullableText = z.string().trim().min(1).nullable();
|
||||
|
||||
export const nullableUrl = z.string().url().nullable();
|
||||
|
||||
export const nullableLatitude = z.number().min(-90).max(90).nullable();
|
||||
|
||||
export const nullableLongitude = z.number().min(-180).max(180).nullable();
|
||||
16
src/models/animators.ts
Normal file
16
src/models/animators.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { nullableUrl, timestampSchema, uuidSchema } from './_shared';
|
||||
|
||||
export const animatorSchema = z.object({
|
||||
id: uuidSchema,
|
||||
name: z.string().trim().min(1).max(255),
|
||||
profile_picture: nullableUrl,
|
||||
genre: z.string().trim().min(1).max(100).nullable(),
|
||||
city: z.string().trim().min(1).max(100).nullable(),
|
||||
bio: z.string().trim().min(1).nullable(),
|
||||
created_at: timestampSchema,
|
||||
updated_at: timestampSchema,
|
||||
});
|
||||
|
||||
export type Animator = z.infer<typeof animatorSchema>;
|
||||
11
src/models/comment_likes.ts
Normal file
11
src/models/comment_likes.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { timestampSchema, uuidSchema } from './_shared';
|
||||
|
||||
export const commentLikeSchema = z.object({
|
||||
user_id: uuidSchema,
|
||||
comment_id: uuidSchema,
|
||||
created_at: timestampSchema,
|
||||
});
|
||||
|
||||
export type CommentLike = z.infer<typeof commentLikeSchema>;
|
||||
15
src/models/comments.ts
Normal file
15
src/models/comments.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { timestampSchema, uuidSchema } from './_shared';
|
||||
|
||||
export const commentSchema = z.object({
|
||||
id: uuidSchema,
|
||||
post_id: uuidSchema,
|
||||
user_id: uuidSchema,
|
||||
parent_comment_id: uuidSchema.nullable(),
|
||||
content: z.string().trim().min(1),
|
||||
created_at: timestampSchema,
|
||||
updated_at: timestampSchema,
|
||||
});
|
||||
|
||||
export type Comment = z.infer<typeof commentSchema>;
|
||||
13
src/models/event_external_links.ts
Normal file
13
src/models/event_external_links.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { uuidSchema } from './_shared';
|
||||
|
||||
export const eventExternalLinkSchema = z.object({
|
||||
id: uuidSchema,
|
||||
event_id: uuidSchema,
|
||||
url: z.string().trim().min(1),
|
||||
label: z.string().trim().min(1).max(100).nullable(),
|
||||
display_order: z.number().int().default(0),
|
||||
});
|
||||
|
||||
export type EventExternalLink = z.infer<typeof eventExternalLinkSchema>;
|
||||
10
src/models/event_hashtags.ts
Normal file
10
src/models/event_hashtags.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { uuidSchema } from './_shared';
|
||||
|
||||
export const eventHashtagSchema = z.object({
|
||||
event_id: uuidSchema,
|
||||
hashtag_id: uuidSchema,
|
||||
});
|
||||
|
||||
export type EventHashtag = z.infer<typeof eventHashtagSchema>;
|
||||
14
src/models/event_images.ts
Normal file
14
src/models/event_images.ts
Normal file
@@ -0,0 +1,14 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { timestampSchema, uuidSchema } from './_shared';
|
||||
|
||||
export const eventImageSchema = z.object({
|
||||
id: uuidSchema,
|
||||
event_id: uuidSchema,
|
||||
url: z.string().url(),
|
||||
is_cover: z.boolean().default(false),
|
||||
display_order: z.number().int().default(0),
|
||||
created_at: timestampSchema,
|
||||
});
|
||||
|
||||
export type EventImage = z.infer<typeof eventImageSchema>;
|
||||
18
src/models/event_lineup.ts
Normal file
18
src/models/event_lineup.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { timestampSchema, uuidSchema } from './_shared';
|
||||
|
||||
export const eventLineupRoleSchema = z.enum(['HEADLINER', 'OPENING', 'CLOSING']);
|
||||
|
||||
export const eventLineupSchema = z.object({
|
||||
id: uuidSchema,
|
||||
event_id: uuidSchema,
|
||||
animator_id: uuidSchema,
|
||||
stage_name: z.string().trim().min(1).max(100).nullable(),
|
||||
start_time: timestampSchema.nullable(),
|
||||
end_time: timestampSchema.nullable(),
|
||||
role: eventLineupRoleSchema.nullable(),
|
||||
display_order: z.number().int().default(0),
|
||||
});
|
||||
|
||||
export type EventLineup = z.infer<typeof eventLineupSchema>;
|
||||
15
src/models/event_stats_snapshots.ts
Normal file
15
src/models/event_stats_snapshots.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { sqlDateSchema, uuidSchema } from './_shared';
|
||||
|
||||
export const eventStatsSnapshotSchema = z.object({
|
||||
id: uuidSchema,
|
||||
event_id: uuidSchema,
|
||||
snapshot_date: sqlDateSchema,
|
||||
view_count: z.number().int().min(0).default(0),
|
||||
participant_count: z.number().int().min(0).default(0),
|
||||
interested_count: z.number().int().min(0).default(0),
|
||||
share_count: z.number().int().min(0).default(0),
|
||||
});
|
||||
|
||||
export type EventStatsSnapshot = z.infer<typeof eventStatsSnapshotSchema>;
|
||||
10
src/models/event_themes.ts
Normal file
10
src/models/event_themes.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { uuidSchema } from './_shared';
|
||||
|
||||
export const eventThemeSchema = z.object({
|
||||
event_id: uuidSchema,
|
||||
theme_id: uuidSchema,
|
||||
});
|
||||
|
||||
export type EventTheme = z.infer<typeof eventThemeSchema>;
|
||||
40
src/models/events.ts
Normal file
40
src/models/events.ts
Normal file
@@ -0,0 +1,40 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import {
|
||||
nullableLatitude,
|
||||
nullableLongitude,
|
||||
nullableText,
|
||||
timestampSchema,
|
||||
uuidSchema,
|
||||
} from './_shared';
|
||||
|
||||
export const eventStatusSchema = z.enum(['DRAFT', 'PUBLISHED', 'CANCELLED']);
|
||||
|
||||
export const eventSchema = z.object({
|
||||
id: uuidSchema,
|
||||
organizer_id: uuidSchema,
|
||||
name: z.string().trim().min(1).max(255),
|
||||
description: z.string().trim().max(600).nullable(),
|
||||
start_date: timestampSchema,
|
||||
end_date: timestampSchema,
|
||||
doors_open_time: timestampSchema.nullable(),
|
||||
min_age: z.number().int().min(0).nullable(),
|
||||
address: nullableText,
|
||||
city: z.string().trim().min(1).max(100).nullable(),
|
||||
latitude: nullableLatitude,
|
||||
longitude: nullableLongitude,
|
||||
price_presale: z.number().min(0).nullable(),
|
||||
price_door: z.number().min(0).nullable(),
|
||||
is_free: z.boolean().default(false),
|
||||
presale_total: z.number().int().min(0).nullable(),
|
||||
presale_sold: z.number().int().min(0).default(0),
|
||||
ticketing_enabled: z.boolean().default(false),
|
||||
ticketing_commission: z.number().min(0).max(100).nullable(),
|
||||
status: eventStatusSchema,
|
||||
featured_image_id: uuidSchema.nullable(),
|
||||
published_at: timestampSchema.nullable(),
|
||||
created_at: timestampSchema,
|
||||
updated_at: timestampSchema,
|
||||
});
|
||||
|
||||
export type Event = z.infer<typeof eventSchema>;
|
||||
10
src/models/hashtags.ts
Normal file
10
src/models/hashtags.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { uuidSchema } from './_shared';
|
||||
|
||||
export const hashtagSchema = z.object({
|
||||
id: uuidSchema,
|
||||
name: z.string().trim().min(1).max(100),
|
||||
});
|
||||
|
||||
export type Hashtag = z.infer<typeof hashtagSchema>;
|
||||
30
src/models/index.ts
Normal file
30
src/models/index.ts
Normal file
@@ -0,0 +1,30 @@
|
||||
export * from './_shared';
|
||||
export * from './animators';
|
||||
export * from './comment_likes';
|
||||
export * from './comments';
|
||||
export * from './event_external_links';
|
||||
export * from './event_hashtags';
|
||||
export * from './event_images';
|
||||
export * from './event_lineup';
|
||||
export * from './event_stats_snapshots';
|
||||
export * from './event_themes';
|
||||
export * from './events';
|
||||
export * from './hashtags';
|
||||
export * from './organizer_members';
|
||||
export * from './organizer_subscriptions';
|
||||
export * from './organizers';
|
||||
export * from './plans';
|
||||
export * from './post_likes';
|
||||
export * from './post_media';
|
||||
export * from './posts';
|
||||
export * from './search_history';
|
||||
export * from './social_auth_providers';
|
||||
export * from './themes';
|
||||
export * from './tickets';
|
||||
export * from './user_animator_follows';
|
||||
export * from './user_event_interactions';
|
||||
export * from './user_event_shares';
|
||||
export * from './user_organizer_follows';
|
||||
export * from './user_theme_preferences';
|
||||
export * from './users';
|
||||
|
||||
20
src/models/organizer_members.ts
Normal file
20
src/models/organizer_members.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { timestampSchema, uuidSchema } from './_shared';
|
||||
|
||||
export const organizerMemberRoleSchema = z.enum(['ADMIN', 'EDITOR']);
|
||||
|
||||
export const organizerMemberStatusSchema = z.enum(['ACTIVE', 'PENDING']);
|
||||
|
||||
export const organizerMemberSchema = z.object({
|
||||
id: uuidSchema,
|
||||
organizer_id: uuidSchema,
|
||||
user_id: uuidSchema.nullable(),
|
||||
email: z.string().trim().email().max(255),
|
||||
role: organizerMemberRoleSchema,
|
||||
status: organizerMemberStatusSchema,
|
||||
invited_at: timestampSchema,
|
||||
joined_at: timestampSchema.nullable(),
|
||||
});
|
||||
|
||||
export type OrganizerMember = z.infer<typeof organizerMemberSchema>;
|
||||
21
src/models/organizer_subscriptions.ts
Normal file
21
src/models/organizer_subscriptions.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { sqlDateSchema, timestampSchema, uuidSchema } from './_shared';
|
||||
|
||||
export const organizerSubscriptionStatusSchema = z.enum([
|
||||
'ACTIVE',
|
||||
'CANCELLED',
|
||||
'EXPIRED',
|
||||
]);
|
||||
|
||||
export const organizerSubscriptionSchema = z.object({
|
||||
id: uuidSchema,
|
||||
organizer_id: uuidSchema,
|
||||
plan_id: uuidSchema,
|
||||
status: organizerSubscriptionStatusSchema,
|
||||
started_at: timestampSchema,
|
||||
renewal_date: sqlDateSchema.nullable(),
|
||||
cancelled_at: timestampSchema.nullable(),
|
||||
});
|
||||
|
||||
export type OrganizerSubscription = z.infer<typeof organizerSubscriptionSchema>;
|
||||
23
src/models/organizers.ts
Normal file
23
src/models/organizers.ts
Normal file
@@ -0,0 +1,23 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { nullableUrl, timestampSchema, uuidSchema } from './_shared';
|
||||
|
||||
export const organizerSchema = z.object({
|
||||
id: uuidSchema,
|
||||
name: z.string().trim().min(1).max(255),
|
||||
email: z.string().trim().email().max(255),
|
||||
profile_picture: nullableUrl,
|
||||
cover_picture: nullableUrl,
|
||||
city: z.string().trim().min(1).max(100).nullable(),
|
||||
is_verified: z.boolean().default(false),
|
||||
verified_at: timestampSchema.nullable(),
|
||||
verified_by: uuidSchema.nullable(),
|
||||
instagram_handle: z.string().trim().min(1).max(100).nullable(),
|
||||
tiktok_handle: z.string().trim().min(1).max(100).nullable(),
|
||||
facebook_handle: z.string().trim().min(1).max(100).nullable(),
|
||||
plan_id: uuidSchema.nullable(),
|
||||
created_at: timestampSchema,
|
||||
updated_at: timestampSchema,
|
||||
});
|
||||
|
||||
export type Organizer = z.infer<typeof organizerSchema>;
|
||||
16
src/models/plans.ts
Normal file
16
src/models/plans.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { uuidSchema } from './_shared';
|
||||
|
||||
export const planNameSchema = z.enum(['FREE', 'PRO', 'TICKETING']);
|
||||
|
||||
export const planSchema = z.object({
|
||||
id: uuidSchema,
|
||||
name: planNameSchema,
|
||||
price_monthly: z.number().min(0),
|
||||
max_active_events: z.number().int().min(0).nullable(),
|
||||
ticketing_enabled: z.boolean().default(false),
|
||||
ticketing_commission: z.number().min(0).max(100).nullable(),
|
||||
});
|
||||
|
||||
export type Plan = z.infer<typeof planSchema>;
|
||||
11
src/models/post_likes.ts
Normal file
11
src/models/post_likes.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { timestampSchema, uuidSchema } from './_shared';
|
||||
|
||||
export const postLikeSchema = z.object({
|
||||
user_id: uuidSchema,
|
||||
post_id: uuidSchema,
|
||||
created_at: timestampSchema,
|
||||
});
|
||||
|
||||
export type PostLike = z.infer<typeof postLikeSchema>;
|
||||
16
src/models/post_media.ts
Normal file
16
src/models/post_media.ts
Normal file
@@ -0,0 +1,16 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { uuidSchema } from './_shared';
|
||||
|
||||
export const postMediaTypeSchema = z.enum(['IMAGE', 'VIDEO']);
|
||||
|
||||
export const postMediaSchema = z.object({
|
||||
id: uuidSchema,
|
||||
post_id: uuidSchema,
|
||||
url: z.string().url(),
|
||||
type: postMediaTypeSchema,
|
||||
duration_seconds: z.number().int().min(0).nullable(),
|
||||
display_order: z.number().int().default(0),
|
||||
});
|
||||
|
||||
export type PostMedia = z.infer<typeof postMediaSchema>;
|
||||
31
src/models/posts.ts
Normal file
31
src/models/posts.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { timestampSchema, uuidSchema } from './_shared';
|
||||
|
||||
export const postTypeSchema = z.enum([
|
||||
'TEXT',
|
||||
'PHOTO',
|
||||
'VIDEO',
|
||||
'ANNOUNCEMENT',
|
||||
'TEASER',
|
||||
]);
|
||||
|
||||
export const postStatusSchema = z.enum(['DRAFT', 'SCHEDULED', 'PUBLISHED']);
|
||||
|
||||
export const postSchema = z.object({
|
||||
id: uuidSchema,
|
||||
organizer_id: uuidSchema,
|
||||
event_id: uuidSchema.nullable(),
|
||||
content: z.string().trim().max(500).nullable(),
|
||||
type: postTypeSchema,
|
||||
status: postStatusSchema,
|
||||
scheduled_at: timestampSchema.nullable(),
|
||||
published_at: timestampSchema.nullable(),
|
||||
rediffusion_instagram: z.boolean().default(false),
|
||||
rediffusion_tiktok: z.boolean().default(false),
|
||||
rediffusion_facebook: z.boolean().default(false),
|
||||
created_at: timestampSchema,
|
||||
updated_at: timestampSchema,
|
||||
});
|
||||
|
||||
export type Post = z.infer<typeof postSchema>;
|
||||
12
src/models/search_history.ts
Normal file
12
src/models/search_history.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { timestampSchema, uuidSchema } from './_shared';
|
||||
|
||||
export const searchHistorySchema = z.object({
|
||||
id: uuidSchema,
|
||||
user_id: uuidSchema,
|
||||
query: z.string().trim().min(1).max(255),
|
||||
searched_at: timestampSchema,
|
||||
});
|
||||
|
||||
export type SearchHistory = z.infer<typeof searchHistorySchema>;
|
||||
13
src/models/social_auth_providers.ts
Normal file
13
src/models/social_auth_providers.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { timestampSchema, uuidSchema } from './_shared';
|
||||
|
||||
export const socialAuthProviderSchema = z.object({
|
||||
id: uuidSchema,
|
||||
user_id: uuidSchema,
|
||||
provider: z.enum(['google', 'apple']),
|
||||
provider_user_id: z.string().trim().min(1).max(255),
|
||||
created_at: timestampSchema,
|
||||
});
|
||||
|
||||
export type SocialAuthProvider = z.infer<typeof socialAuthProviderSchema>;
|
||||
15
src/models/themes.ts
Normal file
15
src/models/themes.ts
Normal file
@@ -0,0 +1,15 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { uuidSchema } from './_shared';
|
||||
|
||||
export const themesSchema = z.object({
|
||||
id: uuidSchema,
|
||||
name: z.string().trim().min(1).max(100),
|
||||
color_hex: z
|
||||
.string()
|
||||
.regex(/^#[0-9A-Fa-f]{6}$/, 'Expected color format #RRGGBB')
|
||||
.nullable(),
|
||||
display_order: z.number().int().default(0),
|
||||
});
|
||||
|
||||
export type Theme = z.infer<typeof themesSchema>;
|
||||
22
src/models/tickets.ts
Normal file
22
src/models/tickets.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { timestampSchema, uuidSchema } from './_shared';
|
||||
|
||||
export const ticketTypeSchema = z.enum(['PRESALE', 'DOOR']);
|
||||
|
||||
export const ticketStatusSchema = z.enum(['VALID', 'USED', 'CANCELLED']);
|
||||
|
||||
export const ticketSchema = z.object({
|
||||
id: uuidSchema,
|
||||
event_id: uuidSchema,
|
||||
user_id: uuidSchema,
|
||||
type: ticketTypeSchema,
|
||||
price_paid: z.number().min(0),
|
||||
bahla_commission: z.number().min(0),
|
||||
status: ticketStatusSchema,
|
||||
purchased_at: timestampSchema,
|
||||
used_at: timestampSchema.nullable(),
|
||||
qr_code: z.string().trim().min(1).nullable(),
|
||||
});
|
||||
|
||||
export type Ticket = z.infer<typeof ticketSchema>;
|
||||
11
src/models/user_animator_follows.ts
Normal file
11
src/models/user_animator_follows.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { timestampSchema, uuidSchema } from './_shared';
|
||||
|
||||
export const userAnimatorFollowSchema = z.object({
|
||||
user_id: uuidSchema,
|
||||
animator_id: uuidSchema,
|
||||
created_at: timestampSchema,
|
||||
});
|
||||
|
||||
export type UserAnimatorFollow = z.infer<typeof userAnimatorFollowSchema>;
|
||||
19
src/models/user_event_interactions.ts
Normal file
19
src/models/user_event_interactions.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { timestampSchema, uuidSchema } from './_shared';
|
||||
|
||||
export const userEventInteractionStatusSchema = z.enum([
|
||||
'PARTICIPATING',
|
||||
'INTERESTED',
|
||||
'SAVED',
|
||||
]);
|
||||
|
||||
export const userEventInteractionSchema = z.object({
|
||||
user_id: uuidSchema,
|
||||
event_id: uuidSchema,
|
||||
status: userEventInteractionStatusSchema,
|
||||
created_at: timestampSchema,
|
||||
updated_at: timestampSchema,
|
||||
});
|
||||
|
||||
export type UserEventInteraction = z.infer<typeof userEventInteractionSchema>;
|
||||
12
src/models/user_event_shares.ts
Normal file
12
src/models/user_event_shares.ts
Normal file
@@ -0,0 +1,12 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { timestampSchema, uuidSchema } from './_shared';
|
||||
|
||||
export const userEventShareSchema = z.object({
|
||||
id: uuidSchema,
|
||||
user_id: uuidSchema.nullable(),
|
||||
event_id: uuidSchema,
|
||||
shared_at: timestampSchema,
|
||||
});
|
||||
|
||||
export type UserEventShare = z.infer<typeof userEventShareSchema>;
|
||||
11
src/models/user_organizer_follows.ts
Normal file
11
src/models/user_organizer_follows.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { timestampSchema, uuidSchema } from './_shared';
|
||||
|
||||
export const userOrganizerFollowSchema = z.object({
|
||||
user_id: uuidSchema,
|
||||
organizer_id: uuidSchema,
|
||||
created_at: timestampSchema,
|
||||
});
|
||||
|
||||
export type UserOrganizerFollow = z.infer<typeof userOrganizerFollowSchema>;
|
||||
10
src/models/user_theme_preferences.ts
Normal file
10
src/models/user_theme_preferences.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import { uuidSchema } from './_shared';
|
||||
|
||||
export const userThemePreferenceSchema = z.object({
|
||||
user_id: uuidSchema,
|
||||
theme_id: uuidSchema,
|
||||
});
|
||||
|
||||
export type UserThemePreference = z.infer<typeof userThemePreferenceSchema>;
|
||||
31
src/models/users.ts
Normal file
31
src/models/users.ts
Normal file
@@ -0,0 +1,31 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
import {
|
||||
nullableLatitude,
|
||||
nullableLongitude,
|
||||
nullableText,
|
||||
nullableUrl,
|
||||
timestampSchema,
|
||||
uuidSchema,
|
||||
} from './_shared';
|
||||
|
||||
export const userSchema = z.object({
|
||||
id: uuidSchema,
|
||||
first_name: z.string().trim().min(1).max(100),
|
||||
last_name: z.string().trim().min(1).max(100),
|
||||
email: z.string().trim().email().max(255),
|
||||
password_hash: z.string().trim().min(1).max(255).nullable(),
|
||||
profile_picture: nullableUrl,
|
||||
address: nullableText,
|
||||
city: z.string().trim().min(1).max(100).nullable(),
|
||||
latitude: nullableLatitude,
|
||||
longitude: nullableLongitude,
|
||||
default_radius_km: z.number().int().min(0).default(25),
|
||||
language: z.string().trim().min(2).max(10).default('fr'),
|
||||
notifications_enabled: z.boolean().default(true),
|
||||
calendar_sync_enabled: z.boolean().default(false),
|
||||
created_at: timestampSchema,
|
||||
updated_at: timestampSchema,
|
||||
});
|
||||
|
||||
export type User = z.infer<typeof userSchema>;
|
||||
Reference in New Issue
Block a user