Skip to content

Commit c22fc80

Browse files
committed
Merge branch 'Footer-socials' of https://github.com/Recxsmacx/conference-website into Footer-socials
2 parents a626c6d + 6b28729 commit c22fc80

37 files changed

Lines changed: 574 additions & 1238 deletions

components/About/about.tsx

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import Heading from '../Typography/heading';
44
import Paragraph from '../Typography/paragraph';
55
import Button from '../Buttons/button';
66
import Image from 'next/image';
7+
import Download from '../illustration/download';
78

89
function About(): JSX.Element {
910
return (
@@ -51,27 +52,21 @@ function About(): JSX.Element {
5152
target="_blank"
5253
rel="noreferrer"
5354
>
54-
<Button type="button" className="w-[200px]">
55-
Become a sponsor now
56-
</Button>
55+
<Button type="button" className="w-[200px]" text="Become a sponsor now"/>
5756
</a>
5857
<a
5958
className="flex justify-center "
6059
href="/pdf/conf-2025.pdf"
6160
download={`conf ${new Date().getFullYear()}.pdf`}
6261
>
63-
<Button type="button" overlay={true} className="w-[240px] border">
64-
<div className="flex gap-2 justify-center items-center">
65-
<Image
66-
src="/img/Download_icon.png"
67-
height={20}
68-
width={20}
69-
alt="Download-icon"
70-
objectFit="contain"
71-
/>
72-
<div>Sponsorship prospectus</div>
73-
</div>
74-
</Button>
62+
<Button
63+
type="button"
64+
outline={true}
65+
className="w-[240px] border"
66+
text="Sponsorship prospectus"
67+
icon={<Download />}
68+
iconPosition="left"
69+
/>
7570
</a>
7671
</div>
7772
</div>

components/Agenda/agenda.tsx

Lines changed: 111 additions & 112 deletions
Original file line numberDiff line numberDiff line change
@@ -8,125 +8,124 @@ interface IAgenda {
88
city: ExtendedCity;
99
}
1010

11+
1112
function Agenda({ city }: IAgenda): JSX.Element {
13+
const hasMultiDayAgenda = city.agenda.some(talk => talk.day);
14+
const agendaByDay = hasMultiDayAgenda
15+
? city.agenda.reduce<Record<string, AgendaType[]>>((acc, talk) => {
16+
const dayKey = talk.day ?? 'Agenda';
17+
(acc[dayKey] ||= []).push(talk);
18+
return acc;
19+
}, {})
20+
: { Agenda: city.agenda };
21+
22+
if (city.agenda.length < 1) {
23+
return (
24+
<div data-test="agenda-com" className="flex flex-col justify-center items-center">
25+
<div className="w-[720px] lg:w-full mt-[10px] text-center">
26+
<Heading typeStyle="heading-md" className="text-white">
27+
Agenda Coming Soon - Stay Tuned!
28+
</Heading>
29+
</div>
30+
</div>
31+
);
32+
}
33+
1234
return (
13-
<div className="" data-test="agenda-com">
14-
<div className="flex flex-col justify-center items-center">
15-
{city.agenda.length < 1 ? (
16-
<div className="w-[720px] lg:w-full mt-[10px] text-center">
17-
<Heading typeStyle="heading-md" className="text-white">
18-
Agenda Coming Soon - Stay Tuned!
19-
</Heading>
20-
</div>
21-
) : (
22-
<div className="">
23-
<Heading className="text-[30px] text-white text-center mb-[40px]">
24-
Agenda
25-
</Heading>
26-
<Heading
27-
typeStyle="heading-md"
28-
className="text-gradient"
29-
level="h3"
30-
>
31-
{city.date}
32-
</Heading>
35+
<div data-test="agenda-com" className="flex flex-col justify-center items-center">
36+
<div className="w-full">
37+
<Heading className="text-[30px] text-white text-center mb-[40px]">Agenda</Heading>
38+
{Object.entries(agendaByDay).map(([day, talks]) => (
39+
<div key={day} className="mb-[80px]">
40+
{hasMultiDayAgenda && (
41+
<Heading
42+
typeStyle="heading-md"
43+
level="h3"
44+
className="text-gradient mb-[30px]"
45+
>
46+
{day}
47+
</Heading>
48+
)}
49+
{talks.map((talk: AgendaType) => {
50+
const getSpeaker = city.speakers.filter(speaker =>
51+
Array.isArray(talk.speaker)
52+
? talk.speaker.includes(speaker.id)
53+
: speaker.id === talk.speaker
54+
);
3355

34-
<div className="mt-[40px]">
35-
{city.agenda.map((talk: AgendaType) => {
36-
const getSpeaker = city.speakers.filter((speaker) => {
37-
if (typeof talk.speaker === 'object') {
38-
return talk.speaker.includes(speaker.id);
39-
}
40-
return speaker.id === talk.speaker;
41-
});
42-
return (
43-
<div
44-
key={talk.time}
45-
className={`flex sm:flex-col justify-between mt-[50px] ${!talk.speaker && 'countdown-text-gradient'}`}
46-
>
47-
<Paragraph typeStyle="body-md">{talk.time}</Paragraph>
48-
<div className="flex justify-between lg:flex-col w-[75%] lg:w-full">
49-
<div className="w-[50%] lg:w-full">
50-
<Paragraph typeStyle="body-sm" className="">
51-
{talk.type}
52-
</Paragraph>
53-
<Heading
54-
level="h3"
55-
typeStyle="heading-md-semibold"
56-
className="mt-[23px] text-white text-[20px] sm:text-[18px]"
57-
>
58-
{talk.session}
59-
</Heading>
60-
</div>
61-
{talk.speaker && typeof talk.speaker === 'number' ? (
62-
<div className="flex items-center lg:mt-4">
63-
<div className="w-[94px] h-[94px]">
64-
<Image
65-
src={getSpeaker[0].img}
66-
alt={getSpeaker[0].name}
67-
width={0}
68-
height={0}
69-
className="object-cover rounded-full w-[100%] h-[100%]"
70-
/>
71-
</div>
72-
<div className="ml-4 w-[300px] sm:w-[250px]">
73-
<Heading
74-
typeStyle="heading-sm-semibold"
75-
className="text-white"
76-
>
77-
{getSpeaker[0].name}
78-
</Heading>
79-
<Paragraph typeStyle="body-sm" className="mt-2">
80-
{getSpeaker[0].title}
81-
</Paragraph>
82-
</div>
56+
return (
57+
<div
58+
key={talk.time}
59+
className={`flex sm:flex-col justify-between mt-[50px] ${!talk.speaker ? 'countdown-text-gradient' : ''}`}
60+
>
61+
<Paragraph typeStyle="body-md">{talk.time}</Paragraph>
62+
<div className="flex justify-between lg:flex-col w-[75%] lg:w-full">
63+
<div className="w-[50%] lg:w-full">
64+
<Paragraph typeStyle="body-sm">{talk.type}</Paragraph>
65+
<Heading
66+
level="h3"
67+
typeStyle="heading-md-semibold"
68+
className="mt-[23px] text-white text-[20px] sm:text-[18px]"
69+
>
70+
{talk.session}
71+
</Heading>
72+
</div>
73+
{/* Single speaker */}
74+
{typeof talk.speaker === 'number' && getSpeaker[0] && (
75+
<div className="flex items-center lg:mt-4">
76+
<div className="w-[94px] h-[94px]">
77+
<Image
78+
src={getSpeaker[0].img}
79+
alt={getSpeaker[0].name}
80+
width={0}
81+
height={0}
82+
className="object-cover rounded-full w-full h-full"
83+
/>
8384
</div>
84-
) : (
85-
<div></div>
86-
)}
87-
{talk.speaker && typeof talk.speaker === 'object' && (
88-
<div className="flex flex-col">
89-
{getSpeaker.length > 1 &&
90-
getSpeaker.map((speaker, i) => {
91-
return (
92-
<div key={i} className="mt-6">
93-
<div className="flex items-center lg:mt-4">
94-
<div className="w-[94px] h-[94px]">
95-
<Image
96-
src={speaker.img}
97-
alt={speaker.name}
98-
width={0}
99-
height={0}
100-
className="object-cover rounded-full w-[100%] h-[100%]"
101-
/>
102-
</div>
103-
<div className="ml-4 w-[300px] sm:w-[250px]">
104-
<Heading
105-
typeStyle="heading-sm-semibold"
106-
className="text-white"
107-
>
108-
{speaker.name}
109-
</Heading>
110-
<Paragraph
111-
typeStyle="body-sm"
112-
className="mt-2"
113-
>
114-
{speaker.title}
115-
</Paragraph>
116-
</div>
117-
</div>
118-
</div>
119-
);
120-
})}
85+
<div className="ml-4 w-[300px] sm:w-[250px]">
86+
<Heading typeStyle="heading-sm-semibold" className="text-white">
87+
{getSpeaker[0].name}
88+
</Heading>
89+
<Paragraph typeStyle="body-sm" className="mt-2">
90+
{getSpeaker[0].title}
91+
</Paragraph>
12192
</div>
122-
)}
123-
</div>
93+
</div>
94+
)}
95+
{/* Multiple speakers */}
96+
{Array.isArray(talk.speaker) && getSpeaker.length > 0 && (
97+
<div className="flex flex-col">
98+
{getSpeaker.map((speaker, i) => (
99+
<div key={i} className="mt-6">
100+
<div className="flex items-center lg:mt-4">
101+
<div className="w-[94px] h-[94px]">
102+
<Image
103+
src={speaker.img}
104+
alt={speaker.name}
105+
width={0}
106+
height={0}
107+
className="object-cover rounded-full w-full h-full"
108+
/>
109+
</div>
110+
<div className="ml-4 w-[300px] sm:w-[250px]">
111+
<Heading typeStyle="heading-sm-semibold" className="text-white">
112+
{speaker.name}
113+
</Heading>
114+
<Paragraph typeStyle="body-sm" className="mt-2">
115+
{speaker.title}
116+
</Paragraph>
117+
</div>
118+
</div>
119+
</div>
120+
))}
121+
</div>
122+
)}
124123
</div>
125-
);
126-
})}
127-
</div>
124+
</div>
125+
);
126+
})}
128127
</div>
129-
)}
128+
))}
130129
</div>
131130
</div>
132131
);
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
import type { Meta, StoryObj } from '@storybook/nextjs';
2+
import Button from './button';
3+
import Download from '../illustration/download';
4+
5+
const meta: Meta<typeof Button> = {
6+
title: 'Components/Buttons',
7+
component: Button,
8+
argTypes: {
9+
children: {
10+
control: { type: 'text' },
11+
description: 'Button content (alternative to text prop)',
12+
defaultValue: 'Button',
13+
},
14+
text: {
15+
control: { type: 'text' },
16+
description: 'Button text (alternative to children)',
17+
},
18+
type: {
19+
options: ['button', 'submit', 'reset'],
20+
control: { type: 'select' },
21+
defaultValue: 'button',
22+
},
23+
className: {
24+
control: { type: 'text' },
25+
description: 'Custom CSS classes',
26+
},
27+
outline: {
28+
control: { type: 'boolean' },
29+
description: 'Remove gradient background if true',
30+
},
31+
disabled: {
32+
control: { type: 'boolean' },
33+
description: 'Disable the button',
34+
},
35+
test: {
36+
control: { type: 'text' },
37+
description: 'Test attribute',
38+
},
39+
icon: {
40+
control: { type: 'object' },
41+
description: 'Icon component to display',
42+
},
43+
iconPosition: {
44+
options: ['left', 'right', 'center'],
45+
control: { type: 'select' },
46+
description: 'Position of the icon relative to text',
47+
defaultValue: 'right',
48+
},
49+
onClick: { action: 'clicked' },
50+
},
51+
};
52+
53+
export default meta;
54+
55+
type Story = StoryObj<typeof Button>;
56+
57+
export const Default: Story = {
58+
args: {
59+
text: 'Default Button',
60+
type: 'button',
61+
},
62+
};
63+
64+
export const Outline: Story = {
65+
args: {
66+
text: 'Outline Button',
67+
outline: true,
68+
className: 'border',
69+
type: 'button',
70+
},
71+
};
72+
73+
export const Submit: Story = {
74+
args: {
75+
text: 'Submit Button',
76+
type: 'submit',
77+
},
78+
};
79+
80+
export const Reset: Story = {
81+
args: {
82+
text: 'Reset Button',
83+
type: 'reset',
84+
},
85+
};
86+
87+
export const WithIconRight: Story = {
88+
args: {
89+
text: 'Download File',
90+
icon: <Download />,
91+
iconPosition: 'right',
92+
type: 'button',
93+
},
94+
};
95+
96+
export const WithIconLeft: Story = {
97+
args: {
98+
text: 'Download File',
99+
icon: <Download />,
100+
iconPosition: 'left',
101+
type: 'button',
102+
},
103+
};
104+
105+
export const IconWithOutline: Story = {
106+
args: {
107+
text: 'Sponsorship Prospectus',
108+
icon: <Download />,
109+
iconPosition: 'left',
110+
outline: true,
111+
className: 'w-[240px] border',
112+
type: 'button',
113+
},
114+
};

0 commit comments

Comments
 (0)