Skip to content

Commit

Permalink
refactor: improve performance and layout of agenda pages (#72)
Browse files Browse the repository at this point in the history
* refactor: improve performance and layout of agenda pages

* ci: add prettier

* feat: mid day split in home

* feat: Add keynote and room labels to speaker card (#73)

* feat: Add keynote and room labels to speaker card

* style: improve spacing of button group
  • Loading branch information
jeanlivino authored Jul 22, 2024
1 parent 932c6eb commit 8d7fe4f
Show file tree
Hide file tree
Showing 12 changed files with 237 additions and 96 deletions.
15 changes: 15 additions & 0 deletions prettier.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
export default {
semi: true,
trailingComma: "es5",
singleQuote: false,
printWidth: 100,
tabWidth: 2,
useTabs: false,
bracketSpacing: true,
arrowParens: "always",
endOfLine: "lf",
quoteProps: "as-needed",
jsxSingleQuote: false,
htmlWhitespaceSensitivity: "strict",
vueIndentScriptAndStyle: false,
};
39 changes: 21 additions & 18 deletions src/api/types.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,29 @@
export type TalkCategory = 'Convida' | 'Frontend' | 'Comunidades';
export type TalkCategory = "Convida" | "Frontend" | "Comunidades";

export interface Agenda extends Record<TalkCategory, Palestra[]>{
[type: string]: Palestra[]
export interface Agenda extends Record<TalkCategory, Palestra[]> {
[type: string]: Palestra[];
}

export interface Palestra {
speaker: Speaker
keynote?: boolean
room: string
hour: string
id: number
title: string
tags: string[]
speaker: Speaker;
keynote?: boolean;
room: string;
hour: string;
id: number;
title: string;
tags: string[];
}

export interface Speaker {
role: string
company: string
bio: string
social_link: string
id: number
title: string
image: string
export interface PalestraWithRoom extends Palestra {
room: string;
}

export interface Speaker {
role: string;
company: string;
bio: string;
social_link: string;
id: number;
title: string;
image: string;
}
34 changes: 27 additions & 7 deletions src/components/ButtonGroup/ButtonGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,33 @@ export const ButtonGroup = (props: Props) => {
if (props.onChange) {
props.onChange(newMode);
}
}
};
return (
<div className="grid grid-cols-2 items-center justify-center gap-6 w-full background-slate-200 max-w-[500px]">
<ButtonTalk mode="Frontend" children="Front-End CE" active={talk == "Frontend"} onModeChange={handleChange} />
<ButtonTalk mode="Invite" children="Convida" active={talk == "Invite"} onModeChange={handleChange} />
<ButtonTalk mode="FireBanking" children="Fire Banking" active={talk == "FireBanking"} onModeChange={handleChange} />
<ButtonTalk mode="Communities" children="Comunidades" active={talk == "Communities"} onModeChange={handleChange} />
<div className="grid grid-cols-2 items-center justify-center gap-3 w-full background-slate-200 max-w-[500px]">
<ButtonTalk
mode="Frontend"
children="Front-End CE"
active={talk == "Frontend"}
onModeChange={handleChange}
/>
<ButtonTalk
mode="Invite"
children="Convida"
active={talk == "Invite"}
onModeChange={handleChange}
/>
<ButtonTalk
mode="FireBanking"
children="Fire Banking"
active={talk == "FireBanking"}
onModeChange={handleChange}
/>
<ButtonTalk
mode="Communities"
children="Comunidades"
active={talk == "Communities"}
onModeChange={handleChange}
/>
</div>
);
};
};
23 changes: 16 additions & 7 deletions src/components/LinkAgenda/LinkAgenda.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
import { cn } from "@/lib/utils";
import { Link } from "react-router-dom";

export const LinkAgenda = () => {
const linkCN = cn("text-white underline text-nowrap");

export const LinkAgenda = ({ isMyAgenda }: { isMyAgenda?: boolean }) => {
return (
<div className="flex flex-wrap gap-8 sm:justify-between justify-center items-center">
<Link className="text-white underline text-nowrap" to="/lives">
Acontecendo agora
<div className="flex flex-wrap gap-8 justify-center items-center">
{/* <Link className={linkCN} to='/lives'>
Acontecendo agora
</Link> */}
{isMyAgenda ? (
<Link className={linkCN} to="/">
Agenda completa
</Link>
<Link className="text-white underline text-nowrap" to="/agenda">
Ver minha agenda &gt;
) : (
<Link className={linkCN} to="/agenda">
Ver minha agenda &gt;
</Link>
</div>
)}
</div>
);
};
6 changes: 6 additions & 0 deletions src/components/SpeakerCard/SpeakerCard.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ const meta: Meta<typeof SpeakerCard> = {
role: { control: "text" },
onChangeMode: { action: "mode changed" },
hour: { control: "text" },
keynote: { control: "boolean" },
showRoom: { control: "boolean" },
room: { control: "text" },
isSaved: { control: "boolean" },
},
} satisfies Meta<typeof SpeakerCard>;
Expand All @@ -31,6 +34,9 @@ export const Default: Story = {
name: "Abraão",
role: "Developer",
hour: "10:00",
keynote: false,
showRoom: false,
room: "Test Room",
isSaved: true,
},
};
20 changes: 18 additions & 2 deletions src/components/SpeakerCard/SpeakerCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@ export const SpeakerCard = ({
role,
hour,
isSaved,
keynote,
showRoom,
room,
onChangeMode,
}: SpeakerCardProps) => {
/* const [isPast, setIsPast] = useState(false);
/* const [isPast, setIsPast] = useState(false);
useEffect(() => {
const now = new Date();
Expand All @@ -35,10 +38,23 @@ export const SpeakerCard = ({

return (
<Card className="max-w-[500px] p-5 w-full flex items-start flex-col justify-center bg-transparent border gap-4 border-[#D9B1FF] rounded-lg ">
{showRoom && room && (
<span className="w-full text-[#E6D5F7] bg-[#261537] text-sm px-4 py-2 rounded-lg">
Trilha: <b>{room}</b>
</span>
)}
<div className="flex gap-3 justify-between items-start w-full">
<span className="text-[#A190B2] text-sm">{hour}</span>
<h1 className="text-[#E6D5F7] mt-0 pt-0 w-full text-wrap whitespace-normal text-base break-words">
{label}
{keynote && (
<Badge
variant="outline"
className="bg-[#A855F7] text-white font-thin rounded-lg ml-1"
>
Keynote
</Badge>
)}
</h1>
<ToggleButton isSaved={isSaved} onToggle={handleToggleSave} />
</div>
Expand All @@ -61,7 +77,7 @@ export const SpeakerCard = ({
imageUrl={imageUrl}
imageFallback={imageFallback}
/>
{/* {isPast && <RatingButton label={"8:00 PM"} ratingLink={"link"} />} */}
{/* {isPast && <RatingButton label={"8:00 PM"} ratingLink={"link"} />} */}
</div>
</Card>
);
Expand Down
3 changes: 3 additions & 0 deletions src/components/SpeakerCard/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,8 @@ export interface SpeakerCardProps extends ProfileCardProps {
tags: string[];
hour: string;
isSaved: boolean;
keynote?: boolean;
showRoom?: boolean;
room?: string;
onChangeMode: (mode: boolean) => void;
}
11 changes: 8 additions & 3 deletions src/components/SpeakerSection/SpeakerSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ import { SpeakerCard } from "@/components/SpeakerCard";
import { Button } from "@/components/ui/button";
import { SpeakerSectionProps } from "./types";

export const SpeakerSection = ({ sectionTitle, liveTalk, savedCardIds, handleCardModeChange }: SpeakerSectionProps) => {

export const SpeakerSection = ({
sectionTitle,
liveTalk,
savedCardIds,
handleCardModeChange,
}: SpeakerSectionProps) => {
return (
<section className="w-full">
{liveTalk && (
Expand All @@ -23,10 +27,11 @@ export const SpeakerSection = ({ sectionTitle, liveTalk, savedCardIds, handleCar
imageFallback={liveTalk.speaker.title[0]}
name={liveTalk.speaker.title}
role={liveTalk.speaker.role}
keynote={liveTalk.keynote}
/>
</div>
</div>
)}
</section>
);
};
};
12 changes: 4 additions & 8 deletions src/hooks/useAgenda.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import { getAgenda } from '@/api';
import {useQuery} from 'react-query';
import { getAgenda } from "@/api";
import { useQuery } from "react-query";


export const useAgenda = () =>{
const data = useQuery(['agenda'], {queryFn: getAgenda, staleTime: Infinity});

return data;
}
export const useAgenda = () =>
useQuery(["agenda"], { queryFn: getAgenda, staleTime: Infinity });
18 changes: 18 additions & 0 deletions src/lib/talks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Agenda, Palestra, PalestraWithRoom } from "@/api/types";

export const splitTalksToMidDay = (talks: PalestraWithRoom[] | Palestra[]) => {
const talksBeforeMidDay = talks.filter(
(item) => item.hour.split(":")[0] < "12",
);
const talksAfterMidDay = talks.filter(
(item) => item.hour.split(":")[0] >= "12",
);

return { talksBeforeMidDay, talksAfterMidDay };
};

export const agendaResponseToTalks = (data: Agenda): PalestraWithRoom[] => {
return Object.entries(data).reduce((acc, [key, value]) => {
return acc.concat(value.map((talk) => ({ ...talk, room: key })));
}, [] as PalestraWithRoom[]);
};
48 changes: 39 additions & 9 deletions src/pages/HomePage/HomePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,28 @@ import { SpeakerCard } from "@/components/SpeakerCard";
import { useAgenda } from "@/hooks/useAgenda";
import { useSavedTalks } from "@/hooks/useSavedTalks";
import { Mode } from "@/components/ButtonGroup/types";
import { splitTalksToMidDay } from "@/lib/talks";

export const HomePage = () => {
const { data } = useAgenda();
const { savedCardIds, toggleSaveCard } = useSavedTalks();
const [currentMode, setCurrentMode] = useState<Mode>("Frontend");

const [currentMode, setCurrentMode] = useState<Mode | undefined>(undefined);

const keys = ["Frontend", "Convida", "FireBanking", "Comunidades"];

const allTalks = keys .reduce((acc: Palestra[], key) => {
const allTalks = keys
.reduce((acc: Palestra[], key) => {
return acc.concat(data?.[key] || []);
}, []).sort((a, b) => a.hour.localeCompare(b.hour));
}, [])
.sort((a, b) => a.hour.localeCompare(b.hour));

const filteredTalks = allTalks.filter(
(talk) => !currentMode || talk.room === currentMode.toLowerCase(),
);

const filteredTalks = allTalks.filter((talk) => talk.room === currentMode.toLowerCase());
const { talksBeforeMidDay, talksAfterMidDay } =
splitTalksToMidDay(filteredTalks);

return (
<section className="container my-12 flex flex-col items-center">
Expand All @@ -34,9 +42,28 @@ export const HomePage = () => {
<div className="my-8 w-full flex justify-center">
<ButtonGroup onChange={setCurrentMode} />
</div>
<DeadComponent title="Abertura" hours="8:00" />
<div className="flex flex-col items-center gap-6 mt-6 w-full mb-8">
{filteredTalks.map((talk) => (

<div className="space-y-4">
<DeadComponent title="Abertura" hours="8:00" />
{talksBeforeMidDay.map((talk) => (
<SpeakerCard
key={talk.id}
hour={talk.hour}
label={talk.title}
tags={talk.tags}
imageUrl={talk.speaker.image}
imageFallback={talk.speaker.title[0]}
name={talk.speaker.title}
role={talk.speaker.role}
room={talk.room}
keynote={talk.keynote}
showRoom={!currentMode}
isSaved={savedCardIds.includes(talk.id)}
onChangeMode={() => toggleSaveCard(talk.id)}
/>
))}
<DeadComponent title="Almoço" hours="12:00" />
{talksAfterMidDay.map((talk) => (
<SpeakerCard
key={talk.id}
hour={talk.hour}
Expand All @@ -46,12 +73,15 @@ export const HomePage = () => {
imageFallback={talk.speaker.title[0]}
name={talk.speaker.title}
role={talk.speaker.role}
room={talk.room}
keynote={talk.keynote}
showRoom={!currentMode}
isSaved={savedCardIds.includes(talk.id)}
onChangeMode={() => toggleSaveCard(talk.id)}
/>
))}
<DeadComponent title="Encerramento" hours="18:00" />
</div>
<DeadComponent title="Encerramento" hours="18:00" />
</section>
);
};
Loading

0 comments on commit 8d7fe4f

Please sign in to comment.