diff --git a/packages/berlin/src/components/cycles/Cycles.styled.tsx b/packages/berlin/src/components/cycles/Cycles.styled.tsx new file mode 100644 index 00000000..5a0c32b3 --- /dev/null +++ b/packages/berlin/src/components/cycles/Cycles.styled.tsx @@ -0,0 +1,9 @@ +import styled from 'styled-components'; +import { FlexRowToColumn } from '../containers/FlexRowToColumn.styled'; + +export const CycleContainer = styled(FlexRowToColumn)` + border: 1px solid var(--color-black); + padding: 2rem; + justify-content: space-between; + border-radius: 0.5rem; +`; diff --git a/packages/berlin/src/components/cycles/Cycles.tsx b/packages/berlin/src/components/cycles/Cycles.tsx new file mode 100644 index 00000000..09b0746f --- /dev/null +++ b/packages/berlin/src/components/cycles/Cycles.tsx @@ -0,0 +1,32 @@ +import { GetCycleResponse } from 'api'; +import { Body } from '../typography/Body.styled'; +import { CycleContainer } from './Cycles.styled'; + +type CyclesProps = { + cycles: GetCycleResponse[] | undefined; + errorMessage: string; +}; + +function Cycles({ cycles, errorMessage }: CyclesProps) { + const formatDate = (date: string) => { + const eventEndDate = new Date(date); + return eventEndDate.toLocaleDateString(); + }; + + return ( + <> + {cycles?.length ? ( + cycles.map((cycle) => ( + + {cycle.forumQuestions[0]?.questionTitle} + {formatDate(cycle.endAt)} + + )) + ) : ( + {errorMessage} + )} + + ); +} + +export default Cycles; diff --git a/packages/berlin/src/components/cycles/index.ts b/packages/berlin/src/components/cycles/index.ts new file mode 100644 index 00000000..7e9e6dfc --- /dev/null +++ b/packages/berlin/src/components/cycles/index.ts @@ -0,0 +1 @@ +export { default } from './Cycles'; diff --git a/packages/berlin/src/components/event-card/EventCard.styled.tsx b/packages/berlin/src/components/event-card/EventCard.styled.tsx index a3742b19..14382b84 100644 --- a/packages/berlin/src/components/event-card/EventCard.styled.tsx +++ b/packages/berlin/src/components/event-card/EventCard.styled.tsx @@ -3,7 +3,7 @@ import { FlexColumn } from '../containers/FlexColumn.styled'; import { FlexRowToColumn } from '../containers/FlexRowToColumn.styled'; export const Card = styled(FlexRowToColumn)` - border-radius: 1rem; + border-radius: 0.5rem; border: 1px solid var(--color-black); overflow: hidden; width: 100%; diff --git a/packages/berlin/src/components/event-card/EventCard.tsx b/packages/berlin/src/components/event-card/EventCard.tsx index 5c6d1878..e08c61aa 100644 --- a/packages/berlin/src/components/event-card/EventCard.tsx +++ b/packages/berlin/src/components/event-card/EventCard.tsx @@ -15,7 +15,7 @@ type EventCardProps = { function EventCard({ event, onClick }: EventCardProps) { return ( - + {`${event.name} diff --git a/packages/berlin/src/components/tab-manager/index.ts b/packages/berlin/src/components/tab-manager/index.ts deleted file mode 100644 index 7ab46372..00000000 --- a/packages/berlin/src/components/tab-manager/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './TabManager'; diff --git a/packages/berlin/src/components/tabs/TabsHeader.styled.tsx b/packages/berlin/src/components/tabs/TabsHeader.styled.tsx new file mode 100644 index 00000000..37162994 --- /dev/null +++ b/packages/berlin/src/components/tabs/TabsHeader.styled.tsx @@ -0,0 +1,21 @@ +import styled from 'styled-components'; +import { Body } from '../typography/Body.styled'; +import { FlexRow } from '../containers/FlexRow.styled'; + +export const Tabs = styled(FlexRow)` + justify-content: flex-start; + + @media (min-width: 600px) { + justify-content: flex-end; + } +`; + +export const Tab = styled(Body)` + cursor: pointer; + text-transform: capitalize; + + &.active { + font-weight: 600; + text-decoration: underline; + } +`; diff --git a/packages/berlin/src/components/tabs/TabsHeader.tsx b/packages/berlin/src/components/tabs/TabsHeader.tsx new file mode 100644 index 00000000..37ac4450 --- /dev/null +++ b/packages/berlin/src/components/tabs/TabsHeader.tsx @@ -0,0 +1,36 @@ +import { Fragment, useState } from 'react'; +import { Body } from '../typography/Body.styled'; +import { Tab, Tabs } from './TabsHeader.styled'; + +type TabsHeaderProps = { + tabNames: string[]; + initialTab?: string; + onTabChange?: (tab: string) => void; +}; + +export function TabsHeader({ tabNames, initialTab, onTabChange }: TabsHeaderProps) { + const [activeTab, setActiveTab] = useState(initialTab || tabNames[0]); + + const handleTabClick = (tab: string) => { + setActiveTab(tab); + if (onTabChange) { + onTabChange(tab); + } + }; + + return ( + + {tabNames.map((tabName, index) => ( + + handleTabClick(tabName)} + > + {tabName} + + {index < tabNames.length - 1 && /} + + ))} + + ); +} diff --git a/packages/berlin/src/components/tab-manager/TabManager.tsx b/packages/berlin/src/components/tabs/TabsManager.tsx similarity index 76% rename from packages/berlin/src/components/tab-manager/TabManager.tsx rename to packages/berlin/src/components/tabs/TabsManager.tsx index 25cda9f2..eba28ca8 100644 --- a/packages/berlin/src/components/tab-manager/TabManager.tsx +++ b/packages/berlin/src/components/tabs/TabsManager.tsx @@ -1,4 +1,4 @@ -export function TabManager({ +export function TabsManager({ tabs, tab, fallback, diff --git a/packages/berlin/src/components/tabs/index.ts b/packages/berlin/src/components/tabs/index.ts new file mode 100644 index 00000000..c3d97fbe --- /dev/null +++ b/packages/berlin/src/components/tabs/index.ts @@ -0,0 +1,2 @@ +export * from './TabsHeader'; +export * from './TabsManager'; diff --git a/packages/berlin/src/pages/Account.tsx b/packages/berlin/src/pages/Account.tsx index 384f2605..01024fe3 100644 --- a/packages/berlin/src/pages/Account.tsx +++ b/packages/berlin/src/pages/Account.tsx @@ -4,7 +4,7 @@ import { Title } from '../components/typography/Title.styled'; import useUser from '../hooks/useUser'; import { FlexColumn } from '../components/containers/FlexColumn.styled'; import { FlexRow } from '../components/containers/FlexRow.styled'; -import { TabManager } from '../components/tab-manager'; +import { TabsManager } from '../components/tabs'; import { Edit, X } from 'lucide-react'; import { GetUserResponse, @@ -64,7 +64,7 @@ function Account() { /> )} - Tab not found} /> + Tab not found} /> ); } diff --git a/packages/berlin/src/pages/Event.tsx b/packages/berlin/src/pages/Event.tsx index 1930710e..80872b12 100644 --- a/packages/berlin/src/pages/Event.tsx +++ b/packages/berlin/src/pages/Event.tsx @@ -1,21 +1,28 @@ // React and third-party libraries -import { useMemo } from 'react'; +import { useState, useMemo } from 'react'; import { useQuery } from '@tanstack/react-query'; import { useNavigate, useParams } from 'react-router-dom'; // API -import { GetCycleResponse, fetchEvent, fetchEventCycles } from 'api'; +import { + fetchEvent, + fetchEventCycles, + fetchEventGroupCategories, + GetGroupCategoriesResponse, +} from 'api'; // Components import { Body } from '../components/typography/Body.styled'; import { FlexColumn } from '../components/containers/FlexColumn.styled'; -import { Table } from '../components/table'; +import { FlexRow } from '../components/containers/FlexRow.styled'; +import { Subtitle } from '../components/typography/Subtitle.styled'; import Button from '../components/button'; +import Cycles from '../components/cycles'; import EventCard from '../components/event-card'; import Link from '../components/link'; +import * as Tabs from '../components/tabs'; function Event() { - const navigate = useNavigate(); const { eventId } = useParams(); const { data: event } = useQuery({ queryKey: ['event', eventId], @@ -30,6 +37,12 @@ function Event() { refetchInterval: 5000, // Poll every 5 seconds }); + const { data: groupCategories } = useQuery({ + queryKey: ['event', eventId, 'group-categories'], + queryFn: () => fetchEventGroupCategories(eventId || ''), + enabled: !!eventId, + }); + const openCycles = useMemo( () => eventCycles?.filter((cycle) => cycle.status === 'OPEN'), [eventCycles], @@ -39,83 +52,88 @@ function Event() { [eventCycles], ); - const handleDataPolicyClick = () => { - navigate(`/data-policy`); - }; - - // TODO: Create functions to navigate to onboarding slides + const tabNames = ['upcoming', 'past']; + const [activeTab, setActiveTab] = useState('upcoming'); - const handleOnboardingClick = () => { - navigate(`/onboarding`); + const tabs = { + upcoming: , + past: , }; + // TODO: flag for showing groups. + const showGroups = true; + return ( - {/* */} - {!!openCycles?.length && } - {!!closedCycles?.length && } {event && } - - Click to revisit the{' '} - - event rules - - ,{' '} - - trust assumptions - - , and the community’s{' '} - - data policy - - . - + Questions + + + + + {showGroups && } + ); } -function CycleTable({ cycles, status }: { cycles: GetCycleResponse[]; status: 'open' | 'closed' }) { - const { eventId } = useParams(); +function RunningText() { const navigate = useNavigate(); - const formatDate = (date: string) => { - const eventEndDate = new Date(date); - return eventEndDate.toLocaleDateString(); - }; - const handleClick = (cycleId: string) => { - navigate(`/events/${eventId}/cycles/${cycleId}`); + + const handleDataPolicyClick = () => { + navigate(`/data-policy`); }; - const formattedColumnText = () => { - if (status === 'open') { - return 'Closes on'; - } else { - return 'Closed on'; - } + const handleOnboardingClick = () => { + navigate(`/onboarding`); }; return ( - [ - cycle.forumQuestions?.[0]?.questionTitle, - formatDate(cycle.endAt), - , - ])} - /> + + Click to revisit the{' '} + + event rules + + ,{' '} + + trust assumptions + + , and the community’s{' '} + + data policy + + . + + ); +} + +function Groups({ groups }: { groups: GetGroupCategoriesResponse | null | undefined }) { + const navigate = useNavigate(); + + return groups ? ( + <> + Groups + + {groups.map((group) => ( + + ))} + + + ) : ( + No groups ); }