Compare commits
No commits in common. "ai-dev" and "master" have entirely different histories.
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,9 +1,3 @@
|
|||||||
from django.contrib import admin
|
from django.contrib import admin
|
||||||
from .models import Member
|
|
||||||
|
|
||||||
@admin.register(Member)
|
# Register your models here.
|
||||||
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
|
|
||||||
|
|||||||
@ -1,30 +0,0 @@
|
|||||||
# 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'],
|
|
||||||
},
|
|
||||||
),
|
|
||||||
]
|
|
||||||
Binary file not shown.
Binary file not shown.
@ -1,27 +1,3 @@
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
class Member(models.Model):
|
# Create your models here.
|
||||||
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,53 +1,25 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<title>{% block title %}Knowledge Base{% endblock %}</title>
|
||||||
<title>{% block title %}TeamLink{% endblock %}</title>
|
{% if project_description %}
|
||||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
<meta name="description" content="{{ project_description }}">
|
||||||
{% load static %}
|
<meta property="og:description" content="{{ project_description }}">
|
||||||
<link rel="stylesheet" href="{% static 'css/custom.css' %}?v={{ deployment_timestamp }}">
|
<meta property="twitter:description" content="{{ project_description }}">
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.0/font/bootstrap-icons.css">
|
{% endif %}
|
||||||
{% block head %}{% endblock %}
|
{% if project_image_url %}
|
||||||
|
<meta property="og:image" content="{{ project_image_url }}">
|
||||||
|
<meta property="twitter:image" content="{{ project_image_url }}">
|
||||||
|
{% endif %}
|
||||||
|
{% load static %}
|
||||||
|
<link rel="stylesheet" href="{% static 'css/custom.css' %}?v={{ deployment_timestamp }}">
|
||||||
|
{% block head %}{% endblock %}
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<nav class="navbar navbar-expand-lg bg-white shadow-sm sticky-top">
|
{% block content %}{% endblock %}
|
||||||
<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>
|
</body>
|
||||||
</html>
|
|
||||||
|
</html>
|
||||||
|
|||||||
@ -1,86 +1,145 @@
|
|||||||
{% extends "base.html" %}
|
{% extends "base.html" %}
|
||||||
{% load static %}
|
|
||||||
|
|
||||||
{% block title %}TeamLink - Organization Member Database{% endblock %}
|
{% block title %}{{ project_name }}{% 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 %}
|
||||||
<section class="hero-section text-center text-lg-start">
|
<main>
|
||||||
<div class="container">
|
<div class="card">
|
||||||
<div class="row align-items-center">
|
<h1>Analyzing your requirements and generating your app…</h1>
|
||||||
<div class="col-lg-7">
|
<div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes">
|
||||||
<h1 class="display-4 fw-bold">Connecting our <br><span class="text-emerald">People and Purpose</span></h1>
|
<span class="sr-only">Loading…</span>
|
||||||
<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>
|
|
||||||
<div class="col-lg-5 d-none d-lg-block">
|
|
||||||
<div class="p-4 bg-white rounded-4 shadow-lg text-dark">
|
|
||||||
<h4 class="mb-4">Quick Stats</h4>
|
|
||||||
<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>
|
</div>
|
||||||
</section>
|
<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>
|
||||||
<section class="py-5">
|
<p class="runtime">
|
||||||
<div class="container">
|
Runtime: Django <code>{{ django_version }}</code> · Python <code>{{ python_version }}</code>
|
||||||
<div class="row text-center mb-5">
|
— UTC <code>{{ current_time|date:"Y-m-d H:i:s" }}</code>
|
||||||
<div class="col-lg-8 mx-auto">
|
</p>
|
||||||
<h2 class="h3 mb-3">One Secure Location for All Team Records</h2>
|
</div>
|
||||||
<p class="text-muted">Effortlessly manage your organization's core contacts with advanced search, role-based filtering, and administrative oversight.</p>
|
</main>
|
||||||
</div>
|
<footer>
|
||||||
</div>
|
Page updated: {{ current_time|date:"Y-m-d H:i:s" }} (UTC)
|
||||||
<div class="row g-4">
|
</footer>
|
||||||
<div class="col-md-4">
|
{% endblock %}
|
||||||
<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 %}
|
|
||||||
@ -1,8 +1,7 @@
|
|||||||
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,53 +2,24 @@ 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, get_object_or_404
|
from django.shortcuts import render
|
||||||
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 directory stats."""
|
"""Render the landing screen with loader and environment details."""
|
||||||
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": "TeamLink",
|
"project_name": "New Style",
|
||||||
"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": timezone.now(),
|
"current_time": now,
|
||||||
"stats": stats,
|
"host_name": host_name,
|
||||||
|
"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,100 +1,4 @@
|
|||||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Outfit:wght@600;700&display=swap');
|
/* Custom styles for the application */
|
||||||
|
|
||||||
: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 {
|
body {
|
||||||
background-color: var(--bg-color);
|
font-family: system-ui, -apple-system, sans-serif;
|
||||||
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