all repos — cameraman @ 3e900b97c788b7eb05b8712b2a344ea2bd0e8fba

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: #000;
 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
 68        .actions i {
 69            cursor: pointer;
 70            padding-right: 5px;
 71        }
 72
 73        .cute-button {
 74            margin-top: 20px;
 75            background-color: var(--green);
 76            border: none;
 77            color: white;
 78            padding: 10px 20px;
 79            text-align: center;
 80            text-decoration: none;
 81            display: inline-block;
 82            font-size: 16px;
 83            margin: 4px 2px;
 84            transition-duration: 0.4s;
 85            cursor: pointer;
 86            border-radius: 12px;
 87        }
 88
 89        .cute-button:hover {
 90            background-color: var(--hover-green);
 91        }
 92
 93        .cute-button-red {
 94            background-color: var(--red);
 95        }
 96
 97        .cute-button-red:hover {
 98            background-color: var(--hover-red);
 99        }
100
101        .hidden {
102            display: none;
103        }
104    </style>
105</head>
106
107<body>
108    <h1>Ricorrenze</h1>
109    <table id="main-table">
110        <tr>
111            <th>ID</th>
112            <th>Nome</th>
113            <th>Descrizione</th>
114            <th>Data (gg/mm)</th>
115            <th>Notifica</th>
116            <th>Azioni</th>
117        </tr>
118        {{ range .Occurrences }}
119        <tr id="occurrence-{{ .ID }}">
120            <td>{{ .ID }}</td>
121            <td>{{ .Name }}</td>
122            <td>{{ .Description }}</td>
123            <td>{{ padZero .Day }}/{{ padZero .Month }}</td>
124            <td><input type="checkbox" {{if .Notify}}checked{{end}} disabled></td>
125            <td class="actions">
126                <i class="fas fa-edit" title="Modifica" onclick="editOccurrence('{{ .ID }}')"></i>
127                <i class="fas fa-trash-alt" title="Elimina" onclick="deleteOccurrence('{{ .ID }}')"></i>
128            </td>
129        </tr>
130        {{ end }}
131        <tr id="occurrence-none">
132            <td colspan="6">Nessuna ricorrenza.</td>
133        </tr>
134    </table>
135    <div style="margin-top: 10px; text-align: center;">
136        <button id="add-row-button" class="cute-button" onclick="addNewOccurrenceRow()">
137            <i class="fas fa-plus"></i> Aggiungi</button>
138        <button id="save-row-button" class="cute-button hidden" onclick="saveOccurrence('0')">
139            <i class="fas fa-save"></i> Salva
140        </button>
141        <button id="cancel-row-button" class="cute-button cute-button-red hidden" onclick="cancelNewOccurrence()">
142            <i class="fas fa-times"></i> Annulla
143        </button>
144    </div>
145
146    <script>
147        const hiddenClass = 'hidden';
148        const addButton = document.getElementById('add-row-button');
149        const saveButton = document.getElementById('save-row-button');
150        const cancelButton = document.getElementById('cancel-row-button');
151        const mainTable = document.getElementById('main-table');
152        const noneRow = document.getElementById('occurrence-none');
153
154        function updateNoneRowDisplay() {
155            const rows = mainTable.getElementsByTagName('tr');
156            const l = rows.length
157            if (l === 2) {
158                noneRow.classList.remove(hiddenClass);
159                return;
160            }
161            noneRow.classList.add(hiddenClass);
162        }
163
164        function deleteOccurrence(id) {
165            if (confirm('Sei sicuro di voler eliminare questa ricorrenza?')) {
166                fetch(`/occurrences/${id}`, {
167                    method: 'DELETE'
168                })
169                    .then(response => {
170                        if (!response.ok) {
171                            console.error('Error:', response.status);
172                            alert('Eliminazione fallita.');
173                            return;
174                        }
175                        const deletedRow = document.getElementById(`occurrence-${id}`);
176                        deletedRow.parentElement.removeChild(deletedRow);
177                        updateNoneRowDisplay();
178                    })
179                    .catch(error => {
180                        console.error('Error:', error);
181                        alert('Non sono riuscito a contattare il backend.');
182                    });
183            }
184        }
185
186        function padNumber(input, n=2) {
187            return input.toString().padStart(n, '0');
188        }
189
190        function createRow(id, name, description, day, month, notify) {
191            return `
192                <td>${id}</td>
193                <td>${name}</td>
194                <td>${description}</td>
195                <td>${padNumber(day)}/${padNumber(month)}</td>
196                <td><input type="checkbox" ${notify ? 'checked' : ''} disabled></td>
197                <td class="actions">
198                    <i class="fas fa-edit" title="Edit" onclick="editOccurrence(${id})"></i>
199                    <i class="fas fa-trash-alt" title="Delete" onclick="deleteOccurrence(${id})"></i>
200                </td>
201            `;
202        }
203
204        function createInputFields(id, name, description, day, month, notify, isNew) {
205            return `
206                <td>${isNew ? '' : id}</td>
207                <td><input type="text" value="${name || ''}" id="name-${id}"></td>
208                <td><input type="text" value="${description || ''}" id="description-${id}"></td>
209                <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>
210                <td><input type="checkbox" id="notify-${id}" ${notify ? 'checked' : ''}></td>
211                <td class="actions">
212                    ${isNew ? '' : `
213                    <i class="fas fa-save" title="Save" onclick="saveOccurrence(${id})"></i>
214                    <i class="fas fa-times" title="Cancel" onclick="cancelEdit(${id}, '${name}', '${description}', ${day}, ${month}, ${notify})"></i>
215                    `}
216                </td>
217            `;
218        }
219
220        function editOccurrence(id) {
221            const row = document.getElementById(`occurrence-${id}`);
222            const cells = row.getElementsByTagName('td');
223
224            const name = cells[1].innerText;
225            const description = cells[2].innerText;
226            const [day, month] = cells[3].innerText.split('/');
227            const notify = cells[4].getElementsByTagName('input')[0].checked;
228
229            row.innerHTML = createInputFields(id, name, description, day, month, notify, false);
230        }
231
232        function cancelEdit(id, name, description, day, month, notify) {
233            const row = document.getElementById(`occurrence-${id}`);
234            row.innerHTML = createRow(id, name, description, day, month, notify);
235        }
236
237        function saveOccurrence(id) {
238            const name = document.getElementById(`name-${id}`).value;
239            const description = document.getElementById(`description-${id}`).value;
240            const day = parseInt(document.getElementById(`day-${id}`).value);
241            const month = parseInt(document.getElementById(`month-${id}`).value);
242            const notify = document.getElementById(`notify-${id}`).checked;
243
244            const isNew = id === '0';
245            const updatedData = {
246                id: isNew ? undefined : id,
247                name: name,
248                description: description,
249                month: month,
250                day: day,
251                notify: notify
252            };
253
254            fetch('/occurrences', {
255                method: 'POST',
256                headers: {
257                    'Content-Type': 'application/json'
258                },
259                body: JSON.stringify(updatedData)
260            })
261                .then(response => {
262                    if (!response.ok) {
263                        console.error('Error:', response.status);
264                        alert('Controlla che i campi siano validi.');
265                        return;
266                    }
267                    if (isNew) {
268                        cancelNewOccurrence();
269                        mainTable.insertRow(-1).id = `occurrence-${id}`
270                    }
271                    updateRow(`occurrence-${id}`, response);
272                })
273                .catch(error => {
274                    console.error('Error:', error);
275                    alert('Non sono riuscito a contattare il backend.');
276                });
277        }
278
279        function addNewOccurrenceRow() {
280            const newRow = mainTable.insertRow(-1);
281            newRow.id = 'new-occurrence';
282            newRow.innerHTML = createInputFields('0', '', '', '', '', true, true);
283
284            hideAddButton();
285            updateNoneRowDisplay();
286        }
287        function hideAddButton() {
288            addButton.classList.add(hiddenClass);
289            saveButton.classList.remove(hiddenClass);
290            cancelButton.classList.remove(hiddenClass);
291        }
292
293        function showAddButton() {
294            addButton.classList.remove(hiddenClass);
295            saveButton.classList.add(hiddenClass);
296            cancelButton.classList.add(hiddenClass);
297        }
298        
299        function updateRow(rowElementId, response) {
300            const newRow = document.getElementById(rowElementId);
301            response.json().then((res) => {
302                newRow.id = `occurrence-${res.id}`;
303                newRow.innerHTML = createRow(res.id, res.name, res.description, res.day, res.month, res.notify);
304                updateNoneRowDisplay()
305            });
306        }
307
308        function cancelNewOccurrence() {
309            const newRow = document.getElementById('new-occurrence');
310            newRow.parentNode.removeChild(newRow);
311            showAddButton();
312            updateNoneRowDisplay();
313        }
314
315        updateNoneRowDisplay()
316    </script>
317
318</body>
319
320</html>