So now that we've wrapped up our accounts entity and we can create new accounts, we can individually delete a single account, we can go ahead and bulk delete accounts and of course we can always edit a specific account. Let's see how fast we can build the equivalent categories page because it's going to be very very simple and we have a lot of components finished now. So first of all, we start in the schema. So let's go inside of database schema.ds. And we can copy and paste the existing accounts, but I'm just going to do it below the insert accounts schema.
And I'm going to call this categories. And let's of course ensure that our PG table is also named categories. It's also going to have an ID, it's going to have a played ID, it's going to have a name and a user ID. So exact same fields. And if you're wondering what does played ID do in both of these, well, we're going to come to that later when we connect to an external service which will be able to read from our bank accounts.
So for now we are not using that but later we will. So we are already preparing for that. Great! So we have that now. Let's go inside of our terminal.
Let's shut down the app and let's run bunrun database generate, our script to generate SQL migrations. And there we go! We now have a migration script here. So let's go ahead and do bunrun database migrate and now this will push it to NeonDB. Let's go ahead and visit our database studio and let's just confirm that everything is fine.
So inside of here I should now have categories and I do and they have ID, blade ID, name and user ID. Perfect! So I'm gonna go ahead and do bun run dev on my app now. And let's go ahead and let's start. So what we can do now is we can easily copy and paste our route, right?
So inside of app API, inside of route folder, we have accounts. Let's copy and paste that and let's rename this to be categories like this. And let's go ahead inside of route.ts and let's import categories from .slash categories like that. And now we're going to go ahead and we're going to chain slash categories right here and make sure they use the categories model. Not model but route.
Right. There we go. So now if we go ahead and go inside of localhost 3000 slash API slash categories, we are going to load accounts, right? Because we just copied and pasted the route for accounts. So regardless because we mapped this under categories inside of the code we are still working with accounts and insert account schema.
So now let's go one by one and let's modify this so it works properly. So I'm going to go ahead and do the easy thing. I'm going to remove the accounts import because that's going to give us errors everywhere where we need to replace them with categories. This is kind of an easy way of us of doing this. So let's import categories instead and the same thing with insert account schema.
Well, we are missing the insert categories schema, right? So let's go back inside of our schema file. Let's copy this and let's paste it here. And this is going to use the categories and it's going to be called insert category schema. Like that.
Perfect. So let's go back inside of categories and let's import insert category schema. There we go. So we have two unused imports and a bunch of errors we've got to fix. Let's start with the first get route.
So inside of here, what we are going to do is we are going to select the same thing, ID and name from categories, from the categories table. And we are going to ensure that it's only the person that created this category that can see these categories right because users can have personal categories we don't want to share them globally with other users. Now let's go ahead and go to the other route so right now I think I'm not sure if this is going to work now because we have errors but if I refresh localhost let's see there we go so we still have errors we can't try this out yet okay but we know that our get route has no errors but this get does have errors I believe there we go So let's go inside of the get individual ID. So the validator for the param stays the same, right? The error codes are the same, but inside of here we are no longer working with accounts, but instead we are working with categories like this.
There we go. So we resolved our get ID route. Now let's get for the creating the route. So this time we are using insert category schema right here and I believe the rule can stay the same. We are only using the name.
There we go. And we are not inserting into accounts but instead into categories and we are still using the same create ID method here. There we go. That's our create request. Now for the bulk delete, same thing.
Everything is exactly the same but instead of removing accounts and instead of doing filtering with accounts we are all changing that to categories. There we go. We just saved a bunch of time from writing this together. Oh, from writing this again. So in the patch request, we do the same thing.
Instead of insert account schema, it is insert category schema like this. And below here, we are using categories like that. And that resolves our patch request for the categories and I think this is the last one the delete by ID so everything above stays the same but we are manipulating the categories not the account and there we go all of a sudden no errors inside of my application so I recommend that you expand all of this and just take a peek that nothing is red and there are no errors there we go This is fine and you can also do a search of accounts just to confirm that you by accident don't use account or accounts anywhere in this code because there shouldn't be any. So right now as you can see my data here is completely empty because it's actually loading the categories. Perfect!
So now let's go ahead back inside of localhost 3000 and what we have to do now is we have to create the page for categories. So we can also copy and paste our existing accounts page. So let's copy and paste that and let's rename this Categories. So just by doing that nothing should change except that when I click on Categories here I will no longer get a 404 instead it's going to load the accounts page because we just copied and pasted it. Again, if you're still getting a 404 here, make sure that your navigation component has the proper href to go to slash categories because that is the name of the folder we just created categories.
Great. Let's go inside of categories page.vsx and let's change the simple things first. So instead of it being accounts page, it's going to be categories page. Like that. That's the first change.
Then what I want to do is I want to change the title. Instead of accounts page, it's categories. There we go. So it's already looking better. What we have to do now is we have to create all of these equivalent hooks but to manipulate, well, categories, right?
So let's go ahead and do that. Let's see if we can do it just by slight modification of the existing ones. So let's go inside of features and let's copy the entire accounts and paste it here and let's rename it categories. Now, first things first, let's go ahead and let's resolve our hooks here. So we're gonna have use new account, rename to use new category.
Let's go inside of that. Instead of new account state, this is going to be new category. New category without a typo. And this can stay exactly as it is. Then let's rename this to use open category.
Let's go inside and let's change this from open account to open category. Again, a typo on my side. And the logic can stay exactly the same. Great, we have the cook hooks resolved. Now let's go inside of the API.
Let's start with a simple use get accounts and let's rename it to use get categories. Just ensure that you're doing these changes in the categories folder. Don't accidentally rename your existing accounts, right? So we copied and pasted the accounts and renamed it into categories so just make sure you're modifying that. So we just renamed this to use get categories and now let's change this to use get categories as well.
Let's go ahead and modify the query key to the categories and now we have to change the response to not call accounts but instead call categories and failed to fetch categories like that. There we go, use get categories is now working. Let's go inside of the individual use get account and rename it to use get category right here. Let's rename it to use getCategory. The ID stays the same.
The query key is category, individual and an ID. And the API is not accounts but categories and targeting a single ID. And since we copied and pasted the entire API everything is the same, the types are exactly the same let's go ahead and resolve the error so account should be failed to fetch category like this there we go Now that we have that let's go ahead and let's do use edit category like this and inside of here what we are going to do is again we're going to replace instances of accounts with categories because everything else stays exactly the same. The patch request, the JSON, everything is the same. And let's change the categories here as well.
Categories like that. And the types are the same. We accept the id param and the json. Instead of account updated it's going to be category updated and we are going to refresh the individual category and we are going to refresh the categories key like that and failed to edit category as the error and this to do can stay the same because later we're going to have to refresh that as well. Now let's go ahead and let's modify the use delete account to be use delete category.
And let me just close everything besides this. All right, so use delete category. Let's rename this to use delete category. Let's go ahead and replace the account instances with categories. Same thing in the mutation function.
We are working with the individual category. Category deleted and categories and failed to delete an individual category here. There we go. Now let's go ahead and let's modify use create to be use create category. Use create category.
Change the accounts instances to categories and same thing for the mutation function everything else is exactly the same because they are so similar so category has been created and we are refreshing the categories here. And let's write fail to create category. Like this. There we go. And last one use bulk delete.
Well use bulk delete can actually stay the same. Let's be specific and let's call it useBulkDeleteCategories. So I'm gonna go ahead and find the previous one in the accounts and I'm gonna add it as well because I want to be explicit about the naming. So this is the full name, useBulkDeleteCategories. There we go, so useBulkDeleteCategories instead of accounts and again instead of accounts it is categories using the bulk delete method.
Inside of here as well, so categories, categories deleted and we are refreshing the categories query key and failed to delete categories. And I believe that is it. So we have everything we need for the API. Now let's go ahead and let's modify our components here which again are going to be very very similar. Let's go inside of the account form and let's rename it to category form.
Inside of category form let's go ahead and do the easy thing and that is to remove the insert account schema and instead import insert category schema so we have the errors telling us exactly what we have to change. There we go. Now this can stay the same. Form values are the same. The props are exactly the same.
And let's rename this to be category form. The form stays the same. Handle submit, handle delete. And now we're just going to have to slightly modify the placeholder because the name is still the only field that exists when creating a category. So this now instead of cash, bank and credit card can be for example food, travel, etc.
And let's go ahead and modify the create account to be create category and below that delete category. There we go. Now, let's go ahead and let's go inside of the new account sheet and let's rename it to new category. Like that. Again, let's do the easy thing and that is, well, first of all, let's do this.
Let's remove the schema and let's write insert category schema. So we get this easy error here. All right so only this place and now what we have to do let's leave these three imports for last. Let's go ahead and modify the labels first. So new category sheet like that.
Let's leave this as it is and let's write new category like that and let's change the description create a new category to organize your transactions like this. We can leave this as it is. And now we can start replacing our components and hooks. So first of all, I wanna go ahead and I wanna remove the account form. And instead I'm going to import category form from .slash category form or features categories components category form like that let's just see if there are any errors, there aren't so this should be in one line like this So now we have category form and we have this error.
If I replace it, there shouldn't be no errors at all. There we go. It matches perfectly. Now let's remove the use new account. And instead let's import use new category from hooks, use new category, but I'm going to change that to features, categories like this.
There we go. Let's find the error. Instead of use new account, it's use new category and nothing else changes. And let's do the last thing for use create account. Instead let's import use create category from API which I am again going to change to use the add features sign.
You can leave it like this if you want to. I just like to be consistent with my imports. Let's find the error and there we go. Use create category. That's it.
That is our new category sheet. Now let's go ahead and do the last one, which is edit account sheet and let's rename it to edit category. Let's go inside of here and let's do the same thing. So easy things first. How about remove the insert account schema in favor of insert category schema and let's replace that with the error here.
Now let's modify the edit account sheet to be edit category like this and now we're gonna go ahead and modify a couple of things so first of all let's find some text here so edit category edit an existing category let's see if there are any other instances there are not But I think that in this useConfirm I kept writing delete the transaction when it's actually delete account right? So let's go ahead and fix it here first. You're about to delete this category not the transaction. It looks like I made a typo. Great.
And now we're going to go ahead and delete things one by one. So first of all, it's the account form. We are no longer using that. So we can remove that and instead we can import our category form from .slash category form or from features, categories components, category form. Let's copy the category form and instead let's use it in place of the account form here and nothing should change because it's exactly the same let's remove the use get account in favor of use get category individual category from features categories like this Let's find where we have the error and there it is.
While we are here, let's also modify to not use account query, but instead category query like this. And then let's change is loading to use category query is loading and below here let's modify category query data, category query data name and That is it. Great. Now let's go ahead and remove the use edit account, sorry, use open account in favor of use open category. And I'm just going to copy this and replace that here.
Let's find where we use use open account and this time it's use open category and nothing else requires a change but let's remove the use edit account now in favor of use edit category do I have use edit category perhaps I don't Let's go ahead and see if I made a mistake here. Use edit category. I did not rename it. So inside of my features folder, inside of categories, I do have use edit category but I forgot to rename it. So use edit category like that.
Let's try this again. Use edit category. There we go. We can now safely import that as well. So we are doing this inside of edit category sheet, right?
Let's see if there are still so features and this should be slash categories like this. Let's see where we have to use that. So it's here and edit mutation logic can stay the same and let's the last one which is use delete account we no longer have that instead we're gonna have use delete category let's go ahead and write features categories api use delete category like that Let's find the error and let's use it here. There we go. I believe we handled all the logic.
So to make sure, this is what I wanna do. I wanna go inside of features here. I want to go inside of categories and what I'm going to do is right-click and I'm going to write find in folder and I'm going to search for account. There we go. So I have no instances of account and I have no instances of accounts but if I search for category I do categories I do perfect so just make sure that you have no instance of account or accounts in your categories that way you know that you properly replaced and renamed everything.
Great. So we now have a fully working features here. What we have to do now is we have to go inside of the providers, sheet provider, and go ahead and copy and paste this too. Add a little space so you separate features. And these two next ones are going to be from features categories and it's going to be new category.
Okay, maybe it's easier for us to do this, right? Import new category like that and below that import edit category from features categories components. Great. And now we're gonna go ahead and write new category and below that edit category. There we go.
Perfect. And now that we have that, let's go inside of the app dashboard. Let's go inside of categories and let's go inside of page.tsx and let's slowly resolve this as well. So we changed the labels, right? So that's fine.
Now let's go ahead and change the individual hooks here. So we're not gonna use use new account. Instead, we're gonna use use new category from features categories hooks. Let's find the error and let's replace it. Let's also replace the name of new account and everywhere where we use it to new category.
Like this. So new category dot open here and I renamed this to new category and that's it. Let's go ahead and next use bulk delete accounts, we remove that in favor of use bulk delete categories and use delete categories here. Let's fix the error here and let's fix the mutation here. There we go, everything matches exactly.
And let's remove use get accounts in favor of use get categories so multiple make sure it's multiple of them let's replace the use get categories and let's change this not be accounts query but categories query and in here we're gonna use the categories query data and these are now going to be categories. Is disabled is going to look for the categories query instead of the accounts query and same thing for this if clause here and then copy and paste this categories constant and we're going to paste it here. There we go. And Oh, I left the filter key to be email. All right.
So this should be changed the name both here and also in the accounts page. I forgot about that. We're going to go back and fix that as well. Great, so this now actually works fine, but we do have to resolve a couple of things. So here in the columns right here, in the categories folder, right?
We have to change the response type to not use accounts, but categories, even though they are exactly the same so nothing visible is changing but if you ever add some new fields you obviously want to read them here, right? Now let's go inside of the actions and in here we have to modify I think the last of our hooks So let's remove use open account in favor of use open category and let's go ahead and see where we have to use it. So right here use open category. Perfect. Let's change this label while we are here.
So you're about to delete this category and let's go and remove use delete account in favor of use delete category, like this. There we go. And let's add that here. And the delete mutation name is generic so it can stay the same. And I think that we don't have to modify anything else.
So this delete mutation seems to have some error but I think there's just some weird cache if I'm not mistaken. If I go ahead and reload my window I think it will go away. There we go it went away. Perfect! So if I'm not mistaken we should now be able to fully control our categories separately from the accounts.
So let's just ensure that we have a couple of accounts. I'm going to call this account one just in case. There we go. So ensure that your accounts are still working intact. Now let's go ahead and first of all, great, the categories are empty meaning that we are loading the categories.
Let's right here, there we go, new category. I'm gonna call this food. Let's see and there we go. Perfect. Let's go ahead and edit this to food too this works let's check out the accounts great nothing is transferred in the accounts meaning that this is fully on its own Let's go and try and delete this individually.
There we go. Let's try creating a food category, a travel category. Let's select both of those and let's delete them. Let's confirm. There we go.
Perfectly working. Now let's go ahead and let's modify just a couple of changes we noticed in the accounts, right? So I want to go ahead and go inside of my Is it features? Accounts, I think inside of here I'm gonna go ahead and right-click and I'm gonna do find in folder and I'm gonna search for transaction. Alright, so this to do is fine, to do is fine, but we have the edit account sheet component right here.
So let me show you where it is. It is inside of features, accounts, components, edit account. Let's change this confirm message to be you're about to delete this account right because that's what we are deleting. All right is that the only place? Let me go ahead and find in folder again transaction.
That is fine So it was only that one instance that was wrong. And there is also another thing that I believe we noticed here. And that's that we called this use bulk delete when it should be use bulk delete accounts like this. And now this will open up another page where we have to use that and that is our app folder dashboard accounts page.tsx so right here we are this just changed automatically So usually we had just used bulk delete, but we renamed that to use bulk delete accounts. So now it is use bulk delete accounts and nothing else should require the change because inside we had it properly named.
It was only the file name, which was missing some information. And I believe that we also have to go inside of accounts page.tsx and change our data table to not filter by email, but by name. There we go. So if I go ahead inside of accounts now, let's go ahead and confirm that I can search for account one great and let's confirm that our bulk delete is still working and it is accounts deleted perfect and let's see if we have a working message here you are about to delete this transaction So we still have this issue that is because of our accounts columns or actions. It's because of accounts actions.psx So you are about to delete this account.
That's the proper message. There we go. You are about to delete this account and that is perfectly fine. That is the correct message and if I try it inside of here you are about to delete this account as well. Perfect!
So that's it. It took us I don't know how much faster to create categories than it took us to create our accounts. And that's because we established so many concepts and so many reusable components that we can easily do that, right? And it helps that the schema is almost identical, well not almost, it is identical to the accounts page. So the next one we're going to do is the transactions which are going to be fairly more complicated than the previous two, especially because they're going to have relations with the two.
So we are gonna have to complicate it a bit and that's why I first wanted to create the accounts and the categories so that now we can fully create transactions without going back to them. Great, great job!