1086 lines
35 KiB
TypeScript
1086 lines
35 KiB
TypeScript
import type {
|
||
Animator,
|
||
Comment,
|
||
CommentLike,
|
||
Event,
|
||
EventExternalLink,
|
||
EventHashtag,
|
||
EventImage,
|
||
EventLineup,
|
||
EventStatsSnapshot,
|
||
EventTheme,
|
||
Hashtag,
|
||
Organizer,
|
||
OrganizerMember,
|
||
OrganizerSubscription,
|
||
Plan,
|
||
Post,
|
||
PostLike,
|
||
PostMedia,
|
||
SearchHistory,
|
||
SocialAuthProvider,
|
||
Theme,
|
||
Ticket,
|
||
User,
|
||
UserAnimatorFollow,
|
||
UserEventInteraction,
|
||
UserEventShare,
|
||
UserOrganizerFollow,
|
||
UserThemePreference,
|
||
} from '@/models';
|
||
|
||
const makeUuid = (seed: string): string => {
|
||
const base = seed.toLowerCase().replace(/[^a-z0-9]/g, '');
|
||
const normalized = base.padEnd(12, 'x').slice(0, 12);
|
||
const parts = [
|
||
normalized.slice(0, 8),
|
||
normalized.slice(8, 12),
|
||
'4' + normalized.slice(12, 15).padEnd(3, '0'),
|
||
'8' + normalized.slice(15, 18).padEnd(3, '0'),
|
||
normalized.slice(18, 30).padEnd(12, '9'),
|
||
];
|
||
|
||
return `${parts[0]}-${parts[1]}-${parts[2]}-${parts[3]}-${parts[4]}`;
|
||
};
|
||
|
||
const baseDate = new Date();
|
||
|
||
const relativeDate = (options: { days?: number; hours?: number; minutes?: number } = {}): Date => {
|
||
const date = new Date(baseDate);
|
||
const { days = 0, hours = 0, minutes = 0 } = options;
|
||
|
||
date.setDate(date.getDate() + days);
|
||
date.setHours(date.getHours() + hours);
|
||
date.setMinutes(date.getMinutes() + minutes);
|
||
|
||
return date;
|
||
};
|
||
|
||
const toSqlDate = (date: Date): string => date.toISOString().slice(0, 10);
|
||
|
||
const makeEventDates = (daysFromNow: number, hours: number, durationHours: number) => {
|
||
const start = relativeDate({ days: daysFromNow, hours });
|
||
const end = new Date(start.getTime() + durationHours * 60 * 60 * 1000);
|
||
return { start, end };
|
||
};
|
||
|
||
const sortByDisplayOrder = <T extends { display_order?: number }>(items: T[]): T[] =>
|
||
[...items].sort((a, b) => (a.display_order ?? 0) - (b.display_order ?? 0));
|
||
|
||
const themeIds = {
|
||
nightlife: makeUuid('theme-nightlife'),
|
||
techno: makeUuid('theme-techno'),
|
||
festival: makeUuid('theme-festival'),
|
||
youth: makeUuid('theme-youth'),
|
||
concert: makeUuid('theme-concert'),
|
||
free: makeUuid('theme-free'),
|
||
withFriends: makeUuid('theme-with-friends'),
|
||
afterwork: makeUuid('theme-afterwork'),
|
||
};
|
||
|
||
const organizerIds = {
|
||
neon: makeUuid('organizer-neon-session'),
|
||
vertige: makeUuid('organizer-club-vertige'),
|
||
nyx: makeUuid('organizer-nyx-vandal'),
|
||
selene: makeUuid('organizer-selene'),
|
||
cernier: makeUuid('organizer-cernier'),
|
||
};
|
||
|
||
const eventIds = {
|
||
neon: makeUuid('event-neon-session-12'),
|
||
vertige: makeUuid('event-club-vertige'),
|
||
nyx: makeUuid('event-nyx-vandal'),
|
||
selene: makeUuid('event-selene'),
|
||
cernier: makeUuid('event-cernier-youth'),
|
||
};
|
||
|
||
const userIds = {
|
||
lucie: makeUuid('user-lucie'),
|
||
noah: makeUuid('user-noah'),
|
||
amelia: makeUuid('user-amelia'),
|
||
sam: makeUuid('user-sam'),
|
||
};
|
||
|
||
const animatorIds = {
|
||
glow: makeUuid('animator-glow-reign'),
|
||
ocho: makeUuid('animator-ocho-k'),
|
||
vanta: makeUuid('animator-vanta-echo'),
|
||
isae: makeUuid('animator-isae-noir'),
|
||
};
|
||
|
||
const hashtagIds = {
|
||
neon: makeUuid('hashtag-neon'),
|
||
techno: makeUuid('hashtag-techno'),
|
||
club: makeUuid('hashtag-club'),
|
||
cernier: makeUuid('hashtag-cernier'),
|
||
electro: makeUuid('hashtag-electro'),
|
||
afterwork: makeUuid('hashtag-afterwork'),
|
||
};
|
||
|
||
const planIds = {
|
||
free: makeUuid('plan-free'),
|
||
pro: makeUuid('plan-pro'),
|
||
ticketing: makeUuid('plan-ticketing'),
|
||
};
|
||
|
||
export const mockPlans: Plan[] = [
|
||
{
|
||
id: planIds.free,
|
||
name: 'FREE',
|
||
price_monthly: 0,
|
||
max_active_events: 3,
|
||
ticketing_enabled: false,
|
||
ticketing_commission: null,
|
||
},
|
||
{
|
||
id: planIds.pro,
|
||
name: 'PRO',
|
||
price_monthly: 19,
|
||
max_active_events: 12,
|
||
ticketing_enabled: true,
|
||
ticketing_commission: 12,
|
||
},
|
||
{
|
||
id: planIds.ticketing,
|
||
name: 'TICKETING',
|
||
price_monthly: 49,
|
||
max_active_events: 30,
|
||
ticketing_enabled: true,
|
||
ticketing_commission: 10,
|
||
},
|
||
];
|
||
|
||
export const mockThemes: Theme[] = [
|
||
{ id: themeIds.nightlife, name: 'Soirée', color_hex: '#D21CFF', display_order: 1 },
|
||
{ id: themeIds.techno, name: 'Techno', color_hex: '#00E5FF', display_order: 2 },
|
||
{ id: themeIds.festival, name: 'Festival', color_hex: '#91F763', display_order: 3 },
|
||
{ id: themeIds.youth, name: 'Fête de jeunesse', color_hex: '#FFB703', display_order: 4 },
|
||
{ id: themeIds.concert, name: 'Concert', color_hex: '#FF6B6B', display_order: 5 },
|
||
{ id: themeIds.free, name: 'Gratuit', color_hex: '#61F0C1', display_order: 6 },
|
||
{ id: themeIds.withFriends, name: 'Entre amis', color_hex: '#7A8BFF', display_order: 7 },
|
||
{ id: themeIds.afterwork, name: 'Afterwork', color_hex: '#F4A261', display_order: 8 },
|
||
];
|
||
|
||
export const mockHashtags: Hashtag[] = [
|
||
{ id: hashtagIds.neon, name: '#NeonSession' },
|
||
{ id: hashtagIds.techno, name: '#Techno' },
|
||
{ id: hashtagIds.club, name: '#ClubNight' },
|
||
{ id: hashtagIds.cernier, name: '#Cernier' },
|
||
{ id: hashtagIds.electro, name: '#Electro' },
|
||
{ id: hashtagIds.afterwork, name: '#Afterwork' },
|
||
];
|
||
|
||
export const mockOrganizers: Organizer[] = [
|
||
{
|
||
id: organizerIds.neon,
|
||
name: 'Neon Session',
|
||
email: 'hello@neonsession.ch',
|
||
profile_picture: 'https://images.unsplash.com/photo-1516280440614-37939bbacd81?auto=format&fit=crop&w=500&q=80',
|
||
cover_picture: 'https://images.unsplash.com/photo-1492684223066-81342ee5ff30?auto=format&fit=crop&w=1200&q=80',
|
||
city: 'La Chaux-de-Fonds',
|
||
is_verified: true,
|
||
verified_at: relativeDate({ days: -14 }),
|
||
verified_by: null,
|
||
instagram_handle: '@neonsession',
|
||
tiktok_handle: '@neonsession',
|
||
facebook_handle: null,
|
||
plan_id: planIds.pro,
|
||
created_at: relativeDate({ days: -120 }),
|
||
updated_at: relativeDate({ hours: -2 }),
|
||
},
|
||
{
|
||
id: organizerIds.vertige,
|
||
name: 'Club Vertige',
|
||
email: 'club@vertige.local',
|
||
profile_picture: 'https://images.unsplash.com/photo-1524504388940-b1c1722653e1?auto=format&fit=crop&w=500&q=80',
|
||
cover_picture: 'https://images.unsplash.com/photo-1501386761578-eac5c94b800a?auto=format&fit=crop&w=1200&q=80',
|
||
city: 'Neuchâtel',
|
||
is_verified: true,
|
||
verified_at: relativeDate({ days: -21 }),
|
||
verified_by: null,
|
||
instagram_handle: '@clubvertige',
|
||
tiktok_handle: null,
|
||
facebook_handle: '@clubvertige',
|
||
plan_id: planIds.ticketing,
|
||
created_at: relativeDate({ days: -180 }),
|
||
updated_at: relativeDate({ hours: -1 }),
|
||
},
|
||
{
|
||
id: organizerIds.nyx,
|
||
name: 'Nyx Vandal',
|
||
email: 'bookings@nyxvandal.ch',
|
||
profile_picture: 'https://images.unsplash.com/photo-1487412720507-e7ab37603c6f?auto=format&fit=crop&w=500&q=80',
|
||
cover_picture: 'https://images.unsplash.com/photo-1507878866276-a947ef722fee?auto=format&fit=crop&w=1200&q=80',
|
||
city: 'Fribourg',
|
||
is_verified: true,
|
||
verified_at: relativeDate({ days: -36 }),
|
||
verified_by: null,
|
||
instagram_handle: '@nyxvandal',
|
||
tiktok_handle: '@nyxvandal',
|
||
facebook_handle: null,
|
||
plan_id: planIds.pro,
|
||
created_at: relativeDate({ days: -210 }),
|
||
updated_at: relativeDate({ days: -1 }),
|
||
},
|
||
{
|
||
id: organizerIds.selene,
|
||
name: 'Sélène',
|
||
email: 'team@selene.events',
|
||
profile_picture: 'https://images.unsplash.com/photo-1521119989659-a83eee488004?auto=format&fit=crop&w=500&q=80',
|
||
cover_picture: 'https://images.unsplash.com/photo-1525201548942-d8732f6617a0?auto=format&fit=crop&w=1200&q=80',
|
||
city: 'Lausanne',
|
||
is_verified: true,
|
||
verified_at: relativeDate({ days: -12 }),
|
||
verified_by: null,
|
||
instagram_handle: '@selene',
|
||
tiktok_handle: null,
|
||
facebook_handle: '@selene.events',
|
||
plan_id: planIds.pro,
|
||
created_at: relativeDate({ days: -160 }),
|
||
updated_at: relativeDate({ hours: -6 }),
|
||
},
|
||
{
|
||
id: organizerIds.cernier,
|
||
name: 'Fête de la Jeunesse de Cernier',
|
||
email: 'contact@cernierjeunesse.ch',
|
||
profile_picture: 'https://images.unsplash.com/photo-1529156069898-49953e39b3ac?auto=format&fit=crop&w=500&q=80',
|
||
cover_picture: 'https://images.unsplash.com/photo-1470229722913-7c0e2dbbafd3?auto=format&fit=crop&w=1200&q=80',
|
||
city: 'Cernier',
|
||
is_verified: true,
|
||
verified_at: relativeDate({ days: -9 }),
|
||
verified_by: null,
|
||
instagram_handle: '@cernierjeunesse',
|
||
tiktok_handle: '@cernierjeunesse',
|
||
facebook_handle: '@cernierjeunesse',
|
||
plan_id: planIds.free,
|
||
created_at: relativeDate({ days: -90 }),
|
||
updated_at: relativeDate({ hours: -4 }),
|
||
},
|
||
];
|
||
|
||
export const mockUsers: User[] = [
|
||
{
|
||
id: userIds.lucie,
|
||
first_name: 'Lucie',
|
||
last_name: 'Morel',
|
||
email: 'lucie@bahla.app',
|
||
password_hash: 'hashed-1',
|
||
profile_picture: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?auto=format&fit=crop&w=500&q=80',
|
||
address: 'Rue de la Gare 7',
|
||
city: 'Neuchâtel',
|
||
latitude: 46.9911,
|
||
longitude: 6.9319,
|
||
default_radius_km: 25,
|
||
language: 'fr',
|
||
notifications_enabled: true,
|
||
calendar_sync_enabled: true,
|
||
created_at: relativeDate({ days: -360 }),
|
||
updated_at: relativeDate({ hours: -3 }),
|
||
},
|
||
{
|
||
id: userIds.noah,
|
||
first_name: 'Noah',
|
||
last_name: 'Martin',
|
||
email: 'noah@bahla.app',
|
||
password_hash: 'hashed-2',
|
||
profile_picture: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?auto=format&fit=crop&w=500&q=80',
|
||
address: 'Rue des Moulins 15',
|
||
city: 'La Chaux-de-Fonds',
|
||
latitude: 47.0998,
|
||
longitude: 6.8233,
|
||
default_radius_km: 30,
|
||
language: 'fr',
|
||
notifications_enabled: true,
|
||
calendar_sync_enabled: false,
|
||
created_at: relativeDate({ days: -430 }),
|
||
updated_at: relativeDate({ hours: -9 }),
|
||
},
|
||
{
|
||
id: userIds.amelia,
|
||
first_name: 'Amélia',
|
||
last_name: 'Dubois',
|
||
email: 'amelia@bahla.app',
|
||
password_hash: 'hashed-3',
|
||
profile_picture: 'https://images.unsplash.com/photo-1544005313-94ddf0286df2?auto=format&fit=crop&w=500&q=80',
|
||
address: 'Avenue du Midi 11',
|
||
city: 'Cernier',
|
||
latitude: 47.0921,
|
||
longitude: 6.9311,
|
||
default_radius_km: 15,
|
||
language: 'fr',
|
||
notifications_enabled: true,
|
||
calendar_sync_enabled: true,
|
||
created_at: relativeDate({ days: -520 }),
|
||
updated_at: relativeDate({ hours: -2 }),
|
||
},
|
||
{
|
||
id: userIds.sam,
|
||
first_name: 'Sam',
|
||
last_name: 'Renaud',
|
||
email: 'sam@bahla.app',
|
||
password_hash: 'hashed-4',
|
||
profile_picture: 'https://images.unsplash.com/photo-1506794778202-cad84cf45f1d?auto=format&fit=crop&w=500&q=80',
|
||
address: 'Place du Marché 4',
|
||
city: 'Lausanne',
|
||
latitude: 46.5197,
|
||
longitude: 6.6323,
|
||
default_radius_km: 40,
|
||
language: 'fr',
|
||
notifications_enabled: false,
|
||
calendar_sync_enabled: false,
|
||
created_at: relativeDate({ days: -300 }),
|
||
updated_at: relativeDate({ days: -2 }),
|
||
},
|
||
];
|
||
|
||
export const mockAnimators: Animator[] = [
|
||
{
|
||
id: animatorIds.glow,
|
||
name: 'Glow Reign',
|
||
profile_picture: 'https://images.unsplash.com/photo-1524504388940-b1c1722653e1?auto=format&fit=crop&w=500&q=80',
|
||
genre: 'Techno / House',
|
||
city: 'Neuchâtel',
|
||
bio: 'Set long, percussion brute, ambiance club.',
|
||
created_at: relativeDate({ days: -210 }),
|
||
updated_at: relativeDate({ days: -7 }),
|
||
},
|
||
{
|
||
id: animatorIds.ocho,
|
||
name: 'Ocho K',
|
||
profile_picture: 'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?auto=format&fit=crop&w=500&q=80',
|
||
genre: 'Electro',
|
||
city: 'Fribourg',
|
||
bio: 'Mélange de synthés, groove et tension.',
|
||
created_at: relativeDate({ days: -180 }),
|
||
updated_at: relativeDate({ days: -2 }),
|
||
},
|
||
{
|
||
id: animatorIds.vanta,
|
||
name: 'Vanta Echo',
|
||
profile_picture: 'https://images.unsplash.com/photo-1521119989659-a83eee488004?auto=format&fit=crop&w=500&q=80',
|
||
genre: 'Synthwave',
|
||
city: 'Lausanne',
|
||
bio: 'Ambiance nocturne et lignes de basse incisives.',
|
||
created_at: relativeDate({ days: -260 }),
|
||
updated_at: relativeDate({ days: -9 }),
|
||
},
|
||
{
|
||
id: animatorIds.isae,
|
||
name: 'Isae Noir',
|
||
profile_picture: 'https://images.unsplash.com/photo-1544005313-94ddf0286df2?auto=format&fit=crop&w=500&q=80',
|
||
genre: 'Live set',
|
||
city: 'Cernier',
|
||
bio: 'Live set improvisé avec voix et machine.',
|
||
created_at: relativeDate({ days: -320 }),
|
||
updated_at: relativeDate({ days: -4 }),
|
||
},
|
||
];
|
||
|
||
const neonEventDates = makeEventDates(0, 19, 4);
|
||
const vertigeEventDates = makeEventDates(1, 22, 5);
|
||
const nyxEventDates = makeEventDates(2, 23, 4);
|
||
const seleneEventDates = makeEventDates(3, 20, 3);
|
||
const cernierEventDates = makeEventDates(7, 18, 6);
|
||
|
||
export const mockEvents: Event[] = [
|
||
{
|
||
id: eventIds.neon,
|
||
organizer_id: organizerIds.neon,
|
||
name: 'Néon Session #12',
|
||
description:
|
||
'Une session nocturne de techno minimale et d’underground, avec des sets longs et une lumière à la limite du visible.',
|
||
start_date: neonEventDates.start,
|
||
end_date: neonEventDates.end,
|
||
doors_open_time: relativeDate({ hours: 2 }),
|
||
min_age: 18,
|
||
address: 'Rue des Étoiles 14',
|
||
city: 'La Chaux-de-Fonds',
|
||
latitude: 47.1012,
|
||
longitude: 6.8251,
|
||
price_presale: 18,
|
||
price_door: 24,
|
||
is_free: false,
|
||
presale_total: 220,
|
||
presale_sold: 177,
|
||
ticketing_enabled: true,
|
||
ticketing_commission: 10,
|
||
status: 'PUBLISHED',
|
||
featured_image_id: makeUuid('event-neon-image'),
|
||
published_at: relativeDate({ days: -3 }),
|
||
created_at: relativeDate({ days: -45 }),
|
||
updated_at: relativeDate({ hours: -1 }),
|
||
},
|
||
{
|
||
id: eventIds.vertige,
|
||
organizer_id: organizerIds.vertige,
|
||
name: 'Club Vertige',
|
||
description:
|
||
'Lieu de tension et de basses profondes, Club Vertige revient pour une nuit de danse jusqu’au bout de l’aube.',
|
||
start_date: vertigeEventDates.start,
|
||
end_date: vertigeEventDates.end,
|
||
doors_open_time: relativeDate({ days: 1, hours: 20 }),
|
||
min_age: 16,
|
||
address: 'Avenue du Jura 8',
|
||
city: 'Neuchâtel',
|
||
latitude: 46.992,
|
||
longitude: 6.929,
|
||
price_presale: 15,
|
||
price_door: 22,
|
||
is_free: false,
|
||
presale_total: 180,
|
||
presale_sold: 142,
|
||
ticketing_enabled: true,
|
||
ticketing_commission: 12,
|
||
status: 'PUBLISHED',
|
||
featured_image_id: makeUuid('event-vertige-image'),
|
||
published_at: relativeDate({ days: -5 }),
|
||
created_at: relativeDate({ days: -60 }),
|
||
updated_at: relativeDate({ hours: -3 }),
|
||
},
|
||
{
|
||
id: eventIds.nyx,
|
||
organizer_id: organizerIds.nyx,
|
||
name: 'Nyx Vandal',
|
||
description:
|
||
'Une nuit pleine de synthés lourds, visuels noirs, peinture laser et énergie brute.',
|
||
start_date: nyxEventDates.start,
|
||
end_date: nyxEventDates.end,
|
||
doors_open_time: relativeDate({ days: 2, hours: 21 }),
|
||
min_age: 18,
|
||
address: 'Impasse des Tilleuls 2',
|
||
city: 'Fribourg',
|
||
latitude: 46.806,
|
||
longitude: 7.161,
|
||
price_presale: 20,
|
||
price_door: 28,
|
||
is_free: false,
|
||
presale_total: 260,
|
||
presale_sold: 210,
|
||
ticketing_enabled: true,
|
||
ticketing_commission: 11,
|
||
status: 'PUBLISHED',
|
||
featured_image_id: makeUuid('event-nyx-image'),
|
||
published_at: relativeDate({ days: -8 }),
|
||
created_at: relativeDate({ days: -80 }),
|
||
updated_at: relativeDate({ hours: -5 }),
|
||
},
|
||
{
|
||
id: eventIds.selene,
|
||
organizer_id: organizerIds.selene,
|
||
name: 'Sélène',
|
||
description:
|
||
'Atmosphère élégante et nocturne, avec un line-up électro et un décor lumineux inspiré du ciel.',
|
||
start_date: seleneEventDates.start,
|
||
end_date: seleneEventDates.end,
|
||
doors_open_time: relativeDate({ days: 3, hours: 18, minutes: 30 }),
|
||
min_age: 18,
|
||
address: 'Boulevard du Soleil 33',
|
||
city: 'Lausanne',
|
||
latitude: 46.5195,
|
||
longitude: 6.633,
|
||
price_presale: 25,
|
||
price_door: 32,
|
||
is_free: false,
|
||
presale_total: 300,
|
||
presale_sold: 243,
|
||
ticketing_enabled: true,
|
||
ticketing_commission: 9,
|
||
status: 'PUBLISHED',
|
||
featured_image_id: makeUuid('event-selene-image'),
|
||
published_at: relativeDate({ days: -5 }),
|
||
created_at: relativeDate({ days: -72 }),
|
||
updated_at: relativeDate({ hours: -2 }),
|
||
},
|
||
{
|
||
id: eventIds.cernier,
|
||
organizer_id: organizerIds.cernier,
|
||
name: 'Fête de la Jeunesse de Cernier',
|
||
description:
|
||
'Parade, musique en plein air et soirées conviviales pour la jeunesse locale, dans un esprit festif et libre.',
|
||
start_date: cernierEventDates.start,
|
||
end_date: cernierEventDates.end,
|
||
doors_open_time: relativeDate({ days: 7, hours: 16 }),
|
||
min_age: 0,
|
||
address: 'Place du Village',
|
||
city: 'Cernier',
|
||
latitude: 47.092,
|
||
longitude: 6.908,
|
||
price_presale: 0,
|
||
price_door: 0,
|
||
is_free: true,
|
||
presale_total: null,
|
||
presale_sold: 0,
|
||
ticketing_enabled: false,
|
||
ticketing_commission: null,
|
||
status: 'PUBLISHED',
|
||
featured_image_id: makeUuid('event-cernier-image'),
|
||
published_at: relativeDate({ days: -12 }),
|
||
created_at: relativeDate({ days: -110 }),
|
||
updated_at: relativeDate({ days: -1 }),
|
||
},
|
||
];
|
||
|
||
export const mockEventImages: EventImage[] = [
|
||
{
|
||
id: makeUuid('image-neon-cover'),
|
||
event_id: eventIds.neon,
|
||
url: 'https://images.unsplash.com/photo-1516280440614-37939bbacd81?auto=format&fit=crop&w=1200&q=80',
|
||
is_cover: true,
|
||
display_order: 1,
|
||
created_at: relativeDate({ days: -12 }),
|
||
},
|
||
{
|
||
id: makeUuid('image-vertige-cover'),
|
||
event_id: eventIds.vertige,
|
||
url: 'https://images.unsplash.com/photo-1501386761578-eac5c94b800a?auto=format&fit=crop&w=1200&q=80',
|
||
is_cover: true,
|
||
display_order: 1,
|
||
created_at: relativeDate({ days: -18 }),
|
||
},
|
||
{
|
||
id: makeUuid('image-nyx-cover'),
|
||
event_id: eventIds.nyx,
|
||
url: 'https://images.unsplash.com/photo-1492684223066-81342ee5ff30?auto=format&fit=crop&w=1200&q=80',
|
||
is_cover: true,
|
||
display_order: 1,
|
||
created_at: relativeDate({ days: -22 }),
|
||
},
|
||
{
|
||
id: makeUuid('image-selene-cover'),
|
||
event_id: eventIds.selene,
|
||
url: 'https://images.unsplash.com/photo-1525201548942-d8732f6617a0?auto=format&fit=crop&w=1200&q=80',
|
||
is_cover: true,
|
||
display_order: 1,
|
||
created_at: relativeDate({ days: -14 }),
|
||
},
|
||
{
|
||
id: makeUuid('image-cernier-cover'),
|
||
event_id: eventIds.cernier,
|
||
url: 'https://images.unsplash.com/photo-1470229722913-7c0e2dbbafd3?auto=format&fit=crop&w=1200&q=80',
|
||
is_cover: true,
|
||
display_order: 1,
|
||
created_at: relativeDate({ days: -20 }),
|
||
},
|
||
];
|
||
|
||
export const mockEventThemes: EventTheme[] = [
|
||
{ event_id: eventIds.neon, theme_id: themeIds.nightlife },
|
||
{ event_id: eventIds.neon, theme_id: themeIds.techno },
|
||
{ event_id: eventIds.vertige, theme_id: themeIds.techno },
|
||
{ event_id: eventIds.vertige, theme_id: themeIds.nightlife },
|
||
{ event_id: eventIds.nyx, theme_id: themeIds.festival },
|
||
{ event_id: eventIds.nyx, theme_id: themeIds.concert },
|
||
{ event_id: eventIds.selene, theme_id: themeIds.nightlife },
|
||
{ event_id: eventIds.selene, theme_id: themeIds.withFriends },
|
||
{ event_id: eventIds.cernier, theme_id: themeIds.youth },
|
||
{ event_id: eventIds.cernier, theme_id: themeIds.free },
|
||
];
|
||
|
||
export const mockEventHashtags: EventHashtag[] = [
|
||
{ event_id: eventIds.neon, hashtag_id: hashtagIds.neon },
|
||
{ event_id: eventIds.neon, hashtag_id: hashtagIds.techno },
|
||
{ event_id: eventIds.vertige, hashtag_id: hashtagIds.club },
|
||
{ event_id: eventIds.vertige, hashtag_id: hashtagIds.electro },
|
||
{ event_id: eventIds.nyx, hashtag_id: hashtagIds.electro },
|
||
{ event_id: eventIds.nyx, hashtag_id: hashtagIds.club },
|
||
{ event_id: eventIds.selene, hashtag_id: hashtagIds.afterwork },
|
||
{ event_id: eventIds.selene, hashtag_id: hashtagIds.techno },
|
||
{ event_id: eventIds.cernier, hashtag_id: hashtagIds.cernier },
|
||
{ event_id: eventIds.cernier, hashtag_id: hashtagIds.afterwork },
|
||
];
|
||
|
||
export const mockEventLineup: EventLineup[] = [
|
||
{
|
||
id: makeUuid('lineup-neon-headliner'),
|
||
event_id: eventIds.neon,
|
||
animator_id: animatorIds.glow,
|
||
stage_name: 'Glow Reign',
|
||
start_time: relativeDate({ days: 0, hours: 19, minutes: 30 }),
|
||
end_time: relativeDate({ days: 0, hours: 22, minutes: 0 }),
|
||
role: 'HEADLINER',
|
||
display_order: 1,
|
||
},
|
||
{
|
||
id: makeUuid('lineup-neon-opening'),
|
||
event_id: eventIds.neon,
|
||
animator_id: animatorIds.vanta,
|
||
stage_name: 'Vanta Echo',
|
||
start_time: relativeDate({ days: 0, hours: 17, minutes: 30 }),
|
||
end_time: relativeDate({ days: 0, hours: 19, minutes: 15 }),
|
||
role: 'OPENING',
|
||
display_order: 2,
|
||
},
|
||
{
|
||
id: makeUuid('lineup-vertige-headliner'),
|
||
event_id: eventIds.vertige,
|
||
animator_id: animatorIds.ocho,
|
||
stage_name: 'Ocho K',
|
||
start_time: relativeDate({ days: 1, hours: 22, minutes: 30 }),
|
||
end_time: relativeDate({ days: 2, hours: 1, minutes: 30 }),
|
||
role: 'HEADLINER',
|
||
display_order: 1,
|
||
},
|
||
{
|
||
id: makeUuid('lineup-nyx-headliner'),
|
||
event_id: eventIds.nyx,
|
||
animator_id: animatorIds.vanta,
|
||
stage_name: 'Vanta Echo',
|
||
start_time: relativeDate({ days: 2, hours: 23, minutes: 15 }),
|
||
end_time: relativeDate({ days: 3, hours: 1, minutes: 45 }),
|
||
role: 'HEADLINER',
|
||
display_order: 1,
|
||
},
|
||
{
|
||
id: makeUuid('lineup-selene-headliner'),
|
||
event_id: eventIds.selene,
|
||
animator_id: animatorIds.isae,
|
||
stage_name: 'Isae Noir',
|
||
start_time: relativeDate({ days: 3, hours: 20, minutes: 0 }),
|
||
end_time: relativeDate({ days: 3, hours: 21, minutes: 45 }),
|
||
role: 'HEADLINER',
|
||
display_order: 1,
|
||
},
|
||
{
|
||
id: makeUuid('lineup-cernier-headliner'),
|
||
event_id: eventIds.cernier,
|
||
animator_id: animatorIds.isae,
|
||
stage_name: 'Isae Noir',
|
||
start_time: relativeDate({ days: 7, hours: 18, minutes: 15 }),
|
||
end_time: relativeDate({ days: 7, hours: 20, minutes: 0 }),
|
||
role: 'HEADLINER',
|
||
display_order: 1,
|
||
},
|
||
];
|
||
|
||
export const mockEventExternalLinks: EventExternalLink[] = [
|
||
{
|
||
id: makeUuid('link-neon-website'),
|
||
event_id: eventIds.neon,
|
||
url: 'https://www.neonsession.ch',
|
||
label: 'Site officiel',
|
||
display_order: 1,
|
||
},
|
||
{
|
||
id: makeUuid('link-vertige-ticketing'),
|
||
event_id: eventIds.vertige,
|
||
url: 'https://www.clubvertige.ch/tickets',
|
||
label: 'Billetterie',
|
||
display_order: 1,
|
||
},
|
||
{
|
||
id: makeUuid('link-nyx-instagram'),
|
||
event_id: eventIds.nyx,
|
||
url: 'https://instagram.com/nyxvandal',
|
||
label: 'Instagram',
|
||
display_order: 1,
|
||
},
|
||
{
|
||
id: makeUuid('link-selene-flyer'),
|
||
event_id: eventIds.selene,
|
||
url: 'https://www.selene.events/flyer',
|
||
label: 'Flyer',
|
||
display_order: 1,
|
||
},
|
||
{
|
||
id: makeUuid('link-cernier-info'),
|
||
event_id: eventIds.cernier,
|
||
url: 'https://www.cernier.ch/fete-jeunesse',
|
||
label: 'Programme',
|
||
display_order: 1,
|
||
},
|
||
];
|
||
|
||
export const mockEventStatsSnapshots: EventStatsSnapshot[] = [
|
||
{
|
||
id: makeUuid('stats-neon-1'),
|
||
event_id: eventIds.neon,
|
||
snapshot_date: toSqlDate(relativeDate({ days: -3 })),
|
||
view_count: 1860,
|
||
participant_count: 1280,
|
||
interested_count: 362,
|
||
share_count: 52,
|
||
},
|
||
{
|
||
id: makeUuid('stats-vertige-1'),
|
||
event_id: eventIds.vertige,
|
||
snapshot_date: toSqlDate(relativeDate({ days: -4 })),
|
||
view_count: 2440,
|
||
participant_count: 1530,
|
||
interested_count: 498,
|
||
share_count: 74,
|
||
},
|
||
{
|
||
id: makeUuid('stats-nyx-1'),
|
||
event_id: eventIds.nyx,
|
||
snapshot_date: toSqlDate(relativeDate({ days: -6 })),
|
||
view_count: 3180,
|
||
participant_count: 1860,
|
||
interested_count: 619,
|
||
share_count: 94,
|
||
},
|
||
{
|
||
id: makeUuid('stats-selene-1'),
|
||
event_id: eventIds.selene,
|
||
snapshot_date: toSqlDate(relativeDate({ days: -7 })),
|
||
view_count: 2920,
|
||
participant_count: 1712,
|
||
interested_count: 444,
|
||
share_count: 81,
|
||
},
|
||
{
|
||
id: makeUuid('stats-cernier-1'),
|
||
event_id: eventIds.cernier,
|
||
snapshot_date: toSqlDate(relativeDate({ days: -2 })),
|
||
view_count: 1240,
|
||
participant_count: 880,
|
||
interested_count: 501,
|
||
share_count: 39,
|
||
},
|
||
];
|
||
|
||
export const mockUserEventInteractions: UserEventInteraction[] = [
|
||
{ user_id: userIds.lucie, event_id: eventIds.neon, status: 'PARTICIPATING', created_at: relativeDate({ days: -3 }), updated_at: relativeDate({ hours: -10 }) },
|
||
{ user_id: userIds.noah, event_id: eventIds.vertige, status: 'INTERESTED', created_at: relativeDate({ days: -1 }), updated_at: relativeDate({ hours: -5 }) },
|
||
{ user_id: userIds.amelia, event_id: eventIds.cernier, status: 'PARTICIPATING', created_at: relativeDate({ days: -6 }), updated_at: relativeDate({ days: -2 }) },
|
||
{ user_id: userIds.sam, event_id: eventIds.selene, status: 'SAVED', created_at: relativeDate({ days: -2 }), updated_at: relativeDate({ days: -1 }) },
|
||
];
|
||
|
||
export const mockUserOrganizerFollows: UserOrganizerFollow[] = [
|
||
{ user_id: userIds.lucie, organizer_id: organizerIds.neon, created_at: relativeDate({ days: -30 }) },
|
||
{ user_id: userIds.noah, organizer_id: organizerIds.vertige, created_at: relativeDate({ days: -18 }) },
|
||
{ user_id: userIds.amelia, organizer_id: organizerIds.cernier, created_at: relativeDate({ days: -8 }) },
|
||
{ user_id: userIds.sam, organizer_id: organizerIds.selene, created_at: relativeDate({ days: -14 }) },
|
||
];
|
||
|
||
export const mockUserThemePreferences: UserThemePreference[] = [
|
||
{ user_id: userIds.lucie, theme_id: themeIds.techno },
|
||
{ user_id: userIds.lucie, theme_id: themeIds.nightlife },
|
||
{ user_id: userIds.noah, theme_id: themeIds.festival },
|
||
{ user_id: userIds.amelia, theme_id: themeIds.youth },
|
||
{ user_id: userIds.sam, theme_id: themeIds.withFriends },
|
||
];
|
||
|
||
export const mockUserAnimatorFollows: UserAnimatorFollow[] = [
|
||
{ user_id: userIds.lucie, animator_id: animatorIds.glow, created_at: relativeDate({ days: -25 }) },
|
||
{ user_id: userIds.noah, animator_id: animatorIds.ocho, created_at: relativeDate({ days: -12 }) },
|
||
{ user_id: userIds.amelia, animator_id: animatorIds.isae, created_at: relativeDate({ days: -10 }) },
|
||
];
|
||
|
||
export const mockUserEventShares: UserEventShare[] = [
|
||
{
|
||
id: makeUuid('share-1'),
|
||
user_id: userIds.lucie,
|
||
event_id: eventIds.neon,
|
||
shared_at: relativeDate({ days: -4 }),
|
||
},
|
||
{
|
||
id: makeUuid('share-2'),
|
||
user_id: userIds.noah,
|
||
event_id: eventIds.vertige,
|
||
shared_at: relativeDate({ days: -2 }),
|
||
},
|
||
];
|
||
|
||
export const mockTickets: Ticket[] = [
|
||
{
|
||
id: makeUuid('ticket-1'),
|
||
event_id: eventIds.neon,
|
||
user_id: userIds.lucie,
|
||
type: 'PRESALE',
|
||
price_paid: 18,
|
||
bahla_commission: 1.8,
|
||
status: 'VALID',
|
||
purchased_at: relativeDate({ days: -10 }),
|
||
used_at: null,
|
||
qr_code: 'QR-NEON-12',
|
||
},
|
||
{
|
||
id: makeUuid('ticket-2'),
|
||
event_id: eventIds.vertige,
|
||
user_id: userIds.noah,
|
||
type: 'PRESALE',
|
||
price_paid: 15,
|
||
bahla_commission: 1.5,
|
||
status: 'VALID',
|
||
purchased_at: relativeDate({ days: -6 }),
|
||
used_at: null,
|
||
qr_code: 'QR-VERTIGE-1',
|
||
},
|
||
{
|
||
id: makeUuid('ticket-3'),
|
||
event_id: eventIds.cernier,
|
||
user_id: userIds.amelia,
|
||
type: 'DOOR',
|
||
price_paid: 0,
|
||
bahla_commission: 0,
|
||
status: 'VALID',
|
||
purchased_at: relativeDate({ days: -3 }),
|
||
used_at: null,
|
||
qr_code: 'QR-CERNIER-1',
|
||
},
|
||
];
|
||
|
||
export const mockPosts: Post[] = [
|
||
{
|
||
id: makeUuid('post-neon'),
|
||
organizer_id: organizerIds.neon,
|
||
event_id: eventIds.neon,
|
||
content: 'Première vague de billets presque sold out. On se retrouve pour une session longue et basse. #NeonSession',
|
||
type: 'ANNOUNCEMENT',
|
||
status: 'PUBLISHED',
|
||
scheduled_at: null,
|
||
published_at: relativeDate({ days: -2 }),
|
||
rediffusion_instagram: true,
|
||
rediffusion_tiktok: false,
|
||
rediffusion_facebook: true,
|
||
created_at: relativeDate({ days: -2 }),
|
||
updated_at: relativeDate({ hours: -8 }),
|
||
},
|
||
{
|
||
id: makeUuid('post-vertige'),
|
||
organizer_id: organizerIds.vertige,
|
||
event_id: eventIds.vertige,
|
||
content: 'Ce week-end, la salle passe en mode club total. Préparez vos meilleures chaussures.',
|
||
type: 'TEASER',
|
||
status: 'PUBLISHED',
|
||
scheduled_at: null,
|
||
published_at: relativeDate({ days: -1 }),
|
||
rediffusion_instagram: true,
|
||
rediffusion_tiktok: true,
|
||
rediffusion_facebook: false,
|
||
created_at: relativeDate({ days: -1 }),
|
||
updated_at: relativeDate({ hours: -6 }),
|
||
},
|
||
{
|
||
id: makeUuid('post-cernier'),
|
||
organizer_id: organizerIds.cernier,
|
||
event_id: eventIds.cernier,
|
||
content: 'La fête commence au village et s’étend sur tout le quartier. On vous attend avec la musique et les lumières.',
|
||
type: 'PHOTO',
|
||
status: 'PUBLISHED',
|
||
scheduled_at: null,
|
||
published_at: relativeDate({ days: -4 }),
|
||
rediffusion_instagram: true,
|
||
rediffusion_tiktok: false,
|
||
rediffusion_facebook: true,
|
||
created_at: relativeDate({ days: -4 }),
|
||
updated_at: relativeDate({ days: -2 }),
|
||
},
|
||
];
|
||
|
||
export const mockPostMedia: PostMedia[] = [
|
||
{
|
||
id: makeUuid('media-neon-1'),
|
||
post_id: mockPosts[0].id,
|
||
url: 'https://images.unsplash.com/photo-1516280440614-37939bbacd81?auto=format&fit=crop&w=1200&q=80',
|
||
type: 'IMAGE',
|
||
duration_seconds: null,
|
||
display_order: 1,
|
||
},
|
||
{
|
||
id: makeUuid('media-vertige-1'),
|
||
post_id: mockPosts[1].id,
|
||
url: 'https://images.unsplash.com/photo-1501386761578-eac5c94b800a?auto=format&fit=crop&w=1200&q=80',
|
||
type: 'IMAGE',
|
||
duration_seconds: null,
|
||
display_order: 1,
|
||
},
|
||
{
|
||
id: makeUuid('media-cernier-1'),
|
||
post_id: mockPosts[2].id,
|
||
url: 'https://images.unsplash.com/photo-1470229722913-7c0e2dbbafd3?auto=format&fit=crop&w=1200&q=80',
|
||
type: 'IMAGE',
|
||
duration_seconds: null,
|
||
display_order: 1,
|
||
},
|
||
];
|
||
|
||
export const mockPostLikes: PostLike[] = [
|
||
{ user_id: userIds.lucie, post_id: mockPosts[0].id, created_at: relativeDate({ days: -1 }) },
|
||
{ user_id: userIds.noah, post_id: mockPosts[0].id, created_at: relativeDate({ days: -2 }) },
|
||
{ user_id: userIds.amelia, post_id: mockPosts[2].id, created_at: relativeDate({ days: -3 }) },
|
||
{ user_id: userIds.sam, post_id: mockPosts[1].id, created_at: relativeDate({ days: -1, hours: -2 }) },
|
||
];
|
||
|
||
export const mockComments: Comment[] = [
|
||
{
|
||
id: makeUuid('comment-1'),
|
||
post_id: mockPosts[0].id,
|
||
user_id: userIds.noah,
|
||
parent_comment_id: null,
|
||
content: 'Le line-up a l’air killer. J’y vais à fond.',
|
||
created_at: relativeDate({ days: -1, hours: -3 }),
|
||
updated_at: relativeDate({ days: -1, hours: -3 }),
|
||
},
|
||
{
|
||
id: makeUuid('comment-2'),
|
||
post_id: mockPosts[0].id,
|
||
user_id: userIds.lucie,
|
||
parent_comment_id: null,
|
||
content: 'J’ai réservé le billet en presale, ça part vite.',
|
||
created_at: relativeDate({ days: -1, hours: -2 }),
|
||
updated_at: relativeDate({ days: -1, hours: -2 }),
|
||
},
|
||
{
|
||
id: makeUuid('comment-3'),
|
||
post_id: mockPosts[2].id,
|
||
user_id: userIds.amelia,
|
||
parent_comment_id: null,
|
||
content: 'On compte sur le village pour faire la fête toute la nuit.',
|
||
created_at: relativeDate({ days: -2 }),
|
||
updated_at: relativeDate({ days: -2 }),
|
||
},
|
||
];
|
||
|
||
export const mockCommentLikes: CommentLike[] = [
|
||
{ user_id: userIds.lucie, comment_id: mockComments[0].id, created_at: relativeDate({ days: -1, hours: -2 }) },
|
||
{ user_id: userIds.amelia, comment_id: mockComments[2].id, created_at: relativeDate({ days: -2, hours: -1 }) },
|
||
];
|
||
|
||
export const mockSearchHistory: SearchHistory[] = [
|
||
{ id: makeUuid('search-1'), user_id: userIds.lucie, query: 'techno neuchâtel', searched_at: relativeDate({ days: -9 }) },
|
||
{ id: makeUuid('search-2'), user_id: userIds.noah, query: 'club vertige', searched_at: relativeDate({ days: -3 }) },
|
||
{ id: makeUuid('search-3'), user_id: userIds.amelia, query: 'cernier fête', searched_at: relativeDate({ days: -7 }) },
|
||
];
|
||
|
||
export const mockSocialAuthProviders = [
|
||
{
|
||
id: makeUuid('auth-1'),
|
||
user_id: userIds.lucie,
|
||
provider: 'google',
|
||
provider_user_id: 'google-1',
|
||
created_at: relativeDate({ days: -120 }),
|
||
},
|
||
{
|
||
id: makeUuid('auth-2'),
|
||
user_id: userIds.noah,
|
||
provider: 'apple',
|
||
provider_user_id: 'apple-2',
|
||
created_at: relativeDate({ days: -90 }),
|
||
},
|
||
] satisfies SocialAuthProvider[];
|
||
|
||
export const mockOrganizerMembers: OrganizerMember[] = [
|
||
{
|
||
id: makeUuid('member-1'),
|
||
organizer_id: organizerIds.neon,
|
||
user_id: userIds.lucie,
|
||
email: 'lucie@bahla.app',
|
||
role: 'ADMIN',
|
||
status: 'ACTIVE',
|
||
invited_at: relativeDate({ days: -60 }),
|
||
joined_at: relativeDate({ days: -55 }),
|
||
},
|
||
{
|
||
id: makeUuid('member-2'),
|
||
organizer_id: organizerIds.vertige,
|
||
user_id: userIds.noah,
|
||
email: 'noah@bahla.app',
|
||
role: 'EDITOR',
|
||
status: 'ACTIVE',
|
||
invited_at: relativeDate({ days: -40 }),
|
||
joined_at: relativeDate({ days: -35 }),
|
||
},
|
||
{
|
||
id: makeUuid('member-3'),
|
||
organizer_id: organizerIds.cernier,
|
||
user_id: userIds.amelia,
|
||
email: 'amelia@bahla.app',
|
||
role: 'ADMIN',
|
||
status: 'ACTIVE',
|
||
invited_at: relativeDate({ days: -20 }),
|
||
joined_at: relativeDate({ days: -19 }),
|
||
},
|
||
];
|
||
|
||
export const mockOrganizerSubscriptions: OrganizerSubscription[] = [
|
||
{
|
||
id: makeUuid('subscription-1'),
|
||
organizer_id: organizerIds.neon,
|
||
plan_id: planIds.pro,
|
||
status: 'ACTIVE',
|
||
started_at: relativeDate({ days: -90 }),
|
||
renewal_date: toSqlDate(relativeDate({ days: 29 })),
|
||
cancelled_at: null,
|
||
},
|
||
{
|
||
id: makeUuid('subscription-2'),
|
||
organizer_id: organizerIds.vertige,
|
||
plan_id: planIds.ticketing,
|
||
status: 'ACTIVE',
|
||
started_at: relativeDate({ days: -120 }),
|
||
renewal_date: toSqlDate(relativeDate({ days: 11 })),
|
||
cancelled_at: null,
|
||
},
|
||
{
|
||
id: makeUuid('subscription-3'),
|
||
organizer_id: organizerIds.cernier,
|
||
plan_id: planIds.free,
|
||
status: 'ACTIVE',
|
||
started_at: relativeDate({ days: -35 }),
|
||
renewal_date: toSqlDate(relativeDate({ days: 18 })),
|
||
cancelled_at: null,
|
||
},
|
||
];
|
||
|
||
export const mockBahlaData = {
|
||
plans: mockPlans,
|
||
themes: mockThemes,
|
||
hashtags: mockHashtags,
|
||
organizers: mockOrganizers,
|
||
users: mockUsers,
|
||
animators: mockAnimators,
|
||
events: mockEvents,
|
||
event_images: mockEventImages,
|
||
event_themes: mockEventThemes,
|
||
event_hashtags: mockEventHashtags,
|
||
event_lineup: mockEventLineup,
|
||
event_external_links: mockEventExternalLinks,
|
||
event_stats_snapshots: mockEventStatsSnapshots,
|
||
organizer_members: mockOrganizerMembers,
|
||
organizer_subscriptions: mockOrganizerSubscriptions,
|
||
posts: mockPosts,
|
||
post_media: mockPostMedia,
|
||
post_likes: mockPostLikes,
|
||
comments: mockComments,
|
||
comment_likes: mockCommentLikes,
|
||
tickets: mockTickets,
|
||
searches: mockSearchHistory,
|
||
social_auth_providers: mockSocialAuthProviders,
|
||
user_event_interactions: mockUserEventInteractions,
|
||
user_organizer_follows: mockUserOrganizerFollows,
|
||
user_theme_preferences: mockUserThemePreferences,
|
||
user_animator_follows: mockUserAnimatorFollows,
|
||
user_event_shares: mockUserEventShares,
|
||
};
|
||
|
||
export const mockEventsWithRelations = mockEvents.map((event) => {
|
||
const organizer = mockOrganizers.find((item) => item.id === event.organizer_id) ?? null;
|
||
const images = mockEventImages.filter((item) => item.event_id === event.id);
|
||
const themes = mockEventThemes
|
||
.filter((item) => item.event_id === event.id)
|
||
.map((item) => mockThemes.find((theme) => theme.id === item.theme_id))
|
||
.filter(Boolean) as Theme[];
|
||
const hashtags = mockEventHashtags
|
||
.filter((item) => item.event_id === event.id)
|
||
.map((item) => mockHashtags.find((tag) => tag.id === item.hashtag_id))
|
||
.filter(Boolean) as Hashtag[];
|
||
const lineup = sortByDisplayOrder(
|
||
mockEventLineup.filter((item) => item.event_id === event.id).map((entry) => ({
|
||
...entry,
|
||
animator: mockAnimators.find((animator) => animator.id === entry.animator_id) ?? null,
|
||
})),
|
||
);
|
||
|
||
return {
|
||
...event,
|
||
organizer,
|
||
images,
|
||
themes,
|
||
hashtags,
|
||
lineup,
|
||
};
|
||
});
|
||
|
||
export const mockNow = baseDate;
|