adrianhajdin / project_e_commerce

This is a code repository for the corresponding video tutorial. In this video, we're going to build a fully functional eCommerce application using commerce.js.
https://jsmastery.pro
1.88k stars 506 forks source link

Does anyone have a working AddressForm.jsx and Checkout.jsx form that conform to recent API object naming conventions? #48

Open KBCodes2021 opened 2 years ago

KBCodes2021 commented 2 years ago

I've completed 2/3rds of the project. I can log the token generated in Checkout.jsx and log it in the AddressForm.jsx. But when adding shippingSubdivision and setShippingOption I get HTTP 500 errors.

Any help would be appreciated! I've commented out components that were very unstable.

This is the Address Form: and Checkout is below:

import React, { useState, useEffect } from 'react'; import { InputLabel, Select, MenuItem, Button, Grid, Typography } from '@material-ui/core'; import { useForm, FormProvider } from 'react-hook-form'; import { Link } from 'react-router-dom';

import { commerce } from '../../lib/commerce'; import FormInput from './CustomTextField';

const AddressForm = ({ checkoutToken }) => { const [shippingCountries, setShippingCountries] = useState([]); const [shippingCountry, setShippingCountry] = useState(''); const [shippingSubdivisions, setShippingSubdivisions] = useState([]); const [shippingSubdivision, setShippingSubdivision] = useState(''); const [shippingOptions, setShippingOptions] = useState([]); const [shippingOption, setShippingOption] = useState(''); const methods = useForm();

const fetchShippingCountries = async (checkoutTokenId) => { const { countries } = await commerce.services.localeListShippingCountries(checkoutTokenId);

console.log(countries);
setShippingCountries(countries);
setShippingCountry(Object.keys(countries)[0]);

};

const fetchSubdivisions = async (countryCode) => { const { subdivisions } = await commerce.services.localeListSubdivisions(countryCode);

setShippingSubdivisions(subdivisions);
setShippingSubdivision(Object.keys(subdivisions)[0]);

};

// const fetchShippingOptions = async (checkoutTokenId, country, stateProvince = null) => { // const options = await commerce.checkout.getShippingOptions(checkoutTokenId, { country, region: stateProvince });

// setShippingOptions(options); // setShippingOption(options[0].id); // };

useEffect(() => {
fetchShippingCountries(checkoutToken.id);

}, []);

useEffect(() => { if (shippingCountry) fetchSubdivisions(shippingCountry); }, [shippingCountry]);

// useEffect(() => { // if (shippingSubdivision) fetchShippingOptions(checkoutToken.id, shippingCountry, shippingSubdivision); // }, [shippingSubdivision]);

return (
    <>
        <Typography variant="h6" gutterBottom>Shipping Address</Typography>
        <FormProvider {...methods}>
            <form>
                <Grid container spacing={3}>
                <FormInput required name="firstName" label="First name" />
                <FormInput required name="lastName" label="Last name" />
                <FormInput required name="address1" label="Address line 1" />
                <FormInput required name="email" label="Email" />
                <FormInput required name="city" label="City" />
                <FormInput required name="zip" label="Zip / Postal code" />
                <Grid item xs={12} sm={6}>

                   <InputLabel>Shipping Country</InputLabel>
                  <Select value={shippingCountry} fullWidth onChange={(e) => setShippingCountry(e.target.value)}>
                  {Object.entries(shippingCountries).map(([code, name]) => ({ id: code, label: name })).map((item) => (
                  <MenuItem key={item.id} value={item.id}>
                  {item.label}
                  </MenuItem>
                   ))}
                  </Select>
                  </Grid>

                <Grid item xs={12} sm={6}>
                <InputLabel>Shipping Subdivision</InputLabel>
                <Select value={shippingSubdivision} fullWidth onChange={(e) => setShippingSubdivision(e.target.value)}>
                    {Object.entries(shippingSubdivisions).map(([code, name]) => ({ id: code, label: name })).map((item) => (
                    <MenuItem key={item.id} value={item.id}>
                        {item.label}
                    </MenuItem>
                    ))}
                </Select>
                </Grid>

        {/* <Grid item xs={12} sm={6}>
          <InputLabel>Shipping Options</InputLabel>
          <Select value={shippingOption} fullWidth onChange={(e) => setShippingOption(e.target.value)}>
            {shippingOptions.map((sO) => ({ id: sO.id, label: `${sO.description} - (${sO.price.formatted_with_symbol})` })).map((item) => (
              <MenuItem key={item.id} value={item.id}>
                {item.label}
              </MenuItem>
            ))}
          </Select>
        </Grid> */}
      </Grid>
      <br />
      {/* <div style={{ display: 'flex', justifyContent: 'space-between' }}>
        <Button component={Link} variant="outlined" to="/cart">Back to Cart</Button>
        <Button type="submit" variant="contained" color="primary">Next</Button>
      </div> */}
    </form>
  </FormProvider>
</>

); };

export default AddressForm;

Checkout

import React, { useState, useEffect } from 'react' import { Paper, Stepper, Step, StepLabel, Typography, CircularProgress, Divider, Button } from '@material-ui/core';

import { commerce } from '../../../lib/commerce'; import useStyles from './styles'; import AddressForm from '../AddressForm'; import PaymentForm from '../PaymentForm';

const steps = ['Shipping address', 'Payment details'];

const Checkout = ({ cart }) => { const [activeStep, setActiveStep] = useState(0); const [checkoutToken, setCheckoutToken] = useState(null); const classes = useStyles();

useEffect(() => {
    const generateToken = async () => {
        try {
            const token = await commerce.checkout.generateToken(cart.id, {type: 'cart'});

            console.log(token);

            setCheckoutToken(token);
        } catch (error) {

        }
    }

    generateToken();
}, [cart]);

const Confirmation = () => (
    <div>
        Confirmation
    </div>
);

const Form = () => activeStep === 0
    ? <AddressForm checkoutToken={checkoutToken}/>
    : <PaymentForm />

return (
    <>

  <div className={classes.toolbar} />
  <main className={classes.layout}>
    <Paper className={classes.paper}>
      <Typography variant="h4" align="center">Checkout</Typography>
      <Stepper activeStep={activeStep} className={classes.stepper}>
        {steps.map((label) => (
          <Step key={label}>
            <StepLabel>{label}</StepLabel>
          </Step>
        ))}
      </Stepper>
      {activeStep === steps.length ? <Confirmation /> : checkoutToken && <Form />}
    </Paper>
  </main>
    </>
)

}

export default Checkout

shvkumar7777 commented 2 years ago

I am stuck at the countries section, where I am getting an empty array. did you the list countries ?

thiernoa98 commented 1 year ago

For anyone new who got stuck, It looks like the error is coming from the commerce js company/webiste themselves as localeListShippingCountries is not working at all but it could be replaced with localeListCountries to display the countries but this function will list all of the countries that's in their website, not the one that you selected, not shipping countries that you want and getShippingOptions is not working at all

surendra-sketch commented 12 months ago

In Address form i am getting error "methods" is not defined please help me someone

i have installed same all pkg