Public Lunch Week Page

Adding a Public Lunch Week Page

Project Source Code

Get the project source code below, and follow along with the lesson material.

Download Project Source Code

To set up the project on your local machine, please follow the directions provided in the README.md file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.

This lesson preview is part of the Fullstack Svelte course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.

This video is available to students only
Unlock This Course

Get unlimited access to Fullstack Svelte, plus 70+ \newline books, guides and courses with the \newline Pro subscription.

Thumbnail for the \newline course Fullstack Svelte

Okay, so the purpose of our application is to publish a weekly lunch menu for the public to access. And to that end, we are going to use what we've learned so far and build a lunch menu view page with a public express endpoint for the data. The page is going to look like this. We'll have the school name and then a little table where we'll display the lunch menu for each day. I've gone ahead and populated some data here that we'll use. So this is the week of 1112.21. So this will be what we use for this lesson. And what we're going to do is use a nice front end convention where the user will be able to see the school name in lowercase with a dash. And then the date. So 2020, 11, 16, for example, in this example. And so we're going to use these two pieces of the front end route to determine what data to pull from the back end. So we'll kind of parse that out. We'll build a URL that will send to a git endpoint on the back end. Let's get started with the back end API endpoint. So we're going to create a new file called lunch week public in the routes directory. So on the back end project routes directory new file lunch week public. And then this will be our first version of it. So this will just be real simple. We're just going to parse the week of peram and then just send it back to the caller. And then we need to import the new route into app.js and register it with the router. So go ahead and grab this part over in app.js. So I'm going to put it right here next to the other routes. And then put it right here. Okay. So let's give this a try in postman. So I'm going to try this sample URL. Change this to a git. Put in the URL. Okay. So I'm going to delete this body. We don't need that. So that's going to give us back just this week of. And that's all we're doing so far. So 1115 here, 1115 there. Okay so the back end end point is up and running. And so we're going to need to wire it up to the database. And earlier we created a dynamic next module that caches and returns next instances based on JWTs. And we use that for our secure grounds. But in this case, we need to access the database from a public route. And so what we're going to do is add another middleware function inside our dynamic next module. And we're going to call it pass next public. So let's copy that. And dynamic next.js. So right now we have pass next. So we're going to add pass next public. And we're going to have a public middleware function here and then a secured middleware function. And so this where we need to start being pretty careful as developers to not use the public middleware function where we don't want to and to only use the secured function where we need security. So I think we should change this name to pass next secured just to make it a little more obvious that this is the secured one and this is the public one. And then what we'll do is export both of them. So we need to change the module dot exports line. Okay. And then since we changed this name here, we're going to need to change it in app.js. And we also need to put curly braces around the import statement since now we 're importing excuse me exporting two functions. So let's change that as well. So right here where we had pass next. Now we're going to change it to curly braces pass next secured. And then we need to change it down here as well. And next we need to apply the new pass next public middleware. And for consistency, it would be really nice if we could use it in app.js right here. But unfortunately, it depends on rec.perams.school name. So it depends on this program right here that we're sending in. And we can't use it in app.js because rec.perams are not parsed by express until after the router.use calls. Unfortunately, they're not parsed until kind of after this step in the chain. So what we're going to end up doing is using it down here at the individual route level. So we're going to import it there. So in our new lunch week public file, import it here. And then we're going to put it inside the router.get middleware or excuse me, router.get endpoint function. So it's going to go right here. Okay. And then we can assign tenant next. Uncomment this part. And then we'll assign it there at the top. So it's going to be passed in. It's going to be similar to the way the other one works where it's part of this , excuse me, by using this middleware function, we're going to add next to our rec. And so that'll make it available to use right there. Okay. So now we've got next ready. So let's create a helper function to return the data we're looking for. So here's our helper function. And we're going to get the lunch week for the week of that's passed in. But we're only going to return where is published is true. So even if the week exists but is published as false, we're not going to return that. And then if the lunch week exists, then we're going to nest the lunch days underneath it. And so we're going to select from lunch day for that given lunch week that we found here in the first step. And we're going to just return the first record. So this will return an object and not an array. Okay. So now let's finish up this endpoint here. I'm just going to copy this whole thing. Okay. So we get the tenant next and assign it to tenant next. We parse the week of variable out of the rec.perams. And then we're going to get the lunch week. Now we don't need to worry about the school name because this rec.next has already been assigned to a school based on what we did over here in this past next public. So we've already got the school part handled. So we just need to worry about the week of part here. And so if our helper function finds that week of then we'll return it. Otherwise we'll return a 404 status not found with a message that says no menu has been published for the week of. And then if we do get an error we'll return a 500. Okay so save that. And now we can test this a little bit better with some actual data. So I've got sunny side high school here and then I've got week of 1112.21. So let's give this a try. Now it's not published yet so we shouldn't actually get any data back on our first try. 2021.1.11. Okay database sunny side high school does not exist maybe. Let me check that. Okay so it's sunny side high. Okay so now we get no menu has been published for the week. So let's try it. We hit this publish button now that menu has been published. And now we get the data back. So here's our JSON payload for that endpoint. Okay so now we can work on the front end. And we already have a placeholder spelt component called lunch menu view dot sp elt. And we're going to work with that next and we'll use the on mount function to fetch the data from that new endpoint and then render a table. We'll use the normal process with a loading icon and an error message state variable to inform the user of any errors. So here's the script portion. So it's going to be lunch menu view dot spelt. Make sure we've got an ending closing script tag. Okay so on mount we're going to get the school name from the actual route in the front end and then we're going to get the week of from the actual route in the front end. And then we're going to send that to our API. And when we get the data back we're going to assign it to this lunch week state variable. And then we've also got a loading state variable and an error message state variable. And then for the markup portion we're going to use our helper function get school name. And all this is going to do is take a lowercase school name with dashes in it and turn it into proper case with spaces. So it's just going to make a nice human readable school name. And then we'll show that as a header at the top. Here's our loading section. So we're going to show our spinner icon. So we've imported icon and refresh. And then we're just going to have an each block. So once we get our state back inside this lunch week variable we're going to iterate it with an each block. We're going to parse those ISO dates and show them in a user-friendly format and then show a little table with the menu details. Okay so we need to do one more thing before we're ready to test this. So the component we've been working on depends on a route convention that has the school and in the week of in the route. And so we need to configure the front end routes.js to use those as named parameters. This is where we use the syntax colon parameter name. So let's go update routes.js on the front end. So front end routes.js. So right here we don't have the name parameters. So let's add this. And now we'll be able to read school and week of from this route in our spelt component. Okay so let's give this a try here. So here's our kind of our admin page. Go ahead and start a new tab. And we're going to do instead of admin we're going to do lunch menu and we're going to do sunny side high. 2021 0111. Okay so when we do that we get our no menu has been published message. So let's just look at the network tab. So we're getting our 404 and with a response with our message from the back end . So let's hit the publish button here. So now it's been published. Try it again and now we get our data from the back end. And let's see. Here we get our data from the back end and it renders here in the table on the front end. Let's try this in an incognito tab. And make sure that it works without a token. So here we go without a token. Looking at our headers we don't have a JWT here. So this is working for a public user without a JWT. Okay. So another thing we can do. This will be a kind of a nice to have feature is adding a link button to the lunch week details page. So it's kind of hard to construct that URL and it would be nice if we just go ahead and generate that link for an administrator to use. They could then send it out in an email or a text message or something like that. So let's add a helper function here. Get public link. And we'll add it to lunch menu admin details. So here's a helper function and we're going to use the data from the user store to get the school name. We'll lowercase it and then we'll add dashes to it. And then we'll use window.location.origin and then the school path that we just retrieved right there and then lunchweek.week of which is data that we already have in this component in our lunch week state object. So that'll give us the public link. And then we're going to use a Bulma dropdown to show kind of a mini modal. And this will be a button that a user can hover over and it will show a little modal right next to that button. And that will contain the public link using that helper function. So this is what the mark mark up looks like. You got a div with class dropdown is hoverable and it's going to trigger based on a button called link. And then this is the actual dropdown content. So we're going to have a little title that says public lunch menu link and then we'll actually get that public link from our helper function and Svelte will render it there. So copy this bit of the markup. And right now we've just got two buttons. We've got the save button and the toggle publish button. So put it right below that second button. Save that. Let's give it a look. Okay. So here's our link. And then when we hover over it, it gives us that public lunch menu. Now it's kind of narrow. So we can address that with a style. So we're going to target the element with ID link dropdown menu. We're going to target this element ID right here and we'll give it a min width of 32 rim and that'll make it good bit wire. So copy that style block there. I'm going to put it right above all this markup. Now let's give it another try. There we go. So now we get a nice wide dropdown there with the link. Okay. So that's it for this lesson. We added a public API endpoint and that allowed us to create the public lunch menu view page for non authenticated users. And to an to accomplish that we had to introduce a new pack pass next public middleware. And we also changed the existing middleware just the name of it we changed to pass next secured so that developers can tell the difference between the two. And then we just kind of followed the standard recipe on our Svelte components. We have a loader flag. We fetch the data in the on mount hook and then stored into our state and then Svelte does the rest. So thank you for joining us on this lesson and we'll look forward to the next one where we're going to talk about production deployment. (silence)