Roadmap to becoming a developer in 2022
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

154 lines
3.6 KiB

feat: user accounts functionality (#3813) * feat: integrate astro * chore: login popup design * chore: data-popup changed * refactor: github and google button * chore: signup page * chore: login popup design * chore: signup page design * chore: auth divider * feat: integrate astro * chore: login popup design * chore: data-popup changed * refactor: github and google button * chore: signup page * chore: login popup design * chore: signup page design * chore: auth divider * chore: login feature * chore: login error message * chore: added name in token decode return * chore: use auth hook * chore: logout vs login * chore: download button link * chore: account dropdown * fix: dropdown z index * chore: profile page * Add missing content for backend roadmap * Remove unused styles * Add login with google * chore: google login implementation * chore: profile guard clause * fix: button size * chore: preact to astro components * chore: preact to astro comp * chore: github astro component * chore: google login error handling * chore: github login error handling * chore: change password page * chore: rename profile to password * fix: change password rename * chore: update profile page * chore: setting sidebar * fix: setting dropdown design * chore: required indicator * chore: change password form * chore: update profile form * chore: mobile navigation * fix: form data empty error * chore: email login and signup components * chore: forgot password page * chore: reset password page * chore: verify account page * chore: resend verification email * fix: types in spinner * chore: forgot password functionality * fix: class -> className * chore: reset password page * chore: reset password functionality * chore: login page * fix: spacing for login and signup page * refactor: email login form * chore: astro spinner * chore: pre-fill user data * chore: dummy placeholder * chore: forgot password link add * fix: replaced constants * chore: forgot password link * chore: change password for social provider * chore: internal pages guard * chore: internal paths * refactor: change password errors * refactor: update profile errors * chore: mark as done overlay * fix: uncontrolled to controlled form * fix: de-structure error * chore: error messages * fix: 401 error code redirect to login page * chore: loading spinner accessibilities * fix: remove spinner * chore: keep spinner after success to redirect * chore: keep the spinner * style: resend email underline * chore: chevron down account * chore: roadmap pdf link download * chore: roadmap pdf link download * chore: best practices buttons * fix: verify account text * fix: topic overlay hide * chore: base verify design * chore: email verify page * fix: div tag missing * Formatting * Refactor top navigation * Prettier * Update dependencies * Refactor top navigation * Refactor login button * Remove captcha and add google scripts * Refactor email sign up form * Resend verfication email functionality * Refactor verification pending page * Add verify account functionality * Update signup text * Add login page * Add login button in top nav * Email login form * Handle authenticatoin * Show hide auth elements change * Add ease-in on the guest elements * Refactor logic for download and subscribe popups * Add forgot password * Rename fetch lib * Add authentication popup * Refactor logic for mark done and pending * Handle logout * Add route protection * Popup opener to close the overlay * Remember page when logging in * Add reset password page * Change placement of constant * Update profile page * Add update password form * Update password page * Update profile page * Update design * chore: toggle mark resource done api * chore: toggle topic done * chore: get user resource progress api * fix: best practice topic toggle * chore: fetch progress * fix: query selector for topics * Keep track of the old page before social login * Update public api url * Add user progress tracking * Update topic done functionality * Add progress loader * Add page wide spinner * Add spinner on setting pages * Add fingerprint to user requests * Use http wrapper instead of fetch * Update fingerprint * Minor improvements --------- Co-authored-by: Arik Chakma <arikchangma@gmail.com>
2 years ago
import Cookies from 'js-cookie';
import fp from '@fingerprintjs/fingerprintjs';
import { TOKEN_COOKIE_NAME } from './jwt';
type HttpOptionsType = RequestInit | { headers: Record<string, any> };
type AppResponse = Record<string, any>;
type FetchError = {
status: number;
message: string;
};
type AppError = {
status: number;
message: string;
errors?: { message: string; location: string }[];
};
type ApiReturn<ResponseType, ErrorType> = {
response?: ResponseType;
error?: ErrorType | FetchError;
};
/**
* Wrapper around fetch to make it easy to handle errors
*
* @param url
* @param options
*/
export async function httpCall<
ResponseType = AppResponse,
ErrorType = AppError
>(
url: string,
options?: HttpOptionsType
): Promise<ApiReturn<ResponseType, ErrorType>> {
try {
const fingerprintPromise = await fp.load({ monitoring: false });
const fingerprint = await fingerprintPromise.get();
const response = await fetch(url, {
credentials: 'include',
...options,
headers: new Headers({
'Content-Type': 'application/json',
Accept: 'application/json',
Authorization: `Bearer ${Cookies.get(TOKEN_COOKIE_NAME)}`,
'fp': fingerprint.visitorId,
...(options?.headers ?? {}),
}),
});
// @ts-ignore
const doesAcceptHtml = options?.headers?.['Accept'] === 'text/html';
const data = doesAcceptHtml ? await response.text() : await response.json();
if (response.ok) {
return {
response: data as ResponseType,
error: undefined,
};
}
// Logout user if token is invalid
if (data.status === 401) {
Cookies.remove(TOKEN_COOKIE_NAME);
window.location.reload();
}
return {
response: undefined,
error: data as ErrorType,
};
} catch (error: any) {
return {
response: undefined,
error: {
status: 0,
message: error.message,
},
};
}
}
export async function httpPost<
ResponseType = AppResponse,
ErrorType = AppError
>(
url: string,
body: Record<string, any>,
options?: HttpOptionsType
): Promise<ApiReturn<ResponseType, ErrorType>> {
return httpCall<ResponseType, ErrorType>(url, {
...options,
method: 'POST',
body: JSON.stringify(body),
});
}
export async function httpGet<ResponseType = AppResponse, ErrorType = AppError>(
url: string,
queryParams?: Record<string, any>,
options?: HttpOptionsType
): Promise<ApiReturn<ResponseType, ErrorType>> {
const searchParams = new URLSearchParams(queryParams).toString();
const queryUrl = searchParams ? `${url}?${searchParams}` : url;
return httpCall<ResponseType, ErrorType>(queryUrl, {
credentials: 'include',
method: 'GET',
...options,
});
}
export async function httpPatch<
ResponseType = AppResponse,
ErrorType = AppError
>(
url: string,
body: Record<string, any>,
options?: HttpOptionsType
): Promise<ApiReturn<ResponseType, ErrorType>> {
return httpCall<ResponseType, ErrorType>(url, {
...options,
method: 'PATCH',
body: JSON.stringify(body),
});
}
export async function httpPut<ResponseType = AppResponse, ErrorType = AppError>(
url: string,
body: Record<string, any>,
options?: HttpOptionsType
): Promise<ApiReturn<ResponseType, ErrorType>> {
return httpCall<ResponseType, ErrorType>(url, {
...options,
method: 'PUT',
body: JSON.stringify(body),
});
}
export async function httpDelete<
ResponseType = AppResponse,
ErrorType = AppError
>(
url: string,
options?: HttpOptionsType
): Promise<ApiReturn<ResponseType, ErrorType>> {
return httpCall<ResponseType, ErrorType>(url, {
...options,
method: 'DELETE',
});
}