bmc_hub/app/conversations/frontend/templates/my_conversations.html

167 lines
7.0 KiB
HTML
Raw Normal View History

{% extends "shared/frontend/base.html" %}
{% block title %}Mine Samtaler - BMC Hub{% endblock %}
{% block content %}
<div class="row mb-4">
<div class="col-md-6">
<h1><i class="bi bi-mic me-2"></i>Mine Optagede Samtaler</h1>
<p class="text-muted">Administrer dine telefonsamtaler og lydnotater.</p>
</div>
<div class="col-md-6 text-end">
<div class="btn-group" role="group">
<input type="radio" class="btn-check" name="filterradio" id="btnradio1" autocomplete="off" checked onclick="filterView('all')">
<label class="btn btn-outline-primary" for="btnradio1">Alle</label>
<input type="radio" class="btn-check" name="filterradio" id="btnradio2" autocomplete="off" onclick="filterView('private')">
<label class="btn btn-outline-primary" for="btnradio2">Kun Private</label>
</div>
</div>
</div>
<div class="card shadow-sm">
<div class="card-body">
<div class="input-group mb-4">
<span class="input-group-text"><i class="bi bi-search"></i></span>
<input type="text" class="form-control" id="conversationSearch" placeholder="Søg i samtaler..." onkeyup="filterConversations()">
</div>
<div id="conversationsContainer">
<div class="text-center py-5">
<div class="spinner-border text-primary"></div>
<p class="mt-2 text-muted">Henter dine samtaler...</p>
</div>
</div>
</div>
</div>
<style>
.conversation-item { transition: transform 0.2s; }
.conversation-item:hover { transform: translateY(-2px); box-shadow: 0 4px 8px rgba(0,0,0,0.1); }
</style>
<script>
let allConversations = [];
document.addEventListener('DOMContentLoaded', () => {
loadMyConversations();
});
async function loadMyConversations() {
try {
const response = await fetch('/api/v1/conversations?only_mine=true');
if (!response.ok) throw new Error('Fejl');
allConversations = await response.json();
renderConversations(allConversations);
} catch(e) {
document.getElementById('conversationsContainer').innerHTML =
'<div class="alert alert-danger">Kunne ikke hente samtaler</div>';
}
}
function renderConversations(list) {
if(list.length === 0) {
document.getElementById('conversationsContainer').innerHTML =
'<div class="text-center py-5 text-muted">Ingen samtaler fundet</div>';
return;
}
document.getElementById('conversationsContainer').innerHTML = list.map(c => `
<div class="card mb-3 conversation-item ${c.is_private ? 'border-warning' : ''}" data-type="${c.is_private ? 'private' : 'public'}" data-text="${(c.transcript||'').toLowerCase()} ${(c.title||'').toLowerCase()}">
<div class="card-body">
<div class="d-flex justify-content-between">
<div>
<h5 class="card-title fw-bold">
${c.is_private ? '<i class="bi bi-lock-fill text-warning"></i> ' : ''}
${c.title}
</h5>
<p class="card-text text-muted small mb-2">
${new Date(c.created_at).toLocaleString()}
${c.customer_id ? `• Customer #${c.customer_id}` : ''}
</p>
<div class="mb-2" style="max-width: 150px;">
<select class="form-select form-select-sm py-0" style="font-size: 0.8rem;" onchange="updateCategory(${c.id}, this.value)">
<option value="General" ${(!c.category || c.category === 'General') ? 'selected' : ''}>Generelt</option>
<option value="Support" ${c.category === 'Support' ? 'selected' : ''}>Support</option>
<option value="Sales" ${c.category === 'Sales' ? 'selected' : ''}>Salg</option>
<option value="Internal" ${c.category === 'Internal' ? 'selected' : ''}>Internt</option>
</select>
</div>
</div>
<div>
<button class="btn btn-sm btn-outline-secondary" onclick="togglePrivacy(${c.id}, ${!c.is_private})">
${c.is_private ? 'Gør Offentlig' : 'Gør Privat'}
</button>
<button class="btn btn-sm btn-outline-danger ms-2" onclick="deleteConversation(${c.id})">
<i class="bi bi-trash"></i>
</button>
</div>
</div>
<audio controls class="w-100 my-2 bg-light rounded">
<source src="/api/v1/conversations/${c.id}/audio" type="audio/mpeg">
</audio>
${c.transcript ? `
<details>
<summary class="text-primary" style="cursor:pointer">Vis Transskription</summary>
<div class="mt-2 p-3 bg-light rounded font-monospace small">${c.transcript}</div>
</details>
` : ''}
</div>
</div>
`).join('');
}
function filterView(type) {
const items = document.querySelectorAll('.conversation-item');
items.forEach(item => {
if (type === 'all') item.style.display = 'block';
else if (type === 'private') item.style.display = item.dataset.type === 'private' ? 'block' : 'none';
});
}
function filterConversations() {
const query = document.getElementById('conversationSearch').value.toLowerCase();
const items = document.querySelectorAll('.conversation-item');
items.forEach(item => {
const text = item.dataset.text;
item.style.display = text.includes(query) ? 'block' : 'none';
});
}
async function togglePrivacy(id, makePrivate) {
await fetch(\`/api/v1/conversations/\${id}\`, {
method: 'PATCH',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({is_private: makePrivate})
});
loadMyConversations();
}
async function deleteConversation(id) {
if(!confirm('Vil du slette denne samtale?')) return;
const hard = confirm('Skal dette være en permanent sletning af fil og data? (Kan ikke fortrydes)');
await fetch(\`/api/v1/conversations/\${id}?hard_delete=\${hard}\`, { method: 'DELETE' });
loadMyConversations();
}
async function updateCategory(id, newCategory) {
try {
const response = await fetch(`/api/v1/conversations/${id}`, {
method: 'PATCH',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({category: newCategory})
});
if (!response.ok) throw new Error('Update failed');
} catch (e) {
alert("Kunne ikke opdatere kategori");
console.error(e);
loadMyConversations(); // Revert UI on error
}
}</script>
{% endblock %}