import { showToast } from '../components/toast.js';
import { esc } from '../utils.js';
import { t } from '../i18n.js';
const API = (url) => fetch('/api' + url, { headers: { Authorization: `Bearer ${localStorage.getItem('token')}` }}).then(r => r.json());
export async function render(container) {
container.innerHTML = `
`;
let offset = 0;
const limit = 50;
async function loadActivity(append = false) {
try {
const items = await API(`/activity?limit=${limit}&offset=${offset}`);
const list = document.getElementById('activityList');
if (!append) list.innerHTML = '';
if (items.length === 0 && offset === 0) {
list.innerHTML = `${t('activity.empty_title')}
${t('activity.empty_desc')}
`;
return;
}
const html = items.map(item => {
const time = new Date(item.created_at * 1000);
const timeStr = time.toLocaleDateString(undefined, { month: 'short', day: 'numeric' }) + ' ' +
time.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit' });
const icon = getActionIcon(item.action);
return `
${icon}
${esc(item.user_name || item.user_email || t('activity.system'))}
${esc(formatAction(item.action))}
${item.details ? `
${esc(item.details)}
` : ''}
${timeStr}
`;
}).join('');
if (append) {
list.insertAdjacentHTML('beforeend', html);
} else {
list.innerHTML = html;
}
document.getElementById('loadMoreBtn').style.display = items.length >= limit ? '' : 'none';
} catch (err) {
showToast(err.message, 'error');
}
}
document.getElementById('loadMoreBtn').onclick = () => {
offset += limit;
loadActivity(true);
};
loadActivity();
}
function getActionIcon(action) {
if (action.includes('DELETE')) return '🗑';
if (action.includes('POST') && action.includes('content')) return '📤';
if (action.includes('POST') && action.includes('provision')) return '🔗';
if (action.includes('POST') && action.includes('assignment')) return '📋';
if (action.includes('alert')) return '🔔';
if (action.includes('PUT')) return '✎';
if (action.includes('POST')) return '➕';
return '📄';
}
// Action verbs are user-visible; translate them through t() so they switch
// languages with the rest of the UI. The mapping below preserves the original
// verb-then-noun structure of the English version.
function formatAction(action) {
// Verbs
let s = action
.replace('POST /api/', t('activity.verb_created') + ' ')
.replace('PUT /api/', t('activity.verb_updated') + ' ')
.replace('DELETE /api/', t('activity.verb_deleted') + ' ');
// Specific endpoints
s = s
.replace('/provision/pair', t('activity.action_paired_device'))
.replace('/content/remote', t('activity.action_added_remote_content'))
.replace('/content', t('activity.noun_content'))
.replace('/devices/:id', t('activity.noun_device'))
.replace('/assignments/device/:deviceId', t('activity.noun_playlist_assignment'))
.replace('/assignments/:id', t('activity.noun_assignment'))
.replace('/layouts', t('activity.noun_layout'))
.replace('/widgets', t('activity.noun_widget'))
.replace('/schedules', t('activity.noun_schedule'))
.replace('/walls', t('activity.noun_video_wall'))
.replace('alert:device_offline', t('activity.alert_device_offline'));
return s;
}
export function cleanup() {}