Skip to content

Commit d254059

Browse files
authored
Merge pull request #143 from ReDI-School/feat/Improve-LandingPage
Feat/improve landing page
2 parents dccc9e5 + 5431e17 commit d254059

File tree

7 files changed

+287
-14
lines changed

7 files changed

+287
-14
lines changed

frontend/src/components/Accordion/Accordion.tsx

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,11 @@
11
import type { AccordionProps } from './Accordion.types';
22
import styles from './Accordion.module.css';
33

4-
const Accordion = ({ items, defaultOpenItem = '1' }: AccordionProps) => {
4+
const Accordion = ({ items }: AccordionProps) => {
55
return (
66
<div className={styles.accordion}>
77
{items.map((item) => (
8-
<details
9-
key={item.id}
10-
className={styles.accordionItem}
11-
name="notes"
12-
open={defaultOpenItem === item.id}
13-
>
8+
<details key={item.id} className={styles.accordionItem} name="notes">
149
<summary>
1510
<p>{item.title}</p>
1611
<div className={styles.close}>
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
.footer {
2+
border-top: var(--border-divider-width) solid var(--grey-825);
3+
color: #b3b3b3;
4+
padding: 48px 24px;
5+
font-size: 14px;
6+
}
7+
8+
.container {
9+
max-width: 1100px;
10+
margin: 0 auto;
11+
}
12+
13+
.topRow {
14+
margin-bottom: 24px;
15+
}
16+
17+
.helpText {
18+
color: #b3b3b3;
19+
}
20+
21+
.phoneLink {
22+
color: #b3b3b3;
23+
text-decoration: underline;
24+
margin-left: 6px;
25+
}
26+
27+
.linksGrid {
28+
display: grid;
29+
grid-template-columns: repeat(4, 1fr);
30+
gap: 16px;
31+
margin: 16px 0 28px 0;
32+
}
33+
34+
@media (max-width: 768px) {
35+
.linksGrid {
36+
grid-template-columns: repeat(2, 1fr);
37+
}
38+
}
39+
40+
.linkColumn {
41+
list-style: none;
42+
padding: 0;
43+
margin: 0;
44+
}
45+
46+
.linkItem {
47+
margin: 8px 0;
48+
}
49+
50+
.link {
51+
color: #b3b3b3;
52+
text-decoration: none;
53+
opacity: 0.9;
54+
}
55+
56+
.link:hover {
57+
color: #ffffff;
58+
text-decoration: underline;
59+
}
60+
61+
.controlsRow {
62+
display: flex;
63+
align-items: center;
64+
justify-content: space-between;
65+
gap: 12px;
66+
margin-top: 12px;
67+
}
68+
69+
copyright {
70+
color: #808080;
71+
}
72+
73+
@media (max-width: 480px) {
74+
.controlsRow {
75+
flex-direction: column;
76+
align-items: flex-start;
77+
gap: 8px;
78+
}
79+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import type { Meta, StoryObj } from '@storybook/react-vite';
2+
3+
import Footer from './Footer';
4+
5+
const meta: Meta<typeof Footer> = {
6+
title: 'Components/Footer',
7+
component: Footer,
8+
tags: ['autodocs'],
9+
};
10+
11+
export default meta;
12+
type Story = StoryObj<typeof Footer>;
13+
14+
export const Default: Story = {
15+
render: () => <Footer />,
16+
};
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
import Select from '../../components/Select/Select';
2+
import styles from './Footer.module.css';
3+
import { languagesMap } from '../../constants/languages';
4+
5+
const footerLinks = [
6+
[
7+
{ label: 'FAQ', href: '#faq' },
8+
{ label: 'Help Center', href: '/help' },
9+
{ label: 'Account', href: '/account' },
10+
{ label: 'Media Center', href: '/media' },
11+
{ label: 'Investor Relations', href: '/investors' },
12+
{ label: 'Jobs', href: '/jobs' },
13+
],
14+
[
15+
{ label: 'Netflix Shop', href: '/shop' },
16+
{ label: 'Redeem Gift Cards', href: '/redeem' },
17+
{ label: 'Buy Gift Cards', href: '/buy' },
18+
{ label: 'Ways to Watch', href: '/ways-to-watch' },
19+
{ label: 'Terms of Use', href: '/terms' },
20+
{ label: 'Privacy', href: '/privacy' },
21+
],
22+
[
23+
{ label: 'Cookie Preferences', href: '/cookies' },
24+
{ label: 'Corporate Information', href: '/corporate' },
25+
{ label: 'Contact Us', href: '/contact' },
26+
{ label: 'Speed Test', href: '/speed-test' },
27+
{ label: 'Legal Notices', href: '/legal' },
28+
{ label: 'Only on Netflix', href: '/only-on-netflix' },
29+
],
30+
[
31+
{ label: 'Do Not Sell or Share Personal Information', href: '/do-not-sell' },
32+
{ label: 'Ad Choices', href: '/ad-choices' },
33+
],
34+
];
35+
36+
const selectOptions = Object.entries(languagesMap).map(([value, label]) => ({
37+
value,
38+
label,
39+
}));
40+
const defaultLanguage = selectOptions.find((option) => option.value === 'en');
41+
42+
const Footer = () => {
43+
return (
44+
<footer className={styles.footer} aria-labelledby="footer-heading">
45+
<div className={styles.container}>
46+
<div className={styles.topRow}>
47+
<div className={styles.helpText}>
48+
<span>Questions? Call </span>
49+
<a className={styles.phoneLink} href="tel:1-844-505-2993">
50+
1-844-505-2993
51+
</a>
52+
</div>
53+
</div>
54+
55+
<div className={styles.linksGrid} role="navigation" aria-label="Footer navigation">
56+
{footerLinks.map((column, colIndex) => (
57+
<ul key={colIndex} className={styles.linkColumn}>
58+
{column.map((link) => (
59+
<li key={link.label} className={styles.linkItem}>
60+
<a href={link.href ?? '#'} className={styles.link}>
61+
{link.label}
62+
</a>
63+
</li>
64+
))}
65+
</ul>
66+
))}
67+
</div>
68+
69+
<div className={styles.controlsRow}>
70+
<Select id="footer-language" options={selectOptions} selected={defaultLanguage} />
71+
<div className={styles.copyright}>
72+
<small>© {new Date().getFullYear()} Rediflix, Inc.</small>
73+
</div>
74+
</div>
75+
</div>
76+
</footer>
77+
);
78+
};
79+
80+
export default Footer;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
.accordion {
2+
margin-top: 10rem;
3+
4+
h2 {
5+
text-align: center;
6+
margin-bottom: 2rem;
7+
}
8+
}
9+
10+
.text {
11+
text-align: center;
12+
margin: 5rem 0 2rem 0;
13+
text-wrap: pretty;
14+
font-size: var(--text-xl);
15+
font-weight: var(--space-2);
16+
}
17+
18+
.emailContainer {
19+
display: flex;
20+
align-items: flex-start;
21+
gap: var(--space-2);
22+
justify-content: center;
23+
margin-bottom: 5rem;
24+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import type { Meta, StoryObj } from '@storybook/react-vite';
2+
3+
import LandingPage from './Landing';
4+
5+
const meta: Meta<typeof LandingPage> = {
6+
title: 'Page/landing',
7+
component: LandingPage,
8+
tags: ['autodocs'],
9+
};
10+
11+
export default meta;
12+
type Story = StoryObj<typeof LandingPage>;
13+
14+
export const Default: Story = {
15+
render: () => <LandingPage />,
16+
};

frontend/src/pages/Landing/Landing.tsx

Lines changed: 70 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,83 @@
1+
import { Accordion } from '../../components';
12
import { ContentBlock } from '../../components/ContentBlock';
23
import { ContentBlockConfig } from '../../components/ContentBlock/constants';
34
import { LandingPageEmail } from '../../components/LandingPageEmail';
5+
import InputField from '../../components/InputField';
6+
import { INPUT_SIZES } from '../../components/InputField/InputField.types';
7+
import { Button } from '../../components/Button';
8+
import Footer from '../../components/Footer/Footer';
9+
import styles from './Landing.module.css';
410

511
const LandingPage = () => {
12+
const items = [
13+
{
14+
id: '1',
15+
title: 'What is Netflix?',
16+
content:
17+
'Netflix is a streaming service that offers a wide variety of award-winning TV shows, movies, anime, documentaries, and more on thousands of internet-connected devices.',
18+
},
19+
{
20+
id: '2',
21+
title: 'How much does Netflix cost?',
22+
content:
23+
'Watch Netflix on your smartphone, tablet, Smart TV, laptop, or streaming device, all for one fixed monthly fee.',
24+
},
25+
{
26+
id: '3',
27+
title: 'Where can I watch?',
28+
content:
29+
'Watch Netflix on your smartphone, tablet, Smart TV, laptop, or streaming device, all for one fixed monthly fee.',
30+
},
31+
{
32+
id: '4',
33+
title: 'How do I cancel?',
34+
content:
35+
'Watch Netflix on your smartphone, tablet, Smart TV, laptop, or streaming device, all for one fixed monthly fee.',
36+
},
37+
{
38+
id: '6',
39+
title: 'What can I watch on Netflix?',
40+
content:
41+
'Watch Netflix on your smartphone, tablet, Smart TV, laptop, or streaming device, all for one fixed monthly fee.',
42+
},
43+
{
44+
id: '7',
45+
title: 'Is Netflix good for kids??',
46+
content:
47+
'Watch Netflix on your smartphone, tablet, Smart TV, laptop, or streaming device, all for one fixed monthly fee.',
48+
},
49+
];
50+
const handleGetStarted = () => {
51+
console.log('Email submitted');
52+
};
653
return (
754
<>
855
<LandingPageEmail />
956
{ContentBlockConfig.map(({ headline, description, image, layout }) => (
10-
<ContentBlock
11-
key={headline}
12-
headline={headline}
13-
description={description}
14-
image={image}
15-
layout={layout}
16-
/>
57+
<>
58+
<ContentBlock
59+
key={headline}
60+
headline={headline}
61+
description={description}
62+
image={image}
63+
layout={layout}
64+
/>
65+
</>
1766
))}
67+
<div id="faq" className={styles.accordion}>
68+
<h2>Frequently Asked Questions</h2>
69+
<Accordion items={items} />
70+
</div>
71+
<h5 className={styles.text}>
72+
Ready to watch? Enter your email to create or restart your membership.
73+
</h5>
74+
<div className={styles.emailContainer}>
75+
<InputField size={INPUT_SIZES.LARGE} />
76+
<Button size="large" icon="chevron" onClick={handleGetStarted}>
77+
Get Started
78+
</Button>
79+
</div>
80+
<Footer />
1881
</>
1982
);
2083
};

0 commit comments

Comments
 (0)