Building Stat Cards0:00
Let's take a look at how we can display stats in our Laravel app. Usually, you see this within admin dashboards as a quick glance of important information. We'll take a look at doing this with just Laravel, and then we'll add a bit of Livewire if you want to make it a bit more dynamic. Let's start off with a simple design. I am using Tailwind here, so how about we add cards for our stats. So let's go into our stats.blade.php. Let's make use of CSS grid here within Tailwind. Let's say class equals, and we'll make it four columns here. So let's say grid, grid-cols-4, and let's give it a gap of 10, and let's add some margin.
Let's say class equals, and we'll make it four columns here. So let's say grid, grid calls four, and let's give it a gap of 10, and let's add some margin as well. Let's go ahead and add one card here. Let's make another div for the container. This will be the title for the card. Let's make it an H4, and let's change the color as well, say text-gray-500, and it's a font-medium. And for this stat, how about we count the number of users within a certain timeframe. And then underneath this will be the actual number.
And for this stat, how about we count the number of Users within a certain timeframe. And then underneath this will be the actual number. So let's make it fairly large with text 3xl. Let's make it bold, and let's put some margin on the top. And let's just put a random number in here for now. Okay, so let's see how this renders in the browser. And I forgot to add the styles for the card, so that will be up here. class equals, let's make it white, give it a shadow, make it rounded, and let's give it some padding. So h-4 py-6 is what I have, and that looks pretty decent.
Querying Users Count1:22
it some padding. So H4PY6 is what I have, and that looks pretty decent. And to get the actual number, we will just query our database. So let's do that within our routes file. Usually you would have a controller, but for this demo, I have everything in the routes file. So we can define a new variable here named usersCount. So let's grab that information. So User::where(created_at, '>=', now()->subDays(30))->get();
So User where created_at, let's say greater than or equal to, and how about we grab all of the new users from within 30 days. So we can say now, we can use the subDays method within Carbon to go back 30 days, and we can count that. Let's make sure to import User. And we can pass that in, say usersCount is usersCount. Okay, now in our Blade view, we can just output that variable here. So usersCount. And hopefully that should show the correct number. And it does.
Adding Orders and Revenue2:23
And hopefully that should show the correct number. And it does. Cool. Now if you wanted more stats, we can just add as many as we like in here. So let's add a few more. So we can duplicate this. How about we make this one the ordersCount. So let's say orders, say ordersCount here. Let's go ahead and count the number of orders within our routes file. So it's basically the same as this.
Let's go ahead and count the number of orders within our routes file. So it's basically the same as this. Orders count. And this would be order. And let's import order. And we can pass it through here. And that should count the number of orders. Okay, and how about one more for our revenue here. So remember, within our orders table, we do have this total count. And we can make use of that to sum up the revenue for a certain time period.
So remember, within our orders table, we do have this total count. And we can make use of that to sum up the revenue for a certain time period. So the query is basically the same. So let's do the same thing here. Let's name it revenue. And this is the same, but instead of counting it, we are going to sum it up. And the column is the total. Let's make sure to pass this as well. And let's make another section in our blade view. So we can duplicate this.
And let's make another section in our blade view. So we can duplicate this. Let's say revenue. And revenue as well. Actually this is within cents, and we do want it in a dollar format. So I'm going to make use of the number_format within php to format it as a currency. And you can do this before you pass it in if you like, from here. You can also put a dedicated method on the Order model if you like. For now, I'm just going to do it directly in the blade view here. So we'll say new NumberFormatter.
For now, I'm just going to do it directly in the Blade view here. So we'll say new NumberFormatter. And the locale, I'll just say en_US. The format type is a currency, so NumberFormatter::CURRENCY. And we want to format, so we'll call the format method, or formatCurrency I mean. We want to format $revenue divided by 100, because we have money stored as cents. And the currency, I'll just put as U.S. dollars. Okay, let's save that, and let's check that out in the browser. And there is our $revenue for the last 30 days. Now what if you wanted to show more information for your stats?
Adding Livewire Dropdown5:31
can select 60 or 90 days as well. So again, we need to perform some sort of AJAX request and update this stat here. So once again, I think Livewire is a great use case for this. We just want to perform some sort of AJAX request and update some data. And it's not as involved as the last video, because there isn't going to be any external JavaScript library. So let's see how we can do that. So I'm going to remove this. Let's go ahead and add that select. So I'm going to put it within here, we need to make this a flex container.
Let's go ahead and add that select. So I'm going to put it within here, we need to make this a flex container. So let's say flex justify-between and items-center. So this will be the first flex item and the select will be the second flex item. And we don't really need the name and id. But again, I'll add it anyways, selectedDays. And same for the id. So let's just add a few options here. Actually, let me add a class first, class equals, add a border and bg-gray-100. Let's add an option here or a few options, let's say 30 days by default, we'll add 60.
Actually, let me add a class first, class equals, border and bg-gray-100. Let's add an option here or a few options, let's say 30 days by default, we'll add 60 and 90. Okay, let's save that. Let's see how that looks. Looks pretty good. And now we can convert this into a Livewire component. So let's do that. So we're going to grab all of this. So this will be one Livewire component.
So we're going to grab all of this. So this will be one Livewire component. Let's name it Livewire. How about we put it within a stats folder, and we'll name it usersCount? Okay, and we'll work on this one first. And then we'll add these other stats as well. So save that. Let's go ahead and make that component. So php artisan livewire:make stats.usersCount. Let's go into our component and paste in our markup.
So php artisan, livewire, make, I said stats.users count. Let's go into our component and paste in our markup. So users count, go ahead and paste in what I copied from the Blade view. Okay, save that. Now we want to move this users count into our livewire component instead of performing the query within our routes web.php. So let's do that first. Let's grab the query from our routes web.php. So users count, we don't need to pass it in anymore from the controller or from the routes file I mean.
So usersCount, we don't need to pass it in anymore from the controller or from the routes file I mean. Let's go back to our template. Actually let's go into our class. So usersCount. And let's make a public property for that. So say public $usersCount. Let's make a mount method to initialize that count. And I'm going to call a method to do that. So say this->updateStats() is what I'll call it.
And I'm going to call a method to do that. So say this updateStat is what I'll call it. Go ahead and make that method, updateStat, no params. And let me just paste in the query here. So this is now going to be this users count, make sure to import User. And this should still work within our browser. It does. But now we also want to keep track of whatever the user selects here within the dropdown. So let's go ahead and do that. So back to our template.
So let's go ahead and do that. So back to our template. Let's put a wire:model on the select. So right here, wire:model. We'll make a new property called selectedDays. So that will update the selectedDays variable. But we also want to make sure we update the count. So we can put a wire:change on this. So wire:change equals. And we can call that method.
So wire change equals. And we can call that method. So this method right here updates that. So let's save this. Go back to our class. Let's add that public property for selectedDays. And this will be updated as the user changes the value in the dropdown. So let's default it to 30 here. So this selectedDays is 30 by default. And now instead of hard coding 30 in our query down here, we can make use of that variable.
So this selected days is 30 by default. And now instead of hard coding 30 in our query down here, we can make use of that variable. So let's paste that in. And hopefully I did that correctly. And our count should update as we change it. So let's refresh. 30 is the default. Let's try 60. And that does update. 90.
Creating More Livewire Stats9:25
And that does update. 90. Cool. So we can pretty much do the same thing for our other stats as well. So let's make a new component, StatsOrdersCount. And we'll make one more for our revenue. Okay. So for our ordersCount, it's going to be pretty much the same as this. We just have to change the query.
So for our orders count, it's going to be pretty much the same as this. We just have to change the query. So I'm going to grab all of this. Let's go to our orders count. Let's paste that in here. Instead of users count, it's orders count. This is going to be order. Let's make sure to import that. Let's get rid of this query within our routes file. Don't need this.
Let's get rid of this query within our routes file. Don't need this. Let's get rid of this as well. Let's save that. Let's go to our template. So users count. Again, this is pretty much the same. And we will have some duplication now, but we'll take a look at how we can dry up our code in a second. So let's go to orders count.
code in a second. So let's go to ordersCount. Let's paste that in. Our only changes are the name of the stat. So orders. And this is now ordersCount. Okay. Save that. Hopefully I did everything correctly. Back to our browser.
Hopefully I did everything correctly. Back to our browser. And I forgot to remove it from our original blade file. So let's do that. So within stats, we can get rid of this, but now it's ordersCount. So let's duplicate this. Okay. ordersCount. And let's save that. Give that another try.
Extracting Reusable Blade Component11:08
So I updated the revenue as well, and that is updating as we change the value. And everything's looking pretty good. We can dynamically change the stat that's showing within our cards here. Now we do have a bit of duplication within our Livewire templates. So if we take a look at our revenue, our orders, and our users count, the only thing that's different between these three is the title and also the actual stat that's showing. So what we can do is extract this to a Blade component and then just pass in these dynamic values as props. So let's go ahead and do that so we can dry up our code. So we'll make this an anonymous component.
So let's go ahead and do that so we can dry up our code. So we'll make this an anonymous component. So we can say php artisan make:component. Let's name it StatLayout. And I actually wanted it to be anonymous. And to do that, you can do --view. But since I already made it, let's go ahead and delete the class that I created. So StatLayout. So this one right here, let me just delete that. Okay.
So this one right here, let me just delete that. Okay. So now we can grab all of this from within one of our Livewire templates. We can put that within the Blade component we made. So StatLayout. Let's go ahead and paste that in. And like I said, the only two pieces of dynamic data are the title. So in this case, it's users here and the actual stat. So let's accept those as props. And to do that, we can say @props and provide an array.
So let's accept those as props. And to do that, we can say $props and provide an array. So let's call them name or title. name is fine. And stat. And now from within our Livewire components, we can just pass those in as props. And also from within here, we can just output the prop here. So this would be name. And this will be stat. Okay.
And this will be stat. Okay. So let's save that. Let's go to our Livewire templates. And we can delete this and just make use of that Blade component. So let's say x-stat-layout is what I named it. And we can pass in our props here. So name equals, in this case, it's the users. So let's say users. And we can pass in the stat like this.
So let's say users. And we can pass in the stat like this. So :stat. And in this case, it's the users count. So let's say $usersCount. Okay. Close that out. Let's save this. And let's see if the stat is still working. And it is.
Let's delete all of this. This is now orders. This is orders count. And we can do the same for revenue as well. Delete all of this. Actually, I'm going to keep this because I need this numberFormatter. So let me just paste it above here. This is the revenue. And we can grab all of this numberFormat stuff and put that within the stat. Okay.
And we can grab all of this number format stuff and put that within the stat. Okay. Let's remove this now. Let's paste that in. And hopefully that still works. I'll save that. Refresh. Let's check our orders. That still works. And let's check our revenue.
That still works. And let's check our revenue. That still works as well. Cool. So yeah, just a few approaches of how you can show stats within your Laravel applications. Let's go ahead and make another commit here. This is episode three. Hit add. Hit commit. Episode three.
