update,
This commit is contained in:
163
_tecky/party-planner/backend/private/itemPostPage/itemPost.css
Normal file
163
_tecky/party-planner/backend/private/itemPostPage/itemPost.css
Normal file
@@ -0,0 +1,163 @@
|
||||
.bi-chevron-left {
|
||||
font-size: 30px;
|
||||
position: fixed;
|
||||
top: 90px;
|
||||
left: 40px;
|
||||
color: #444a58;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.category-text {
|
||||
font-size: 20px;
|
||||
font-family: 'Lato', sans-serif;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
/* shopping list */
|
||||
.shopping-list {
|
||||
background-color: #fefde2;
|
||||
height: 700px;
|
||||
border-radius: 20px;
|
||||
margin: 10px 2px 5px 5px;
|
||||
width: 100%;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.shopping-list .item-list {
|
||||
height: 700px;
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.pending-item-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.bi-filter-circle {
|
||||
color: #495871;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.pending-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.check-btn {
|
||||
border: none;
|
||||
border-radius: 20px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.bi-check-circle {
|
||||
color: #495871;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.shorting-btn {
|
||||
border: none;
|
||||
border-radius: 20px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
/* item category */
|
||||
|
||||
.category-text-items {
|
||||
font-size: 20px;
|
||||
font-family: 'Lato', sans-serif;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.category-edit {
|
||||
border-radius: 20px;
|
||||
border: none;
|
||||
background-color: #f29559;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.bi-pencil-square:hover {
|
||||
color: #495871;
|
||||
}
|
||||
|
||||
.item-category {
|
||||
background-color: #fefde2;
|
||||
height: 338px;
|
||||
border-radius: 20px;
|
||||
margin: 15px;
|
||||
width: 100%;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.item-category .item-list {
|
||||
height: 70%;
|
||||
width: 100%;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
/* Modal UI */
|
||||
#editModalTittle {
|
||||
font-size: 30px;
|
||||
font-family: 'Lato', sans-serif;
|
||||
}
|
||||
|
||||
.modal-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
/* modal - table */
|
||||
.border {
|
||||
border: 10px solid #9bafd0;
|
||||
border-radius: 20px;
|
||||
padding: 10px;
|
||||
max-height: 500px;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
tr {
|
||||
font-family: 'Lato', sans-serif;
|
||||
color: #293241;
|
||||
}
|
||||
|
||||
.bi-trash {
|
||||
color: #ee6c4d;
|
||||
}
|
||||
|
||||
.delete-btn {
|
||||
border-radius: 20px;
|
||||
border: none;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
/* modal - footer */
|
||||
.format {
|
||||
justify-content: space-between;
|
||||
font-family: 'Lato', sans-serif;
|
||||
color: #293241;
|
||||
}
|
||||
|
||||
.save-submit {
|
||||
font-size: 18px;
|
||||
color: #293241;
|
||||
font-family: 'Lato', sans-serif;
|
||||
background-color: #f2d492;
|
||||
padding: 4px 14px 4px 14px;
|
||||
border-radius: 20px;
|
||||
margin: 8px;
|
||||
width: 100px;
|
||||
box-sizing: border-box;
|
||||
border: none;
|
||||
outline: solid 3px #f2d492;
|
||||
transition: outline 0.3s linear;
|
||||
margin: 0.5em;
|
||||
}
|
||||
|
||||
.save-submit:hover {
|
||||
outline-width: 5px;
|
||||
}
|
259
_tecky/party-planner/backend/private/itemPostPage/itemPost.html
Normal file
259
_tecky/party-planner/backend/private/itemPostPage/itemPost.html
Normal file
@@ -0,0 +1,259 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<link
|
||||
href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/css/bootstrap.min.css"
|
||||
rel="stylesheet"
|
||||
integrity="sha384-iYQeCzEYFbKjA/T2uDLTpkwGzCiq6soy8tYaI1GyVh/UjpbCx/TYkiZhlZB6+fzT"
|
||||
crossorigin="anonymous"
|
||||
/>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.9.1/font/bootstrap-icons.css" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Lato:wght@300;400&family=Pacifico&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css"
|
||||
integrity="sha512-xh6O/CkQoPOWDdYTDqeRdPCVd1SpvCA9XXcUnZS2FmJNp1coAFzvtCN9BmamE+4aHK8yyUHUSCcJHgXloTyT2A=="
|
||||
crossorigin="anonymous"
|
||||
referrerpolicy="no-referrer"
|
||||
/>
|
||||
<link rel="stylesheet" href="./itemPost.css" />
|
||||
<title>Post Event Items</title>
|
||||
</head>
|
||||
|
||||
<body style="display: none">
|
||||
<div class="navbar-container container">
|
||||
<!-- NAVBAR: to be loaded with js -->
|
||||
</div>
|
||||
|
||||
<div class="container">
|
||||
<a id="back-page"><i class="bi bi-chevron-left"></i></a>
|
||||
<div class="row">
|
||||
<div class="col-xl-4">
|
||||
<div class="shopping-list">
|
||||
<div class="category-text">Shopping list:</div>
|
||||
<div class="item-list border">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="pending-item-header">
|
||||
Pending Items:
|
||||
<div>
|
||||
<button
|
||||
id="shopping-list-shorting"
|
||||
class="shorting-btn"
|
||||
type="button"
|
||||
data-bs-toggle="dropdown"
|
||||
aria-expanded="false"
|
||||
>
|
||||
<i class="bi bi-filter-circle"></i>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item">Food</a></li>
|
||||
<li><a class="dropdown-item">Drink</a></li>
|
||||
<li><a class="dropdown-item">Decoration</a></li>
|
||||
<li><a class="dropdown-item">Other</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="shipping-list-update">
|
||||
<!--loaded with itemPost.js "shopping list JS"-->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- item category -->
|
||||
<div class="col-xl-4">
|
||||
<div class="item-category">
|
||||
<div class="item-category-title">
|
||||
<div class="category-text-items">
|
||||
Food:
|
||||
<button
|
||||
type="button"
|
||||
class="category-edit"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#editModal"
|
||||
itemtype="food"
|
||||
>
|
||||
<i class="bi bi-pencil-square"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-list border">
|
||||
<table id="food-table" class="table">
|
||||
<tbody>
|
||||
<!-- loaded with itemPost.js "category items JS"-->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-category">
|
||||
<div class="category-text-items">
|
||||
Decoration:
|
||||
<button
|
||||
type="button"
|
||||
class="category-edit"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#editModal"
|
||||
itemtype="decoration"
|
||||
>
|
||||
<i class="bi bi-pencil-square"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="item-list border">
|
||||
<table id="decoration-table" class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<!-- loaded with itemPost.js "category items JS" -->
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xl-4">
|
||||
<div class="item-category">
|
||||
<div class="category-text-items">
|
||||
Drink:
|
||||
<button
|
||||
type="button"
|
||||
class="category-edit"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#editModal"
|
||||
itemtype="drink"
|
||||
>
|
||||
<i class="bi bi-pencil-square"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="item-list border">
|
||||
<table id="drink-table" class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<!-- loaded with itemPost.js "category items JS"-->
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item-category">
|
||||
<div class="category-text-items">
|
||||
Others:
|
||||
<button
|
||||
type="button"
|
||||
class="category-edit"
|
||||
data-bs-toggle="modal"
|
||||
data-bs-target="#editModal"
|
||||
itemtype="others"
|
||||
>
|
||||
<i class="bi bi-pencil-square"></i>
|
||||
</button>
|
||||
</div>
|
||||
<div class="item-list border">
|
||||
<table id="other-table" class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<!-- loaded with itemPost.js "category items JS"-->
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- modal UI -->
|
||||
<div class="modal fade" id="editModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<div></div>
|
||||
<h1 class="modal-title fs-5" id="editModalTittle">Edit Item</h1>
|
||||
<div class="exit-modal">
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="border">
|
||||
<table class="table">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th scope="col">Item description</th>
|
||||
<th scope="col">Quantity</th>
|
||||
<th scope="col">Price $</th>
|
||||
<th scope="col"><i class="bi bi-person-fill"></i></th>
|
||||
<th scope="col"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="edit-item-list">
|
||||
<!-- loaded with itemPost.js "category model list JS" -->
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<!-- footer modal -->
|
||||
<div class="modal-footer">
|
||||
<div class="container-fluid">
|
||||
<form id="from-container">
|
||||
<div class="row format">
|
||||
<div class="col-md-5">
|
||||
<label for="add-item" class="form-label">Item name</label>
|
||||
<input type="text" class="form-control" id="add-item" name="item_name" />
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<label for="add-quantity" class="form-label">Quantity</label>
|
||||
<input
|
||||
type="number"
|
||||
class="form-control"
|
||||
id="add-quantity"
|
||||
name="item_quantity"
|
||||
min="1"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<label for="add-price" class="form-label">Price</label>
|
||||
<input
|
||||
type="number"
|
||||
class="form-control"
|
||||
id="add-price"
|
||||
name="item_price"
|
||||
min="0"
|
||||
/>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<label for="add-user" class="form-label">
|
||||
<i class="bi bi-person-fill"></i>
|
||||
PIC
|
||||
</label>
|
||||
<select id="select-participant" class="form-select" name="item_user">
|
||||
<option selected value="">Select</option>
|
||||
<!-- loaded with itemPost.js "modal participants select"-->
|
||||
</select>
|
||||
</div>
|
||||
<button class="save-submit">Add</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script
|
||||
src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/js/bootstrap.bundle.min.js"
|
||||
integrity="sha384-u1OknCvxWvY5kfmNBILK2hRnQC3Pr17a+RTT6rIHI7NnikvbZlHgTPOOmMi466C8"
|
||||
crossorigin="anonymous"
|
||||
></script>
|
||||
<script type="module" src="./itemPost.js"></script>
|
||||
</body>
|
||||
</html>
|
202
_tecky/party-planner/backend/private/itemPostPage/itemPost.js
Normal file
202
_tecky/party-planner/backend/private/itemPostPage/itemPost.js
Normal file
@@ -0,0 +1,202 @@
|
||||
import { addNavbar } from '/functions/addNavbar.js';
|
||||
import { loadName } from '/functions/loadName.js';
|
||||
|
||||
let editingType = null;
|
||||
let itemData = null;
|
||||
let eventID = null;
|
||||
|
||||
window.addEventListener('load', async () => {
|
||||
const query = new URLSearchParams(window.location.search);
|
||||
eventID = query.get('event-id');
|
||||
itemData = await (await fetch(`/items?eventID=${eventID}`)).json();
|
||||
addNavbar();
|
||||
await loadName();
|
||||
fetchItem();
|
||||
fetchParticipant(eventID);
|
||||
fetchPendingItems('food');
|
||||
document.body.style.display = 'block';
|
||||
});
|
||||
|
||||
document.querySelectorAll('.category-edit').forEach((button) => {
|
||||
button.addEventListener('click', function (e) {
|
||||
editingType = button.attributes.itemType.value;
|
||||
fetchEditItem(itemData);
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelector('#from-container').addEventListener('submit', async function (e) {
|
||||
const query = new URLSearchParams(window.location.search);
|
||||
const eventID = query.get('event-id');
|
||||
e.preventDefault();
|
||||
const form = e.target;
|
||||
const typeName = editingType;
|
||||
const itemName = form.item_name.value;
|
||||
const itemQuantity = form.item_quantity.value;
|
||||
const itemPrice = form.item_price.value || null;
|
||||
const user_id = form.item_user.value || null;
|
||||
|
||||
let formObj = {
|
||||
typeName,
|
||||
itemName,
|
||||
itemQuantity,
|
||||
itemPrice,
|
||||
user_id
|
||||
};
|
||||
|
||||
let dataPass = true;
|
||||
|
||||
if (!user_id) {
|
||||
alert('Please select PIC');
|
||||
return;
|
||||
}
|
||||
|
||||
if (dataPass) {
|
||||
const res = await fetch(`/items/eventId/${eventID}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(formObj)
|
||||
});
|
||||
|
||||
const eventsResult = await res.json();
|
||||
if (eventsResult.status === true) {
|
||||
const itemData = await (await fetch(`/items?eventID=${eventID}`)).json();
|
||||
fetchEditItem(itemData);
|
||||
}
|
||||
}
|
||||
form.reset();
|
||||
fetchItem();
|
||||
fetchPendingItems(typeName);
|
||||
});
|
||||
|
||||
// category items JS
|
||||
async function fetchItem() {
|
||||
const res = await (await fetch(`/items?eventID=${eventID}`)).json();
|
||||
if (res.status === true) {
|
||||
const typeName = ['food', 'drink', 'decoration', 'other'];
|
||||
for (const tableName of typeName) {
|
||||
let itemsList = '';
|
||||
for (const items of res.itemObj[tableName]) {
|
||||
itemsList += `
|
||||
<tr>
|
||||
<td>${items.name}</td>
|
||||
</tr>
|
||||
`;
|
||||
}
|
||||
document.querySelector(`#${tableName}-table`).innerHTML = itemsList;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// category model list JS
|
||||
async function fetchEditItem() {
|
||||
const resEditItem = await (await fetch(`/items?eventID=${eventID}`)).json();
|
||||
if (resEditItem.status === true) {
|
||||
let items = '';
|
||||
for (const itemsData of resEditItem.itemObj[editingType]) {
|
||||
items += `
|
||||
<tr id="item-row-${itemsData.id}">
|
||||
<td>${itemsData.name}</td>
|
||||
<td>${itemsData.quantity}</td>
|
||||
<td>${itemsData.price}</td>
|
||||
<td>${itemsData.first_name} ${itemsData.last_name}</td>
|
||||
<td>
|
||||
<button id="item-${itemsData.id}" data-type-name="${itemsData.type_name}"
|
||||
itemDelete="button" class="delete-btn">
|
||||
<i class="bi bi-trash"></i>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
}
|
||||
document.querySelector(`#edit-item-list`).innerHTML = items;
|
||||
addDeleteEventListener();
|
||||
}
|
||||
}
|
||||
|
||||
function addDeleteEventListener() {
|
||||
document.querySelectorAll('.delete-btn').forEach((button) => {
|
||||
button.addEventListener('click', async function (e) {
|
||||
const itemID = e.currentTarget.id.slice(5);
|
||||
const typeName = e.currentTarget.getAttribute('data-type-name');
|
||||
const res = await fetch(`/items/${itemID}`, {
|
||||
method: 'DELETE'
|
||||
});
|
||||
if ((await res.json()).status === true) {
|
||||
const deleteResult = document.querySelector('#item-row-' + itemID);
|
||||
deleteResult.remove();
|
||||
fetchItem();
|
||||
fetchPendingItems(typeName);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// modal participants select
|
||||
async function fetchParticipant(eventID) {
|
||||
const resParticipant = await (await fetch(`/items/participated?eventID=${eventID}`)).json();
|
||||
if (resParticipant.status === true) {
|
||||
for (const participantData of resParticipant.user) {
|
||||
document.querySelector(`#select-participant`).innerHTML += `
|
||||
<option value="${participantData.id}">${participantData.first_name} ${participantData.last_name}
|
||||
</option>
|
||||
`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// shopping list JS
|
||||
async function fetchPendingItems(selectType) {
|
||||
const resShopList = await (await fetch(`/items/pendingItems?eventID=${eventID}`)).json();
|
||||
if (resShopList.status === true) {
|
||||
let listItems = '';
|
||||
|
||||
for (const items of resShopList.itemObj[selectType]) {
|
||||
listItems += `
|
||||
<tr id="list-item-${items.id}">
|
||||
<td>
|
||||
<div class="pending-item">
|
||||
${items.name}
|
||||
<button id="checking-${items.id}" class="check-btn">
|
||||
<i class="bi bi-check-circle"></i>
|
||||
</button>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
}
|
||||
document.querySelector(`#shipping-list-update`).innerHTML = listItems;
|
||||
checkShoppingListItem();
|
||||
fetchItem();
|
||||
}
|
||||
}
|
||||
|
||||
function checkShoppingListItem() {
|
||||
document.querySelectorAll(`.check-btn`).forEach((button) => {
|
||||
button.addEventListener('click', async function (e) {
|
||||
const itemID = e.currentTarget.id.slice(9);
|
||||
const res = await fetch(`/items/pendingItems/${itemID}`, {
|
||||
method: 'PUT'
|
||||
});
|
||||
if ((await res.json()).status === true) {
|
||||
const updateOnTheList = document.querySelector('#list-item-' + itemID);
|
||||
updateOnTheList.remove();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
document.querySelector(`#back-page`).addEventListener('click', function () {
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
const eventId = params.get('event-id');
|
||||
const isCreator = params.get('is-creator');
|
||||
window.location = `/eventSummary/event.html?event-id=${eventId}&is-creator=${isCreator}`;
|
||||
});
|
||||
|
||||
document.querySelectorAll(`.dropdown-item`).forEach((dropdown) => {
|
||||
dropdown.addEventListener('click', function (e) {
|
||||
const selectType = e.currentTarget.innerHTML.toLowerCase();
|
||||
fetchPendingItems(selectType);
|
||||
});
|
||||
});
|
Reference in New Issue
Block a user