Skip to content

gregrickaby/vue-commerce-lab

Repository files navigation

VueCommerceLab

Project Overview πŸš€

This repository houses an experimental E-commerce dashboard that serves as a practical application for learning and implementing Laravel. I scaffolded this with Laravel Breeze and use Laravel Valet for local development.

Key Features πŸ› 

  • CRUD Operations: Comprehensive Create, Read, Update, and Delete functionalities for products and customers, showcasing Laravel's robust back-end capabilities.
  • Laravel 10: A powerful PHP framework for building scalable web applications with a clean, expressive syntax.
  • TypeScript: A superset of JavaScript that adds static type definitions, enabling a more robust development experience.
  • Vue.js 3: A dynamic and reactive frontend built with Vue.js, offering an engaging user experience.
  • Ziggy: Exposes Laravel's named server-side routes via a global route() function, allowing for easy route generation in Vue components.
  • Inertia.js: Bridges Laravel and Vue.js, enabling server-side rendering and client-side navigation without page reloads.
  • TailwindCSS: A utility-first CSS framework used for designing sleek, responsive layouts with speed and efficiency.
  • Storybook: A development environment for UI components, allowing for rapid iteration and testing.
  • Atomic Design: A methodology for designing UIs with a focus on reusability and scalability.
  • Tests: Unit tests for all models and controllers using PHPUnit, and component tests for Vue.js components using Vitest and Vue Test Utils.
  • Linting and Formatting: Automatic linting and formatting for PHP, JavaScript, CSS and Vue.js files.
  • Github Actions: Continuous integration and testing with Github Actions.

Learning Outcomes πŸ“š

  • Mastering Laravel's MVC architecture for building scalable web applications.
  • Implementing SPA behaviors in Laravel with Vue.js and Inertia.js.
  • Developing intuitive UIs with Tailwind CSS.
  • Understanding state management and reactivity in Vue.js.
  • Grasping the principles of RESTful API design and CRUD operations in Laravel.
  • Writing unit tests for models and controllers with PHPUnit and Vitest.

Project Sections πŸ”

  • Products: Includes features like product listing, adding new products, editing, and deleting.
  • Customers: Manages customer data with functionalities for adding, viewing, editing, and removing customer records.
  • Orders: Allows users to place orders for products, with a dedicated page for viewing all orders.
  • Reports: Provides a dashboard for viewing sales reports and other metrics.

Motivation πŸ’‘

This project serves as a comprehensive example for anyone interested in developing full-featured web applications using these technologies.


Installation

Clone the repository (into your Valet sites directory):

git clone git@github.com:gregrickaby/vue-commerce-lab.git

Install dependencies:

composer install && npm install

Create .env file:

cp .env.example .env

Create database.sqlite file:

touch database/database.sqlite

Generate application key:

php artisan key:generate

Run a migration:

php artisan migrate:fresh

Seed the database:

php artisan db:seed

Set the PHP version to 8.3:

valet isolate php@8.3

Secure the site:

valet secure

Start development server:

npm run dev

Visit the site: https://vue-commerce-lab.test and login with the following credentials:


Laravel

Models

Models are located in the app/Models directory. Each model has a corresponding factory and seeder in the database/factories and database/seeders directories.

Models are responsible for managing the data of the application. They receive input from the controller, validate it, then send it to the database.

Views

This application uses Vue and Inertia, so the views are in the resources/js/pages directory and routed via the web.php file.

Views are responsible for displaying the data to the user. They receive data from the controller, then render it to the browser.

Controllers

Controllers are located in the app/Http/Controllers directory. Each controller has a corresponding test in the tests/Feature directory

Controllers are responsible for handling requests and returning responses. They receive input from the user, validate it, then pass it to the model.

Routes

Routes are located in the routes directory. The web.php file contains all the routes for the application.


Vue.js

Vue.js files are located in the resources/js directory.

Directory Structure

The directory structure follows standard Laravel conventions, with the addition of a types directory for TypeScript interfaces and types, and a utils directory for utility and helper functions.

β”œβ”€β”€ resources
β”‚   β”œβ”€β”€ css
β”‚   β”‚   └── app.css <-- TailwindCSS
β”‚   β”œβ”€β”€ js
β”‚   β”‚   β”œβ”€β”€ Components
β”‚   β”‚   β”‚   β”œβ”€β”€ Atoms
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ ApplicationLogo
β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ ApplicationLogo.stories.ts <-- Storybook
β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ ApplicationLogo.test.ts <-- Test
β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ ApplicationLogo.test.ts.snap <-- Snapshot
β”‚   β”‚   β”‚   β”‚   β”‚   └── ApplicationLogo.vue <-- Vue Component
β”‚   β”‚   β”‚   β”œβ”€β”€ Molecules
β”‚   β”‚   β”‚   β”œβ”€β”€ Organisms
β”‚   β”‚   β”œβ”€β”€ Layouts
β”‚   β”‚   β”œβ”€β”€ Pages
β”‚   β”‚   β”‚   β”œβ”€β”€ Customers
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ Create.vue
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ Index.vue
β”‚   β”‚   β”‚   β”‚   └── {customer} <-- Dynamic route
β”‚   β”‚   β”‚   β”‚       β”œβ”€β”€ Edit.vue
β”‚   β”‚   β”‚   β”‚       └── Show.vue
β”‚   β”‚   β”œβ”€β”€ app.ts <-- Vue app
β”‚   β”‚   β”œβ”€β”€ types
β”‚   β”‚   β”‚   └── index.d.ts <-- Typescript interfaces and types
β”‚   β”‚   └── utils
β”‚   β”‚       └── index.ts <-- Utility and helper functions
β”‚   └── views
β”‚       β”œβ”€β”€ app.blade.php
β”‚       └── welcome.blade.php

Dynamic Routes

Folders with a {} around them are dynamic routes. For example, /Pages/Customers/{customers}/Edit.vue is a dynamic route that will match any customer ID. The ID is then available in the Edit.vue component.


Tests

This application is equipped with both PHPUnit and Vitest for testing. It also leverages Github Actions for continuous integration and testing, and Storybook for developing UI components in isolation.

PHPUnit

This application is equipped with PHPUnit tests for all models and controllers. PHP tests are located in the /tests directory:

β”œβ”€β”€ tests
β”‚   β”œβ”€β”€ Feature
β”‚   β”‚   β”œβ”€β”€ Auth
β”‚   β”‚   β”‚   β”œβ”€β”€ AuthenticationTest.php
β”‚   β”‚   └── ExampleTest.php
β”‚   └── Unit
β”‚       └── ExampleTest.php

Laravel routes return Inertia responses that depend on the presence of Vue components. Without the built front-end assets, these components won't be available, leading to failures in tests that make requests to these routes. To avoid this, you must run the development server in the background while running tests.

Start the development server:

npm run dev

Run PHPUnit tests with:

php artisan test

Run a specific test with:

php artisan test --filter=CustomerTest

Vue Component Testing

This application is equipped with both Vitest (official test runner) and Vue Test Utils (official testing library) for testing Vue components. Tests must be placed next to the component and named ComponentName.test.ts:

β”œβ”€β”€ resources
β”‚   β”œβ”€β”€ js
β”‚   β”‚   β”œβ”€β”€ Components
β”‚   β”‚   β”‚   β”œβ”€β”€ Atoms
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ ApplicationLogo
β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ ApplicationLogo.stories.ts <-- Storybook
β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ ApplicationLogo.test.ts <-- Test
β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ ApplicationLogo.test.ts.snap <-- Snapshot
β”‚   β”‚   β”‚   β”‚   β”‚   └── ApplicationLogo.vue <-- Vue Component

You can run the tests with:

npm run test

Vitest will run the tests in watch mode, so you can make changes to the component and see the results in real-time.

Writing Component Tests

Component tests are written in TypeScript and use the Vitest API for assertions. Here's an example:

import ApplicationLogo from '@/Components/Atoms/ApplicationLogo/ApplicationLogo.vue'
import { mount } from '@vue/test-utils'
import { describe, expect, test } from 'vitest'

/**
 * Define a test suite.
 *
 * @see https://vitest.dev/api/#describe
 */
describe('ApplicationLogo', () => {
    /**
     * Mount the component.
     *
     * @see https://vue-test-utils.vuejs.org/api/#mount
     */
    const wrapper = mount(ApplicationLogo)

    /**
     * Assert the component renders.
     *
     * @see https://vitest.dev/api/expect.html
     */
    test('component renders', () => {
        expect(wrapper).toBeTruthy()
    })

    /**
     * Assert the component is a SVG.
     */
    test('component is SVG', () => {
        wrapper.find('svg')
    })

    /**
     * Assert the component matches the snapshot.
     *
     * @see https://vitest.dev/api/expect.html#tomatchsnapshot
     */
    test('component matches snapshot', () => {
        expect(wrapper.html()).toMatchSnapshot()
    })
})

Helpful Links

  1. Vitest API
  2. Vue Test Utils API

Github Actions

Github Actions will also run the tests on every PR to the main branch.


Linting

ESLint

This application is equipped with ESLint and configured for parsing TypeScript. Automatic linting JavaScript and Vue files happens on_save.

You can also run lint manually:

npm run lint

Stylelint and TailwindCSS (Prettier)

This application is equipped with Stylelint and the Prettier plugin for TailwindCSS. Automatic linting and formatting happens on_save.

Prettier and Pint

Automatic formatting for both JavaScript and PHP files is configured for on_save. Please see the VSCode settings and extension configs for more information.

Manually run Prettier and Pint with:

npm run format && composer run lint

Storybook

View Storybook: https://gregrickaby.github.io/vue-commerce-lab/ πŸ‘€

This application is equipped with Storybook for developing UI components in isolation. Stories must be written in CSF, placed next to the component in the resources/js/Components directory. Stories must be named ComponentName.stories.ts:

β”œβ”€β”€ resources
β”‚   β”œβ”€β”€ js
β”‚   β”‚   β”œβ”€β”€ Components
β”‚   β”‚   β”‚   β”œβ”€β”€ Atoms
β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ ApplicationLogo
β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ ApplicationLogo.stories.ts <-- Storybook
β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ ApplicationLogo.test.ts <-- Test
β”‚   β”‚   β”‚   β”‚   β”‚   β”œβ”€β”€ ApplicationLogo.test.ts.snap <-- Snapshot
β”‚   β”‚   β”‚   β”‚   β”‚   └── ApplicationLogo.vue <-- Vue Component

Run Storybook with:

npm run storybook

Build Storybook with:

npm run build:storybook

License

The MIT License (MIT). Please see LICENSE