Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

19 10 2021 #13

Open
wants to merge 37 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
fb9aa51
Users view added
ChachoPacho Oct 15, 2021
1808250
New Database Tables
ChachoPacho Oct 15, 2021
97a24a1
TSC transpirate
ChachoPacho Oct 15, 2021
e0a0bb3
routes dir rename to controllers
ChachoPacho Oct 15, 2021
f592b1a
CSS
ChachoPacho Oct 15, 2021
e545e2f
bundle
ChachoPacho Oct 15, 2021
469956a
API class rename to DataBase
ChachoPacho Oct 15, 2021
4da0cb6
Login and Register Functionalities
ChachoPacho Oct 15, 2021
dbe8482
Filters
ChachoPacho Oct 15, 2021
84c756d
Users HREF added, CSS, and minor fixes
ChachoPacho Oct 15, 2021
bffa003
User Interface
ChachoPacho Oct 15, 2021
c82b7ad
Client Users support
ChachoPacho Oct 15, 2021
5a2c07f
Users API support
ChachoPacho Oct 15, 2021
aeec08f
Users path added
ChachoPacho Oct 15, 2021
77dbe18
Refactor of ProductsAPI
ChachoPacho Oct 15, 2021
2ed37c6
API more general
ChachoPacho Oct 15, 2021
74411fa
Users Listeners support
ChachoPacho Oct 15, 2021
7e915f9
Saves only IDs now
ChachoPacho Oct 15, 2021
289745b
Listen to API
ChachoPacho Oct 15, 2021
e03177e
bundle
ChachoPacho Oct 15, 2021
6c1d380
Database Tests
ChachoPacho Oct 15, 2021
d7635ef
Fix Errors on Register & getProduct (string -> number)
ChachoPacho Oct 15, 2021
87a8a86
Ignore
ChachoPacho Oct 15, 2021
f8ca37c
mend
ChachoPacho Oct 15, 2021
13ff892
config
ChachoPacho Oct 19, 2021
09aec14
bundle
ChachoPacho Oct 19, 2021
f063738
tests
ChachoPacho Oct 19, 2021
29f2056
logued users view. Minor fix
ChachoPacho Oct 19, 2021
7e9edd6
Products Server Side
ChachoPacho Oct 19, 2021
5567460
Favorites
ChachoPacho Oct 19, 2021
9e40fcc
Users Class Refactor
ChachoPacho Oct 19, 2021
bbfa851
bundle
ChachoPacho Oct 19, 2021
338e487
Routes
ChachoPacho Oct 19, 2021
aa5ce87
Users View
ChachoPacho Oct 19, 2021
b97eba0
Users View
ChachoPacho Oct 19, 2021
d4b7bf7
Paginator
ChachoPacho Oct 19, 2021
c97ace1
config
ChachoPacho Oct 19, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
/js/
/node_modules/
node_modules/
build/**/*
public/js/app.min.js
44 changes: 35 additions & 9 deletions app/client/class/API.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,25 +9,51 @@ import apiErrorHandler from "../errors/apiErrorHandler";
export default abstract class API {
public static async fetchAPI(
url: string,
data?: object
): Promise<Product[] | apiError | Product> {
return await fetch(url, {
method: "POST",
data?: object,
method: string = "POST"
): Promise<any | apiError> {
const response = await fetch(url, {
method,
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(data)
})
.then((e) => e.json())
.then((res) => (Object.keys(res).length === 0 ? API_ERROR : res));
body: JSON.stringify(data),
});
const responseJson = await response.json();

if (response.ok) {
return Object.keys(responseJson).length === 0 ? API_ERROR : responseJson;
}
return (responseJson as any).message;
}

public static async fetchRedirectAPI(
url: string,
data?: object,
method: string = "POST"
): Promise<any | apiError> {
const response = await fetch(url, {
method,
headers: {
"Content-Type": "application/json",
},
redirect: "follow",
body: JSON.stringify(data),
});
const responseJson = await response.json();

if (response.ok) {
return Object.keys(responseJson).length === 0 ? API_ERROR : responseJson;
}
return (responseJson as any).message;
}

/**
*
* @param apiResponse An API method return
* @returns if the api is or not an Error
*/
public static isApiError(apiResponse: Product[] | apiError | Product): boolean {
public static isApiError(apiResponse: any | apiError): boolean {
if (typeof apiResponse === "string") {
apiErrorHandler("Ha ocurrido un error.");
return true;
Expand Down
25 changes: 24 additions & 1 deletion app/client/class/App.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
// LISTENERES
import loginRegisterListener from "../listeners/loginRegisterListener";
import menuHandlerListener from "../listeners/menuHandlerListener";
import closeCartListener from "../listeners/closeCartListener";
import paginatorListener from "../listeners/paginatorListener";
Expand All @@ -7,29 +8,36 @@ import shopListener from "../listeners/shopListener";

// CLASSES
import Favorites from "./Favorites";
import Router from "./Router";
import Users from "./Users";
import Cart from "./Cart";
import UI from "./UI";

// SCRIPTS
import updateQuantityProducts from "../scripts/updateQuantityProducts";
import loadUsers from "../scripts/loadUsers";
import loadTable from "../scripts/loadTable";
import { CURRENT_PAGE } from "../config";
import favoritesListener from "../listeners/favoritesListener";

export default class App {
public ui: UI;
public cart: Cart;
public users: Users;
public favorites: Favorites;
private PREPARE: {
[index: string]: string;
} = {
products: "productsPrepare",
product: "productPrepare",
cart: "cartPrepare",
users: "usersPrepare"
};

constructor(HTML_APP: HTMLElement) {
this.ui = new UI(HTML_APP);
this.cart = new Cart();
this.users = new Users();
this.favorites = new Favorites();
}

Expand All @@ -52,14 +60,15 @@ export default class App {
* Loads all listeners for Products.
*/
private productsPrepare(): void {
this.productPrepare();
paginatorListener();
shopListener(this.cart);
}

/**
* Loads all listeners for Product.
*/
private productPrepare(): void {
favoritesListener(this.users, this.favorites);
shopListener(this.cart);
}

Expand All @@ -70,4 +79,18 @@ export default class App {
closeCartListener(this.cart);
loadTable(this.cart);
}

/**
* Loads all listeners for Users.
*/
private async usersPrepare(): Promise<void> {
if (this.users.isLogued()) {
if (!Router.getParam(1)) {
return Router.follow(`/users/${this.users.getUser()}`);
}
return await loadUsers(this.users, this.favorites);
}

loginRegisterListener();
}
}
2 changes: 1 addition & 1 deletion app/client/class/Cart.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import CartStructure from "../interfaces/CartStructure";
import CartProduct from "../interfaces/CartProduct";

import { cartProductsList } from "../types/cart";

import Storage from "./Storage";

import { SS_CART } from "../config";
import cartErrorHandler from "../errors/cartErrorHandler";
import CartProduct from "../interfaces/CartProduct";

export default class Cart extends Storage<CartStructure> {
private products: any = [];
Expand Down
55 changes: 11 additions & 44 deletions app/client/class/Favorites.ts
Original file line number Diff line number Diff line change
@@ -1,61 +1,28 @@
import { favoritesArray } from "../types/favorites";
import { productID } from "../types/products";

import Storage from "./Storage";
import Router from "./Router";
import API from "./API";

import { SS_FAVORITES } from "../config";
import UsersStorage from "./UsersStorage";

export default class Favorites extends Storage<favoritesArray> {
export default class Favorites extends UsersStorage {
constructor() {
super(SS_FAVORITES, []);
super();
}

public addToFavorites(productID: productID): void {
const favoritesSet: Set<number> = new Set(this.getStorage()).add(productID);
this.updateFavorites(favoritesSet);
}

public removeFromFavorite(productID: number): void {
const favoritesSet: Set<number> = new Set(this.getStorage())
favoritesSet.delete(productID);
this.updateFavorites(favoritesSet);
}

public handleFavorite(productID: number): void {
const favoritesSet: Set<number> = new Set(this.getStorage());
if (favoritesSet.has(productID)) {
favoritesSet.delete(productID);
return
}
favoritesSet.add(productID);
}

/**
* @return if the Cart is empty or not.
*/
public isEmpty(): boolean {
return this.getStorage().length === 0;
public async toggleFavorites(productID: productID): Promise<boolean> {
return await API.fetchAPI(this.getFavoritesAPI(`${productID}`), {}, "PUT");
}

/**
* @return favorites products.
*/
public getFavorites(): favoritesArray {
return this.getStorage();
public async getFavorites(): Promise<favoritesArray> {
return (await API.fetchAPI(this.getFavoritesAPI())).favorites;
}

/**
* @return favorites products.
*/
public isFavorite(id: number): boolean {
return this.getStorage().includes(id);;
}

/**
* Update the Favorites Products Storage.
*/
private updateFavorites(favoritesSet: Set<number>): void {
const favoritesArray: favoritesArray = [...favoritesSet];
this.updateStorage(favoritesArray);
private getFavoritesAPI(productID: string = ""): string {
return Router.createURL(`/favorites/${this.getUser()}/${productID}`);
}
}
39 changes: 23 additions & 16 deletions app/client/class/Router.ts
Original file line number Diff line number Diff line change
@@ -1,35 +1,42 @@
import { htmlFileName } from "../types/search";

export default class Router {
public static followWithParams(
path: string,
params: any
): void {
window.location.replace(
window.location.origin + path + Router.stringfyParams(params)
);
public static follow(path: string): void {
window.location.replace(window.location.origin + path);
}

public static followWithCurrentParams(
path: string
): void {
public static followWithQuery(path: string, query: any): void {
window.location.replace(
window.location.origin + path + Router.getParams()
window.location.origin + path + Router.stringfyQuery(query)
);
}

public static getParams(): string {
public static followWithCurrentQuery(path: string): void {
window.location.replace(window.location.origin + path + Router.getQuery());
}

public static getQuery(): string {
return window.location.search;
}

public static createURL(path: string): string {
return window.location.origin + path;
}

private static stringfyParams(params: any): string {
public static getPage(): htmlFileName {
return window.location.pathname.split("/")[1] as htmlFileName;
}

public static getParam(nParam: number): string {
return window.location.pathname.split("/")[nParam + 1];
}

private static stringfyQuery(query: any): string {
return (
"?" +
Object.keys(params)
.map((key) => `${key}=params[key]`)
Object.keys(query)
.map((key) => `${key}=${query[key]}`)
.join("&")
);
}
}
}
6 changes: 2 additions & 4 deletions app/client/class/UI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,8 @@ export default class UI {
maxPage: number
): void {
const innerHTML: string = products
.map((product: Product): string =>
ProductsCardComponent(product, favorites.isFavorite(product.id))
)
.map((product: Product): string => ProductsCardComponent(product))
.join("");
PaginatorComponenet(page || 1, maxPage)
PaginatorComponenet(page || 1, maxPage);
}
}
45 changes: 45 additions & 0 deletions app/client/class/Users.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import API from "./API";
import Router from "./Router";
import UsersStorage from "./UsersStorage";

export default class Users extends UsersStorage {
constructor() {
super();
}

public async loginUser(email: string, password: string): Promise<void | string> {
const response = await API.fetchAPI(Router.createURL("/users"), { email, password });
if (API.isApiError(response)) {
return response.message
}
this.updateStorage({
id: response.id,
email,
password
})
}

public async registerUser(email: string, password: string): Promise<void | string> {
const response = await API.fetchAPI(Router.createURL("/users"), { email, password }, "PUT");
if (API.isApiError(response)) {
return response.message
}
this.updateStorage({
id: response.id,
email,
password
})
}

public getEmail() {
return super.getEmail();
}

public getUser() {
return super.getUser();
}

public isLogued() {
return super.isLogued();
}
}
25 changes: 25 additions & 0 deletions app/client/class/UsersStorage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import User from "../interfaces/User";

import Storage from "./Storage";

export default class UsersStorage extends Storage<User> {
constructor() {
super("user", {
id: null,
email: "",
password: "",
});
}

protected getUser(): number {
return +this.getStorage().id;
}

protected getEmail(): string {
return this.getStorage().email;
}

protected isLogued(): boolean {
return !!this.getStorage().id;
}
}
4 changes: 3 additions & 1 deletion app/client/config.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
import { apiError, apiURL } from "./types/api";
import { htmlFileName } from "./types/search";

import Router from "./class/Router";

// HTML
const SEARCH_INPUT_S: HTMLElement = document.getElementById("search-input-s");
const SEARCH_INPUT: HTMLElement = document.getElementById("search-input");
const QUANTITY_PRODUCTS_INDICATOR: HTMLElement = document.getElementById("quantityProducts")

// GENERAL
const CURRENT_PAGE: htmlFileName = window.location.pathname.split("/")[1] as htmlFileName;
const CURRENT_PAGE: htmlFileName = Router.getPage();
const PAGES: htmlFileName[] = ["index", "cart", "products", "product", "error"];
const DEFAULT_HTML_FILE: htmlFileName = "index";
const SEARCH_PAIR_INPUTS: {
Expand Down
Loading