Okay, the next thing we're going to take a look at is adding the ability to upload a file via our browser
as well.
And if we take a look at our product form, then effectively we're going to have the ability to drag
and drop an image inside here or click and select an image from the file system.
And we're going to get some help with this in the form of react dropzone.
This gives us the utility so that we can just display a drop zone on our page.
And that gives you that functionality that I was referring to.
So it's just a matter of installing React Dropzone.
And if we take a look at a basic example then it gives us this kind of functionality.
If I just go and drag a file in to this drop zone, then we can drop it in.
And then we've got access to the file, which we're going to effectively add as one of our form properties
effectively.
But that's the idea of this.
And that's what we'll add now.
So we'll go across to VS code.
And this is something that we're going to need to install.
I'll clean things up at the top.
It feels like it's getting busy up there and I'll go into the client folder.
So I'm just going to CD into the client.
Please make sure you're in that client folder before adding any npm installs.
And I'm just going to use npm install react dropzone.
Now if you're on a stable version of react 19, then you won't need to do what I'm about to do, which
is add the legacy dash peer dash deps switch.
I'm 99% certain that's going to be required for myself.
And now Lance is installed and available, so now we can go ahead and use it.
So we will just make this a shared component, just like the other ones that we've added so far for
our select input and our text input.
And I'm just going to right click the components folder and say app dropzone dot TSX.
And once again I'm just going to use the text input just to get the starting point for this.
I'm just going to control a Ctrl C and paste it inside here, because it is going to be a form input
that we're working with here.
We don't need a label for this one, so I'll remove that from the props.
I'll keep the field values and the controller props.
And we're not going to extend from anything on this one apart from the use controller props.
So I'll remove the text field props, but we'll keep the use controller.
And I'll just change the name of this to App Drop Zone.
And this is going to extend field values and props etc. because we still need the field functionality
so that we can add this as part of our form.
Because if we remember what we did in postman, then we needed to send up the image as a file inside
the form body or form data.
That's how we're sending it up to our API.
And then we don't need the text field inside here.
So we can remove this.
And let's go across to the docks and see if we can just copy anything from their basic example, just
as a as a quick look to make sure we've got the functionality we need.
So inside here inside this basic example then we use a hook for use drop zone.
And then this part here is so that they can display the file path and the file size.
We saw that in this example up here.
And then we've got our return statement with stuff.
Let's just copy the elements from here I'm going to copy the use drop zone hook.
We need that anyway.
So I'm just going to add that inside this component.
And I'll just bring in using the quick fix the add import from react Drop zone.
And then in the return statement let's take a look at this.
We've got a section here.
And then we're using the Get Root props and giving it a class name of drop zone.
And then the input drag and drop some files.
Okay, let's just copy this and see what it gives us.
We'll be replacing it very, very soon.
So if the documentation has changed then feel free to copy this in.
But it's only temporary.
Just to make sure we've got the basic functionality working, I'll put it inside a fragment and I'll
just paste in.
In fact, I didn't need the fragment there for some reason.
I thought that was two different elements.
So I'll just paste in the section that we have and great.
Okay.
So I'm going to take out this aside.
I'm not even going to use that.
But we do need something to use for the accepted files here.
This is what we store the file that's dropped in into our browser.
So just above the return statement I'm going to create an on drop function.
And for this one we're going to use another hook that we haven't looked at yet.
It's the equivalent of usememo but for functions.
And this is called use callback.
So I'm going to use this particular hook.
And we're going to pass in as a parameter a callback function.
So we'll pass in accepted files, add the arrow and then open curly brackets.
And I'm just going to, for the time being console log the accepted files.
And then in the dependencies for the use callback.
This operates just like a Usememo or a Useeffect.
We need to give this a dependency array, and the idea is that this function, this Ondrop function
is Memoized.
So if our component gets rerendered, then the function doesn't get recreated.
And I don't need any dependencies inside here.
And I'm getting a warning about accepted files having a implicit any type.
Okay, so I'll ignore the TypeScript warnings for now, but I'll give it an explicit any type for the
time being, although I'm sure we can get away with just using an actual type of file here.
And yeah, sure, that's a bit more like it, so I won't use the any type.
I'll use file array because we can drop multiple files into our react dropzone.
And then we need to use our on drop function.
But that needs to be passed to the use dropzone.
So I'm just going to cut this and move it below the on drop function.
Because we're going to pass that in as an option in curly brackets.
We're going to use our on drop function, which is named exactly the same as the property that dropzone
is looking for.
So we don't need to say on drop colon on drop.
We can just shorthand that.
And we don't need the accepted files from here either.
So I can remove that and let's see how we're getting on.
This should give us enough to get started with.
So I'll remove the unused import there.
We've got our use controller props.
We're not hooking this up to our form just yet.
We will do soon.
So I'll ignore those warnings as well.
And let's head over to our product form, and we will replace our app text inputs with the app dropzone.
And we'll take a look.
And I'm missing some required properties here.
This needs the name property.
So I'm going to give it the name.
And I'm going to set it equal to file because that's what our create product DTO is expecting.
And do I have any warnings inside the product form itself?
I do not.
So just the warnings in the app dropzone.
But I know what they are and there's nothing else inside here causing a problem.
So we should be able to go and have a quick look and see our progress here.
And if I go to the create then I've got a problem reading control of course, because we also need to
pass the control to the app dropzone as well.
Even though we're not using the form functionality yet, we do need to pass the control and I'll set
that to control.
Okay.
So let's give that another go.
And I'll click on the create button.
And now we've got our drop zone.
It's not styled very well at the moment.
And we will fix that soon.
But I'm going to take a file.
In fact let's open up the console first of all and what we would expect to see of course inside here
is after we have dropped a file in, we would expect to see that file present in our Chrome DevTools.
So let's just drag an image across here.
We're not going to see any user interface niceness yet, but I'm just going to drop it onto the text.
And then we can see that we have the file available inside here.
And we've got all of the file details.
That's what we're looking for right now.
Let's just adjust the styling so it looks a bit more presentable.
And I'll head back to the app drop zone and we can get another property from use.
Drop zone called is drag active.
So we know if somebody's hovering over the drag inputs or the drop zone, and let's give it some styling.
So I'm going to create an object for this called DS styles equals and open curly brackets.
And inside here we're going to create some styles.
So I'll use Display Flex I'll have a border.
And this is going to be dashed 3PX.
And we'll use hash e.
We'll have a border color.
And we'll set that also to hash e.
And that needs to be in quotes hash e.
We'll have a border radius and I'll make it five pixels.
We'll have padding top.
And I'll set that to 30 pixels.
Will align items and specify center, and we'll give it a height of 200.
And a width of 500.
And we'll create another object and say const ds active equals.
And we'll just update the border color here.
So it changes when they're hovering over it with a file.
And set that to green.
And let's adjust what's going on in here.
I don't actually want any of that code at all.
And inside here we'll have a div and we'll use the in curly brackets dot dot dot get root props.
This is what we get from the drop zone for its properties that it needs.
Then we'll have a form control.
And we'll give it some style.
And we'll check to see if the drag is active.
If it is, then we'll open curly brackets and say dot dot dot ds styles.
And then if the drag is active we'll also apply the DS active style.
So that's going to override the border color.
Otherwise it's just going to be DS styles.
And we'll also give this the error property as well.
So let's just move the style down inside there.
Move this angle bracket down and below the style.
We'll just specify the error property.
And we'll check the exclamation mark exclamation mark and the field state dot error.
And inside here we need an input which doesn't need any types or anything because we get the input props
from drop zone.
So inside curly brackets we'll say dot dot dot gets input props.
And then below the input we'll use upload File, which is an icon from Mui material, and give it a
self-closing tag.
And we'll give it the SE property.
And we're going to set the font size to be 100 pixels.
Below this we'll use typography, and we'll give it a variant of H4 and just say drop image here.
And we'll use the form helper text again.
So if there is an error we can display that.
And we'll use filled states dot error dot message.
And that should make it look a bit more presentable.
We've still got the field not being used yet.
We need to add a bit of functionality into our ondrop, but we'll just see how we're doing right now
with our drop zone.
So I'll go back to the browser, I'll click create and we can see that we've got our big Drop image
here.
I think I'd like the border to be colored more like the other borders, but I'll leave it for now and
we'll come back and adjust that soon.
And let's just open up the console.
Just make sure we've still got the same functionality.
We haven't really changed anything.
In fact, I need to refresh that.
Loads of warnings in there and I'll click on create.
And let's just drop an image inside.
Here we can see the border.
In fact I've got the whole thing taken up here.
So I need to adjust the grid size because the grid is 12 along here.
But that's going to change once we put something on the right hand side.
And we shrink this to a grid size of six, but I can drop the image in.
And then we see the file again as we did before.
So progress is being made.
We've now got the ability to drop files in here.
I'd like to see a preview on the right hand side before they do, upload or submit the form, and we'll
add the functionality for this next.