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.
route()
function, allowing for easy route generation in Vue components.This project serves as a comprehensive example for anyone interested in developing full-featured web applications using these technologies.
Clone the repository (into your Valet sites directory):
git clone [email protected]: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 [email protected]
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:
password
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.
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 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 are located in the routes
directory. The web.php
file contains all the routes for the application.
Vue.js files are located in the resources/js
directory.
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
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.
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.
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
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.
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()
})
})
Github Actions will also run the tests on every PR to the main
branch.
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
This application is equipped with Stylelint and the Prettier plugin for TailwindCSS. Automatic linting and formatting happens on_save
.
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
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
The MIT License (MIT). Please see LICENSE