Skip to content

Conversation

Annysah
Copy link
Contributor

@Annysah Annysah commented Oct 12, 2021

No description provided.

import ProductCard from './components/ProductCard';
import Cart from './components/Cart';

import { useQuery } from 'react-query';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So here's what we're gonna do. We're going to use graphql-codegen to generate types for the queries. You'll need to learn how to create query files, and configure graphql codegen for react-query.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

amount: number
}

const endpoint = 'http://localhost:8810/graphql'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'd have to start using environment variables so we can deploy to the cloud

}
`

const fetchProducts = () => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Once you generate types with react-query and graphql-codegen, this function will be handled. Let me know how your research on how to use it goes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


const handleRemoveFromCart = (id: number) => {
setCartLists(prevItem => (
prevItem.reduce((ack, item) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use better variable names. I'm not sure what ack is. also, prevItem might be clearer as previousItem.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done


import { Product } from '../App'

type CartProp = {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CartProps

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

handleRemoveFromCart: (id: number) => void
}

const Cart:React.FunctionComponent<CartProp> = ({ cartLists, handleAddToCart, handleRemoveFromCart }) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not cartLists, its not a list, but rather a list of items, so cartItems would be better here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

handleRemoveFromCart: (id: number) => void
}

const Cart:React.FunctionComponent<CartProp> = ({ cartLists, handleAddToCart, handleRemoveFromCart }) => {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So instead of calling your props handleAddToCart or handleRemoveFromCart, its best to call them onAddToCart, onRemoveFromCart. Much better because all event listeners in react start with on and not handle.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


const ProductCard:React.FunctionComponent<ProductCardProp> = ({ product, handleAddToCart }) => {
return (
<div className="column is-half">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Formatting is off I think. Do you have prettier setup ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I just did a prettier setup and worked on the formatting. It looks much better.

};

const onRemoveFromCart = (id: number) => {
setCartItems((findProductItem) =>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code is not readable. Try breaking it down into multiple steps. So its readable and understandable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved

@@ -0,0 +1,10 @@
query Products {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this automatically generated? Shouldn't be here I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The requests in this file was used to auto-generate types by graphql codegen.


type ProductCardProps = {
product: Product;
onAddToCart: (clickedProduct: Product) => void;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A much better variable name to clickedProduct is product.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

};

const Navbar: React.FunctionComponent<NavbarProp> = ({ cartItems }) => {
const getCartTotal = (products: CartItem[]) =>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Variable name should be cartItems: CartItem[]. Not products: CartItem[]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

const App = () => {
const [cartItems, setCartItems] = useState<CartItem[]>([]);
const { data, isLoading, error } = useProductsQuery<ProductsQuery>({
endpoint: "http://127.0.0.1:8810/graphql",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you try searching for a way to not have this here ? I'm thinking there should be a way to globally define this in the fetcher used by the generated products.

}
})

const totalPrice = products.reduce((total:any, product:any) => total + parseInt(product.price), 0)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not use any here. total is number and product is ProductModel. You can import ProductModel from '@tensei/orm`.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

import { graphql } from '@tensei/graphql'
import { welcome, tensei, cors, resource, text, textarea, integer, graphQlQuery } from '@tensei/core'

const stripe = new Stripe('sk_test_51JjsxtJnZnb1n2GnbebKQgYe73xTZtT1147z1dLFU9CGmkfbZKvcrW1VX4jA10Wav82slFIGjp9AW6puPURjibMP00z7Fw14Em', {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use process.env.STRIPE_SECRET here. The article should note that this key will be set in environment.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noted

import Cart from "./components/Cart";
import { Checkout } from "./components/Checkout";
import PaymentSuccessful from "./components/PaymentSuccessful";
import { isTemplateTail } from "typescript";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Weird 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oops, it was not meant to be there.
Done.

.fields([
text('Image'),
text('Name'),
text('Price'),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Price should actually be a number (integer) field.

const getTotal = (products: CartItem[]) =>
products.reduce(
(accumulator: number, product) =>
accumulator + product.quantity * Number(product.product.price),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you change the price to a number field, you won't need to use Number( here.

// if succedded, redirect to thank you page
setError(null);
setProcessing(false);
setSucceeded(true);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we need success and redirect. Here, we can just call router.push i think to redirect the user. Please let me know if this function exists. There should be a hook or something.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants