Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
012eaee40e |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,3 +1,9 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
|
from .models import Member
|
||||||
|
|
||||||
# Register your models here.
|
@admin.register(Member)
|
||||||
|
class MemberAdmin(admin.ModelAdmin):
|
||||||
|
list_display = ('full_name', 'email', 'role', 'status', 'join_date')
|
||||||
|
list_filter = ('role', 'status', 'join_date')
|
||||||
|
search_fields = ('full_name', 'email', 'notes')
|
||||||
|
list_per_page = 25
|
||||||
30
core/migrations/0001_initial.py
Normal file
30
core/migrations/0001_initial.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# Generated by Django 5.2.7 on 2026-02-24 00:57
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Member',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('full_name', models.CharField(max_length=255)),
|
||||||
|
('email', models.EmailField(max_length=254, unique=True)),
|
||||||
|
('phone', models.CharField(blank=True, max_length=20, null=True)),
|
||||||
|
('role', models.CharField(choices=[('STAFF', 'Staff'), ('BOARD', 'Board Member'), ('YOUTH_VOLUNTEER', 'Youth Volunteer')], default='STAFF', max_length=20)),
|
||||||
|
('status', models.CharField(choices=[('ACTIVE', 'Active'), ('INACTIVE', 'Inactive')], default='ACTIVE', max_length=10)),
|
||||||
|
('join_date', models.DateField(auto_now_add=True)),
|
||||||
|
('notes', models.TextField(blank=True, null=True)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'ordering': ['-join_date'],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
||||||
BIN
core/migrations/__pycache__/0001_initial.cpython-311.pyc
Normal file
BIN
core/migrations/__pycache__/0001_initial.cpython-311.pyc
Normal file
Binary file not shown.
Binary file not shown.
@ -1,3 +1,27 @@
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
# Create your models here.
|
class Member(models.Model):
|
||||||
|
ROLE_CHOICES = [
|
||||||
|
('STAFF', 'Staff'),
|
||||||
|
('BOARD', 'Board Member'),
|
||||||
|
('YOUTH_VOLUNTEER', 'Youth Volunteer'),
|
||||||
|
]
|
||||||
|
|
||||||
|
STATUS_CHOICES = [
|
||||||
|
('ACTIVE', 'Active'),
|
||||||
|
('INACTIVE', 'Inactive'),
|
||||||
|
]
|
||||||
|
|
||||||
|
full_name = models.CharField(max_length=255)
|
||||||
|
email = models.EmailField(unique=True)
|
||||||
|
phone = models.CharField(max_length=20, blank=True, null=True)
|
||||||
|
role = models.CharField(max_length=20, choices=ROLE_CHOICES, default='STAFF')
|
||||||
|
status = models.CharField(max_length=10, choices=STATUS_CHOICES, default='ACTIVE')
|
||||||
|
join_date = models.DateField(auto_now_add=True)
|
||||||
|
notes = models.TextField(blank=True, null=True)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.full_name} ({self.get_role_display()})"
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
ordering = ['-join_date']
|
||||||
@ -1,25 +1,53 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<title>{% block title %}Knowledge Base{% endblock %}</title>
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
{% if project_description %}
|
<title>{% block title %}TeamLink{% endblock %}</title>
|
||||||
<meta name="description" content="{{ project_description }}">
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||||
<meta property="og:description" content="{{ project_description }}">
|
|
||||||
<meta property="twitter:description" content="{{ project_description }}">
|
|
||||||
{% endif %}
|
|
||||||
{% if project_image_url %}
|
|
||||||
<meta property="og:image" content="{{ project_image_url }}">
|
|
||||||
<meta property="twitter:image" content="{{ project_image_url }}">
|
|
||||||
{% endif %}
|
|
||||||
{% load static %}
|
{% load static %}
|
||||||
<link rel="stylesheet" href="{% static 'css/custom.css' %}?v={{ deployment_timestamp }}">
|
<link rel="stylesheet" href="{% static 'css/custom.css' %}?v={{ deployment_timestamp }}">
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css">
|
||||||
{% block head %}{% endblock %}
|
{% block head %}{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
{% block content %}{% endblock %}
|
<nav class="navbar navbar-expand-lg bg-white shadow-sm sticky-top">
|
||||||
</body>
|
<div class="container">
|
||||||
|
<a class="navbar-brand fw-bold" href="{% url 'home' %}">
|
||||||
|
<i class="bi bi-people-fill text-emerald"></i> TeamLink
|
||||||
|
</a>
|
||||||
|
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarNav">
|
||||||
|
<span class="navbar-toggler-icon"></span>
|
||||||
|
</button>
|
||||||
|
<div class="collapse navbar-collapse" id="navbarNav">
|
||||||
|
<ul class="navbar-nav ms-auto">
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{% url 'home' %}">Home</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link" href="{% url 'member_list' %}">Directory</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link btn btn-outline-primary ms-lg-3 px-3 py-1" href="/admin/">
|
||||||
|
Admin Login
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
{% block content %}{% endblock %}
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="py-4 mt-5 bg-white border-top">
|
||||||
|
<div class="container text-center">
|
||||||
|
<p class="text-muted mb-0">© {{ current_time.year }} TeamLink - Internal Member Management</p>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
{% block scripts %}{% endblock %}
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
@ -1,145 +1,86 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
|
{% load static %}
|
||||||
|
|
||||||
{% block title %}{{ project_name }}{% endblock %}
|
{% block title %}TeamLink - Organization Member Database{% endblock %}
|
||||||
|
|
||||||
{% block head %}
|
|
||||||
<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;700&display=swap" rel="stylesheet">
|
|
||||||
<style>
|
|
||||||
:root {
|
|
||||||
--bg-color-start: #6a11cb;
|
|
||||||
--bg-color-end: #2575fc;
|
|
||||||
--text-color: #ffffff;
|
|
||||||
--card-bg-color: rgba(255, 255, 255, 0.01);
|
|
||||||
--card-border-color: rgba(255, 255, 255, 0.1);
|
|
||||||
}
|
|
||||||
|
|
||||||
* {
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
body {
|
|
||||||
margin: 0;
|
|
||||||
font-family: 'Inter', sans-serif;
|
|
||||||
background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end));
|
|
||||||
color: var(--text-color);
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
min-height: 100vh;
|
|
||||||
text-align: center;
|
|
||||||
overflow: hidden;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
body::before {
|
|
||||||
content: '';
|
|
||||||
position: absolute;
|
|
||||||
inset: 0;
|
|
||||||
background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='100' height='100' viewBox='0 0 100 100'><path d='M-10 10L110 10M10 -10L10 110' stroke-width='1' stroke='rgba(255,255,255,0.05)'/></svg>");
|
|
||||||
animation: bg-pan 20s linear infinite;
|
|
||||||
z-index: -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes bg-pan {
|
|
||||||
0% {
|
|
||||||
background-position: 0% 0%;
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
background-position: 100% 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
main {
|
|
||||||
padding: 2rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.card {
|
|
||||||
background: var(--card-bg-color);
|
|
||||||
border: 1px solid var(--card-border-color);
|
|
||||||
border-radius: 16px;
|
|
||||||
padding: 2.5rem 2rem;
|
|
||||||
backdrop-filter: blur(20px);
|
|
||||||
-webkit-backdrop-filter: blur(20px);
|
|
||||||
box-shadow: 0 12px 36px rgba(0, 0, 0, 0.25);
|
|
||||||
}
|
|
||||||
|
|
||||||
h1 {
|
|
||||||
font-size: clamp(2.2rem, 3vw + 1.2rem, 3.2rem);
|
|
||||||
font-weight: 700;
|
|
||||||
margin: 0 0 1.2rem;
|
|
||||||
letter-spacing: -0.02em;
|
|
||||||
}
|
|
||||||
|
|
||||||
p {
|
|
||||||
margin: 0.5rem 0;
|
|
||||||
font-size: 1.1rem;
|
|
||||||
opacity: 0.92;
|
|
||||||
}
|
|
||||||
|
|
||||||
.loader {
|
|
||||||
margin: 1.5rem auto;
|
|
||||||
width: 56px;
|
|
||||||
height: 56px;
|
|
||||||
border: 4px solid rgba(255, 255, 255, 0.25);
|
|
||||||
border-top-color: #fff;
|
|
||||||
border-radius: 50%;
|
|
||||||
animation: spin 1s linear infinite;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes spin {
|
|
||||||
to {
|
|
||||||
transform: rotate(360deg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.runtime code {
|
|
||||||
background: rgba(0, 0, 0, 0.25);
|
|
||||||
padding: 0.15rem 0.45rem;
|
|
||||||
border-radius: 4px;
|
|
||||||
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
||||||
}
|
|
||||||
|
|
||||||
.sr-only {
|
|
||||||
position: absolute;
|
|
||||||
width: 1px;
|
|
||||||
height: 1px;
|
|
||||||
padding: 0;
|
|
||||||
margin: -1px;
|
|
||||||
overflow: hidden;
|
|
||||||
clip: rect(0, 0, 0, 0);
|
|
||||||
border: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
footer {
|
|
||||||
position: absolute;
|
|
||||||
bottom: 1rem;
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
font-size: 0.85rem;
|
|
||||||
opacity: 0.75;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<main>
|
<section class="hero-section text-center text-lg-start">
|
||||||
<div class="card">
|
<div class="container">
|
||||||
<h1>Analyzing your requirements and generating your app…</h1>
|
<div class="row align-items-center">
|
||||||
<div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes">
|
<div class="col-lg-7">
|
||||||
<span class="sr-only">Loading…</span>
|
<h1 class="display-4 fw-bold">Connecting our <br><span class="text-emerald">People and Purpose</span></h1>
|
||||||
|
<p class="lead text-white-50 mb-4">The centralized hub for managing Staff, Board Members, and Youth Volunteers. Secure, searchable, and always accessible.</p>
|
||||||
|
<div class="d-flex gap-3 justify-content-center justify-content-lg-start">
|
||||||
|
<a href="{% url 'member_list' %}" class="btn btn-primary btn-lg">Browse Directory</a>
|
||||||
|
<a href="/admin/core/member/add/" class="btn btn-outline-light btn-lg">Add Member</a>
|
||||||
</div>
|
</div>
|
||||||
<p class="hint">AppWizzy AI is collecting your requirements and applying the first changes.</p>
|
|
||||||
<p class="hint">This page will refresh automatically as the plan is implemented.</p>
|
|
||||||
<p class="runtime">
|
|
||||||
Runtime: Django <code>{{ django_version }}</code> · Python <code>{{ python_version }}</code>
|
|
||||||
— UTC <code>{{ current_time|date:"Y-m-d H:i:s" }}</code>
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</main>
|
<div class="col-lg-5 d-none d-lg-block">
|
||||||
<footer>
|
<div class="p-4 bg-white rounded-4 shadow-lg text-dark">
|
||||||
Page updated: {{ current_time|date:"Y-m-d H:i:s" }} (UTC)
|
<h4 class="mb-4">Quick Stats</h4>
|
||||||
</footer>
|
<div class="row g-3">
|
||||||
|
<div class="col-6">
|
||||||
|
<div class="stat-card border rounded-3 p-3">
|
||||||
|
<span class="number h2 mb-0">{{ stats.total }}</span>
|
||||||
|
<span class="label small">Total Members</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
<div class="stat-card border rounded-3 p-3">
|
||||||
|
<span class="number h2 mb-0">{{ stats.staff }}</span>
|
||||||
|
<span class="label small">Staff</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
<div class="stat-card border rounded-3 p-3">
|
||||||
|
<span class="number h2 mb-0">{{ stats.board }}</span>
|
||||||
|
<span class="label small">Board</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-6">
|
||||||
|
<div class="stat-card border rounded-3 p-3">
|
||||||
|
<span class="number h2 mb-0">{{ stats.volunteers }}</span>
|
||||||
|
<span class="label small">Volunteers</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section class="py-5">
|
||||||
|
<div class="container">
|
||||||
|
<div class="row text-center mb-5">
|
||||||
|
<div class="col-lg-8 mx-auto">
|
||||||
|
<h2 class="h3 mb-3">One Secure Location for All Team Records</h2>
|
||||||
|
<p class="text-muted">Effortlessly manage your organization's core contacts with advanced search, role-based filtering, and administrative oversight.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row g-4">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="card h-100 p-4">
|
||||||
|
<div class="icon h3 text-primary mb-3"><i class="bi bi-shield-lock-fill"></i></div>
|
||||||
|
<h5>Secure Management</h5>
|
||||||
|
<p class="text-muted small">Admin-only data entry ensures your sensitive member data is protected and managed by authorized staff only.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="card h-100 p-4">
|
||||||
|
<div class="icon h3 text-primary mb-3"><i class="bi bi-search"></i></div>
|
||||||
|
<h5>Quick Discovery</h5>
|
||||||
|
<p class="text-muted small">Instantly find any staff member, board representative, or volunteer using our powerful search and filter tools.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<div class="card h-100 p-4">
|
||||||
|
<div class="icon h3 text-primary mb-3"><i class="bi bi-file-earmark-spreadsheet-fill"></i></div>
|
||||||
|
<h5>Reporting Ready</h5>
|
||||||
|
<p class="text-muted small">Our structured data model makes it easy to export and report on your organization's human resources at any time.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
@ -1,7 +1,8 @@
|
|||||||
from django.urls import path
|
from django.urls import path
|
||||||
|
from .views import home, member_list, member_detail
|
||||||
from .views import home
|
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("", home, name="home"),
|
path("", home, name="home"),
|
||||||
|
path("members/", member_list, name="member_list"),
|
||||||
|
path("members/<int:pk>/", member_detail, name="member_detail"),
|
||||||
]
|
]
|
||||||
@ -2,24 +2,53 @@ import os
|
|||||||
import platform
|
import platform
|
||||||
|
|
||||||
from django import get_version as django_version
|
from django import get_version as django_version
|
||||||
from django.shortcuts import render
|
from django.shortcuts import render, get_object_or_404
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
from .models import Member
|
||||||
|
|
||||||
def home(request):
|
def home(request):
|
||||||
"""Render the landing screen with loader and environment details."""
|
"""Render the landing screen with directory stats."""
|
||||||
host_name = request.get_host().lower()
|
host_name = request.get_host().lower()
|
||||||
agent_brand = "AppWizzy" if host_name == "appwizzy.com" else "Flatlogic"
|
agent_brand = "AppWizzy" if host_name == "appwizzy.com" else "Flatlogic"
|
||||||
now = timezone.now()
|
|
||||||
|
stats = {
|
||||||
|
'total': Member.objects.count(),
|
||||||
|
'staff': Member.objects.filter(role='STAFF').count(),
|
||||||
|
'board': Member.objects.filter(role='BOARD').count(),
|
||||||
|
'volunteers': Member.objects.filter(role='YOUTH_VOLUNTEER').count(),
|
||||||
|
}
|
||||||
|
|
||||||
context = {
|
context = {
|
||||||
"project_name": "New Style",
|
"project_name": "TeamLink",
|
||||||
"agent_brand": agent_brand,
|
"agent_brand": agent_brand,
|
||||||
"django_version": django_version(),
|
"django_version": django_version(),
|
||||||
"python_version": platform.python_version(),
|
"python_version": platform.python_version(),
|
||||||
"current_time": now,
|
"current_time": timezone.now(),
|
||||||
"host_name": host_name,
|
"stats": stats,
|
||||||
"project_description": os.getenv("PROJECT_DESCRIPTION", ""),
|
|
||||||
"project_image_url": os.getenv("PROJECT_IMAGE_URL", ""),
|
|
||||||
}
|
}
|
||||||
return render(request, "core/index.html", context)
|
return render(request, "core/index.html", context)
|
||||||
|
|
||||||
|
def member_list(request):
|
||||||
|
"""View to list all members with filtering and search."""
|
||||||
|
query = request.GET.get('q')
|
||||||
|
role_filter = request.GET.get('role')
|
||||||
|
|
||||||
|
members = Member.objects.all()
|
||||||
|
|
||||||
|
if query:
|
||||||
|
members = members.filter(full_name__icontains=query) | members.filter(email__icontains=query)
|
||||||
|
|
||||||
|
if role_filter:
|
||||||
|
members = members.filter(role=role_filter)
|
||||||
|
|
||||||
|
context = {
|
||||||
|
"members": members,
|
||||||
|
"query": query,
|
||||||
|
"role_filter": role_filter,
|
||||||
|
}
|
||||||
|
return render(request, "core/member_list.html", context)
|
||||||
|
|
||||||
|
def member_detail(request, pk):
|
||||||
|
"""View for individual member details."""
|
||||||
|
member = get_object_or_404(Member, pk=pk)
|
||||||
|
return render(request, "core/member_detail.html", {"member": member})
|
||||||
@ -1,4 +1,100 @@
|
|||||||
/* Custom styles for the application */
|
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Outfit:wght@600;700&display=swap');
|
||||||
body {
|
|
||||||
font-family: system-ui, -apple-system, sans-serif;
|
:root {
|
||||||
|
--primary-color: #10b981; /* Vibrant Emerald */
|
||||||
|
--secondary-color: #1a1d23; /* Deep Charcoal */
|
||||||
|
--bg-color: #f8fafc; /* Soft Slate */
|
||||||
|
--text-color: #334155;
|
||||||
|
--heading-font: 'Outfit', sans-serif;
|
||||||
|
--body-font: 'Inter', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
background-color: var(--bg-color);
|
||||||
|
color: var(--text-color);
|
||||||
|
font-family: var(--body-font);
|
||||||
|
line-height: 1.6;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
font-family: var(--heading-font);
|
||||||
|
color: var(--secondary-color);
|
||||||
|
font-weight: 700;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-section {
|
||||||
|
background: linear-gradient(135deg, var(--secondary-color) 0%, #334155 100%);
|
||||||
|
color: white;
|
||||||
|
padding: 100px 0;
|
||||||
|
margin-bottom: 50px;
|
||||||
|
border-radius: 0 0 30px 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.hero-section h1 {
|
||||||
|
color: white;
|
||||||
|
font-size: 3.5rem;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
border: none;
|
||||||
|
border-radius: 15px;
|
||||||
|
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||||
|
transition: transform 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card:hover {
|
||||||
|
transform: translateY(-5px);
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary {
|
||||||
|
background-color: var(--primary-color);
|
||||||
|
border-color: var(--primary-color);
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 10px 25px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-primary:hover {
|
||||||
|
background-color: #059669;
|
||||||
|
border-color: #059669;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card {
|
||||||
|
padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card .number {
|
||||||
|
font-size: 2.5rem;
|
||||||
|
color: var(--primary-color);
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-card .label {
|
||||||
|
font-weight: 500;
|
||||||
|
color: #64748b;
|
||||||
|
}
|
||||||
|
|
||||||
|
.nav-link {
|
||||||
|
font-weight: 500;
|
||||||
|
color: var(--secondary-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.navbar-brand {
|
||||||
|
font-family: var(--heading-font);
|
||||||
|
font-size: 1.5rem;
|
||||||
|
color: var(--secondary-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge-staff { background-color: #dcfce7; color: #166534; }
|
||||||
|
.badge-board { background-color: #dbeafe; color: #1e40af; }
|
||||||
|
.badge-volunteer { background-color: #fef9c3; color: #854d0e; }
|
||||||
|
|
||||||
|
.search-bar {
|
||||||
|
background: white;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 15px;
|
||||||
|
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
|
||||||
|
margin-bottom: 30px;
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user