10 KiB
Multi-Stage Tabbed Club Modal - Implementation Complete
Overview
A comprehensive, multi-stage tabbed modal for creating and editing clubs in the Laravel admin panel. The modal features 5 tabs with full validation, reuses existing components, and supports both create and edit modes.
✅ Components Created
1. Main Modal Component
File: resources/views/components/club-modal.blade.php
- Responsive modal with max-width and internal scrolling
- Tab navigation with progress indicator (Step X of 5)
- Form state management across tabs
- Draft persistence using localStorage
- AJAX submission with validation
- Support for both create and edit modes
2. Tab Components
Tab 1: Basic Information
File: resources/views/components/club-modal/tabs/basic-info.blade.php
- Club Name (auto-generates slug)
- Club Owner (opens user picker modal)
- Established Date
- Slogan
- Description (with character counter)
- Commercial Registration Number & Document Upload
- VAT Registration Number & Certificate Upload
- VAT Percentage
Tab 2: Identity & Branding
File: resources/views/components/club-modal/tabs/identity-branding.blade.php
- Club Slug (auto-generated, editable)
- Club URL Preview (read-only)
- QR Code Generator (downloadable, printable)
- Club Logo (using existing
x-takeone-cropper, square aspect) - Cover Image (using existing
x-takeone-cropper, banner aspect) - Social Media Links (dynamic list with add/remove)
Tab 3: Location
File: resources/views/components/club-modal/tabs/location.blade.php
- Country (using existing
x-nationality-dropdown) - Timezone (using existing
x-timezone-dropdown, filtered by country) - Currency (using existing
x-currency-dropdown, default from country) - Interactive Map with draggable marker (Leaflet.js)
- Latitude/Longitude inputs (two-way binding with map)
- Google Maps Link parser (extracts coordinates)
- "Use My Current Location" button
- "Center on Selected Country" button
Tab 4: Contact Information
File: resources/views/components/club-modal/tabs/contact.blade.php
- Email toggle (use owner's or custom)
- Phone toggle (use owner's or custom, with existing
x-country-code-dropdown) - Owner contact info display (read-only when using owner's)
Tab 5: Finance & Settings
File: resources/views/components/club-modal/tabs/finance-settings.blade.php
- Bank Accounts (dynamic list with add/remove)
- Bank Name, Account Name, Account Number
- IBAN, SWIFT/BIC Code
- BenefitPay Account Number
- Club Status (Active/Inactive/Pending)
- Public Profile Toggle
- Enrollment Fee
- Summary display
- Metadata (created/updated dates, owner info)
3. Supporting Components
User Picker Modal
File: resources/views/components/user-picker-modal.blade.php
- Search users by name, email, or phone (debounced)
- Display user cards with avatar, name, email, phone
- Select button updates main form
4. Backend API Controller
File: app/Http/Controllers/Admin/ClubApiController.php
getUsers()- Fetch all users for user pickergetClub($id)- Get club data for editingcheckSlug()- Validate slug availabilitystore()- Create new club with all related dataupdate($id)- Update existing clubhandleBase64Image()- Process cropped images
🔧 Updated Files
1. Routes
File: routes/web.php
- Updated club store/update routes to use ClubApiController
- Added API endpoints:
GET /admin/api/users- Get all usersGET /admin/api/clubs/{id}- Get club dataPOST /admin/api/clubs/check-slug- Check slug availability
2. Models
File: app/Models/Tenant.php
- Added fillable fields:
established_date,status,public_profile_enabled
File: app/Models/ClubBankAccount.php
- Added fillable field:
benefitpay_account
3. Admin Clubs View
File: resources/views/admin/platform/clubs-with-modal.blade.php
- Changed "Add New Club" button to open modal
- Added "Edit" button on each club card
- Integrated modal and user picker components
- Added JavaScript for modal management
🎨 Features
Design & UX
- ✅ Compact modal with internal scrolling (max-height: 90vh)
- ✅ Responsive design (mobile-friendly)
- ✅ Uses existing design system colors and styles
- ✅ Smooth animations and transitions
- ✅ Progress indicator (Step X of 5)
- ✅ Tab navigation with validation
- ✅ Keyboard accessible
Functionality
- ✅ Create Mode: Empty form, auto-generate slug from name
- ✅ Edit Mode: Pre-filled form with existing data
- ✅ Validation: Per-tab validation before navigation
- ✅ Draft Persistence: Auto-save to localStorage every 30 seconds
- ✅ AJAX Submission: No page reload
- ✅ Image Upload: Integrated with existing cropper component
- ✅ QR Code: Auto-generated, downloadable, printable
- ✅ Map Integration: Leaflet.js with draggable marker
- ✅ Auto-fill: Country selection updates timezone, currency, and map
- ✅ Dynamic Lists: Social links and bank accounts with add/remove
Component Reuse
- ✅
x-takeone-cropper- Image cropping - ✅
x-nationality-dropdown- Country selection - ✅
x-currency-dropdown- Currency selection - ✅
x-timezone-dropdown- Timezone selection - ✅
x-country-code-dropdown- Phone country code
External Libraries
- ✅ Leaflet.js (v1.9.4) - Interactive maps
- ✅ QRCode.js (v1.0.0) - QR code generation
- ✅ Bootstrap 5 - UI framework (already in project)
- ✅ jQuery - DOM manipulation (already in project)
- ✅ Select2 - Enhanced dropdowns (already in project)
📋 Usage
Opening the Modal
Create Mode
// Button in clubs.blade.php
<button type="button"
class="btn btn-primary"
data-bs-toggle="modal"
data-bs-target="#clubModal"
onclick="openClubModal('create')">
<i class="bi bi-plus-circle me-2"></i>Add New Club
</button>
Edit Mode
// Edit button on club card
<button type="button"
class="btn btn-sm btn-light"
onclick="openClubModal('edit', {{ $club->id }})">
<i class="bi bi-pencil"></i>
</button>
Modal Props
<x-club-modal mode="create" />
<!-- or -->
<x-club-modal mode="edit" :club="$club" />
🔄 Data Flow
Create Flow
- User clicks "Add New Club"
- Modal opens in create mode with empty form
- User fills in data across 5 tabs
- Form validates per tab
- On submit: POST to
/admin/clubs - Success: Modal closes, page refreshes
- Draft cleared from localStorage
Edit Flow
- User clicks "Edit" on club card
- AJAX request to
/admin/api/clubs/{id} - Modal opens with pre-filled data
- User modifies data
- On submit: PUT to
/admin/clubs/{id} - Success: Modal closes, page refreshes
🗄️ Database Schema
Required Fields in tenants table:
established_date(date, nullable)status(string, default: 'active')public_profile_enabled(boolean, default: true)
Required Fields in club_bank_accounts table:
benefitpay_account(string, nullable)
🧪 Testing Checklist
Create Mode
- Modal opens with empty form
- Slug auto-generates from club name
- User picker modal works
- All tabs are accessible
- Validation prevents forward navigation
- Images upload via cropper
- QR code generates correctly
- Map initializes and marker is draggable
- Country change updates timezone/currency/map
- Social links can be added/removed
- Bank accounts can be added/removed
- Form submits successfully
- Success message shows
- Page refreshes with new club
Edit Mode
- Modal opens with pre-filled data
- All fields show existing values
- Images display correctly
- Social links load
- Bank accounts load
- Changes can be made
- Form updates successfully
- Changes reflect on page
Validation
- Required fields show errors
- Email format validated
- URL format validated
- IBAN pattern validated
- SWIFT/BIC pattern validated
- Slug uniqueness checked
- Cannot proceed to next tab with errors
Responsive
- Modal fits on mobile screens
- Tabs scroll horizontally on mobile
- Map is usable on mobile
- All buttons are tappable
- Form inputs are accessible
🚀 Deployment Steps
-
Backup Database
php artisan backup:run -
Run Migrations (if new fields added)
php artisan migrate -
Clear Caches
php artisan config:clear php artisan cache:clear php artisan view:clear php artisan route:clear -
Test in Staging
- Test create mode
- Test edit mode
- Test all validations
- Test on mobile devices
-
Deploy to Production
- Push code to repository
- Pull on production server
- Run migrations
- Clear caches
- Test thoroughly
📝 Notes
- The modal uses the existing design system, so it matches the current UI perfectly
- All existing components are reused (cropper, dropdowns, etc.)
- The modal is fully accessible and keyboard-navigable
- Draft persistence helps prevent data loss
- The QR code is high-quality and printable
- The map integration is lightweight and fast
- Bank account data is encrypted in the database
- The implementation follows Laravel best practices
🐛 Known Issues / Future Enhancements
- Add real-time slug availability check (currently validates on submit)
- Add image preview before cropping
- Add bulk import for bank accounts
- Add club logo as favicon generation
- Add more social media platforms
- Add Google Maps API integration (currently uses Leaflet + OSM)
- Add multi-language support for QR code
- Add club statistics in summary sidebar
📞 Support
For issues or questions, refer to:
- Laravel Documentation: https://laravel.com/docs
- Leaflet.js Documentation: https://leafletjs.com
- Bootstrap 5 Documentation: https://getbootstrap.com/docs/5.0
Implementation Date: January 2026
Version: 1.0.0
Status: ✅ Complete and Ready for Testing