drag drop sort swap
This commit is contained in:
+45
-13
@@ -8,9 +8,12 @@ import './styles/app.css';
|
|||||||
function App() {
|
function App() {
|
||||||
|
|
||||||
const [data, setData] = useState([]);
|
const [data, setData] = useState([]);
|
||||||
|
|
||||||
const [boxID, setBoxID] = useState(undefined);
|
const [boxID, setBoxID] = useState(undefined);
|
||||||
const [boxName, setBoxName] = useState('');
|
const [boxName, setBoxName] = useState('');
|
||||||
const [boxDescription, setBoxDescription] = useState('');
|
const [boxDescription, setBoxDescription] = useState('');
|
||||||
|
const [boxSort, setBoxSort] = useState(0);
|
||||||
|
|
||||||
const [showModalBox, setShowModalBox] = useState(false);
|
const [showModalBox, setShowModalBox] = useState(false);
|
||||||
const [showModalItem, setShowModalItem] = useState(false);
|
const [showModalItem, setShowModalItem] = useState(false);
|
||||||
|
|
||||||
@@ -24,14 +27,7 @@ function App() {
|
|||||||
const [filter, setFilter] = useState('');
|
const [filter, setFilter] = useState('');
|
||||||
const [filteredData, setFilteredData] = useState([]);
|
const [filteredData, setFilteredData] = useState([]);
|
||||||
|
|
||||||
|
const [dragSource, setDragSource] = useState({});
|
||||||
|
|
||||||
const handleName = (e) => {
|
|
||||||
setItemName(e.target.value)
|
|
||||||
}
|
|
||||||
const handleDescription = (e) => {
|
|
||||||
setItemDescription(e.target.value)
|
|
||||||
}
|
|
||||||
|
|
||||||
//fetch all box data
|
//fetch all box data
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -98,6 +94,15 @@ function App() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const sortBox = async (target, source) => {
|
||||||
|
try {
|
||||||
|
const response = await axios.put(`${api.baseApiUrl}/${source._id}/sort`,target);
|
||||||
|
setData(response.data);
|
||||||
|
}
|
||||||
|
catch (error) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
const handleNameBox = (e) => {
|
const handleNameBox = (e) => {
|
||||||
setBoxName(e.target.value);
|
setBoxName(e.target.value);
|
||||||
}
|
}
|
||||||
@@ -146,13 +151,32 @@ function App() {
|
|||||||
setBoxID(undefined);
|
setBoxID(undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleDragStartBox = (dragSource, event) => {
|
||||||
|
setDragSource(dragSource);
|
||||||
|
event.dataTransfer.dropEffect = "move";
|
||||||
|
}
|
||||||
|
const handleDragOverBox = (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
event.dataTransfer.dropEffect = "move";
|
||||||
|
}
|
||||||
|
const handleDropBox = async (dragTarget, event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
if(dragTarget._id !== dragSource._id) {
|
||||||
|
const target = dragTarget;
|
||||||
|
const source = dragSource;
|
||||||
|
await sortBox(target, source);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
const boxHandler = {
|
const boxHandler = {
|
||||||
handleSubmit: handleSubmitBox,
|
handleSubmit: handleSubmitBox,
|
||||||
handleRemove: handleRemoveBox,
|
handleRemove: handleRemoveBox,
|
||||||
handleName: handleNameBox,
|
handleName: handleNameBox,
|
||||||
handleDescription: handleBoxDescription,
|
handleDescription: handleBoxDescription,
|
||||||
handleEdit: handleEditBox
|
handleEdit: handleEditBox,
|
||||||
|
handleDragStart: handleDragStartBox,
|
||||||
|
handleDragOver: handleDragOverBox,
|
||||||
|
handleDrop: handleDropBox
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleModalCloseBox = () => {
|
const handleModalCloseBox = () => {
|
||||||
@@ -245,11 +269,20 @@ function App() {
|
|||||||
setItemDescription('');
|
setItemDescription('');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const handleNameItem = (e) => {
|
||||||
|
setItemName(e.target.value)
|
||||||
|
}
|
||||||
|
const handleDescriptionItem = (e) => {
|
||||||
|
setItemDescription(e.target.value)
|
||||||
|
}
|
||||||
const itemHandler = {
|
const itemHandler = {
|
||||||
handleSubmit: handleSubmitItem,
|
handleSubmit: handleSubmitItem,
|
||||||
handleRemove: handleRemoveItem,
|
handleRemove: handleRemoveItem,
|
||||||
handleAdd: handleAddItem,
|
handleAdd: handleAddItem,
|
||||||
handleEdit: handleEditItem,
|
handleEdit: handleEditItem,
|
||||||
|
handleName: handleNameItem,
|
||||||
|
handleDescription: handleDescriptionItem,
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleFilterChange = (event) => {
|
const handleFilterChange = (event) => {
|
||||||
@@ -277,10 +310,10 @@ function App() {
|
|||||||
<fieldset>
|
<fieldset>
|
||||||
<input id="id" name="id" value={itemID} readOnly hidden></input>
|
<input id="id" name="id" value={itemID} readOnly hidden></input>
|
||||||
<label htmlFor="item-name">name
|
<label htmlFor="item-name">name
|
||||||
<input autoFocus onChange={handleName} value={itemName} id="item-name" name="name" type="text"></input>
|
<input autoFocus onChange={itemHandler.handleName} value={itemName} id="item-name" name="name" type="text"></input>
|
||||||
</label>
|
</label>
|
||||||
<label htmlFor="item-description">description
|
<label htmlFor="item-description">description
|
||||||
<input onChange={handleDescription} value={itemDescription} id="item-description" name="description" type="text"></input>
|
<input onChange={itemHandler.handleDescription} value={itemDescription} id="item-description" name="description" type="text"></input>
|
||||||
</label>
|
</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
<button type="submit">submit</button>
|
<button type="submit">submit</button>
|
||||||
@@ -289,7 +322,6 @@ function App() {
|
|||||||
<>
|
<>
|
||||||
{<Modal show={showModalItem} edit={editItemBool} content={itemForm} handleClose={handleModalCloseItem} />}
|
{<Modal show={showModalItem} edit={editItemBool} content={itemForm} handleClose={handleModalCloseItem} />}
|
||||||
{<Modal show={showModalBox} edit={editBoxBool} content={boxForm} handleClose={handleModalCloseBox} />}
|
{<Modal show={showModalBox} edit={editBoxBool} content={boxForm} handleClose={handleModalCloseBox} />}
|
||||||
|
|
||||||
<label htmlFor="box-filter">filter:</label>
|
<label htmlFor="box-filter">filter:</label>
|
||||||
<input type="search" id="box-filter" name="filter" value={filter} onChange={handleFilterChange} />
|
<input type="search" id="box-filter" name="filter" value={filter} onChange={handleFilterChange} />
|
||||||
<ul className="list-box">
|
<ul className="list-box">
|
||||||
|
|||||||
+9
-4
@@ -4,11 +4,14 @@ import Item from './item';
|
|||||||
const Box = ({ boxData, boxHandler, itemHandler }) => {
|
const Box = ({ boxData, boxHandler, itemHandler }) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<li className="box">
|
<li className="box" draggable='true'
|
||||||
|
onDragStart={(event) => boxHandler.handleDragStart(boxData, event)}
|
||||||
|
onDragOver={boxHandler.handleDragOver}
|
||||||
|
onDrop={(event) => boxHandler.handleDrop(boxData, event)}>
|
||||||
|
<span>{boxData.sort}</span>
|
||||||
<h2 className="box-title">{boxData.name}</h2>
|
<h2 className="box-title">{boxData.name}</h2>
|
||||||
<div className="box-subtitle">
|
<div className="box-subtitle">
|
||||||
<h3>{boxData.description}</h3>
|
<h3>{boxData.description}</h3>
|
||||||
<button onClick={() => itemHandler.handleAdd(boxData._id)}>add item</button>
|
|
||||||
</div>
|
</div>
|
||||||
<ul className="list-box-item">
|
<ul className="list-box-item">
|
||||||
{boxData.item.map(((item, index) => {
|
{boxData.item.map(((item, index) => {
|
||||||
@@ -19,8 +22,10 @@ const Box = ({ boxData, boxHandler, itemHandler }) => {
|
|||||||
itemHandler={itemHandler} />
|
itemHandler={itemHandler} />
|
||||||
}))}
|
}))}
|
||||||
</ul>
|
</ul>
|
||||||
<button className="edit-box" onClick={() => boxHandler.handleEdit(boxData._id)}>edit</button>
|
<button className="edit-box box-function" onClick={() => boxHandler.handleEdit(boxData._id)}>edit</button>
|
||||||
<button className="remove-box" onClick={() => boxHandler.handleRemove(boxData._id)}>remove</button>
|
<button className="remove-box box-function" onClick={() => boxHandler.handleRemove(boxData._id)}>remove</button>
|
||||||
|
<button className="add-item item-function" onClick={() => itemHandler.handleAdd(boxData._id)}>add item</button>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|||||||
+4
-2
@@ -3,8 +3,10 @@ import React from 'react';
|
|||||||
const Item = ({ data, itemHandler, boxID }) => {
|
const Item = ({ data, itemHandler, boxID }) => {
|
||||||
return (<li className="item">
|
return (<li className="item">
|
||||||
<p className="item-name">{data.name}</p>
|
<p className="item-name">{data.name}</p>
|
||||||
<button onClick={() => itemHandler.handleEdit(boxID, data._id)}>edit</button>
|
<div className="item-menu">
|
||||||
<button onClick={() => itemHandler.handleRemove(boxID, data._id)}>remove</button>
|
<button className="item-function" onClick={() => itemHandler.handleEdit(boxID, data._id)}>edit</button>
|
||||||
|
<button className="item-function" onClick={() => itemHandler.handleRemove(boxID, data._id)}>remove</button>
|
||||||
|
</div>
|
||||||
</li>);
|
</li>);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -25,26 +25,31 @@ h1, h2, h3, h4 {
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
button {
|
button {
|
||||||
margin: 0.2em;
|
|
||||||
border: none;
|
border: none;
|
||||||
padding: 0.4em;
|
padding: 0.4em;
|
||||||
}
|
}
|
||||||
button.remove-box, button.edit-box {
|
button.box-function, button.item-function {
|
||||||
width: 100%;
|
font-size: 1em;
|
||||||
}
|
}
|
||||||
button:hover {
|
button:hover {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
.box {
|
||||||
|
box-sizing: content-box;
|
||||||
|
outline: 1px solid black;
|
||||||
|
box-shadow: 4px 4px black;
|
||||||
|
}
|
||||||
.box-subtitle {
|
.box-subtitle {
|
||||||
|
margin: 0;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 1fr 1fr;
|
grid-template-columns: 1fr 1fr;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
text-transform: lowercase;
|
text-transform: lowercase;
|
||||||
}
|
}
|
||||||
ul.list-box {
|
ul.list-box {
|
||||||
|
padding: 10px;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(5, 1fr);
|
grid-template-columns: repeat(5, 1fr);
|
||||||
padding: 0 0 0 1em;
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
gap: 1em;
|
gap: 1em;
|
||||||
}
|
}
|
||||||
@@ -55,3 +60,7 @@ ul.list-box-item {
|
|||||||
p {
|
p {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
.drop-zone {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
+14
-5
@@ -22,17 +22,16 @@ db.once('open', function() {
|
|||||||
/*------------MODELS------------*/
|
/*------------MODELS------------*/
|
||||||
//create schema
|
//create schema
|
||||||
var itemSchema = new mongoose.Schema({
|
var itemSchema = new mongoose.Schema({
|
||||||
id: String,
|
|
||||||
name: String,
|
name: String,
|
||||||
description: String,
|
description: String,
|
||||||
quantity: Number
|
quantity: Number
|
||||||
});
|
});
|
||||||
|
|
||||||
var boxSchema = new mongoose.Schema({
|
var boxSchema = new mongoose.Schema({
|
||||||
id: String,
|
|
||||||
name: String,
|
name: String,
|
||||||
description: String,
|
description: String,
|
||||||
item: [itemSchema],
|
item: [itemSchema],
|
||||||
|
sort: Number,
|
||||||
});
|
});
|
||||||
|
|
||||||
//compile schema into model
|
//compile schema into model
|
||||||
@@ -51,7 +50,9 @@ app.get('/box', async (request, response) => {
|
|||||||
|
|
||||||
// create box
|
// create box
|
||||||
app.post('/box', async (request, response) => {
|
app.post('/box', async (request, response) => {
|
||||||
await Box.create(request.body);
|
const numBoxes = await Box.countDocuments({});
|
||||||
|
const query = Object.assign({sort: numBoxes}, request.body);
|
||||||
|
await Box.create(query);
|
||||||
const updatedBoxes = await getAllBoxes();
|
const updatedBoxes = await getAllBoxes();
|
||||||
response.send(updatedBoxes);
|
response.send(updatedBoxes);
|
||||||
});
|
});
|
||||||
@@ -68,7 +69,15 @@ app.delete('/box/:id', async (request, response) => {
|
|||||||
const updatedBoxes = await getAllBoxes();
|
const updatedBoxes = await getAllBoxes();
|
||||||
response.send(updatedBoxes);
|
response.send(updatedBoxes);
|
||||||
});
|
});
|
||||||
|
//change box sort
|
||||||
|
app.put('/box/:id/sort', async (request, response) => {
|
||||||
|
const source = await getBox(request.params.id);
|
||||||
|
const target = request.body;
|
||||||
|
await Box.updateOne({ _id: source._id }, { $set: { sort: target.sort } });
|
||||||
|
await Box.updateOne({ _id: target._id }, { $set: { sort: source.sort } });
|
||||||
|
const updatedBoxes = await getAllBoxes();
|
||||||
|
response.send(updatedBoxes);
|
||||||
|
})
|
||||||
//create item
|
//create item
|
||||||
app.post('/box/:id/item', async (request, response) => {
|
app.post('/box/:id/item', async (request, response) => {
|
||||||
const id = request.params.id;
|
const id = request.params.id;
|
||||||
@@ -106,7 +115,7 @@ app.delete('/box/:boxId/item/:itemId', async (request, response) => {
|
|||||||
|
|
||||||
const getAllBoxes = async (queryParameters) => {
|
const getAllBoxes = async (queryParameters) => {
|
||||||
queryParameters = queryParameters ?? {};
|
queryParameters = queryParameters ?? {};
|
||||||
const data = await Box.find(queryParameters);
|
const data = await Box.find(queryParameters).sort({sort: 1});
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user