summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorHombreLaser <sebastian-440@live.com>2023-05-22 21:18:20 -0600
committerHombreLaser <sebastian-440@live.com>2023-05-22 21:18:20 -0600
commit21508a3514500f8f38ddaa8bef7a9cd420d76628 (patch)
treee416d58752154f7cbe78a96c1fbe35dd34a8703f /src
parentb5885b23a8d3593428334683b8c03075ce071f3a (diff)
Añade carrito
Diffstat (limited to 'src')
-rw-r--r--src/clients/actions.ts6
-rw-r--r--src/clients/loaders.ts21
-rw-r--r--src/components/navbar.tsx26
-rw-r--r--src/components/payment_methods_table.tsx8
-rw-r--r--src/components/product_cart.tsx28
-rw-r--r--src/main.tsx18
-rw-r--r--src/models/product.ts26
-rw-r--r--src/routes/account/cards/create.tsx18
-rw-r--r--src/routes/account/cart.tsx41
9 files changed, 180 insertions, 12 deletions
diff --git a/src/clients/actions.ts b/src/clients/actions.ts
index acc5ad3..cee9a85 100644
--- a/src/clients/actions.ts
+++ b/src/clients/actions.ts
@@ -56,13 +56,15 @@ export async function authenticatedEdit({ request }) {
}
}
-export async function createAddress({ request }) {
+export async function create({ request }) {
clearSessionStorage();
const client = new ApiClient();
+ const paths = new URL(request.url).pathname.split('/');
+ const request_path = paths.slice(0, paths.length - 1).join('/');
const form_data = await request.formData();
try{
- await client.post('/account/addresses', form_data, client.authorizationHeaders());
+ await client.post(request_path, form_data, client.authorizationHeaders());
return redirect("/account");
} catch(error) {
diff --git a/src/clients/loaders.ts b/src/clients/loaders.ts
index 7e44f16..9f5a131 100644
--- a/src/clients/loaders.ts
+++ b/src/clients/loaders.ts
@@ -1,5 +1,7 @@
import { redirect } from "react-router-dom";
import { ApiClient } from "./api_client";
+import { Product, mapProduct } from "../models/product";
+import Token from "../lib/token";
export async function loader({ request }) {
const client = new ApiClient();
@@ -9,6 +11,25 @@ export async function loader({ request }) {
return response;
}
+export async function cartLoader() {
+ const data = new Array<Product>();
+ const token = new Token();
+ const client = new ApiClient();
+ const request = await client.authenticatedGet("/account/cart");
+
+ if(request.response) {
+ token.logout();
+
+ return redirect("/products")
+ }
+
+ request.data.data.attributes.products.data.map(response_data => {
+ data.push(mapProduct(response_data));
+ });
+
+ return data;
+}
+
export async function addressLoader({ params }) {
const client = new ApiClient();
const path = `/account/addresses/${params.addressId}`;
diff --git a/src/components/navbar.tsx b/src/components/navbar.tsx
index d136e31..4078405 100644
--- a/src/components/navbar.tsx
+++ b/src/components/navbar.tsx
@@ -2,8 +2,26 @@ import { CartFill } from "react-bootstrap-icons";
import "./stylesheets/navbar.css";
import "./stylesheets/shared.css";
import MainPageDropdownMenu from "./main_page_dropdown_menu";
+import Token from "../lib/token";
export default function Navbar() {
+ const session = new Token();
+ let cart;
+
+ if (session.present()) {
+ cart = (
+ <a className="mr-4 text-neutral-500 hover:text-neutral-700 focus:text-neutral-700 disabled:text-black/30 dark:text-neutral-200 dark:hover:text-neutral-300 dark:focus:text-neutral-300 [&.active]:text-black/90 dark:[&.active]:text-neutral-400"
+ href="/account/cart">
+ <span className="[&>svg]:w-5">
+ <CartFill color="#394490" size={32}/>
+ </span>
+ </a>
+ );
+ }
+ else {
+ cart = null;
+ }
+
return(
<>
<header>
@@ -33,12 +51,8 @@ export default function Navbar() {
{ /* Lado derecho */}
<div className="flex items-center">
- <a className="mr-4 text-neutral-500 hover:text-neutral-700 focus:text-neutral-700 disabled:text-black/30 dark:text-neutral-200 dark:hover:text-neutral-300 dark:focus:text-neutral-300 [&.active]:text-black/90 dark:[&.active]:text-neutral-400"
- href="#">
- <span className="[&>svg]:w-5">
- <CartFill color="#394490" size={32}/>
- </span>
- </a>
+
+ {cart}
<MainPageDropdownMenu/>
</div>
diff --git a/src/components/payment_methods_table.tsx b/src/components/payment_methods_table.tsx
index e9ac639..03fe473 100644
--- a/src/components/payment_methods_table.tsx
+++ b/src/components/payment_methods_table.tsx
@@ -7,10 +7,16 @@ export default function PaymentMethodsTable({ payment_methods }) {
);
return(
- <div className="my-2 w-4/5 relative overflow-x-auto">
+ <div className="my-4 w-4/5 relative overflow-x-auto">
<h1 className="text-2xl my-2">
Métodos de pago
</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/cards/new">
+ Nuevo método de pago
+ </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/product_cart.tsx b/src/components/product_cart.tsx
new file mode 100644
index 0000000..86d2615
--- /dev/null
+++ b/src/components/product_cart.tsx
@@ -0,0 +1,28 @@
+import "./stylesheets/product_listing.css";
+
+export default function ProductCart({ product }) {
+ return (
+ <div className="my-2 w-4/6 grid grid-cols-3 gap-2 border-2 border-gray-300">
+ <div className="col-span-2">
+ <img className="listing-image" src={product.picture} />
+ </div>
+ <div className="grid grid-rows-3">
+ <div className="product-listing-text text-2xl">
+ {product.name}
+ </div>
+ <div className="text-lg">
+ <span className="product-listing-text text-xl">
+ Precio unitario
+ </span>
+ {product.unitary_price}
+ </div>
+ <div className="text-lg">
+ <span className="product-listing-text text-xl">
+ Precio al por mayor
+ </span>
+ {product.bulk_price}
+ </div>
+ </div>
+ </div>
+ );
+} \ No newline at end of file
diff --git a/src/main.tsx b/src/main.tsx
index 404cc0f..ebe246a 100644
--- a/src/main.tsx
+++ b/src/main.tsx
@@ -5,14 +5,16 @@ 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 Cart from "./routes/account/cart";
import { EditAccount } from './routes/account/edit';
import { Edit as EditAddress } from "./routes/account/addresses/edit";
-import { createAddress, editAccount, authenticatedEdit } from './clients/actions';
+import { create, editAccount, authenticatedEdit } from './clients/actions';
import Layout from "./components/layout";
-import { accountLoader, loader, productLoader, addressLoader, cardLoader } from "./clients/loaders";
+import { accountLoader, loader, productLoader, addressLoader, cardLoader, cartLoader } from "./clients/loaders";
import './index.css';
import { Create as CreateAddress } from './routes/account/addresses/create';
import { Edit as EditCard } from './routes/account/cards/edit';
+import { Create as CreateCard } from './routes/account/cards/create';
const routes = [
{
@@ -50,7 +52,7 @@ const routes = [
{
path: "/account/addresses/new",
element: <CreateAddress/>,
- action: createAddress
+ action: create
},
{
path: "/account/cards/:cardId/edit",
@@ -59,6 +61,16 @@ const routes = [
action: authenticatedEdit
},
{
+ path: "/account/cards/new",
+ element: <CreateCard/>,
+ action: create
+ },
+ {
+ path: "/account/cart",
+ element: <Cart/>,
+ loader: cartLoader
+ },
+ {
path: '/',
element: <Navigate to='/products'/>
}
diff --git a/src/models/product.ts b/src/models/product.ts
new file mode 100644
index 0000000..b375537
--- /dev/null
+++ b/src/models/product.ts
@@ -0,0 +1,26 @@
+export interface Product {
+ id: number;
+ name: string;
+ picture: string;
+ unitary_price: number;
+ bulk_price: number;
+ available_quantity: number;
+ company_name: string;
+}
+
+export function mapProduct(data: any) {
+ if(!data)
+ return null;
+
+ const product: Product = {
+ id: data.id,
+ name: data.attributes.name,
+ picture: data.attributes.picture,
+ unitary_price: data.attributes.unitary_price,
+ bulk_price: data.attributes.bulk_price,
+ available_quantity: data.attributes.available_quantity,
+ company_name: data.attributes.company.name
+ };
+
+ return product;
+} \ No newline at end of file
diff --git a/src/routes/account/cards/create.tsx b/src/routes/account/cards/create.tsx
new file mode 100644
index 0000000..9779ef2
--- /dev/null
+++ b/src/routes/account/cards/create.tsx
@@ -0,0 +1,18 @@
+import { useActionData } from "react-router-dom";
+import CardForm from "../../../components/forms/card_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">
+ Nuevo método de pago
+ </h1>
+ <CardForm errors={errors}/>
+ </div>
+ </MainContentLayout>
+ );
+} \ No newline at end of file
diff --git a/src/routes/account/cart.tsx b/src/routes/account/cart.tsx
new file mode 100644
index 0000000..a98cf20
--- /dev/null
+++ b/src/routes/account/cart.tsx
@@ -0,0 +1,41 @@
+import { useLoaderData } from "react-router-dom";
+import { cartLoader } from "../../clients/loaders";
+import ProductCart from "../../components/product_cart";
+import { Product } from "../../models/product";
+import MainContentLayout from "../../components/main_content_layout";
+import { CartXFill } from "react-bootstrap-icons";
+
+export default function Cart() {
+ let products;
+ const data = useLoaderData() as Array<Product>;
+
+ if(data.length > 0) {
+ products = data.map(product =>
+ <ul>
+ <li key={product.id}>
+ <ProductCart product={product}/>
+ </li>
+ </ul>
+ );
+ }
+ else {
+ products = (
+ <div>
+ <div className="flex justify-center my-4 w-4/6">
+ <CartXFill color="rgb(55 65 81)" size={256}/>
+ </div>
+ <div className="flex justify-center my-4 w-4/6 text-2xl text-gray-900 my-2">
+ Su carrito está vacío, añada algunos productos para empezar a comprar.
+ </div>
+ </div>
+ );
+ }
+
+ return(
+ <>
+ <MainContentLayout>
+ {products}
+ </MainContentLayout>
+ </>
+ );
+} \ No newline at end of file