From 385606ee05a8ceb9073169639eb1a311f81cac10 Mon Sep 17 00:00:00 2001 From: HombreLaser Date: Thu, 11 May 2023 19:28:47 -0600 Subject: Añade información a la vista de usuario MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/clients/api_client.ts | 33 ++++++++++++++++++++++--- src/clients/loaders.ts | 15 ++++++------ src/components/address.tsx | 28 +++++++++++++++++++++ src/components/addresses_table.tsx | 42 ++++++++++++++++++++++++++++++++ src/components/payment_method.tsx | 23 +++++++++++++++++ src/components/payment_methods_table.tsx | 40 ++++++++++++++++++++++++++++++ src/components/stylesheets/shared.css | 12 +++++++++ src/lib/token.ts | 23 +++++++++++------ src/routes/account/account.tsx | 35 +++++++++++++++++++++++--- 9 files changed, 229 insertions(+), 22 deletions(-) create mode 100644 src/components/address.tsx create mode 100644 src/components/addresses_table.tsx create mode 100644 src/components/payment_method.tsx create mode 100644 src/components/payment_methods_table.tsx (limited to 'src') diff --git a/src/clients/api_client.ts b/src/clients/api_client.ts index 7d2cf34..fc2d361 100644 --- a/src/clients/api_client.ts +++ b/src/clients/api_client.ts @@ -1,11 +1,38 @@ -import axios from "axios"; +import axios, { AxiosResponse } from "axios"; +import Token from "../lib/token"; export class ApiClient { readonly url = "http://localhost:3000/api"; + token = new Token(); - async get(path: string, params?: URLSearchParams, headers?: object) { + async authenticatedGet(path: string) { const request_url = `${ this.url }${ path }`; - const response = await this.makeGetRequest(request_url, headers); + let request: any; + let options = { + headers: { + Authorization: this.token.get() + } + }; + + request = await this.makeGetRequest(request_url, options); + + if(request.response) { + // Let's try with a refreshed token. + this.token.refresh() + options = { + headers: { + Authorization: this.token.getRefresh() + } + }; + request = await this.makeGetRequest(request_url, options); + } + + return request; + } + + async get(path: string) { + const request_url = `${ this.url }${ path }`; + const response = await this.makeGetRequest(request_url); return response; } diff --git a/src/clients/loaders.ts b/src/clients/loaders.ts index 2af7770..d9972d5 100644 --- a/src/clients/loaders.ts +++ b/src/clients/loaders.ts @@ -12,17 +12,16 @@ export async function loader({ request }) { export async function accountLoader() { const client = new ApiClient(); - const token = new Token(); + + const account_response = await client.authenticatedGet("/account"); + const addresses_response = await client.authenticatedGet("/account/addresses"); + const cards_response = await client.authenticatedGet("/account/cards"); - if(!token.present()) + // Authentication error handling. + if(account_response.response || addresses_response.response || cards_response.response) return redirect("/products"); - const headers = { - "Authentication": `Bearer ${ token.get() }` - }; - - const response = await client.get("/account", undefined, headers); - return response; + return [account_response, addresses_response, cards_response]; } export async function productLoader({ params }) { diff --git a/src/components/address.tsx b/src/components/address.tsx new file mode 100644 index 0000000..1701fd1 --- /dev/null +++ b/src/components/address.tsx @@ -0,0 +1,28 @@ +import countryList from "react-select-country-list"; + +export default function Address({ address }) { + return( + + + {address.attributes.street} + + + {address.attributes.number} + + + {address.attributes.zip_code} + + + {address.attributes.city} + + + {countryList().getLabel(address.attributes.country)} + + + + + + ); +} \ No newline at end of file diff --git a/src/components/addresses_table.tsx b/src/components/addresses_table.tsx new file mode 100644 index 0000000..ae46f21 --- /dev/null +++ b/src/components/addresses_table.tsx @@ -0,0 +1,42 @@ +import Address from "./address"; + +export default function AddressesTable({ addresses }) { + const digested_addresses = addresses.map(address => +
+ ); + + return( +
+

+ Direcciones de envío +

+ + + + + + + + + + + + + {digested_addresses} + +
+ Calle + + Número + + Código postal + + Ciudad + + País + + Editar +
+
+ ); +} \ No newline at end of file diff --git a/src/components/payment_method.tsx b/src/components/payment_method.tsx new file mode 100644 index 0000000..66f7e54 --- /dev/null +++ b/src/components/payment_method.tsx @@ -0,0 +1,23 @@ +export default function PaymentMethod({ payment_method }) { + return( + + + {payment_method.attributes.number} + + + {payment_method.attributes.expiration_day} + + + {payment_method.attributes.expiration_month} + + + {payment_method.attributes.expiration_year} + + + + + + ); +} \ No newline at end of file diff --git a/src/components/payment_methods_table.tsx b/src/components/payment_methods_table.tsx new file mode 100644 index 0000000..e9ac639 --- /dev/null +++ b/src/components/payment_methods_table.tsx @@ -0,0 +1,40 @@ +import PaymentMethod from "./payment_method"; +import "./stylesheets/shared.css"; + +export default function PaymentMethodsTable({ payment_methods }) { + const digested_payment_methods = payment_methods.map(payment_method => + + ); + + return( +
+

+ Métodos de pago +

+ + + + + + + + + + + + {digested_payment_methods} + +
+ Número + + Día de expiración + + Mes de expiración + + Año de expiración + + Editar +
+
+ ); +} \ No newline at end of file diff --git a/src/components/stylesheets/shared.css b/src/components/stylesheets/shared.css index 9bda368..cc9e4a2 100644 --- a/src/components/stylesheets/shared.css +++ b/src/components/stylesheets/shared.css @@ -6,6 +6,18 @@ left: 50%; } +h1 { + color: #394490; +} + +.field_name { + color: #394490; +} + +.bg-blue-arma { + background-color: #394490 !important; +} + .button { background-color: #394490 !important; } diff --git a/src/lib/token.ts b/src/lib/token.ts index f838ac0..05de87e 100644 --- a/src/lib/token.ts +++ b/src/lib/token.ts @@ -1,12 +1,7 @@ import { ApiClient } from "../clients/api_client"; +import axios from "axios"; export default class Token { - client: ApiClient; - - constructor() { - this.client = new ApiClient(); - } - get() { return sessionStorage.getItem("token"); } @@ -16,7 +11,7 @@ export default class Token { } getRefresh() { - sessionStorage.getItem("refresh"); + return sessionStorage.getItem("refresh"); } setRefresh(refresh_token: string) { @@ -33,6 +28,18 @@ export default class Token { } refresh() { - this.client.post("/refresh_tokens") + const options = { + headers: { + Authorization: `Bearer ${this.getRefresh()}` + } + } + + try { + const response = axios.post('/refresh_tokens', null, options); + this.setRefresh(response.data.refresh); + this.set(response.data.token); + } catch(error) { + this.logout(); + } } } \ No newline at end of file diff --git a/src/routes/account/account.tsx b/src/routes/account/account.tsx index baca1a5..8458285 100644 --- a/src/routes/account/account.tsx +++ b/src/routes/account/account.tsx @@ -1,13 +1,42 @@ import { useLoaderData } from "react-router-dom"; +import { PersonCircle } from "react-bootstrap-icons"; +import AddressesTable from "../../components/addresses_table"; +import PaymentMethodsTable from "../../components/payment_methods_table"; import MainContentLayout from "../../components/main_content_layout"; +import "../../components/stylesheets/shared.css"; export default function Account() { + const response = useLoaderData(); + const full_name = response[0].data.data.attributes.first_name + ' ' + response[0].data.data.attributes.last_name + const email = response[0].data.data.attributes.email + const addresses = response[1].data.data; + const payment_methods = response[2].data.data; + return( <> -

- Cuenta -

+
+
+ +
+
+
+

+ {full_name} +

+
+
+ Correo electrónico: {email} +
+ +
+
+ +
); -- cgit v1.2.3