From cbebedd51e1b4a2f709341b792dd073bac83f15d Mon Sep 17 00:00:00 2001 From: HombreLaser Date: Fri, 12 May 2023 23:01:55 -0600 Subject: Añadido formulario de edición de cuenta MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.json | 1 + src/clients/actions.ts | 18 ++++++++++++++++++ src/clients/api_client.ts | 30 +++++++++++++++++++----------- src/clients/loaders.ts | 1 - src/lib/form_utils.ts | 10 ++++++++++ src/lib/token.ts | 27 ++++++++++++++++++++++++++- src/main.tsx | 8 ++++++++ src/routes/account/account.tsx | 2 +- src/routes/account/edit.tsx | 40 ++++++++++++++++++++++++++++++++++++++++ 9 files changed, 123 insertions(+), 14 deletions(-) create mode 100644 src/clients/actions.ts create mode 100644 src/lib/form_utils.ts create mode 100644 src/routes/account/edit.tsx diff --git a/package.json b/package.json index b2f92e0..0d301bd 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "axios": "^1.3.6", "flowbite": "^1.6.5", "flowbite-react": "^0.4.4", + "jwt-decode": "^3.1.2", "react": "^18.2.0", "react-bootstrap-icons": "^1.10.3", "react-dom": "^18.2.0", diff --git a/src/clients/actions.ts b/src/clients/actions.ts new file mode 100644 index 0000000..36935cb --- /dev/null +++ b/src/clients/actions.ts @@ -0,0 +1,18 @@ +import { redirect } from "react-router-dom"; +import { ApiClient } from "./api_client"; +import { deleteEmptyFields } from "../lib/form_utils"; + +export async function editAccount({ request }) { + const client = new ApiClient(); + let form_data = await request.formData(); + form_data = deleteEmptyFields(form_data); + const response = await client.put("/account", form_data); + + if(response.status == 401) + return redirect("/products"); + + client.token.set(response.data.token); + client.token.setRefresh(response.data.refresh); + + return redirect("/account"); +} \ No newline at end of file diff --git a/src/clients/api_client.ts b/src/clients/api_client.ts index fc2d361..93d713a 100644 --- a/src/clients/api_client.ts +++ b/src/clients/api_client.ts @@ -3,27 +3,19 @@ import Token from "../lib/token"; export class ApiClient { readonly url = "http://localhost:3000/api"; - token = new Token(); + public readonly token = new Token(); async authenticatedGet(path: string) { const request_url = `${ this.url }${ path }`; let request: any; - let options = { - headers: { - Authorization: this.token.get() - } - }; + let options = this.authorizationHeaders(); 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() - } - }; + options = this.authorizationHeaders(); request = await this.makeGetRequest(request_url, options); } @@ -44,6 +36,14 @@ export class ApiClient { return response; } + async put(path: string, data: FormData) { + const request_url = `${ this.url }${ path }`; + const options = this.authorizationHeaders(); + const response = await axios.put(request_url, data, options); + + return response; + } + async getProduct(id: string) { const request_url = `${ this.url }/products/${ id }`; const [product_response, product_reviews] = await Promise.all([ @@ -63,4 +63,12 @@ export class ApiClient { return error; } } + + private authorizationHeaders() { + return { + headers: { + Authorization: this.token.get() + } + }; + } } \ No newline at end of file diff --git a/src/clients/loaders.ts b/src/clients/loaders.ts index d9972d5..8d0f06f 100644 --- a/src/clients/loaders.ts +++ b/src/clients/loaders.ts @@ -1,5 +1,4 @@ import { redirect } from "react-router-dom"; -import Token from "../lib/token"; import { ApiClient } from "./api_client"; export async function loader({ request }) { diff --git a/src/lib/form_utils.ts b/src/lib/form_utils.ts new file mode 100644 index 0000000..a4e7bff --- /dev/null +++ b/src/lib/form_utils.ts @@ -0,0 +1,10 @@ +export function deleteEmptyFields(form: FormData) { + const trimmed_form = form; + + for(const key of trimmed_form) { + if(trimmed_form.get(key[0]) == '') + trimmed_form.delete(key[0]); + } + + return trimmed_form; +} \ No newline at end of file diff --git a/src/lib/token.ts b/src/lib/token.ts index 05de87e..93ec0cf 100644 --- a/src/lib/token.ts +++ b/src/lib/token.ts @@ -1,4 +1,4 @@ -import { ApiClient } from "../clients/api_client"; +import jwt_decode from "jwt-decode"; import axios from "axios"; export default class Token { @@ -42,4 +42,29 @@ export default class Token { this.logout(); } } + + getEmail() { + return this.decode()?.data; + } + + getRole() { + return this.decode()?.aud; + } + + getJTI() { + return this.decode()?.jti; + } + + getExpirationDate() { + return this.decode()?.exp; + } + + private decode(): { data: string; aud: string; jti: string; exp: number; } | null { + const token = this.get(); + + if(token != null) + return jwt_decode(token); + + return null; + } } \ No newline at end of file diff --git a/src/main.tsx b/src/main.tsx index a3eb1b2..cd65146 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -5,6 +5,8 @@ import Products from "./routes/products/products"; import Product from "./routes/products/product"; import Companies from "./routes/companies/companies"; import Account from "./routes/account/account"; +import { EditAccount } from './routes/account/edit'; +import { editAccount } from './clients/actions'; import Layout from "./components/layout"; import { accountLoader, loader, productLoader } from "./clients/loaders"; import './index.css'; @@ -30,6 +32,12 @@ const routes = [ loader: accountLoader, element: }, + { + path: "/account/edit", + element: , + loader: accountLoader, + action: editAccount + }, { path: '/', element: diff --git a/src/routes/account/account.tsx b/src/routes/account/account.tsx index 8458285..8a04427 100644 --- a/src/routes/account/account.tsx +++ b/src/routes/account/account.tsx @@ -29,7 +29,7 @@ export default function Account() { Correo electrónico: {email}
- + Editar
diff --git a/src/routes/account/edit.tsx b/src/routes/account/edit.tsx new file mode 100644 index 0000000..c2dfcb5 --- /dev/null +++ b/src/routes/account/edit.tsx @@ -0,0 +1,40 @@ +import MainContentLayout from "../../components/main_content_layout"; +import Token from "../../lib/token"; +import { Form, useLoaderData } from "react-router-dom"; +import "../../components/stylesheets/shared.css"; + +export function EditAccount() { + const account = useLoaderData()[0].data.data.attributes; + const token = new Token(); + + return( + <> + +
+

+ Editar cuenta +

+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+ +
+
+
+ + ); +} \ No newline at end of file -- cgit v1.2.3