From 44a016256717b871ada858d5dc064d9d0e06425e Mon Sep 17 00:00:00 2001 From: HombreLaser Date: Thu, 18 May 2023 22:04:52 -0600 Subject: Añade creación de direcciones MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/clients/actions.ts | 49 ++++++++++++++++++++++------ src/clients/api_client.ts | 16 ++++----- src/components/addresses_table.tsx | 6 ++++ src/components/forms/address_form.tsx | 34 +++++++++---------- src/components/forms/fields/select_field.tsx | 32 +++++++++++++----- src/lib/form_utils.ts | 17 ++++++++-- src/main.tsx | 12 +++++-- src/routes/account/addresses/create.tsx | 18 ++++++++++ src/routes/account/addresses/edit.tsx | 7 ++-- 9 files changed, 139 insertions(+), 52 deletions(-) create mode 100644 src/routes/account/addresses/create.tsx (limited to 'src') diff --git a/src/clients/actions.ts b/src/clients/actions.ts index bfddf54..cb5ba23 100644 --- a/src/clients/actions.ts +++ b/src/clients/actions.ts @@ -1,8 +1,22 @@ import { redirect } from "react-router-dom"; import { ApiClient } from "./api_client"; -import { clearSessionStorage, deleteEmptyFields, setFormErrorsInSessionStorage } from "../lib/form_utils"; +import { clearSessionStorage, deleteEmptyFields, setFormErrorsInSessionStorage, FormError } from "../lib/form_utils"; import Token from "../lib/token"; +function requestErrorsToArray(errors: any) { + const errors_array = new Array(); + + for(const [field, error_message] of Object.entries(errors)) { + const e = { + field_name: field, + message: error_message.toString() + }; + errors_array.push(e); + } + + return errors_array; +} + export async function editAccount({ request }) { const client = new ApiClient(); let form_data = await request.formData(); @@ -25,23 +39,38 @@ export async function editAddress({ params, request }) { form_data = deleteEmptyFields(form_data); try { - - const response = await client.put(`/account/addresses/${params.addressId}`, form_data); - - if(response.status == 401 || response.status == 404) - return redirect("/products"); + await client.put(`/account/addresses/${params.addressId}`, form_data); return redirect("/account"); } catch(error) { if(error.response.status == 401) { - new Token().logout; + new Token().logout(); - return redirect("/products") + return redirect("/products"); } else { - setFormErrorsInSessionStorage(error.response.data.errors); + return requestErrorsToArray(error.response.data.errors); + } + } +} + +export async function createAddress({ request }) { + clearSessionStorage(); + const client = new ApiClient(); + const form_data = await request.formData(); + + try{ + await client.post('/account/addresses', form_data, client.authorizationHeaders()); - return redirect(`/account/addresses/${params.addressId}/edit`); + return redirect("/account"); + } catch(error) { + if(error.response.status == 401) { + new Token().logout(); + + return redirect("/products"); + } + else { + return requestErrorsToArray(error.response.data.errors); } } } \ No newline at end of file diff --git a/src/clients/api_client.ts b/src/clients/api_client.ts index 4362c4d..81ae482 100644 --- a/src/clients/api_client.ts +++ b/src/clients/api_client.ts @@ -54,6 +54,14 @@ export class ApiClient { return [product_response, product_reviews]; } + authorizationHeaders() { + return { + headers: { + Authorization: `Bearer ${this.token.get()}` + } + }; + } + private async makeGetRequest(request_url: string, headers?: object) { try { const response = await axios.get(request_url, headers); @@ -63,12 +71,4 @@ export class ApiClient { return error; } } - - private authorizationHeaders() { - return { - headers: { - Authorization: `Bearer ${this.token.get()}` - } - }; - } } \ No newline at end of file diff --git a/src/components/addresses_table.tsx b/src/components/addresses_table.tsx index ae46f21..ea7d840 100644 --- a/src/components/addresses_table.tsx +++ b/src/components/addresses_table.tsx @@ -10,6 +10,12 @@ export default function AddressesTable({ addresses }) {

Direcciones de envío

+
+ + Nueva dirección + +
diff --git a/src/components/forms/address_form.tsx b/src/components/forms/address_form.tsx index 11b0191..53822bb 100644 --- a/src/components/forms/address_form.tsx +++ b/src/components/forms/address_form.tsx @@ -1,72 +1,72 @@ import { Form } from "react-router-dom"; -import { formHasErrors } from "../../lib/form_utils"; import countryList from "react-select-country-list"; import FieldProperties from "./fields/field_properties"; import Field from "./fields/field"; import SelectField from "./fields/select_field"; +import { useEffect } from "react"; +import { setFieldErrorMessages } from "../../lib/form_utils"; -function getFieldProperties(address: any) { +function getFieldProperties(address?: any) { const fields: Array = [ { id: "street-field", type: "text", name: "street", label: "Calle", - placeholder: address.street + placeholder: address?.street }, { id: "number-field", type: "number", name: "number", label: "Número", - placeholder: address.number + placeholder: address?.number }, { id: "zip-code-field", type: "number", name: "zip_code", label: "Código postal", - placeholder: address.zip_code + placeholder: address?.zip_code }, { id: "city-field", type: "text", name: "city", label: "Ciudad", - placeholder: address.city + placeholder: address?.city } ]; - for(const field of fields) { - if(sessionStorage.getItem(field.name)) { - field.error_message = sessionStorage.getItem(field.name); - } - } - return fields; } function getCountrySelectOptions(address: any, country_code: string) { - if(country_code == address.country) + if(address && country_code == address.country) return (); else return (); } -export default function AddressForm({ address }) { + +export default function AddressForm({ address = null, errors = null }) { + let field_properties = getFieldProperties(address); const select_field_properties: FieldProperties = { id: "country-field", type: "select", - name: "city", + name: "country", label: "Ciudad" } + if(errors) + field_properties = setFieldErrorMessages(field_properties, errors); + const options = countryList().getValues().map(country_code => getCountrySelectOptions(address, country_code) ); - const fields = getFieldProperties(address).map(field_properties => - + const fields = field_properties.map(field_property => + ); return( diff --git a/src/components/forms/fields/select_field.tsx b/src/components/forms/fields/select_field.tsx index 75859d9..4d67754 100644 --- a/src/components/forms/fields/select_field.tsx +++ b/src/components/forms/fields/select_field.tsx @@ -1,10 +1,26 @@ export default function SelectField({ properties, options }) { - return( -
- - -
- ); + let select_field; + + if(properties.error_message) { + select_field = ( +
+ + +

{properties.error_message }

+
+ ); + } else { + select_field = ( +
+ + +
+ ); + } + + return select_field; } \ No newline at end of file diff --git a/src/lib/form_utils.ts b/src/lib/form_utils.ts index af29463..43fe0fa 100644 --- a/src/lib/form_utils.ts +++ b/src/lib/form_utils.ts @@ -1,8 +1,8 @@ +import FieldProperties from "../components/forms/fields/field_properties"; import Token from "./token"; -export interface Error { - field_div_id: string; - field_input_id: string; +export interface FormError { + field_name: string; message: string; } @@ -23,6 +23,17 @@ export function setFormErrorsInSessionStorage(errors: Array) { } } +export function setFieldErrorMessages(fields: FieldProperties[], errors: FormError[]) { + for(const field of fields) { + const error = errors.find(e => e.field_name == field.name) + if(error){ + field.error_message = error.message; + } + } + + return fields; +} + export function clearSessionStorage() { const token = new Token(); const stored_token = sessionStorage.getItem('token'); diff --git a/src/main.tsx b/src/main.tsx index b044f49..f1020b1 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -7,10 +7,11 @@ import Companies from "./routes/companies/companies"; import Account from "./routes/account/account"; import { EditAccount } from './routes/account/edit'; import { Edit as EditAddress } from "./routes/account/addresses/edit"; -import { editAccount, editAddress } from './clients/actions'; +import { createAddress, editAccount, editAddress } from './clients/actions'; import Layout from "./components/layout"; import { accountLoader, loader, productLoader, addressLoader } from "./clients/loaders"; import './index.css'; +import { Create as CreateAddress } from './routes/account/addresses/create'; const routes = [ { @@ -45,6 +46,11 @@ const routes = [ loader: addressLoader, action: editAddress, }, + { + path: "/account/addresses/new", + element: , + action: createAddress + }, { path: '/', element: @@ -54,9 +60,9 @@ const routes = [ const router = createBrowserRouter(routes); ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( - // + - // + ) \ No newline at end of file diff --git a/src/routes/account/addresses/create.tsx b/src/routes/account/addresses/create.tsx new file mode 100644 index 0000000..5e33a2a --- /dev/null +++ b/src/routes/account/addresses/create.tsx @@ -0,0 +1,18 @@ +import { useActionData } from "react-router-dom"; +import AddressForm from "../../../components/forms/address_form"; +import MainContentLayout from "../../../components/main_content_layout"; + +export function Create() { + const errors = useActionData(); + + return ( + +
+

+ Nueva dirección +

+ +
+
+ ); +} \ No newline at end of file diff --git a/src/routes/account/addresses/edit.tsx b/src/routes/account/addresses/edit.tsx index 31bfaed..65c7b9a 100644 --- a/src/routes/account/addresses/edit.tsx +++ b/src/routes/account/addresses/edit.tsx @@ -1,17 +1,18 @@ import AddressForm from "../../../components/forms/address_form"; -import { useLoaderData } from "react-router-dom"; +import { useLoaderData, useActionData } from "react-router-dom"; import MainContentLayout from "../../../components/main_content_layout"; export function Edit() { const address = useLoaderData().data.data.attributes; + const errors = useActionData(); return(

- Editar cuenta + Editar dirección

- +
); -- cgit v1.2.3