feat(client): joined event list
Some checks failed
Backend Check Build (NixCN CMS) TeamCity build failed
Client CMS Check Build (NixCN CMS) TeamCity build finished

Signed-off-by: Noa Virellia <noa@requiem.garden>
This commit is contained in:
2026-02-08 14:50:34 +08:00
parent bd23a53fbb
commit fc29d62a00
15 changed files with 262 additions and 70 deletions

View File

@@ -1,10 +1,9 @@
import type { EventInfo } from '../types'; import { useEvents } from '@/hooks/data/useEvents';
import PlaceholderImage from '@/assets/event-placeholder.png';
import { useGetEvents } from '@/hooks/data/useGetEvents';
import { Button } from '../../ui/button'; import { Button } from '../../ui/button';
import { DialogTrigger } from '../../ui/dialog'; import { DialogTrigger } from '../../ui/dialog';
import { EventJoinDialogContainer } from '../event-join.dialog.container'; import { EventJoinDialogContainer } from '../event-join.dialog.container';
import { KycDialogContainer } from '../kyc/kyc.dialog.container'; import { KycDialogContainer } from '../kyc/kyc.dialog.container';
import { toEventInfo } from '../types';
import { EventGridSkeleton } from './event-grid.skeleton'; import { EventGridSkeleton } from './event-grid.skeleton';
import { EventGridView } from './event-grid.view'; import { EventGridView } from './event-grid.view';
@@ -15,24 +14,14 @@ function JoinButton() {
} }
export function EventGridContainer() { export function EventGridContainer() {
const { data, isLoading } = useGetEvents(); const { data, isLoading } = useEvents();
return ( return (
isLoading isLoading
? <EventGridSkeleton /> ? <EventGridSkeleton />
: ( : (
<EventGridView <EventGridView
events={data.pages.flatMap(page => page.data ?? []).map(it => ({ events={data.pages.flatMap(page => page.data ?? []).map(toEventInfo)}
type: it.type! as EventInfo['type'],
eventId: it.event_id!,
isJoined: it.is_joined!,
requireKyc: it.enable_kyc!,
coverImage: it.thumbnail! || PlaceholderImage,
eventName: it.name!,
description: it.description!,
startTime: new Date(it.start_time!),
endTime: new Date(it.end_time!),
} satisfies EventInfo))}
footer={eventInfo => (eventInfo.isJoined footer={eventInfo => (eventInfo.isJoined
? <Button className="w-full" disabled></Button> ? <Button className="w-full" disabled></Button>
: ( : (

View File

@@ -0,0 +1,33 @@
import type { EventInfo } from './types';
import { useJoinedEvents } from '@/hooks/data/useJoinedEvents';
import { isInDateRange } from '@/lib/utils';
import { Button } from '../ui/button';
import { EventGridSkeleton } from './event-grid/event-grid.skeleton';
import { EventGridView } from './event-grid/event-grid.view';
import { toEventInfo } from './types';
export function JoinedEventGridFooter({ event }: { event: EventInfo }) {
return (
<div className="flex flex-row justify-between w-full gap-4">
<Button className="flex-1" disabled={!isInDateRange(event.startTime, event.endTime)}></Button>
<Button className="flex-1"></Button>
</div>
);
}
export function JoinedEventsContainer() {
const { data, isLoading } = useJoinedEvents();
return (
isLoading
? <EventGridSkeleton />
: (
<EventGridView
events={data.pages.flatMap(page => page.data ?? []).map(toEventInfo)}
footer={event => (
<JoinedEventGridFooter event={event} />
)}
/>
)
);
}

View File

@@ -1,3 +1,6 @@
import type { DataEventIndexDoc } from '@/client';
import PlaceholderImage from '@/assets/event-placeholder.png';
export interface EventInfo { export interface EventInfo {
type: 'official' | 'party'; type: 'official' | 'party';
eventId: string; eventId: string;
@@ -9,3 +12,17 @@ export interface EventInfo {
startTime: Date; startTime: Date;
endTime: Date; endTime: Date;
} }
export function toEventInfo(raw: DataEventIndexDoc): EventInfo {
return {
type: raw.type! as EventInfo['type'],
eventId: raw.event_id!,
isJoined: raw.is_joined!,
requireKyc: raw.enable_kyc!,
coverImage: raw.thumbnail! || PlaceholderImage,
eventName: raw.name!,
description: raw.description!,
startTime: new Date(raw.start_time!),
endTime: new Date(raw.end_time!),
};
}

View File

@@ -2,7 +2,7 @@ import { useInfiniteQuery } from '@tanstack/react-query';
import { isNil } from 'lodash-es'; import { isNil } from 'lodash-es';
import { getEventListInfiniteOptions } from '@/client/@tanstack/react-query.gen'; import { getEventListInfiniteOptions } from '@/client/@tanstack/react-query.gen';
export function useGetEvents() { export function useEvents() {
return useInfiniteQuery({ return useInfiniteQuery({
...getEventListInfiniteOptions({ ...getEventListInfiniteOptions({
query: {}, query: {},

View File

@@ -0,0 +1,19 @@
import { useInfiniteQuery } from '@tanstack/react-query';
import { isNil } from 'lodash-es';
import { getEventJoinedInfiniteOptions } from '@/client/@tanstack/react-query.gen';
export function useJoinedEvents() {
return useInfiniteQuery({
...getEventJoinedInfiniteOptions({
query: {},
}),
initialPageParam: 0,
getNextPageParam: (lastPage, allPages) => {
const currentData = lastPage?.data;
if (!isNil(currentData) && currentData.length === 20) {
return allPages.length * 20;
}
return undefined;
},
});
}

View File

@@ -1,4 +1,5 @@
import { import {
IconCalendarClock,
IconCalendarEvent, IconCalendarEvent,
IconDashboard, IconDashboard,
IconUser, IconUser,
@@ -16,6 +17,11 @@ export const navData = {
url: '/events', url: '/events',
icon: IconCalendarEvent, icon: IconCalendarEvent,
}, },
{
title: '已加入的活动',
url: '/joined-events',
icon: IconCalendarClock,
},
], ],
navSecondary: [ navSecondary: [
{ {

View File

@@ -27,3 +27,8 @@ export function invalidateBlurry(id: string) {
}, },
}; };
} }
export function isInDateRange(start: Date, end: Date, target: Date = new Date()): boolean {
const time = target.getTime();
return time >= start.getTime() && time <= end.getTime();
}

View File

@@ -14,9 +14,12 @@ import { Route as MagicLinkSentRouteImport } from './routes/magicLinkSent'
import { Route as AuthorizeRouteImport } from './routes/authorize' import { Route as AuthorizeRouteImport } from './routes/authorize'
import { Route as WorkbenchLayoutRouteImport } from './routes/_workbenchLayout' import { Route as WorkbenchLayoutRouteImport } from './routes/_workbenchLayout'
import { Route as WorkbenchLayoutIndexRouteImport } from './routes/_workbenchLayout/index' import { Route as WorkbenchLayoutIndexRouteImport } from './routes/_workbenchLayout/index'
import { Route as WorkbenchLayoutJoinedEventsRouteImport } from './routes/_workbenchLayout/joined-events'
import { Route as WorkbenchLayoutEventsRouteImport } from './routes/_workbenchLayout/events' import { Route as WorkbenchLayoutEventsRouteImport } from './routes/_workbenchLayout/events'
import { Route as WorkbenchLayoutProfileIndexRouteImport } from './routes/_workbenchLayout/profile.index' import { Route as WorkbenchLayoutProfileIndexRouteImport } from './routes/_workbenchLayout/profile/index'
import { Route as WorkbenchLayoutProfileUserIdRouteImport } from './routes/_workbenchLayout/profile.$userId' import { Route as WorkbenchLayoutEventsIndexRouteImport } from './routes/_workbenchLayout/events/index'
import { Route as WorkbenchLayoutProfileUserIdRouteImport } from './routes/_workbenchLayout/profile/$userId'
import { Route as WorkbenchLayoutEventsEventIdRouteImport } from './routes/_workbenchLayout/events/$eventId'
const TokenRoute = TokenRouteImport.update({ const TokenRoute = TokenRouteImport.update({
id: '/token', id: '/token',
@@ -42,6 +45,12 @@ const WorkbenchLayoutIndexRoute = WorkbenchLayoutIndexRouteImport.update({
path: '/', path: '/',
getParentRoute: () => WorkbenchLayoutRoute, getParentRoute: () => WorkbenchLayoutRoute,
} as any) } as any)
const WorkbenchLayoutJoinedEventsRoute =
WorkbenchLayoutJoinedEventsRouteImport.update({
id: '/joined-events',
path: '/joined-events',
getParentRoute: () => WorkbenchLayoutRoute,
} as any)
const WorkbenchLayoutEventsRoute = WorkbenchLayoutEventsRouteImport.update({ const WorkbenchLayoutEventsRoute = WorkbenchLayoutEventsRouteImport.update({
id: '/events', id: '/events',
path: '/events', path: '/events',
@@ -53,29 +62,46 @@ const WorkbenchLayoutProfileIndexRoute =
path: '/profile/', path: '/profile/',
getParentRoute: () => WorkbenchLayoutRoute, getParentRoute: () => WorkbenchLayoutRoute,
} as any) } as any)
const WorkbenchLayoutEventsIndexRoute =
WorkbenchLayoutEventsIndexRouteImport.update({
id: '/',
path: '/',
getParentRoute: () => WorkbenchLayoutEventsRoute,
} as any)
const WorkbenchLayoutProfileUserIdRoute = const WorkbenchLayoutProfileUserIdRoute =
WorkbenchLayoutProfileUserIdRouteImport.update({ WorkbenchLayoutProfileUserIdRouteImport.update({
id: '/profile/$userId', id: '/profile/$userId',
path: '/profile/$userId', path: '/profile/$userId',
getParentRoute: () => WorkbenchLayoutRoute, getParentRoute: () => WorkbenchLayoutRoute,
} as any) } as any)
const WorkbenchLayoutEventsEventIdRoute =
WorkbenchLayoutEventsEventIdRouteImport.update({
id: '/$eventId',
path: '/$eventId',
getParentRoute: () => WorkbenchLayoutEventsRoute,
} as any)
export interface FileRoutesByFullPath { export interface FileRoutesByFullPath {
'/': typeof WorkbenchLayoutIndexRoute '/': typeof WorkbenchLayoutIndexRoute
'/authorize': typeof AuthorizeRoute '/authorize': typeof AuthorizeRoute
'/magicLinkSent': typeof MagicLinkSentRoute '/magicLinkSent': typeof MagicLinkSentRoute
'/token': typeof TokenRoute '/token': typeof TokenRoute
'/events': typeof WorkbenchLayoutEventsRoute '/events': typeof WorkbenchLayoutEventsRouteWithChildren
'/joined-events': typeof WorkbenchLayoutJoinedEventsRoute
'/events/$eventId': typeof WorkbenchLayoutEventsEventIdRoute
'/profile/$userId': typeof WorkbenchLayoutProfileUserIdRoute '/profile/$userId': typeof WorkbenchLayoutProfileUserIdRoute
'/events/': typeof WorkbenchLayoutEventsIndexRoute
'/profile/': typeof WorkbenchLayoutProfileIndexRoute '/profile/': typeof WorkbenchLayoutProfileIndexRoute
} }
export interface FileRoutesByTo { export interface FileRoutesByTo {
'/authorize': typeof AuthorizeRoute '/authorize': typeof AuthorizeRoute
'/magicLinkSent': typeof MagicLinkSentRoute '/magicLinkSent': typeof MagicLinkSentRoute
'/token': typeof TokenRoute '/token': typeof TokenRoute
'/events': typeof WorkbenchLayoutEventsRoute '/joined-events': typeof WorkbenchLayoutJoinedEventsRoute
'/': typeof WorkbenchLayoutIndexRoute '/': typeof WorkbenchLayoutIndexRoute
'/events/$eventId': typeof WorkbenchLayoutEventsEventIdRoute
'/profile/$userId': typeof WorkbenchLayoutProfileUserIdRoute '/profile/$userId': typeof WorkbenchLayoutProfileUserIdRoute
'/events': typeof WorkbenchLayoutEventsIndexRoute
'/profile': typeof WorkbenchLayoutProfileIndexRoute '/profile': typeof WorkbenchLayoutProfileIndexRoute
} }
export interface FileRoutesById { export interface FileRoutesById {
@@ -84,9 +110,12 @@ export interface FileRoutesById {
'/authorize': typeof AuthorizeRoute '/authorize': typeof AuthorizeRoute
'/magicLinkSent': typeof MagicLinkSentRoute '/magicLinkSent': typeof MagicLinkSentRoute
'/token': typeof TokenRoute '/token': typeof TokenRoute
'/_workbenchLayout/events': typeof WorkbenchLayoutEventsRoute '/_workbenchLayout/events': typeof WorkbenchLayoutEventsRouteWithChildren
'/_workbenchLayout/joined-events': typeof WorkbenchLayoutJoinedEventsRoute
'/_workbenchLayout/': typeof WorkbenchLayoutIndexRoute '/_workbenchLayout/': typeof WorkbenchLayoutIndexRoute
'/_workbenchLayout/events/$eventId': typeof WorkbenchLayoutEventsEventIdRoute
'/_workbenchLayout/profile/$userId': typeof WorkbenchLayoutProfileUserIdRoute '/_workbenchLayout/profile/$userId': typeof WorkbenchLayoutProfileUserIdRoute
'/_workbenchLayout/events/': typeof WorkbenchLayoutEventsIndexRoute
'/_workbenchLayout/profile/': typeof WorkbenchLayoutProfileIndexRoute '/_workbenchLayout/profile/': typeof WorkbenchLayoutProfileIndexRoute
} }
export interface FileRouteTypes { export interface FileRouteTypes {
@@ -97,16 +126,21 @@ export interface FileRouteTypes {
| '/magicLinkSent' | '/magicLinkSent'
| '/token' | '/token'
| '/events' | '/events'
| '/joined-events'
| '/events/$eventId'
| '/profile/$userId' | '/profile/$userId'
| '/events/'
| '/profile/' | '/profile/'
fileRoutesByTo: FileRoutesByTo fileRoutesByTo: FileRoutesByTo
to: to:
| '/authorize' | '/authorize'
| '/magicLinkSent' | '/magicLinkSent'
| '/token' | '/token'
| '/events' | '/joined-events'
| '/' | '/'
| '/events/$eventId'
| '/profile/$userId' | '/profile/$userId'
| '/events'
| '/profile' | '/profile'
id: id:
| '__root__' | '__root__'
@@ -115,8 +149,11 @@ export interface FileRouteTypes {
| '/magicLinkSent' | '/magicLinkSent'
| '/token' | '/token'
| '/_workbenchLayout/events' | '/_workbenchLayout/events'
| '/_workbenchLayout/joined-events'
| '/_workbenchLayout/' | '/_workbenchLayout/'
| '/_workbenchLayout/events/$eventId'
| '/_workbenchLayout/profile/$userId' | '/_workbenchLayout/profile/$userId'
| '/_workbenchLayout/events/'
| '/_workbenchLayout/profile/' | '/_workbenchLayout/profile/'
fileRoutesById: FileRoutesById fileRoutesById: FileRoutesById
} }
@@ -164,6 +201,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof WorkbenchLayoutIndexRouteImport preLoaderRoute: typeof WorkbenchLayoutIndexRouteImport
parentRoute: typeof WorkbenchLayoutRoute parentRoute: typeof WorkbenchLayoutRoute
} }
'/_workbenchLayout/joined-events': {
id: '/_workbenchLayout/joined-events'
path: '/joined-events'
fullPath: '/joined-events'
preLoaderRoute: typeof WorkbenchLayoutJoinedEventsRouteImport
parentRoute: typeof WorkbenchLayoutRoute
}
'/_workbenchLayout/events': { '/_workbenchLayout/events': {
id: '/_workbenchLayout/events' id: '/_workbenchLayout/events'
path: '/events' path: '/events'
@@ -178,6 +222,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof WorkbenchLayoutProfileIndexRouteImport preLoaderRoute: typeof WorkbenchLayoutProfileIndexRouteImport
parentRoute: typeof WorkbenchLayoutRoute parentRoute: typeof WorkbenchLayoutRoute
} }
'/_workbenchLayout/events/': {
id: '/_workbenchLayout/events/'
path: '/'
fullPath: '/events/'
preLoaderRoute: typeof WorkbenchLayoutEventsIndexRouteImport
parentRoute: typeof WorkbenchLayoutEventsRoute
}
'/_workbenchLayout/profile/$userId': { '/_workbenchLayout/profile/$userId': {
id: '/_workbenchLayout/profile/$userId' id: '/_workbenchLayout/profile/$userId'
path: '/profile/$userId' path: '/profile/$userId'
@@ -185,18 +236,42 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof WorkbenchLayoutProfileUserIdRouteImport preLoaderRoute: typeof WorkbenchLayoutProfileUserIdRouteImport
parentRoute: typeof WorkbenchLayoutRoute parentRoute: typeof WorkbenchLayoutRoute
} }
'/_workbenchLayout/events/$eventId': {
id: '/_workbenchLayout/events/$eventId'
path: '/$eventId'
fullPath: '/events/$eventId'
preLoaderRoute: typeof WorkbenchLayoutEventsEventIdRouteImport
parentRoute: typeof WorkbenchLayoutEventsRoute
}
} }
} }
interface WorkbenchLayoutEventsRouteChildren {
WorkbenchLayoutEventsEventIdRoute: typeof WorkbenchLayoutEventsEventIdRoute
WorkbenchLayoutEventsIndexRoute: typeof WorkbenchLayoutEventsIndexRoute
}
const WorkbenchLayoutEventsRouteChildren: WorkbenchLayoutEventsRouteChildren = {
WorkbenchLayoutEventsEventIdRoute: WorkbenchLayoutEventsEventIdRoute,
WorkbenchLayoutEventsIndexRoute: WorkbenchLayoutEventsIndexRoute,
}
const WorkbenchLayoutEventsRouteWithChildren =
WorkbenchLayoutEventsRoute._addFileChildren(
WorkbenchLayoutEventsRouteChildren,
)
interface WorkbenchLayoutRouteChildren { interface WorkbenchLayoutRouteChildren {
WorkbenchLayoutEventsRoute: typeof WorkbenchLayoutEventsRoute WorkbenchLayoutEventsRoute: typeof WorkbenchLayoutEventsRouteWithChildren
WorkbenchLayoutJoinedEventsRoute: typeof WorkbenchLayoutJoinedEventsRoute
WorkbenchLayoutIndexRoute: typeof WorkbenchLayoutIndexRoute WorkbenchLayoutIndexRoute: typeof WorkbenchLayoutIndexRoute
WorkbenchLayoutProfileUserIdRoute: typeof WorkbenchLayoutProfileUserIdRoute WorkbenchLayoutProfileUserIdRoute: typeof WorkbenchLayoutProfileUserIdRoute
WorkbenchLayoutProfileIndexRoute: typeof WorkbenchLayoutProfileIndexRoute WorkbenchLayoutProfileIndexRoute: typeof WorkbenchLayoutProfileIndexRoute
} }
const WorkbenchLayoutRouteChildren: WorkbenchLayoutRouteChildren = { const WorkbenchLayoutRouteChildren: WorkbenchLayoutRouteChildren = {
WorkbenchLayoutEventsRoute: WorkbenchLayoutEventsRoute, WorkbenchLayoutEventsRoute: WorkbenchLayoutEventsRouteWithChildren,
WorkbenchLayoutJoinedEventsRoute: WorkbenchLayoutJoinedEventsRoute,
WorkbenchLayoutIndexRoute: WorkbenchLayoutIndexRoute, WorkbenchLayoutIndexRoute: WorkbenchLayoutIndexRoute,
WorkbenchLayoutProfileUserIdRoute: WorkbenchLayoutProfileUserIdRoute, WorkbenchLayoutProfileUserIdRoute: WorkbenchLayoutProfileUserIdRoute,
WorkbenchLayoutProfileIndexRoute: WorkbenchLayoutProfileIndexRoute, WorkbenchLayoutProfileIndexRoute: WorkbenchLayoutProfileIndexRoute,

View File

@@ -0,0 +1,9 @@
import { createFileRoute } from '@tanstack/react-router';
export const Route = createFileRoute('/_workbenchLayout/events/$eventId')({
component: RouteComponent,
});
function RouteComponent() {
return <div>Hello "/_workbenchLayout/events/$eventId"!</div>;
}

View File

@@ -0,0 +1,14 @@
import { createFileRoute } from '@tanstack/react-router';
import { EventGridContainer } from '@/components/events/event-grid/event-grid.container';
export const Route = createFileRoute('/_workbenchLayout/events/')({
component: RouteComponent,
});
function RouteComponent() {
return (
<div className="py-4 px-6 md:gap-6 md:py-6 h-full">
<EventGridContainer />
</div>
);
}

View File

@@ -0,0 +1,14 @@
import { createFileRoute } from '@tanstack/react-router';
import { JoinedEventsContainer } from '@/components/events/joined-events.containers';
export const Route = createFileRoute('/_workbenchLayout/joined-events')({
component: RouteComponent,
});
function RouteComponent() {
return (
<div className="py-4 px-6 md:gap-6 md:py-6 h-full">
<JoinedEventsContainer />
</div>
);
}

View File

@@ -1,8 +1,10 @@
import type { Meta, StoryObj } from '@storybook/react-vite'; import type { Meta, StoryObj } from '@storybook/react-vite';
import { EventGridSkeleton } from '@/components/events/event-grid/event-grid.skeleton'; import { EventGridSkeleton } from '@/components/events/event-grid/event-grid.skeleton';
import { EventGridView } from '@/components/events/event-grid/event-grid.view'; import { EventGridView } from '@/components/events/event-grid/event-grid.view';
import { JoinedEventGridFooter } from '@/components/events/joined-events.containers';
import { Button } from '@/components/ui/button'; import { Button } from '@/components/ui/button';
import { Skeleton as UiSkeleton } from '@/components/ui/skeleton'; import { Skeleton as UiSkeleton } from '@/components/ui/skeleton';
import { exampleMultiEvents } from './event.example';
const meta = { const meta = {
title: 'Events/EventGrid', title: 'Events/EventGrid',
@@ -14,56 +16,18 @@ type Story = StoryObj<typeof meta>;
export const Primary: Story = { export const Primary: Story = {
args: { args: {
events: [ events: exampleMultiEvents,
{
eventId: '1',
requireKyc: true,
isJoined: false,
type: 'official',
coverImage: 'https://github.com/NixOS/nixos-artwork/blob/master/wallpapers/nix-wallpaper-watersplash.png?raw=true',
eventName: 'Nix CN Conference 26.05',
description: 'Event Description',
startTime: new Date('2026-06-13T04:00:00.000Z'),
endTime: new Date('2026-06-14T04:00:00.000Z'),
},
{
eventId: '2',
requireKyc: true,
isJoined: false,
type: 'official',
coverImage: 'https://github.com/NixOS/nixos-artwork/blob/master/wallpapers/nix-wallpaper-moonscape.png?raw=true',
eventName: 'Nix CN Conference 26.05',
description: 'Event Description',
startTime: new Date('2026-06-13T04:00:00.000Z'),
endTime: new Date('2026-06-14T04:00:00.000Z'),
},
{
eventId: '3',
requireKyc: true,
isJoined: false,
type: 'official',
coverImage: 'https://github.com/NixOS/nixos-artwork/blob/master/wallpapers/nix-wallpaper-nineish-catppuccin-latte.png?raw=true',
eventName: 'Nix CN Conference 26.05',
description: 'Event Description',
startTime: new Date('2026-06-13T04:00:00.000Z'),
endTime: new Date('2026-06-14T04:00:00.000Z'),
},
{
eventId: '4',
requireKyc: true,
isJoined: false,
type: 'official',
coverImage: 'https://github.com/NixOS/nixos-artwork/blob/master/wallpapers/nixos-wallpaper-catppuccin-macchiato.png?raw=true',
eventName: 'Nix CN Conference 26.05',
description: 'Event Description',
startTime: new Date('2026-06-13T04:00:00.000Z'),
endTime: new Date('2026-06-14T04:00:00.000Z'),
},
],
footer: () => <Button className="w-full"></Button>, footer: () => <Button className="w-full"></Button>,
}, },
}; };
export const Joined: Story = {
args: {
events: exampleMultiEvents,
footer: event => <JoinedEventGridFooter event={event} />,
},
};
export const Empty: Story = { export const Empty: Story = {
decorators: [Story => <div className="h-screen"><Story /></div>], decorators: [Story => <div className="h-screen"><Story /></div>],
args: { args: {

View File

@@ -11,3 +11,50 @@ export const exampleEvent: EventInfo = {
startTime: new Date('2026-06-13T04:00:00.000Z'), startTime: new Date('2026-06-13T04:00:00.000Z'),
endTime: new Date('2026-06-14T04:00:00.000Z'), endTime: new Date('2026-06-14T04:00:00.000Z'),
}; };
export const exampleMultiEvents: EventInfo[] = [
{
eventId: '1',
requireKyc: true,
isJoined: false,
type: 'official',
coverImage: 'https://github.com/NixOS/nixos-artwork/blob/master/wallpapers/nix-wallpaper-watersplash.png?raw=true',
eventName: 'Nix CN Conference 26.05',
description: 'Event Description',
startTime: new Date('2026-06-13T04:00:00.000Z'),
endTime: new Date('2026-06-14T04:00:00.000Z'),
},
{
eventId: '2',
requireKyc: true,
isJoined: false,
type: 'official',
coverImage: 'https://github.com/NixOS/nixos-artwork/blob/master/wallpapers/nix-wallpaper-moonscape.png?raw=true',
eventName: 'Nix CN Conference 26.05',
description: 'Event Description',
startTime: new Date('2026-06-13T04:00:00.000Z'),
endTime: new Date('2026-06-14T04:00:00.000Z'),
},
{
eventId: '3',
requireKyc: true,
isJoined: false,
type: 'official',
coverImage: 'https://github.com/NixOS/nixos-artwork/blob/master/wallpapers/nix-wallpaper-nineish-catppuccin-latte.png?raw=true',
eventName: 'Nix CN Conference 26.05',
description: 'Event Description',
startTime: new Date('2026-06-13T04:00:00.000Z'),
endTime: new Date('2026-06-14T04:00:00.000Z'),
},
{
eventId: '4',
requireKyc: true,
isJoined: false,
type: 'official',
coverImage: 'https://github.com/NixOS/nixos-artwork/blob/master/wallpapers/nixos-wallpaper-catppuccin-macchiato.png?raw=true',
eventName: 'Nix CN Conference 26.05',
description: 'Event Description',
startTime: new Date('2026-06-13T04:00:00.000Z'),
endTime: new Date('2026-06-14T04:00:00.000Z'),
},
];