# 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',
            ]);
    }
}
Copied!
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');
});

...
Copied!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 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>
Copied!
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',
            ]);
    }
}
Copied!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

# 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;
    
    ...
    
    /** Add additional attributes ... */
    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'];
    
    ...
}
Copied!
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">
Copied!
1

Orderline with cover

Last Updated: 4/20/2023, 6:43:28 PM