-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feature/add CRUD functions for admin merch panel
- Loading branch information
Showing
7 changed files
with
3,094 additions
and
156 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
import React, { Fragment, useState } from "react"; | ||
import { getErrorMessage } from "@/utils/utilFunctions"; | ||
import {Modal, ModalContent, ModalHeader, ModalBody, ModalFooter, Button, useDisclosure} from "@nextui-org/react"; | ||
|
||
|
||
const EditMerch = ({ merch }: any) => { | ||
|
||
const [name, setName] = useState<string>(merch.name); | ||
const [description, setDescription] = useState<string>(merch.description); | ||
const [image, setImage] = useState<File | null>(merch.image); | ||
const [price, setPrice] = useState<number>(merch.price); | ||
|
||
//edit description function | ||
const updateDescription = async (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => { | ||
e.preventDefault(); // allows to run code before refreshing | ||
try { | ||
const body = { description }; | ||
const response = await fetch( | ||
`http://localhost:3001/admin/admin-merch/${merch.id}`, | ||
{ | ||
method: "PUT", | ||
headers: { "Content-Type": "application/json" }, | ||
body: JSON.stringify(body) | ||
} | ||
); | ||
|
||
window.location.href = "/admin/admin-merch"; | ||
} catch (err) { | ||
console.error(getErrorMessage(err)); | ||
} | ||
} | ||
|
||
return ( | ||
<Fragment> | ||
<button type="button" className="h-10 w-20 bg-yellow-400 border rounded-md hover:bg-blue-800" data-toggle="modal" data-target={`#id${merch.id}`}> | ||
Edit | ||
</button> | ||
|
||
<div | ||
className="modal" | ||
id={`id${merch.id}`} | ||
onClick={() => setDescription(merch.description)} | ||
> | ||
<div className="modal-dialog"> | ||
<div className="modal-content"> | ||
|
||
<div className="modal-header"> | ||
<h4 className="modal-title">Edit Merch</h4> | ||
<button | ||
type="button" | ||
className="close" | ||
data-dismiss="modal" | ||
onClick={() => setDescription(merch.description)} | ||
> | ||
× | ||
</button> | ||
</div> | ||
|
||
<div className="modal-body"> | ||
<input | ||
type="text" | ||
className="form-control" | ||
value={description} | ||
onChange={e => setDescription(e.target.value)} | ||
/> | ||
</div> | ||
|
||
<div className="modal-footer"> | ||
<button | ||
type="button" | ||
className="btn btn-warning" | ||
data-dismiss="modal" | ||
onClick={e => updateDescription(e)} | ||
> | ||
Edit | ||
</button> | ||
<button | ||
type="button" | ||
className="btn btn-danger" | ||
data-dismiss="modal" | ||
onClick={() => setDescription(merch.description)} | ||
> | ||
Close | ||
</button> | ||
</div> | ||
|
||
</div> | ||
</div> | ||
</div> | ||
</Fragment> | ||
); | ||
}; | ||
|
||
export default EditMerch; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import React, { Fragment, useState, ChangeEvent } from "react"; | ||
import { getErrorMessage } from "../utils/utilFunctions"; | ||
|
||
|
||
const InputMerch = () => { | ||
const [name, setName] = useState(""); | ||
const [description, setDescription] = useState(""); | ||
const [image, setImage] = useState<File | null>(null); | ||
const [price, setPrice] = useState<number | string>(""); | ||
|
||
const onSubmitForm = async (event: { preventDefault: () => void; }) => { | ||
event.preventDefault(); | ||
try { | ||
const body = { name, description, image, price }; | ||
const response = await fetch("http://localhost:3001/admin/admin-merch", { | ||
method: "POST", | ||
headers: { "Content-type": "application/json" }, | ||
body: JSON.stringify(body) | ||
}); | ||
|
||
window.location.href = "/admin/admin-merch"; | ||
} catch (err) { | ||
console.error(getErrorMessage(err)); | ||
} | ||
} | ||
|
||
const handleImageChange = (e: ChangeEvent<HTMLInputElement>) => { | ||
const file = e.target.files?.[0]; | ||
setImage(file || null); | ||
}; | ||
|
||
return ( | ||
<Fragment> | ||
<h1 className="text-center mt-5">PERN Merch List</h1> | ||
<form className="d-flex mt-5" onSubmit={ onSubmitForm }> | ||
<div className="my-6"> | ||
<h1 className="text-black text-3xl underline underline-offset-4"> | ||
Create GDSC merch | ||
</h1> | ||
</div> | ||
<div className="flex flex-col space-y-8"> | ||
<div> | ||
<p className="text-black text-lg font-semibold mb-1">Merch Name</p> | ||
<input | ||
type="text" | ||
className="text-black h-8 w-64 border border-stone-900" | ||
placeholder="Name" | ||
value={name} | ||
onChange={event => setName(event.target.value)} | ||
/> | ||
</div> | ||
<div> | ||
<p className="text-black text-lg font-semibold mb-1"> | ||
Merch Description | ||
</p> | ||
<textarea | ||
typeof="text" | ||
className="text-black h-24 w-1/2 border border-stone-900" | ||
placeholder="Description" | ||
value={description} | ||
onChange={event => setDescription(event.target.value)} | ||
/> | ||
</div> | ||
<div> | ||
<p className="text-black text-lg font-semibold mb-1">Merch Photo</p> | ||
<input | ||
type="file" | ||
className="text-black" | ||
accept="image/png, image/jpeg" | ||
// onChange={handleImageChange} | ||
/> | ||
{/* {image && <img src={URL.createObjectURL(image)} alt="Uploaded" />} */} | ||
</div> | ||
<div> | ||
<p className="text-black text-lg font-semibold mb-1">Merch Price</p> | ||
<input | ||
type="number" | ||
className="text-black h-8 w-64 border border-stone-900" | ||
placeholder="Price" | ||
value={price} | ||
onChange={event => setPrice(Number(event.target.value))} | ||
/> | ||
</div> | ||
<div> | ||
<button className="h-10 w-40 bg-blue-600 border rounded-md hover:bg-blue-800"> | ||
Add Merch | ||
</button> | ||
</div> | ||
</div> | ||
</form> | ||
</Fragment> | ||
); | ||
}; | ||
|
||
export default InputMerch; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
import React, { Fragment, useEffect, useState } from "react"; | ||
import { getErrorMessage } from "../utils/utilFunctions"; | ||
import EditMerch from "./EditMerch"; | ||
|
||
type Merch = { | ||
id: number; | ||
name: string; | ||
description: string; | ||
image: File | null; | ||
price: number; | ||
}; | ||
|
||
const ListMerch = () => { | ||
const [merches, setMerches] = useState<Merch[]>([]); | ||
|
||
//delete merch function | ||
const deleteMerch = async (id: number) => { | ||
try { | ||
const deleteMerch = await fetch(`http://localhost:3001/admin/admin-merch/${id}`, { | ||
method: "DELETE" | ||
}); | ||
|
||
setMerches(merches.filter(merch => merch.id !== id)); | ||
} catch (err) { | ||
console.error(getErrorMessage(err)); | ||
} | ||
} | ||
|
||
//get merch function | ||
const getMerches = async () => { | ||
try { | ||
const response = await fetch("http://localhost:3001/admin/admin-merch"); | ||
const jsonData = await response.json(); | ||
|
||
setMerches(jsonData); | ||
} catch (err) { | ||
console.error(getErrorMessage(err)); | ||
} | ||
} | ||
|
||
useEffect(() => { | ||
getMerches(); | ||
}, [] /* bracket ensures useEffect does not repeatedly request multiple times */); | ||
|
||
return ( | ||
<Fragment> | ||
<table className="table-auto mt-12 text-center text-black"> | ||
<thead> | ||
<tr> | ||
<th className="px-4 py-2">Description</th> | ||
<th className="px-4 py-2">Edit</th> | ||
<th className="px-4 py-2">Delete</th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
{/* | ||
<tr> | ||
<td>John</td> | ||
<td>Doe</td> | ||
<td>[email protected]</td> | ||
</tr> | ||
*/} | ||
{merches.map(merch => ( | ||
<tr key={merch.id}> | ||
<td className="border px-4 py-2">{merch.name}</td> | ||
<td className="border px-4 py-2">{merch.description}</td> | ||
{/* <td className="border px-4 py-2">{merch.image}</td> */} | ||
<td className="border px-4 py-2">P {merch.price}</td> | ||
<td> | ||
<EditMerch merch={merch} /> | ||
</td> | ||
<td> | ||
<button | ||
className="h-10 w-20 bg-red-600 border rounded-md hover:bg-blue-800" | ||
onClick={() => deleteMerch(merch.id)} | ||
> | ||
Delete | ||
</button> | ||
</td> | ||
</tr> | ||
))} | ||
</tbody> | ||
</table> | ||
</Fragment> | ||
); | ||
}; | ||
|
||
export default ListMerch; |
Oops, something went wrong.