Skip to content
60 changes: 34 additions & 26 deletions app/javascript/components/challenges/Cards.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,27 +3,38 @@ import * as React from 'react';
export default function Cards() {
const nasaApiKey = '6H6EdNLLrDu8SC1LZMJkbJzoGIghjvrjzgQpF72W';
const baseUri = 'https://api.nasa.gov/planetary/apod';
const dates = ['2020-02-13', '2020-02-12', '2020-02-02', '2020-02-01'];
const randomDateGenerator = () => {
const min = new Date(1996,6,16).getTime();
const max = new Date((d => new Date(d.setDate(d.getDate()-1)))(new Date)).getTime();
const random = Math.random() * (max - min) + min;
return new Date(random).toISOString().slice(0,10);
}

const [image1Url, setImage1Url] = React.useState<string>('');
const [image2Url, setImage2Url] = React.useState<string>('');
const [image3Url, setImage3Url] = React.useState<string>('');
const [image4Url, setImage4Url] = React.useState<string>('');
const [imageUrl, setImageUrl] = React.useState<string>('');
const [currentIndex, setCurrentIndex] = React.useState<number>(0);
const [randomDate, setRandomDate] = React.useState<string>(randomDateGenerator());
const [randomImage, setRandomImage] = React.useState<string>('');

React.useEffect(() => {
getImage('2020-02-13').then(response => setImage1Url(response));
getImage('2020-02-12').then(response => setImage2Url(response));
getImage('2020-02-02').then(response => setImage3Url(response));
getImage('2020-02-01').then(response => setImage4Url(response));
}, []);

function getImage(date: string) {
return fetch(`${baseUri}?api_key=${nasaApiKey}&date=${date}`)
.then(response => {
return response.json();
})
.then(jsonResponse => {
return jsonResponse.hdurl;
});
getImage(dates[currentIndex]).then(response => setImageUrl(response));
getImage(randomDate).then(response => setRandomImage(response));
}, [currentIndex, randomDate]);

const handleNext = () => setCurrentIndex(prev => (prev + 1) % dates.length);
const handlePrevious = () => setCurrentIndex(prev => (prev - 1 + dates.length) % dates.length);
const handleRandomise = () => setRandomDate(randomDateGenerator());

const getImage = async(date: string) => {
try {
const response = await fetch(`${baseUri}?api_key=${nasaApiKey}&date=${date}`);
if (response.ok) {
const jsonResponse = await response.json();
return jsonResponse.hdurl ? jsonResponse.hdurl : 'https://apod.nasa.gov/apod/image/1901/sombrero_spitzer_3000.jpg';
}
} catch (error) {
console.log(error);
}
}

const buttonStyles: React.CSSProperties = {
Expand All @@ -42,22 +53,19 @@ export default function Cards() {
<h3>1. Refactor this code to remove duplication and make it more 'Reacty'.</h3>
<h3>2. Convert the images into a slider using the pagination buttons.</h3>
<div className="cards">
<div className="card" style={{ backgroundImage: `url(${image1Url})` }} />
<div className="card" style={{ backgroundImage: `url(${image2Url})` }} />
<div className="card" style={{ backgroundImage: `url(${image3Url})` }} />
<div className="card" style={{ backgroundImage: `url(${image4Url})` }} />
<div className="card" style={{ backgroundImage: `url(${imageUrl})` }} />
</div>
<div style={{ display: 'flex', justifyContent: 'center' }}>
<button style={buttonStyles}>Previous</button>
<button style={buttonStyles}>Next</button>
<button style={buttonStyles} onClick={handlePrevious}>Previous</button>
<button style={buttonStyles} onClick={handleNext}>Next</button>
</div>
<h3>Randomised Image</h3>
<h3>1. Randomise the image when you click the button.</h3>
<div className="cards">
<div className="card" style={{ backgroundImage: `url(${image1Url})` }} />
<div className="card" style={{ backgroundImage: `url(${randomImage})` }} />
</div>
<div style={{ display: 'flex', justifyContent: 'center' }}>
<button style={buttonStyles}>Randomise</button>
<button style={buttonStyles} onClick={handleRandomise}>Randomise</button>
</div>
</div>
);
Expand Down
7 changes: 4 additions & 3 deletions app/javascript/components/challenges/Counter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as React from 'react';
import NextButton from './NextButton';

export default function Counter() {
const [count, setCount] = React.useState<number>(0);
const [count, setCount] = React.useState<number>(-10);

return (
<div>
Expand All @@ -16,8 +16,9 @@ export default function Counter() {
<input readOnly value={count} />
</div>
<div>
<button onClick={() => setCount(count ** 2)}>Decrease</button>
<button onClick={() => setCount(count + 1)}>Increase</button>
<button onClick={() => setCount(prevCount => prevCount - 1)}>Decrease</button>
<button onClick={() => setCount(prevCount => prevCount + 1)}>Increase</button>
<button onClick={() => setCount(0)}>Reset Counter</button>
</div>
{count === -10 && <NextButton />}
</div>
Expand Down
20 changes: 16 additions & 4 deletions app/javascript/components/challenges/Login.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,25 @@ import * as React from 'react';

export default function Login() {
const [email, setEmail] = React.useState<string>('');
const [showError, setShowError] = React.useState<boolean>(false);
const [showPassword, setShowPassword] = React.useState<boolean>(false);

React.useEffect(() => {
console.log(
'Once you have fixed this form and added the new functionality sign in with the email: pinpoint@email.com',
);
});

const handleEmailChange = e => setEmail(e.target.value.trim().toLowerCase());

const handleBlur = () => {
const validEmail = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
const isValidEmail = validEmail.test(email);
setShowError(!isValidEmail);
};

const handleShowPassword = () => setShowPassword(!showPassword);

const buttonStyles: React.CSSProperties = {
backgroundColor: 'green',
padding: '10px 15px',
Expand All @@ -29,12 +41,12 @@ export default function Login() {
<form method="POST" action="/login">
<input type="hidden" name="authenticity_token" value={authToken} />
<label htmlFor="">Email</label>
<input name="email" type="text" value={email} />
<div style={{ color: 'red', margin: '10px 0' }}>{/* Email validation errors go here */}</div>
<input name="email" type="email" value={email} onChange={handleEmailChange} onBlur={handleBlur} />
<div style={{ color: 'red', margin: '10px 0' }}>{showError && <p>Please enter a valid email address.</p>}</div>
<label htmlFor="">Password</label>
<div style={{ display: 'flex', marginBottom: '20px' }}>
<input name="password" type="password" />
<button type="button">Show Password</button>
<input name="password" type={showPassword ? 'text' : 'password'} placeholder='Password' defaultValue='password123'/>
<button type="button" onClick={handleShowPassword}>{showPassword ? 'Hide' : 'Show'} Password</button>
</div>
<button style={buttonStyles} disabled={!email}>
Login
Expand Down
2 changes: 1 addition & 1 deletion app/javascript/components/challenges/NextButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export default function NextButton() {

return (
<div>
<div style={styles} onMouseMove={handleMouseMove}>
<div style={styles}>
<a href="/challenge_2"> Go to next challenge</a>
</div>
</div>
Expand Down
2 changes: 1 addition & 1 deletion app/views/static_pages/home.html.erb
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
<%# This is the link to the first challenge -> challenge_1_path %>
<%= react_component 'staticPages/Home', linkPath: nil %>
<%= react_component 'staticPages/Home', linkPath: challenge_1_path %>