In this chapter, we're going to develop the widget screen router. This is basically going to be our own custom routing system using Yotai as our state management. And my apologies in advance if I'm pronouncing it incorrectly. Basically, the reason we are doing this and not using Next.js routing which is completely fine by the way you can implement it with that too. But I kept thinking about this widget application and I just feel like it's a very very small app.
The reason I initialize it with Next.js is so I can share components from chat.cn so I have the exact same style. That was why, right? But I keep thinking of it as a very very lightweight component that could easily be moved into just react with Vite or something like that. So for that reason I don't want it to depend on Next.js routing. So that's why we're going to implement our own.
So let's start by adding the Yotai package. So let's go ahead inside of here pnpm f widget add Yotai. Feel free to correct me in the comments how to pronounce this if I'm doing it incorrectly. Perfect. So we just added that package here inside of our widget package Jason.
Now let's get inside of a widget and let's get inside of components inside of providers here. And how about we import provider from our new package. And let's go ahead and add it here like this and now what we can do is we can create widget atoms so let's go ahead instead of the widget app and I'm gonna go inside of modules here inside of widget and I will create atoms and I'm gonna go ahead and call this widget atoms dot DS. In here let's go ahead and let's import atom and let's go ahead and create the first one so basic widget state atoms export const screen atom will be Atom and the default screen will be Loading, for example. And now let's actually create a type and some constants to actually define all possible screens in our app.
Inside of the widget module here I'm going to go ahead and create types.ts and I'm going to export const widget screens as an array. And these are all the possible options. Error, loading, selection, voice, auth, inbox, chat and contact. As constant. And let's also export const contact session key.
And in here, I recommend that you add like a little prefix like echo contact session. Echo would basically be your app name something so it doesn't conflict with some other app right because this will be our local storage key we're not going to use it now but I think it's cool to add it already here since we're defining. And my apologies, these aren't the types, these are constants, like that. Now in the same widget module, let's create the types. And the only type we're going to have will be using the widget screens.
So let's go ahead and import widget screens from modules UI, my apologies, widget constants, export type widget screen will be a type of widget screens and then just an index to access it. And when you hover over, you can see all the possible options. Now let's go back instead of our widget atoms And let's go ahead and type it correctly, like this. And I like to use modules, widget types. And there we go.
So now if you try something else, you will get an error, right? We can only do specific screens like ALF. So change it to ALF actually because that is the current screen that we have. Like this. Now let's go ahead inside of our widget view.
So that is inside of modules widget UI we have views here so widget view like that and in here what we're going to do is we're going to import use atom value from Yodai. Let me just remove this imports. Don't need them. So import this like that. And then let's go ahead and set const screen here to be useAtomValue.
And inside of here, let's go ahead and let's add screen atom from atoms widget atoms and I'm just gonna replace this with modules widget UI screens and this too you didn't have to do this I just really like it this way. All right. So now that we have the screen here, let's create a constant screen components. And now for the error, let's go ahead and add error. Let's just say to do like this.
And now let's go ahead and do the same for all other options. So just like this. Error, loading, alt, voice, inbox, selection, chat and contact. Now the only screen that we actually have here is the ALT screen. So we can already use that.
So widget ALT screen and it's a self-closing tag like this. And then inside of here let's remove this and instead let's do screen components screened. Just like that. And now since inside of our widget atoms, we set the ALF to be default, if you actually run through both dev and head to localhost 3001, because that is where our widget component is, you will see out here, right? But if you change this to loading, for example, you will see to do loading, right?
So that is our little internal routing system here. So let's go inside of the widget view now. And what I want to do now is I want to create the error screen and I want actually, let me see what is the best course of action here. Well actually it doesn't really make sense to go anywhere right now because we can't really develop any other screen before we finish the loading screen. The loading screen will ensure that we have organization ID, that we have verified the organization ID and that we are then ready to redirect the user to either the out screen or to the selection screen.
So in the next chapter, we're going to develop the loading state. And we're also going to implement the ability to save our contact session inside of local storage for each organization ID. So that's why I want to separate those chapters simply because in this chapter I just want to focus on adding our state management as we just did and adding the atom values here screen atom. So let's go ahead and end the chapter here. So I'm going to add all of this changes here.
So we did all of this. We added our state management, created the atoms, defined the screens and created the router. So 11 widget screen router. Let's go ahead and commit. Let's go ahead and create a new branch.
11 widget screen router. And let's publish this branch. And let's go ahead and let's review our changes just to see if there is something seriously wrong with the app. I always like to do a double check with CodeRabbit especially because it notices security issues before we do. And that's something important, especially with the anonymous part of this app, which is the chat box, where anyone can submit anything.
And this one was fairly simple. So we introduced dynamic screen rendering in the widget, allowing different views such as alph, error, loading, etc. To be displayed based on the current state. We added new constants and types to support multiple widget screens and session management. We also added new dependency to enhance the state management capabilities.
The only comment that was left here was to add organization ID, but we're actually not going to do that because we're going to be using the atoms to store organization ID as well as some other things of course. So we can go ahead and merge this pull request, no other comments, perfect. And after this pull request has been merged as always make sure to go back inside of your main branch and just synchronize the changes so that you have a graph that looks like this. We detached to implement the screen router and then we merged it back here. Amazing!
That is the end of this chapter and see you in the next one.