This commit is contained in:
louiscklaw
2025-02-01 01:58:47 +08:00
parent b3da7aaef5
commit 04dbefcbaf
1259 changed files with 280657 additions and 0 deletions

View File

@@ -0,0 +1,307 @@
export async function getEventSchedule() {
const params = new URLSearchParams(window.location.search);
const eventId = params.get('event-id');
const isCreator = params.get('is-creator');
const res = await fetch(`/events/?event-id=${eventId}&is-creator=${isCreator}`);
if (res.status !== 200) {
const data = await res.json();
alert(data.msg);
return;
}
const result = await res.json();
if (result.status) {
const option = {
hour12: false,
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit'
};
const startDateTime = new Date(result.detail.start_datetime)
.toLocaleString('en-US', option)
.replace(', ', ' ')
.slice(0, -3);
const endDateTime = new Date(result.detail.end_datetime)
.toLocaleString('en-US', option)
.replace(', ', ' ')
.slice(0, -3);
const activitiesArr = result.activities;
const startTime = startDateTime.slice(-5);
const endTime = endDateTime.slice(-5);
const startDate = startDateTime.slice(0, 10);
const endDate = endDateTime.slice(0, 10);
const startYear = startDateTime.slice(6, 10);
const endYear = endDateTime.slice(6, 10);
const startMonth = startDateTime.slice(0, 2);
const endMonth = endDateTime.slice(0, 2);
const startDay = startDateTime.slice(3, 5);
const endDay = endDateTime.slice(3, 5);
const date = `${startYear}${startMonth}${startDay}`;
let startTimeInMin = toMin(startTime);
let endTimeInMin = toMin(endTime);
const dayDifference = (new Date(endDate).getTime() - new Date(startDate).getTime()) / 1000 / 60 / 60 / 24;
if (
dayDifference > 0 &&
date !== `${startYear}${startMonth}${startDay}` &&
date !== `${endYear}${endMonth}${endDay}`
) {
startTimeInMin = 0;
endTimeInMin = 1440;
}
if (dayDifference > 0 && date === `${startYear}${startMonth}${startDay}`) {
endTimeInMin = 1440;
}
if (dayDifference > 0 && date === `${endYear}${endMonth}${endDay}`) {
startTimeInMin = 0;
}
await getPresetTimeBlock(startTimeInMin);
await getSavedTimeBlocks(activitiesArr);
await correctDiv(startTimeInMin, endTimeInMin);
setGlobalHeight(2);
}
}
async function getPresetTimeBlock(startTime) {
let rundown = document.querySelector('#rundown');
//generate time block for 24 hours
for (let i = 0; i < 96; i++) {
let start = i * 15;
let end = (i + 1) * 15;
const timeString = minToTimeString(start);
const height = end - start;
rundown.innerHTML += `
<div id="time-block-container-${start}" start="${start}" end="${end}" class="individual-time-block row">
<span id="time-stamp-box" class="time-stamp-container col-sm-2">
<div id="stamp-${start}" class="time-stamp">${timeString}</div>
</span>
<span id="time-block-${start}" start="${start}" end="${end}" class="time-block col-sm-10"></span>
</div>
`;
document.querySelector(`#time-block-${start}`).style.height = `${height}px`;
}
//set scroll bar top
document.querySelector(`#time-block-${startTime}`).innerHTML = 'Event Start Time';
const scrollBarDiv = document.querySelector('#rundown-container');
scrollBarDiv.scrollTop = document.querySelector(`#time-block-${startTime}`).offsetTop;
}
async function getSavedTimeBlocks(activitiesArr) {
activitiesArr.forEach(async (activity) => {
const start = activity.start_time;
const title = activity.title;
const startTimeInMin = toMin(activity.start_time);
const endTimeInMin = toMin(activity.end_time);
const divHeight = endTimeInMin - startTimeInMin;
const id = activity.id;
const presetColor = '#f29659';
let color = activity.color;
if (activity.color === null || undefined) {
color = presetColor;
}
document.querySelector(`#time-block-container-${startTimeInMin}`).innerHTML = `
<span id="time-stamp-box" class="time-stamp-container col-2">
<div id="stamp-${startTimeInMin}" class="time-stamp">${start}</div>
</span>
<span value="${id}" type="button" id="time-block-${startTimeInMin}" start="${startTimeInMin}" end="${endTimeInMin}" class="time-block save-time-block col-10">
</span>
`;
document.querySelector(`#time-block-${startTimeInMin}`).innerHTML = title;
document.querySelector(`#time-block-${startTimeInMin}`).style.height = `${divHeight}px`;
document.querySelector(`#time-block-${startTimeInMin}`).style.backgroundColor = `${color}`;
});
}
async function fixDivHeight(x) {
if (x > 0) {
const divCluster = document.querySelectorAll('.time-block');
divCluster.forEach((div) => {
let nextDiv;
if (div.parentElement.nextElementSibling?.childNodes) {
nextDiv = div.parentElement.nextElementSibling.childNodes[3];
}
const height = parseInt(div.getAttribute('end')) - parseInt(div.getAttribute('start'));
if (!!div.parentElement.nextElementSibling?.childNodes) {
if (nextDiv) {
if (div.classList === nextDiv.classList && !div.classList.contains('save-time-block')) {
div.style.height = newHeight;
const newHeight = parseInt(nextDiv.getAttribute('end')) - parseInt(div.getAttribute('start'));
div.setAttribute(`start`, `${nextDiv.getAttribute('end')}`);
nextDiv.parentElement.innerHTML = '';
} else if (height > 60 && !div.classList.contains('save-time-block')) {
div.style.height = '60px';
const redundantHeight = height - 60;
nextDiv.setAttribute(`start`, `${parseInt(nextDiv.getAttribute('start')) + redundantHeight}`);
} else {
div.style.height = `${height}px`;
}
}
}
});
fixDivHeight(x - 1);
} else {
return;
}
}
function toMin(timeInput) {
const hourInMin = parseInt(timeInput.slice(0, 2)) * 60;
const min = parseInt(timeInput.slice(3, 5));
return hourInMin + min;
}
async function setGlobalHeight(input) {
const allBlocks = document.querySelectorAll('.time-block');
allBlocks.forEach((block) => {
const originalHeight = parseInt(block.style.height.slice(0, -2));
block.style.height = `${originalHeight * input}px`;
});
}
async function fixTimeStamp() {
const timeStampDiv = document.querySelectorAll('.time-stamp');
timeStampDiv.forEach((stamp) => {
let nextTimeBlock;
let placeholder = stamp.parentElement.nextElementSibling;
while (placeholder) {
if (placeholder.classList.contains('time-block')) {
nextTimeBlock = placeholder;
break;
}
placeholder = placeholder.nextElementSibling;
}
const time = minToTimeString(parseInt(nextTimeBlock.getAttribute('start')));
stamp.innerHTML = time;
});
}
async function deleteRedundantDiv(x) {
const divCluster = document.querySelectorAll(`.time-block`);
if (x > 0) {
for (let i = 0; i < divCluster.length; i++) {
if (!!divCluster[i + 1]) {
const endTime = parseInt(divCluster[i].getAttribute('end'));
const nextStartTime = parseInt(divCluster[i + 1].getAttribute('start'));
if (endTime > nextStartTime) {
divCluster[i + 1].parentElement.remove();
} else if (endTime < nextStartTime) {
divCluster[i + 1].setAttribute(`start`, `${endTime}`);
}
}
}
deleteRedundantDiv(x - 1);
}
return;
}
async function correctDiv(eventStartTimeInMin, eventEndTimeInMin) {
const divCluster = document.querySelectorAll(`.time-block`);
const params = new URLSearchParams(window.location.search);
const isCreator = params.get('is-creator');
for (let i = 0; i < divCluster.length; i++) {
const startTime = parseInt(divCluster[i].getAttribute('start'));
const endTime = parseInt(divCluster[i].getAttribute('end'));
const height = endTime - startTime;
const timeString = minToTimeString(startTime);
if (!!divCluster[i + 1]) {
divCluster[i].style.height = `${height}px`;
const nextStartTime = parseInt(divCluster[i + 1].getAttribute('start'));
const nextEndTime = parseInt(divCluster[i + 1].getAttribute('end'));
const newDivHeight = nextStartTime - endTime;
const nextStartTimeFormat = minToTimeString(nextStartTime);
if (endTime < nextStartTime && startTime >= eventStartTimeInMin && startTime < eventEndTimeInMin) {
divCluster[i].parentNode.insertAdjacentHTML(
'afterend',
`
<div id="time-block-container-${endTime}" class="individual-time-block row">
<span id="time-stamp-box" class="time-stamp-container col-2">
<div id="stamp-${endTime}" class="time-stamp">${nextStartTimeFormat}</div>
</span>
<span type="button" id="time-block-${endTime}" start="${endTime}" end="${nextStartTime}" class="time-block event-schedule col-10" data-bs-toggle="modal" data-bs-target="#create-time-block-modal"></span>
</div>
`
);
document.querySelector(`#time-block-${endTime}`).style.height = `${newDivHeight}px`;
} else if (endTime < nextStartTime) {
divCluster[i].parentNode.insertAdjacentHTML(
'afterend',
`
<div id="time-block-container-${endTime}" class="individual-time-block row">
<span id="time-stamp-box" class="time-stamp-container col-2">
<div id="stamp-${endTime}" class="time-stamp">${nextStartTimeFormat}</div>
</span>
<span id="time-block-${endTime}" start="${endTime}" end="${nextStartTime}" class="time-block col-10"></span>
</div>
`
);
document.querySelector(`#time-block-${endTime}`).style.height = `${newDivHeight}px`;
}
document.querySelector(`#stamp-${startTime}`).innerHTML = timeString;
divCluster[i].style.height = `${height}`;
}
if (
startTime >= eventStartTimeInMin &&
startTime < eventEndTimeInMin &&
!divCluster[i].classList.contains('save-time-block')
) {
divCluster[i].classList.add('event-schedule');
if (isCreator === '1') {
divCluster[i].setAttribute(`data-bs-target`, `#create-time-block-modal`);
divCluster[i].setAttribute(`type`, 'button');
divCluster[i].setAttribute(`data-bs-toggle`, `modal`);
}
}
}
deleteRedundantDiv(100);
fixTimeStamp();
fixDivHeight(10);
}
function minToTimeString(timeInMin) {
if (timeInMin < 10) {
return `00:0${timeInMin}`;
} else if (timeInMin < 60) {
return `00:${timeInMin}`;
} else if (Math.floor(timeInMin / 60) < 10 && timeInMin % 60 < 10) {
const hour = Math.floor(timeInMin / 60);
const min = timeInMin % 60;
return `0${hour}:0${min}`;
} else if (Math.floor(timeInMin / 60) >= 10 && timeInMin % 60 < 10) {
const hour = Math.floor(timeInMin / 60);
const min = timeInMin % 60;
return `${hour}:0${min}`;
} else if (Math.floor(timeInMin / 60) >= 10 && timeInMin % 60 >= 10) {
const hour = Math.floor(timeInMin / 60);
const min = timeInMin % 60;
return `${hour}:${min}`;
} else if (Math.floor(timeInMin / 60) < 10 && timeInMin % 60 >= 10) {
const hour = Math.floor(timeInMin / 60);
const min = timeInMin % 60;
return `0${hour}:${min}`;
}
}

View File

@@ -0,0 +1,410 @@
body {
position: relative;
margin-left: 2px;
margin-right: 20px;
font-family: 'Kalam';
font-size: 16px;
}
.modal-body {
height: fit-content;
}
.input-group {
display: flex;
justify-content: center;
}
.input-panel {
margin: 0px;
}
.item-list-box {
min-height: 150px;
min-width: 100px;
}
#item-form-text {
text-align: center;
}
header {
display: flex;
justify-content: center;
}
#item-form-header {
text-align: center;
}
.item-list-box {
border-radius: 10px;
background-color: #e8e892;
height: 100%;
padding-top: 10px;
padding-bottom: 10px;
overflow: auto;
}
.modal-content {
align-items: center;
width: fit-content;
}
#date-selector-container {
display: flex;
justify-content: right;
padding-bottom: 10px;
padding-right: 10px;
}
textarea {
border-radius: 5px;
background: none;
border-color: #3f3f3f;
max-height: 100%;
overflow: auto;
}
header {
text-align: center;
}
#time-block-memo-container {
position: relative;
max-height: 100%;
}
#close-memo {
position: absolute;
top: 0px;
font-size: 10px;
right: 10px;
}
#time-block-page-container {
max-height: 800px;
height: 550px;
padding-top: 0px;
padding-bottom: 30px;
}
#event-time-container {
text-align: center;
}
.event-schedule {
background-color: #efefd0 !important;
}
.event-schedule:hover {
background-color: #e8e892 !important;
}
@media (max-width: 1000px) {
#line {
display: none;
}
}
@media (max-width: 576px) {
@media (max-width: 1000px) {
#line {
display: none;
}
#memo {
font-size: large;
max-height: 100%;
max-width: 100%;
overflow: auto;
}
#time-block-memo-container {
max-height: 300px;
height: 300px;
overflow: auto;
}
#rundown-container {
max-height: 300px;
}
}
}
#memo {
background-color: #efefd0;
height: 90%;
border-radius: 10px;
overflow: auto;
}
#page {
display: flex;
justify-content: center;
height: 90%;
width: 100%;
}
/* #line {
position: absolute;
} */
textarea {
width: 100%;
}
.create-button {
position: fixed;
left: 30px;
bottom: 30px;
}
#rundown {
max-height: 80%;
max-width: 100%;
}
#rundown-container {
max-height: 100%;
position: relative;
background-color: white;
padding-top: 30px;
padding-bottom: 20px;
}
.time-stamp-container {
background-color: none;
position: relative;
display: flex;
justify-content: center;
align-items: center;
}
.individual-time-block {
height: 100%;
padding: 2px;
max-width: 100%;
overflow: visible;
}
.time-block {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
background-color: rgba(181, 180, 180, 0.625);
padding: 10px;
border-radius: 5px;
padding: 1px;
font-size: 1.5vw;
text-align: center;
transition: background-color 50ms ease-out 50ms;
}
.save-time-block {
height: 100%;
color: white;
opacity: 0.7;
padding: 10px;
border-radius: 5px;
text-align: center;
transition: background-color 50ms ease-out 50ms;
}
.save-time-block:hover {
opacity: 0.8;
transform: scale(1.01);
}
.time-stamp {
position: absolute;
top: -5px;
right: 10px;
font-size: 10px;
}
.last-time-stamp {
position: absolute;
bottom: -5px;
right: 10px;
font-size: 10px;
}
.memo-item-container {
position: relative;
background-color: rgba(255, 255, 255, 0.522);
border-radius: 10px;
width: 100%;
height: 100%;
margin-bottom: 10px;
padding: 10px;
font-size: 15px;
}
#memo-item-cluster {
display: flex;
flex-direction: column;
justify-content: space-between;
height: 100%;
padding: 10px;
}
.memo-item-label {
font-weight: 800;
font-size: 15px;
padding: 5px;
}
/* Scroll bar */
::-webkit-scrollbar {
width: 15px;
}
::-webkit-scrollbar-track {
box-shadow: inset 0 0 5px grey;
border-radius: 5px;
height: 200px;
}
::-webkit-scrollbar-thumb {
background: #efefd0;
border-radius: 5px;
min-height: 250px;
}
::-webkit-scrollbar-thumb:hover {
background: white;
}
#memo,
#memo-tag {
animation-duration: 0.5s;
animation-name: animate-fade;
animation-delay: 0.1s;
animation-fill-mode: backwards;
}
@keyframes animate-fade {
0% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#edit-activities {
border-radius: 100px;
background-color: #f2965985;
color: white;
text-align: center;
min-width: 22px !important;
min-height: 22px !important;
padding: 3px;
font-size: 10px;
}
#edit-remarks {
border-radius: 100px;
background-color: #f2965985;
color: white;
text-align: center;
min-width: 22px !important;
min-height: 22px !important;
padding: 3px;
font-size: 10px;
}
#edit-show-item {
border-radius: 100px;
background-color: #f2965985;
color: white;
text-align: center;
min-width: 22px !important;
min-height: 22px !important;
padding: 3px;
font-size: 10px;
}
.edit-button {
position: absolute;
top: 5px;
right: 5px;
}
.modal-dialog {
display: flex;
justify-content: center;
align-items: center;
height: 100%;
}
#event-name {
font-size: 2vw;
padding-top: 10px;
}
.fa-trash {
z-index: 1000;
right: 20px;
top: 20px;
}
.creator-function {
z-index: 1000;
}
/* CSS */
.button-53 {
background-color: #f29659;
border: 0 solid #e5e7eb;
box-sizing: border-box;
color: #000000;
display: flex;
font-family: ui-sans-serif, system-ui, -apple-system, system-ui, 'Segoe UI', Roboto, 'Helvetica Neue', Arial,
'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
font-size: 1rem;
font-weight: 700;
justify-content: center;
line-height: 1.75rem;
padding: 0.75rem 1.65rem;
position: relative;
text-align: center;
text-decoration: none #000000 solid;
text-decoration-thickness: auto;
width: 100%;
max-width: 460px;
position: relative;
cursor: pointer;
transform: rotate(-2deg);
user-select: none;
-webkit-user-select: none;
touch-action: manipulation;
}
.button-53:focus {
outline: 0;
}
.button-53:after {
content: '';
position: absolute;
border: 1px solid #000000;
bottom: 4px;
left: 4px;
width: calc(100% - 1px);
height: calc(100% - 1px);
}
.button-53:hover:after {
bottom: 2px;
left: 2px;
}
@media (min-width: 768px) {
.button-53 {
padding: 0.75rem 3rem;
font-size: 1.25rem;
}
}