Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge develop to main #742

Merged
merged 10 commits into from
Aug 6, 2024
1 change: 1 addition & 0 deletions packages/api/src/types/Events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export type GetEventResponse = {
description: string | null;
fields: unknown;
status: 'OPEN' | 'CLOSED' | 'UPCOMING' | null;
eventDisplayRank: number | null;
};

export type GetEventsResponse = GetEventResponse[];
16 changes: 13 additions & 3 deletions packages/berlin/src/components/cycles/Cycles.tsx
Original file line number Diff line number Diff line change
@@ -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) => {
Expand All @@ -34,7 +40,11 @@ function Cycles({ cycles, errorMessage, eventId }: CyclesProps) {
</article>
))
) : (
<Body>{errorMessage}</Body>
<section className="flex w-full flex-col items-center gap-4 pt-12">
<CalendarX2 width={64} height={64} />
<Body>{fallback.message}</Body>
<Button onClick={fallback.buttonOnClick}>{fallback.buttonMessage}</Button>
</section>
)}
</>
);
Expand Down
14 changes: 10 additions & 4 deletions packages/berlin/src/components/events/Events.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};

Expand All @@ -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 (
<article
key={event.id}
Expand Down
4 changes: 3 additions & 1 deletion packages/berlin/src/components/header/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,9 @@ export default function Header() {
</div>
</>
) : (
<ZupassLoginButton>Login</ZupassLoginButton>
<ZupassLoginButton style={{ fontSize: '14px', lineHeight: '14px' }}>
Login
</ZupassLoginButton>
)}
<NavigationMenuItem>
<NavigationMenuLink>
Expand Down
2 changes: 1 addition & 1 deletion packages/berlin/src/components/option/Option.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ export default function Option({
{option.subTitle}
</Markdown>
)}
<MessageSquareText onClick={handleCommentsClick} />
<MessageSquareText className="cursor-pointer" onClick={handleCommentsClick} />
</section>
</article>
);
Expand Down
9 changes: 3 additions & 6 deletions packages/berlin/src/components/tabs/TabsHeader.tsx
Original file line number Diff line number Diff line change
@@ -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<string>(initialTab || tabNames[0]);

export function TabsHeader({ tabNames, activeTab, className, onTabChange }: TabsHeaderProps) {
const handleTabClick = (tab: string) => {
setActiveTab(tab);
if (onTabChange) {
onTabChange(tab);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -81,12 +82,7 @@ function ZupassLoginButton({ children, $variant, ...props }: ZupassLoginButtonPr

return (
<>
<Button
onClick={handleLoginClick}
{...props}
$variant={$variant}
style={{ fontSize: '14px', lineHeight: '14px', borderRadius: 4 }}
>
<Button onClick={handleLoginClick} {...props} $variant={$variant}>
{children}
</Button>
</>
Expand Down
131 changes: 89 additions & 42 deletions packages/berlin/src/pages/Event.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -44,55 +44,102 @@ function Event() {
[eventCycles],
);

const tabNames = ['upcoming', 'past'];
const [activeTab, setActiveTab] = useState<string>('upcoming');

const tabs = {
upcoming: <Cycles cycles={openCycles} eventId={eventId} errorMessage="No upcoming events..." />,
past: <Cycles cycles={closedCycles} eventId={eventId} errorMessage="No past events..." />,
};
const initialTab = useMemo(
() => (openCycles && openCycles.length > 0 ? 'upcoming' : 'past'),
[openCycles],
);

return (
<>
<Onboarding steps={eventSteps} type="event" />
<FlexColumn $gap="2rem" className="event">
<section className="grid w-full grid-cols-3 gap-x-4">
<div className={`${event?.imageUrl ? 'col-span-2' : 'col-span-3'} flex flex-col gap-4`}>
<BackButton fallbackRoute="/events" />
<Subtitle>{event?.name}</Subtitle>
{event?.description && (
<div>
<Markdown
components={{
a: ({ node, ...props }) => <Link to={props.href ?? ''}>{props.children}</Link>,
p: ({ node, ...props }) => <Body>{props.children}</Body>,
}}
>
{event.description}
</Markdown>
</div>
)}
</div>
{event?.imageUrl && (
<div className="col-span-1">
<img
src={event?.imageUrl}
alt={`${event.name} image`}
className="h-full w-full object-cover object-center"
/>
<section className="event grid w-full grid-cols-3 gap-4">
<div className={`${event?.imageUrl ? 'col-span-2' : 'col-span-3'} flex flex-col gap-4`}>
<BackButton fallbackRoute="/events" />
<Subtitle>{event?.name}</Subtitle>
{event?.description && (
<div>
<Markdown
components={{
a: ({ node, ...props }) => <Link to={props.href ?? ''}>{props.children}</Link>,
p: ({ node, ...props }) => <Body>{props.children}</Body>,
}}
>
{event.description}
</Markdown>
</div>
)}
</section>
<section className="flex w-full flex-col justify-between gap-2 md:flex-row md:items-center">
<Subtitle>Questions</Subtitle>
<Tabs.TabsHeader className="tabs" tabNames={tabNames} onTabChange={setActiveTab} />
</section>
<FlexColumn className="cycles">
<Tabs.TabsManager tabs={tabs} tab={activeTab} fallback={'Tab not found'} />
</FlexColumn>
</FlexColumn>
</div>
{event?.imageUrl && (
<div className="col-span-3 md:col-span-1">
<img
src={event?.imageUrl}
alt={`${event.name} image`}
className="h-52 w-full object-cover object-center md:h-full"
/>
</div>
)}
<Questions
initialTab={initialTab}
key={initialTab}
closedCycles={closedCycles}
eventId={eventId}
openCycles={openCycles}
/>
</section>
</>
);
}

function Questions({
initialTab,
openCycles,
closedCycles,
eventId,
}: {
initialTab: string;
openCycles: GetCycleResponse[] | undefined;
eventId?: string;
closedCycles: GetCycleResponse[] | undefined;
}) {
const [activeTab, setActiveTab] = useState<string>(initialTab);

const tabNames = ['upcoming', 'past'];

const tabs = {
upcoming: (
<Cycles
cycles={openCycles}
eventId={eventId}
fallback={{
message: 'No upcoming questions available.',
buttonMessage: 'Past questions',
buttonOnClick: () => setActiveTab('past'),
}}
/>
),
past: (
<Cycles
cycles={closedCycles}
eventId={eventId}
fallback={{
message: 'No past questions available.',
buttonMessage: 'Upcoming questions',
buttonOnClick: () => setActiveTab('upcoming'),
}}
/>
),
};

return (
<FlexColumn className="col-span-3">
<section className="flex w-full flex-col justify-between gap-2 md:flex-row md:items-center">
<Subtitle>Questions</Subtitle>
<Tabs.TabsHeader tabNames={tabNames} activeTab={activeTab} onTabChange={setActiveTab} />
</section>
<FlexColumn className="cycles">
<Tabs.TabsManager tabs={tabs} tab={activeTab} fallback={'Tab not found'} />
</FlexColumn>
</FlexColumn>
);
}
export default Event;
18 changes: 1 addition & 17 deletions packages/berlin/src/pages/Events.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
// React and third-party libraries
import { useMemo, useState } from 'react';
import { useQuery } from '@tanstack/react-query';

// API
Expand All @@ -11,38 +10,23 @@ 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<string>('upcoming');
const { user } = useUser();
const { data: events } = useQuery({
queryKey: ['events'],
queryFn: () => fetchEvents({ serverUrl: import.meta.env.VITE_SERVER_URL }),
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: <EventsCards events={openEvents} errorMessage="No upcoming events..." />,
past: <EventsCards events={closedEvents} errorMessage="No past events..." />,
};

return (
<FlexColumn $gap="2rem">
<section className="flex w-full flex-col justify-between gap-2 md:flex-row md:items-center">
<Title>Events</Title>
<Tabs.TabsHeader className="tabs" tabNames={tabNames} onTabChange={setActiveTab} />
</section>
<section className="grid w-full gap-4 md:grid-cols-2">
<Tabs.TabsManager tabs={tabs} tab={activeTab} fallback={'Tab not found'} />
<EventsCards events={events} errorMessage="No events found..." />
</section>
</FlexColumn>
);
Expand Down
Loading