Now let's create an endpoint which is going to be called inside of the editor project ID page so that we can actually fetch the project from the ID in our URL. So let's go ahead and let's visit our route file inside of Hono. So app, API, route and inside of here we have projects.ts so just here above I'm gonna add a get and I'm gonna specifically add a colon id after that let's also ensure that only verified users can look at this. So verify out like this. And then let's add a Z validator, but only for the param.
And that's going to be Z object from Zod so let's just move Zod at the top here and it's going to be a very simple schema in which ID will be a type of string like this and after that we're gonna have our asynchronous controller. Inside of here, we're going to get the data by using await database.select from projects. And let's just confirm that we have the projects schema here. We do great. From projects where and now we're going to have to create a query which will match the idea of the project but also ensure that we are the author of that project so other users can't load our projects.
So for that, from Drizzle we're gonna have to add the following I believe it's DrizzleRM we're gonna need equals and literally and right, so add those two and go ahead and combine so both two equals so you can prepare them like this or if it's easier for you what I like to do is add these in new lines so then it's easier for me to understand what's going on in this query builder. So the first thing we are going to compare is whether projects.id matches the ID which we have here in the request valid params which is this ID. And then the second thing we have to validate is that users which we have to import from our schema so make sure you've added the users schema here we have to ensure that the user's ID matches our auth.token.id. My apologies, no, it should be projects.userid. Yes, that's the one we are looking for.
And then we don't need the user's schema. My apologies for the confusion. And now inside of here, let's go ahead and do the following. If data question mark length is zero, we're going to return back an error. This means that nothing was found.
So error not found. And let's return back a 404 status code. And then let's return c.json here with the data and simply the first item in the array because we know that we are looking for a unique item. But regardless of that, SQL always returns an array. Great!
So now we have our getById hook. So let's go ahead and let's now create useGetProject hook. So let me close everything here and let's go inside of source inside of features and let's see which one can I use for example use get images is a good one we can copy so let's go inside of projects and let me paste that here I'm gonna rename this to use get project dot DS I'm gonna rename this to use get project as well and now what we have to do is also pass the ID which will be a string inside of here and then my query key here will be project whoops project and I'm also gonna add ID like this? And now let's go ahead and do the following. Let's only enable this if we have an ID.
So we're gonna have to turn the id into a boolean. We can do that by simply adding two exclamation points before the variable. Great! And now that we have that let's actually change this to use our projects and then ID and then inside of here open an object and simply fill the param property to be our ID and if we fail this request we're going to simply say failed to fetch project. There we go.
So that should be it for our use get project query. And now I want to go back to our source app. Where is it? Editor project ID page and this is what I'm going to do. I'm going to change this to be use client like this and I'm going to remove asynchronous from here and I'm going to remove the protect server here.
Instead what I'm going to call is the use get project from features project API get project and then I'm gonna go ahead and create an interface editor project ID page props and I'm gonna leverage next.js's file and folder based routing so that we can extract the project ID from our params so I'm gonna write params project ID will be a type of string I don't know how I refresh this, okay. And now inside of here, let's assign those props. So editor project, oops, editor project ID page props now have params. And now we're gonna go ahead and do the following. We're gonna use get project and pass in params dot project ID and from here we can now extract data is loading and is error.
So let me just collapse them so it's more readable like this and now depending on what we get that's what we are going to render. So if we are loading or if we don't have data we can go ahead and return the following. A class name with the full height, flex, flexCol, items, center and justifyCenter. And inside of this div we can simply render the loader element. Like this.
And we're gonna give this loader element a class name Size6AnimateSpin and TextMutedForeground. Like that. And then if is error we can copy and paste this and change the icon to be triangle alert from lucid react as well and let's change this a tiny bit by adding a gap y5 here and removing the animate spin and then adding a paragraph failed to fetch project and add a class name here text muted foreground and text small let's try these things out now So I will refresh this entire page and now I have a little loader as you can see right here. And then it loads. And now let's go ahead and try and changing this to true and refreshing again just so we can see how the error will look like.
Oh my apologies one thing that we forgot is to wrap this inside of a return. There we go like this. Let's try it again and there we go. Now it says failed to fetch project. So that will be our error screen here.
Great, so change this back to isError. And we can also, let's bring it back to true. So if we get the error, let's also add a button here which will say you know back to home and let's go ahead and give it an as child property let's add a link So I imported link from next link here. And let's give this an href here. And let's give this a variant of outline maybe.
Or actually I think it looks okay as it is or maybe secondary, huh? Let's see There we go, this looks fine so now when I click this I get back home perfect So you can click start creating here again. And now let's change this to be isError perfect and now what we have to do is the following we have to pass the initial data inside of this editor so initial data will be data like this and now let's go ahead and let's go inside of the editor component itself so that we can actually well create the interface which accepts the initial data right So let's go inside of the editor here. Now we have to create interface, editor props, initial data and right now let's make it any. So inside of here we add editor props and we now have initial data but let's actually give it a proper type by going inside of our newly created use get not get images but our use get project hook and let's define the actual response type so export type response type will be infer response type which you can get from Hono so let me just move it above here and let me expand as much as I can so we have more room here.
So infer response type will look for a type of client API projects, specifically id and then specifically get the request and we are going to focus on 200, right? So the positive type of request. We want to return the data. Just a single data here, like this. And now let's use this response type here and let's add it here.
Import response type from features, projects, API, use get project and let me just separate this right here. I like to separate my features so I know where they're coming from and now we're going to be a little bit more specific here. So we will only look for the data, right? We don't need to, we don't need, we don't want to do initial data dot data. We're directly going to pass in the data like this.
So initial data is now JSON name, ID, user ID, height, width, thumbnail, is template, is pro, all of those things. And now we can use that to actually load something inside of here. The only problem is I don't think it's worth it to create that feature right now because we don't even have the functionality to save something. So all of our loading will be completely empty projects, right? We could technically inject into the database directly.
But what I want to do first is I want to add a drawing method here. Not the drawing method, I want to add a saving method for something that we draw, for example. And then I want to come back here and use this initial data to actually load that. And let's just go back to the project ID page and confirm that the initial data no longer has any errors. Great!
So the next thing we're gonna do is implement the autosave functionality. Great, great job!