npm install sass-loader node-sass --save-dev
- Now we got cors setup and categories we can filter by and grab product that belongs to that category.
- Now we implement in the front end to grab the correct products based on category.
- Reason why http://localhost:3000/products/nike-air-max works is
- because without having to introduce cors within nuxt it runs on nuxt.js
- We were making request on node.js server which doesn't require cors.
- However when we get to the point where we try to filter by category
- When we load in product coffee this will go ahead and do an ajax request
- To our endpoint that is where cors comes in.
- products/_slug.vue
- Create component
- will be iterated over every single type of variation ex whole beans coffee
- Will also trigger an event when user selects a variation
- Then have separate for te quantity
- Now when you select a different Coffee it will remove the past variation selection.
- disable out of stock products
- As well put notice item is out of stock
- https://auth.nuxtjs.org/
- https://github.com/nuxt-community/auth-module
- npm install @nuxtjs/auth
- you can access the store anywhere for auth using $auth
- Now if you want to log out you can do so by going to Application and delete Local Storage and Cookies
- We create new store to keep all cart related in it.
- alternative code: Better way instead is using addressSelected method instead
/*
watch: {
// will switch out from selecting address menu after you choose new address
selectedAddress() {
this.selecting = false;
},
},
*/
- Pass Id to
<CountryDropdown v-model="form.country_id" />
- using a emit
<select @change="changed">
<option :value="country.id" v-for="country in countries" :key="country.id">
{{ country.name }}
</option>
</select>
- We can use v-model on a component itself
- What we can do is in ShippingAddress watch for selectedAddress
- then emit the fact that we want to update and use that particular value
- What this will archieve is allow us to use v-model within this component
- You can do this creating a watch in ShippingAddress and watch selectedAddress
watch: {
selectedAddress(address) {
this.$emit("input", address.id);
},
},
- Then v-model will be able to listen to it
<ShippingAddress
:addresses="addresses"
v-model="form.address_id"
/>
- We going to store our shipping method that we choosen inside of our store, so we can send it accross
- We using computed property in checkout/index.vue is because to update your store as if it was a peace of data of your component hook up with the model, you need to use computed property for this.
npm install query-string
- Now it will grab shipping method and pass it down when you select new address
- We going to use submitting: false in checkout/index.vue to not allow user to send submit button more than once
- Even through we already have protection via the if statement in store method in the backend since the cart would be empty.
- We going to test if alert message works by going to stocks table and turning quantity to 0 of the product we have on cart
- add a console log to see message that api give up when it shows the error
} catch (e) {
console.log(e.response);
}
- There is bug that cart doesn't refresh propery that we will fix later. That the quantity of available items in cart is not selected
- We can also change stock from 2 to 1 to test what happens as well.
- The causes the value of quantity does not be selected in the checkout when the stock quanity changed to less than available stock.
- You can now inspect the element in the browser to see what is causing the problem
- The issue seem to be in CartOverviewProduct.vue component where quantity is been updated, but data is not refreshing to reflect that
- What we can do is take the data and use a computed property instead that has a get and set
- which will always be updated when that value changes
- The set( will have the data, while the set() will take the place of the watcher which we will remove.
- Now test it by changing stock quantity to 0 from 1 and 2 to 1 to see that now works properly.
- We going to slice products so we can limit amount show using a computed products property
- A way yo refactor
<span
class="tag is-medium"
:class="{
'is-success': this.order.status === 'complete',
'is-info': this.order.status === 'processing' || this.order.status === 'pending',
'is-danger': this.order.status === 'payment_failed',
}"
>
{{ order.status }}
</span>
- Into data() property instead
data() {
return {
maxProducts: 1,
statusClasses: {
"is-success": this.order.status === "complete",
"is-info":
this.order.status === "processing" || this.order.status === "pending",
"is-danger": this.order.status === "payment_failed",
},
};
},
- then just use statusClasses
<span class="tag is-medium" :class="statusClasses">
- This is how we have it set up now
<div v-for="product in products" :key="product.id">
{{ product }}
<a href="">Product 1</a>
</div>
- We get back from {{ product }}
{ "id": 3, "name": "250g", "price": "$0.10", "price_varies": false, "stock_count": 0, "type": "whole bean", "in_stock": false, "product": { "id": 1, "name": "coffee", "slug": "coffee", "description": "delicious coffee", "price": "$0.10", "stock_count": 18, "in_stock": true } } Product 1
- We make some changes to also display the product variation we do this by
<div v-for="variation in products" :key="variation.id">
{{ variation.product }}
<a href="">Product 1</a>
</div>
- Result we get is that now we have the coffee we also have the type as well.
{ "id": 1, "name": "coffee", "slug": "coffee", "description": "delicious coffee", "price": "$0.10", "stock_count": 18, "in_stock": true }
- Currently is very static
statusClasses: {
"is-success": this.order.status === "complete",
"is-info":
this.order.status === "processing" || this.order.status === "pending",
"is-danger": this.order.status === "payment_failed",
},
-
Instead we going to use dynamic components that are rendered base on the name of the component matching the status we have in orders database
-
create folder named statuses in order folder in components
-
Add file names
OrderStatus-payment_failed.vue
matching the status name. -
We have to name them with same structure
OrderStatus-pending.vue
-
Replace
<span
class="tag is-medium"
:class="statusClasses"
>
{{ order.status }}
</span>
- with
<component :is="order.status" />
export default {
components: {
payment_failed: OrderStatusPaymentFailed,
pending: OrderStatusPending,
// processing: OrderStatusProcessing,
// completed: OrderStatusCompleted,
},
- Now the component change dynamically.
- This give you a lot more control and you can even pass props with them.
- Been able to switch between Payment methods is very similar to changing address
- So we going to copy and reuse a lot of code from Address switching components
- Go to browser console on Network then choose XHR and look in Headers for Respond Payload to verify the payment_method_id
- Added https://js.stripe.com/v3/ to Nuxt.config.js
- Clear out all payment_methods we have in database. Left click table > tools > truncate.
- Select Restart Identity and Cascade
- Go to user table and delete gateway_customer_id
- Hide change payment method when there is no one added as default
- Nuxt comes with is on middleware
nuxt-cart-client/node_modules/@nuxtjs/auth/lib/core/middleware.js
- When you try to access
http://localhost:3000/orders
you get error unless you loggin. - To fix this you can add
middleware: ["auth"]
to the component. - So that when you try to access
http://localhost:3000/orders
you get redirected to login pagehttp://localhost:3000/login
- Problem is we have our login page in
http://localhost:3000/auth/signin
- So we going to create our own custom middleware
nuxt-cart-client/middleware
and create middleware formiddleware: ["redirectIfGuest"]
- Now if you try to access
http://localhost:3000/orders
which has middleware - You will be redirected to login page with
- the query
http://localhost:3000/auth/signin?redirect=%2Forders
- %2F = /
- Now after sign in we want to modify the singin.vue so that it redirect back to the page in query above.
- Now we add
middleware: ["redirectIfGuest"]
every place we want authenticated to be required. - Create middleware called redirectIfAuthenticated.js
- When user tries to go to http://localhost:3000/auth/signin
- and they already logged in, redirect them to index page