basic dashboard
This commit is contained in:
parent
26e9533758
commit
cd0902b381
BIN
assets/pasted-20251217-191304-2ce2b104.png
Normal file
BIN
assets/pasted-20251217-191304-2ce2b104.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 76 KiB |
BIN
assets/vm-shot-2025-12-17T19-12-54-230Z.jpg
Normal file
BIN
assets/vm-shot-2025-12-17T19-12-54-230Z.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
Binary file not shown.
Binary file not shown.
@ -30,15 +30,22 @@
|
|||||||
</div>
|
</div>
|
||||||
<nav class="sidebar-nav">
|
<nav class="sidebar-nav">
|
||||||
<ul>
|
<ul>
|
||||||
<li class="active"><a href="#"><i data-feather="home"></i> Dashboard</a></li>
|
<li class="{% if request.path == '/' %}active{% endif %}"><a href="{% url 'index' %}"><i data-feather="home"></i> Dashboard</a></li>
|
||||||
<li><a href="#"><i data-feather="briefcase"></i> Projects</a></li>
|
<li class="{% if '/projects' in request.path %}active{% endif %}"><a href="{% url 'projects' %}"><i data-feather="briefcase"></i> Projects</a></li>
|
||||||
<li><a href="#"><i data-feather="file-text"></i> Invoices</a></li>
|
<li><a href="#"><i data-feather="file-text"></i> Invoices</a></li>
|
||||||
<li><a href="#"><i data-feather="users"></i> Clients</a></li>
|
<li><a href="#"><i data-feather="users"></i> Clients</a></li>
|
||||||
<li><a href="#"><i data-feather="settings"></i> Settings</a></li>
|
<li><a href="#"><i data-feather="settings"></i> Settings</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
<ul class="auth-nav">
|
<ul class="auth-nav">
|
||||||
{% if user.is_authenticated %}
|
{% if user.is_authenticated %}
|
||||||
<li><a href="{% url 'logout' %}"><i data-feather="log-out"></i> Logout</a></li>
|
<li>
|
||||||
|
<a href="{% url 'logout' %}" onclick="event.preventDefault(); document.getElementById('logout-form').submit();">
|
||||||
|
<i data-feather="log-out"></i> Logout
|
||||||
|
</a>
|
||||||
|
<form id="logout-form" action="{% url 'logout' %}" method="post" style="display: none;">
|
||||||
|
{% csrf_token %}
|
||||||
|
</form>
|
||||||
|
</li>
|
||||||
{% else %}
|
{% else %}
|
||||||
<li><a href="{% url 'login' %}"><i data-feather="log-in"></i> Login</a></li>
|
<li><a href="{% url 'login' %}"><i data-feather="log-in"></i> Login</a></li>
|
||||||
<li><a href="{% url 'register' %}"><i data-feather="user-plus"></i> Register</a></li>
|
<li><a href="{% url 'register' %}"><i data-feather="user-plus"></i> Register</a></li>
|
||||||
|
|||||||
@ -17,7 +17,51 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="analytics-grid">
|
||||||
|
<div class="stat-card">
|
||||||
|
<div class="stat-info">
|
||||||
|
<h3>Total projects</h3>
|
||||||
|
<p class="stat-number">{{ total_projects }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="stat-icon">
|
||||||
|
<i data-feather="archive"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card planned">
|
||||||
|
<div class="stat-info">
|
||||||
|
<h3>Planned</h3>
|
||||||
|
<p class="stat-number">{{ planned_projects }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="stat-icon">
|
||||||
|
<i data-feather="calendar"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card in-progress">
|
||||||
|
<div class="stat-info">
|
||||||
|
<h3>In progress</h3>
|
||||||
|
<p class="stat-number">{{ in_progress_projects }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="stat-icon">
|
||||||
|
<i data-feather="trending-up"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="stat-card completed">
|
||||||
|
<div class="stat-info">
|
||||||
|
<h3>Completed</h3>
|
||||||
|
<p class="stat-number">{{ completed_projects }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="stat-icon">
|
||||||
|
<i data-feather="check-circle"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="content-grid">
|
<div class="content-grid">
|
||||||
|
{% if request.path == '/projects/' %}
|
||||||
|
<div class="project-list-header">
|
||||||
|
<h2>Wszystkie projekty</h2>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
{% if projects %}
|
{% if projects %}
|
||||||
{% for project in projects %}
|
{% for project in projects %}
|
||||||
<div class="project-card">
|
<div class="project-card">
|
||||||
@ -30,15 +74,7 @@
|
|||||||
<p><strong>Okres:</strong> {{ project.start_date|date:"d M Y" }} - {{ project.end_date|date:"d M Y" }}</p>
|
<p><strong>Okres:</strong> {{ project.start_date|date:"d M Y" }} - {{ project.end_date|date:"d M Y" }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer">
|
<div class="card-footer">
|
||||||
<div class="participants">
|
|
||||||
<span>Uczestnicy</span>
|
|
||||||
<div class="avatars">
|
|
||||||
<!-- Placeholder avatars -->
|
|
||||||
<img src="https://i.pravatar.cc/32?u=a" alt="Avatar">
|
|
||||||
<img src="https://i.pravatar.cc/32?u=b" alt="Avatar">
|
|
||||||
<img src="https://i.pravatar.cc/32?u=c" alt="Avatar">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% if user.is_authenticated %}
|
{% if user.is_authenticated %}
|
||||||
<a href="{% url 'edit_project' project.id %}" class="btn-view">Edit</a>
|
<a href="{% url 'edit_project' project.id %}" class="btn-view">Edit</a>
|
||||||
<a href="{% url 'delete_project' project.id %}" class="btn-view">Delete</a>
|
<a href="{% url 'delete_project' project.id %}" class="btn-view">Delete</a>
|
||||||
|
|||||||
52
core/templates/core/projects.html
Normal file
52
core/templates/core/projects.html
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
|
{% block title %}Projekty - webFirma{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="main-header">
|
||||||
|
<h1>Projekty</h1>
|
||||||
|
<div class="header-actions">
|
||||||
|
<div class="search-bar">
|
||||||
|
<i data-feather="search"></i>
|
||||||
|
<input type="text" placeholder="Search projects...">
|
||||||
|
</div>
|
||||||
|
{% if user.is_authenticated %}
|
||||||
|
<a href="{% url 'add_project' %}" class="btn btn-primary"><i data-feather="plus"></i> Dodaj projekt</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content-grid">
|
||||||
|
{% if projects %}
|
||||||
|
{% for project in projects %}
|
||||||
|
<div class="project-card">
|
||||||
|
<div class="card-header">
|
||||||
|
<h3>{{ project.name }}</h3>
|
||||||
|
<span class="badge status-{{ project.status|lower }}">{{ project.get_status_display }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<p><strong>Klient:</strong> {{ project.client }}</p>
|
||||||
|
<p><strong>Okres:</strong> {{ project.start_date|date:"d M Y" }} - {{ project.end_date|date:"d M Y" }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer">
|
||||||
|
|
||||||
|
{% if user.is_authenticated %}
|
||||||
|
<a href="{% url 'edit_project' project.id %}" class="btn-view">Edit</a>
|
||||||
|
<a href="{% url 'delete_project' project.id %}" class="btn-view">Delete</a>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% else %}
|
||||||
|
<div class="empty-state">
|
||||||
|
<div class="empty-state-icon">
|
||||||
|
<i data-feather="briefcase"></i>
|
||||||
|
</div>
|
||||||
|
<h2>Brak projektów</h2>
|
||||||
|
<p>Nie masz jeszcze żadnych projektów. Dodaj swój pierwszy projekt, aby rozpocząć.</p>
|
||||||
|
<a href="{% url 'add_project' %}" class="btn btn-primary">Dodaj projekt</a>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
@ -1,9 +1,10 @@
|
|||||||
from django.urls import path
|
from django.urls import path
|
||||||
from .views import index, add_project, register, edit_project, delete_project
|
from .views import index, add_project, register, edit_project, delete_project, projects
|
||||||
from django.contrib.auth.views import LoginView, LogoutView
|
from django.contrib.auth.views import LoginView, LogoutView
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path('', index, name='index'),
|
path('', index, name='index'),
|
||||||
|
path('projects/', projects, name='projects'),
|
||||||
path('add-project/', add_project, name='add_project'),
|
path('add-project/', add_project, name='add_project'),
|
||||||
path('register/', register, name='register'),
|
path('register/', register, name='register'),
|
||||||
path('login/', LoginView.as_view(template_name='core/login.html'), name='login'),
|
path('login/', LoginView.as_view(template_name='core/login.html'), name='login'),
|
||||||
|
|||||||
@ -9,7 +9,20 @@ from .forms import ProjectForm
|
|||||||
def index(request):
|
def index(request):
|
||||||
if request.user.is_authenticated:
|
if request.user.is_authenticated:
|
||||||
projects = Project.objects.all().order_by('-start_date')
|
projects = Project.objects.all().order_by('-start_date')
|
||||||
return render(request, 'core/index.html', {'projects': projects})
|
|
||||||
|
total_projects = projects.count()
|
||||||
|
planned_projects = projects.filter(status='planowany').count()
|
||||||
|
in_progress_projects = projects.filter(status='realizowany').count()
|
||||||
|
completed_projects = projects.filter(status='zakonczony').count()
|
||||||
|
|
||||||
|
context = {
|
||||||
|
'projects': projects,
|
||||||
|
'total_projects': total_projects,
|
||||||
|
'planned_projects': planned_projects,
|
||||||
|
'in_progress_projects': in_progress_projects,
|
||||||
|
'completed_projects': completed_projects,
|
||||||
|
}
|
||||||
|
return render(request, 'core/index.html', context)
|
||||||
else:
|
else:
|
||||||
return render(request, 'core/landing.html')
|
return render(request, 'core/landing.html')
|
||||||
|
|
||||||
@ -52,3 +65,10 @@ def register(request):
|
|||||||
else:
|
else:
|
||||||
form = UserCreationForm()
|
form = UserCreationForm()
|
||||||
return render(request, 'core/register.html', {'form': form})
|
return render(request, 'core/register.html', {'form': form})
|
||||||
|
|
||||||
|
def projects(request):
|
||||||
|
if request.user.is_authenticated:
|
||||||
|
projects = Project.objects.all().order_by('-start_date')
|
||||||
|
return render(request, 'core/projects.html', {'projects': projects})
|
||||||
|
else:
|
||||||
|
return render(request, 'core/landing.html')
|
||||||
@ -320,3 +320,62 @@ body {
|
|||||||
padding: 14px 28px;
|
padding: 14px 28px;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Analytics Cards */
|
||||||
|
.analytics-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
|
||||||
|
gap: 24px;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card {
|
||||||
|
background-color: var(--white-color);
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
padding: 24px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
border-left: 4px solid var(--primary-color);
|
||||||
|
box-shadow: var(--card-shadow);
|
||||||
|
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card:hover {
|
||||||
|
transform: translateY(-4px);
|
||||||
|
box-shadow: 0 8px 20px rgba(0,0,0,0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card .stat-info h3 {
|
||||||
|
margin: 0 0 4px 0;
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--dark-grey);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card .stat-info .stat-number {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card .stat-icon {
|
||||||
|
color: var(--dark-grey);
|
||||||
|
}
|
||||||
|
.stat-card .stat-icon svg {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card.planned {
|
||||||
|
border-left-color: #EF6C00;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card.in-progress {
|
||||||
|
border-left-color: #673AB7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card.completed {
|
||||||
|
border-left-color: #2E7D32;
|
||||||
|
}
|
||||||
|
|||||||
@ -320,3 +320,62 @@ body {
|
|||||||
padding: 14px 28px;
|
padding: 14px 28px;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Analytics Cards */
|
||||||
|
.analytics-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
|
||||||
|
gap: 24px;
|
||||||
|
margin-bottom: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card {
|
||||||
|
background-color: var(--white-color);
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
padding: 24px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
border-left: 4px solid var(--primary-color);
|
||||||
|
box-shadow: var(--card-shadow);
|
||||||
|
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card:hover {
|
||||||
|
transform: translateY(-4px);
|
||||||
|
box-shadow: 0 8px 20px rgba(0,0,0,0.08);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card .stat-info h3 {
|
||||||
|
margin: 0 0 4px 0;
|
||||||
|
font-size: 14px;
|
||||||
|
color: var(--dark-grey);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card .stat-info .stat-number {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 28px;
|
||||||
|
font-weight: 700;
|
||||||
|
color: var(--text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card .stat-icon {
|
||||||
|
color: var(--dark-grey);
|
||||||
|
}
|
||||||
|
.stat-card .stat-icon svg {
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card.planned {
|
||||||
|
border-left-color: #EF6C00;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card.in-progress {
|
||||||
|
border-left-color: #673AB7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card.completed {
|
||||||
|
border-left-color: #2E7D32;
|
||||||
|
}
|
||||||
|
|||||||
BIN
staticfiles/pasted-20251217-191304-2ce2b104.png
Normal file
BIN
staticfiles/pasted-20251217-191304-2ce2b104.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 76 KiB |
BIN
staticfiles/vm-shot-2025-12-17T19-12-54-230Z.jpg
Normal file
BIN
staticfiles/vm-shot-2025-12-17T19-12-54-230Z.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 31 KiB |
Loading…
x
Reference in New Issue
Block a user