summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHombreLaser <sebastian-440@live.com>2023-05-11 19:28:47 -0600
committerHombreLaser <sebastian-440@live.com>2023-05-11 19:28:47 -0600
commit385606ee05a8ceb9073169639eb1a311f81cac10 (patch)
treeac8af50a15ce3e834009afef773988213c961cdb /src
parentab540055c99074c1c67fd65b45d0afb785ca5a0b (diff)
Añade información a la vista de usuario
Diffstat (limited to 'src')
-rw-r--r--src/clients/api_client.ts33
-rw-r--r--src/clients/loaders.ts15
-rw-r--r--src/components/address.tsx28
-rw-r--r--src/components/addresses_table.tsx42
-rw-r--r--src/components/payment_method.tsx23
-rw-r--r--src/components/payment_methods_table.tsx40
-rw-r--r--src/components/stylesheets/shared.css12
-rw-r--r--src/lib/token.ts23
-rw-r--r--src/routes/account/account.tsx35
9 files changed, 229 insertions, 22 deletions
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(
+ <tr className="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
+ <th scope="row" className="px-6 py-4 font-medium text-gray-900 whitespace-nowrap dark:text-white">
+ {address.attributes.street}
+ </th>
+ <td className="px-6 py-4">
+ {address.attributes.number}
+ </td>
+ <td className="px-6 py-4">
+ {address.attributes.zip_code}
+ </td>
+ <td className="px-6 py-4">
+ {address.attributes.city}
+ </td>
+ <td className="px-6 py-4">
+ {countryList().getLabel(address.attributes.country)}
+ </td>
+ <td className="px-6 py-4">
+ <button type="button" className="focus:outline-none text-white bg-green-700 hover:bg-green-800 focus:ring-4 focus:ring-green-300 font-medium rounded-lg text-sm px-5 py-2.5 mr-2 mb-2 dark:bg-green-600 dark:hover:bg-green-700 dark:focus:ring-green-800">
+ Editar
+ </button>
+ </td>
+ </tr>
+ );
+} \ 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 =>
+ <Address address={address}/>
+ );
+
+ return(
+ <div className="w-4/5 relative overflow-x-auto">
+ <h1 className="text-2xl my-2">
+ Direcciones de envío
+ </h1>
+ <table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
+ <thead className="bg-blue-arma text-xs text-white uppercase dark:bg-gray-700 dark:text-gray-400">
+ <tr>
+ <th scope="col" className="px-6 py-3">
+ Calle
+ </th>
+ <th scope="col" className="px-6 py-3">
+ Número
+ </th>
+ <th scope="col" className="px-6 py-3">
+ Código postal
+ </th>
+ <th scope="col" className="px-6 py-3">
+ Ciudad
+ </th>
+ <th scope="col" className="px-6 py-3">
+ País
+ </th>
+ <th scope="col" className="px-6 py-3">
+ Editar
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ {digested_addresses}
+ </tbody>
+ </table>
+ </div>
+ );
+} \ 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(
+ <tr className="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
+ <th scope="row" className="px-6 py-4 font-medium text-gray-900 whitespace-nowrap dark:text-white">
+ {payment_method.attributes.number}
+ </th>
+ <td className="px-6 py-4">
+ {payment_method.attributes.expiration_day}
+ </td>
+ <td className="px-6 py-4">
+ {payment_method.attributes.expiration_month}
+ </td>
+ <td className="px-6 py-4">
+ {payment_method.attributes.expiration_year}
+ </td>
+ <td className="px-6 py-4">
+ <button type="button" className="focus:outline-none text-white bg-green-700 hover:bg-green-800 focus:ring-4 focus:ring-green-300 font-medium rounded-lg text-sm px-5 py-2.5 mr-2 mb-2 dark:bg-green-600 dark:hover:bg-green-700 dark:focus:ring-green-800">
+ Editar
+ </button>
+ </td>
+ </tr>
+ );
+} \ 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 =>
+ <PaymentMethod payment_method={payment_method}/>
+ );
+
+ return(
+ <div className="my-2 w-4/5 relative overflow-x-auto">
+ <h1 className="text-2xl my-2">
+ Métodos de pago
+ </h1>
+ <table className="w-full text-sm text-left text-gray-500 dark:text-gray-400">
+ <thead className="bg-blue-arma text-xs text-white uppercase dark:bg-gray-700 dark:text-gray-400">
+ <tr>
+ <th scope="col" className="px-6 py-3">
+ Número
+ </th>
+ <th scope="col" className="px-6 py-3">
+ Día de expiración
+ </th>
+ <th scope="col" className="px-6 py-3">
+ Mes de expiración
+ </th>
+ <th scope="col" className="px-6 py-3">
+ Año de expiración
+ </th>
+ <th scope="col" className="px-6 py-3">
+ Editar
+ </th>
+ </tr>
+ </thead>
+ <tbody>
+ {digested_payment_methods}
+ </tbody>
+ </table>
+ </div>
+ );
+} \ 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(
<>
<MainContentLayout>
- <h2>
- Cuenta
- </h2>
+ <div className="grid my-6 w-4/5 grid-cols-10 gap-2">
+ <div className="w-2/5 col-span-1">
+ <PersonCircle size={128} color="#394490"/>
+ </div>
+ <div className="grid grid-rows-3 col-span-9 mx-4">
+ <div className="my-2">
+ <h1 className="text-4xl">
+ {full_name}
+ </h1>
+ </div>
+ <div className="text-2xl">
+ <span className="mx-1 field_name">Correo electrónico:</span> {email}
+ </div>
+ <div>
+ <a type="button" className="button text-white hover:bg-blue-300 hover:text-gray focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 mr-2 mb-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800" href="#">
+ Editar
+ </a>
+ </div>
+ </div>
+ </div>
+ <AddressesTable addresses={addresses}/>
+ <PaymentMethodsTable payment_methods={payment_methods}/>
</MainContentLayout>
</>
);