Full Stack Threads Clone with Nuxt 3, Vue js, Tailwind CSS, Supabase, Prisma, Javascript, PWA,

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
okay so let's start what do you need to get this app up and running all you basically need is node.js so this so make sure you have that installed on your machine and then we can start let's go so let's open the terminal zoom in right in and I'm going to say CD and I'm going to put this in my sites folder and then inside this I want to say npx nuxy at latest init threads hyphen clone and then press enter awesome that is done so now let's CD into threads clone and the first thing we're going to do is install all the dependencies so we don't have to do it later so I'm going to paste this in and it says npmi and we've got nuxjs super bass then nuxjs Tailwind CSS Pena slash NAX Prisma slash client vit pwa next next icon Prisma and uuid we're going to press enter now we're going to wait for this to install awesome that is done so let me just clear this out a sec and we're also going to need to do npmi Pina hyphen f because sometimes with pinea it's a bit funny so if you force install it like this it should be fine awesome done right okay now all we have to do is say npm run Dev and we should be up and running awesome localhost 3000 let's copy that minimize this terminal open the browser and paste in localhost 3000 and there we go there's our next app right now if I open vs code and then I go into my sites folder where I just created that project and if I scroll to T threads clone right there so I'm just going to grab this and drop it into vs code and there is our project awesome right let me just pull this over here a sec let's Zoom that in so we can see it a bit better okay awesome right first up go into nux.config and there's a couple of changes we're gonna have to make in this so above Dev tools we're gonna add pages is true then we need to add our modules and that's going to look like that so we've got next icon on Tailwind CSS Super Bass pinia and Veet pwa underneath that we need our public runtime config and that's going to be runtime config public bucket URL and then we've got process.m dot bucketurl which we're going to make the dot end later but for now we might as well set this up so we don't have to think about it and that is pretty good for the moment if we save that this window should reload yeah and 500 Super Bass URL is required okay so for now just this Super Bass comment that out and save it because we need the um we need to set up super bass and have the end points and stuff like that so for now we can just comment that out and 404 is good because we don't have pages so in the side panel we're going to say new folder pages and then we want a new file inside that and that's going to be index Dot View we need our template for this so let's v-base that up dial we don't need get rid of it I'm just going to put in this index for now and then we're going to jump in app.view and this next welcome becomes not cage and save that now if we refresh this there we go index so we know it's working awesome right we'll start with all the Styles and all that type of stuff because it's easy to do and then when we finish that up we'll do all the back end stuff all the API endpoints convert it to a pwa and then put it on netify awesome right let's go and before I forget the first thing we should definitely do is if you go into the GitHub repository there should be a link in the description so this is the threads clone if I go to public all of these inside here you're gonna have to download so the for the favicon is an image of the threads logo you can see right there and then we've got a GitHub logo and then the pwa logos Anna threads big logo so download all of these and put them into your public folder and that should look like that so there's the favicon GitHub logo pwa image another pwa image and then the big threads logo awesome okay and around this next page we have this div we're just going to add a class to this and it's going to look like that so BG black fixed width calc 100 plus 1 pixel and height full save it and you can see now that our entire screen is black awesome right next we're going to make a new folder and this is going to be called layouts and inside layouts we can have a new file called mainlayout Dot View and we're going to V base that as well I'll get rid of it don't need that and let me close the side panel and we can start by saying ID main layout and then we've got a class H screen so the full height now inside this we've got our first block section so div open it class it with W full Max width 500 pixels and MX Auto inside there another div open it up and add an ID of top menu and a class W full Flex item sender just if I send a px2 h10 and my2 and inside this we're going to add an image tag with a class of width 35 and the source is the threads hyphen logo what we just imported into our public file which is that one right there awesome right now if we save this and go back to index.view we need to import that so we're going to say import main layout from layouts main layout and then instead of this div we're going to say main layout and now just save that and let's see what happens yeah there we go we can see we've got our little logo at the top of our application and it is centered awesome beautiful okay let's go back in mainlayout Dot View and continue so from this image we're going to go down two divs one two make a space and we're going to add in a div with the class Flex with full Max with 500 MX Auto and height screen and inside that we need a slot so we can pass information into it and now underneath this we're going to do our bottom nav so we've got another div open it and open this top bit up but ID of bottom nav and we're also going to add a class that is going to have fixed Z50 bottom zero Flex widthful height 70 pixels border T border T gray 700 and PG black and then inside that divot again add a class with flex widthful Max width 500 pixels MX Auto Flex item sender justify around and in this we're going to add some of our navigation buttons so the first one is going to be a button we can have an act click with navigate to Home a class with full and height full and then we have this little icon in there the name is material symbols home outline size is 35 and the color is white so six F's so let's save that and see what we've got awesome mix here on the bottom we've got this um debugger at the bottom so if we just quickly jump into nux config and Dev tools just put it to a false and let this reload awesome there now you can see we've got our little home icon so let's just add in the rest go back in the main layout and actually if you want to know where I get get these icons from let me just show you the site icons.js I think it is icons.js.org there it is right there and it has got so many icons it is stupid so that is where you get the icons from okay right let's add in our next button so underneath this I'm gonna add this in another button at click we're going to go into the user store and this is going to be for the threads overlay so we're going to set this user store up now let's just finish this section we've also got the class is exactly the same the icon is basically the same we've got a class with mb1 name material symbols edit Square outline rounded size 32 and the color is white and the final button is for the log out and that's going to look like that again we have an at click and the user store is logout overlay is equal to true so that's a different one class is the same with full height full and then the icon is all the same as the one before except the name is pH sign out and if you you save this a sec is it going to break no we can see all our icons right there looking beautiful so now all we have to do is sort this out for our opinion store so all we're going to add into our script is import use user store from stores users which we haven't made yet we're going to go make it right now and then we're going to put the user store into accounts and assign that to it awesome save that now let's open the side panel we're going to make a new folder called stores and inside stores new file and we're going to say user.js and this is very simple I'll just drop it in all it is is that so we're defining our opinion store name in it use user store and then inside the state we have posts which is an array is manual hopefully defaults and is logged out overlay defaults and later on we're going to add one action to this but for now we don't need to put it in we'll do it later so save that and we can close that and now that is our main layout done so we can go on to the index section which is in pages and we can do all of that so this index I'm going to get rid of it and in sign I'm going to say div and we're going to add an ID of index page and a class with full and overflow Auto next inside that another div lasted with MX Auto Max with 500 pixels overflow hidden then inside that another div that's going to be ID posts class PX4 Max width 600 pixels nmx Auto Now inside this we're going to have a loop and we're going to say div VF is post which is going to be a Boolean we'll make that in a minute and then we're going to add a V4 that's going to look like that so posts in post and the key is post and all we're going to do right now is dump out the post object let's save that and down in our script section we're going to add in a couple of things so first we want to import the user store and then put it into our cons also so I don't forget I'm going to import the use super bass user and I'm just going to comment that out for now like that then I'm going to add in the variables and that's going to be posts which is an array is posts which is false and is loading which is false and now under this I'm going to say on before Mount we're going to take this post dot value equals array open that up and we're going to need something that looks a bit like that so we have a name image text and picture so I've just got a placeholder for the image and the picture the image will be an image of you and the picture is going to be whatever the picture is and let me just put this a little bit bigger let me put it to 500 like that okay save that and now we should be able to see our post oh we won't because is post set the false let's just set that to True temporarily so we can see something and I'll quickly just add a class that is going to be text and if I refresh this uh I don't actually see anything well it's happened so I got a couple of errors in this inspect let me just quickly open the terminal and stop this npm run Dev open a new tab close the old one so we terminate the process and then re-run npm run Dev so everything recompiles okay let's have a look yeah there we go okay so yeah it does that sometimes so if you get that error just rerun npm run Dev and it should be okay right close our inspect and put this back over here and now you can see we have our data so next thing we have to do is create a component for each post so we can Loop through it and dump out what we need to see so if I get rid of that delete this class with text white because we don't need it anymore and open the side panel we're going to make a new folder called components and then inside components new file we're going to call it post dot view vbase it get rid of the style don't need it and in our index we're going to drop in that component so we're going to say post has a prop which is post and we're going to emit out of this so when one is deleted we update the post but I'm just going to leave this as an empty array now because we're not going to do any of that stuff yet until we get to setting up Super Bass so it's just kind of there as a placeholder right anyway save that and let's jump into our post component and let's add what we need to add so on this div we're going to add a class that is Z50 bottom zero H4 and widthful inside that another div class with py2 and with full then inside that divot class it with flex item sender and justify between and then inside this we're going to have a block that is going to look like that so the outer Dave has a class of flex item sender and text white and then we have an image tag the class is rounded full h35 pixels and the source is post dot image underneath class ml tool font semi bold and text 18 pixels and we've got post dot name right under this div we're going to put an click event that's going to look like that so at click is menu is not equal to is menu so if it's true it becomes false if it's false it becomes true and we've got a class of relative and all of the variables will do that at the end when we do our script stuff now inside this we need a button open him up and open the top bit we're going to add a disabled and that's going to be is deleting so if it's true it's disabled we have a big class that is going to be Flex item sender text white P1 h24 pixels with 24 pixels of a BG gray 800 rounded full and cursor pointer and under that we have a dynamic class that is if is menu so if it's true we have BG gray 800 else nothing now inside this button we have two icons and that looks like that so first icon VF is deleting is false the name is bi3 dots color white and size 18 and the other icon VLS name EOS icons bubble loading color white and size 18. so if we save this are we going to see anything probably not because we don't have any of these variables in so when we go down to the script and start adding stuff in first we need to import our Pina store so import stores user and assign that to a user store cons we're going to bring in our variables like that and also this use runtime config object because we're going to need it later now we also need our emits and our props so Define emits is deleted and if you remember if we go back to index we have an is deleted right there and also the props we have a post object being passed through I'm also going to add in this Super Bass stuff and comment that out for now because otherwise it'll break and for now that should be good if we save this and I give this page a refresh we can start to see the image name and icon coming through and if I press this icon nothing happens oh because we haven't actually built that bit yet so let's scroll back up and underneath move this button we're going to say Dev VF is menu so if it's true we're going to show whatever's we're going to show whatever is inside it we're also going to add a class that is absolute border border grade 600 right zero z20 mt1 and rounded and then inside this we're going to add a button and that's going to look like that so let me just open this a bit more we have a class on this with flex item sender rounded Gap tool text red 500 justify between BG black with full pl4 pr3 py1 and hover BG gray 900 and then inside that a little div with delete and the icon is solar trash bin trash broken so now if we save that and we take a look we can start to see it coming together but there's an overflow hidden so we need to finish this off to be able to see the rest of it so let's continue from this button let's go three down so one two three make a space div that add a class relative Flex item sender and width full and then we've got a little div block inside that which is going to look like that so let me just open this the outer div is with 42 pixels MX Auto and then the inner single div with the close-in flash at the end of it class absolute ml4 mt1 top zero with one pixel BG Grace 700 and height full now save that and let's take a look still nothing yet let's continue okay under this div block we want to do another div and we're going to class it with BG black rounded LG width calc 100 minus 50 pixels text SM with full and font light then inside that a div with a Class py2 Tech screen 300 post dot text and if we save it take a look we can start to see the text and this little line going down the side and then if I press this button you can now see the delete button that comes up awesome okay next we're going to add in an image under that and that's going to look like that so save that and there you can see now we've got a nice little post image looking beautiful and if we pull it out of it still dead center perfect okay right underneath this image gonna put a div gonna class it with absolute empty tool with full and ml2 and inside that we can have a button open it up and open the top section and we're going to add a disabled is like so if it's true then it's disabled and then this class Flex item Center and GAP one and then inside this button we need an icon and this is the heart icon and that is going to look like that so class P1 text white hover BG gray 800 rounded Fallen cursor pointer the name is MDI cards heart outline and the size is 28. let's save Alan take a look we don't see anything yet so let's add in the little section through display all of that stuff so under the button add a div class it with relative active text SM text Gray 500 and inside this we're going to have a div that has some spam stuff inside it so and now we're going to put in this and this is simplified because later when we have all the other stuff there will be dynamic stuff inside it but for now this will do it so save that and we still can't see it yet because it's hidden but we will see it now when we put this in so after this likes this div if we go down six so one two three four five six make a space divot plus it with relative inline block text Gray 500 pt1 and PB 1.5 I see we can start to see it coming together now there's the heart inside this another div flash it with flex item Center another div inside that with another class that is flex item Center Flex wrap text white Gap one and width 42 pixels and now we have a block with two images inside it and that is going to look like that so outer div Flex Gap 0.5 and we have the first image which is rounded full height 14 pixels and mt2 and then we've got this dummy image in there which is pick some dot photos forward slash ID forward slash 202 forward slash 50. and the other one is basically the same except the height is 17 there's no margin and we got 223 and 50 again so if we save that we go take a look we start to get these little images down the side for there which looks awesome and then finally under this div another div block with one image inside it that looks like that so same again Flex Center rounded full height 11 pixels ml4 and the source is the same as before except the ID is 99 so save it and now we can see if I open this a bit and I zoom in you can see we've got those images down there awesome right zoom out and let's plug that back over there and last little bit go one div from the bottom so make a space there and we're gonna add in a single div that has and then tag in it and the class is H1 pixel BG gray 800 widthful and mt3 let's save it and then we have a little separator line at the bottom just like that beautiful okay and all the styling in this component is done now so if you go back to index and I think if we just make a couple of copies save it actually see now what it looks like when we scroll through it look at that beautiful easy as that awesome right let's revert this right next we might as well make the overlay so we can post a thread so this button at the bottom when we click it we want the overlay to come up so we can add an image and some text so let's do that let's open the side panel in components this post I'm gonna duplicate and I'm going to call this create post Dot View and this bottom line I'm going to delete this section I'm going to delete well basically everything inside it apart from the outer div I'll just delete like that and we're remove this class and we're going to add an ID in a class that's going to be ID created at and the class is fixed Z50 bottom zero H4 widthful and overflow hidden and we should probably change all our script so what we can do the user store stuff we need above it we're going to add in our uuid so add this line in all of these props and variables just delete and then under this we're going to add some new variables so text which is null and is loading which is false we're going to add in this little function that is called adjust text area height so this we're going to get it by ID we're going to put height to Auto and then we want the style height to be dynamic so the text area changes height based on how many characters or words you have inside the text area also I'm going to add in a function called clear data which just clears all of our variables and we are going to add the extra ones in underneath this so file file display and file data and finally we're going to have an on change so when we upload the image we can save it and then convert it into a readable URL so we can see it and for now that'll do so if we save that and then jump into the side panel we're going to go into app.view now underneath the template we need to add a script so we've got a script in with our user store stuff and in our template underneath next page we're going to say create post and we're going to open that up and we are going to add a dynamic class that is going to look like that so let me open this up so what happens if is menu overlay is true we are going to open our overlay so it covers the entire screen and then if it's false we close it so this is what the max side 100 VH is for so view height and then Max side zero when it's false so let's save that and let's go back into create post and let's go up to the template and put in all the stuff that we need so next additive class it with BG black H4 widthful text text white and overflow Auto inside that another div placed it with flex item Center justify start py4 Max width 500 pixels MX Auto Body gray 700 and now inside this we've got a couple of things inside a button so I'll add that in we have a button right there we've got an at click so when we click it his menu overlay is false we're going to clear all the data remember we've got this clear data function down the bottom we've got a little class rounded full and px2 and an icon that is MDI close and just under this button we've got a little div the text is new thread and the class is text 16 pixels and font semi bold so if I save that and now I need to go back into the side panel into main layout and you can see on this button we have is menu overlay equals true so let's go back to create post if I open this up and I click the middle button at the bottom we should get the overlay so let's click it yes beautiful and then we close beautiful right let's add in what we need for this okay so from this new thread div go down one make a space divot we're gonna add an ID and a class and the ID is going to be post and then we've got a class that's Z for the bottom zero Max height 100 VH minus 200 pixels with full PX3 Max width 500 pixels in MX Auto and inside that they flash it with py2 and with full then inside that divot again add another class with flex and item Center and then inside that we have a div block that's going to look like that so the outer div it's got a class Flex item sender and text white and then we have an image that's rounded for height 35 pixels and we have a dummy image at the moment and we have this div at the bottom of these Styles and I've just hard coded in my name at the moment because we don't have a database yet so this will do for now save that you can see it already at the top we open them up image and name awesome right let's pull that back okay so two divs down one two make a space divot add a class relative Flex item Center and with full and then inside this we have a div block that is class width 42 pixels and NX Auto and then this single div class absolute ml4 mt1 top zero with one pixel BG gray 700 in height full let's save it now under that div lassit with PG black rounded LG with calc 100 minus 50 pixels text with full and font light inside that div class with pt2 text grade 300 BG black and with fault and now inside this is our text area so this is going to look like that so we have a v model which is Tech so two-way binding dial we have size renan placeholder starting thread ID text area the input is the function we made adjust text height area which is that right there and a class with full BG black and outline none so save it and now we can see we've got this little section and if we start going nuts you can see that it just dynamically changes size and if we take it away beautiful working perfectly okay awesome right next one div down from the text so one make a space if under that add a little class with with fault and inside that divot open it up and we're gonna add class Flex Flex call gap2 py1 and then inside that we have a div block which is going to look like that so the outer div if file display has something in it we want to display this image and the class is MX Auto with full empty tool MR2 rounded LG and we've got a source which is file display and then finally underneath that div we have a little label that is going to be our file input and that's going to look like that so we've got label for file input we have an icon which is a paper clip so Clarity paperclip line color is white and the size is 25 and then this input we've got a ref which is file type file ID file name input on change it's hidden and it accepts jpeg in two formats and a DOT PMG so let's save that and now if I open this back up and let me just zoom in a little bit if I press this paper clip this opens up and then I'll pick an image open and there we go beautiful so that is working let's Zoom back pull that back to the side and now finally we need to make a button to be able to post it so from this label tag we're going to go down six one two three four five six open this and we're going to add in a button open it and open the topic because there's quite a lot on this and this topic is going to look like that so we have a VF text so if there is some text throw the button if it's loading make it disabled our class is fixed bottom zero fun bold text LG widthful P2 BG black inline block float right P4 border T and Border T gray 700 and then we've got a dynamic class if it is loading text Gray 600 else text blue 600 and then inside this button we're going to add this so if it's not loading go post else if it is loading show this section with an icon that is eos icons bubble loading and please wait so if we save that and then I bring this back into the sender and I type something you can see now at the bottom we have this little post and it's not going to change now if I click it but later on when we add the functionality that will turn to a loading icon and please wait awesome so this page is done now what do we go into our authentication page so our login page because it's quite straightforward so if we open the side panel and in Pages we want new file auth Dot View and v-base it rid of the style and I'm going to do all the script stuff now so we don't forget later so I'm going to add in all of the Super Bass stuff and then comment it out so we don't get an error I'm also going to add this watch effect and then comment that out so watch effect and if user.value is true you want to redirect back to the main page with all the posts because that means you're logged in so you don't want to see the login page but for now just comment that out and the same with the login function so that is the login function we're passing a Prof which is a provider so in this case we're going to pass GitHub and we have this little function which is the super base login so we have client auth sign in with oauth the provider is Prof the parameter we're passing and we're redirecting to origin and at the end if there's an error just console it out so we can see what happens but for the moment I'm just going to comment that out as well because we don't have any of that but now that we have it we can just comment it out right let's do the template stuff so at the top up we're going to add ID of auth page and class with full height 100 VH and pt32 next inside that we got a div last it with windfall then inside that we have a div block that has an image and a span in it a class on the outside is with full Flex item sender just if I send a gap 2.5 and P2 the image class is width 35 and the source is the threads logo which is in the public folder and then a span with a class font bold text to XL and text white and we got threads in there so let's save that a sec and if we go back to this I close that and I go forward slash auth we can see there we go threads beautiful let's continue next underneath this div make a space and add another div class it with Max width 350 pixels MX Auto px2 and text white inside that we have another div which is just login and register now underneath this is our login button and that is going to be button open it up and open this top section and we're going to need to add a class with flex item sender just if I send the Gap 3 p 1.5 woodflow border rounded full text LG and font semi-bold and then inside that a div block that looks like that so we got this little div with these Styles and then the image with all these Styles and the source image is the GitHub logo and underneath text that is GitHub so if we save that and you can see there there is our login page beautiful and that is that page done nice and simple now we have one final page left to do which is going to be the modal to log out so if we go into the side panel component new file modal Dot View and then we're going to say V base get rid of the style and then on our div at the top we're going to add an ID and a class and the ID is modal and the class is quite a lot so we have fixed grid Place item Center H screen Z50 bottom zero BG black BG opacity 50 backdrop blur MD page screen and width full now inside that we got a div and we're going to class that with BG black with full Max width 300 pixels rounded algae text white border border gray 600 and P2 now inside this we have a button I'm going to drop that in that's gonna look like that so we got an at click is log out overlay equals false our class Flex item Center Justified between PG black widthful and P3 and then we have a closed modal text and the icon is MDI close beautiful so underneath this button we have another div and this is a single div with class border border B grade 700 and my one and then a final button underneath that which is going to look like that so class is flex item sender Justified between BG black with full mp3 we got some text that says log out and the icon name is pH sign out so now if we add in our script because there's not very much we're going to say in support the user store assign it to accounts and this super based client we're just going to comment out for a second and we're going to have a little log out function that looks like that but for now we are just going to comment that out as well just in case it gives us an error so save that and what we can do now is open the side panel go into app Dot View and we're going to add our model and it's basically the same as the create post so we're going to copy it paste it beneath free post becomes modal and instead of is menu overlay we're going to have is log out overlay make sure on both of them save that let's go to our browser open it up and then go back to the home page and now if we click this log out button we should get the model so let's click yeah beautiful look at that and then we click this button and it should close beautiful okay I think that is all of our Styles done right so now we've got all that let's set up Super Bass so let's open this browser let's put in superbase.com Tom there it is and I'm going to sign in if you don't have an account you're gonna have to sign up continue with GitHub I think yeah okay so I already have uh threads hyphen C from the previous project so I'm gonna make a new project and I choose an organization I think yeah this one project name threads hyphen clone database password I'm just going to put in this is a test one two three and everything else is fine so create a new project and now all of this stuff we need in an end file so let's go back to vs code and open the side panel and we're going to make a new file so new file dot end and inside this we need three keys so that is going to be that so super bass URL super bass key and bucket URL right let's go back into the browser and we have this project URL so we're going to copy that back in vs code Super Bass URL paste that in and then API key copy paste that into key like that and now we're gonna go make our bucket so on the side menu down here we go in storage and I'm going to say new bucket and I'm going to call this threads clone files like that and I'm going to make it a public bucket because otherwise we need to do permissions and all that type of stuff and in this case it's really not necessary so let's save that like that so save awesome there is our bucket Let me just zoom in you can see all buckets threads clone files which is public awesome how we get access to this is go back into our code we're going to take this Super Bass URL paste it into the bucket URL and then on the end of this we're going to add that so storage V1 object public threads clone files and then we save that and now we have the endpoint for our bucket awesome we also need to go into the side panel for authentication so let's go in authentication and then providers and we need to look for GitHub there it is GitHub enabled we want that and we need to get a client ID and a secret so we need to go and make that and where we do that is we need to go into a new tab and add github.com forward slash settings forward slash developers and then press enter and there's my original clone app and I'm going to say new oauthap application name threads clone home page URL is localhost 3000 application description we don't need and this authorization callback URL if we go back in Super Bass we have it right there so we copy that and then we paste that into there and then register application awesome application created successfully now we have our client ID right there copy that back to Super Bass client ID goes in there and then we need to generate the secret I need to put in my password awesome and that secret has been generated so copy it back to Super Bass paste it in and then press save awesome now GitHub authentication is a labeled so that is the database created the bucket created and authentication enabled awesome okay let's go back to our application let's close this into the side now what we're going to do is open the side panel and open the integrated terminal because we need to set up Prisma next so how we do that is we're going to put in MPX Prisma init and that is successful you can see now that we have a Prisma file in our side panel with the schema and also in our end it has added in this section for our database URL so we also need to update that so let's jump back into Super Bass let's open this up and we need to go into settings database and if we scroll down that is it there the connection string right there so copy that go back to vs code and paste it in the database URL and then your password is whatever your password is when you created the project mine was this is a test one two three and the port we need to change from six five four three to five four three two just like that and that should be it so if we save that and now this file we should be good so if we save there so if we close this and now we jump into Prisma schema we're gonna add in what we need for our database so we only need two tables the first one is going to be post so this is going to be model posts we have an ID which is auto increment a user ID with a uuid name image text picture and the picture is like a long string of characters create it out which is the date and then the likes which is a one-to-many relationship so now if we add in the likes let's go beneath so model likes again Auto increment ID user ID again and then a post ID because these this like or likes are associated with a certain post ID the day and then this at the bottom posts which defines the relationship so post ID and ID are related and then on delete so when you delete the post it also Cascades so deletes all of the likes associated with that post awesome and that is it save it and let's open this terminal and now all we need to do is say oh wait first before we do that let's jump back into our next config and just uncomment this Super Bass module that we commented out before save it and now let's put in MPX Charisma generate enter that has been generated awesome let me just clear this out so we can see it a bit better and then finally we're going to say npm Prisma migrate Dev hyphen hyphen name Annette enter now we have to wait for that to do whatever it does awesome and that is done so now let's go back to our browser and go in Super Bass and if we go into a database and then there we can see how tables so we got the Prisma migrations the likes and the posts awesome so that is super bass and Prisma basically done all we have to do now is do our API and get our application working so if we go back to our code and we can close this now we don't really need that so close pages close Prisma and if you go into server we need a new file sorry a new folder called API and probably the best thing to do is create all of the API endpoints now so we don't have to jump back and forth so first let's say new file and this one's going to be get allposts.js and this is pretty straightforward we need the Prisma client so we're gonna have to import that at the top like so and then assign that new client to a Prisma const and then all we do is say export default Define event handler make it async pass an event open it up and then inside this all we're going to say is a weight Prisma post find many and we're going to order them in ascending order and we want to include the likes so the relationship and then all we do is return and that is it so save that and that is basically how all of them are going to look like so when we duplicate this file rename it to create post.js all the Prisma stuff we need this section will just get rid of and we're going to add in this so we can read the body and then we add that to a body cons and then all we're going to say is Prisma posts create and then pass the date there in an object we need the user ID name image text and picture and that is it all we do then return the result beautiful save it and next let's take this create post duplicate it and it's going to be like post.js we're gonna delete this section out and we're going to change it for that so a weight Prisma likes dot create and the data that's being passed is the user ID and the post ID that is it save it now next API new folder and we're going to say unlike post folder and then inside that we want a new file and this is going to be with a dynamic ID so we say ID dot JS and again we need the Prisma client then we Define the event handler like so and then we add in that so await Prisma likes delete where the ID equals the ID we've passed as this parameter simple as that easy save it and the last one is going to be delete post so if you take this unlike post duplicate it and we copy it and paste it and then rename to delete post we already have this ID in there which is perfect let's go inside that and everything in this is exactly the same except this section where it says likes we change that to post and that's it it's done save that is all of our API endpoints how easy was that awesome right let's close that up okay so next let's go into pages and we're going to do the auth stuff so the GitHub login so off and now we can uncomment all of this like so and we need to add in a couple of extra things first one being on the button we need to add an at click event like so that is log in and we're passing GitHub as the provider and if we scroll down all of this looks good so if I save that and let's go back to the browser nothing has broken so that is a good sign looks good let's go forward slash auth let's open the inspect window just to make sure it's not going nuts yeah that's okay and all of this uh warnings you can see that is from one of my Chrome extensions one of these plugins up yeah so you probably won't have that so we don't need to worry about that let's just get rid of that for now okay let's quickly jump back into our code and this where it says user I'm going to copy this and inside this watch effect inside the F and a console DOT log and I'm going to put the user dot value inside it and just turn off this redirect temporarily so we can see if it's working so let's save that and now let's try and log in so let's press the button looks good authorize John week's Dev let's press it is it working uh something happened I think it is working because there is the access token so oh yeah because the Callback goes to the home page so yeah it is working so now actually if I go back into the code if I revert this save that and then go into the home page so Index uncomment this Super Bass user in our setup and I take the user I go to the top of main layout and if I dump this out let's see what we can see nothing there let's change it let's put it somewhere else maybe inside this posts why is that being funny why is it not working and get rid of that let's go back to Wolf revert this a sec let's put this console log back in inside watch effect and let's go back to the off page off and let's try it again yeah it is working but something is broken let me figure out what's going on okay let's just revert this again put it back to how it was and maybe I need to reset my project so if I go on the terminal and I close this again make a new tab go back to the original terminate it and then say npm run Dev and then reload this let's take a look okay so I did fix it that was being funny the other day I don't know why but um what I've done in the auth page I put the watch effect like that and then in the index page I've put a watch effect inside there as well and imported this user and if there's no user we're going to navigate back to Wolf and I did stop the process so I killed the terminal and then did npm run Dev again so we go on the localhost 3000 and now if I run this we're going to say login with GitHub and there we go that seems to have worked so now if I go into index and I just make a div at the top and I put in that user and then I say class text white and I save it and I go back into this you can see there is the user awesome so if I just open this up and I zoom in a bit you can see we've got the ID email address provider is GitHub and then all the stuff like the URL for the image and the username awesome so everything that we need so that is now working beautiful yeah I don't know what happened to that I mean sometimes development does suck anyway I sort this back out let's get rid of this user and now that we have that we can put it in all the sections of all the pages that that is needed so if we go into the side panel and we'll start from components and we'll just go through each section we need to put the user in so let's start in create post let's open this up okay let's go through it so if we go down to line 20 this div section here with a image in the name we're going to add a VF user so if the user exists and then in the image we're going to say SRC equals user.identities zero index identity data Avatar URL and then for the name we're going to say exactly the same except dot full name at the end then if we scroll down a bit more and there we have the user and the client why don't we just uncomment that save it awesome let's go take a look right so now if we open the create Post Yeah you can see there is my image and there is my name because I'm logged in awesome right close that stack now let's quickly jump into modal.view and we need to make one small change in this so if we uncomment what we commented out before like so and on this button all we're going to do is add an at click that is log out just like that awesome and this one is done next post Dot View let's scroll to the top and this section where it says menu equals not menu let's Chuck that on a new line like that and we're going to add in a VF that is going to look like that so if there is a user and user identities then we're going to say if the user ID equals the post user ID we want to show this button section because that means it's our post and we can delete it but if the user ID isn't the same as the logged in user ID then it's not our post so we can't delete it awesome let's format that save it let's just have a quick scroll through and see if there's anything else yes this post picture uh is going to be dynamic from our bucket so what we need to add is the runtime config like that so we're going to say runtime config.public.bucket URL and then concatenate that with the picture because if you remember in our next config we have this runtime config which is called bucket URL and that bucket URL is coming from our EnV which is right there you can see a bucket URL awesome so let's save that and in our script set action let's just uncomment these so we got them in there like so and at the moment that one should be fine so now let's jump into uh off no actually that's fine we need to go to index.view and this index page what we're going to do is finish it off because there's not really that much to do so this watch effect stuff is perfect and instead of this hard-coded object we're going to take this out and we're going to make it an async and then we're going to say try catch and then let's just console.log the error and inside this we're going to say is loading is equal to true and then we're going to get all of the posts available and then once that is done we're going to set this load into false awesome now underneath on before Mount we're going to have on mounted open that and then inside that we'll have a little watch effect and open that up and inside that we're going to say if users store.post and use the store.post's length is greater than or equal to zero we want to assign those posts or post variable which we've got right there and then we're going to say is posts is true so for now this is post I hard coded it true I'm just going to put it through false like so and then finally we're gonna have a single watch to watch for changes because sometimes on mobile uh the pwa can be a bit funny loading so this is kind of like a fallback function to double check I can say Post stop value open that up and we're just going to take what we put in this watch effect drop it in there like that and at the end of this watch we're just gonna add deep true so deep is watching inside of the object to see if anything changes so then when something changes it re-gets all of the posts awesome right save that and let's jump into our template section so we have this is post under that we're going to say div V else and I'm going to put all this stuff inside a client only tag because it was being a bit funny so basically that means that you don't get any server side rendering for this section and then first off we're going to do it div and then say v f is loading and then we're going to add a class is going to look like that so mt20 with full Flex item Center justify Center and MX Auto and inside this we have a little div block that's going to look like that so a class is going to be text white MX Auto Flex Flex call Item sender and justify Center then we have this icon which is es icons bubble loading size 15 colors white and then inside there we got just this text that says loading and then under that we basically have exactly the same except a couple of changes so I'm going to put this in if it's not loading this is all exactly the same this is also the same the only thing that's different is the icon which is tableer mood empty size is 50 and the color is white and then we got make the first post as the text and that is it so save that and let's just jump back into our main page what is going on in this a user store get all posts uh yeah because we need to put that into our opinion store so go in stores user.js and we're going to add in an action and that's going to be actions open them up and it's one function very simple async Kettle post we're going to use fetch API get all post which if you remember if we go into the server folder API this get or post.js this we're just call in this and then we assign that to a post and also return just in case we need it so save that and now let's go back into our browser let's give this a refresh now you can see we gotta make the first post so that means this is working very good we have no posts which is perfect okay awesome so this is basically the final section now where we're just going to put in the functionality to actually make posts like unlike and delete posts and log out and all that type of stuff so we'll do the same process we'll go through each individual file add in what we need to I'll walk you through what it does and then we'll start using our application and then after that we'll host it on netlify so let's go back to create posts inside components which is right there and let's add in our create post function so underneath on change I'm going to say can't create posts and that's going to be in async we need some variables in that so data out and error out is null and then we got is loading is true now we want to check if we're uploading a file with our post so we're going to say if file data has anything in it then we want to upload the image to our bucket so in the storage and for that we're going to say that so we have await client dot storage from our bucket which is threads clone files and if we just jump into Super basis SEC and we go into our project threads clone where is it storage you can see there we've got a public bucket threads clone files so that is where we're going to store our image awesome go back to localhost and after that we're going to assign the data and the error and we're just going to do that because data and error being passed back and we just to sign them and then after that if we have if there's an error return error we're just going to drop it out if you have this in a real application you'll probably want to do a bit more rigorous error handling and then display the error and all that type of stuff but but for this this will be fine so if there is an error we stop the process and then if there is not an error we're going to say let pick is nothing because we can create the post without an image and then if there is a path we're going to assign that to the picture and then finally at the end we can have a little try catch again and in the try section we're going to say await use Fetch and we're calling the create post endpoint again which is in our server file you can see there create post.js the method is post and we want the pass a body which is going to look like that the user ID name image text and picture and if we just confirm this we go and create post user ID name image text and picture awesome and we're passing the user ID from the logged in user the name the image so the the avatar for the user the text that we've input and the picture that we've uploaded and then after that is complete we're going to say await use user store and then we want to get all the posts after that so we get all the fresh data if he was doing this in a production application you should probably get the new post by ID and add it to the array so just kind of slot it in because if you're getting all of the posts every single time it's going to be kind of slow depending on how many records you're actually getting so just know that if you're doing an application like this in a live environment and then afterwards once that is complete we're just going to close this menu so the overlay and then finally we want to clear the data and then is loading set it back to false and then in this catch section we're just going to dump out the error and in case there's an error set is loaded into false awesome right save either and I think actually we should be able to make a post now so let's try it let's go into the browser uh we're already logged in so let's try and create a post let's open them up we're going to say this is the first post let's try it without an image first let's just click this post down the bottom and why is that our work oh I forgot to add in the at click event yeah so on that button underneath disable just say at click create post and then save that and then let's go back in this and let's try it again let's click post that is working yeah awesome all right so you can see there now on our main page we have this is the first post awesome okay let's continue so so now let's go to the next winning components modal and actually this is done we've already got the logout function in there so awesome post is next and this is the post component so there's quite a few functions in this but nothing to tricky okay let's go to the script section and let's put in all of our functions and then just add it into the template so first we want a computed called has liked computed and just so we don't get any error we're going to say if there's no user just return just exit then under that we can have a let res equals to false and then we are going to Loop through our props so the post object and that is going to look like that so we Loop through the likes inside the post because a post has multiple likes so it's a one-to-many relationship so get each individual like and if the like user ID is equal to the logged in user and post ID equals the post ID being passed as a prop we want to set this to true and then we just return the result which is either true or false awesome that's the first one next we have delete post so let's go underneath we can say font delete posts and we want to open that up we're going to put a little confirm on there so we're going to say are you sure you want to delete this post and then put that into a res and then under that if it's false we just want to exit this function but if not we're going to say try catch and then we're going to start off by saying is menu value is false and is deleting is true and then we're going to get our storage stuff and we're going to say that so again client.storage from threads clone files and we want to dot remove the picture first because we're deleting this so if the picture gets deleted after that we then want to say await use fetch API delete posts and we're deleting this by an ID so we're passing the ID as a parameter and the method is delete so if we just jump into the side panel and go into server you can see delete post and we're passing ID as a parameter there it is right there and now if that is successful we are going to emit is deleted and just pull that to true and at the end of this we're just going to say is deleted is equal to false and then for the catch section we just want to console log an error and just put is delete the default so it stops loading awesome and that is the delete post function done so if we just test that delete post to SEC a scroll up um where is it line 24 when it says vif is menu on this button we're going to put them at click event that's going to look like that so we pass two parameters which is the post ID and the picture and now let's go and test that out so let's go back to the browser give it a quick refresh okay so let's see what happens if we press delete so let's try are you sure you want to delete this post okay and what happened there let's give it a refresh okay so it did delete but it didn't refresh so at least we know it is deleting so instead of worrying about the refreshing at the moment let's just carry on with all of our functions and get him in there so when it's all together we can make make it all work as one awesome okay let's make a new post anyway the test now that we can upload it with an image let's just say image test let's click this little icon and I'll just upload that open right let's clear this console and let's click post and we have a little error there what is that let me zoom in file threads clone file okay let's check it out okay what does this error say at the bottom new row violates row level security policy for the table object okay ah we need to yeah we need to make a policy or our bucket but we're just going to make this extremely simple so if we go back into Super Bass and in our storage so if you come to the side and you press storage and then policies we have no policies yet so let's click this new policy and we're going to do it for full customization all we're going to do is select all of these so select insert update and delete and then we need a descriptive name for our policy we're just going to say oh open policy and then at the bottom we're just going to click review and save policy successfully saved okay right let's go back to localhost and let's try it again let's clear this out let's give it a refresh right let's open create post and we're going to say test and then add an image just pick this one okay and post see if this works yes there we go so now we've successfully created a post that has text and an image awesome so we're nearly done if we just do our like section so this little heart when we click it we have a like and then we'll do a little cleanup and we should be done then we can host it on netlify so let's close this up and let's finish this off so let's scroll down to our script and after delete post we now want to add in like post which is in async open that up and we want to say is like dot value equals true and then we're going to have a try catch and inside this we're gonna do use Fetch and this is pretty straightforward it just looks like that so a weight use fetch API like post a message his post and in the body we're passing the user ID and the post ID which is being passed as a parameter there and then after that all we're going to do is say get all the posts so get a fresh copy of everything and again I think I mentioned this before if it's for a production app you want to have something a bit more specific you want to get you want to get the likes per post instead of calling all of them because otherwise your application will be super slow but for our use case this is perfect and after that all we do is set is like back to false and finish it off we just add a console.log with an error and just in case set like defaults awesome save that next is unlike post and it's almost the same thing so if we go underneath unlike post which is an async let's open them up we're passing ideas parameter and again we're going to say is like is set to true and then we got a try catch and inside that very simple looks like that so we use Fetch and we're going to the endpoint API unlike post and the parameter is the ID which would pass in method is delete and then again we're updating all the posts and setting like back to false and then in the catch same again console log out the error and put is like default just in case now finally one last function which is going to be called likes Funk and let's open that up so this is where we figure out if we're liking or unliking a post first we're going to say let like post object equals null and the first thing we're going to say is if props post likes length is less than one we obviously want it to be alike because there is no likes on it at all so we're going to call this like post and then after that we're going to say else and then we've got a bit of a loop in there so we're going to grab our props post likes for each and we can open that up we're going to say like open it and then inside this we're going to say if like user ID equals your user ID and the post ID equals the post ID being passed in we're going to assign that like to this variable that we've set up here and and then finally after this else we're going to say if the like post object has something in it we want to unlike and then we have this return null to exit the function but if this is not true we're gonna like the post and that is it I'm going to save that and let's update our template so let's scroll through let's have a look so this is like there underneath this disabled is like we need at click likes Funk and we're going to slightly change this icon instead of having one we're going to have two and it's going to be like this so if I get rid of this and we're going to say that so if has light computed is false we're going to show the empty heart so MDI cards heart outline else if this is true we want to show the full heart MDI cards hard and you can see on this top one we have text white and on this bottom one we have text red 500 so we have a red heart awesome save that and inside this little section on line 70 we're going to add in a couple of things it's going look like that so if is like is false we want to show the length how many likes there are for this post else we're going to show this loading icon which is eos icons bubble loading and that is it save it and let's just have a look yeah we should be good to go so if we go back to the browser you can see now we have zero likes let me just zoom in a bit zero likes right there and now if I click this we got the loader and there we go we like the post awesome so now if we click it again we should unlike click awesome that is working perfectly so I think actually this application is done well let's try and delete this a sec so let's delete are you sure you want to delete okay that is loading and it wasn't an error but it didn't go away so let's figure out why it's not reloading let me just give that a refresh yeah so it's definitely deleted okay so let's jump back into our delete function and what have we got oh this emit is deleted okay so let's go back into index and we have this is deleted right there so we need to update that and all we're going to do for this is put that so posts equals user store get all posts that's it save it and now if we go back in the browser let's give them a refresh right let's create a new post let's say awesome let's add an image I'll add this one there we go and now we're going to say post and let's see if it works beautiful look at that awesome let's like it and then let's unlike it yep beautiful working perfectly now let's delete it okay okay so I made a slight change to our index page from index.view inside the watch effect I've taken this out of the if statement so before this was in there like that so put it on the outside there and add this else at the end and Pern it is post is equal to false and then just take this copy it and paste it into this section into the watch down the bottom and then save it and then if we go back into this add post let's say cool pick an image this will do and then we just say post awesome that is being created let's like it working unlike it awesome now let's test the delete so let's delete and hopefully it should show us no posts awesome there we go working perfectly now let's try logging out log out yep we can log out let's log back in awesome this is working very nice let's just create a little post let's say cool post We'll add this little image again post it and there we go awesome right let's set this up so it can be a pwa and this is very simple let's go to our code next.config and underneath Dev tools we're going to put in this first so pwa manifest and we got all this stuff the easiest way is just go to the actual repository that I put in GitHub and just paste it in it makes it much quicker and the same for the app we're just going to add this in like that so app head and then the viewport size and stuff like that for mobile awesome save that and now we're going to jump into app.view so our main file and at the top of this all we're going to do is say pwa manifest and that's it save it and because we've already got all the stuff in public like all the pwa pictures and stuff like that we should be good to go so let's go back to our browser and I can see it right there the download button to install threads clone so let's do it let's install threads clone and there we go look at that bad boy how easy was that and we can see now in our little dock at the bottom we've got our little threads clone icon so that is it let's just give it a little test let's like awesome let's create another post let's say pwa post and let's just add this threads image again post it awesome that is in there let's try and delete this one okay let's delete awesome yes look at that okay this is working beautiful
Info
Channel: John Weeks Dev
Views: 25,611
Rating: undefined out of 5
Keywords: vue js, vue 3, laravel, laravel sanctum, laravel spa authentication, laravel authentication, laravel api, laravel api tutorial, tailwind css tutorial, axios, axios interceptors, pinia nuxt 3, pinia vue 3, pinia vue 3 authentication, php, javascript, intervention image, intervention image laravel, tiktok clone, tiktok clone app, file upload in php, build a tiktok clone, linktree, linktree clone, camera javascript, digitalocean, hosting, javascript camera, nuxt 3, nuxt js, vue, nuxt
Id: TfKDkErJUtk
Channel Id: undefined
Length: 69min 14sec (4154 seconds)
Published: Mon Jul 24 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.