Jul 10 - Update codes to catch up with the single tenant project (Medium)

This commit is contained in:
2026-07-10 12:58:57 -04:00
parent e41998b561
commit aa749107c7
12 changed files with 815 additions and 68 deletions
+46 -22
View File
@@ -42,11 +42,23 @@
<div class="d-flex justify-content-between align-items-center mb-3">
<div>
<h4 class="mb-0"><i class="bi bi-chat-dots me-2 text-primary"></i>JQC Support Chat</h4>
<small class="text-muted">Ask a question or browse common topics below</small>
<small class="text-muted">
{% if chat_session %}
Conversation from {{ chat_session.created_at.strftime('%b %d, %Y') }}
· <a href="{{ url_for('support.chat') }}">New Chat</a>
{% else %}
Ask a question or browse common topics below
{% endif %}
</small>
</div>
<div class="d-flex gap-2">
<a href="{{ url_for('support.my_conversations') }}" class="btn btn-outline-secondary btn-sm">
<i class="bi bi-clock-history me-1"></i>History
</a>
<button class="btn btn-outline-danger btn-sm" data-bs-toggle="modal" data-bs-target="#submitModal">
<i class="bi bi-envelope me-1"></i>Submit to Support
</button>
</div>
<button class="btn btn-outline-danger btn-sm" data-bs-toggle="modal" data-bs-target="#submitModal">
<i class="bi bi-envelope me-1"></i>Submit to Support
</button>
</div>
{# ── Chat card ── #}
@@ -54,8 +66,9 @@
{# Message window #}
<div id="chat-window"></div>
{# FAQ quick-reply chips #}
<div id="faq-section" class="px-3 pt-2 pb-1 border-top bg-white">
{# FAQ quick-reply chips — hidden when viewing a prior session #}
<div id="faq-section" class="px-3 pt-2 pb-1 border-top bg-white"
{% if db_history %}style="display:none;"{% endif %}>
<p class="small text-muted mb-2"><i class="bi bi-lightning-charge me-1"></i>Common questions:</p>
<div class="d-flex flex-wrap gap-2 mb-2">
{% for faq in faqs %}
@@ -114,7 +127,7 @@
<div class="modal-body">
<div class="mb-3">
<label class="form-label fw-semibold">Subject <span class="text-danger">*</span></label>
<input type="text" name="subject" class="form-control" required maxlength="200"
<input type="text" name="subject" id="ticketSubject" class="form-control" required maxlength="200"
placeholder="Briefly describe your issue">
</div>
{% if facilities %}
@@ -156,14 +169,23 @@
const faqSection = document.getElementById('faq-section');
const CSRF_TOKEN = '{{ csrf_token() }}';
// In-memory conversation history sent to the server with each message
let history = [];
// Persisted session ID — returned by the server on first message, sent on all subsequent ones
let session_id = {{ (chat_session.id if chat_session else none) | tojson }};
// ── Greeting on page load ──────────────────────────────────────────────
// Last user message — used to pre-fill the support ticket subject
let last_user_msg = '';
// ── Render DB history on page load ────────────────────────────────────
var userName = {{ current_user.display_name | tojson }};
appendMessage('ai', "👋 Hi " + userName + "! I'm your JQC support assistant. " +
"I can help you with inspections, issues, reports, and more. " +
"Click a question below or type your own.");
{% if db_history %}
{% for msg in db_history %}
appendMessage({{ msg.role | tojson }}, {{ msg.content | tojson }});
{% endfor %}
{% else %}
appendMessage('ai', "👋 Hi " + userName + "! I'm your JQC support assistant. " +
"I can help you with inspections, issues, reports, and more. " +
"Click a question below or type your own.");
{% endif %}
// ── Append a message bubble ────────────────────────────────────────────
function appendMessage(role, text) {
@@ -198,17 +220,18 @@
if (el) el.remove();
}
// ── Send message to Groq ───────────────────────────────────────────────
// ── Send message to server ─────────────────────────────────────────────
function sendMessage(text) {
if (!text.trim()) return;
last_user_msg = text;
// Hide FAQ chips after first interaction
if (faqSection) faqSection.style.display = 'none';
appendMessage('user', text);
history.push({ role: 'user', content: text });
chatInput.value = '';
chatInput.value = '';
chatInput.disabled = true;
document.getElementById('send-btn').disabled = true;
showTyping();
@@ -219,14 +242,16 @@
'Content-Type': 'application/json',
'X-CSRFToken': CSRF_TOKEN,
},
body: JSON.stringify({ message: text, messages: history }),
body: JSON.stringify({ message: text, session_id: session_id }),
})
.then(function (r) { return r.json(); })
.then(function (data) {
hideTyping();
// Store session_id returned by the server for subsequent messages
if (data.session_id) session_id = data.session_id;
const reply = data.reply || 'Sorry, I could not process your request.';
appendMessage('ai', reply);
history.push({ role: 'assistant', content: reply });
// Suggest escalation if the AI hints it can't help
const lower = reply.toLowerCase();
@@ -268,10 +293,9 @@
// ── Pre-fill modal subject from last user message ──────────────────────
document.getElementById('submitModal').addEventListener('show.bs.modal', function () {
const subjectInput = this.querySelector('[name="subject"]');
if (subjectInput && !subjectInput.value && history.length) {
const lastUser = [...history].reverse().find(function (m) { return m.role === 'user'; });
if (lastUser) subjectInput.value = lastUser.content.slice(0, 200);
const subjectInput = document.getElementById('ticketSubject');
if (subjectInput && !subjectInput.value && last_user_msg) {
subjectInput.value = last_user_msg.slice(0, 200);
}
});
}());