diff --git a/.replit b/.replit index 3520ba63..809f821d 100644 --- a/.replit +++ b/.replit @@ -54,6 +54,10 @@ outputType = "webview" localPort = 5000 externalPort = 80 +[[ports]] +localPort = 32933 +externalPort = 3002 + [[ports]] localPort = 41923 externalPort = 3000 diff --git a/replit.md b/replit.md index 4ebceeb3..08beef24 100644 --- a/replit.md +++ b/replit.md @@ -56,6 +56,7 @@ Migrations: All applied successfully (including circular dependency resolution) ✅ **Spatial Data Support**: GeoDjango Point objects and spatial functionality working correctly ✅ **CloudflareImages Integration**: Avatar functionality preserved with proper foreign key relationships ✅ **Django-Cotton Integration**: Modern component-based template system with EXACT visual preservation +✅ **Cotton Components**: Standardized park_card.html and ride_card.html components with full feature support ### API Endpoints Available - `/api/v1/parks/` - Parks API with spatial data diff --git a/static/css/tailwind.css b/static/css/tailwind.css index 8481364f..9e447eeb 100644 --- a/static/css/tailwind.css +++ b/static/css/tailwind.css @@ -22,6 +22,7 @@ --color-orange-200: oklch(90.1% 0.076 70.697); --color-orange-600: oklch(64.6% 0.222 41.116); --color-orange-800: oklch(47% 0.157 37.304); + --color-orange-900: oklch(40.8% 0.123 38.172); --color-amber-100: oklch(96.2% 0.059 95.617); --color-amber-800: oklch(47.3% 0.137 46.201); --color-yellow-50: oklch(98.7% 0.026 102.212); @@ -1730,6 +1731,10 @@ --tw-gradient-to: var(--color-blue-50); --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position)); } + .to-blue-600 { + --tw-gradient-to: var(--color-blue-600); + --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position)); + } .to-gray-100 { --tw-gradient-to: var(--color-gray-100); --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position)); @@ -3907,6 +3912,11 @@ } } } + .dark\:bg-orange-900 { + @media (prefers-color-scheme: dark) { + background-color: var(--color-orange-900); + } + } .dark\:bg-purple-800 { @media (prefers-color-scheme: dark) { background-color: var(--color-purple-800); @@ -4239,6 +4249,11 @@ color: var(--color-green-900); } } + .dark\:text-orange-200 { + @media (prefers-color-scheme: dark) { + color: var(--color-orange-200); + } + } .dark\:text-primary { @media (prefers-color-scheme: dark) { color: var(--color-primary); diff --git a/templates/cotton/park_card.html b/templates/cotton/park_card.html new file mode 100644 index 00000000..ed8a4c8b --- /dev/null +++ b/templates/cotton/park_card.html @@ -0,0 +1,190 @@ +{% comment %} +Park Card Component - Django Cotton Version + +A reusable park card component that supports both list and grid view modes. +Includes status badges, operator information, description, and ride/coaster statistics. + +Usage Examples: + +List View: + + +Grid View: + + +With custom CSS classes: + + +Parameters: +- park: Park object (required) +- view_mode: "list" or "grid" (default: "grid") +- class: Additional CSS classes (optional) + +Features: +- Responsive design with hover effects +- Status badge with proper color coding +- Operator information display +- Description with automatic truncation (30 words for list, 15 for grid) +- Ride and coaster count statistics with icons +- Gradient effects and modern styling +- Links to park detail pages +{% endcomment %} + + + +{% if park %} + {% if view_mode == 'list' %} + {# Enhanced List View Item #} +
+
+
+ {# Main Content Section #} +
+
+

+ + {{ park.name }} + +

+ + {# Status Badge #} + + {{ park.get_status_display }} + +
+ + {% if park.operator %} +
+ {{ park.operator.name }} +
+ {% endif %} + + {% if park.description %} +

+ {{ park.description|truncatewords:30 }} +

+ {% endif %} +
+ + {# Stats Section #} + {% if park.ride_count or park.coaster_count %} +
+ {% if park.ride_count %} +
+ + + + {{ park.ride_count }} + rides +
+ {% endif %} + {% if park.coaster_count %} +
+ + + + {{ park.coaster_count }} + coasters +
+ {% endif %} +
+ {% endif %} +
+
+
+ {% else %} + {# Enhanced Grid View Item #} +
+ {# Card Header with Gradient #} +
+ +
+
+

+ + {{ park.name }} + +

+ + {# Status Badge #} + + {{ park.get_status_display }} + +
+ + {% if park.operator %} +
+ {{ park.operator.name }} +
+ {% endif %} + + {% if park.description %} +

+ {{ park.description|truncatewords:15 }} +

+ {% endif %} + + {# Stats Footer #} + {% if park.ride_count or park.coaster_count %} +
+
+ {% if park.ride_count %} +
+ + + + {{ park.ride_count }} +
+ {% endif %} + {% if park.coaster_count %} +
+ + + + {{ park.coaster_count }} +
+ {% endif %} +
+ + {# View Details Arrow #} +
+ + + +
+
+ {% endif %} +
+
+ {% endif %} +{% endif %} \ No newline at end of file diff --git a/templates/cotton/ride_card.html b/templates/cotton/ride_card.html new file mode 100644 index 00000000..da69497c --- /dev/null +++ b/templates/cotton/ride_card.html @@ -0,0 +1,215 @@ +{% comment %} +Ride Card Component - Django Cotton Version + +A comprehensive ride card component with image handling, status badges, and feature displays. +Includes all ride statistics, special features, and manufacturer information. + +Usage Examples: + +Basic usage: + + +With custom CSS classes: + + +With custom image fallback: + + +Parameters: +- ride: Ride object (required) +- class: Additional CSS classes (optional) +- fallback_gradient: Custom gradient for image fallback (default: "from-blue-500 to-purple-600") + +Features: +- Image handling with gradient fallback backgrounds +- Status badges with proper color coding (operating, closed_temporarily, closed_permanently, under_construction) +- Ride name with link to detail page +- Category and park information display +- Statistics grid for height, speed, capacity, duration +- Special features badges (inversions, launches, track_type) +- Opening date and manufacturer/designer information +- Responsive design with hover effects +- Modern Tailwind styling and animations +{% endcomment %} + + + +{% if ride %} +
+ +
+ {% if ride.image %} + {{ ride.name }} + {% else %} +
+ +
+ {% endif %} + + +
+ {% if ride.operating_status == 'operating' or ride.operating_status == 'OPERATING' %} + + + Operating + + {% elif ride.operating_status == 'closed_temporarily' or ride.operating_status == 'CLOSED_TEMP' %} + + + Temporarily Closed + + {% elif ride.operating_status == 'closed_permanently' or ride.operating_status == 'CLOSED_PERM' %} + + + Permanently Closed + + {% elif ride.operating_status == 'under_construction' or ride.operating_status == 'UNDER_CONSTRUCTION' %} + + + Under Construction + + {% elif ride.operating_status == 'sbno' or ride.operating_status == 'SBNO' %} + + + SBNO + + {% endif %} +
+
+ + +
+ +
+

+ + {{ ride.name }} + +

+
+ + {{ ride.category|default:"Ride" }} + + {% if ride.park %} + + + {{ ride.park.name }} + + {% endif %} +
+
+ + +
+ {% if ride.height %} +
+
{{ ride.height }}ft
+
Height
+
+ {% endif %} + + {% if ride.rollercoaster_stats.max_speed %} +
+
{{ ride.rollercoaster_stats.max_speed }}mph
+
Top Speed
+
+ {% elif ride.max_speed %} +
+
{{ ride.max_speed }}mph
+
Max Speed
+
+ {% endif %} + + {% if ride.capacity_per_hour %} +
+
{{ ride.capacity_per_hour }}
+
Capacity/Hr
+
+ {% endif %} + + {% if ride.duration %} +
+
{{ ride.duration }}s
+
Duration
+
+ {% endif %} +
+ + + {% if ride.has_inversions or ride.has_launches or ride.rollercoaster_stats.track_type or ride.track_type %} +
+ {% if ride.has_inversions %} + + + {% if ride.rollercoaster_stats.number_of_inversions %} + {{ ride.rollercoaster_stats.number_of_inversions }} Inversion{{ ride.rollercoaster_stats.number_of_inversions|pluralize }} + {% else %} + Inversions + {% endif %} + + {% endif %} + + {% if ride.has_launches %} + + + {% if ride.rollercoaster_stats.number_of_launches %} + {{ ride.rollercoaster_stats.number_of_launches }} Launch{{ ride.rollercoaster_stats.number_of_launches|pluralize }} + {% else %} + Launched + {% endif %} + + {% endif %} + + {% if ride.rollercoaster_stats.track_type %} + + {{ ride.rollercoaster_stats.track_type|title }} + + {% elif ride.track_type %} + + {{ ride.track_type|title }} + + {% endif %} +
+ {% endif %} + + + {% if ride.opened_date %} +
+ + Opened {{ ride.opened_date|date:"F j, Y" }} +
+ {% endif %} + + + {% if ride.manufacturer or ride.designer %} +
+ {% if ride.manufacturer %} +
+ + {{ ride.manufacturer.name }} +
+ {% endif %} + {% if ride.designer and ride.designer != ride.manufacturer %} +
+ + Designed by {{ ride.designer.name }} +
+ {% endif %} +
+ {% endif %} +
+
+{% endif %} \ No newline at end of file