Setting up an ASP.NET Core Restaurant Website with a Vue.js Online Ordering Page.
Tags: vue, csharp, webdev, sql
Published: 2020-01-26 12:30:55

I went ahead and installed [.NET Core](https://dotnet.microsoft.com/download) 2.2. I used a starter pizza related bootstrap 4 theme from [colorlib](https://colorlib.com/) for base [CSS](https://www.w3schools.com/css/), with the only license requirement being a link to [colorlib](https://colorlib.com/) in the footer.

Once I had customized the pages and stylings, I started to build a [Vue.js](https://vuejs.org/) powered online ordering page. I used [entity framework](https://docs.microsoft.com/en-us/ef/core/get-started/?tabs=netcore-cli) to build a database schema in an [MS SQL](https://www.microsoft.com/en-us/sql-server/sql-server-2019) [Azure](https://azure.microsoft.com/en-us/) database.


I downloaded the [Vue.js](https://vuejs.org/) library file and put it in the `/wwwroot/js` which I include in the `/Views/Order/index.cshtml` file at the bottom as:

    <script  src="~/js/vue.js"></script>
    <script  src="~/js/orderpage.js"></script>

`Views/Order/index.cshtml` is the root [Vue.js Template](https://vuejs.org/v2/guide/syntax.html).

I initialize the root [Vue.js](https://vuejs.org/) instance in the `/wwwroot/js/orderpage.js` file with a function call similar to this:

    var  app  =  new  Vue({
        el:  '#app'
    )};

In the [Vue.js initialization](https://vuejs.org/v2/guide/index.html) function call above, I set the `data`, `computed`, `filters`, `methods`, and a `mounted` life-cycle hook.

This is how the order page Vue.js app looks with the styling and after the Vue initialization has finished:
![Image of the front-end ordering page with categories, items in the selected category, and cart information shown](https://thepracticaldev.s3.amazonaws.com/i/d5glzzt27yoyu99vnfk0.jpg)

I include 
`<script  src="https://js.stripe.com/v3/"></script>`
in the `/Views/Shared/_Layout.cshtml`.

On the second step, checkout, if a user has selected credit as payment, a stripe credit card input appears because of the inclusion of following logic at the bottom of `/wwwroot/js/orderpage.js`:

    $(document).ready(function () {
        stripe  =  Stripe($('#StripeApiKey').val());
        var  elements  =  stripe.elements();
        card  =  elements.create('card');
        card.mount('#card-element');
        card.addEventListener('change', function (event) {
            var  displayError  =  document.getElementById('card-errors');
            if (event.error) {
                displayError.textContent  =  event.error.message;
            } else {
                displayError.textContent  =  '';
            }
        });
    });

The checkout step looks like this:
![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/k1u9y7rkfbqai82yqogo.jpg)

The `Controllers/OrderController.cs` houses all of the Ecommerce logic and APIs. I should probably split it into smaller files, but I haven't felt the need to yet.

The `public  IActionResult PlaceOrder(OrderParam  order, bool  pos  =  false)` method is the entry point to placing an order. This method calls a lot of private methods, because if all the code was in one method, it would be too long. It does data validation based on certain options the customer selected. If the customer selected delivery, it will ask [Google Map's API](https://developers.google.com/maps/documentation) if the distance between the customer and the restaurant is less than a certain amount of miles.

The method `private  bool  ValidateOrderPrices(OrderParam  order, bool  isPOS)` validates the user's supplied cart prices to see if they match the prices in the database. `isPOS` tells the method if it should expect a delivery fee.

I charge the customer via [Stripe](https://stripe.com/) if the customer selected the credit payment type and they are on the customer facing website online ordering system ([http://stunodspizza.com/order](http://stunodspizza.com/order)) 

The following code creates a [Stripe](https://stripe.com/) charge:

    var  options  =  new  ChargeCreateOptions
    {
        Amount  =  Convert.ToInt32(order.total*100),
        Currency  =  "usd",
        Description  =  "Stunod's Charge for "+order.email,
        Source  =  order.stripeToken,
        ReceiptEmail  =  order.email,
        Metadata  =  metadata
    };
    var  service  =  new  ChargeService();
    try{
        Charge  charge  =  service.Create(options);
    }catch(Exception  exception){
        return  Json(new{Success  =  false, Message="Unable to process credit/debit card."});
    }

If the user did not select credit as a payment method, or the [Stripe](https://stripe.com/) payment was successful, the order is saved to the database using the method `private  int  SaveOrderToDatabase(OrderParam  order, bool  placedOnPOS)`.

The `PlaceOrder` method also generates emails by using replace string methods on text files for dynamic data. If the business has emails listed in the `/appSettings.json`, they will receive receipt emails. The customer will also receive an email receipt if a customer email was supplied in the order.

Text messages are also sent to business and/or customers via a simple [Twilio API](https://www.twilio.com/).

Within the `PlaceOrder` method, a PDF is generated with certain thin width dimensions using the library [PdfSharp](https://www.nuget.org/packages/PdfSharpCore/). This PDF gets sent via `HTTPS` to a [python](https://www.python.org/) [development flask server](https://flask.palletsprojects.com/en/1.1.x/). The server gets booted by the client by double clicking a `.sh` file on a [raspberry pi](https://www.raspberrypi.org/) desktop. The `.sh` script also runs a [noip](https://www.noip.com/) library for use as a DDNS service. This allows the web app on [Azure](https://azure.microsoft.com/en-us/) to send the PDF receipt to a URL that stays aware of the printer's router's IP address. The [python](https://www.python.org/) [development flask server](https://flask.palletsprojects.com/en/1.1.x/) receives, downloads, and prints the PDF receipt using CUPS and a [nice print driver](https://github.com/klirichek/zj-58) for the restaurant's `TM-T20II POS Thermal Receipt Printer` connected to the `raspberry pi` via USB. If you're interested in the printer setup, please check out the `raspberry-pi/README.md` when I release the source code at the end of this [dev.to](https://dev.to/) series.

## Coming up next: a Vue.js CLI App walkthrough and tutorial

> I walk you through building a web app that's a full point of sale, a
> order history management app. a sales reporting app, and a Ecommerce CMS with
> functionality for editing hours and menu items. The whole projects is in
> a nested folder setup with the [Vue
> CLI](https://cli.vuejs.org/guide/). When we run `yarn build` it will
> place our Vue app in the `/Views/POS/index.cshtml` with its assets in
> the `/wwwroot/js` and `/wwwroot/css` folders. Both our
> development and production builds will be able to hit API functions in
> the `/Controllers/OrderController.cs` by use of the
> `/pizza-pos/vue.config.js`.

## Note:
### I'll be releasing the open source code at the end of the series.