Next.js, Mapbox, Prisma: Crosswalk user voting platform - Project Overview (Crossywalk)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
so I live in Toronto and I used to work in this building 121 Bloor and to get there every morning I would take the subway to here Glory Young and then the exit is right around here yeah you pop out of the subway right here and then I would have to cross from here to get to here this building and if you look carefully there's no crosswalk so what are my options I could either backtrack to blue or young I know there's another exit here actually but I never come out of that one or I could go to church which honestly neither option is that far but nobody has the extra two minutes in the morning so what would I do I would just risk my life here naturally and I can show you a better picture right here across from over here to over here so that's not ideal but I'm also pretty sure that at least 50 people in this building do the exact same thing at least 50. this I mean we had 400 people in my office alone which could be pretty powerful we could somehow aggregate our our thoughts together and there isn't really a good way to do that in Toronto right now if you want to request a crosswalk you have to either visit someone or call someone which is a complete non-starter in 2023 so I decided to make a cute little platform to do just that that's what we'll be talking about today so the first thing you see when you get to crossy walk.com is this map and it'll show you all the existing suggestions you can click on one of them it'll Zoom you in and copy the link if you want you can upvote things you have to log in so we'll do that in a sec and you also can search a specific location I'll just do Cherry Beach and it'll bounce you to it there's also these tabs over here that'll fly you to different cities but we can do that in a sec so let's say we want to stick a crosswalk here I actually haven't been to Cherry Beach in a while so suggest crosswalk you have to log in and this just uses the built-in next off uh with the Google service provider so here now I can it bounces you to the same spot after you log in and we can add our own crosswalk so I'll do that here summer is approach especially for families and dogs something like that and then we hit submit it'll give a sec and there it is there it is so zero up votes right now um I can upload myself I can go to my crosswalks to see the stuff that I've already suggested and pretty simple just a bunch of cards here and you can also do things I can show it on the map show on the map I can edit this one so let's say very busy so that'll edit it you can see it updates it'll be shown on the map again it'll it'll update there and finally I can delete so are you sure yes delete and then if I go back to here yep there is nothing at Cherry Beach so that's that one final thing I forgot to show actually is just these tabs over here they'll fly you to the cities that honestly just where my friends live you know New York London and Hong Kong so pretty straightforward there so on the front end I'm using xjs I like it a lot and the site eventually is deployed in Versa and also use a lot of Tailwind UI components so that is the one you pay for and yeah it's up to you to decide whether it's worth it or not I I find it very helpful on the back end I'm using a postgres database hosting on Heroku which is not free anymore and I'm using Prisma as my orm Prisma is something I've used for other projects and I just think it it works pretty well and I like it and this map part this is actually where a lot of the new things came in for me and this is part of why I wanted to do this project was to get some exposure to maps and mapbox and then finally behind the scenes I'm using the Google Places API so this Powers the search functionality so that example I used if you search for charity Beach this API is what takes that query and then gives me coordinates back that I can then feed into mapbox so that's the tech stack and I'm now going to jump into the code so I'm going through the front end code first because I think it makes more sense you can see how it maps to what you actually see with your own eyes so this is a pretty typical next photo structure this is nexjs13 but I'm not using the app directory so you can still see your pages my Prisma directory which is where I Define the schema Source where I have a bunch of these components that's pretty much it but straight off the bat I do something that you probably should not do because my index is actually not really in use when you go to crossyalk.com it actually redirects you to crosswalk.com whatever location this is some coordinates and then a zoom level that's why this index.js is not in use otherwise it would typically be so that's actually a dynamic route here and this is the real home page so to speak the way I do that redirect is just in next config so when you try to go to index.js it'll bounce you to this location which is downtown Toronto if I were to take this further I would try and make this location actually the location of your device which would be cooler but let me go do that later so starting from index.js in location there's the dynamic route you see your typical head tags uh there's a bit of a loading spinner but this is the first thing I actually will dig into is this layout component as you'd expect stores the basic layout of the site this is the stuff that really shows up on every screen so mainly the navbar I think it's honestly only the navbar here so I just keep everything in this layout dot JS and then here is where I actually have the real content so in index I pass this down into this layout and here it is this main main prop and that shows up here jumping back to this index I do have get server side props here because I want to do some work before serving the components first I do some very dirty validation to see that the URL actually contains a valid location it's not the best way I'm sure I could find better ways to do it but it's quick and dirty and then here I'm just calling the database to retrieve all the existing markers and then I passed all these three things into my props and then I can access them up here so I'm going to go down the rabbit hole now of showing you how this page actually comes to be from index we go to places and then from places we have this map component this is where the bulk of the map logic shows up and it's a bit messy but bear with me so we have a bunch of States here to keep track of things like whether a panel is open and pop-ups open right this is what I'm actually returning right this is the map and you can see I have my on move on click handlers things like that then I finally have a bunch of these other components which control things like crosswalk panel that's the side panel that shows up when I want to edit something for example this panel is what shows up the authorization model that's what pops up when I try to log in and some other modals so you can see that these are controlled by these states that's why I have so many states up there of panel open set panel open probably is a better way to do this so I was just going quick and I kept adding modals so that's really the bulk of how this works you have the index page and then there's a sub component which is this places component and then there's a map component within that that is how this big map screen shows up and how I get that data into there so that's the front end and I'll now go through a bit of the back end stuff so this is what I'm using this postgres add-on you do have to pay a bit of money now it used to be free but I'm using my GitHub student credits so if we hop back into vs code this is my Prisma schema so this is where I Define yeah the schema for my two tables I only have two tables one is to hold all the crosswalks and one is to keep track of the votes the API calls are in Pages API and the way I use Prisma in this project is here I actually export this Prisma client and what that lets me do is I only have to instantiate the client once and not every time I have to use it when I make an API call those API calls they are sitting in Pages API and there's actually a few more here than I need I didn't end up using all of these but an example would be create crosswalk this is good so let's go through an example of this one a little bit I call this with axios I'll show you later first I'll just check that there's a session I grab the data from the request body here is what I do I'm importing that Prisma client that I showed you just now and so it's just await Prisma dot create and then this is the data I get the result so it's fairly straightforward you could do some better error handling here again probably could do anything better here and this is called for example in one of my components if I remember which one yeah this was that the panel that pops up when you try to edit or create a crosswalk so this side panel it actually shows up in one of the helpers the handle submit so when you hit this submit button it grabs all the data in this form that you write down here it goes to either create a crosswalk or update a crosswalk that's how I use I use these roots but I don't have a root for every time I need to actually call the database if you remember actually this original index.js I imported that client directly and I just call it a find many because the goal here is to retrieve all the crosswalks in the database I'm not doing a specific query so I found it easier to just include this find many in get server side props so I'll take a second here to talk about authentication because I just used this out of the box next auth JS which I found very helpful what allows you to do is use these built-in providers like Google or GitHub I use the Google one here so you don't actually have to handle user data really or you don't have to handle saving emails saving passwords there are upsides and downsides for a project like this where I'm trying to just get something out go quickly I found it super simple what I did there is under API Pages API there is this little provider setup there are plenty of guides out there I just followed one of them and this next auth is something that I import in other components or Pages this my crosswalks page for example so that's where you can see your crosswalks and you use it in get server side props to just get information about the current session that's how I did that and honestly all this back-end database stuff took me a second to figure out the way I have it set up here it works for small scale projects if you want to scale something further it probably is not the best way I'm not doing things like the roots in the most efficient way and it's probably also not the most secure but we'll move on and we are into our final big section which is all those map business and this was interesting this was a good learning experience for me so if you want to play with maps then I will try and give you some knowledge here this part was also a little bit annoying because you had to to read docs but maybe I don't actually need to read docs anymore that's my first time using mapbox so I definitely still have a lot to learn but it was just super smooth straightforward and and satisfying to use honestly so I didn't use mapbox straight out of the box I used react map GL which makes it even easier to use mapbox with react they're pretty good docs you'll probably be able to figure stuff out and there's a decent amount on stock overflow or Reddit already and I'm gonna pop back into the map component because that is this map that you see here so looking at map I'll just go through everything we have here I have an on move helper which just handles the dragging aspect of it you can see how it's taking the event and it's setting the view State it's just updating that so I can drag around zoom in zoom out my map style this is a custom map style which map box is pretty good in this I can go into more detail in another time perhaps but you can make these custom map Styles and control what you see on the map so what I did because this is a web app about crosswalk suggestions is I kept the crosswalks here and I removed things like subway labels for example or there's an option to show the streetcar tracks makes more sense but I have to show the streetcar tracks I took those out so keeping the crosswalks and some minimal labeling in so I really like that about mapbox they make that super easy an access token pretty simple and unclick Handler so this is oh never mind handle click there's just some small manipulation on when I hit suggest crosswalk I want to see a Crosshair if I cancel then it goes back to a pointer and unload right this is just when the map loads that's how I control the spinner so it stops spinning when the map loads and then I load everything at the same time and then finally I have the way I did this pop-up I talked a bit about it briefly but pop-up info is something that I'm storing in state and so when you select a crosswalk it sets pop-up info right here with the information of this marker and so then pop-up info is no longer null and so then this pop-up component is rendered and yeah I could probably clean this up a little bit um maybe I will maybe I won't and then I finally have within each pop-up This Heart icon and then there's handlers for the upvotes there and handle upvote is what controls whether this is um the vote counter and also whether this is red or not and what I'm doing here is I'm calling yeah more Roots uh the upvote and the downvote crosswalk API room so that is honestly it for the map I can elaborate on this more because I did learn quite a bit trying to figure this out if anyone's interested if anyone even watches this I don't know if anyone will watch it but yeah that's it for the map I will quickly go over this location search because it requires fiddling around with the Google Maps API as a reminder this is the search box here so you can just jump to specific places and what I am using here behind the scenes is the Google Places API and specifically Place search I believe place is autocomplete never mind places autocomplete so what I'm doing with this autocomplete API is that as I type it will give me suggestions to autocomplete my my search term and then once I hit enter or search it takes that string and because it's Auto completed it converts that string into coordinates and I access those coordinates with this Handler in my search box component this handle select which gives me the result I geocode the address I get the latitude and longitude from those results and then this set selected is a function that I pass into this search box so if you notice here set selected is a prop and I'm keeping track of that here it's a little confusing again could probably do it better but end result is when I search it auto completes it for me when I search it I can grab that result I can pass it back up from the search box component into the map component and that's how I control where to fly to on the map so I got lazy with the tripod setup and I'll just do the conclusion this way this isn't a big project but I had quite a bit of fun making it and there are definitely a ton of things that can be improved especially on the database side this were a real thing up and running the first thing is probably to just cache the existing markers so you're not retrieving it on every page though you notice that was a little bit slow so yeah I'm not sure if anyone will actually watch this or if it'll just stay as part of my portfolio if people do watch it and you want to see more of anything in here that's worth elaborating on let me know and yeah go check it out crossywalk.com you can leave some crosswalk suggestions in your own City perhaps and thanks for watching
Info
Channel: Hudson Yuen
Views: 4,171
Rating: undefined out of 5
Keywords:
Id: 5jnd4w65lWs
Channel Id: undefined
Length: 15min 53sec (953 seconds)
Published: Sat Apr 01 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.