import { showToast } from '../components/toast.js';
const API = (url, opts = {}) => fetch('/api' + url, { headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${localStorage.getItem('token')}`, ...opts.headers }, ...opts }).then(r => r.json());
const WIDGET_TYPES = [
{ id: 'clock', name: 'Clock', icon: '🕓', desc: 'Digital clock with date' },
{ id: 'weather', name: 'Weather', icon: '⛅', desc: 'Current weather conditions' },
{ id: 'rss', name: 'News Ticker', icon: '📰', desc: 'Scrolling RSS feed' },
{ id: 'text', name: 'Text/HTML', icon: '📝', desc: 'Custom text or HTML content' },
{ id: 'webpage', name: 'Webpage', icon: '🌐', desc: 'Embed a webpage' },
{ id: 'social', name: 'Social Feed', icon: '💬', desc: 'Social media feed' },
];
export async function render(container) {
container.innerHTML = `
`;
let editingWidget = null;
let creatingType = null;
document.getElementById('newWidgetBtn').onclick = () => {
const grid = document.getElementById('widgetTypeGrid');
grid.style.display = grid.style.display === 'none' ? 'grid' : 'none';
};
container.querySelectorAll('[data-create-type]').forEach(el => {
el.onclick = () => {
creatingType = el.dataset.createType;
editingWidget = null;
document.getElementById('widgetTypeGrid').style.display = 'none';
showConfigForm(creatingType, {});
};
});
function showConfigForm(type, config) {
const typeName = WIDGET_TYPES.find(t => t.id === type)?.name || type;
document.getElementById('widgetModalTitle').textContent = editingWidget ? `Edit ${typeName}` : `New ${typeName}`;
let html = '';
switch (type) {
case 'clock':
html += `
`;
break;
case 'weather':
html += `
`;
break;
case 'rss':
html += `
`;
break;
case 'text':
html += `
`;
break;
case 'webpage':
html += `
`;
break;
case 'social':
html += `
`;
break;
}
document.getElementById('widgetConfigForm').innerHTML = html;
document.getElementById('widgetModal').style.display = 'flex';
}
function getConfigFromForm(type) {
const config = {};
const val = id => document.getElementById(id)?.value;
switch (type) {
case 'clock': Object.assign(config, { format: val('wFormat'), timezone: val('wTimezone'), font_size: parseInt(val('wFontSize')) || 64, color: val('wColor'), background: val('wBg'), show_date: true }); break;
case 'weather': Object.assign(config, { location: val('wLocation'), units: val('wUnits'), font_size: parseInt(val('wFontSize')) || 48, color: val('wColor') }); break;
case 'rss': Object.assign(config, { feed_url: val('wFeedUrl'), scroll_speed: parseInt(val('wScrollSpeed')) || 30, max_items: parseInt(val('wMaxItems')) || 10, font_size: parseInt(val('wFontSize')) || 24, color: val('wColor'), background: val('wBg') }); break;
case 'text': Object.assign(config, { html: val('wHtml'), css: val('wCss'), background: val('wBg') }); break;
case 'webpage': Object.assign(config, { url: val('wUrl'), zoom: parseInt(val('wZoom')) || 100, refresh_interval: parseInt(val('wRefresh')) || 0 }); break;
case 'social': Object.assign(config, { platform: val('wPlatform'), query: val('wQuery') }); break;
}
return config;
}
document.getElementById('saveWidgetBtn').onclick = async () => {
const type = editingWidget?.widget_type || creatingType;
const name = document.getElementById('wName').value;
const config = getConfigFromForm(type);
try {
if (editingWidget) {
await API(`/widgets/${editingWidget.id}`, { method: 'PUT', body: JSON.stringify({ name, config }) });
} else {
await API('/widgets', { method: 'POST', body: JSON.stringify({ widget_type: type, name, config }) });
}
document.getElementById('widgetModal').style.display = 'none';
showToast('Widget saved', 'success');
loadWidgets();
} catch (err) { showToast(err.message, 'error'); }
};
document.getElementById('previewWidgetBtn').onclick = () => {
if (editingWidget) {
window.open(`/api/widgets/${editingWidget.id}/render`, '_blank', 'width=600,height=400');
} else {
showToast('Save the widget first to preview', 'info');
}
};
async function loadWidgets() {
const widgets = await API('/widgets');
const grid = document.getElementById('widgetGrid');
if (!widgets.length) {
grid.innerHTML = 'No widgets yet
Create a widget to add dynamic content to your layouts.
';
return;
}
grid.innerHTML = widgets.map(w => {
const typeMeta = WIDGET_TYPES.find(t => t.id === w.widget_type) || {};
return `
${typeMeta.icon || '?'}
${w.name}
${typeMeta.name || w.widget_type}
`;
}).join('');
grid.onclick = async (e) => {
const editBtn = e.target.closest('[data-edit-widget]');
if (editBtn) {
const w = widgets.find(x => x.id === editBtn.dataset.editWidget);
if (w) {
editingWidget = w;
creatingType = w.widget_type;
const config = JSON.parse(w.config || '{}');
config._name = w.name;
showConfigForm(w.widget_type, config);
}
return;
}
const deleteBtn = e.target.closest('[data-delete-widget]');
if (deleteBtn) {
try {
await API(`/widgets/${deleteBtn.dataset.deleteWidget}`, { method: 'DELETE' });
showToast('Widget deleted', 'success');
loadWidgets();
} catch (err) { showToast(err.message, 'error'); }
}
};
}
loadWidgets();
}
export function cleanup() {}