Files
WebChecker--Web-app-/templates/admin/shifts.html
T
2026-05-24 18:10:11 -04:00

225 lines
8.8 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{% extends "base.html" %}
{% block title %}Shifts — Website Checker{% endblock %}
{% block content %}
<div class="page-header">
<h1 class="page-title">Shift Management</h1>
<div style="display:flex;gap:.5rem">
<button class="btn btn-ghost btn-sm tab-btn active" data-tab="tab-list" data-group="shifts-tabs">☰ List</button>
<button class="btn btn-ghost btn-sm tab-btn" data-tab="tab-calendar" data-group="shifts-tabs">📅 Calendar</button>
<button class="btn btn-primary" onclick="openModal('modal-create-shift')"> New Shift</button>
</div>
</div>
<div id="shifts-tabs">
<!-- List tab -->
<div class="tab-panel active" id="tab-list">
<div class="card">
<table class="table table-hover">
<thead>
<tr><th>Name</th><th>Days</th><th>Time</th><th>Users</th><th>Sites</th><th>Active</th><th>Actions</th></tr>
</thead>
<tbody>
{% for s in shifts %}
<tr>
<td><strong>{{ s.name }}</strong><br><span class="text-muted text-sm">{{ s.note or '' }}</span></td>
<td>{{ s.days_of_week }}</td>
<td class="text-muted">{{ s.start_time }} {{ s.end_time }}</td>
<td>{{ s.user_count }}</td>
<td>{{ s.website_count }}</td>
<td><span class="badge badge-{{ 'success' if s.is_active else 'neutral' }}">{{ 'Active' if s.is_active else 'Inactive' }}</span></td>
<td class="actions">
<button class="btn btn-ghost btn-sm" onclick="loadEditShift({{ s.id }})">✎ Edit</button>
<form method="post" action="{{ url_for('admin_shifts.delete', shift_id=s.id) }}"
style="display:inline" onsubmit="return confirm('Deactivate shift {{ s.name }}?')">
<button class="btn btn-danger btn-sm" type="submit"></button>
</form>
</td>
</tr>
{% else %}
<tr><td colspan="7" class="text-center text-muted">No shifts configured.</td></tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<!-- Calendar tab -->
<div class="tab-panel" id="tab-calendar">
<div class="card">
<div class="card-header"><span class="card-title">Weekly Schedule</span></div>
<div style="overflow-x:auto">
<table class="table">
<thead>
<tr>
<th style="min-width:160px">Shift</th>
{% for label, _ in day_map %}
<th style="text-align:center;min-width:64px">{{ label }}</th>
{% endfor %}
</tr>
</thead>
<tbody>
{% for s in shifts if s.is_active %}
<tr>
<td>
<strong>{{ s.name }}</strong>
<div class="text-muted text-sm">{{ s.start_time|hhmm }}{{ s.end_time|hhmm }}</div>
</td>
{% for _, day_val in day_map %}
<td style="text-align:center">
{% if day_val in s.days_of_week %}
<span class="badge badge-success" title="{{ s.name }} runs on this day"></span>
{% else %}
<span class="text-muted" style="font-size:.9rem"></span>
{% endif %}
</td>
{% endfor %}
</tr>
{% else %}
<tr><td colspan="8" class="text-center text-muted">No active shifts.</td></tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
</div><!-- /shifts-tabs -->
<!-- Create Shift Modal -->
<div class="modal-overlay" id="modal-create-shift">
<div class="modal-dialog modal-lg">
<div class="modal-header">
<h3>New Shift</h3>
<button class="modal-close" onclick="closeModal('modal-create-shift')"></button>
</div>
<form method="post" action="{{ url_for('admin_shifts.create') }}">
<div class="modal-body">
<div class="form-group">
<label class="form-label">Shift Name *</label>
<input class="form-control" name="name" required>
</div>
<div class="form-group">
<label class="form-label">Days of Week</label>
<div class="day-checkboxes">
{% for label, val in day_map %}
<label class="day-check">
<input type="checkbox" name="days_of_week[]" value="{{ val }}"> {{ label }}
</label>
{% endfor %}
</div>
</div>
<div class="form-row">
<div class="form-group flex-1">
<label class="form-label">Start Time</label>
<input class="form-control" type="time" name="start_time" value="08:00">
</div>
<div class="form-group flex-1">
<label class="form-label">End Time</label>
<input class="form-control" type="time" name="end_time" value="17:00">
</div>
</div>
<div class="form-group">
<label class="form-label">Assign Users</label>
<div class="checkbox-list">
{% for u in all_users %}
<label><input type="checkbox" name="user_ids[]" value="{{ u.id }}"> {{ u.username }}</label>
{% endfor %}
</div>
</div>
<div class="form-group">
<label class="form-label">Assign Websites</label>
<div class="checkbox-list">
{% for w in all_sites %}
<label><input type="checkbox" name="website_ids[]" value="{{ w.id }}"> {{ w.name }}</label>
{% endfor %}
</div>
</div>
<div class="form-group">
<label class="form-label">Note</label>
<textarea class="form-control" name="note" rows="2"></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-ghost" onclick="closeModal('modal-create-shift')">Cancel</button>
<button type="submit" class="btn btn-primary">Create Shift</button>
</div>
</form>
</div>
</div>
<!-- Edit Shift Modal -->
<div class="modal-overlay" id="modal-edit-shift">
<div class="modal-dialog modal-lg">
<div class="modal-header">
<h3>Edit Shift</h3>
<button class="modal-close" onclick="closeModal('modal-edit-shift')"></button>
</div>
<form method="post" id="edit-shift-form">
<div class="modal-body" id="edit-shift-body"><div class="text-center text-muted">Loading…</div></div>
<div class="modal-footer">
<button type="button" class="btn btn-ghost" onclick="closeModal('modal-edit-shift')">Cancel</button>
<button type="submit" class="btn btn-primary">Save Changes</button>
</div>
</form>
</div>
</div>
<script>
const ALL_USERS = {{ all_users | tojson }};
const ALL_SITES = {{ all_sites | tojson }};
const DAY_MAP = {{ day_map | tojson }};
function loadEditShift(id) {
fetch('/admin/shifts/' + id + '/detail')
.then(r => r.json())
.then(s => {
document.getElementById('edit-shift-form').action = '/admin/shifts/' + id + '/edit';
document.getElementById('edit-shift-body').innerHTML = buildShiftForm(s);
openModal('modal-edit-shift');
});
}
function buildShiftForm(s) {
const days = DAY_MAP.map(([lbl, val]) => `
<label class="day-check">
<input type="checkbox" name="days_of_week[]" value="${val}"
${s.days_of_week.includes(val)?'checked':''}>${lbl}
</label>`).join('');
const users = ALL_USERS.map(u => `
<label><input type="checkbox" name="user_ids[]" value="${u.id}"
${s.user_ids.includes(u.id)?'checked':''}> ${u.username}</label>`).join('');
const sites = ALL_SITES.map(w => `
<label><input type="checkbox" name="website_ids[]" value="${w.id}"
${s.website_ids.includes(w.id)?'checked':''}> ${w.name}</label>`).join('');
return `
<div class="form-group"><label class="form-label">Shift Name *</label>
<input class="form-control" name="name" value="${esc(s.name)}" required></div>
<div class="form-group"><label class="form-label">Days of Week</label>
<div class="day-checkboxes">${days}</div></div>
<div class="form-row">
<div class="form-group flex-1"><label class="form-label">Start Time</label>
<input class="form-control" type="time" name="start_time" value="${esc(s.start_time)}"></div>
<div class="form-group flex-1"><label class="form-label">End Time</label>
<input class="form-control" type="time" name="end_time" value="${esc(s.end_time)}"></div>
</div>
<div class="form-group"><label class="form-label">Active</label>
<select class="form-control" name="is_active">
<option value="1" ${s.is_active?'selected':''}>Yes</option>
<option value="0" ${!s.is_active?'selected':''}>No</option>
</select></div>
<div class="form-group"><label class="form-label">Assign Users</label>
<div class="checkbox-list">${users}</div></div>
<div class="form-group"><label class="form-label">Assign Websites</label>
<div class="checkbox-list">${sites}</div></div>
<div class="form-group"><label class="form-label">Note</label>
<textarea class="form-control" name="note" rows="2">${esc(s.note)}</textarea></div>`;
}
function esc(s) { return (s||'').replace(/&/g,'&amp;').replace(/"/g,'&quot;').replace(/</g,'&lt;'); }
</script>
{% endblock %}