Skip to content

Commit 21dc3d0

Browse files
Update directory structure
1 parent b75db4b commit 21dc3d0

File tree

4 files changed

+334
-1
lines changed

4 files changed

+334
-1
lines changed

src/App.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import React from "react";
22
import "./App.scss";
33
import { Link, Route, BrowserRouter as Router, Routes } from "react-router";
4-
import ProfilePage from "./Components/ProfilePage";
54
import PhotoOfTheDay from "./Components/photoOfTheDay/photoOfTheDay";
5+
import ProfilePage from "./pages/Profile/ProfilePage";
66

77
function App() {
88
return (

src/pages/Profile/ProfilePage.scss

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
@import '../Styles/GlobalStyles.scss';
2+
3+
4+
body {
5+
background-color: $blueBackground;
6+
color: $whiteFontColor;
7+
font-family: $PublicSans;
8+
}
9+
10+
11+
.input-field{
12+
display: flex;
13+
justify-content: center;
14+
align-items: center;
15+
p{
16+
width: 50px;
17+
margin-right: 20px;
18+
}
19+
}
20+
21+
.profile-button-image{
22+
width: 100px;
23+
height: 100px;
24+
}
25+
26+
#build-your-profile-button-text{
27+
margin-top: 0;
28+
}
29+
30+
.pop-up-profile-section{
31+
display: flex;
32+
flex-direction: column;
33+
background-color: #EE8434;
34+
width: 80%;
35+
justify-self: center;
36+
justify-content: center;
37+
font-family: $MartianMono;
38+
#profile-astronaut-picture{
39+
width: 200px;
40+
height: auto;
41+
border: black 3px solid;
42+
// float: right;
43+
// margin-right: 20px;
44+
}
45+
}
46+
47+
.profile-information{
48+
line-height: 25px;
49+
display: block;
50+
// flex-direction: row;
51+
// justify-content: space-between;
52+
}
53+
.side-by-side-information{
54+
display: flex;
55+
justify-content: space-between;
56+
margin-bottom: 30px;
57+
margin-top: 30px;
58+
margin-left: 50px;
59+
margin-right: 50px;
60+
}
61+
62+
.name-and-age-profile{}
63+
64+
.profile-fun-facts{
65+
margin-left: 20px;
66+
margin-right: 20px;
67+
}
68+
69+
.profile-rover-photos{
70+
width: 50%;
71+
height: auto;
72+
justify-content: center;
73+
margin: 0 auto;
74+
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import "@testing-library/jest-dom";
2+
import ProfilePage from "./ProfilePage";
3+
import { render, screen, fireEvent, waitFor } from "@testing-library/react";
4+
import React from "react";
5+
6+
describe("ProfilePage", () => {
7+
it("renders the name input", () => {
8+
render(<ProfilePage />);
9+
const nameInputField = screen.getByLabelText(/Name:/i);
10+
fireEvent.change(nameInputField, { target: { value: "Beth" } });
11+
fireEvent.click(screen.getByAltText(/clickable button of mars/i));
12+
expect(screen.getByText(/Beth/)).toBeInTheDocument();
13+
});
14+
15+
it("allows user to select birthday", () => {
16+
render(<ProfilePage />);
17+
const datePicker = screen.getByPlaceholderText("Select your birthday");
18+
fireEvent.change(datePicker, { target: { value: "12/03/2016" } });
19+
fireEvent.click(screen.getByAltText(/clickable button of mars/i));
20+
expect(
21+
screen.getByText(/Welcome to your Mars profile/),
22+
).toBeInTheDocument();
23+
});
24+
25+
it("displays pop-up profile after clicking Mars button", async () => {
26+
render(<ProfilePage />);
27+
const nameInputField = screen.getByLabelText(/Name:/i);
28+
fireEvent.change(nameInputField, { target: { value: "Beth" } });
29+
const datePicker = screen.getByPlaceholderText("Select your birthday");
30+
fireEvent.change(datePicker, { target: { value: "12/03/2016" } });
31+
expect(
32+
screen.queryByText(/Welcome to your Mars profile/i),
33+
).not.toBeInTheDocument();
34+
fireEvent.click(screen.getByAltText(/clickable button of mars/i));
35+
await waitFor(() =>
36+
expect(
37+
screen.getByText(/Welcome to your Mars profile/),
38+
).toBeInTheDocument(),
39+
);
40+
expect(screen.getByText(/Age on Earth:/)).toBeInTheDocument();
41+
expect(screen.getByText(/Age on Mars:/)).toBeInTheDocument();
42+
});
43+
44+
it("displays error message and images for birthdays before the Curiosity's launch date", async () => {
45+
render(<ProfilePage />);
46+
const datePicker = screen.getByPlaceholderText("Select your birthday");
47+
fireEvent.change(datePicker, { target: { value: "12/03/2010" } });
48+
fireEvent.click(screen.getByAltText(/clickable button of mars/i));
49+
await waitFor(() =>
50+
expect(
51+
screen.getByText(/Uh Oh! You're older than the Curiosity Rover/i),
52+
).toBeInTheDocument(),
53+
);
54+
});
55+
56+
it("displays rover photos when API returns images", async () => {
57+
const mockRoverPhotos = {
58+
photos: [
59+
{
60+
img_src:
61+
"http://mars.jpl.nasa.gov/msl-raw-images/proj/msl/redops/ods/surface/sol/01004/opgs/edr/fcam/FLB_486615455EDR_F0481570FHAZ00323M_.JPG",
62+
},
63+
],
64+
};
65+
global.fetch = jest.fn().mockResolvedValue({
66+
json: jest.fn().mockResolvedValue(mockRoverPhotos),
67+
});
68+
render(<ProfilePage />);
69+
const datePicker = screen.getByPlaceholderText("Select your birthday");
70+
fireEvent.change(datePicker, { target: { value: "03/06/2015" } });
71+
fireEvent.click(screen.getByAltText(/clickable button of mars/i));
72+
73+
const images = (await screen.findAllByAltText(
74+
/Mars/,
75+
)) as HTMLImageElement[];
76+
expect(images.length).toBeGreaterThan(0);
77+
const image = images[0] as HTMLImageElement;
78+
79+
expect(image.src).toContain("nasa.gov");
80+
});
81+
});

src/pages/Profile/ProfilePage.tsx

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
import React from "react";
2+
import { useState } from "react";
3+
import DatePicker from "react-datepicker";
4+
import "react-datepicker/dist/react-datepicker.css";
5+
import dayjs from "dayjs";
6+
import "./profilePage.scss";
7+
import "slick-carousel/slick/slick.css";
8+
import "slick-carousel/slick/slick-theme.css";
9+
import Slider from "react-slick";
10+
11+
const API_KEY = "qUubKrhKBBrb0M4uQISHm089PavbKEcLW3v7tgiP";
12+
13+
export default function ProfilePage() {
14+
const [name, setName] = useState<string>("");
15+
const [date, setDate] = useState<Date | null>(new Date());
16+
const [showProfile, setShowProfile] = useState<boolean>(false);
17+
const [roverPhotoUrls, setRoverPhotoUrls] = useState<string[]>([]);
18+
const [message, setMessage] = useState<string>(
19+
"These are the photos taken by the 'Curiosity' Rover on your birthday!",
20+
);
21+
const curiosityStartDate = new Date("2012-08-06");
22+
const settings = {
23+
dots: false,
24+
infinite: false,
25+
speed: 500,
26+
slidesToShow: 1,
27+
slidesToScroll: 1,
28+
};
29+
30+
const handleClick = () => {
31+
setShowProfile(true);
32+
getRoverPhotos().then((roverPhotos) => setRoverPhotoUrls(roverPhotos));
33+
};
34+
35+
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
36+
setName(event.target.value);
37+
};
38+
39+
const calculateAge = (date: Date) => {
40+
const today = new Date();
41+
let age = today.getFullYear() - date.getFullYear();
42+
43+
const m = today.getMonth() - date.getMonth();
44+
if (m < 0 || (m === 0 && today.getDate() < date.getDate())) {
45+
age--;
46+
}
47+
return age;
48+
};
49+
const age = date ? calculateAge(date) : 0;
50+
const marsAge = Math.round(age / 1.88);
51+
52+
async function getRoverPhotos(): Promise<string[]> {
53+
let earthDate = dayjs(date).format("YYYY-M-D");
54+
if (date && date < curiosityStartDate) {
55+
earthDate = dayjs(curiosityStartDate).format("YYYY-M-D");
56+
57+
setMessage(
58+
"Uh Oh! You're older than the Curiosity Rover, so there are no photos available. Here are the first images taken by the Curiosity Rover.",
59+
);
60+
} else {
61+
earthDate = dayjs(date).format("YYYY-M-D");
62+
}
63+
const fetchImages = await fetch(
64+
`https://api.nasa.gov/mars-photos/api/v1/rovers/curiosity/photos?earth_date=${earthDate}&api_key=${API_KEY}`,
65+
);
66+
const imagesData = await fetchImages.json();
67+
const roverPhotos = [];
68+
const roverPhotoCarouselLength = Math.min(imagesData.photos.length, 25);
69+
if (imagesData.photos.length !== 0) {
70+
for (let i = 0; i < roverPhotoCarouselLength; i++)
71+
roverPhotos.push(imagesData.photos[i].img_src);
72+
} else {
73+
setMessage(
74+
"The date of the first pictures taken by the Curiosity Rover is 06/08/2012",
75+
);
76+
}
77+
return roverPhotos;
78+
}
79+
80+
return (
81+
<div className="mars-profile-page">
82+
<div className="profile-input-section">
83+
<h1>Create your Mars profile</h1>
84+
<label className="input-field" htmlFor="name">
85+
<p>Name: </p>
86+
<input
87+
id="name"
88+
type="text"
89+
name="name"
90+
onChange={handleChange}
91+
placeholder="Enter your name here"
92+
required
93+
></input>
94+
</label>
95+
96+
<label className="input-field">
97+
<p>Birthday: </p>
98+
<DatePicker
99+
selected={date}
100+
onChange={(date) => setDate(date)}
101+
dateFormat="dd/MM/yyyy"
102+
maxDate={new Date()}
103+
showYearDropdown
104+
scrollableMonthYearDropdown
105+
placeholderText="Select your birthday"
106+
/>
107+
</label>
108+
<img
109+
className="profile-button-image"
110+
onClick={handleClick}
111+
src="https://www.pngall.com/wp-content/uploads/13/Mars-Planet-PNG-Cutout.png"
112+
alt="clickable button of mars"
113+
/>
114+
<p id="build-your-profile-button-text">
115+
Click on Mars to build your profile!
116+
</p>
117+
</div>
118+
{showProfile && (
119+
<div className="pop-up-profile-section">
120+
<div className="profile-information">
121+
<h2>Welcome to your Mars profile</h2>
122+
<div className="side-by-side-information">
123+
<div className="name-and-age-profile">
124+
<h3>
125+
<strong>Name:</strong> {name}
126+
</h3>
127+
<h3>
128+
<strong>Age on Earth:</strong> {age}
129+
</h3>
130+
<h3>
131+
<strong>Age on Mars:</strong> {marsAge}
132+
</h3>
133+
</div>
134+
<img
135+
id="profile-astronaut-picture"
136+
alt="astronaut"
137+
src="https://static.vecteezy.com/system/resources/previews/010/938/481/original/cute-astronaut-floating-space-cartoon-vector.jpg"
138+
/>
139+
</div>
140+
</div>
141+
142+
<div className="profile-fun-facts">
143+
<p>
144+
Did you know you would weigh 2.5x less on Mars? This is because
145+
the gravity is weaker on Mars than on Earth as it is smaller!
146+
</p>
147+
<p>
148+
On Earth you are <strong>{age} years old </strong>, but on Mars
149+
you would only be <strong>{marsAge} years old.</strong> This is
150+
because 1 year on Mars is roughly twice that on Earth.
151+
</p>
152+
</div>
153+
154+
<div className="profile-rover-photos">
155+
<Slider {...settings}>
156+
{roverPhotoUrls.length === 0 ? (
157+
<p>
158+
Sorry there are no available photos on your birthday, try a
159+
different day.
160+
</p>
161+
) : (
162+
roverPhotoUrls.map((photo: string, index) => (
163+
<img
164+
className="rover-images-from-API"
165+
src={photo}
166+
key={index}
167+
alt="Mars"
168+
/>
169+
))
170+
)}
171+
</Slider>
172+
<p>{message}</p>
173+
</div>
174+
</div>
175+
)}
176+
</div>
177+
);
178+
}

0 commit comments

Comments
 (0)