4 Commits 2e04f663de ... 76ba38f319

Auteur SHA1 Message Date
  kiboky 76ba38f319 algoria 검색 기능 추가 il y a 5 ans
  kiboky dcc0aaf1f1 algoria 검색 API 추가 il y a 5 ans
  kiboky 43d8ffe088 검색엔진 algolia 설정 il y a 5 ans
  kiboky c6837eeda6 stripe 결제 추가 il y a 5 ans

+ 35 - 2
client/components/Search.vue

@@ -13,8 +13,20 @@
 
     <form novalidate="novalidate" onsubmit="return false;" class="searchbox sbx-amazon">
       <div role="search" class="sbx-amazon__wrapper">
-        <input type="search" name="search" placeholder="Search your Product" autocomplete="off" required="required" class="sbx-amazon__input">
-        <button type="submit" title="Submit your search query." class="sbx-amazon__submit">
+        <input
+          v-model="query"
+          type="search"
+          name="search"
+          placeholder="Search your Product"
+          autocomplete="off"
+          required="required"
+          class="sbx-amazon__input">
+        <button
+          @click="onSearch"
+          type="submit"
+          title="Submit your search query."
+          class="sbx-amazon__submit"
+        >
           <svg role="img" aria-label="Search">
             <use xlink:href="#sbx-icon-search-11"></use>
           </svg>
@@ -28,3 +40,24 @@
     </form>
   </div>
 </template>
+
+<script>
+export default {
+  data () {
+    return {
+      query: ''
+    }
+  },
+
+  methods: {
+    onSearch () {
+      this.$router.push({
+        path: '/search',
+        query: {
+          title: this.query
+        }
+      })
+    }
+  }
+}
+</script>

+ 405 - 0
client/pages/placeorder.vue

@@ -0,0 +1,405 @@
+<template>
+<body>
+  <!--SHIPPING ADDRESS-->
+  <div class="container-fluid">
+    <div class="shipping-address">
+      <div class="navbarShipping a-spacing-large">
+        <nuxt-link to="/">
+          <img src="img/placeHeadernav.gif" class="img-fluid" />
+        </nuxt-link>
+      </div>
+      <div class="a-row">
+        <div class="a-size-large a-text-bold a-spacing-mini">Review your order</div>
+        <div class="a-row a-spacing-small a-size-mini"></div>
+      </div>
+      <div class="row">
+        <div class="col-xl-9 col-lg-8 col-md-9 col-sm-12">
+          <div class="a-row a-spacing-large"></div>
+          <div class="spc-top a-box a-spacing-small">
+            <div class="a-box-inner">
+              <div class="row">
+                <div class="col-xl-4 col-lg-6 col-sm-6 col-6">
+                  <div class="a-spacing-base">
+                    <div class="a-row">
+                      <strong>
+                        Shipping address
+                        <small>
+                          <a href="#">Change</a>
+                        </small>
+                      </strong>
+                    </div>
+                    <div class="a-row">
+                      <div class="displayAddressDiv">
+                        <!-- User's address -->
+                        <ul class="displayAddressUL">
+                          <li>{{ $auth.$state.user.address.fullname }}</li>
+                          <li>{{ $auth.$state.user.address.streetAddress}}</li>
+                          <li>{{ $auth.$state.user.address.city }}</li>
+                          <li>{{ $auth.$state.user.address.country}}</li>
+                          <li>
+                            Phone:
+                            <span dir="ltr">{{ $auth.$state.user.address.phoneNumber}}</span>
+                          </li>
+                        </ul>
+                      </div>
+                    </div>
+                  </div>
+                </div>
+                <div class="col-xl-4 col-lg-6 col-sm-6 col-6">
+                  <div class="a-spacing-base">
+                    <div class="a-row">
+                      <strong>
+                        Payment Method
+                        <small>
+                          <a href="#">Change</a>
+                        </small>
+                      </strong>
+                    </div>
+                    <div class="a-row">
+                      <ul class="no-bullet-list">
+                        <li class="a-spacing-micro">
+                          <span class="a-list-item">
+                            <span>
+                              <img src="img/visa.gif" class="img-fluid" />
+                            </span>
+                            ending in
+                            <span>6397</span>
+                          </span>
+                        </li>
+                      </ul>
+                    </div>
+                  </div>
+                  <div class="a-row a-spacing-base">
+                    <div class="a-row">
+                      <strong>
+                        Billing Address
+                        <small>
+                          <a href="#">Change</a>
+                        </small>
+                      </strong>
+                    </div>
+                    <span>Same as shipping address</span>
+                  </div>
+                </div>
+                <div class="col-xl-4 col-lg-6 col-sm-12 col-12">
+                  <div class="a-spacing-base">
+                    <div class="a-spacing-mini">
+                      <span>
+                        <strong>Gift cards &amp; promotional codes</strong>
+                      </span>
+                    </div>
+                    <div class="row">
+                      <div class="col-xl-8 col-lg-7 col-md-7 col-sm-7 col-8 pr-0">
+                        <input
+                          type="text"
+                          autocomplete="off"
+                          class="a-input-text"
+                          placeholder="Enter Code"
+                        />
+                      </div>
+                      <div class="col-xl-4 col-lg-5 col-md-5 col-sm-5 col-4">
+                        <span class="a-buton-apply-code">
+                          <span class="a-button-inner">
+                            <span class="a-button-text">Apply</span>
+                          </span>
+                        </span>
+                      </div>
+                    </div>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+          <div class="spc-orders a-box">
+            <div class="a-box-inner">
+              <div class="shipping-group">
+                <!-- Estimated delivery -->
+                <div
+                  class="a-row a-color-state a-text-bold a-size-medium a-spacing-small"
+                >Estimated delivery: {{ estimatedDelivery }}</div>
+                <div class="row">
+                  <!-- Cart -->
+                  <div class="col-xl-6 col-lg-7 col-sm-6 col-12">
+                    <div v-for="product in getCart" :key="product._id" class="a-row a-spacing-base">
+                      <div class="row">
+                        <!-- Product's photo -->
+                        <div class="col-sm-3 col-3">
+                          <img :src="product.photo" style="width: 100px;" />
+                        </div>
+                        <!-- Product's Title -->
+                        <div class="col-sm-9 col-9">
+                          <div class="a-row">
+                            <strong>{{ product.title }}</strong>
+                          </div>
+                          <!-- Product's owner name -->
+                          <div class="a-row a-size-small">{{ product.owner.name }}</div>
+                          <div class="a-row">
+                            <!-- Product's price -->
+                            <span class="a-color-price a-spacing-micro">
+                              <strong dir="ltr">${{ product.price * product.quantity }}</strong>
+                            </span>
+                          </div>
+                          <div class="a-row">
+                            <span class="availability a-color-success">In Stock.</span>
+                          </div>
+                          <div class="a-row">
+                            <!-- Product's quantity -->
+                            <strong>Quantity: {{ product.quantity }}</strong>
+                          </div>
+                          <div
+                            class="a-row a-color-secondary a-size-small"
+                          >Sold by:&nbsp;Amazon.com Services, Inc</div>
+                          <div class="a-row">
+                            <div class="a-row a-spacing-top-micro">
+                              <span class="a-button-small">
+                                <span class="a-button-inner">
+                                  <i class="a-icon checkout-giftbox-icon"></i>
+                                  <a
+                                    href="#"
+                                    class="a-button-text gift-popover-link"
+                                  >Add a gift receipt</a>
+                                </span>
+                              </span>
+                            </div>
+                            <div class="a-row">
+                              <span class="a-color-secondary a-size-mini">and see other gift options</span>
+                            </div>
+                          </div>
+                        </div>
+                      </div>
+                    </div>
+                  </div>
+                  <div class="col-xl-6 col-lg-5 col-sm-6 col-12">
+                    <div class="a-row shipping-speeds">
+                      <fieldset>
+                        <span class="shipping-speeds-title a-size-medium">
+                          <b>Choose a delivery option:</b>
+                        </span>
+                        <!-- Delivery option -->
+                        <div class="a-spacing-mini wednesday">
+                          <!-- Shipping normal -->
+                          <input @change="onChooseShipping('normal')" checked="checked" type="radio" name="order0" />
+                          <span class="a-radio-label">
+                            <span class="a-color-success">
+                              <strong>Averages 7 business days</strong>
+                            </span>
+                            <br />
+                            <span
+                              class="a-color-secondary"
+                            >$13.98&nbsp;-&nbsp;Standard International Shipping - No Tracking</span>
+                          </span>
+                        </div>
+                        <br />
+                        <div class="a-spacing-mini tuesday">
+                          <!-- Shipping fast -->
+                          <input @change="onChooseShipping('fast')" type="radio" name="order0" />
+                          <span class="a-radio-label">
+                            <span class="a-color-success">
+                              <strong>Averages 3 business days</strong>
+                            </span>
+                            <br />
+                            <span class="a-color-secondary">$49.98&nbsp;-&nbsp;Shipping</span>
+                          </span>
+                        </div>
+                      </fieldset>
+                    </div>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+        <div class="col-xl-3 col-lg-4 col-md-3 col-sm-12 pl-0">
+          <div class="a-box-group">
+            <div class="a-box a-first">
+              <div class="a-box-inner">
+                <div class="a-row a-spacing-micro">
+                  <nuxt-link to="/payment">
+                    <span class="a-button-place-order">Place your order in USD</span>
+                  </nuxt-link>
+                </div>
+                <div class="a-row a-spacing-small a-size-small a-text-center">
+                  By placing your order, you agree to Amazon's
+                  <a href="#">privacy notice</a>
+                  and
+                  <a href="#">conditions of use</a>.
+                </div>
+                <div class="a-row">
+                  <div id="tfx-header">
+                    <div class="a-box a-alert-info a-spacing-small">
+                      <div class="a-box-inner alert-info-no-icon">
+                        <strong>
+                          Amazon Currency Converter is Enabled. &nbsp;
+                          <a
+                            href="#"
+                            class="a-size-mini"
+                          >Learn More</a>
+                        </strong>
+                      </div>
+                    </div>
+                  </div>
+                  <h3 class="a-spacing-micro a-size-base">Order Summary</h3>
+                  <div class="order-summary" style="font-size: 12px;">
+                    <div class="row">
+                      <!-- Cart's total price -->
+                      <div class="col-sm-6">Items:</div>
+                      <div class="col-sm-6 text-right">USD ${{ getCartTotalPrice }}</div>
+                    </div>
+                    <div class="row">
+                      <!-- Shipping cost -->
+                      <div class="col-sm-6">Shipping & handling:</div>
+                      <div class="col-sm-6 text-right">USD {{ shippingPrice }}</div>
+                    </div>
+                    <div class="row mt-2">
+                      <div class="col-sm-6"></div>
+                      <div class="col-sm-6 text-right">
+                        <hr />
+                      </div>
+                    </div>
+                    <!-- Total Price with Shipping -->
+                    <div class="row">
+                      <div class="col-sm-6">Total Before Tax:</div>
+                      <div class="col-sm-6 text-right">USD {{ getCartTotalPriceWithShipping }}</div>
+                    </div>
+                    <div class="row">
+                      <div class="col-sm-6">Estimated tax to be collected:</div>
+                      <div class="col-sm-6 text-right">USD 0.00</div>
+                    </div>
+                    <hr />
+                    <div class="row">
+                      <div class="col-sm-6">
+                        <div class="a-color-price a-size-medium a-text-bold">Order total:</div>
+                      </div>
+                      <div class="col-sm-6 text-right">
+                        <!-- Total Price with Shipping -->
+                        <div class="a-color-price a-size-medium a-text-bold">USD {{ getCartTotalPriceWithShipping }}</div>
+                      </div>
+                    </div>
+                  </div>
+                </div>
+              </div>
+            </div>
+            <div class="a-box a-last a-color-alternate-background">
+              <div class="a-box-inner">
+                <div class="a-spacing-base">
+                  <div class="a-row">
+                    <span>
+                      <i class="fas fa-caret-down"></i>
+                      <a href="#">Selected payment currency</a>
+                    </span>
+                    <fieldset class="pl-3">
+                      <span style="margin-left: 1rem;">
+                        <input type="radio" class="no-js-hide" value="transactional" />
+                        <span class="a-radio-label">USD</span>
+                      </span>
+                      <div class="a-row">
+                        <span class="a-size-mini">
+                          <a href="#">(Change card currency)</a>
+                        </span>
+                      </div>
+                    </fieldset>
+                  </div>
+                </div>
+                <div class="a-size-mini">
+                  <div class="a-row a-spacing-mini mb-1">
+                    Please note that your country may charge import duties, taxes and fees that you may have to pay ahead of delivery.
+                    <a
+                      href="#"
+                    >Learn more</a>
+                  </div>
+                  <div class="a-row a-spacing-mini mb-1">
+                    <a href="#">How are shipping costs calculated?</a>
+                  </div>
+                  <div class="a-row a-spacing-mini">
+                    <a href="#">Why didn't I qualify for free shipping?</a>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+      <div class="a-row a-spacing-small a-spacing-top-small">
+        <p class="a-color-secondary a-size-mini">
+          Do you need help? Explore our
+          <a href="#">Help pages</a> or
+          <a href="#">contact us</a>
+        </p>
+        <p
+          class="a-color-secondary a-size-mini"
+        >For an item sold by Amazon.com: When you click the "Place your order" button, we'll send you an email message acknowledging receipt of your order. Your contract to purchase an item will not be complete until we send you an email notifying you that the item has been shipped.</p>
+        <p id="state-sales-tax-info" class="a-color-secondary a-size-mini">
+          Colorado, Oklahoma, South Dakota and Vermont Purchasers:
+          <a
+            href="#"
+          >Important information regarding sales tax you may owe in your State</a>
+        </p>
+        <div class="a-color-secondary a-size-mini">
+          <p class="a-color-secondary a-size-mini">
+            Within 30 days of delivery, you may return new, unopened merchandise in its original condition. Exceptions and restrictions apply. See Amazon.com's
+            <a
+              href="#"
+            >Returns Policy</a>
+            <br />
+            <br />Go to the
+            <a href="#">Amazon.com homepage</a> without completing your order.
+          </p>
+        </div>
+      </div>
+      <hr />
+      <p class="a-size-small a-text-center a-color-secondary" data-testid>
+        <a href="#">Conditions of Use</a> |
+        <a href="#">Privacy Notice</a> © 1996-2019, Amazon.com, Inc.
+      </p>
+    </div>
+  </div>
+  <!--/SHIPPING ADDRESS-->
+</body>
+</template>
+
+<script>
+import { mapGetters } from 'vuex'
+export default {
+  layout: "none",
+  async asyncData ({ $axios, store }) {
+    try {
+      let response = await $axios.$post('/api/shipment', { shipment: 'normal' })
+
+      store.commit('setShipping', {
+        price: response.shipment.price,
+        estimatedDelivery: response.shipment.estimated
+      })
+
+      return {
+        shippingPrice: response.shipment.price,
+        estimatedDelivery: response.shipment.estimated
+      }
+    } catch (err) {
+
+    }
+
+  },
+  computed: {
+    ...mapGetters(['getCart', 'getCartTotalPrice', 'getCartTotalPriceWithShipping'])
+  },
+  methods: {
+    async onChooseShipping (shipment) {
+      try {
+        let response = await this.$axios.$post('/api/shipment', { shipment })
+
+        this.$store.commit('setShipping', {
+          price: response.shipment.price,
+          estimatedDelivery: response.shipment.estimated
+        })
+
+        this.shippingPrice = response.shipment.price,
+        this.estimatedDelivery = response.shipment.estimated
+
+      } catch (err) {
+
+      }
+    }
+
+  }
+};
+</script>

+ 148 - 0
client/pages/search.vue

@@ -0,0 +1,148 @@
+<template>
+  <main class="listingPage">
+    <div class="container-fluid">
+      <div class="row">
+        <div class="col-xl-2 col-lg-3 md-4 col-sm-4">
+          <!--SideBar -->
+        </div>
+        <!-- main content -->
+        <div class="col-xl-10 col-lg-9 md-8 col-sm-8">
+
+
+          <div class="mainResuts">
+            <div class="s-result-list">
+              <div v-for="product in products" :key="product._id" class="s-result-item celwidget">
+                <div class="s-item-container">
+                  <div class="a-spacing-micro">
+                    <div class="bestSeller">
+                      <a href="#">Best seller</a>
+                    </div>
+                  </div>
+
+                  <div>
+                    <div class="row">
+                      <!--image-->
+                      <div class="col-sm-3 text-center">
+                        <a href="">
+                          <img :src="product.photo" alt="" class="img-fluid" style="width: 150px">
+                        </a>
+                      </div>
+
+                      <div class="col-sm-9">
+                        <div class="a-row a-spacing-small">
+                          <!-- Title and date -->
+                          <nuxt-link :to="`/products/${product._id}`" class="a-link-normal">
+                            <h2 class="a-size-medium">
+                              {{ product.title }}
+                              <span class="a-letter-space"></span>
+                              <span class="a-letter-space"></span>
+                              <span class="a-size-small a-color-secondary">Sep 3, 2019</span>
+                            </h2>
+                          </nuxt-link>
+                        </div>
+
+                        <!--Author name -->
+                        <div class="a-row a-spacing-small">
+                          <span class="a-size-small a-color-secondary">by</span>
+                          <span class="a-size-small a-color-secondary">
+                            <a href="#" class="a-link-normal a-text-normal">{{ product.owner.name }}</a>
+                          </span>
+                        </div>
+
+                        <!--Author name -->
+                        <div class="a-row">
+                          <span class="a-size-small">Ships to USA</span>
+                        </div>
+
+                        <div class="row">
+                          <div class="col-sm-7">
+                            <div class="a-row a-spacing-none">
+                              <a href="#" class="a-link-normal a-text-normal">Hardcover</a>
+                            </div>
+
+                            <!-- price-->
+                            <div class="a-row a-spacing-none">
+                              <a href="" class="a-link-normal a-text-normal">
+                                <span class="a-offscreen">{{ product.price }}</span>
+                                <span class="a-color-base sx-zero-spacing">
+                                  <span class="sx-price sx-price-large">
+                                    <sup class="sx-price-currency">$</sup>
+                                    <span class="sx-price-wholsup">{{ product.price }}</span>
+                                    <sup class="sx-price-fractional">00</sup>
+                                  </span>
+                                </span>
+                              </a>
+                              <span class="a-letter-space"></span>
+                              <span class="a-size-base-plug a-color-secondary a-text-strike">$28.00</span>
+                            </div>
+
+                            <!-- Audible Trial -->
+                            <div class="a-row a-spacing-none">
+                              <span class="a-size-small a-color-secondary">Free wuith trial </span>
+                            </div>
+                            <hr/>
+
+                            <!-- Other Format -->
+                            <span class="a-size-small a-color-secondray">
+                              other form
+                              <span class="a-letter-space"></span>
+                              <a href="" class="a-size-small a-linkl-normal a-text-normal">Audio CD</a>
+                            </span>
+
+                            <!-- Ratiings -->
+                            <div class="col-sm-5">
+                              <div class="a-row a-spacing-mini">
+                                <!-- star rating -->
+                                <no-ssr>
+                                  <star-rating
+                                    :rating="product.averageRating"
+                                    :show-rating="false"
+                                    :glow="1"
+                                    :border-width="1"
+                                    :rounded-corners="true"
+                                    :read-only="true"
+                                    :star-size="18"
+                                    :star-points="[23,2,14,17,0,19,10,34,7,50,23,43,38,50,36,34,46,19,31,17]"
+                                  ></star-rating>
+                                </no-ssr>
+                              </div>
+                            </div>
+                          </div>
+                        </div>
+
+                      </div>
+                    </div>
+                  </div>
+
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+  </main>
+</template>
+
+<script>
+import StarRating from 'vue-star-rating'
+
+export default {
+  components: {
+    StarRating
+  },
+  watchQuery: ['title'],
+
+  async asyncData ({ $axios, query }) {
+    try {
+      let products = await $axios.$post('/api/search', { title: query.title })
+
+      return {
+        products
+      }
+    } catch (err) {
+
+    }
+  }
+}
+</script>

+ 16 - 1
client/store/index.js

@@ -1,6 +1,9 @@
 export const state = () => ({
   cart: [],
-  cartLength: 0
+  cartLength: 0,
+  price: 0,
+  shippingPrice:0,
+  estimatedDelivery: ''
 })
 
 export const actions = {
@@ -57,6 +60,11 @@ export const mutations = {
     state.cartLength -= product.quantity
     let indexOfProduct = state.cart.indexOf(product)
     state.cart.splice(indexOfProduct, 1)
+  },
+
+  setShipping (state, { price, estimatedDelivery }) {
+    state.price = price
+    state.estimatedDelivery = estimatedDelivery
   }
 
 }
@@ -74,5 +82,12 @@ export const getters = {
       total += product.price * product.quantity
     })
     return total
+  },
+  getCartTotalPriceWithShipping (state) {
+    let total = 0
+    state.cart.map(product => {
+      total += product.price * product.quantity
+    })
+    return total + state.shippingPrice
   }
 }

+ 22 - 2
server/models/product.js

@@ -1,4 +1,5 @@
 const mongoose = require('mongoose')
+const mongooseAlgolia = require('mongoose-algolia')
 const Schema = mongoose.Schema
 
 const ProductSchema = new Schema({
@@ -18,7 +19,7 @@ const ProductSchema = new Schema({
 ProductSchema.virtual('averageRating').get(function () {
   if (this.reviews.length > 0) {
     let sum = this.reviews.reduce((total, review) => {
-      console.log('review', review)
+      // console.log('review', review)
       return total + review.rating
     }, 0)
     
@@ -28,4 +29,23 @@ ProductSchema.virtual('averageRating').get(function () {
   return 0
 })
 
-module.exports = mongoose.model('Product', ProductSchema)
+ProductSchema.plugin(mongooseAlgolia, {
+  appId: process.env.ALGOLIA_APP_ID,
+  apiKey: process.env.ALGOLIA_SECRET,
+  indexName: process.env.ALGOLIA_INDEX,
+  
+  selector: 'title _id photo description price rating averageRating owner',
+  populate: {
+    path: 'owner reviews'
+  },
+  debug: true
+})
+
+let Model = mongoose.model('Product', ProductSchema)
+Model.SyncToAlgolia()
+Model.SetAlgoliaSettings({
+  searchableAttributes: ['title']
+})
+
+module.exports = Model
+// module.exports = mongoose.model('Product', ProductSchema)

+ 293 - 0
server/package-lock.json

@@ -4,6 +4,11 @@
   "lockfileVersion": 1,
   "requires": true,
   "dependencies": {
+    "@types/node": {
+      "version": "13.1.6",
+      "resolved": "https://registry.npmjs.org/@types/node/-/node-13.1.6.tgz",
+      "integrity": "sha512-Jg1F+bmxcpENHP23sVKkNuU3uaxPnsBMW0cLjleiikFKomJQbsn0Cqk2yDvQArqzZN6ABfBkZ0To7pQ8sLdWDg=="
+    },
     "accepts": {
       "version": "1.3.7",
       "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
@@ -13,6 +18,45 @@
         "negotiator": "0.6.2"
       }
     },
+    "agentkeepalive": {
+      "version": "2.2.0",
+      "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-2.2.0.tgz",
+      "integrity": "sha1-xdG9SxKQCPEWPyNvhuX66iAm4u8="
+    },
+    "algoliasearch": {
+      "version": "3.35.1",
+      "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-3.35.1.tgz",
+      "integrity": "sha512-K4yKVhaHkXfJ/xcUnil04xiSrB8B8yHZoFEhWNpXg23eiCnqvTZw1tn/SqvdsANlYHLJlKl0qi3I/Q2Sqo7LwQ==",
+      "requires": {
+        "agentkeepalive": "^2.2.0",
+        "debug": "^2.6.9",
+        "envify": "^4.0.0",
+        "es6-promise": "^4.1.0",
+        "events": "^1.1.0",
+        "foreach": "^2.0.5",
+        "global": "^4.3.2",
+        "inherits": "^2.0.1",
+        "isarray": "^2.0.1",
+        "load-script": "^1.0.0",
+        "object-keys": "^1.0.11",
+        "querystring-es3": "^0.2.1",
+        "reduce": "^1.0.1",
+        "semver": "^5.1.0",
+        "tunnel-agent": "^0.6.0"
+      },
+      "dependencies": {
+        "isarray": {
+          "version": "2.0.5",
+          "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+          "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="
+        }
+      }
+    },
+    "ansi-regex": {
+      "version": "2.1.1",
+      "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
+      "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
+    },
     "append-field": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
@@ -126,6 +170,19 @@
       "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
       "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
     },
+    "cli-color": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.4.0.tgz",
+      "integrity": "sha512-xu6RvQqqrWEo6MPR1eixqGPywhYBHRs653F9jfXB2Hx4jdM/3WxiNE1vppRmxtMIfl16SFYTpYlrnqH/HsK/2w==",
+      "requires": {
+        "ansi-regex": "^2.1.1",
+        "d": "1",
+        "es5-ext": "^0.10.46",
+        "es6-iterator": "^2.0.3",
+        "memoizee": "^0.4.14",
+        "timers-ext": "^0.1.5"
+      }
+    },
     "concat-stream": {
       "version": "1.6.2",
       "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
@@ -198,6 +255,15 @@
         "vary": "^1"
       }
     },
+    "d": {
+      "version": "1.0.1",
+      "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
+      "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
+      "requires": {
+        "es5-ext": "^0.10.50",
+        "type": "^1.0.1"
+      }
+    },
     "debug": {
       "version": "2.6.9",
       "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@@ -206,6 +272,11 @@
         "ms": "2.0.0"
       }
     },
+    "deep-keys": {
+      "version": "0.4.0",
+      "resolved": "https://registry.npmjs.org/deep-keys/-/deep-keys-0.4.0.tgz",
+      "integrity": "sha1-AimHC98UV7BUy/VUhOkvivWcvqs="
+    },
     "depd": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
@@ -225,6 +296,11 @@
         "streamsearch": "0.1.2"
       }
     },
+    "dom-walk": {
+      "version": "0.1.1",
+      "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.1.tgz",
+      "integrity": "sha1-ZyIm3HTI95mtNTB9+TaroRrNYBg="
+    },
     "dotenv": {
       "version": "8.2.0",
       "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.2.0.tgz",
@@ -248,16 +324,84 @@
       "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
       "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
     },
+    "envify": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/envify/-/envify-4.1.0.tgz",
+      "integrity": "sha512-IKRVVoAYr4pIx4yIWNsz9mOsboxlNXiu7TNBnem/K/uTHdkyzXWDzHCK7UTolqBbgaBz0tQHsD3YNls0uIIjiw==",
+      "requires": {
+        "esprima": "^4.0.0",
+        "through": "~2.3.4"
+      }
+    },
+    "es5-ext": {
+      "version": "0.10.53",
+      "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz",
+      "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==",
+      "requires": {
+        "es6-iterator": "~2.0.3",
+        "es6-symbol": "~3.1.3",
+        "next-tick": "~1.0.0"
+      }
+    },
+    "es6-iterator": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
+      "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=",
+      "requires": {
+        "d": "1",
+        "es5-ext": "^0.10.35",
+        "es6-symbol": "^3.1.1"
+      }
+    },
+    "es6-promise": {
+      "version": "4.2.8",
+      "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
+      "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w=="
+    },
+    "es6-symbol": {
+      "version": "3.1.3",
+      "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz",
+      "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
+      "requires": {
+        "d": "^1.0.1",
+        "ext": "^1.1.2"
+      }
+    },
+    "es6-weak-map": {
+      "version": "2.0.3",
+      "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz",
+      "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==",
+      "requires": {
+        "d": "1",
+        "es5-ext": "^0.10.46",
+        "es6-iterator": "^2.0.3",
+        "es6-symbol": "^3.1.1"
+      }
+    },
     "escape-html": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
       "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
     },
+    "esprima": {
+      "version": "4.0.1",
+      "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+      "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
+    },
     "etag": {
       "version": "1.8.1",
       "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
       "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
     },
+    "event-emitter": {
+      "version": "0.3.5",
+      "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
+      "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=",
+      "requires": {
+        "d": "1",
+        "es5-ext": "~0.10.14"
+      }
+    },
     "events": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
@@ -300,6 +444,21 @@
         "vary": "~1.1.2"
       }
     },
+    "ext": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz",
+      "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==",
+      "requires": {
+        "type": "^2.0.0"
+      },
+      "dependencies": {
+        "type": {
+          "version": "2.0.0",
+          "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz",
+          "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow=="
+        }
+      }
+    },
     "file-type": {
       "version": "3.9.0",
       "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz",
@@ -337,6 +496,11 @@
         }
       }
     },
+    "foreach": {
+      "version": "2.0.5",
+      "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz",
+      "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k="
+    },
     "forwarded": {
       "version": "0.1.2",
       "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
@@ -347,6 +511,15 @@
       "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
       "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
     },
+    "global": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz",
+      "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==",
+      "requires": {
+        "min-document": "^2.19.0",
+        "process": "^0.11.10"
+      }
+    },
     "html-comment-regex": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/html-comment-regex/-/html-comment-regex-1.1.2.tgz",
@@ -387,6 +560,11 @@
       "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.0.tgz",
       "integrity": "sha512-M4Sjn6N/+O6/IXSJseKqHoFc+5FdGJ22sXqnjTpdZweHK64MzEPAyQZyEU3R/KRv2GLoa7nNtg/C2Ev6m7z+eA=="
     },
+    "is-promise": {
+      "version": "2.1.0",
+      "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz",
+      "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o="
+    },
     "is-svg": {
       "version": "2.1.0",
       "resolved": "https://registry.npmjs.org/is-svg/-/is-svg-2.1.0.tgz",
@@ -453,6 +631,11 @@
       "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.1.tgz",
       "integrity": "sha512-l3hLhffs9zqoDe8zjmb/mAN4B8VT3L56EUvKNqLFVs9YlFA+zx7ke1DO8STAdDyYNkeSo1nKmjuvQeI12So8Xw=="
     },
+    "load-script": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/load-script/-/load-script-1.0.0.tgz",
+      "integrity": "sha1-BJGTngvuVkPuSUp+PaPSuscMbKQ="
+    },
     "lodash.includes": {
       "version": "4.3.0",
       "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
@@ -488,11 +671,34 @@
       "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
       "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
     },
+    "lru-queue": {
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz",
+      "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=",
+      "requires": {
+        "es5-ext": "~0.10.2"
+      }
+    },
     "media-typer": {
       "version": "0.3.0",
       "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
       "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
     },
+    "memoizee": {
+      "version": "0.4.14",
+      "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz",
+      "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==",
+      "requires": {
+        "d": "1",
+        "es5-ext": "^0.10.45",
+        "es6-weak-map": "^2.0.2",
+        "event-emitter": "^0.3.5",
+        "is-promise": "^2.1",
+        "lru-queue": "0.1",
+        "next-tick": "1",
+        "timers-ext": "^0.1.5"
+      }
+    },
     "memory-pager": {
       "version": "1.5.0",
       "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
@@ -527,6 +733,14 @@
         "mime-db": "1.42.0"
       }
     },
+    "min-document": {
+      "version": "2.19.0",
+      "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz",
+      "integrity": "sha1-e9KC4/WELtKVu3SM3Z8f+iyCRoU=",
+      "requires": {
+        "dom-walk": "^0.1.0"
+      }
+    },
     "minimist": {
       "version": "0.0.8",
       "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
@@ -540,6 +754,11 @@
         "minimist": "0.0.8"
       }
     },
+    "moment": {
+      "version": "2.24.0",
+      "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
+      "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg=="
+    },
     "mongodb": {
       "version": "3.4.1",
       "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.4.1.tgz",
@@ -576,6 +795,16 @@
         }
       }
     },
+    "mongoose-algolia": {
+      "version": "1.9.1",
+      "resolved": "https://registry.npmjs.org/mongoose-algolia/-/mongoose-algolia-1.9.1.tgz",
+      "integrity": "sha512-lpQptDr2OnSjBV8OUNfGdqV4pVV41dP3ikZHTx9uBVXmvZXetOh29H6Smn7Z/OfpCRovrbNxwXD7mj8MdTtEgw==",
+      "requires": {
+        "algoliasearch": "^3.19.1",
+        "cli-color": "^1.1.0",
+        "deep-keys": "^0.4.0"
+      }
+    },
     "mongoose-legacy-pluralize": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz",
@@ -655,11 +884,21 @@
       "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
       "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
     },
+    "next-tick": {
+      "version": "1.0.0",
+      "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz",
+      "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw="
+    },
     "object-assign": {
       "version": "4.1.1",
       "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
       "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM="
     },
+    "object-keys": {
+      "version": "1.1.1",
+      "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+      "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
+    },
     "on-finished": {
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
@@ -683,6 +922,11 @@
       "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
       "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
     },
+    "process": {
+      "version": "0.11.10",
+      "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+      "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI="
+    },
     "process-nextick-args": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
@@ -712,6 +956,11 @@
       "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
       "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA="
     },
+    "querystring-es3": {
+      "version": "0.2.1",
+      "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
+      "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM="
+    },
     "range-parser": {
       "version": "1.2.1",
       "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
@@ -746,6 +995,14 @@
         }
       }
     },
+    "reduce": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/reduce/-/reduce-1.0.2.tgz",
+      "integrity": "sha512-xX7Fxke/oHO5IfZSk77lvPa/7bjMh9BuCk4OOoX5XTXrM7s0Z+MkPfSDfz0q7r91BhhGSs8gii/VEN/7zhCPpQ==",
+      "requires": {
+        "object-keys": "^1.1.0"
+      }
+    },
     "regexp-clone": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz",
@@ -876,11 +1133,47 @@
       "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
       "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
     },
+    "stripe": {
+      "version": "8.0.1",
+      "resolved": "https://registry.npmjs.org/stripe/-/stripe-8.0.1.tgz",
+      "integrity": "sha512-0D9r1YGkrNFmX6RRk34P0uslrOw4cuav1yuJVcxlIwwhh8R06XIqTTPU6/PeGvJ89SUTU/+jny8gFZU0MZ0rpg==",
+      "requires": {
+        "@types/node": "^13.1.0",
+        "qs": "^6.6.0"
+      }
+    },
+    "through": {
+      "version": "2.3.8",
+      "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
+      "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
+    },
+    "timers-ext": {
+      "version": "0.1.7",
+      "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz",
+      "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==",
+      "requires": {
+        "es5-ext": "~0.10.46",
+        "next-tick": "1"
+      }
+    },
     "toidentifier": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
       "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
     },
+    "tunnel-agent": {
+      "version": "0.6.0",
+      "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+      "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
+      "requires": {
+        "safe-buffer": "^5.0.1"
+      }
+    },
+    "type": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
+      "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg=="
+    },
     "type-is": {
       "version": "1.6.18",
       "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",

+ 5 - 1
server/package.json

@@ -9,6 +9,7 @@
   "author": "",
   "license": "ISC",
   "dependencies": {
+    "algoliasearch": "^3.35.1",
     "aws-sdk": "^2.596.0",
     "axios": "^0.19.1",
     "bcrypt-nodejs": "0.0.3",
@@ -17,9 +18,12 @@
     "dotenv": "^8.2.0",
     "express": "^4.17.1",
     "jsonwebtoken": "^8.5.1",
+    "moment": "^2.24.0",
     "mongoose": "^5.8.3",
+    "mongoose-algolia": "^1.9.1",
     "morgan": "^1.9.1",
     "multer": "^1.4.2",
-    "multer-s3": "^2.9.0"
+    "multer-s3": "^2.9.0",
+    "stripe": "^8.0.1"
   }
 }

+ 36 - 0
server/routes/payment.js

@@ -0,0 +1,36 @@
+const router = require('express').Router()
+const moment = require('moment')
+
+const SHIPMENT = {
+  normal: {
+    price: 13.98,
+    days: 7
+  },
+  fast: {
+    price: 49.98,
+    days: 3
+  }
+}
+
+function shipmentPrice (shipmentOption) {
+  let estimated = moment().add(shipmentOption.days, 'd').format('dddd MMMM Do')
+  return {
+    estimated,
+    price: shipmentOption.price
+  }
+}
+
+router.post('/shipment', (req, res) => {
+  let shipment;
+  if (req.body.shipment === 'normal') {
+    shipment = shipmentPrice(SHIPMENT.normal)
+  } else {
+    shipment = shipmentPrice(SHIPMENT.fast)
+  }
+
+  res.json({
+    success: true,
+    shipment
+  })
+})
+module.exports = router

+ 20 - 0
server/routes/search.js

@@ -0,0 +1,20 @@
+const router = require('express').Router()
+
+const algoliraSearch = require('algoliasearch')
+
+const client = algoliraSearch(
+  process.env.ALGOLIA_APP_ID,
+  process.env.ALGOLIA_SECRET,
+)
+
+const index = client.initIndex(process.env.ALGOLIA_INDEX)
+router.post('/search', async (req, res) => {
+  try {
+    let result  = await index.search(req.body.title)
+    res.json(result.hits)
+  } catch (err) {
+    res.json(err.message)
+  }
+})
+
+module.exports = router

+ 4 - 0
server/server.js

@@ -31,6 +31,8 @@ const ownerRouters = require('./routes/owner')
 const userRouters = require('./routes/auth')
 const reviewRouters = require('./routes/review')
 const addressRouters = require('./routes/address')
+const paymentRouters = require('./routes/payment')
+const searchRouters = require('./routes/search')
 
 
 app.use('/api', productRouters)
@@ -39,6 +41,8 @@ app.use('/api', ownerRouters)
 app.use('/api', userRouters)
 app.use('/api', reviewRouters)
 app.use('/api', addressRouters)
+app.use('/api', paymentRouters)
+app.use('/api', searchRouters)
 
 app.listen(3000, (err) => {
   if (err) {