-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathhome.js
262 lines (224 loc) · 10.5 KB
/
home.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
const faq = document.querySelector(".questions");
const header = document.querySelector(".primary-header");
const hero = document.querySelector(".hero");
const popularMovies = document.querySelector(".anime");
const signInForm = document.querySelector("[data-sign-in]");
const signUpForm = document.querySelector("[data-sign-up]");
const signInBtn = document.querySelector(".sign-in");
const signUpBtn = document.querySelector(".sign-up");
const signUpCard = document.querySelector(".signup-form");
const signInCard = document.querySelector(".signin-form");
const overlay = document.querySelector(".form-overlay");
const signInOverlay = document.querySelector(".sign-in-overlay");
const errorMessage = document.querySelector(".error");
const successMessage = document.querySelector(".success");
// question accordian
faq.addEventListener("click", e => {
if (
e.target.classList.contains("question-title") ||
e.target.classList.contains("arrow")
) {
const parent = e.target.closest(".question");
const info = parent.querySelector(".info");
const rotate = parent.querySelector(".arrow");
info.classList.toggle("hidden");
rotate.classList.toggle("rotate");
}
});
// fixed nav intersection observer
const navFixed = entries => {
// entries gives an array so i used destructuring to get a single entry so that the function can work right.
const [entry] = entries;
// it will run at least once the moment it is observer is initialized so i put the a check in place.
if (!entry.isIntersecting) {
header.classList.add("fixed");
// If you scroll down past the 1st section the form becomes absolute meaning you wont have access to other inputs because you can't scroll further so i made the sign in/sign up forms only available in the 1st section where you can scroll to at least get the last few inputs without leaving the the 1st section where observer won't be intersecting resulting in hidding the elements.
// Sign In Form
signInCard.classList.add("hidden");
signInCard.classList.remove("animate");
signInOverlay.classList.add("hidden");
// Sign Up Form
signUpCard.classList.add("hidden");
signUpCard.classList.remove("animate");
overlay.classList.add("hidden");
} else {
header.classList.remove("fixed");
}
};
const observer = new IntersectionObserver(navFixed, {
root: null,
threshold: 0,
});
observer.observe(hero);
/* =============================
GET MOVIES
============================== */
const roundedOff = score => score.toFixed(1);
const getMovies = async () => {
const URL = "https://api.jikan.moe/v3/top/anime/1/movie";
const response = await fetch(URL);
if (!response.ok) return;
try {
const data = await response.json();
const movies = data.top.slice(0, 4);
movies.forEach(movieCardTemplate);
} catch (e) {
console.error(e);
}
};
const movieCardTemplate = show => {
const { image_url, mal_id, title, score } = show;
const rating = roundedOff(score);
const card = `
<div class="anime-card flow-content">
<div class="image">
<a href="#">
<svg class="heart" width="21" height="21" viewBox="0 0 21 21" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M16.3531 10.5C13.8063 10.5 11.7063 12.5553 11.7063 15.1468C11.7063 17.6936 13.7616 19.7936 16.3531 19.7936C18.9446 19.7936 20.9999 17.7383 20.9999 15.1468C20.9999 12.5553 18.9446 10.5 16.3531 10.5ZM18.8106 15.817H17.2467C17.1127 15.817 17.0233 15.9064 17.0233 16.0404V17.6043C17.0233 17.9617 16.7106 18.2745 16.3531 18.2745C15.9957 18.2745 15.6829 17.9617 15.6829 17.6043V16.0404C15.6829 15.9064 15.5935 15.817 15.4595 15.817H13.8957C13.5382 15.817 13.2254 15.5043 13.2254 15.1468C13.2254 14.7894 13.5382 14.4766 13.8957 14.4766H15.4595C15.5935 14.4766 15.6829 14.3872 15.6829 14.2532V12.6894C15.6829 12.3319 15.9957 12.0191 16.3531 12.0191C16.7106 12.0191 17.0233 12.3319 17.0233 12.6894V14.2532C17.0233 14.3872 17.1127 14.4766 17.2467 14.4766H18.8106C19.168 14.4766 19.4808 14.7894 19.4808 15.1468C19.4808 15.5043 19.2127 15.817 18.8106 15.817Z" fill="#FFD9D9"/>
<path d="M10.4106 14.566C10.6787 11.8851 12.734 9.69575 15.3702 9.24894C16.9787 8.98085 18.4979 9.38298 19.7043 10.1872C19.7489 10.2319 19.8383 10.1872 19.8383 10.1426C20.5532 8.53404 20.9553 7.10426 20.9553 6.0766C20.9553 2.72553 18.4979 0 15.5043 0C13.5383 0 11.7064 1.20638 10.7681 3.0383C10.6787 3.17234 10.4553 3.17234 10.4106 3.0383C9.42766 1.20638 7.64043 0 5.58511 0C2.50213 0 0 2.77021 0 6.21064C0 9.74043 3.84255 16.2191 10.2766 20.9106C10.366 20.9553 10.4106 21 10.5 21C10.5894 21 10.634 21 10.7234 20.9553C11.3043 20.5979 11.8404 20.1957 12.3766 19.7489C12.4213 19.7043 12.4213 19.6149 12.3766 19.5702C10.9915 18.3638 10.2319 16.5319 10.4106 14.566Z" fill="#FFD9D9"/>
</svg>
<img class="poster" height="318" width="224" src="${image_url}" alt="${title} anime image" loading="lazy">
</a>
</div>
<div class="info">
<h3 class="title">
<a class="name" href="#" data-id="${mal_id}">${title}</a>
</h3>
<div class="rating">
<p>${rating}</p>
<svg class="star" width="21" height="21" xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" viewBox="0 0 20 20" fill="#ffdbdb">
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" />
</svg>
</div>
</div>
</div>
`;
popularMovies.innerHTML += card;
};
getMovies();
// Form Validation
// Sign Up Button
signUpBtn.addEventListener("click", () => {
// Reset the other sign in for incase a user doesnt exit this on properly and goes straight to clicking it
signInOverlay.classList.add("hidden");
signInCard.classList.add("hidden");
signInCard.classList.remove("animate");
signUpCard.classList.toggle("hidden");
overlay.classList.toggle("hidden");
signUpCard.classList.toggle("animate");
});
// Sign In Button
signInBtn.addEventListener("click", () => {
// Reset the other sign up for incase a user doesnt exit this on properly and goes straight to clicking it
overlay.classList.add("hidden");
signUpCard.classList.add("hidden");
signUpCard.classList.remove("animate");
signInCard.classList.toggle("hidden");
signInOverlay.classList.toggle("hidden");
signInCard.classList.toggle("animate");
});
overlay.addEventListener("click", e => {
if (!e.target.classList.contains("form-overlay")) return;
signUpCard.classList.add("hidden");
overlay.classList.add("hidden");
signUpCard.classList.remove("animate");
});
signInOverlay.addEventListener("click", e => {
if (!e.target.classList.contains("sign-in-overlay")) return;
signInCard.classList.add("hidden");
signInOverlay.classList.add("hidden");
signInCard.classList.remove("animate");
});
signInForm.addEventListener("submit", e => {
e.preventDefault();
const username = signInForm.username.value.trim();
const password = signInForm.password.value.trim();
const usernameError = document.querySelector("[data-username-error]");
const passwordError = document.querySelector("[data-password-error]");
const usernameRegex = /^[a-zA-Z0-9]{7,20}$/;
const passwordRegex = /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$/;
// Username Validation
if (!usernameRegex.test(username)) {
usernameError.textContent = "Username doesn't exist";
usernameError.classList.remove("hidden");
} else {
usernameError.classList.add("hidden");
}
// Password Validation
if (!passwordRegex.test(password)) {
passwordError.textContent = "Password you've entered is invalid";
passwordError.classList.remove("hidden");
} else {
passwordError.classList.add("hidden");
}
if (usernameRegex.test(username) && passwordRegex.test(password)) {
successMessage.textContent = "You've logged in successfully";
successMessage.classList.remove("hidden");
setTimeout(() => {
successMessage.classList.add("hidden");
signInCard.classList.add("hidden");
signInCard.classList.remove("animate");
signInOverlay.classList.add("hidden");
signInForm.reset();
}, 1500);
}
});
signUpForm.addEventListener("submit", e => {
e.preventDefault();
const username = signUpForm.username.value.trim();
const email = signUpForm.email.value.trim();
const password = signUpForm.password.value.trim();
const confirmPassword = signUpForm.confirmedPassword.value.trim();
const checkbox = signUpForm.checkbox.checked;
const emailRegex = /\S+@\S+\.\S+/;
const usernameRegex = /^[a-zA-Z0-9]{7,20}$/;
const passwordRegex = /^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$/;
let message = [];
// Username Validation
if (!usernameRegex.test(username))
message.push("Username must be a minimum 7 characters");
// Email Validation
if (!emailRegex.test(email)) message.push("Email is not valid");
// Password Validation
if (!passwordRegex.test(password))
message.push(
"Password must be a minimum 8 characters, at least 1 letter and 1 number"
);
// Confirm Password Validation
if (!passwordRegex.test(confirmPassword)) {
message.push(
"Password must be a minimum 8 characters, at least 1 letter and 1 number"
);
} else if (password !== confirmPassword) {
message.push("Passwords don't match");
} else {
console.log("passwords matched");
}
// Checkbox Validation
if (!checkbox) message.push("Please accept our Terms and Conditions"); // checkbox works
errorMessage.innerText = message.join(", ");
if (
!usernameRegex.test(username) ||
!emailRegex.test(email) ||
!passwordRegex.test(password) ||
!passwordRegex.test(confirmPassword) ||
password !== confirmPassword ||
!checkbox
) {
errorMessage.classList.remove("success");
errorMessage.classList.remove("hidden");
} else {
errorMessage.textContent =
"You have successfully signed up to Animestudio+";
errorMessage.classList.add("success");
errorMessage.classList.remove("hidden");
setTimeout(() => {
errorMessage.classList.add("hidden");
signUpCard.classList.add("hidden");
signUpCard.classList.remove("animate");
overlay.classList.add("hidden");
errorMessage.classList.remove("success");
signUpForm.reset();
}, 1500);
}
});