Skip to content

Commit

Permalink
704 add events page (#705)
Browse files Browse the repository at this point in the history
* Create new option component

* Naming changes

* Add max height transition to tailwind

* Add expanded and animation

* Update option card

* Install dropdown menu

* Add sorting menu

* Make button boxy

* Current changes

* Add new App.tsx from origin

* Update type

* Add event cards
  • Loading branch information
camilovegag authored Jul 30, 2024
1 parent 337753b commit 085e804
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 21 deletions.
1 change: 1 addition & 0 deletions packages/api/src/types/Events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ export type GetEventResponse = {
updatedAt: string;
description: string | null;
fields: unknown;
status: 'OPEN' | 'CLOSED' | 'UPCOMING' | null;
};

export type GetEventsResponse = GetEventResponse[];
4 changes: 2 additions & 2 deletions packages/berlin/src/components/cycles/Cycles.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,14 @@ function Cycles({ cycles, errorMessage, eventId }: CyclesProps) {
<>
{cycles?.length ? (
cycles.map((cycle) => (
<div
<article
className="border-secondary flex w-full flex-col gap-4 border p-4"
key={cycle.id}
onClick={() => handleCycleClick(cycle.id)}
>
<Body>{cycle?.questions[0]?.title}</Body>
<Body>{formatDate(cycle.endAt)}</Body>
</div>
</article>
))
) : (
<Body>{errorMessage}</Body>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import styled from 'styled-components';
import { FlexColumn } from '../containers/FlexColumn.styled';
import { FlexRowToColumn } from '../containers/FlexRowToColumn.styled';

export const Card = styled(FlexRowToColumn)`
border-radius: 0.5rem;
export const Card = styled(FlexColumn)`
border: 1px solid var(--color-black);
overflow: hidden;
width: 100%;
Expand All @@ -12,7 +10,7 @@ export const Card = styled(FlexRowToColumn)`
export const ImageContainer = styled.div`
background-color: var(--color-gray);
width: 100%;
height: 300px;
height: 160px;
img {
height: 100%;
Expand All @@ -24,4 +22,5 @@ export const ImageContainer = styled.div`

export const CardContent = styled(FlexColumn)`
padding: 2rem;
max-height: 170px;
`;
11 changes: 5 additions & 6 deletions packages/berlin/src/components/event-card/EventCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { GetEventResponse } from 'api';
import { Subtitle } from '../typography/Subtitle.styled';
import { Body } from '../typography/Body.styled';
import { Card, CardContent, ImageContainer } from './EventCard.styled';
import Button from '../button';
import Link from '../link';

// Third-party libraries
Expand All @@ -15,14 +14,12 @@ type EventCardProps = {

function EventCard({ event, onClick }: EventCardProps) {
return (
<Card $gap="0">
<ImageContainer>
<img src={event.imageUrl} alt={`${event.name} image`} />
</ImageContainer>
<Card className="cursor-pointer" $gap="0" onClick={onClick}>
<CardContent $gap="1.25rem">
<Subtitle>{event.name}</Subtitle>
{event.description && (
<Markdown
className="max-w-[100ch] truncate"
components={{
a: ({ node, ...props }) => <Link to={props.href ?? ''}>{props.children}</Link>,
p: ({ node, ...props }) => <Body>{props.children}</Body>,
Expand All @@ -31,8 +28,10 @@ function EventCard({ event, onClick }: EventCardProps) {
{event.description}
</Markdown>
)}
{onClick && <Button onClick={onClick}>Go</Button>}
</CardContent>
<ImageContainer>
<img src={event.imageUrl} alt={`${event.name} image`} />
</ImageContainer>
</Card>
);
}
Expand Down
60 changes: 60 additions & 0 deletions packages/berlin/src/components/events/Events.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import Markdown from 'react-markdown';

import { GetEventResponse } from 'api';

import { Body } from '../typography/Body.styled';
import { Subtitle } from '../typography/Subtitle.styled';
import Link from '../link';
import { useNavigate } from 'react-router-dom';

type EventsProps = {
events: GetEventResponse[] | undefined;
errorMessage: string;
};

export default function Events({ events, errorMessage }: EventsProps) {
const navigate = useNavigate();

const handleClick = (eventId: string) => {
navigate(`/events/${eventId}/cycles`);
};

return events?.length ? (
events.map((event) => {
return (
<article
key={event.id}
className="border-secondary flex w-full cursor-pointer flex-col border"
onClick={() => handleClick(event.id)}
>
<section className="flex flex-col gap-4 p-4">
<Subtitle>{event.name}</Subtitle>
{event.description && (
<Markdown
components={{
a: ({ node, ...props }) => <Link to={props.href ?? ''}>{props.children}</Link>,
p: ({ node, ...props }) => (
<Body className="truncate" style={{ whiteSpace: 'nowrap' }}>
{props.children}
</Body>
),
}}
>
{event.description}
</Markdown>
)}
</section>
<section className="h-40 w-full">
<img
className="h-full w-full object-cover object-center"
src={event.imageUrl}
alt={`${event.name} image`}
/>
</section>
</article>
);
})
) : (
<Body>{errorMessage}</Body>
);
}
1 change: 1 addition & 0 deletions packages/berlin/src/components/events/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from './Events';
30 changes: 21 additions & 9 deletions packages/berlin/src/pages/Events.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// React and third-party libraries
import { useNavigate } from 'react-router-dom';
import { useMemo, useState } from 'react';
import { useQuery } from '@tanstack/react-query';

// API
Expand All @@ -11,27 +11,39 @@ import useUser from '../hooks/useUser';
// Components
import { FlexColumn } from '../components/containers/FlexColumn.styled';
import { Title } from '../components/typography/Title.styled';
import EventCard from '../components/event-card';
import * as Tabs from '../components/tabs';
import EventsCards from '../components/events';

function Events() {
const navigate = useNavigate();
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 handleClick = (eventId: string) => {
navigate(`/events/${eventId}/cycles`);
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">
<Title>Welcome, {user?.username ?? 'User'}</Title>
{events?.map((event) => {
return <EventCard key={event.id} event={event} onClick={() => handleClick(event.id)} />;
})}
<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 grid-cols-2 gap-4">
<Tabs.TabsManager tabs={tabs} tab={activeTab} fallback={'Tab not found'} />
</section>
</FlexColumn>
);
}
Expand Down

0 comments on commit 085e804

Please sign in to comment.