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;
|
||||
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>
|
||||
</head>
|
||||
<body>
|
||||
@ -491,6 +574,25 @@
|
||||
<div id="loader" class="loader hidden"></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>
|
||||
// Mock API URL - Replace with your actual API endpoint
|
||||
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
|
||||
function showTourView() {
|
||||
document.getElementById('createTourSection').classList.add('hidden');
|
||||
@ -889,6 +954,65 @@
|
||||
function hideLoader() {
|
||||
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>
|
||||
</body>
|
||||
</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