Fixes and service.sh.
This commit is contained in:
parent
c66772fd67
commit
fdf214c7d4
198
index.html
198
index.html
@ -409,6 +409,89 @@
|
|||||||
margin-bottom: 4px;
|
margin-bottom: 4px;
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#voteModal {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
z-index: 999;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
#voteModal.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.modal-backdrop {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: rgba(10, 10, 15, 0.8);
|
||||||
|
backdrop-filter: blur(2px);
|
||||||
|
z-index: 1;
|
||||||
|
}
|
||||||
|
.modal-content {
|
||||||
|
position: relative;
|
||||||
|
z-index: 2;
|
||||||
|
width: 90%;
|
||||||
|
max-width: 400px;
|
||||||
|
padding: 30px;
|
||||||
|
border-radius: 20px;
|
||||||
|
background: rgba(255, 255, 255, 0.05);
|
||||||
|
backdrop-filter: blur(10px);
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
|
||||||
|
text-align: center;
|
||||||
|
animation: modalFadeIn 0.3s ease-out;
|
||||||
|
}
|
||||||
|
.modal-title {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
color: var(--accent-primary);
|
||||||
|
}
|
||||||
|
.modal-subtitle {
|
||||||
|
color: var(--text-secondary);
|
||||||
|
font-size: 0.9rem;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
#voterNameInput {
|
||||||
|
width: 100%;
|
||||||
|
padding: 12px;
|
||||||
|
border: 1px solid var(--border-color);
|
||||||
|
border-radius: 8px;
|
||||||
|
background: rgba(255, 255, 255, 0.05);
|
||||||
|
color: var(--text-primary);
|
||||||
|
font-size: 1rem;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
#voterNameInput:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: var(--accent-secondary);
|
||||||
|
box-shadow: 0 0 0 3px rgba(123, 47, 247, 0.1);
|
||||||
|
background: rgba(255, 255, 255, 0.08);
|
||||||
|
}
|
||||||
|
.modal-buttons {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
gap: 10px;
|
||||||
|
}
|
||||||
|
.modal-buttons .btn {
|
||||||
|
font-size: 0.9rem;
|
||||||
|
padding: 8px 16px;
|
||||||
|
}
|
||||||
|
@keyframes modalFadeIn {
|
||||||
|
from { opacity: 0; transform: translateY(-10px) scale(0.97); }
|
||||||
|
to { opacity: 1; transform: translateY(0) scale(1); }
|
||||||
|
}
|
||||||
|
@keyframes modalFadeOut {
|
||||||
|
from { opacity: 1; transform: translateY(0) scale(1); }
|
||||||
|
to { opacity: 0; transform: translateY(-10px) scale(0.97); }
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
@ -491,6 +574,25 @@
|
|||||||
<div id="loader" class="loader hidden"></div>
|
<div id="loader" class="loader hidden"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="voteModal" class="hidden">
|
||||||
|
<div class="modal-backdrop"></div>
|
||||||
|
<div class="modal-content glass-card">
|
||||||
|
<h3 class="modal-title">Cast Your Vote</h3>
|
||||||
|
<p class="modal-subtitle">Enter your name to vote for this idea</p>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
id="voterNameInput"
|
||||||
|
placeholder="Your name…"
|
||||||
|
maxlength="50"
|
||||||
|
autofocus
|
||||||
|
/>
|
||||||
|
<div class="modal-buttons">
|
||||||
|
<button id="voteCancelBtn" class="btn btn-secondary btn-small">Cancel</button>
|
||||||
|
<button id="voteSubmitBtn" class="btn btn-small">Submit</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
// Mock API URL - Replace with your actual API endpoint
|
// Mock API URL - Replace with your actual API endpoint
|
||||||
const API_URL = 'https://kaizenkodo.no/tour/v1';
|
const API_URL = 'https://kaizenkodo.no/tour/v1';
|
||||||
@ -648,43 +750,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vote for idea
|
|
||||||
async function voteForIdea(ideaId) {
|
|
||||||
const voterName = prompt('Enter your name to vote:');
|
|
||||||
if (!voterName) return;
|
|
||||||
|
|
||||||
showLoader();
|
|
||||||
try {
|
|
||||||
const response = await fetch(
|
|
||||||
`${API_URL}/tours/${currentTour.id}/ideas/${ideaId}/vote`,
|
|
||||||
{
|
|
||||||
method: 'POST',
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
body: JSON.stringify({ voterName })
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if (response.status === 404) {
|
|
||||||
throw new Error('Tour or Idea not found');
|
|
||||||
}
|
|
||||||
if (!response.ok) {
|
|
||||||
throw new Error(`Server responded with ${response.status}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// FastAPI returns the Idea object (with updated voters list)
|
|
||||||
const updatedIdea = await response.json();
|
|
||||||
// Replace the old idea in currentTour.ideas with the updated one
|
|
||||||
currentTour.ideas = currentTour.ideas.map(i =>
|
|
||||||
i.id === updatedIdea.id ? updatedIdea : i
|
|
||||||
);
|
|
||||||
renderIdeas();
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error voting:', error);
|
|
||||||
alert('Failed to vote. Please try again.');
|
|
||||||
} finally {
|
|
||||||
hideLoader();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Show tour view
|
// Show tour view
|
||||||
function showTourView() {
|
function showTourView() {
|
||||||
document.getElementById('createTourSection').classList.add('hidden');
|
document.getElementById('createTourSection').classList.add('hidden');
|
||||||
@ -889,6 +954,65 @@
|
|||||||
function hideLoader() {
|
function hideLoader() {
|
||||||
document.getElementById('loader').classList.add('hidden');
|
document.getElementById('loader').classList.add('hidden');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const voteModal = document.getElementById('voteModal');
|
||||||
|
const voterNameInput = document.getElementById('voterNameInput');
|
||||||
|
const voteCancelBtn = document.getElementById('voteCancelBtn');
|
||||||
|
const voteSubmitBtn = document.getElementById('voteSubmitBtn');
|
||||||
|
let _pendingVoteIdeaId = null;
|
||||||
|
|
||||||
|
function voteForIdea(ideaId) {
|
||||||
|
_pendingVoteIdeaId = ideaId;
|
||||||
|
voterNameInput.value = '';
|
||||||
|
voteSubmitBtn.disabled = true;
|
||||||
|
voteModal.classList.remove('hidden');
|
||||||
|
setTimeout(() => voterNameInput.focus(), 100);
|
||||||
|
}
|
||||||
|
|
||||||
|
voterNameInput.addEventListener('input', () => {
|
||||||
|
voteSubmitBtn.disabled = voterNameInput.value.trim().length === 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
function closeVoteModal() {
|
||||||
|
const content = voteModal.querySelector('.modal-content');
|
||||||
|
content.style.animation = 'modalFadeOut 0.2s ease-out forwards';
|
||||||
|
setTimeout(() => {
|
||||||
|
voteModal.classList.add('hidden');
|
||||||
|
content.style.animation = 'modalFadeIn 0.3s ease-out'; // reset for next open
|
||||||
|
_pendingVoteIdeaId = null;
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
voteCancelBtn.addEventListener('click', closeVoteModal);
|
||||||
|
voteSubmitBtn.addEventListener('click', async () => {
|
||||||
|
const voterName = voterNameInput.value.trim();
|
||||||
|
if (!voterName) return;
|
||||||
|
|
||||||
|
closeVoteModal();
|
||||||
|
showLoader();
|
||||||
|
try {
|
||||||
|
const resp = await fetch(
|
||||||
|
`${API_URL}/tours/${currentTour.id}/ideas/${_pendingVoteIdeaId}/vote`,
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ voterName }),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
if (resp.status === 404) throw new Error('Tour or Idea not found');
|
||||||
|
if (!resp.ok) throw new Error(`Server responded with ${resp.status}`);
|
||||||
|
const updatedIdea = await resp.json();
|
||||||
|
currentTour.ideas = currentTour.ideas.map((i) =>
|
||||||
|
i.id === updatedIdea.id ? updatedIdea : i
|
||||||
|
);
|
||||||
|
renderIdeas();
|
||||||
|
} catch (err) {
|
||||||
|
console.error('Error voting:', err);
|
||||||
|
alert('Failed to vote. Please try again.');
|
||||||
|
} finally {
|
||||||
|
hideLoader();
|
||||||
|
_pendingVoteIdeaId = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
4
service.sh
Executable file
4
service.sh
Executable file
@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
cd /home/kaizen/repos/tourplanner || exit 1
|
||||||
|
exec python3.11 server.py --port=3002 --data-dir=/home/kaizen/repos/tourplanner/data
|
||||||
Loading…
x
Reference in New Issue
Block a user