User: order history On the Order history page, a user can view all the orders the user has ever placed REMARKS
The history is a static view with no interaction, so we can use a simple Blade view for this page or a Livewire component We will use a Livewire component for this page, so we can easily add more functionality later on if we want to Preparation Create a Histories component Create a new Livewire component with the terminal command php artisan make:livewire User/History
app/Http/Livewire/User/History.php (the component class) resources/views/livewire/user/history.blade.php (the component view) Open the component class and change the layout to layouts.vinylshop
class History extends Component
{
public function render ( )
{
return view ( 'livewire.user.history' )
- > layout ( 'layouts.vinylshop' , [
'description' = > 'Your order history' ,
'title' = > 'Your order history' ,
] ) ;
}
}
1 2 3 4 5 6 7 8 9 10 11
Add a new route Add a new get-route for the History to the routes/web.php file Update the navigation menu in resources/views/components/layouts/nav-bar.blade.php Add the route in the new user group Protected the group with the auth
and active
middleware, so only logged-in, active users can access this routes
The URL is user/history (prefix is already set to user ) The view is user/history The route name is user.history (the group name is already set to user. ) Route: : view ( '/' , 'home' ) - > name ( 'home' ) ;
Route: : get ( 'shop' , Shop: : class ) - > name ( 'shop' ) ;
Route: : view ( 'contact' , 'contact' ) - > name ( 'contact' ) ;
Route: : get ( 'basket' , Basket: : class ) - > name ( 'basket' ) ;
Route: : view ( 'playground' , 'playground' ) - > name ( 'playground' ) ;
Route: : get ( 'itunes' , Itunes: : class ) - > name ( 'itunes' ) ;
Route: : middleware ( [ 'auth' , 'active' ] ) - > prefix ( 'user' ) - > name ( 'user.' ) - > group ( function ( ) {
Route: : redirect ( '/' , '/user/history' ) ;
Route: : get ( 'history' , History: : class ) - > name ( 'history' ) ;
} ) ;
Route: : middleware ( [ 'auth' , 'active' , 'admin' ] ) - > prefix ( 'admin' ) - > name ( 'admin.' ) - > group ( function ( ) {
Route: : redirect ( '/' , '/admin/records' ) ;
Route: : get ( 'genres' , Genres: : class ) - > name ( 'genres' ) ;
Route: : get ( 'records_old' , [ RecordController: : class , 'index' ] ) - > name ( 'records.old' ) ;
Route: : get ( 'records' , Records: : class ) - > name ( 'records' ) ;
Route: : get ( 'users/basic' , UsersBasic: : class ) - > name ( 'users.basic' ) ;
Route: : get ( 'users/advanced' , UsersAdvanced: : class ) - > name ( 'users.advanced' ) ;
Route: : get ( 'users/expert' , UsersExpert: : class ) - > name ( 'users.expert' ) ;
Route: : get ( 'covers' , Covers: : class ) - > name ( 'covers' ) ;
} ) ;
. . .
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
Line 14 : add, just below the Update profile link, a new link to the route route('user.history')
@auth
< x- jet- dropdown align= "right" width= "48" >
{ { -- avatar -- } }
< x- slot name= "trigger" >
< img class = "rounded-full h-8 w-8 object-cover cursor-pointer"
src= "{{ $avatar }}"
alt= "{{ auth()->user()->name }}" >
< / x- slot>
< x- slot name= "content" >
{ { -- all users -- } }
< div class = "block px-4 py-2 text-xs text-gray-400" > { { auth ( ) - > user ( ) - > name } } < / div>
< x- jet- dropdown- link href= "{{ route('dashboard') }}" > Dashboard< / x- jet- dropdown- link>
< x- jet- dropdown- link href= "{{ route('profile.show') }}" > Update Profile< / x- jet- dropdown- link>
< x- jet- dropdown- link href= "{{ route('user.history') }}" > Order history< / x- jet- dropdown- link>
< div class = "border-t border-gray-100" > < / div>
. . .
< / x- slot>
< / x- jet- dropdown>
@endauth
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
Basic scaffolding for view Open resources/views/livewire/user/history.blade.php and replace the content with the following code: < div class = "grid grid-cols-1 lg:grid-cols-2 2xl:grid-cols-3 gap-8 items-start" >
< div class = "flex flex-col bg-white border border-gray-300 shadow-md rounded-lg overflow-hidden" >
< div class = "p-2 bg-gray-100 border-b border-b-gray-300" >
< p class = "font-bold" > Order date: < span class = "font-normal" > . . . < / span> < / p>
< / div>
< div class = "p-2 flex-1 flex gap-4" >
< img src= "{{ asset('storage/covers/no-cover.png') }}" alt= "" class = "w-28 h-28 object-cover" >
< div class = "flex-1 flex flex-col" >
< p class = "font-medium" > Artist< / p>
< p class = "italic" > Title< / p>
< p class = "font-sm text-gray-400" > Quantity: . . . < / p>
< p class = "font-sm text-gray-400" > Price: € . . . < / p>
< / div>
< / div>
< div class = "p-2 bg-gray-100 border-t border-t-gray-300" >
< p class = "font-bold" > Total price: < span class = "font-normal" > € . . . < / span> < / p>
< / div>
< / div>
< / div>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
Orders overview The only thing we need to do is get all the orders with the orderlines and send them to the view Line 5 : get all the orders for the current user Line 6 : include the orderlines for each order Line 7 : order the orders by the date (the newest first) Line 9 : compact the orders and send them to the view class History extends Component
{
public function render ( )
{
$orders = Order: : where ( 'user_id' , auth ( ) - > id ( ) )
- > with ( 'orderlines' )
- > orderByDesc ( 'created_at' )
- > get ( ) ;
return view ( 'livewire.user.history' , compact ( 'orders' ) )
- > layout ( 'layouts.vinylshop' , [
'description' = > 'Your order history' ,
'title' = > 'Your order history' ,
] ) ;
}
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
Line 2 and 22 - 27 : loop over the orders:
line 22 - 27 if there are no orders, show alert message Line 5 : show the date of the order Line 19 : show the total price of the order Line 7 - 17 : loop over each orderline
Line 11 : show the artist Line 12 : show the title of the record Line 13 : show the quantity Line 14 : show the price < div class = "grid grid-cols-1 lg:grid-cols-2 2xl:grid-cols-3 gap-8 items-start" >
@forelse ( $orders as $order )
< div class = "flex flex-col bg-white border border-gray-300 shadow-md rounded-lg overflow-hidden" >
< div class = "p-2 bg-gray-100 border-b border-b-gray-300" >
< p class = "font-bold" > Order date: < span class = "font-normal" > { { $order - > created_at } } < / span> < / p>
< / div>
@foreach ( $order - > orderlines as $orderline )
< div class = "p-2 flex-1 flex gap-4" >
< img src= "{{ asset('storage/covers/no-cover.png') }}" alt= "" class = "w-28 h-28 object-cover" >
< div class = "flex-1 flex flex-col" >
< p class = "font-medium" > { { $orderline - > artist } } < / p>
< p class = "italic" > { { $orderline - > title } } < / p>
< p class = "font-sm text-gray-400" > Quantity: { { $orderline - > quantity } } < / p>
< p class = "font-sm text-gray-400" > Price: € { { $orderline - > total_price } } < / p>
< / div>
< / div>
@endforeach
< div class = "p-2 bg-gray-100 border-t border-t-gray-300" >
< p class = "font-bold" > Total price: < span class = "font-normal" > € { { $order - > total_price } } < / span> < / p>
< / div>
< / div>
@empty
< x- tmk. alert type= "info" dismissible= "false" class = "lg:col-span-2 2xl:col-span-3" >
< h3> No orders found< / h3>
< p> You have not placed any orders yet. < / p>
< / x- tmk. alert>
@endforelse
< / div>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
User has no orders yet
User ITF User 2 has placed 2 orders
Get the cover image We don't have the cover image yet, so we need to get it from the mb_id
of the orderline Open the app/Models/Orderline.php model and make a new attribute cover
and add it to the $appends
array class Orderline extends Model
{
use HasFactory ;
. . .
protected function cover ( ) : Attribute
{
return Attribute: : make (
get: function ( $value , $attributes ) {
return Storage: : disk ( 'public' ) - > exists ( 'covers/' . $attributes [ 'mb_id' ] . '.jpg' )
? Storage: : url ( 'covers/' . $attributes [ 'mb_id' ] . '.jpg' )
: Storage: : url ( 'covers/no-cover.png' ) ;
} ,
) ;
}
protected $appends = [ 'cover' ] ;
. . .
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
Replace the img
tag in the resources/views/livewire/user/history.blade.php view with the $orderline->cover
attribute:
Replace de src attribute with $orderline->cover
< img src= "{{ $orderline - > cover }}" alt= "" class = "w-28 h-28 object-cover" >
1
Last Updated: 4/20/2023, 6:43:28 PM