updated edit category functionality and created menu item page for admin panel
This commit is contained in:
parent
cc709d5bd5
commit
ee1869b0b8
6 changed files with 149 additions and 7 deletions
21
donutshop_ecommerce/src/app/api/categories/route.js
Normal file
21
donutshop_ecommerce/src/app/api/categories/route.js
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
import { Category } from "../models/Category";
|
||||||
|
|
||||||
|
export async function POST(req){
|
||||||
|
const {name} = await req.json();
|
||||||
|
const categoryDoc = await Category.create({name})
|
||||||
|
|
||||||
|
return Response.json(categoryDoc);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function PUT(req){
|
||||||
|
const {_id, name} = await req.json();
|
||||||
|
await Category.updateOne({_id}, {name});
|
||||||
|
|
||||||
|
return Response.json(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function GET(req){
|
||||||
|
return Response.json(
|
||||||
|
await Category.find()
|
||||||
|
)
|
||||||
|
}
|
11
donutshop_ecommerce/src/app/api/models/Category.js
Normal file
11
donutshop_ecommerce/src/app/api/models/Category.js
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
import { Schema, model, models } from "mongoose";
|
||||||
|
|
||||||
|
const CategorySchema = new Schema({
|
||||||
|
name: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
|
||||||
|
}, {timestamps: true})
|
||||||
|
|
||||||
|
export const Category = models?.Category || model('Category', CategorySchema);
|
|
@ -1,24 +1,96 @@
|
||||||
"use client"
|
"use client"
|
||||||
import React from 'react'
|
import React, { useEffect, useState } from 'react'
|
||||||
import UserTab from '../../components/layout/UserTab'
|
import UserTab from '../../components/layout/UserTab'
|
||||||
import useProfile from '../../components/UseProfile'
|
import useProfile from '../../components/UseProfile'
|
||||||
|
import toast from 'react-hot-toast'
|
||||||
|
|
||||||
const CategoriesPage = () => {
|
const CategoriesPage = () => {
|
||||||
const {loading:profileLoading, data:profileData} = useProfile();
|
const {loading:profileLoading, data:profileData} = useProfile();
|
||||||
|
const [categoryName, setCategoryName] = useState('');
|
||||||
|
const [categories, setCategories] = useState([]);
|
||||||
|
const [editCategory, setEditCategory] = useState(null);
|
||||||
|
|
||||||
|
|
||||||
|
//create new category && toast promis functionlity
|
||||||
|
useEffect(() => {
|
||||||
|
fetchCategories();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
function fetchCategories(){
|
||||||
|
fetch('api/categories').then(res => {
|
||||||
|
res.json().then(categories => {
|
||||||
|
setCategories(categories)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async function handleCategorySubmit(ev){
|
||||||
|
ev.preventDefault();
|
||||||
|
const creatCategoryPromise = new Promise(async (resolve, reject) => {
|
||||||
|
const data = {name:categoryName}; //edit category functionality
|
||||||
|
if(editCategory){
|
||||||
|
data._id = editCategory._id
|
||||||
|
}
|
||||||
|
const response = await fetch('api/categories', {
|
||||||
|
method: editCategory ? 'PUT' : 'POST',
|
||||||
|
headers: {'Content-Type': 'application/json'},
|
||||||
|
body: JSON.stringify(data),
|
||||||
|
});
|
||||||
|
setCategoryName('');
|
||||||
|
fetchCategories();
|
||||||
|
setEditCategory(null)
|
||||||
|
if(response.ok)
|
||||||
|
resolve();
|
||||||
|
else
|
||||||
|
reject();
|
||||||
|
});
|
||||||
|
await toast.promise(creatCategoryPromise, {
|
||||||
|
loading: editCategory ? 'Updating...' : 'Creating...',
|
||||||
|
success: editCategory ? 'A category is updated' : 'A new category is created',
|
||||||
|
error: editCategory ? 'Fail to update category' : 'Fail to create a new category',
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//loading & admin
|
||||||
if(profileLoading){
|
if(profileLoading){
|
||||||
return <p className='flex justify-center items-center'>Loading...</p>
|
return <p className='flex justify-center items-center'>Loading...</p>
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!profileData.admin){
|
if(!profileData.admin){
|
||||||
return <p className='flex justify-center items-center'>Please login as an admin</p>
|
return <p className='flex justify-center items-center'>Please login as an admin</p>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='px-5 mb-10 max-w-lg mx-auto'>
|
<div className='px-5 mb-10 max-w-md mx-auto'>
|
||||||
<UserTab isAdmin={true}/>
|
<UserTab isAdmin={true}/>
|
||||||
This is a category page
|
<form className='mt-10' onSubmit={handleCategorySubmit}>
|
||||||
|
<div className='flex flex-col'>
|
||||||
|
<label className='-mb-1 text-gray-700 font-semibold text-sm flex'>
|
||||||
|
{editCategory ? 'Update category' : 'New category name'}
|
||||||
|
{editCategory && (
|
||||||
|
<div className='font-notmal'>: {editCategory.name}</div>
|
||||||
|
)}
|
||||||
|
</label>
|
||||||
|
<div className='flex gap-2 items-center'>
|
||||||
|
<div className='grow'>
|
||||||
|
<input type='text' value={categoryName} onChange={ev => setCategoryName(ev.target.value)} placeholder='Enter category name'/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<button type='submit' className='bg-pink-500 text-white p-2 rounded-md hover:opacity-80 duration-300'>{editCategory ? 'Update' : 'Create'}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
<div className='mt-5'>
|
||||||
|
<label className='-mb-1 text-gray-700 font-semibold text-sm'>Edit category</label>
|
||||||
|
{categories?.length > 0 && categories.map(c => (
|
||||||
|
<button onClick={() => {setEditCategory(c); setCategoryName(c.name)}} className='w-full flex gap-2 bg-slate-100 px-4 py-2 cursor-pointer rounded-md mb-2'>
|
||||||
|
<p>{c.name}</p>
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ input[type="email"], input[type="password"], input[type="text"], input[type="tel
|
||||||
}
|
}
|
||||||
/*===== profile =====*/
|
/*===== profile =====*/
|
||||||
div.tabs > *{
|
div.tabs > *{
|
||||||
@apply py-2 px-4 bg-gray-200 text-gray-700 rounded-md
|
@apply py-1 px-2 sm:py-2 sm:px-4 bg-gray-200 text-gray-700 rounded-md
|
||||||
}
|
}
|
||||||
div.tabs > *.active{
|
div.tabs > *.active{
|
||||||
@apply bg-pink-500 text-white font-semibold
|
@apply bg-pink-500 text-white font-semibold
|
||||||
|
|
39
donutshop_ecommerce/src/app/menu-items/page.js
Normal file
39
donutshop_ecommerce/src/app/menu-items/page.js
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
"use client"
|
||||||
|
import React from 'react'
|
||||||
|
import UserTab from '../../components/layout/UserTab'
|
||||||
|
import useProfile from '../../components/UseProfile'
|
||||||
|
|
||||||
|
const MenuItemsPage = () => {
|
||||||
|
const {loading, data} = useProfile();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
if(loading){
|
||||||
|
return <p className='flex justify-center items-center'>Loading...</p>
|
||||||
|
}
|
||||||
|
if(!data.admin){
|
||||||
|
return <p className='flex justify-center items-center'>Please login as an admin</p>
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className='px-5 mb-10 max-w-md mx-auto'>
|
||||||
|
<UserTab isAdmin={true}/>
|
||||||
|
<form className='mt-10'>
|
||||||
|
<div className='flex flex-col'>
|
||||||
|
<label className='-mb-1 text-gray-700 font-semibold text-sm flex'>Items name</label>
|
||||||
|
<div className='flex gap-2 items-center'>
|
||||||
|
<div className='grow'>
|
||||||
|
<input type='text' placeholder='Enter items name'/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<button type='submit' className='bg-pink-500 text-white p-2 rounded-md hover:opacity-80 duration-300'>Create</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default MenuItemsPage
|
|
@ -88,7 +88,6 @@ const ProfilePage = () => {
|
||||||
success: 'An image is uploaded',
|
success: 'An image is uploaded',
|
||||||
error: 'Fail to upload image!',
|
error: 'Fail to upload image!',
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue