Now let's go ahead and let's create the filters. So we're gonna revisit an old component of ours called header. So let's go, I think it's inside of components right here, header.tsx and just below the welcome message we're gonna add the filters like this. There we go. Now go inside of the components and create filters.tsx component.
We're going to go ahead and export const filters and let's go ahead and let's return a div with a class name flex flex call large flex row items center gap y2 lg gap y0 and lg gap x2. And then add what's going to be an account filter. So for now it's going to be an error, right? Let's go back inside of the header and let's just import filters from ./.filters or in this case from components filters like this. Now let's go ahead and let's develop our account filter.
So I'm going to create that in the components as well. Account filter. Let's mark it as use client. Let's export const account filter. Let's go ahead and let's import everything we need from the select component so that's gonna be select select content, select item, select trigger and select value as usual.
And let's also go ahead and let's import our use get accounts here. So import use get accounts multiple from feature accounts API use get accounts. Let's also prepare a couple of things here. So I need to add a package, bun add query-string. Let's import Qs from query string like this And let's import from next navigation a couple of things.
So we're going to need the usePathName. We're gonna need the useRouter and we're gonna need the useSearchParams. So all three of those. Now let's go ahead and let's start developing this so we're gonna go ahead and return a select component here Let's go ahead and give it some props. So value for now is going to be empty.
On value change will be an empty method. And disabled will be false. Now inside we're going to create a select trigger. And let's go ahead and give it a specific class name. So LG with auto Full width Height is gonna be 9, rounded is gonna be medium, PX is gonna be 3, font will be normal, bg white 10, cover bg white 20, cover text white, border none, focus ring offset zero.
Focus ring transparent. Let's go ahead and add some more. Outline none. Text white and focus. PG white 30 and transition.
There we go. Now inside, we're going to add a select value, which will have a placeholder account. Now let's add a select content here with the first item be a default select item which will say all accounts with a value of all. And now what we have to do is we have to add the hook to load the accounts. So we already have that here.
So let's use get accounts will be right here. Whoops. So use get accounts. Let's destructure the data. That's gonna be the accounts and let's add is loading is loading accounts.
Let's go ahead and do it like this. Let's go ahead and use the accounts here. So we're gonna do that right here, just below this item. We're gonna go over data, question mark dot map, get the account, And we're going to add the individual select items. So account.name and key will be account.id and value will be account.id as well.
And no, it's not data, it is accounts, my apologies, right? So accounts.map, and then we get the individual account. There we go. Great, let's go back inside of the filters and let's use the account filter. So I'm gonna switch this to components, account filter.
Let's refresh our localhost to see how this looks at the moment. Let's go ahead and there we go. So this is it right now. It says account looks like we have some clerk hydration error here. So I'm just going to refresh this.
There we go. So in here we have all accounts. We have checking and we have savings here. Great. So now we're going to go ahead and improve this value a bit.
So let's go ahead. And let's try and get the default value. So we're gonna do that using the use search params here. So let's go ahead and write const params use search params and then we're gonna have const account id be params.get account id or all right so this all needs to match this value right here. So now when I refresh, I think that this should be this, but it's not, oh, because we're not passing the value here.
So let's go ahead and pass in the account ID as the value here. There we go. So now the default is all accounts, as you can see here. And let's make this select and select account. Right?
So we should technically never see the placeholder, right? Because we fall back to all here and we just pass the value. So by default, it's all accounts. Great, so we have that. And now we have to also get the from or an empty string.
And we also have to get to because we want to preserve those values, right? So now we have this. Let's go ahead and let's add the router from use router which we have imported. And let's get the path name. Oops, path name from use path name.
So let's get all of those. And now we're gonna create a method called const on change which will get the new value, which is a string. And inside of here, we're gonna define our query account id new value from and to and then we're going to say if new value is equal to all we're going to go ahead and do query.accountid and reset the entire thing and let's go ahead and write const url qs stringify url. URL will be the path name Query And let's go ahead and add additional options here Skip null will be true and skip empty string will be true as well Like this So it's important that we preserve the from and to here. And lastly, router.pushURL.
There we go. Let's go ahead and let's use this on change now. So I'm gonna add that here on change. And now I wanna go ahead and try this out. So it's gonna be disabled if we are loading the accounts.
So let's use isLoadingAccounts and use that for the disabled value here. So what should happen now? In my transactions, Let's see which account am I using. So I'm using the checking account, it seems everywhere. So if I go ahead, select savings, there we go.
I have no results. If I go into the overview and try savings here, no data for this period, no data, zero, zero, zero. Perfect, if I go back to checkings, everything is working. And you can see my url change using the account id so all of that is perfectly transmitted inside of all of those hooks that I have for my transactions so use get transactions for example uses those account ID params from my URL, which we now push right here, right? We align it.
And we did the same thing in use get summary, for example, account ID, right? So let's go ahead now and let's do one more thing. And that is to go inside of the account filter and we're going to add one more hook here called use get summary. And the reason I want that is because every time we change the account filter, the summary will reload. So I want to keep track of that.
So I'm gonna go ahead and add const use get summary here. And I'm going to add, I'm going to extract the is loading, is loading summary like this. And I'm going to ensure that my select is disabled if I'm loading the summary or if I'm loading the accounts. There we go. Perfect.
So now I want to go ahead and I want to develop the date filter which will be fairly similar. So let's go inside of the filters here And let's add the date filter component. So we don't have it yet, but we're gonna create it in a moment. Let me just close all of these things. Date filter dot CSX.
Let's mark it as use client here. And let's go ahead and let's just export const date filter. And let's return a div. Now I can go back to my filters component and I can import the date filter. And let me just change my type of import here, like this.
And let's go ahead inside of here. And we're gonna add a lot of similar things from our account filter, especially when it comes to the summary, the query string and this kind of stuff, right? So we need the query string, we need all of these and we need use get summary right here. Besides that we're also going to add a couple of things from React itself. So we need use state from date FNS package.
We need format and sub days from react day picker. We need the date range and we have react date picker because we install chat CNUI calendar. And I also want to add an icon just Chevron down this is the icon I need Chevron down from Lucid React great and we are also going to add a couple of utils here. So we need CN and format date range. And we also need our button component.
We need our reusable calendar component. And we also need everything from the popover. And the only thing we don't have here is the popover close. So let's go inside of components UI popover here. Let's add it.
So const popover close will be popover primitive.close and what we have to do is we have to export it like this and now there we go, no problems with popover close here perfect Let's go ahead inside of the date filter component here. Let me just refresh my localhost to ensure that we see what we develop, right? So we're gonna be using the popover component. So let's start with the popover. And now we are going to work with popover trigger here as a child.
And we're going to use a button component here. Let's give it a couple of props. So disabled will be false. Size will be small and variant will be our outline. And now let's go ahead and let's give it a class name.
So I'm gonna go ahead inside of my account filter and I'm just going to copy my class name right here. Let's go ahead and copy that and see if that's going to fit exactly what we need here. Looks like this fits quite well. Great, And inside of this button, we're going to go ahead and write a span. And inside of here, we have to format the existing date range.
So for that, we need the param state. So this is what we're going to do. We're gonna go inside of the account filter and we're just going to copy this, the params, right? And we can also copy the router and the path name. So let's do that.
Add it to the date filter here. There we go. And now we're gonna do const default to will be new date and we're gonna have const default from will be sub days as we usually do from default to and subtract 30 days. Great. And now what we can build is we can build a constant called param state.
So if we have from we're gonna add new date from. Otherwise it's gonna be the default from. If we have to, we're gonna use new date to otherwise default to like that. There we go. And now I want to go ahead and use that param state right here.
And we're gonna use the format date range and pass in the param state inside. So there we go. Now you have default one. From April 10th to May 10th. The same one we can see right here it's the default right without any changes.
Great so we have that now and now what I want to do is I want to introduce a state so do we have useState we already have the state great So let's go ahead and do the following. Let's add const use state here. And inside of the state, we're going to keep the date. So let's add set date here. We need to keep it in the state because it's gonna be a range.
So we need to keep track of users first input. So it can be this or undefined. And by default, it can be param state. And now let's go ahead and let's build our const push to URL method. So this will accept a date range which can be a date range or undefined.
Let's create our query here which will have from to be format, date, range, question mark, from, or default from. So it's going to use one of the two. And our usual format starting with the year, month and then the date. Copy this and do the same thing for 2. So it's gonna go ahead and use the date range .2 otherwise default 2 and the exact same format goes here.
Now inside of here, we're gonna add const URL to be a QS query string. My apologies, stringify URL. URL will be the path name. I believe we have added the path name when we copied it. There we go.
We're gonna pass in the query and let's add skip null. Let's add both skip empty string and skip null to be true. There we go. And lastly, let's do router.pushURL. There we go.
And we're just gonna create an onReset function here to reset the date and to push undefined to the URL. Great. So now what I want to do is alongside this param state for metadata range, I want to add a chevron down. So we already have that imported. Let's give it a class name of MarginLeft2 Size of 4 and Opacity of 50 Like that And let's go ahead and let's go outside of the popover trigger and let's add a popover content with a class name, LG with auto, full width and padding of zero and a line of start.
If you want to, you can also collapse these so they don't look like that. There we go. And then inside of here, we're gonna use our calendar component. So let's go ahead and give it a couple of options here. So we're gonna have disabled to be false for now.
Let's give it the initial focus. Mode will be a range, so that's important because we're selecting two dates. Default month will be date from. Selected will be date. So this is from the state, right?
OnSelect will simply call setDate and numberOfMonths shown are going to be 2 by default. And then below that we're going to have a div with a class name. Adding for full width LexItemCenter and GapX2 Inside of that we're going to add a popover close which will have the as child property and use a button. This button will have an on click which we'll call on reset. And the reset will be disabled if we don't have date from.
Or if we don't have date to. And now let's add class name, full width, variant of outline, and let's write reset. There we go. Let's copy and paste this below. This one will say apply.
OnClick will be a method which will call push to URL and push in the date. And the rest can say the same except the variant right here. Like that. So I think that should be it. And we also have the account ID.
So let's use that here as well. So the query account ID will be account ID. Let's go. Let's try this out now. So I'm gonna go ahead and select a much lower range now, for example, from 14th to 28th, click apply and take a look at my from end too.
So it's from the 14th of April to the 28th of April. And it looks like I have no transactions in that period or do I? Let's go ahead and try it from here. So from this to this let's try no results here and I shouldn't have any there either. So let's go ahead and see if I have any in the past.
Can we do this? Alright, so I'm gonna go ahead and see whether we have any bugs here. Alright, so we do have a bug and the bug is in the account ID. So our account ID was copied and it looked like this, but we should not have this all because this all is not handled here. It's only handed in the account filter right here.
There we go. So let's go ahead and let's try this out now. So go ahead and remove everything. So just go to localhost 3000 and go ahead and select something in the past or just some smaller amount like 7 to 13 like this just a week. If using the seed script, you should definitely have that data.
There we go. Look at this beautiful information and you can do the same thing right here on these queries like this. There we go. So now it's only loading those in that and you can also combine that with the checking and the savings here. Great!
Amazing, amazing job! Well you finished pretty much the entire application. Let's go ahead and see what we are going to do next.