Skip to content

Commit 9fa83f2

Browse files
committed
feat: add necessary components and paths to fetch api from a form.
1 parent faf0f85 commit 9fa83f2

File tree

10 files changed

+252
-25
lines changed

10 files changed

+252
-25
lines changed
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
.button {
2+
border-radius: 10px;
3+
color: white;
4+
background-color: #f47d26;
5+
padding: 10px 20px;
6+
margin-left: auto;
7+
font-family: Poppins, sans-serif;
8+
font-size: 18px;
9+
cursor: pointer;
10+
border: none;
11+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import './Button.scss';
2+
3+
type ButtonProps = {
4+
label: string;
5+
onClick?: () => void;
6+
type?: 'button' | 'submit' | 'reset';
7+
className?: string;
8+
};
9+
10+
const Button = ({
11+
label,
12+
onClick,
13+
type = 'submit', // ← change default to 'submit'
14+
className = '',
15+
}: ButtonProps) => {
16+
return (
17+
<button type={type} onClick={onClick} className={`button ${className}`}>
18+
{label}
19+
</button>
20+
);
21+
};
22+
23+
export default Button;

lesson_27/JBey/src/components/header/Header.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import './Header.scss';
22
import logoImg from '@/assets/logo.png';
33
import * as React from 'react';
4+
import {Link} from 'react-router-dom';
45

56
export const Header: React.FC = () => {
67
return (
@@ -12,14 +13,17 @@ export const Header: React.FC = () => {
1213
</div>
1314
<ul className="header-top-menu">
1415
<li>
15-
<a href="#">Home</a>
16+
<a href="/">Home</a>
1617
</li>
1718
<li>
1819
<a href="#">About</a>
1920
</li>
2021
<li>
2122
<a href="#">Contact</a>
2223
</li>
24+
<li>
25+
<Link to="/new-program">New Programs</Link>
26+
</li>
2327
</ul>
2428
<div className="header-cta">
2529
<a className="sign-up-button" href="#">

lesson_27/JBey/src/main.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import App from './App.tsx';
22
import {Home} from './pages/Home/Home.tsx';
3+
import {NewFormAccepted} from './pages/NewForm/NewForm.tsx';
4+
import {NewProgram} from './pages/NewProgram/NewProgram.tsx';
35
import {QueryClient, QueryClientProvider} from '@tanstack/react-query';
6+
import React from 'react';
47
import ReactDOM from 'react-dom/client';
58
import {RouterProvider, createBrowserRouter} from 'react-router-dom';
69

@@ -17,6 +20,14 @@ const router = createBrowserRouter([
1720
path: '/',
1821
element: <Home />,
1922
},
23+
{
24+
path: '/new-program',
25+
element: <NewProgram />,
26+
},
27+
{
28+
path: `/form-accepted`,
29+
element: <NewFormAccepted />,
30+
},
2031
],
2132
},
2233
]);

lesson_27/JBey/src/pages/Home/components/ProgramList/ProgramList.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@
88
.program {
99
min-width: 100%;
1010
}
11-
}
11+
}

lesson_27/JBey/src/pages/Home/components/ProgramList/ProgramList.tsx

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,46 +3,42 @@ import {useEffect, useState} from 'react';
33

44
import {Program} from '../Program';
55

6-
// Define the shape of my program data
7-
interface ProgramData {
6+
type ProgramData = {
87
title: string;
98
description: string;
10-
}
9+
};
1110

1211
export const ProgramList: React.FC = () => {
1312
const [programs, setPrograms] = useState<ProgramData[]>([]);
14-
const [loading, setLoading] = useState(true);
1513

1614
useEffect(() => {
17-
// Replacing this with a real API call
18-
fetch('/api/programs')
15+
fetch('http://localhost:4000/programs')
1916
.then(response => {
20-
if (!response.ok) {
21-
throw new Error('Failed to fetch programs');
17+
if (response.ok) {
18+
return response.json();
19+
} else {
20+
return Promise.reject(new Error('Failed to load data'));
2221
}
23-
return response.json();
2422
})
2523
.then(data => {
2624
setPrograms(data);
27-
setLoading(false);
2825
})
2926
.catch(error => {
30-
console.error('Error fetching program data:', error);
31-
setLoading(false);
27+
console.error("Couldn't load data", error);
3228
});
3329
}, []);
3430

35-
if (loading) {
36-
return <p>Loading programs...</p>;
37-
}
38-
3931
return (
40-
<ul className="programs">
41-
{programs.map((program, index) => (
42-
<Program key={index} title={program.title}>
43-
<p>{program.description}</p>
44-
</Program>
45-
))}
46-
</ul>
32+
<>
33+
<ul className="programs">
34+
{programs.map((program, index) => (
35+
<li key={index} className="program">
36+
<Program title={program.title}>
37+
<p>{program.description}</p>
38+
</Program>
39+
</li>
40+
))}
41+
</ul>
42+
</>
4743
);
4844
};
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// NewForm.scss
2+
3+
.container {
4+
max-width: 800px;
5+
margin: 40px auto;
6+
padding: 20px;
7+
background-color: #f9f9f9;
8+
border: 1px solid #ddd;
9+
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
10+
}
11+
12+
.card {
13+
padding: 20px;
14+
background-color: #fff;
15+
border: 1px solid #ddd;
16+
border-radius: 10px;
17+
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
18+
}
19+
20+
h2 {
21+
font-size: 24px;
22+
margin-bottom: 10px;
23+
}
24+
25+
p {
26+
font-size: 18px;
27+
margin-bottom: 20px;
28+
}
29+
30+
.button {
31+
margin-top: 20px;
32+
}
33+
34+
/* Add any other styles you want to customize */
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import './NewForm.scss';
2+
import {Link} from 'react-router-dom';
3+
4+
import Button from '@/components/Button/Button';
5+
6+
export const NewFormAccepted = () => {
7+
return (
8+
<div className="container">
9+
<div className="card">
10+
<h2>Form Submitted!</h2>
11+
<p>Your form submission has been sent successfully.</p>
12+
<Link to="/">
13+
<Button label="Back to Home" />
14+
</Link>
15+
</div>
16+
</div>
17+
);
18+
};
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
.container {
2+
min-height: 100vh;
3+
display: flex;
4+
align-items: center;
5+
justify-content: center;
6+
padding: 0 40px;
7+
background-color: #f5f5f5;
8+
9+
.card {
10+
background-color: white;
11+
padding: 40px;
12+
border-radius: 12px;
13+
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.1);
14+
width: 100%;
15+
max-width: 600px;
16+
flex-direction: column;
17+
18+
h1 {
19+
color: rgb(68, 68, 68);
20+
font-weight: 900;
21+
font-size: 36px;
22+
font-family: Montserrat, sans-serif;
23+
}
24+
25+
.form {
26+
width: 100%;
27+
max-width: 600px;
28+
margin: 0 auto;
29+
display: flex;
30+
flex-direction: column;
31+
gap: 20px;
32+
33+
label {
34+
display: flex;
35+
flex-direction: column;
36+
font-weight: 700;
37+
font-family: Poppins, sans-serif;
38+
font-size: 22px;
39+
color: rgb(68, 68, 68);
40+
text-align: left;
41+
}
42+
43+
input,
44+
textarea {
45+
background-color: rgba(0, 0, 0, 0.04);
46+
color: rgb(60, 60, 60);
47+
padding: 12px 16px;
48+
font-size: 14px;
49+
border: none;
50+
border-radius: 4px;
51+
font-family: Poppins;
52+
text-transform: uppercase;
53+
margin-top: 8px;
54+
}
55+
56+
textarea {
57+
min-height: 120px;
58+
resize: vertical;
59+
}
60+
}
61+
}
62+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import './NewProgram.scss';
2+
import {useState} from 'react';
3+
import {useNavigate} from 'react-router-dom';
4+
5+
import Button from '@/components/Button/Button';
6+
7+
export const NewProgram = () => {
8+
const [title, setTitle] = useState('');
9+
const [description, setDescription] = useState('');
10+
const navigate = useNavigate();
11+
12+
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
13+
e.preventDefault();
14+
console.log('Submitting form...');
15+
const newProgram = {title, description};
16+
17+
try {
18+
const response = await fetch('http://localhost:4000/programs', {
19+
method: 'POST',
20+
headers: {
21+
'Content-Type': 'application/json',
22+
},
23+
body: JSON.stringify(newProgram),
24+
});
25+
26+
if (!response.ok) {
27+
throw new Error('Failed to add program');
28+
}
29+
30+
console.log('Submitted:', {title, description});
31+
setTitle('');
32+
setDescription('');
33+
navigate('/form-accepted');
34+
} catch (error) {
35+
console.error('Error adding program:', error);
36+
}
37+
};
38+
39+
return (
40+
<div className="container">
41+
<div className="card">
42+
<h1>Add a new program:</h1>
43+
<form onSubmit={handleSubmit} className="form">
44+
<label>
45+
Title:
46+
<input
47+
id="title"
48+
type="text"
49+
value={title}
50+
onChange={e => setTitle(e.target.value)}
51+
required
52+
/>
53+
</label>
54+
<label>
55+
Description:
56+
<textarea
57+
id="content"
58+
value={description}
59+
onChange={e => setDescription(e.target.value)}
60+
required
61+
/>
62+
</label>
63+
<Button label="Submit" type="submit" />
64+
</form>
65+
</div>
66+
</div>
67+
);
68+
};

0 commit comments

Comments
 (0)