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

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long