Refactor API structure and add comprehensive user management features

- Restructure API v1 with improved serializers organization
- Add user deletion requests and moderation queue system
- Implement bulk moderation operations and permissions
- Add user profile enhancements with display names and avatars
- Expand ride and park API endpoints with better filtering
- Add manufacturer API with detailed ride relationships
- Improve authentication flows and error handling
- Update frontend documentation and API specifications
This commit is contained in:
pacnpal
2025-08-29 16:03:51 -04:00
parent 7b9f64be72
commit bb7da85516
92 changed files with 19690 additions and 9076 deletions

View File

@@ -7,449 +7,426 @@
--font-family-sans: Poppins, sans-serif;
}
@layer components {
/* Button Styles */
.btn-primary {
@apply inline-flex items-center px-6 py-2.5 border border-transparent rounded-full shadow-md text-sm font-medium text-white bg-gradient-to-r from-primary to-secondary hover:from-primary/90 hover:to-secondary/90 focus:outline-hidden focus:ring-3 focus:ring-offset-2 focus:ring-primary/50 transform hover:scale-105 transition-all;
}
.btn-secondary {
@apply inline-flex items-center px-6 py-2.5 border border-gray-200 dark:border-gray-700 rounded-full shadow-md text-sm font-medium text-gray-700 dark:text-gray-200 bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-hidden focus:ring-3 focus:ring-offset-2 focus:ring-primary/50 transform hover:scale-105 transition-all;
}
/* [Previous styles remain unchanged until mobile menu section...] */
/* Mobile Menu */
#mobileMenu {
@apply overflow-hidden transition-all duration-300 ease-in-out opacity-0 max-h-0;
}
#mobileMenu.show {
@apply max-h-[300px] opacity-100;
}
#mobileMenu .space-y-4 {
@apply pb-6;
}
.mobile-nav-link {
@apply flex items-center justify-center px-6 py-3 text-gray-700 transition-all border border-transparent rounded-lg dark:text-gray-200 hover:bg-primary/10 dark:hover:bg-primary/20 hover:text-primary dark:hover:text-primary hover:border-primary/20 dark:hover:border-primary/30;
}
.mobile-nav-link i {
@apply text-xl transition-colors;
}
@media (max-width: 540px) {
.mobile-nav-link i {
@apply text-lg;
}
}
.mobile-nav-link.primary {
@apply text-white bg-gradient-to-r from-primary to-secondary hover:from-primary/90 hover:to-secondary/90;
}
.mobile-nav-link.primary i {
@apply mr-3 text-white;
}
.mobile-nav-link.secondary {
@apply text-gray-700 bg-gray-100 dark:bg-gray-700 dark:text-gray-300 hover:bg-gray-200 dark:hover:bg-gray-600;
}
.mobile-nav-link.secondary i {
@apply mr-3 text-gray-500 dark:text-gray-400;
}
/* Theme Toggle */
#theme-toggle+.theme-toggle-btn i::before {
content: "\f186";
font-family: "Font Awesome 5 Free";
font-weight: 900;
}
#theme-toggle:checked+.theme-toggle-btn i::before {
content: "\f185";
@apply text-yellow-400;
}
/* Navigation Components */
.nav-link {
@apply flex items-center text-gray-700 transition-all dark:text-gray-200;
}
/* Extra small screens (540px and below) */
@media (max-width: 540px) {
.nav-link {
@apply px-2 py-2 text-sm;
}
.nav-link i {
@apply mr-1 text-base;
}
.nav-link span {
@apply text-sm;
}
.site-logo {
@apply px-1 text-lg;
}
.nav-container {
@apply px-2;
}
}
/* Small screens (541px to 767px) */
@media (min-width: 541px) and (max-width: 767px) {
.nav-link {
@apply px-3 py-2;
}
.nav-link i {
@apply mr-2;
}
.site-logo {
@apply px-2 text-xl;
}
.nav-container {
@apply px-4;
}
}
/* Medium screens and up */
@media (min-width: 768px) {
.nav-link {
@apply px-6 py-2.5 rounded-lg font-medium border border-transparent hover:border-primary/20 dark:hover:border-primary/30;
}
.nav-link i {
@apply mr-3 text-lg;
}
.site-logo {
@apply px-3 text-2xl;
}
.nav-container {
@apply px-6;
}
}
.nav-link:hover {
@apply text-primary dark:text-primary bg-primary/10 dark:bg-primary/20;
}
.nav-link i {
@apply text-gray-500 transition-colors dark:text-gray-400;
}
.nav-link:hover i {
@apply text-primary;
}
@media (min-width: 1024px) {
#mobileMenu {
@apply !hidden;
}
}
/* Menu Items */
.menu-item {
@apply flex items-center w-full px-4 py-3 text-sm text-gray-700 transition-all dark:text-gray-200 hover:bg-primary/10 dark:hover:bg-primary/20 hover:text-primary dark:hover:text-primary first:rounded-t-lg last:rounded-b-lg;
}
.menu-item i {
@apply mr-3 text-base text-gray-500 dark:text-gray-400;
}
/* Form Components */
.form-input {
@apply w-full px-4 py-3 text-gray-900 transition-all border border-gray-200 rounded-lg shadow-xs dark:border-gray-700 bg-white/70 dark:bg-gray-800/70 backdrop-blur-xs dark:text-white focus:ring-3 focus:ring-primary/50 focus:border-primary;
}
.form-label {
@apply block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1.5;
}
.form-hint {
@apply mt-2 space-y-1 text-sm text-gray-500 dark:text-gray-400;
}
.form-error {
@apply mt-2 text-sm text-red-600 dark:text-red-400;
}
/* Status Badges */
.status-badge {
@apply inline-flex items-center px-3 py-1 text-sm font-medium rounded-full;
}
.status-operating {
@apply text-green-800 bg-green-100 dark:bg-green-700 dark:text-green-50;
}
.status-closed {
@apply text-red-800 bg-red-100 dark:bg-red-700 dark:text-red-50;
}
.status-construction {
@apply text-yellow-800 bg-yellow-100 dark:bg-yellow-600 dark:text-yellow-50;
}
/* Auth Components */
.auth-card {
@apply w-full max-w-md p-8 mx-auto border shadow-xl bg-white/90 dark:bg-gray-800/90 rounded-2xl backdrop-blur-xs border-gray-200/50 dark:border-gray-700/50;
}
.auth-title {
@apply mb-8 text-2xl font-bold text-center text-transparent bg-gradient-to-r from-primary to-secondary bg-clip-text;
}
.auth-divider {
@apply relative my-6 text-center;
}
.auth-divider::before,
.auth-divider::after {
@apply absolute top-1/2 w-1/3 border-t border-gray-200 dark:border-gray-700 content-[''];
}
.auth-divider::before {
@apply left-0;
}
.auth-divider::after {
@apply right-0;
}
.auth-divider span {
@apply px-4 text-sm text-gray-500 dark:text-gray-400 bg-white/90 dark:bg-gray-800/90;
}
/* Social Login Buttons */
.btn-social {
@apply w-full flex items-center justify-center px-6 py-3 border border-gray-200 dark:border-gray-700 rounded-lg shadow-xs text-sm font-medium text-gray-700 dark:text-gray-200 bg-white dark:bg-gray-800 hover:bg-gray-50 dark:hover:bg-gray-700 focus:outline-hidden focus:ring-3 focus:ring-offset-2 focus:ring-primary/50 transform hover:scale-[1.02] transition-all mb-3;
}
.btn-discord {
@apply text-gray-700 bg-white border-gray-200 hover:bg-gray-50 shadow-gray-200/50 dark:shadow-gray-900/50;
}
.btn-google {
@apply text-gray-700 bg-white border-gray-200 hover:bg-gray-50 shadow-gray-200/50 dark:shadow-gray-900/50;
}
/* Alert Components */
.alert {
@apply p-4 mb-4 shadow-lg rounded-xl backdrop-blur-xs;
}
.alert-success {
@apply text-green-800 border border-green-200 bg-green-100/90 dark:bg-green-800/30 dark:text-green-100 dark:border-green-700;
}
.alert-error {
@apply text-red-800 border border-red-200 bg-red-100/90 dark:bg-red-800/30 dark:text-red-100 dark:border-red-700;
}
.alert-warning {
@apply text-yellow-800 border border-yellow-200 bg-yellow-100/90 dark:bg-yellow-800/30 dark:text-yellow-100 dark:border-yellow-700;
}
.alert-info {
@apply text-blue-800 border border-blue-200 bg-blue-100/90 dark:bg-blue-800/30 dark:text-blue-100 dark:border-blue-700;
}
/* Layout Components */
.card {
@apply p-6 bg-white border rounded-lg shadow-lg dark:bg-gray-800 border-gray-200/50 dark:border-gray-700/50;
}
.card-hover {
@apply transition-transform transform hover:-translate-y-1;
}
.grid-cards {
@apply grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-3;
}
/* Adaptive Grid System - White Space Solutions */
.grid-adaptive {
@apply grid gap-6;
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
}
.grid-adaptive-sm {
@apply grid gap-4;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
.grid-adaptive-lg {
@apply grid gap-8;
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
}
/* Stats Grid - Always Even Layout */
.grid-stats {
@apply grid gap-4;
/* Default: Force 2+3 layout for small screens */
grid-template-columns: repeat(2, 1fr);
}
.grid-stats-wide {
@apply grid gap-4;
grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
}
/* Enhanced Responsive Grid */
.grid-responsive {
@apply grid grid-cols-1 gap-6;
@apply sm:grid-cols-2;
@apply md:grid-cols-3;
@apply lg:grid-cols-4;
@apply xl:grid-cols-5;
@apply 2xl:grid-cols-6;
}
.grid-responsive-cards {
@apply grid grid-cols-1 gap-6;
@apply md:grid-cols-2;
@apply lg:grid-cols-3;
@apply xl:grid-cols-4;
@apply 2xl:grid-cols-5;
}
/* Tablet-specific optimizations for 768px breakpoint */
@media (min-width: 768px) and (max-width: 1023px) {
.grid-adaptive-sm {
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
}
/* Force 2+3 even layout for tablets */
.grid-stats {
grid-template-columns: repeat(2, 1fr);
}
.grid-adaptive {
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
}
/* Content-aware grid adjustments */
@media (min-width: 1024px) and (max-width: 1279px) {
.grid-adaptive {
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
}
.grid-adaptive-lg {
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
}
/* Force 3+2 even layout for intermediate sizes */
.grid-stats {
grid-template-columns: repeat(3, 1fr);
}
}
@media (min-width: 1280px) {
.grid-adaptive {
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
}
.grid-adaptive-lg {
grid-template-columns: repeat(auto-fit, minmax(380px, 1fr));
}
/* Force 5-column even layout for large screens */
.grid-stats {
grid-template-columns: repeat(5, 1fr);
}
}
/* Priority Card - Operator/Owner Full-Width Responsive Behavior */
.card-stats-priority {
/* Full width by default (small screens) */
grid-column: 1 / -1;
}
/* Medium screens - still full width for emphasis */
@media (min-width: 768px) and (max-width: 1023px) {
.card-stats-priority {
grid-column: 1 / -1;
}
}
/* Large screens - normal grid behavior */
@media (min-width: 1024px) {
.card-stats-priority {
grid-column: auto;
}
}
@media (min-width: 1536px) {
.grid-adaptive {
grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
}
.grid-adaptive-lg {
grid-template-columns: repeat(auto-fit, minmax(400px, 1fr));
}
}
/* Typography */
.heading-1 {
@apply mb-6 text-3xl font-bold text-gray-900 dark:text-white;
}
.heading-2 {
@apply mb-4 text-2xl font-bold text-gray-900 dark:text-white;
}
.text-body {
@apply text-gray-600 dark:text-gray-300;
}
/* Turnstile Widget */
.turnstile {
@apply flex items-center justify-center my-4;
}
/* Layout Optimization - Phase 1 Critical Fixes */
/* Optimized Padding System */
.p-compact {
@apply p-5; /* 20px - replaces excessive p-6 (24px) */
}
.p-optimized {
@apply p-4; /* 16px - replaces p-6 (24px) for 33% reduction */
}
.p-minimal {
@apply p-3; /* 12px - replaces p-2 (8px) for consistency */
}
/* Consistent Card Heights */
.card-standard {
@apply min-h-[120px];
}
.card-large {
@apply min-h-[200px];
}
.card-stats {
@apply min-h-[80px];
}
/* Mobile Responsive Padding Adjustments */
@media (max-width: 768px) {
.p-compact {
@apply p-4; /* 16px on mobile */
}
.p-optimized {
@apply p-3.5; /* 14px on mobile */
}
.p-minimal {
@apply p-2.5; /* 10px on mobile */
}
.card-standard {
@apply min-h-[100px];
}
.card-large {
@apply min-h-[160px];
}
.card-stats {
@apply min-h-[80px];
}
}
/* Base Component Styles */
.site-logo {
font-size: 1.5rem;
font-weight: 700;
background: linear-gradient(135deg, var(--color-primary), var(--color-secondary));
-webkit-background-clip: text;
background-clip: text;
color: transparent;
transition: transform 0.2s ease;
}
.site-logo:hover {
transform: scale(1.05);
}
/* Navigation Styles */
.nav-container {
padding: 1rem 1.5rem;
max-width: 1200px;
margin: 0 auto;
}
.nav-link {
display: inline-flex;
align-items: center;
gap: 0.5rem;
padding: 0.5rem 0.75rem;
border-radius: 0.5rem;
font-weight: 500;
color: #6b7280;
transition: all 0.2s ease;
text-decoration: none;
}
.nav-link:hover {
color: var(--color-primary);
background-color: rgba(79, 70, 229, 0.1);
}
.nav-link i {
font-size: 1rem;
}
@media (max-width: 640px) {
.nav-link span {
display: none;
}
}
/* Form Styles */
.form-input {
width: 100%;
padding: 0.75rem 1rem;
border: 1px solid #d1d5db;
border-radius: 0.5rem;
font-size: 0.875rem;
background-color: white;
transition: all 0.2s ease;
}
.form-input:focus {
outline: none;
border-color: var(--color-primary);
box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1);
}
.form-input::placeholder {
color: #9ca3af;
}
/* Dark mode form styles */
@media (prefers-color-scheme: dark) {
.form-input {
background-color: #374151;
border-color: #4b5563;
color: white;
}
.form-input:focus {
border-color: var(--color-primary);
box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.2);
}
.form-input::placeholder {
color: #6b7280;
}
}
/* Button Styles */
.btn-primary {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
padding: 0.75rem 1.5rem;
border: none;
border-radius: 0.5rem;
font-size: 0.875rem;
font-weight: 600;
color: white;
background: linear-gradient(135deg, var(--color-primary), #3730a3);
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
transition: all 0.2s ease;
cursor: pointer;
text-decoration: none;
}
.btn-primary:hover {
background: linear-gradient(135deg, #3730a3, #312e81);
transform: translateY(-1px);
box-shadow: 0 6px 12px -2px rgba(0, 0, 0, 0.15);
}
.btn-primary:active {
transform: translateY(0);
}
.btn-secondary {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 0.5rem;
padding: 0.75rem 1.5rem;
border: 1px solid #d1d5db;
border-radius: 0.5rem;
font-size: 0.875rem;
font-weight: 600;
color: #374151;
background-color: white;
box-shadow: 0 2px 4px -1px rgba(0, 0, 0, 0.06);
transition: all 0.2s ease;
cursor: pointer;
text-decoration: none;
}
.btn-secondary:hover {
background-color: #f9fafb;
border-color: #9ca3af;
transform: translateY(-1px);
box-shadow: 0 4px 8px -2px rgba(0, 0, 0, 0.1);
}
.btn-secondary:active {
transform: translateY(0);
}
/* Dark mode button styles */
@media (prefers-color-scheme: dark) {
.btn-secondary {
border-color: #4b5563;
color: #e5e7eb;
background-color: #374151;
}
.btn-secondary:hover {
background-color: #4b5563;
border-color: #6b7280;
}
}
/* Menu Styles */
.menu-item {
display: flex;
align-items: center;
gap: 0.75rem;
width: 100%;
padding: 0.75rem 1rem;
font-size: 0.875rem;
color: #374151;
background: none;
border: none;
text-align: left;
text-decoration: none;
transition: all 0.2s ease;
cursor: pointer;
}
.menu-item:hover {
background-color: #f3f4f6;
color: var(--color-primary);
}
.menu-item i {
width: 1.25rem;
text-align: center;
}
/* Dark mode menu styles */
@media (prefers-color-scheme: dark) {
.menu-item {
color: #e5e7eb;
}
.menu-item:hover {
background-color: #4b5563;
color: var(--color-primary);
}
}
/* Theme Toggle Styles */
.theme-toggle-btn {
position: relative;
width: 2.5rem;
height: 2.5rem;
border-radius: 0.5rem;
transition: all 0.2s ease;
}
.theme-toggle-btn:hover {
background-color: rgba(79, 70, 229, 0.1);
}
.theme-toggle-btn i::before {
content: "\f185"; /* sun icon */
}
@media (prefers-color-scheme: dark) {
.theme-toggle-btn i::before {
content: "\f186"; /* moon icon */
}
}
/* Mobile Menu Styles */
#mobileMenu {
display: none;
padding: 1rem 0;
border-top: 1px solid #e5e7eb;
margin-top: 1rem;
}
#mobileMenu.show {
display: block;
}
@media (prefers-color-scheme: dark) {
#mobileMenu {
border-top-color: #4b5563;
}
}
/* Grid Adaptive Styles */
.grid-adaptive-sm {
display: grid;
gap: 1rem;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
.grid-adaptive {
display: grid;
gap: 1.5rem;
grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
}
@media (min-width: 768px) {
.grid-adaptive {
grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
}
}
@media (min-width: 1024px) {
.grid-adaptive {
grid-template-columns: repeat(3, 1fr);
}
}
/* Card Styles */
.card {
background: white;
border-radius: 0.75rem;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1);
overflow: hidden;
transition: all 0.3s ease;
}
.card:hover {
transform: translateY(-2px);
box-shadow: 0 10px 25px -3px rgba(0, 0, 0, 0.1);
}
@media (prefers-color-scheme: dark) {
.card {
background: #1f2937;
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.3);
}
.card:hover {
box-shadow: 0 10px 25px -3px rgba(0, 0, 0, 0.4);
}
}
/* Alert Styles */
.alert {
position: fixed;
top: 1rem;
right: 1rem;
z-index: 50;
padding: 1rem 1.5rem;
border-radius: 0.5rem;
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
animation: slideInRight 0.3s ease-out;
}
.alert-success {
background-color: #10b981;
color: white;
}
.alert-error {
background-color: #ef4444;
color: white;
}
.alert-info {
background-color: #3b82f6;
color: white;
}
.alert-warning {
background-color: #f59e0b;
color: white;
}
@keyframes slideInRight {
from {
transform: translateX(100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
/* Loading States */
.loading {
opacity: 0.6;
pointer-events: none;
}
.spinner {
display: inline-block;
width: 1rem;
height: 1rem;
border: 2px solid #f3f4f6;
border-radius: 50%;
border-top-color: var(--color-primary);
animation: spin 1s ease-in-out infinite;
}
@keyframes spin {
to {
transform: rotate(360deg);
}
}
/* Utility Classes */
.text-gradient {
background: linear-gradient(135deg, var(--color-primary), var(--color-secondary));
-webkit-background-clip: text;
background-clip: text;
color: transparent;
}
.bg-gradient-primary {
background: linear-gradient(135deg, var(--color-primary), #3730a3);
}
.bg-gradient-secondary {
background: linear-gradient(135deg, var(--color-secondary), #be185d);
}
/* Responsive Utilities */
@media (max-width: 1023px) {
.lg\:hidden {
display: none !important;
}
}
@media (min-width: 1024px) {
.lg\:flex {
display: flex !important;
}
.lg\:hidden {
display: none !important;
}
}
/* Focus States */
.focus-ring {
transition: all 0.2s ease;
}
.focus-ring:focus {
outline: none;
box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.2);
}
/* Animation Classes */
.fade-in {
animation: fadeIn 0.3s ease-out;
}
.slide-up {
animation: slideUp 0.3s ease-out;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
@keyframes slideUp {
from {
transform: translateY(1rem);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}

File diff suppressed because it is too large Load Diff