summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHombreLaser <sebastian-440@live.com>2023-05-18 22:04:52 -0600
committerHombreLaser <sebastian-440@live.com>2023-05-18 22:04:52 -0600
commit44a016256717b871ada858d5dc064d9d0e06425e (patch)
tree008bb13cc1b10355f335e24e46d0d74e85669364 /src
parent2cc3bd2a5ab71ced121ea6e8fef3be5db2b98e4f (diff)
Añade creación de direcciones
Diffstat (limited to 'src')
-rw-r--r--src/clients/actions.ts49
-rw-r--r--src/clients/api_client.ts16
-rw-r--r--src/components/addresses_table.tsx6
-rw-r--r--src/components/forms/address_form.tsx34
-rw-r--r--src/components/forms/fields/select_field.tsx32
-rw-r--r--src/lib/form_utils.ts17
-rw-r--r--src/main.tsx12
-rw-r--r--src/routes/account/addresses/create.tsx18
-rw-r--r--src/routes/account/addresses/edit.tsx7
9 files changed, 139 insertions, 52 deletions
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<FormError>();
+
+ 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 }) {
<h1 className="text-2xl my-2">
Direcciones de envío
</h1>
+ <div className="absolute top-0 right-0">
+ <a 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"
+ href="/account/addresses/new">
+ Nueva dirección
+ </a>
+ </div>
<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>
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<FieldProperties> = [
{
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 (<option key={ country_code } value={ country_code } selected>{ countryList().getLabel(country_code) }</option>);
else
return (<option key={ country_code } value={ country_code }>{ countryList().getLabel(country_code) }</option>);
}
-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 =>
- <Field properties={field_properties}/>
+ const fields = field_properties.map(field_property =>
+ <Field properties={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(
- <div className="mb-6">
- <label className="block mb-2 text-lg text-gray-900 dark:text-white">{properties.label}</label>
- <select id={properties.id} className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
- {options}
- </select>
- </div>
- );
+ let select_field;
+
+ if(properties.error_message) {
+ select_field = (
+ <div className="mb-6">
+ <label className="block mb-2 text-lg text-red-700 dark:text-red-500">{properties.label}</label>
+ <select id={properties.id} name={properties.name} className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
+ {options}
+ </select>
+ <p className="mt-2 text-sm text-red-600 dark:text-red-500"> {properties.error_message }</p>
+ </div>
+ );
+ } else {
+ select_field = (
+ <div className="mb-6">
+ <label className="block mb-2 text-lg text-gray-900 dark:text-white">{properties.label}</label>
+ <select id={properties.id} name={properties.name} className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
+ {options}
+ </select>
+ </div>
+ );
+ }
+
+ 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<any>) {
}
}
+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 = [
{
@@ -46,6 +47,11 @@ const routes = [
action: editAddress,
},
{
+ path: "/account/addresses/new",
+ element: <CreateAddress/>,
+ action: createAddress
+ },
+ {
path: '/',
element: <Navigate to='/products'/>
}
@@ -54,9 +60,9 @@ const routes = [
const router = createBrowserRouter(routes);
ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
- //<React.StrictMode>
+ <React.StrictMode>
<Layout>
<RouterProvider router={router}/>
</Layout>
- //</React.StrictMode>
+ </React.StrictMode>
) \ 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 (
+ <MainContentLayout>
+ <div className="w-4/5 my-6">
+ <h1 className="my-6 text-3xl">
+ Nueva dirección
+ </h1>
+ <AddressForm errors={errors}/>
+ </div>
+ </MainContentLayout>
+ );
+} \ 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(
<MainContentLayout>
<div className="w-4/5 my-6">
<h1 className="my-6 text-3xl">
- Editar cuenta
+ Editar dirección
</h1>
- <AddressForm address={address}/>
+ <AddressForm address={address} errors={errors}/>
</div>
</MainContentLayout>
);