all repos — cameraman @ 85f22f5ab0e2fc67d5a8679d88a09ae77d68c246

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