
Welcome to the course! Let's talk about Jot, the project we'll be building and get familiar with the end goal of the course. Hope you join me on this journey as we build Jot from scratch.
To get started, let's install a fresh installation of Laravel and get working on setting up our project.
In this episode, we cover:
Scaffolding of new Laravel project
Scaffolding of authentication
Strip all of the default front-end
Install Vue, Vue Router & Tailwindcss using NPM
Our application will need a combination of Laravel route and Vue Router. Let's get it all setup.
In this episode, we cover:
Laravel Routing
Vue Router
Front-end Setup Complete
Vue Components
Single Page Applications or SPAs are driven by APIs. If you are not familiar, we will cover the basics of it in this video.
In this episode, we cover:
RESTful Controllers
7 RESTful Verbs
Introduction to API Development
In order to get the TDD workflow working, we need to take some extra steps to finish the setup.
In this episode, we cover:
Setting up Testing Database
Bash aliases for PHPUnit
Creating our first feature test
First stab at adding contacts to the database test
Now that we have the basic test working, let's explore how to perform validation to our project.
In this episode, we cover:
Adding other fields to contact model
Writing validation tests
With all of the test in green and passing state, let's take time cleanup and refactor parts of our test suite.
In this episode, we cover:
Extracting data into a private method
Extracting validation tests into systematic method
DRY-ing up tests
Let's continue on to the 2 special fields that we have. The email and the birthday field.
In this episode, we cover:
Validation for email addresses
Casting of Birthday field as Carbon instance
Laravel Mutators
Parsing dates on the fly with Carbon::parse()
Reformatting dates for testing purposes
Retrieving single a contact from the database is the mission during this lesson.
In this episode, we cover:
Test for retrieving a single contact
Contact Model Factory
Using faker for test data on the fly
Adds a route for the contact show action
It's time to cover patching a contact using the PATCH method.
In this episode, we cover:
PATCH vs PUT
Contact can be patched Test
Using Laravel fresh() to get fresh database data
Adding a path route
Validating data during patch
Next up in the CRUD actions, it's time to tackle the destroy action for deleting a contact.
In this episode, we cover:
Testing for deleting a contact
Route for a delete request
Deleting a contact using Eloquent
Introduction to multi-tenancy
It's time to start refining our API to get it closer to production-ready code.
In this episode, we cover:
Review of project so far
Test to assert a user gets redirected when they are not authenticated
Locking up all of our Routes using the middleware auth:api
Fixing broken "contact can be added" test
Update UserFactory class
Refactoring our test to create a user during the SetUp method
Let's handle the index action and take the time to associate our contacts to the user that created the contact.
In this episode, we cover:
Test for making sure only the authenticated user's contacts get returned
Creating an Eloquent relationship for a User hasMany Contacts
If we run our test suite right now, we find a lot of broken tests. Let's start fixing them one at a time.
In this episode, we cover:
Fixing broken tests
Overriding data when using model factories
Checking if the authenticated user is authorized to perform an action
Detecting false green tests
Contact belongsTo a User
Proper HTTP Status Codes
404 vs 401 vs. 403 Status Codes
Let's fix all of the remaining tests.
In this episode, we cover:
Storing a contact through the relationship using create()
Test to assert only the owner of a contact can retrieve it
Test to assert only the owner of a contact can patch it
Test to assert only the owner of a contact can delete it
Let's refactor to model policy for our Contact model.
In this episode, we cover:
Laravel Model Policies
Fixing broken tests after the refactor
Introducing Resources, a very useful Laravel feature specifically design for API development.
In this episode, we cover:
Introduction to why you need Resources when developing an API
Making a Contact Resource
Using class aliases during import
Adding fields to a resource including custom fields
Human-friendly date for update at timestamp
Proper HTTP responses with correct status codes are a requirement for any robust API. Let's make sure we tackle that in this episode.
In this episode, we cover:
Review of current state of our codebase
Refactoring the store method to use the Resource
Asserting the proper status code in our tests
Adding links to our response API
Using a new method of path() for the Contact model can access itself
Let's tackle the update() and destroy() method so they too return the correct HTTP status code.
In this episode, we cover:
Adopting the correct assertion for the new response structure
Proper HTTP Response Status Code
Let's shift our focus to the front-end and first of, Tailwindcss.
In this episode, we cover:
Proper setup of Tailwindcss in a Laravel project
Creating a Tailwind config file
Check that Tailwind is working on our project
In part 1 of 3, let's try to follow the screenshot mock to implement the login screen.
In this episode, we cover:
Recreating designs from a screenshot using Tailwind classes
Positioning of elements on the screen
Adding a custom width in Tailwind using the config file
Using svg tags directly in views
In part 2 of 3, we design the email and password input field.
In this episode, we cover:
Designing input fields and positioning the label
Adding bottom padding vs adding top padding
Input placeholder
Removing the outline and replacing it with a background change
In part 3 of 3, we finish up the lower third design of the login window view.
In this episode, we cover:
Styling for a button
Using flex to spread items
Displaying and styling validation errors
Now that we have the design for login, register and forgot password, let's move on to actually registering a new user.
In this episode, we cover:
Setting up MySQL local database
Creating an api_token on the fly for new users
Fillable fields in the User model
Remove /home default from all controllers
Manually logging out a user
Now that we have user registered, let's start transferring the main app design from mock to real code.
In this episode, we cover:
How to structure divs based on the design
Creating layouts using fixed width and flex
Changing the color of an svg
Linking svgs
Next, let's take care of the rest of the navigation bar.
In this episode, we cover:
Designing proper navigation items with an icon and text
Design Tips for making designs look better
Using flex for vertical alignment
Creating large link targets for ease of use
Let's wrap up the right side of the app design.
In this episode, we cover:
Designing a top section with a fixed width
Proper padding for a main app view
How to scroll only one side of our app
Let's tackle the create form including validation.
In this episode, we cover:
Adding new routes to Vue Router
Styling input fields and labels
Removing focus outline and replacing with prettier design focus accent
Styling buttons including hover states
Let's pull the input field into a reusable Vue component.
In this episode, we cover:
Steps to extract a piece of code into a component
Register components in another component
Passing data into a component for customizing the name, label and others
Firing an event to pass data back to the parent
Listening to events to save new value of input
Adding Vue Devtools for development environment
In order for us to submit the form, we will need to stop the browser from actually submitting. Then, let's use axios to fire our form back to our server.
In this episode, we cover:
Using a method to handle form submission
Handling a Javascript promise
Passing the user data to Vue
Getting the api_token into every request using an interceptor
Let's take care of properly displaying any validation errors in our new InputField Vue component.
In this episode, we cover:
Designing error messages
Passing errors into a component
Dismissing errors after user starts to fix error
Adding custom classes when the input field has an error using an object
In this bonus lesson, let's remove some duplication by using a computed property.
In this episode, we cover:
Introduction to Vue's computed properties
Clean up and code readability
Next up, let's tackle the show view. This is the place where we will display all of the details of a particular contact.
In this episode, we cover:
New Vue component for the show view
Fetching data from the server for a single contact
Creating a new route in Vue Router with a wildcard for contact id
Fixing the axios interceptor to work with GET requests
mounted() vs created()
Grabbing wildcards from the route
Design for the Show view.
In this episode, we cover:
Structuring the design with flex
Styling links as buttons
Let's grab the user circle and make a reusable Vue component.
In this episode, we cover:
Extracting a section into a component
Parsing a name to get only the letter we want for the circle
Regular expression for grabbing capital letters
Using the new component in a second design
After a contact gets created we need to redirect them to the newly created resource.
In this episode, we cover:
Review of the problem we are fixing
Fixing the path() method on the contact model to not return a fully qualified path
Creating a loading state to prevent errors
In this lesson, we handle the delete sequence.
In this episode, we cover:
Creating a modal from scratch
Toggling a data property inline
Styling a modal, buttons and background
Firing a delete request using axios
Let's handle editing a contact in our application.
In this episode, we cover:
Using Vue Router to return back using a new back button
Adding a new view for editing
Reusing InputField component to display edit view
Passing data into InputField
Coding a watcher to detect change
Fetch request using axios
To list all of our users contacts, we need to implement the contacts index view.
In this episode, we cover:
Loading state for a component while axios is fetching data
Fetching all contacts from the server that belong to the auth user
Handling if there is no contacts for this user
Styling of list of contacts reusing the UserCircle component
Updating the navigation to redirect to the proper /contacts route
Let's show all of the contacts that have birthdays on the current month.
In this episode, we cover:
Filtering contacts by birthday month
Testing A & B Scenarios
RAW Queries with Eloquent
Extracting a ContactList is exactly what we need to display any other contacts list view like the birthdays contact.
In this episode, we cover:
Extracting a Vue Component
Reuse Vue component
Add new route using Vue Router
In part 1, we do an introduction to Laravel Scout package and install it on our project.
In this episode, we cover:
Laravel Scout
TeamTNT's Scout Driver
Setting up Scout config file
Using the Searchable Trait
Using Scout Import command
Search Controller
In part 2, we add the input field and style it to look just like the rest of our application.
In this episode, we cover:
Implementing the search input field using a Vue Component
Axios request to get search results through the API
Limiting how many times the search hits the server
Deboucing with lodash
In part 3, we start to show all of the results from our search.
In this episode, we cover:
Design a modal to show the search results
Add a cover for the whole app to dismiss our modal
Wrap up all lose ends on the searching feature of our app
We need to achieve adding titles to each page but when writing an SPA this becomes a bit more complicated.
In this episode, we cover:
How to pass a meta property from the route
Watch Vue data properties for changes and react to them
Set page titles using document
When it's time to logout, it's time for us to pull one more trick to get the stock Laravel auth to hook up to our SPA routing.
In this episode, we cover:
Create a logout component
Create a route to perform logout
Redirect the user back to the login screen
Developing Single-Page Applications requires a special set of skills. In this course, we will be learning how to develop the required API to power a simple address book project named Jot. Jot will be a SPA written in Vue JS using the TailwindCSS front-end framework. By the end of this course, Jot will be able to create, view, edit and delete contacts. We'll also implement search functionality using Laravel Scout, a free first-party package for Laravel for simple searchable models.