Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,15 @@ import React from "react";
import PrivacyPolicy from "@/pages/PrivacyPolicy.tsx";
import Footer from "@/components/Footer.tsx";
import SpeakerInfo from "@/components/SpeakerInfo.tsx";
import {AppProvider} from "@/context/AppContext.tsx";
import {AppProvider, useAppContext} from "@/context/AppContext.tsx";
import TicketsPage from "@/pages/TicketsPage.tsx";
import CodeOfConductSpeakers from "@/pages/CodeOfConductSpeakers.tsx";
import Agenda from "@/pages/Agenda.tsx";
import MediaKit from "@/pages/MediaKit.tsx";
import SessionPage from "@/pages/SessionPage.tsx";
import {AppStatus} from "@/types/types.ts";
import Loading from "@/pages/Loading.tsx";
import ErrorPage from "@/pages/ErrorPage.tsx";

const queryClient = new QueryClient();

Expand Down
7 changes: 5 additions & 2 deletions src/components/Photo.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {ZoomIn} from "lucide-react";
import React from "react";
import React, {useState} from "react";
import {IImage} from "@/types/types.ts";

export interface PhotoProps {
Expand All @@ -9,6 +9,8 @@ export interface PhotoProps {
}

const Photo: React.FC<PhotoProps> = ({image, setSelectedImage, index}) => {
const [loaded, setLoaded] = useState(false);

const openLightbox = (index: number) => {
setSelectedImage(index);
document.body.style.overflow = 'hidden';
Expand All @@ -27,7 +29,8 @@ const Photo: React.FC<PhotoProps> = ({image, setSelectedImage, index}) => {
alt={image.alt}
decoding="async"
loading="lazy"
className="w-full h-64 object-cover transition-transform duration-500 group-hover:scale-110 hover-scale"
className={`w-full h-64 object-cover transition-transform duration-500 group-hover:scale-110 hover-scale ${loaded ? "blur-0" : "blur-xl bg-gray-200"}`}
onLoad={() => setLoaded(true)}
/>
{/* Overlay */}
<div className="absolute inset-0 bg-black/20 lg:group-hover:bg-black/60 flex justify-between align-middle via-transparent to-transparent opacity-100 lg:opacity-0 group-hover:opacity-100 transition-opacity duration-300">
Expand Down
10 changes: 8 additions & 2 deletions src/components/Speaker.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React from "react";
import React, {useState} from "react";
import {ISpeaker} from "@/types/speakers.ts";
import {Card} from "@/components/ui/card.tsx";
import SocialMedia from "@/components/SocialMedia.tsx";
Expand All @@ -10,14 +10,20 @@ interface SpeakerProps {

const Speaker: React.FC<SpeakerProps> = ({speaker}) => {
const navigate = useNavigate();
const [loaded, setLoaded] = useState(false);

const handleClick = (speaker: ISpeaker) => {
navigate(`/speaker/${speaker.id}`, {state: {speaker}});
}

return (
<article className="h-full w-full mx-1 flex flex-col justify-center items-center">
<img src={speaker.profilePicture} alt={speaker.fullName} className="h-60 w-60 rounded-3xl" loading="lazy"/>
<img
src={speaker.profilePicture}
alt={speaker.fullName}
className={`h-60 w-60 rounded-3xl transition-all duration-500 ${loaded ? "blur-0" : "blur-xl bg-gray-200"}`}
onLoad={() => setLoaded(true)}
/>
<Card className="bg-white/10 border-0 shadow-none text-white flex flex-col justify-start gap-4 h-52 p-6 w-full max-w-[400px]">
<p className="text-2xl font-bold">{`${speaker.firstName.split(" ")[0]} ${speaker.lastName.split(" ")[0]}`}</p>
<p className="my-2 text-xl break-words line-clamp-2 overflow-hidden flex-shrink-0 rounded">{speaker.tagLine}</p>
Expand Down
8 changes: 5 additions & 3 deletions src/components/agenda/AgendaContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const AgendaContent = () => {
if (agenda.length === 0) return (<></>)

if (!displayAll && savedSessions.size === 0) {
return (<Card className="w-full pb-8 md:px-6 relative shadow-gray-500 min-h-60">
return (<Card className="w-full pb-8 md:px-6 shadow-gray-500 min-h-60">
<nav className="flex gap-4 pt-8 pb-2 sticky bg-white w-full h-20">
<Badge variant={`${displayAll ? "default" : "ghost"}`} onClick={() => setDisplayAll(true)} role="button">Mostrar todos</Badge>
<Badge variant={`${displayAll ? "ghost" : "default"}`} onClick={() => setDisplayAll(false)} role="button">Mostrar guardados</Badge>
Expand All @@ -28,14 +28,16 @@ const AgendaContent = () => {
}

return (
<Card className="w-full pb-8 md:px-6 relative shadow-gray-500">
<nav className="flex gap-4 mt-4 py-2 px-4 sticky top-[80px] z-20 bg-white w-full h-14">
<Card className="w-full pb-8 shadow-gray-500">
<nav className="flex gap-4 mt-4 py-2 px-4 sticky top-[80px] z-20 bg-white w-full h-14 border-b border-gray-200">
<Badge variant={`${displayAll ? "default" : "ghost"}`} onClick={() => setDisplayAll(true)} role="button">Mostrar todos</Badge>
<Badge variant={`${displayAll ? "ghost" : "default"}`} onClick={() => setDisplayAll(false)} role="button">Mostrar guardados</Badge>
</nav>
<aside className="flex flex-col md:px-6">
{agenda.map(({slotStart, rooms}) => (
<AgendaRow key={slotStart} slotStart={slotStart} rooms={rooms}/>
))}
</aside>
</Card>
)
}
Expand Down
4 changes: 2 additions & 2 deletions src/components/agenda/AgendaHeader.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const AgendaHeader = () => {
<div className="w-20 h-1 bg-gradient-to-r from-posadev-darkPink to-posadev-brightPink mx-auto rounded-full"/>
</header>
<aside className="flex flex-col gap-4 w-full lg:w-3/4">
<Card className="p-4 flex flex-col gap-4 border-none bg-transparent shadow-none">
<Card className="px-4 md:p-4 flex flex-col gap-4 border-none bg-transparent shadow-none">
<p className="text-primary-800 font-bold">En este evento te invitamos a:</p>
<ul className="w-full list-none grid gap-x-6 gap-y-2 grid-cols-2">
<Markup id="li-charlas" text="Asistir a las charlas" />
Expand All @@ -26,7 +26,7 @@ const AgendaHeader = () => {
<Markup id="li-diversion" text="Pásartela increible !!!" />
</ul>
</Card>
<div className="flex md:flex-row flex-col gap-10 justify-center items-center md:items-baseline text-primary-500 mt-[72px]">
<div className="flex md:flex-row flex-col gap-10 justify-center items-baseline text-primary-500 mt-[72px] px-4 md:px-0">
<AgendaItem time={['9:00 AM - 3:00 PM']} title={'Registro'} icon={IdCardLanyard } />
<AgendaItem time={['9:30am - 11:00am']} title={'Coffee break'} icon={Coffee} />
<AgendaItem time={['10:15 AM - 2:00 PM','3:55 PM - 7:00 PM']} title={'Charlas'} icon={Megaphone} />
Expand Down
26 changes: 14 additions & 12 deletions src/components/agenda/AgendaItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,22 @@ const AgendaItem: React.FC<AgendaItemProps> = ({ icon: Icon, title, time }) => {
const isSingleTime = time.length === 1;

return (
<aside className="flex flex-col items-center text-center gap-2 w-[180px] hover:scale-105 transition-transform">
<span className="h-14 w-14 border-2 border-primary-500 flex items-center justify-center">
<aside className="flex md:flex-col items-start md:items-center justify-center gap-4 md:gap-2 w-full md:w-[180px] hover:scale-105 transition-transform">
<span className="h-14 min-w-14 max-w-14 border-2 border-primary-500 flex items-center justify-center">
{Icon && <Icon className="h-6 w-6 text-primary-500" />}
</span>
<p className="font-medium text-primary-800">{title}</p>
{
time.map((timeString, index) => (
<time key={`time-${index}`} className={`flex ${isSingleTime ? "flex-col" : "flex-row flex-wrap gap-2"} items-center text-primary-600 text-sm leading-tight`}>
<span>{splitTime(timeString).start}</span>
{splitTime(timeString).end && <span className="text-xs">-</span>}
<span>{splitTime(timeString).end}</span>
</time>
))
}
<div className="flex flex-col md:gap-y-2 w-full items-start justify-start md:items-center text-center h-full">
<p className="font-medium text-primary-800">{title}</p>
{
time.map((timeString, index) => (
<time key={`time-${index}`} className={`flex ${isSingleTime ? "md:flex-col lg:flex-row lg:gap-2" : "md:flex-col lg:flex-row flex-wrap lg:gap-2"} text-primary-600 text-sm leading-tight`}>
<span>{splitTime(timeString).start}</span>
{splitTime(timeString).end && <span aria-label="a" className="text-xs">-</span>}
<span>{splitTime(timeString).end}</span>
</time>
))
}
</div>
</aside>
)
}
Expand Down
15 changes: 7 additions & 8 deletions src/components/agenda/AgendaRow.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import React, {useEffect, useState} from "react";
import Rooms from "@/components/agenda/Rooms.tsx";
import {useIsMobile} from "@/hooks/use-mobile.tsx";
import {IRoomAgenda} from "@/types/agenda.ts";
import {formatTime} from "@/lib/utils.ts";
import {useAppContext} from "@/context/AppContext.tsx";
import Adorno from "@/components/icons/Adorno.tsx";
import {Card} from "@/components/ui/card.tsx";

Expand All @@ -13,13 +11,10 @@ interface AgendaRowProps {
}

const AgendaRow: React.FC<AgendaRowProps> = ({slotStart, rooms}) => {
const {displayAll} = useAppContext()
const isMobile = useIsMobile()
const eventDate = "2025-12-06"
const slotDateTime = new Date(`${eventDate}T${slotStart}`)
const now = new Date()
const endDateTime = new Date(rooms[0]?.session.endsAt)
const expandableLogic = (!displayAll && isMobile) || (!isMobile)

const endTime = endDateTime.toLocaleTimeString(["en-US"], {hour: '2-digit', minute:'2-digit'})
const hasPassed = now > endDateTime
Expand Down Expand Up @@ -50,14 +45,18 @@ const AgendaRow: React.FC<AgendaRowProps> = ({slotStart, rooms}) => {
hasPassed ? "opacity-0 pointer-events-none" : "opacity-100"
}`}
>
<Card className="flex items-center gap-4 p-2 bg-alternative-700 border-alternative-700 sticky top-[136px] z-10">
<Card className="
flex items-center gap-4 p-2
bg-alternative-700 border-alternative-700
sticky top-[136px] z-10
md:static md:top-auto md:z-auto
">
<Adorno className="h-8 w-8" />
<time className="font-bold text-2xl text-white">{formatTime(slotStart)}</time>
<span aria-label="a" className="font-bold text-2xl text-gray-500">-</span>
<time className="font-bold text-2xl text-white">{endTime}</time>
<h2 className="font-bold text-2xl text-gray-700"></h2>
</Card>
<Rooms rooms={rooms} slotStart={slotStart} endsAt={endTime} hide={false} />
<Rooms rooms={rooms} />
</section>
)
}
Expand Down
68 changes: 43 additions & 25 deletions src/components/agenda/CardCharla.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React, { useEffect, useState } from "react";
import { IRoomAgenda } from "@/types/agenda.ts";
import { Link } from "react-router-dom";
import { useAppContext } from "@/context/AppContext.tsx";
import {ISession} from "@/types/speakers.ts";
import {Star} from "lucide-react";
import {Button} from "@/components/ui/button.tsx";
import {useNavigate} from "react-router-dom";

interface CardEventProps {
room: IRoomAgenda;
Expand All @@ -12,6 +13,7 @@ interface CardEventProps {
const CardEvent: React.FC<CardEventProps> = ({ room }) => {
const { savedSessions, setSavedSessions, displayAll } = useAppContext();
const session = room.session;
const navigate = useNavigate();
const [isSaved, setIsSaved] = useState(false);

useEffect(() => {
Expand All @@ -21,11 +23,12 @@ const CardEvent: React.FC<CardEventProps> = ({ room }) => {

const handleSaveSession = (session: ISession) => {
// @ts-ignore
setSavedSessions(prev => {
const newSet = new Set(prev);
setSavedSessions((prev: Set<number>) => {
const newSet: Set<number> = new Set(prev);
if (newSet.has(session.id)) {
newSet.delete(session.id);
setIsSaved(false);
if (navigator.vibrate) navigator.vibrate(25);
} else {
newSet.add(session.id);
setIsSaved(true);
Expand All @@ -36,30 +39,46 @@ const CardEvent: React.FC<CardEventProps> = ({ room }) => {

if (!displayAll && !savedSessions.has(session.id)) return null;
return (
<div id={`session-${session.id}`} className="flex flex-col gap-4 mt-6 w-full">
<h3 className="font-bold text-2xl">Sala: {room.name}</h3>
<WrappedCardEvent className={`${isSaved ? "bg-primary-700" : "bg-white"} relative flex flex-col gap-2 border-2 border-primary-600 rounded-lg w-full min-h-52 h-full shadow-sm shadow-gray-600 p-4`}
session={session}
<div id={`session-${session.id}`} className="flex flex-col gap-4 mt-6">
<h3 className={`font-bold text-2xl`}>Sala: {room.name}</h3>
<WrappedCardEvent className={`relative
bg-white shadow-sm shadow-gray-600 border-2 border-primary-600
flex flex-col gap-2 rounded-lg min-h-52 h-full p-4
transition-all duration-300
`}
session={session}
>
<h4 className={` text-2xl font-bold ${isSaved ? "text-white" : "text-alternative-600"}`}>
<aside className="flex w-full items-center">
{isSaved && (
<span className="bg-primary-500 text-white text-xs font-bold px-2 py-1 rounded-full shadow w-20 text-center justify-self-start">Guardado</span>
)}
<div className="flex-1" />
<button
type="button"
onClick={(e) => {
e.preventDefault();
handleSaveSession(session);
}}
className={`bg-white justify-self-end group flex justify-center items-center gap-2 border border-primary-500 font-bold px-2 py-1 rounded-lg transition-colors duration-300`}
>
<Star className={`h-4 w-4 text-primary-500 ${isSaved ? "fill-primary-500" : "fill-white group-hover:fill-primary-500"}`}/>
</button>
</aside>

<h4 className={` text-2xl font-bold text-alternative-600 ${isSaved ? "" : ""}`}>
{session.title}
</h4>
<aside className="h-full" hidden={session.speakers.length == 0}>
<div className="h-full" hidden={session.speakers.length == 0}>
{session.speakers.map((speaker) => (
<p key={speaker.id} className={`${isSaved ? "text-gray-300" : "text-gray-500"} font-bold text-2xl`}>{speaker.name}</p>
<p key={speaker.id} className={`${isSaved ? "text-gray-600" : "text-gray-500"} font-bold text-2xl`}>{speaker.name}</p>
))}
</aside>
<p hidden={session.speakers.length > 0} className={`h-full ${isSaved ? "text-gray-300" : "text-gray-500"} font-bold text-2xl`}>{session.description}</p>
<button
type="button"
onClick={(e) => {
e.preventDefault();
handleSaveSession(session);
}}
className="self-end"
>
<Star className={`h-8 w-8 ${isSaved ? " fill-white text-primary-700 hover:text-white hover:fill-primary-600" : "text-primary-600 hover:fill-primary-600"} transition-colors duration-300`} />
</button>
</div>
<p hidden={session.speakers.length > 0} className={`h-full ${isSaved ? "text-gray-600" : "text-gray-500"} font-bold text-2xl`}>{session.description}</p>
{ session.speakers.length > 0 && (
<Button variant="ghost" onClick={() => navigate(`/session/${session.id}`)}>
Ver detalles
</Button>
)}
</WrappedCardEvent>
</div>
);
Expand All @@ -73,11 +92,10 @@ interface WrappedCardEventProps {

const WrappedCardEvent: React.FC<WrappedCardEventProps> = ({session, children, className}) => {
if (session.speakers.length === 0) return (<div className={className}>{children}</div>)
return <Link
to={`/session/${session.id}`}
return <div
className={className}
>{children}
</Link>
</div>
}

export default CardEvent;
7 changes: 2 additions & 5 deletions src/components/agenda/Rooms.tsx
Original file line number Diff line number Diff line change
@@ -1,16 +1,13 @@
import React from "react";
import CardCharla from "@/components/agenda/CardCharla.tsx";

const Rooms = ({rooms, slotStart, hide, endsAt}) => {
if (hide) return null;
const Rooms = ({rooms}) => {
return (
<>
<div className="flex flex-col flex-wrap flex-grow md:flex-row gap-6 px-10 w-full">
<div className="grid grid-cols-[repeat(auto-fit,minmax(280px,1fr))] gap-6 px-4 w-full">
{rooms.map((room) => {
return <CardCharla key={room.id} room={room} />
})}
</div>
</>
)
}
export default Rooms
2 changes: 1 addition & 1 deletion src/components/ui/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ const buttonVariants = cva(
"border border-input bg-background hover:bg-accent hover:text-accent-foreground",
secondary:
"bg-secondary text-secondary-foreground hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
ghost: "bg-white border text-primary-600 hover:border-primary-500",
link: "text-primary underline-offset-4 hover:underline",
},
size: {
Expand Down
Loading