ai-reports/index-convo.html
DJP 0da5b0e73d Initial commit: AI Tool Usage Reporting Dashboard
Complete suite of HTML dashboards for AI tool usage and conversation reporting via webhook APIs. Includes main navigation dashboard, multiple conversation reports (Latam, SBII, Sidekick), and AI tools usage report with comprehensive analytics.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-15 10:41:07 -04:00

309 lines
No EOL
11 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Conversation Reporting Tool</title>
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500;600;700&display=swap" rel="stylesheet">
<style>
body {
font-family: 'Montserrat', sans-serif;
margin: 0;
padding: 20px;
background-color: #f5f5f5;
}
.container {
max-width: 1200px;
margin: 0 auto;
background-color: white;
padding: 15px;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
h1 {
color: #333;
text-align: center;
margin-bottom: 20px;
font-size: 22px;
}
.controls {
display: flex;
gap: 20px;
margin-bottom: 15px;
align-items: center;
justify-content: center;
}
select {
padding: 10px;
border-radius: 4px;
border: 1px solid #ddd;
font-family: 'Montserrat', sans-serif;
font-size: 16px;
}
button {
padding: 10px 20px;
background-color: #4285f4;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-family: 'Montserrat', sans-serif;
font-size: 16px;
font-weight: 500;
}
button:hover {
background-color: #3367d6;
}
.loading {
text-align: center;
display: none;
}
.loader {
border: 4px solid #f3f3f3;
border-top: 4px solid #3498db;
border-radius: 50%;
width: 30px;
height: 30px;
animation: spin 2s linear infinite;
margin: 0 auto;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.results {
margin-top: 15px;
}
table {
width: 100%;
border-collapse: collapse;
font-size: 13px;
}
th, td {
padding: 6px 12px;
text-align: left;
border-bottom: 1px solid #ddd;
line-height: 1.3;
}
th {
background-color: #f8f9fa;
font-weight: 600;
}
tr:hover {
background-color: #f5f5f5;
}
.error {
color: red;
text-align: center;
margin-top: 20px;
font-weight: 500;
}
</style>
</head>
<body>
<div class="container">
<h1>Conversation Reporting Tool</h1>
<div class="controls">
<select id="optionSelect">
<option value="itau2-Conversations">itau2-Conversations</option>
<option value="Oliver Latam-Conversations">Oliver Latam-Conversations</option>
<option value="Ancar-Conversations">Ancar-Conversations</option>
</select>
<button id="sendButton">Send Request</button>
</div>
<div id="loading" class="loading">
<div class="loader"></div>
<p>Loading data, please wait...</p>
</div>
<div id="error" class="error"></div>
<div id="results" class="results">
<!-- Results will be dynamically inserted here -->
</div>
</div>
<script>
document.getElementById('sendButton').addEventListener('click', async () => {
const selectedOption = document.getElementById('optionSelect').value;
const loadingDiv = document.getElementById('loading');
const errorDiv = document.getElementById('error');
const resultsDiv = document.getElementById('results');
// Clear previous results
errorDiv.textContent = '';
resultsDiv.innerHTML = '';
loadingDiv.style.display = 'block';
try {
const response = await fetch('https://hook.us1.make.celonis.com/ewnkda13g1b65s1h2on2clo8ql7vdkl0', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
option: selectedOption,
auth_code: "jh87dkjs9sdj392sw72sj0210h*^&b$#rfg"
})
});
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
const data = await response.json();
// Process the data for pivot table
const pivotData = processPivotData(data);
// Generate and display the table
displayPivotTable(pivotData);
} catch (error) {
errorDiv.textContent = `Error: ${error.message}`;
console.error('Error:', error);
} finally {
loadingDiv.style.display = 'none';
}
});
function processPivotData(data) {
// Group conversations by Assistant_ID
const assistantGroups = {};
data.forEach(item => {
const assistantId = item.data.Assistant_ID || 'Unknown';
const userId = item.data.User_ID || 'Unknown';
if (!assistantGroups[assistantId]) {
assistantGroups[assistantId] = {
users: {},
totalCount: 0
};
}
if (!assistantGroups[assistantId].users[userId]) {
assistantGroups[assistantId].users[userId] = 0;
}
assistantGroups[assistantId].users[userId]++;
assistantGroups[assistantId].totalCount++;
});
return assistantGroups;
}
function displayPivotTable(pivotData) {
const resultsDiv = document.getElementById('results');
// Create the table
const table = document.createElement('table');
const thead = document.createElement('thead');
const tbody = document.createElement('tbody');
// Create header row
const headerRow = document.createElement('tr');
const headers = ['Assistant ID', 'User ID', 'Conversation Count'];
headers.forEach(headerText => {
const header = document.createElement('th');
header.textContent = headerText;
headerRow.appendChild(header);
});
thead.appendChild(headerRow);
table.appendChild(thead);
// Create table body
for (const assistantId in pivotData) {
const assistantData = pivotData[assistantId];
let firstRow = true;
for (const userId in assistantData.users) {
const row = document.createElement('tr');
// Assistant ID column (only show in first row of group)
const assistantCell = document.createElement('td');
assistantCell.textContent = firstRow ? assistantId : '';
if (firstRow) {
assistantCell.style.fontWeight = 'bold';
}
row.appendChild(assistantCell);
// User ID column
const userCell = document.createElement('td');
userCell.textContent = userId;
row.appendChild(userCell);
// Count column
const countCell = document.createElement('td');
countCell.textContent = assistantData.users[userId];
row.appendChild(countCell);
tbody.appendChild(row);
firstRow = false;
}
// Add a total row for this assistant
const totalRow = document.createElement('tr');
const totalLabelCell = document.createElement('td');
totalLabelCell.textContent = '';
totalRow.appendChild(totalLabelCell);
const totalUserCell = document.createElement('td');
totalUserCell.textContent = 'Total';
totalUserCell.style.fontWeight = 'bold';
totalRow.appendChild(totalUserCell);
const totalCountCell = document.createElement('td');
totalCountCell.textContent = assistantData.totalCount;
totalCountCell.style.fontWeight = 'bold';
totalRow.appendChild(totalCountCell);
tbody.appendChild(totalRow);
// Add an empty row as a separator
const spacerRow = document.createElement('tr');
const spacerCell = document.createElement('td');
spacerCell.setAttribute('colspan', '3');
spacerCell.style.height = '4px';
spacerRow.appendChild(spacerCell);
tbody.appendChild(spacerRow);
}
// Add grand total row
const grandTotalRow = document.createElement('tr');
// Create grand total cells
const grandTotalLabelCell = document.createElement('td');
grandTotalLabelCell.textContent = 'GRAND TOTAL';
grandTotalLabelCell.style.fontWeight = 'bold';
grandTotalLabelCell.style.fontSize = '16px';
grandTotalRow.appendChild(grandTotalLabelCell);
const grandTotalBlankCell = document.createElement('td');
grandTotalRow.appendChild(grandTotalBlankCell);
// Calculate grand total
let grandTotal = 0;
for (const assistantId in pivotData) {
grandTotal += pivotData[assistantId].totalCount;
}
const grandTotalCountCell = document.createElement('td');
grandTotalCountCell.textContent = grandTotal;
grandTotalCountCell.style.fontWeight = 'bold';
grandTotalCountCell.style.fontSize = '16px';
grandTotalRow.appendChild(grandTotalCountCell);
tbody.appendChild(grandTotalRow);
table.appendChild(tbody);
resultsDiv.appendChild(table);
}
</script>
</body>
</html>