Shopper store is an application that lists shops near your by distance. It allows you to have your own personal list of favourite/preferred shops that you like for easier access rather than browsing through the entire collection all shops.
- Introduction
- Prerequisites
- Installation
- Database Seeding
- Running
- Features
- Architecture
- Contributing
- Author
- Credits
To adhere to the technical specifications of the challenge requiring the solution to be a single page application, the application uses Vue.js in the front-end for routing & navigation between pages while the backend is written in Asp.Net Core 2.2.1
Below is a list of all the tools & developer resources required to get the project up and running.
- Visual Studio 2019
- .NET Core SDK 2.2
- Nuget - Package manager for .NET apps.
- Entity Framework Core - Will act as our ORM.
- Asp.Net Core Identity - Membership system to add login/register functionality.
- Node.js - Required for acquisition of npm packages, running webpack commands e.t.c
- Webpack - For bundling & minification of front-end dependecies as we shall see later on in this document.
To get the application started on your local machine, first clone this git repository by running the following command on a terminal in a folder of your choice.
git clone https://github.com/tmacharia/shop-challenge-vue.git
Navigate to the cloned directory as follows by running cd shop-challenge-vue
Restore/Install Dependencies
First, let's get all dependecies & npm packages installed by consecutively running the following commands
Packages Restore/Install
npm run restore
This command will run two commands, dotnet restore to restore all .NET nuget packages & npm install that will install all devDependencies needed as outlined in package.json
We now need to generate the static resources i.e js,and css files that will be rendered by the browser and also build the .NET project (the backend) to ascertain that it builds successfully and therefore can run. There are two sets of scripts in package.json for building the project. Both will build the project & generate our static resources in our public folder wwwroot
npm run build-dev
Builds the project in Debug mode and generates sitemaps for the static resources as you will see after running this command. You can checkout webpack.config.js to how we instruct webpack to generate our files in Development mode.
npm run build-prod
Builds the project in Release mode, generates our static resources & optimizes them by applying UglifyJsPlugin to reduce the size of the output js files.
To create database schemas & initial seed data to get our application up running, we need to apply the migrations in the 📁 Migrations folder.
Before you run the migrations, you need to confirm that the database ConnectionString is correct in appsettings.json. Make sure that is points to a valid instance of Microsoft SQL Server.
Command to apply migrations & seed initial data:
dotnet ef database update --verbose
That's it! The application is now ready to run.
Just run the following command on a terminal in the root directory of the project
dotnet run
The application will immediately start running:
http://locahost:5000
- View Nearby Shops - access this on the main page or by navigating to either of the following paths on your browser: (
/shops
) - Like Shop - like a shop so that it appears under My Preferred Shops for easy access & hidden from the main page.
- Dislike Shop - unfavourite a shop by disliking it so that it's hidden from the mainpage for the next 2 hours.
- Remove Preferred Shop - deletes a shop from the list of My Preferred Shops and unhides from the mainpage. (
/shops/preferred
) - User SignUp - allows users to signup/register an account using an email address, username & password. (
/account/signup
) - User SignIn - allows already registered users to sign in to their account. (
/account/signin
)
Using vue.js, we modularize all our features/requirements into components with each having it's own folder as shown in the figure below.
📦ClientApp
┣ 📂components
┃ ┣ 📂account
┃ ┃ ┣ 📜account.css
┃ ┃ ┣ 📜account.ts
┃ ┃ ┣ 📜account.vue.html
┃ ┃ ┣ 📜signin.ts
┃ ┃ ┣ 📜signin.vue.html
┃ ┃ ┣ 📜signup.ts
┃ ┃ ┗ 📜signup.vue.html
┃ ┣ 📂app
┃ ┃ ┣ 📜app.ts
┃ ┃ ┗ 📜app.vue.html
┃ ┣ 📂navmenu
┃ ┃ ┣ 📜navmenu.css
┃ ┃ ┣ 📜navmenu.ts
┃ ┃ ┗ 📜navmenu.vue.html
┃ ┣ 📂preferred-shops
┃ ┃ ┣ 📜preferred-shops.ts
┃ ┃ ┗ 📜preferred-shops.vue.html
┃ ┣ 📂shops
┃ ┃ ┣ 📜shops.ts
┃ ┃ ┗ 📜shops.vue.html
┃ ┗ 📜cookiesHelper.ts
┣ 📂css
┃ ┗ 📜site.css
┗ 📜boot.ts
In boot.ts, which acts as the main entry point for our frontend application, we register routes for all our features that will instruct the browser what to render for what routes.
Server-side solution architecture, structure & organization.
Below is a list of some of the design patterns, principles and best practises in accordance to the framework used (AspNet Core) & general software engineering guidelines:
1 Inversion of Control Containers & Dependency Injection Pattern
As you can see in the figure above, we are adding ShopDbContext to the default Asp.Net Core container so that it can be available to any controller at runtime.Inversion of control is all about giving control to the container to get instance objects rather than creating objects using the new operator, let the container do that for you.
We are also configuring Microsoft ASP.NET Core Identity Users model, Roles model, and the storage provider for these models. This will in turn avail identity interfaces, and other methods to use in user account membership & access control.
Let's now see how we use the added services in our controllers/Api Endpoints.
Dependency Injection in AccountsController
Dependency Injection in ShopsController
Just fork this repository to get started.
N.B Follow the project's current structure & methodologies when adding new features to enable consitency in throughout the project.
Let's say you want to add a new feature, below are some guidelines to get you started:
- Create a new page - by adding a new component in ClientApp/components/{feature-name}/. Remember to use a descriptive name that symbolizes what your feature does.
- Add html, css, and Typescript file as it is in the other components.
- Register route - add a route in ClientApp/boot.ts that points to your component so users can access it.
- If your feature does/requires some server processing, you may need to create a controller in Controllers/ folder and add the API endpoints you need. You can call your endpoints from the frontend in your Typescript file using Axios as it is the case ClientApp/components/shops.ts component.
- If you need a new database table, all schema definitions are in the Models/ folder, once you've added your new class, remember to add it to ShopDbContext class so that EntityFramework knows that a new table/migration should be generated.
Once you've made your updates; be it updates, fixes, or new feature developments, create a pull request and your changes will get reviewed and merged to master.
Project written by Timothy Macharia
Incase of any questions, drop me an inbox at my 📧Email
This project is part of a coding challenge by United Remote