diff options
author | HombreLaser <sebastian-440@live.com> | 2023-05-22 21:18:20 -0600 |
---|---|---|
committer | HombreLaser <sebastian-440@live.com> | 2023-05-22 21:18:20 -0600 |
commit | 21508a3514500f8f38ddaa8bef7a9cd420d76628 (patch) | |
tree | e416d58752154f7cbe78a96c1fbe35dd34a8703f /src | |
parent | b5885b23a8d3593428334683b8c03075ce071f3a (diff) |
Añade carrito
Diffstat (limited to 'src')
-rw-r--r-- | src/clients/actions.ts | 6 | ||||
-rw-r--r-- | src/clients/loaders.ts | 21 | ||||
-rw-r--r-- | src/components/navbar.tsx | 26 | ||||
-rw-r--r-- | src/components/payment_methods_table.tsx | 8 | ||||
-rw-r--r-- | src/components/product_cart.tsx | 28 | ||||
-rw-r--r-- | src/main.tsx | 18 | ||||
-rw-r--r-- | src/models/product.ts | 26 | ||||
-rw-r--r-- | src/routes/account/cards/create.tsx | 18 | ||||
-rw-r--r-- | src/routes/account/cart.tsx | 41 |
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 |