Ver 1.02
This commit is contained in:
parent
d10151cf40
commit
28c36a1e12
Binary file not shown.
Binary file not shown.
@ -182,3 +182,6 @@ if EMAIL_USE_SSL:
|
||||
# https://docs.djangoproject.com/en/5.2/ref/settings/#default-auto-field
|
||||
|
||||
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'
|
||||
LOGIN_URL = 'login'
|
||||
LOGIN_REDIRECT_URL = 'home'
|
||||
LOGOUT_REDIRECT_URL = 'login'
|
||||
|
||||
@ -5,6 +5,7 @@ from django.conf.urls.static import static
|
||||
|
||||
urlpatterns = [
|
||||
path("admin/", admin.site.urls),
|
||||
path("accounts/", include("django.contrib.auth.urls")),
|
||||
path("", include("core.urls")),
|
||||
]
|
||||
|
||||
|
||||
BIN
core/__pycache__/tests.cpython-311.pyc
Normal file
BIN
core/__pycache__/tests.cpython-311.pyc
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -4,65 +4,128 @@
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>{% block title %}Fox Fitt Construction{% endblock %}</title>
|
||||
|
||||
<title>{% block title %}FoxFitt{% endblock %}</title>
|
||||
<!-- Bootstrap 5.3 CSS -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH" crossorigin="anonymous">
|
||||
<!-- Google Fonts -->
|
||||
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@700&family=Open+Sans:wght@400;600&display=swap" rel="stylesheet">
|
||||
|
||||
<!-- Bootstrap 5 CSS -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Poppins:wght@500;600;700&display=swap" rel="stylesheet">
|
||||
<!-- Font Awesome 6 -->
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
|
||||
<!-- Custom CSS -->
|
||||
<link rel="stylesheet" href="{% static 'css/custom.css' %}?v={{ deployment_timestamp }}">
|
||||
|
||||
{% block head %}{% endblock %}
|
||||
<link rel="stylesheet" href="{% static 'css/custom.css' %}?v={{ request.timestamp|default:'1.0' }}">
|
||||
<style>
|
||||
body { font-family: 'Inter', sans-serif; background-color: #f8f9fa; display: flex; flex-direction: column; min-height: 100vh; }
|
||||
h1, h2, h3, h4, h5, h6, .navbar-brand { font-family: 'Poppins', sans-serif; }
|
||||
.navbar { background-color: #0f172a !important; }
|
||||
.navbar-brand-fox { color: #10b981; font-weight: 700; }
|
||||
.navbar-brand-fitt { color: #ffffff; font-weight: 700; }
|
||||
.nav-link { font-weight: 500; }
|
||||
.dropdown-menu { border-radius: 8px; box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1); }
|
||||
main { flex-grow: 1; }
|
||||
footer { background-color: #0f172a; color: #cbd5e1; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<nav class="navbar navbar-expand-lg navbar-dark sticky-top">
|
||||
<nav class="navbar navbar-expand-lg navbar-dark sticky-top shadow-sm">
|
||||
<div class="container">
|
||||
<a class="navbar-brand fw-bold" href="{% url 'index' %}">FOX FITT</a>
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||
<a class="navbar-brand d-flex align-items-center" href="{% url 'home' %}">
|
||||
<span class="navbar-brand-fox">Fox</span>
|
||||
<span class="navbar-brand-fitt">Fitt</span>
|
||||
</a>
|
||||
|
||||
{% if user.is_authenticated %}
|
||||
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarNav">
|
||||
<ul class="navbar-nav ms-auto">
|
||||
<ul class="navbar-nav me-auto mb-2 mb-lg-0">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'index' %}">Dashboard</a>
|
||||
<a class="nav-link {% if request.resolver_match.url_name == 'home' %}active{% endif %}" href="{% url 'home' %}">
|
||||
<i class="fas fa-home me-1"></i> Dashboard
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="{% url 'attendance_log' %}">Log Attendance</a>
|
||||
<a class="nav-link {% if request.resolver_match.url_name == 'attendance_log' %}active{% endif %}" href="{% url 'attendance_log' %}">
|
||||
<i class="fas fa-clipboard-list me-1"></i> Log Work
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="/admin/">Admin Portal</a>
|
||||
<a class="nav-link" href="#">
|
||||
<i class="fas fa-clock me-1"></i> History
|
||||
</a>
|
||||
</li>
|
||||
{% if user.is_staff %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">
|
||||
<i class="fas fa-wallet me-1"></i> Payroll
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" href="#">
|
||||
<i class="fas fa-receipt me-1"></i> Receipts
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle d-flex align-items-center" href="#" id="navbarDropdown" role="button" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<i class="fas fa-user-circle me-2 fs-5"></i>
|
||||
{{ user.username }}
|
||||
</a>
|
||||
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
|
||||
{% if user.is_staff %}
|
||||
<li>
|
||||
<a class="dropdown-item" href="{% url 'admin:index' %}">
|
||||
<i class="fas fa-cog me-2 text-secondary"></i> Admin Panel
|
||||
</a>
|
||||
</li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
{% endif %}
|
||||
<li>
|
||||
<form method="post" action="{% url 'logout' %}" class="px-3 py-2">
|
||||
{% csrf_token %}
|
||||
<button type="submit" class="btn btn-danger w-100 btn-sm">
|
||||
<i class="fas fa-sign-out-alt me-1"></i> Logout
|
||||
</button>
|
||||
</form>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
{% if messages %}
|
||||
<div class="container mt-4">
|
||||
{% for message in messages %}
|
||||
<div class="alert alert-{{ message.tags }} alert-dismissible fade show" role="alert">
|
||||
{{ message }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<!-- Messages Block -->
|
||||
{% if messages %}
|
||||
{% for message in messages %}
|
||||
<div class="alert alert-{{ message.tags }} alert-dismissible fade show shadow-sm" role="alert">
|
||||
{{ message }}
|
||||
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Main Content -->
|
||||
<main>
|
||||
{% block content %}{% endblock %}
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
</main>
|
||||
|
||||
<footer class="footer mt-auto">
|
||||
<!-- Footer -->
|
||||
<footer class="py-4 mt-auto border-top border-secondary">
|
||||
<div class="container text-center">
|
||||
<p>© 2026 Fox Fitt Construction - Payroll Management</p>
|
||||
<p class="mb-0 small">© {% now "Y" %} FoxFitt Construction. All rights reserved.</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<!-- Bootstrap 5 JS Bundle -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
{% block scripts %}{% endblock %}
|
||||
<!-- Bootstrap 5.3 JS Bundle -->
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-YvpcrYf0tY3lHB60NNkmxc5s9fDVZLESaAA55NDzOxhy9GkcIdslK1eN7N6jIeHz" crossorigin="anonymous"></script>
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
@ -1,47 +1,53 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block title %}Log Work | FoxFitt{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<section class="container py-5">
|
||||
<div class="container py-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1 class="h3 mb-0" style="color: #0f172a; font-family: 'Poppins', sans-serif;">Log Daily Attendance</h1>
|
||||
<a href="{% url 'home' %}" class="btn btn-outline-secondary btn-sm shadow-sm">
|
||||
<i class="fas fa-arrow-left fa-sm me-1"></i> Back
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-lg-8">
|
||||
<div class="card shadow">
|
||||
<div class="card-header bg-primary text-white text-center py-3">
|
||||
<h2 class="h4 mb-0">Log Daily Attendance</h2>
|
||||
</div>
|
||||
<div class="card-body p-4">
|
||||
<div class="card shadow-sm border-0" style="border-radius: 12px;">
|
||||
<div class="card-body p-5">
|
||||
<form method="POST" id="attendanceForm">
|
||||
{% csrf_token %}
|
||||
<div class="mb-4">
|
||||
<label class="form-label fw-bold">{{ form.date.label }}</label>
|
||||
<label class="form-label" style="font-weight: 600;">{{ form.date.label }}</label>
|
||||
{{ form.date }}
|
||||
</div>
|
||||
|
||||
<div class="row g-3 mb-4">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-bold">{{ form.project.label }}</label>
|
||||
<label class="form-label" style="font-weight: 600;">{{ form.project.label }}</label>
|
||||
{{ form.project }}
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-bold">{{ form.supervisor.label }}</label>
|
||||
<label class="form-label" style="font-weight: 600;">{{ form.supervisor.label }}</label>
|
||||
{{ form.supervisor }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label class="form-label fw-bold">{{ form.team.label }} (Optional - selection will auto-check workers)</label>
|
||||
<label class="form-label" style="font-weight: 600;">{{ form.team.label }} <span class="text-muted fw-normal">(Optional)</span></label>
|
||||
{{ form.team }}
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label class="form-label fw-bold d-block mb-3">Workers Present</label>
|
||||
<div class="worker-selection border rounded p-3 bg-light" style="max-height: 300px; overflow-y: auto;">
|
||||
<label class="form-label d-block mb-3" style="font-weight: 600;">Workers Present</label>
|
||||
<div class="worker-selection border rounded p-3" style="max-height: 300px; overflow-y: auto; background-color: #f8fafc; border-color: #e2e8f0 !important;">
|
||||
<div class="row">
|
||||
{% for worker in form.workers %}
|
||||
<div class="col-md-6 mb-2">
|
||||
<div class="form-check">
|
||||
{{ worker.tag }}
|
||||
<label class="form-check-label" for="{{ worker.id_for_label }}">
|
||||
<label class="form-check-label ms-1" for="{{ worker.id_for_label }}">
|
||||
{{ worker.choice_label }}
|
||||
</label>
|
||||
</div>
|
||||
@ -53,30 +59,23 @@
|
||||
|
||||
<div class="row g-3 mb-4">
|
||||
<div class="col-md-6">
|
||||
<label class="form-label fw-bold">{{ form.overtime_amount.label }}</label>
|
||||
<label class="form-label" style="font-weight: 600;">{{ form.overtime_amount.label }}</label>
|
||||
{{ form.overtime_amount }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<label class="form-label fw-bold">{{ form.notes.label }}</label>
|
||||
<label class="form-label" style="font-weight: 600;">{{ form.notes.label }}</label>
|
||||
{{ form.notes }}
|
||||
</div>
|
||||
|
||||
<div class="d-grid">
|
||||
<button type="submit" class="btn btn-primary btn-lg shadow">Save Attendance Log</button>
|
||||
<div class="d-grid mt-5">
|
||||
<button type="submit" class="btn btn-lg text-white shadow-sm" style="background-color: #10b981; border: none; font-weight: 600; border-radius: 8px;">Save Attendance Log</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
||||
{% block scripts %}
|
||||
<script>
|
||||
// Simple team selection auto-checking logic could be added here
|
||||
// For this MVP, we'll keep it as a standard multi-select for workers.
|
||||
</script>
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
@ -1,66 +1,86 @@
|
||||
{% extends 'base.html' %}
|
||||
{% load static %}
|
||||
|
||||
{% block title %}Dashboard | FoxFitt{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<section class="hero-section text-center">
|
||||
<div class="container">
|
||||
<h1 class="display-4 mb-4">Construction Payroll & Attendance</h1>
|
||||
<p class="lead mb-5">Efficiently track workers, projects, and payroll for Fox Fitt Construction.</p>
|
||||
<div class="d-flex justify-content-center gap-3">
|
||||
<a href="{% url 'attendance_log' %}" class="btn btn-primary btn-lg px-5 py-3">Log Attendance</a>
|
||||
<a href="/admin/core/worker/" class="btn btn-outline-light btn-lg px-5 py-3">Manage Workers</a>
|
||||
</div>
|
||||
<div class="container py-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h1 class="h3 mb-0 text-gray-800">Welcome back, {{ user.first_name|default:user.username }}!</h1>
|
||||
<a href="{% url 'attendance_log' %}" class="btn text-white shadow-sm" style="background-color: #10b981;">
|
||||
<i class="fas fa-plus fa-sm text-white-50 me-1"></i> Log Work
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="container py-5">
|
||||
<div class="row g-4 text-center">
|
||||
<div class="col-md-4">
|
||||
<div class="card h-100 p-4">
|
||||
<!-- Stats Row -->
|
||||
<div class="row g-4 mb-4">
|
||||
<!-- Active Workers Card -->
|
||||
<div class="col-xl-4 col-md-6">
|
||||
<div class="card border-0 shadow-sm h-100 py-2" style="border-left: 4px solid #10b981 !important;">
|
||||
<div class="card-body">
|
||||
<h3 class="h1 text-primary mb-3">{{ total_workers|default:"0" }}</h3>
|
||||
<h5 class="card-title">Active Workers</h5>
|
||||
<p class="card-text text-muted">Field workers registered in the system.</p>
|
||||
<div class="row no-gutters align-items-center">
|
||||
<div class="col me-2">
|
||||
<div class="text-xs font-weight-bold text-uppercase mb-1" style="color: #10b981;">
|
||||
Active Workers</div>
|
||||
<div class="h5 mb-0 font-weight-bold text-gray-800">{{ total_workers|default:"0" }}</div>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<i class="fas fa-users fa-2x text-secondary opacity-50"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card h-100 p-4">
|
||||
<div class="card-body">
|
||||
<h3 class="h1 text-primary mb-3">{{ total_projects|default:"0" }}</h3>
|
||||
<h5 class="card-title">Projects</h5>
|
||||
<p class="card-text text-muted">Ongoing solar farm foundation projects.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="card h-100 p-4">
|
||||
<div class="card-body">
|
||||
<h3 class="h1 text-primary mb-3">{{ today_attendance|default:"0" }}</h3>
|
||||
<h5 class="card-title">Today's Attendance</h5>
|
||||
<p class="card-text text-muted">Workers logged for today across all sites.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="container py-5 bg-white rounded-3 shadow-sm mb-5">
|
||||
<div class="row align-items-center">
|
||||
<div class="col-lg-6">
|
||||
<h2 class="mb-4">Streamlined Attendance Tracking</h2>
|
||||
<p class="text-muted mb-4">Supervisors can now quickly log attendance directly from their mobile devices while on-site. Select a whole team with one click or pick individual workers for each project.</p>
|
||||
<ul class="list-unstyled mb-4">
|
||||
<li class="mb-2">✅ Real-time attendance logging</li>
|
||||
<li class="mb-2">✅ Integrated overtime calculations</li>
|
||||
<li class="mb-2">✅ Instant team selection</li>
|
||||
<li class="mb-2">✅ Offline-first field record management</li>
|
||||
</ul>
|
||||
<a href="{% url 'attendance_log' %}" class="btn btn-primary px-4 py-2">Get Started</a>
|
||||
<!-- Projects Card -->
|
||||
<div class="col-xl-4 col-md-6">
|
||||
<div class="card border-0 shadow-sm h-100 py-2" style="border-left: 4px solid #3b82f6 !important;">
|
||||
<div class="card-body">
|
||||
<div class="row no-gutters align-items-center">
|
||||
<div class="col me-2">
|
||||
<div class="text-xs font-weight-bold text-uppercase mb-1" style="color: #3b82f6;">
|
||||
Active Projects</div>
|
||||
<div class="h5 mb-0 font-weight-bold text-gray-800">{{ total_projects|default:"0" }}</div>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<i class="fas fa-hard-hat fa-2x text-secondary opacity-50"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-lg-6">
|
||||
<img src="https://images.pexels.com/photos/159306/construction-site-build-construction-worker-159306.jpeg?auto=compress&cs=tinysrgb&w=800" alt="Construction Worker" class="img-fluid rounded-3 shadow">
|
||||
|
||||
<!-- Today's Attendance Card -->
|
||||
<div class="col-xl-4 col-md-6">
|
||||
<div class="card border-0 shadow-sm h-100 py-2" style="border-left: 4px solid #f59e0b !important;">
|
||||
<div class="card-body">
|
||||
<div class="row no-gutters align-items-center">
|
||||
<div class="col me-2">
|
||||
<div class="text-xs font-weight-bold text-uppercase mb-1" style="color: #f59e0b;">
|
||||
Today's Logs</div>
|
||||
<div class="h5 mb-0 font-weight-bold text-gray-800">{{ today_attendance|default:"0" }}</div>
|
||||
</div>
|
||||
<div class="col-auto">
|
||||
<i class="fas fa-clipboard-check fa-2x text-secondary opacity-50"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{% endblock %}
|
||||
|
||||
<!-- Content Row -->
|
||||
<div class="row">
|
||||
<div class="col-lg-12 mb-4">
|
||||
<div class="card shadow-sm border-0 mb-4">
|
||||
<div class="card-header py-3 bg-white d-flex flex-row align-items-center justify-content-between">
|
||||
<h6 class="m-0 font-weight-bold" style="color: #0f172a;">Recent Activity</h6>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p class="text-muted mb-0">No recent activity to show yet. Start by logging today's attendance!</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
32
core/templates/registration/login.html
Normal file
32
core/templates/registration/login.html
Normal file
@ -0,0 +1,32 @@
|
||||
{% extends "base.html" %}
|
||||
|
||||
{% block content %}
|
||||
<div class="container d-flex justify-content-center align-items-center min-vh-100">
|
||||
<div class="card shadow-sm" style="width: 100%; max-width: 400px; border-radius: 12px; border: none;">
|
||||
<div class="card-body p-5">
|
||||
<h2 class="text-center mb-4" style="font-family: 'Poppins', sans-serif; font-weight: 700;">
|
||||
<span style="color: #10b981;">Fox</span>Fitt
|
||||
</h2>
|
||||
|
||||
{% if form.errors %}
|
||||
<div class="alert alert-danger" role="alert">
|
||||
Your username and password didn't match. Please try again.
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<form method="post" action="{% url 'login' %}">
|
||||
{% csrf_token %}
|
||||
<div class="mb-3">
|
||||
<label for="id_username" class="form-label" style="font-family: 'Inter', sans-serif; font-weight: 500;">Username</label>
|
||||
<input type="text" name="username" class="form-control form-control-lg" id="id_username" required autofocus style="border-radius: 8px;">
|
||||
</div>
|
||||
<div class="mb-4">
|
||||
<label for="id_password" class="form-label" style="font-family: 'Inter', sans-serif; font-weight: 500;">Password</label>
|
||||
<input type="password" name="password" class="form-control form-control-lg" id="id_password" required style="border-radius: 8px;">
|
||||
</div>
|
||||
<button type="submit" class="btn btn-lg w-100 text-white" style="background-color: #10b981; border: none; border-radius: 8px; font-weight: 600;">Login</button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% endblock %}
|
||||
@ -2,6 +2,6 @@ from django.urls import path
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
path('', views.index, name='index'),
|
||||
path('', views.index, name='home'),
|
||||
path('attendance/log/', views.attendance_log, name='attendance_log'),
|
||||
]
|
||||
@ -3,7 +3,10 @@ from django.utils import timezone
|
||||
from .models import Worker, Project, WorkLog, Team
|
||||
from .forms import AttendanceLogForm
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.decorators import login_required
|
||||
|
||||
# Home view for the dashboard
|
||||
@login_required
|
||||
def index(request):
|
||||
total_workers = Worker.objects.filter(active=True).count()
|
||||
total_projects = Project.objects.filter(active=True).count()
|
||||
@ -16,14 +19,16 @@ def index(request):
|
||||
}
|
||||
return render(request, 'core/index.html', context)
|
||||
|
||||
# View for logging attendance
|
||||
@login_required
|
||||
def attendance_log(request):
|
||||
if request.method == 'POST':
|
||||
form = AttendanceLogForm(request.POST)
|
||||
if form.is_valid():
|
||||
form.save()
|
||||
messages.success(request, 'Attendance logged successfully!')
|
||||
return redirect('index')
|
||||
return redirect('home')
|
||||
else:
|
||||
form = AttendanceLogForm(initial={'date': timezone.now().date()})
|
||||
|
||||
return render(request, 'core/attendance_log.html', {'form': form})
|
||||
return render(request, 'core/attendance_log.html', {'form': form})
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user