This commit is contained in:
Flatlogic Bot 2025-12-17 19:53:37 +00:00
parent cd0902b381
commit 5b190bc3f3
25 changed files with 650 additions and 67 deletions

5
cookies.txt Normal file
View File

@ -0,0 +1,5 @@
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
127.0.0.1 FALSE / TRUE 1797450401 csrftoken gNby2S5EHlDB1Xsw0eGC7JVKq4F45wQW

View File

@ -1,3 +1,14 @@
from django.contrib import admin
from .models import Project, Client
# Register your models here.
@admin.register(Client)
class ClientAdmin(admin.ModelAdmin):
list_display = ('name', 'email', 'phone')
search_fields = ('name',)
@admin.register(Project)
class ProjectAdmin(admin.ModelAdmin):
list_display = ('name', 'client', 'start_date', 'end_date', 'status')
list_filter = ('status', 'client')
search_fields = ('name', 'client__name')
autocomplete_fields = ('client',)

View File

@ -1,5 +1,5 @@
from django import forms
from .models import Project
from .models import Project, Client
class ProjectForm(forms.ModelForm):
class Meta:
@ -7,8 +7,18 @@ class ProjectForm(forms.ModelForm):
fields = ['name', 'client', 'start_date', 'end_date', 'status']
widgets = {
'name': forms.TextInput(attrs={'class': 'form-control'}),
'client': forms.TextInput(attrs={'class': 'form-control'}),
'client': forms.Select(attrs={'class': 'form-select'}),
'start_date': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}),
'end_date': forms.DateInput(attrs={'class': 'form-control', 'type': 'date'}),
'status': forms.Select(attrs={'class': 'form-select'}),
}
class ClientForm(forms.ModelForm):
class Meta:
model = Client
fields = ['name', 'email', 'phone']
widgets = {
'name': forms.TextInput(attrs={'class': 'form-control'}),
'email': forms.EmailInput(attrs={'class': 'form-control'}),
'phone': forms.TextInput(attrs={'class': 'form-control'}),
}

View File

@ -0,0 +1,93 @@
# Generated by Django 5.2.7 on 2025-12-17 19:22
from django.db import migrations, models
import django.db.models.deletion
def migrate_clients_forward(apps, schema_editor):
Project = apps.get_model('core', 'Project')
Client = apps.get_model('core', 'Client')
for project in Project.objects.all():
client_name = getattr(project, 'client_temp', None)
if client_name:
client, created = Client.objects.get_or_create(name=client_name)
project.client = client
project.save()
def migrate_clients_backward(apps, schema_editor):
# This is a one-way migration, but we can try to restore the old values
Project = apps.get_model('core', 'Project')
for project in Project.objects.all():
if project.client:
project.client_temp = project.client.name
project.save()
class Migration(migrations.Migration):
dependencies = [
('core', '0001_initial'),
]
operations = [
# 1. Create the new Client model
migrations.CreateModel(
name='Client',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=200, verbose_name='Client Name')),
('email', models.EmailField(blank=True, max_length=200, null=True, verbose_name='Email')),
('phone', models.CharField(blank=True, max_length=20, null=True, verbose_name='Phone')),
],
),
# 2. Rename the existing 'client' CharField to a temporary field
migrations.RenameField(
model_name='project',
old_name='client',
new_name='client_temp',
),
# 3. Add the new 'client' ForeignKey field, allowing it to be null for now
migrations.AddField(
model_name='project',
name='client',
field=models.ForeignKey(
to='core.Client',
on_delete=django.db.models.deletion.CASCADE,
related_name='projects',
verbose_name='Client',
null=True, # Allow null during migration
blank=True
),
),
# 4. Run the Python script to migrate the data
migrations.RunPython(migrate_clients_forward, migrate_clients_backward),
# 5. Remove the temporary CharField
migrations.RemoveField(
model_name='project',
name='client_temp',
),
# 6. Alter other fields (translations)
migrations.AlterField(
model_name='project',
name='end_date',
field=models.DateField(verbose_name='End Date'),
),
migrations.AlterField(
model_name='project',
name='name',
field=models.CharField(max_length=200, verbose_name='Project Name'),
),
migrations.AlterField(
model_name='project',
name='start_date',
field=models.DateField(verbose_name='Start Date'),
),
migrations.AlterField(
model_name='project',
name='status',
field=models.CharField(choices=[('planning', 'Planning'), ('in_progress', 'In Progress'), ('completed', 'Completed')], default='planning', max_length=20, verbose_name='Status'),
),
]

View File

@ -1,17 +1,25 @@
from django.db import models
class Client(models.Model):
name = models.CharField(max_length=200, verbose_name="Client Name")
email = models.EmailField(max_length=200, verbose_name="Email", blank=True, null=True)
phone = models.CharField(max_length=20, verbose_name="Phone", blank=True, null=True)
def __str__(self):
return self.name
class Project(models.Model):
STATUS_CHOICES = [
('planowany', 'Planowany'),
('realizowany', 'Realizowany'),
('zakonczony', 'Zakończony'),
('planning', 'Planning'),
('in_progress', 'In Progress'),
('completed', 'Completed'),
]
name = models.CharField(max_length=200, verbose_name="Nazwa projektu")
client = models.CharField(max_length=200, verbose_name="Kontrahent")
start_date = models.DateField(verbose_name="Data rozpoczęcia")
end_date = models.DateField(verbose_name="Data zakończenia")
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='planowany', verbose_name="Status")
name = models.CharField(max_length=200, verbose_name="Project Name")
client = models.ForeignKey(Client, on_delete=models.CASCADE, related_name='projects', verbose_name="Client", null=True, blank=True)
start_date = models.DateField(verbose_name="Start Date")
end_date = models.DateField(verbose_name="End Date")
status = models.CharField(max_length=20, choices=STATUS_CHOICES, default='planning', verbose_name="Status")
def __str__(self):
return self.name

View File

@ -33,7 +33,7 @@
<li class="{% if request.path == '/' %}active{% endif %}"><a href="{% url 'index' %}"><i data-feather="home"></i> Dashboard</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="users"></i> Clients</a></li>
<li><a href="{% url 'clients' %}"><i data-feather="users"></i> Clients</a></li>
<li><a href="#"><i data-feather="settings"></i> Settings</a></li>
</ul>
<ul class="auth-nav">

View File

@ -14,6 +14,7 @@
<meta property="twitter:image" content="{{ project_image_url }}">
{% endif %}
{% load static %}
<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;700&display=swap" rel="stylesheet">
@ -37,6 +38,7 @@
{% block content %}{% endblock %}
</main>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<script>
feather.replace()
</script>

View File

@ -0,0 +1,48 @@
{% extends 'base.html' %}
{% load static %}
{% block title %}Add Client - webFirma{% endblock %}
{% block content %}
<div class="container mt-5">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card shadow-sm">
<div class="card-header bg-primary text-white">
<h4 class="mb-0">Create a New Client</h4>
</div>
<div class="card-body">
<form method="post">
{% csrf_token %}
<div class="form-floating mb-3">
{{ form.name }}
<label for="{{ form.name.id_for_label }}">Name</label>
</div>
<div class="form-floating mb-3">
{{ form.email }}
<label for="{{ form.email.id_for_label }}">Email</label>
</div>
<div class="form-floating mb-3">
{{ form.phone }}
<label for="{{ form.phone.id_for_label }}">Phone</label>
</div>
<div class="d-flex justify-content-end">
<a href="{% url 'clients' %}" class="btn btn-secondary me-2">Cancel</a>
<button type="submit" class="btn btn-primary">Save Client</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<style>
.form-floating .form-control {
height: calc(3.5rem + 2px);
padding: 1rem;
}
.form-floating > label {
padding: 1rem;
}
</style>
{% endblock %}

View File

@ -1,22 +1,68 @@
{% extends 'base.html' %}
{% load static %}
{% block title %}Dodaj Projekt - webFirma{% endblock %}
{% block title %}Add Project - webFirma{% endblock %}
{% block content %}
<div class="main-header">
<h1>Dodaj Nowy Projekt</h1>
</div>
<div class="content-grid">
<div class="project-card">
<div class="card-body">
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Zapisz projekt</button>
</form>
<div class="container mt-5">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card shadow-sm">
<div class="card-header bg-primary text-white">
<h4 class="mb-0">Create a New Project</h4>
</div>
<div class="card-body">
<form method="post">
{% csrf_token %}
<div class="row">
<div class="col-md-6 mb-3">
<div class="form-floating">
{{ form.name }}
<label for="{{ form.name.id_for_label }}">Project Name</label>
</div>
</div>
<div class="col-md-6 mb-3">
<div class="form-floating">
{{ form.client }}
<label for="{{ form.client.id_for_label }}">Client</label>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<div class="form-floating">
{{ form.start_date }}
<label for="{{ form.start_date.id_for_label }}">Start Date</label>
</div>
</div>
<div class="col-md-6 mb-3">
<div class="form-floating">
{{ form.end_date }}
<label for="{{ form.end_date.id_for_label }}">End Date</label>
</div>
</div>
</div>
<div class="form-floating mb-3">
{{ form.status }}
<label for="{{ form.status.id_for_label }}">Status</label>
</div>
<div class="d-flex justify-content-end">
<a href="{% url 'projects' %}" class="btn btn-secondary me-2">Cancel</a>
<button type="submit" class="btn btn-primary">Save Project</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
<style>
.form-floating .form-control, .form-floating .form-select {
height: calc(3.5rem + 2px);
padding: 1rem;
}
.form-floating > label {
padding: 1rem;
}
</style>
{% endblock %}

View File

@ -0,0 +1,45 @@
{% extends 'base.html' %}
{% load static %}
{% block title %}Clients - webFirma{% endblock %}
{% block content %}
<div class="main-header">
<div class="main-header-left">
<h1>Clients</h1>
<p>You have {{ total_clients }} clients</p>
</div>
<div class="header-actions">
<div class="search-bar">
<i data-feather="search"></i>
<input type="text" placeholder="Search clients...">
</div>
<a href="{% url 'add_client' %}" class="btn btn-primary">Add client</a>
</div>
</div>
<div class="content-grid">
{% if clients %}
{% for client in clients %}
<div class="project-card">
<div class="card-header">
<h3>{{ client.name }}</h3>
</div>
<div class="card-body">
<p><strong>Email:</strong> {{ client.email }}</p>
<p><strong>Phone:</strong> {{ client.phone_number }}</p>
</div>
</div>
{% endfor %}
{% else %}
<div class="empty-state">
<div class="empty-state-icon">
<i data-feather="users"></i>
</div>
<h2>No clients yet</h2>
<p>You don't have any clients yet. Click the button to add your first client.</p>
<a href="{% url 'add_client' %}" class="btn btn-primary">Add client</a>
</div>
{% endif %}
</div>
{% endblock %}

View File

@ -1,11 +1,11 @@
{% extends 'base.html' %}
{% load static %}
{% block title %}Edytuj Projekt - webFirma{% endblock %}
{% block title %}Edit Project - webFirma{% endblock %}
{% block content %}
<div class="main-header">
<h1>Edytuj Projekt</h1>
<h1>Edit Project</h1>
</div>
<div class="content-grid">
@ -14,7 +14,7 @@
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Zapisz zmiany</button>
<button type="submit" class="btn btn-primary">Save changes</button>
</form>
</div>
</div>

View File

@ -12,7 +12,7 @@
<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>
<a href="{% url 'add_project' %}" class="btn btn-primary"><i data-feather="plus"></i> Add project</a>
{% endif %}
</div>
</div>
@ -59,7 +59,7 @@
<div class="content-grid">
{% if request.path == '/projects/' %}
<div class="project-list-header">
<h2>Wszystkie projekty</h2>
<h2>All Projects</h2>
</div>
{% endif %}
{% if projects %}
@ -70,8 +70,8 @@
<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>
<p><strong>Client:</strong> {{ project.client.name }}</p>
<p><strong>Period:</strong> {{ project.start_date|date:"d M Y" }} - {{ project.end_date|date:"d M Y" }}</p>
</div>
<div class="card-footer">
@ -87,9 +87,9 @@
<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>
<h2>No projects yet</h2>
<p>You don't have any projects yet. Add your first project to get started.</p>
<a href="{% url 'add_project' %}" class="btn btn-primary">Add project</a>
</div>
{% endif %}
</div>

View File

@ -1,14 +1,51 @@
{% extends 'base_public.html' %}
{% load static %}
{% block title %}Login - webFirma{% endblock %}
{% block content %}
<div class="container">
<h2>Login</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Login</button>
</form>
<div class="container-fluid">
<div class="row min-vh-100">
<div class="col-md-6 d-flex flex-column justify-content-center align-items-center text-white" style="background: linear-gradient(45deg, #007bff, #0056b3);">
<div class="text-center p-5">
<h1 class="display-4 font-weight-bold">webFirma</h1>
<p class="lead mt-3">Streamline your client and project management.</p>
</div>
</div>
<div class="col-md-6 d-flex justify-content-center align-items-center">
<div class="card shadow-lg p-5" style="width: 100%; max-width: 450px;">
<div class="card-body">
<h2 class="card-title text-center mb-4">Login</h2>
<form method="post">
{% csrf_token %}
<div class="form-floating mb-3">
{{ form.username }}
<label for="{{ form.username.id_for_label }}">Username</label>
</div>
<div class="form-floating mb-3">
{{ form.password }}
<label for="{{ form.password.id_for_label }}">Password</label>
</div>
<div class="d-grid">
<button type="submit" class="btn btn-primary btn-lg">Login</button>
</div>
</form>
<div class="text-center mt-3">
<p>Don't have an account? <a href="{% url 'register' %}">Register here</a></p>
</div>
</div>
</div>
</div>
</div>
</div>
<style>
.form-floating .form-control {
height: calc(3.5rem + 2px);
padding: 1rem;
}
.form-floating > label {
padding: 1rem;
}
</style>
{% endblock %}

View File

@ -1,18 +1,18 @@
{% extends 'base.html' %}
{% load static %}
{% block title %}Projekty - webFirma{% endblock %}
{% block title %}Projects - webFirma{% endblock %}
{% block content %}
<div class="main-header">
<h1>Projekty</h1>
<h1>Projects</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>
<a href="{% url 'add_project' %}" class="btn btn-primary"><i data-feather="plus"></i> Add project</a>
{% endif %}
</div>
</div>
@ -26,8 +26,8 @@
<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>
<p><strong>Client:</strong> {{ project.client.name }}</p>
<p><strong>Period:</strong> {{ project.start_date|date:"d M Y" }} - {{ project.end_date|date:"d M Y" }}</p>
</div>
<div class="card-footer">
@ -43,9 +43,9 @@
<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>
<h2>No projects yet</h2>
<p>You don't have any projects yet. Add your first project to get started.</p>
<a href="{% url 'add_project' %}" class="btn btn-primary">Add project</a>
</div>
{% endif %}
</div>

View File

@ -1,14 +1,59 @@
{% extends 'base_public.html' %}
{% load static %}
{% block title %}Register - webFirma{% endblock %}
{% block content %}
<div class="container">
<h2>Register</h2>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Register</button>
</form>
<div class="container-fluid">
<div class="row min-vh-100">
<div class="col-md-6 d-flex flex-column justify-content-center align-items-center text-white" style="background: linear-gradient(45deg, #007bff, #0056b3);">
<div class="text-center p-5">
<h1 class="display-4 font-weight-bold">webFirma</h1>
<p class="lead mt-3">Join us and streamline your workflow.</p>
</div>
</div>
<div class="col-md-6 d-flex justify-content-center align-items-center">
<div class="card shadow-lg p-5" style="width: 100%; max-width: 450px;">
<div class="card-body">
<h2 class="card-title text-center mb-4">Create Account</h2>
<form method="post">
{% csrf_token %}
<div class="form-floating mb-3">
{{ form.username }}
<label for="{{ form.username.id_for_label }}">Username</label>
</div>
<div class="form-floating mb-3">
{{ form.email }}
<label for="{{ form.email.id_for_label }}">Email</label>
</div>
<div class="form-floating mb-3">
{{ form.password }}
<label for="{{ form.password.id_for_label }}">Password</label>
</div>
<div class="form-floating mb-3">
{{ form.password2 }}
<label for="{{ form.password2.id_for_label }}">Confirm Password</label>
</div>
<div class="d-grid">
<button type="submit" class="btn btn-primary btn-lg">Register</button>
</div>
</form>
<div class="text-center mt-3">
<p>Already have an account? <a href="{% url 'login' %}">Login here</a></p>
</div>
</div>
</div>
</div>
</div>
</div>
<style>
.form-floating .form-control {
height: calc(3.5rem + 2px);
padding: 1rem;
}
.form-floating > label {
padding: 1rem;
}
</style>
{% endblock %}

View File

@ -1,10 +1,12 @@
from django.urls import path
from .views import index, add_project, register, edit_project, delete_project, projects
from .views import index, add_project, register, edit_project, delete_project, projects, clients, add_client
from django.contrib.auth.views import LoginView, LogoutView
urlpatterns = [
path('', index, name='index'),
path('projects/', projects, name='projects'),
path('clients/', clients, name='clients'),
path('clients/add/', add_client, name='add_client'),
path('add-project/', add_project, name='add_project'),
path('register/', register, name='register'),
path('login/', LoginView.as_view(template_name='core/login.html'), name='login'),

View File

@ -3,17 +3,17 @@ from django.contrib.auth import login
from django.contrib.auth.decorators import login_required
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.views import LoginView, LogoutView
from .models import Project
from .forms import ProjectForm
from .models import Project, Client
from .forms import ProjectForm, ClientForm
def index(request):
if request.user.is_authenticated:
projects = Project.objects.all().order_by('-start_date')
projects = Project.objects.select_related("client").all().order_by('-start_date')
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()
planned_projects = projects.filter(status='planning').count()
in_progress_projects = projects.filter(status='in_progress').count()
completed_projects = projects.filter(status='completed').count()
context = {
'projects': projects,
@ -68,7 +68,26 @@ def register(request):
def projects(request):
if request.user.is_authenticated:
projects = Project.objects.all().order_by('-start_date')
projects = Project.objects.select_related("client").all().order_by('-start_date')
return render(request, 'core/projects.html', {'projects': projects})
else:
return render(request, 'core/landing.html')
return render(request, 'core/landing.html')
def clients(request):
if request.user.is_authenticated:
clients = Client.objects.all()
total_clients = clients.count()
return render(request, "core/clients.html", {"clients": clients, "total_clients": total_clients})
else:
return render(request, "core/landing.html")
@login_required
def add_client(request):
if request.method == 'POST':
form = ClientForm(request.POST)
if form.is_valid():
form.save()
return redirect('clients')
else:
form = ClientForm()
return render(request, 'core/add_client.html', {'form': form})

View File

@ -145,6 +145,21 @@ body {
background-color: var(--primary-dark);
}
.btn-secondary {
background-color: var(--white-color);
color: var(--text-color);
padding: 10px 16px;
border-radius: var(--border-radius);
text-decoration: none;
font-weight: 600;
display: inline-flex;
align-items: center;
gap: 8px;
border: 1px solid var(--medium-grey);
cursor: pointer;
transition: background-color 0.2s ease;
}
/* Project Cards */
.content-grid {
display: grid;
@ -379,3 +394,94 @@ body {
.stat-card.completed {
border-left-color: #2E7D32;
}
/* Auth Card */
.auth-card {
background-color: var(--white-color);
border-radius: var(--border-radius);
box-shadow: var(--card-shadow);
padding: 48px;
width: 100%;
max-width: 450px;
}
.auth-card-header h2 {
font-size: 24px;
font-weight: 700;
color: var(--primary-dark);
margin-bottom: 8px;
}
.auth-card-header p {
color: var(--dark-grey);
margin-bottom: 32px;
}
.auth-card form p {
margin-bottom: 16px;
}
.auth-card form label {
display: block;
margin-bottom: 8px;
font-weight: 600;
}
.auth-card form input {
width: 100%;
padding: 12px;
border-radius: var(--border-radius);
border: 1px solid var(--medium-grey);
font-size: 14px;
}
.auth-card form .btn-primary {
width: 100%;
justify-content: center;
padding: 14px;
font-size: 16px;
}
/* Form Card */
.form-card {
background-color: var(--white-color);
border-radius: var(--border-radius);
box-shadow: var(--card-shadow);
padding: 32px;
}
.form-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 24px;
}
.form-group {
margin-bottom: 16px;
}
.form-group.full-width {
grid-column: 1 / -1;
}
.form-group label {
display: block;
margin-bottom: 8px;
font-weight: 600;
}
.form-group input,
.form-group select {
width: 100%;
padding: 12px;
border-radius: var(--border-radius);
border: 1px solid var(--medium-grey);
font-size: 14px;
box-sizing: border-box;
}
.form-actions {
margin-top: 32px;
display: flex;
gap: 16px;
}

View File

@ -145,6 +145,21 @@ body {
background-color: var(--primary-dark);
}
.btn-secondary {
background-color: var(--white-color);
color: var(--text-color);
padding: 10px 16px;
border-radius: var(--border-radius);
text-decoration: none;
font-weight: 600;
display: inline-flex;
align-items: center;
gap: 8px;
border: 1px solid var(--medium-grey);
cursor: pointer;
transition: background-color 0.2s ease;
}
/* Project Cards */
.content-grid {
display: grid;
@ -379,3 +394,94 @@ body {
.stat-card.completed {
border-left-color: #2E7D32;
}
/* Auth Card */
.auth-card {
background-color: var(--white-color);
border-radius: var(--border-radius);
box-shadow: var(--card-shadow);
padding: 48px;
width: 100%;
max-width: 450px;
}
.auth-card-header h2 {
font-size: 24px;
font-weight: 700;
color: var(--primary-dark);
margin-bottom: 8px;
}
.auth-card-header p {
color: var(--dark-grey);
margin-bottom: 32px;
}
.auth-card form p {
margin-bottom: 16px;
}
.auth-card form label {
display: block;
margin-bottom: 8px;
font-weight: 600;
}
.auth-card form input {
width: 100%;
padding: 12px;
border-radius: var(--border-radius);
border: 1px solid var(--medium-grey);
font-size: 14px;
}
.auth-card form .btn-primary {
width: 100%;
justify-content: center;
padding: 14px;
font-size: 16px;
}
/* Form Card */
.form-card {
background-color: var(--white-color);
border-radius: var(--border-radius);
box-shadow: var(--card-shadow);
padding: 32px;
}
.form-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 24px;
}
.form-group {
margin-bottom: 16px;
}
.form-group.full-width {
grid-column: 1 / -1;
}
.form-group label {
display: block;
margin-bottom: 8px;
font-weight: 600;
}
.form-group input,
.form-group select {
width: 100%;
padding: 12px;
border-radius: var(--border-radius);
border: 1px solid var(--medium-grey);
font-size: 14px;
box-sizing: border-box;
}
.form-actions {
margin-top: 32px;
display: flex;
gap: 16px;
}