all repos — cameraman @ ac9177ae9453c770241849e2831d3d3611993ebc

templates/index.html (view raw)

  1<!DOCTYPE html>
  2<html>
  3
  4<head>
  5    <title>Ricorrenze</title>
  6    <link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%2210 0 100 100%22><text y=%22.90em%22 font-size=%2290%22>📅</text></svg>"></link>
  7    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
  8    <style>
  9        :root {
 10            color-scheme: light dark;
 11            --text: #000;
 12            --bg: #fff;
 13            --green: #4CAF50;
 14            --hover-green: #45a049;
 15            --red: #af4c4c;
 16            --hover-red: #a14545;
 17        }
 18
 19        @media (prefers-color-scheme: dark) {
 20            :root {
 21                color-scheme: dark light;
 22                --text: #fff;
 23                --bg: #121212;
 24                --green: #265929;
 25                --hover-green: #214d23;
 26                --red: #592626;
 27                --hover-red: #4d2121;
 28            }
 29        }
 30
 31        body {
 32            font-family: Arial, sans-serif;
 33            background-color: var(--bg);
 34            color: var(--text);
 35        }
 36
 37        table {
 38            width: 100%;
 39            border-collapse: collapse;
 40        }
 41
 42        table,
 43        th,
 44        td {
 45            border: 1px solid var(--text);
 46        }
 47
 48        th,
 49        td {
 50            padding: 10px;
 51            text-align: left;
 52        }
 53
 54        th {
 55            background-color: var(--bg);
 56        }
 57
 58        .date-inputs {
 59            display: flex;
 60            align-items: center;
 61            border: none;
 62            gap: 2px;
 63        }
 64        .small-input {
 65            width: 32px;
 66        }
 67        .big-input {
 68            width: 100%;
 69        }
 70
 71        .actions i {
 72            cursor: pointer;
 73            padding-right: 5px;
 74        }
 75
 76        .cute-button {
 77            margin-top: 20px;
 78            background-color: var(--green);
 79            border: none;
 80            color: white;
 81            padding: 10px 20px;
 82            text-align: center;
 83            text-decoration: none;
 84            display: inline-block;
 85            font-size: 16px;
 86            margin: 4px 2px;
 87            transition-duration: 0.4s;
 88            cursor: pointer;
 89            border-radius: 12px;
 90        }
 91
 92        .cute-button:hover {
 93            background-color: var(--hover-green);
 94        }
 95
 96        .cute-button-red {
 97            background-color: var(--red);
 98        }
 99
100        .cute-button-red:hover {
101            background-color: var(--hover-red);
102        }
103
104        .hidden {
105            display: none;
106        }
107    </style>
108</head>
109
110<body>
111    <h1>Ricorrenze</h1>
112    <table id="main-table">
113        <tr>
114            <th>Nome</th>
115            <th>Descrizione</th>
116            <th>Data (gg/mm)</th>
117            <th>Notifica</th>
118            <th>Inviata</th>
119            <th>Azioni</th>
120        </tr>
121        {{ range .Occurrences }}
122        <tr id="occurrence-{{ .ID }}">
123            <td>{{ .Name }}</td>
124            <td>{{ .Description }}</td>
125            <td>{{ padZero .Day }}/{{ padZero .Month }}</td>
126            <td><input type="checkbox" {{if .Notify}}checked{{end}} disabled></td>
127            <td><input type="checkbox" {{if .Notified}}checked{{end}} disabled></td>
128            <td class="actions">
129                <i class="fas fa-edit" title="Modifica" onclick="editOccurrence('{{ .ID }}')"></i>
130                <i class="fas fa-trash-alt" title="Elimina" onclick="deleteOccurrence('{{ .ID }}')"></i>
131            </td>
132        </tr>
133        {{ end }}
134        <tr id="occurrence-none" class="hidden">
135            <td colspan="6">Nessuna ricorrenza.</td>
136        </tr>
137    </table>
138    <div style="margin-top: 10px; text-align: center;">
139        <button id="add-row-button" class="cute-button" onclick="addNewOccurrenceRow()">
140            <i class="fas fa-plus"></i> Aggiungi</button>
141        <button id="save-row-button" class="cute-button hidden" onclick="saveOccurrence('0')">
142            <i class="fas fa-save"></i> Salva
143        </button>
144        <button id="cancel-row-button" class="cute-button cute-button-red hidden" onclick="cancelNewOccurrence()">
145            <i class="fas fa-times"></i> Annulla
146        </button>
147    </div>
148
149    <script>
150        const hiddenClass = 'hidden';
151        const addButton = document.getElementById('add-row-button');
152        const saveButton = document.getElementById('save-row-button');
153        const cancelButton = document.getElementById('cancel-row-button');
154        const mainTable = document.getElementById('main-table');
155        const noneRow = document.getElementById('occurrence-none');
156
157        function updateNoneRowDisplay() {
158            const rows = mainTable.getElementsByTagName('tr');
159            const l = rows.length
160            if (l === 2) {
161                noneRow.classList.remove(hiddenClass);
162                return;
163            }
164            noneRow.classList.add(hiddenClass);
165        }
166
167        function deleteOccurrence(id) {
168            if (confirm('Sei sicuro di voler eliminare questa ricorrenza?')) {
169                fetch(`/occurrences/${id}`, {
170                    method: 'DELETE'
171                })
172                    .then(response => {
173                        if (!response.ok) {
174                            console.error('Error:', response.status);
175                            alert('Eliminazione fallita.');
176                            return;
177                        }
178                        const deletedRow = document.getElementById(`occurrence-${id}`);
179                        deletedRow.parentElement.removeChild(deletedRow);
180                        updateNoneRowDisplay();
181                    })
182                    .catch(error => {
183                        console.error('Error:', error);
184                        alert('Non sono riuscito a contattare il backend.');
185                    });
186            }
187        }
188
189        function padNumber(input, n=2) {
190            return Math.max(1, Math.min(input, 12)).toString().padStart(n, '0');
191        }
192
193        function createRow(id, name, description, day, month, notify, notified) {
194            return `
195                <td>${name}</td>
196                <td>${description}</td>
197                <td>${padNumber(day)}/${padNumber(month)}</td>
198                <td><input type="checkbox" ${notify ? 'checked' : ''} disabled></td>
199                <td><input type="checkbox" ${notified ? 'checked' : ''} disabled></td>
200                <td class="actions">
201                    <i class="fas fa-edit" title="Edit" onclick="editOccurrence(${id})"></i>
202                    <i class="fas fa-trash-alt" title="Delete" onclick="deleteOccurrence(${id})"></i>
203                </td>
204            `;
205        }
206
207        function createInputFields(id, name, description, day, month, notify, notified, isNew) {
208            return `
209                <td><input class="big-input" type="text" value="${name || ''}" id="name-${id}"></td>
210                <td><input class="big-input" type="text" value="${description || ''}" id="description-${id}"></td>
211                <td class="date-inputs"><input type="number" value="${day || ''}" id="day-${id}" class="small-input" min="1" max="31" onchange="this.value = padNumber(this.value);"> /<input type="number" value="${month || ''}" id="month-${id}" class="small-input" min="1" max="12" onchange="this.value = padNumber(this.value);"></td>
212                <td><input type="checkbox" id="notify-${id}" ${notify ? 'checked' : ''}></td>
213                <td><input type="checkbox" id="notified-${id}" ${notified ? 'checked' : 'disabled'}></td>
214                <td class="actions">
215                    ${isNew ? '' : `
216                    <i class="fas fa-save" title="Save" onclick="saveOccurrence(${id})"></i>
217                    <i class="fas fa-times" title="Cancel" onclick="cancelEdit(${id}, '${name}', '${description}', ${day}, ${month}, ${notify})"></i>
218                    `}
219                </td>
220            `;
221        }
222
223        function editOccurrence(id) {
224            const row = document.getElementById(`occurrence-${id}`);
225            const cells = row.getElementsByTagName('td');
226
227            const name = cells[0].innerText;
228            const description = cells[1].innerText;
229            const [day, month] = cells[2].innerText.split('/');
230            const notify = cells[3].getElementsByTagName('input')[0].checked;
231            const notified = cells[4].getElementsByTagName('input')[0].checked;
232
233            row.innerHTML = createInputFields(id, name, description, day, month, notify, notified, false);
234        }
235
236        function cancelEdit(id, name, description, day, month, notify) {
237            const row = document.getElementById(`occurrence-${id}`);
238            row.innerHTML = createRow(id, name, description, day, month, notify);
239        }
240
241        function saveOccurrence(id) {
242            const name = document.getElementById(`name-${id}`).value;
243            const description = document.getElementById(`description-${id}`).value;
244            const day = parseInt(document.getElementById(`day-${id}`).value);
245            const month = parseInt(document.getElementById(`month-${id}`).value);
246            const notify = document.getElementById(`notify-${id}`).checked;
247            const notified = document.getElementById(`notified-${id}`).checked;
248
249            const isNew = id === '0';
250            const updatedData = {
251                id: isNew ? undefined : id,
252                name: name,
253                description: description,
254                month: month,
255                day: day,
256                notify: notify,
257                notified: notified
258            };
259
260            fetch('/occurrences', {
261                method: 'POST',
262                headers: {
263                    'Content-Type': 'application/json'
264                },
265                body: JSON.stringify(updatedData)
266            })
267                .then(response => {
268                    if (!response.ok) {
269                        console.error('Error:', response.status);
270                        alert('Controlla che i campi siano validi.');
271                        return;
272                    }
273                    if (isNew) {
274                        cancelNewOccurrence();
275                        mainTable.insertRow(-1).id = `occurrence-${id}`
276                    }
277                    updateRow(`occurrence-${id}`, response);
278                })
279                .catch(error => {
280                    console.error('Error:', error);
281                    alert('Non sono riuscito a contattare il backend.');
282                });
283        }
284
285        function addNewOccurrenceRow() {
286            const newRow = mainTable.insertRow(-1);
287            newRow.id = 'new-occurrence';
288            newRow.innerHTML = createInputFields('0', '', '', '', '', true, false, true);
289
290            hideAddButton();
291            updateNoneRowDisplay();
292        }
293        function hideAddButton() {
294            addButton.classList.add(hiddenClass);
295            saveButton.classList.remove(hiddenClass);
296            cancelButton.classList.remove(hiddenClass);
297        }
298
299        function showAddButton() {
300            addButton.classList.remove(hiddenClass);
301            saveButton.classList.add(hiddenClass);
302            cancelButton.classList.add(hiddenClass);
303        }
304        
305        function updateRow(rowElementId, response) {
306            const newRow = document.getElementById(rowElementId);
307            response.json().then((res) => {
308                newRow.id = `occurrence-${res.id}`;
309                newRow.innerHTML = createRow(res.id, res.name, res.description, res.day, res.month, res.notify, res.notified);
310                updateNoneRowDisplay()
311            });
312        }
313
314        function cancelNewOccurrence() {
315            const newRow = document.getElementById('new-occurrence');
316            newRow.parentNode.removeChild(newRow);
317            showAddButton();
318            updateNoneRowDisplay();
319        }
320
321        updateNoneRowDisplay()
322    </script>
323
324</body>
325
326</html>