diff --git a/packages/api/src/types/Events.ts b/packages/api/src/types/Events.ts index 2ea07899..69fe8a37 100644 --- a/packages/api/src/types/Events.ts +++ b/packages/api/src/types/Events.ts @@ -9,6 +9,7 @@ export type GetEventResponse = { description: string | null; fields: unknown; status: 'OPEN' | 'CLOSED' | 'UPCOMING' | null; + eventDisplayRank: number | null; }; export type GetEventsResponse = GetEventResponse[]; diff --git a/packages/berlin/src/components/cycles/Cycles.tsx b/packages/berlin/src/components/cycles/Cycles.tsx index 926b5f9f..2da49123 100644 --- a/packages/berlin/src/components/cycles/Cycles.tsx +++ b/packages/berlin/src/components/cycles/Cycles.tsx @@ -1,14 +1,20 @@ import { GetCycleResponse } from 'api'; import { Body } from '../typography/Body.styled'; import { useNavigate } from 'react-router-dom'; +import { CalendarX2 } from 'lucide-react'; +import Button from '../button'; type CyclesProps = { cycles: GetCycleResponse[] | undefined; - errorMessage: string; eventId: string | undefined; + fallback: { + message: string; + buttonMessage: string; + buttonOnClick: () => void; + }; }; -function Cycles({ cycles, errorMessage, eventId }: CyclesProps) { +function Cycles({ cycles, eventId, fallback }: CyclesProps) { const navigate = useNavigate(); const formatDate = (date: string) => { @@ -34,7 +40,11 @@ function Cycles({ cycles, errorMessage, eventId }: CyclesProps) { )) ) : ( - {errorMessage} +
+ + {fallback.message} + +
)} ); diff --git a/packages/berlin/src/components/events/Events.tsx b/packages/berlin/src/components/events/Events.tsx index 1e11699b..e2a24d36 100644 --- a/packages/berlin/src/components/events/Events.tsx +++ b/packages/berlin/src/components/events/Events.tsx @@ -2,14 +2,14 @@ import { useNavigate } from 'react-router-dom'; // API -import { GetEventResponse } from 'api'; +import { GetEventsResponse } from 'api'; // Components import { Body } from '../typography/Body.styled'; import { Subtitle } from '../typography/Subtitle.styled'; type EventsProps = { - events: GetEventResponse[] | undefined; + events: GetEventsResponse | null | undefined; errorMessage: string; }; @@ -20,8 +20,14 @@ export default function Events({ events, errorMessage }: EventsProps) { navigate(`/events/${eventId}/cycles`); }; - return events?.length ? ( - events.map((event) => { + const sortedEvents = events?.sort((a, b) => { + const rankA = a.eventDisplayRank ?? Number.MAX_SAFE_INTEGER; + const rankB = b.eventDisplayRank ?? Number.MAX_SAFE_INTEGER; + return rankA - rankB; + }); + + return sortedEvents?.length ? ( + sortedEvents.map((event) => { return (
) : ( - Login + + Login + )} diff --git a/packages/berlin/src/components/option/Option.tsx b/packages/berlin/src/components/option/Option.tsx index ca7485d6..167c11e6 100644 --- a/packages/berlin/src/components/option/Option.tsx +++ b/packages/berlin/src/components/option/Option.tsx @@ -159,7 +159,7 @@ export default function Option({ {option.subTitle} )} - +
); diff --git a/packages/berlin/src/components/tabs/TabsHeader.tsx b/packages/berlin/src/components/tabs/TabsHeader.tsx index 1c256e88..abee1a7d 100644 --- a/packages/berlin/src/components/tabs/TabsHeader.tsx +++ b/packages/berlin/src/components/tabs/TabsHeader.tsx @@ -1,19 +1,16 @@ -import { Fragment, useState } from 'react'; +import { Fragment } from 'react'; import { Body } from '../typography/Body.styled'; import { Tab } from './TabsHeader.styled'; type TabsHeaderProps = { tabNames: string[]; - initialTab?: string; + activeTab?: string; className?: string; onTabChange?: (tab: string) => void; }; -export function TabsHeader({ tabNames, initialTab, className, onTabChange }: TabsHeaderProps) { - const [activeTab, setActiveTab] = useState(initialTab || tabNames[0]); - +export function TabsHeader({ tabNames, activeTab, className, onTabChange }: TabsHeaderProps) { const handleTabClick = (tab: string) => { - setActiveTab(tab); if (onTabChange) { onTabChange(tab); } diff --git a/packages/berlin/src/components/zupass-button/ZupassLoginButton.tsx b/packages/berlin/src/components/zupass-button/ZupassLoginButton.tsx index e7b6f735..50b6d519 100644 --- a/packages/berlin/src/components/zupass-button/ZupassLoginButton.tsx +++ b/packages/berlin/src/components/zupass-button/ZupassLoginButton.tsx @@ -16,6 +16,7 @@ import { useNavigate } from 'react-router-dom'; type ZupassLoginButtonProps = { $variant?: 'contained' | 'link'; children: React.ReactNode; + style?: React.CSSProperties; }; const POPUP_URL = window.location.origin + '/popup'; @@ -81,12 +82,7 @@ function ZupassLoginButton({ children, $variant, ...props }: ZupassLoginButtonPr return ( <> - diff --git a/packages/berlin/src/pages/Event.tsx b/packages/berlin/src/pages/Event.tsx index 7f9fb6b5..c8e079a3 100644 --- a/packages/berlin/src/pages/Event.tsx +++ b/packages/berlin/src/pages/Event.tsx @@ -4,7 +4,7 @@ import { useQuery } from '@tanstack/react-query'; import { useParams } from 'react-router-dom'; // API -import { fetchEvent, fetchEventCycles } from 'api'; +import { fetchEvent, fetchEventCycles, GetCycleResponse } from 'api'; // Components import { Body } from '../components/typography/Body.styled'; @@ -44,55 +44,102 @@ function Event() { [eventCycles], ); - const tabNames = ['upcoming', 'past']; - const [activeTab, setActiveTab] = useState('upcoming'); - - const tabs = { - upcoming: , - past: , - }; + const initialTab = useMemo( + () => (openCycles && openCycles.length > 0 ? 'upcoming' : 'past'), + [openCycles], + ); return ( <> - -
-
- - {event?.name} - {event?.description && ( -
- {props.children}, - p: ({ node, ...props }) => {props.children}, - }} - > - {event.description} - -
- )} -
- {event?.imageUrl && ( -
- {`${event.name} +
+
+ + {event?.name} + {event?.description && ( +
+ {props.children}, + p: ({ node, ...props }) => {props.children}, + }} + > + {event.description} +
)} -
-
- Questions - -
- - - - +
+ {event?.imageUrl && ( +
+ {`${event.name} +
+ )} + +
); } +function Questions({ + initialTab, + openCycles, + closedCycles, + eventId, +}: { + initialTab: string; + openCycles: GetCycleResponse[] | undefined; + eventId?: string; + closedCycles: GetCycleResponse[] | undefined; +}) { + const [activeTab, setActiveTab] = useState(initialTab); + + const tabNames = ['upcoming', 'past']; + + const tabs = { + upcoming: ( + setActiveTab('past'), + }} + /> + ), + past: ( + setActiveTab('upcoming'), + }} + /> + ), + }; + + return ( + +
+ Questions + +
+ + + +
+ ); +} export default Event; diff --git a/packages/berlin/src/pages/Events.tsx b/packages/berlin/src/pages/Events.tsx index 01923e4f..73986f1c 100644 --- a/packages/berlin/src/pages/Events.tsx +++ b/packages/berlin/src/pages/Events.tsx @@ -1,5 +1,4 @@ // React and third-party libraries -import { useMemo, useState } from 'react'; import { useQuery } from '@tanstack/react-query'; // API @@ -11,11 +10,9 @@ import useUser from '../hooks/useUser'; // Components import { FlexColumn } from '../components/containers/FlexColumn.styled'; import { Title } from '../components/typography/Title.styled'; -import * as Tabs from '../components/tabs'; import EventsCards from '../components/events'; function Events() { - const [activeTab, setActiveTab] = useState('upcoming'); const { user } = useUser(); const { data: events } = useQuery({ queryKey: ['events'], @@ -23,26 +20,13 @@ function Events() { enabled: !!user?.id, }); - const openEvents = useMemo(() => events?.filter((event) => event.status === 'OPEN'), [events]); - const closedEvents = useMemo( - () => events?.filter((events) => events.status === 'CLOSED'), - [events], - ); - - const tabNames = ['upcoming', 'past']; - const tabs = { - upcoming: , - past: , - }; - return (
Events -
- +
);