A modern mobile application that replaces physical gym membership cards with secure QR codes. Members can access gym facilities by simply showing a QR code on their phone.
| Phone Input | OTP Verification | Home Screen (Active) | Home Screen (Inactive) |
|---|---|---|---|
- π² One-time SMS Authentication - Login once, stay logged in for 30 days
- π Secure Token Management - Encrypted storage with automatic refresh
- π· Dynamic QR Codes - Auto-refreshing every 5 minutes for security
- π Membership Tracking - See your membership status and expiry date
- π Offline Support - QR codes work without internet connection
- π¨ Beautiful UI - Modern, clean interface with smooth animations
- π Auto-Login - No need to login every time you open the app
- Flutter SDK (3.x or higher)
- Dart SDK (3.0 or higher)
- Android Studio / VS Code
- iOS: Xcode 14+ and CocoaPods
- Android: Android Studio and Android SDK
- Clone the repository
git clone https://github.com/your-company/gympass-qr.git
cd gympass-qr- Install dependencies
flutter pub get- Run the app
# For development with hot reload
flutter run
# For specific device
flutter run -d device_id
# List available devices
flutter devicesThe app comes with built-in test accounts for development:
| Phone Number | User Type | Description | Test OTP |
|---|---|---|---|
+90 555 123 4567 |
Premium | Active membership (150 days) | 123456 |
+90 555 987 6543 |
Standard | Expiring soon (5 days) | 123456 |
+90 555 555 5555 |
Basic | Expired membership | 123456 |
- Run the app in debug mode
- Click on any test number in the phone input screen (they're clickable!)
- Use OTP:
123456for all test accounts - Test persistence: Login β Close app β Reopen (should skip login)
- Test logout: Click logout β Confirm β Returns to login
Edit lib/config/constants.dart:
// For DEVELOPMENT (Mock Data)
static const bool useMockData = true;
static const String baseUrl = 'mock://api';
// For PRODUCTION (Real API)
static const bool useMockData = false;
static const String baseUrl = 'https://api.gympass.com/v1';If your API endpoints are different, update them in constants.dart:
static const String sendOtpEndpoint = '/auth/send-otp';
static const String verifyOtpEndpoint = '/auth/verify-otp';
static const String getUserProfileEndpoint = '/user/profile';
static const String refreshTokenEndpoint = '/auth/refresh';
static const String generateQrEndpoint = '/user/generate-qr';Create different configs for each environment:
// lib/config/dev_config.dart
class DevConfig {
static const String baseUrl = 'https://dev-api.gympass.com';
static const bool enableLogging = true;
}
// lib/config/prod_config.dart
class ProdConfig {
static const String baseUrl = 'https://api.gympass.com';
static const bool enableLogging = false;
}lib/
βββ main.dart # App entry point
βββ app.dart # App configuration
β
βββ config/ # Configuration files
β βββ constants.dart # App-wide constants
β βββ routes.dart # Navigation routing
β βββ theme.dart # UI theme and styling
β
βββ models/ # Data models
β βββ user_model.dart # User data structure
β βββ auth_model.dart # Authentication models
β βββ qr_model.dart # QR code model
β
βββ services/ # Business logic
β βββ api_service.dart # API communication (Dio)
β βββ auth_service.dart # Authentication logic
β βββ storage_service.dart # Secure local storage
β βββ qr_service.dart # QR code generation
β
βββ providers/ # State management (Provider)
β βββ auth_provider.dart # Authentication state
β βββ user_provider.dart # User and QR state
β
βββ screens/ # UI screens
β βββ splash/ # Splash screen
β β βββ splash_screen.dart
β βββ auth/ # Authentication screens
β β βββ phone_input_screen.dart
β β βββ otp_verification_screen.dart
β βββ home/ # Main screen
β βββ home_screen.dart
β
βββ widgets/ # Reusable UI components
β βββ common/
β βββ custom_button.dart
β βββ loading_overlay.dart
β
βββ utils/ # Helper utilities
β βββ validators.dart # Input validation
β βββ logger.dart # Debug logging
β
βββ mock/ # Mock data for testing
βββ mock_data_service.dart
Your backend should return data in these formats:
{
"success": true,
"message": "OTP sent successfully"
}{
"accessToken": "eyJhbGciOiJIUzI1NiIs...",
"refreshToken": "eyJhbGciOiJIUzI1NiIs...",
"expiresIn": 2592000,
"user": {
"id": "user_001",
"firstName": "Ahmet",
"lastName": "YΔ±lmaz",
"phoneNumber": "+905551234567",
"profilePhotoUrl": "https://example.com/photo.jpg",
"membershipStart": "2024-01-01",
"membershipEnd": "2024-07-01",
"membershipType": "Premium",
"isActive": true
}
}{
"userId": "user_001",
"token": "qr_token_abc123",
"validUntil": "2024-01-15T14:30:00Z",
"metadata": {
"gymId": "gym_001",
"location": "Main Branch"
}
}- Update version in
pubspec.yaml:
version: 1.0.0+1 # Increment for each release- Build APK:
flutter build apk --release
# Output: build/app/outputs/flutter-apk/app-release.apk- Build App Bundle (for Play Store):
flutter build appbundle --release
# Output: build/app/outputs/bundle/release/app-release.aab-
Update version in Xcode or
pubspec.yaml -
Build for iOS:
flutter build ios --release
# Then open Xcode and archive
open ios/Runner.xcworkspace- Archive and upload through Xcode
// In lib/utils/logger.dart
AppLogger.debug('Your debug message');
AppLogger.info('Info message');
AppLogger.error('Error message', error);| Issue | Solution |
|---|---|
| Can't receive OTP | Check phone number format (+90 prefix for Turkey) |
| Token expired error | Logout and login again |
| QR not generating | Check internet connection and API status |
| Build fails | Run flutter clean then flutter pub get |
| iOS build fails | Run cd ios && pod install |
# View all logs
flutter logs
# Filter logs
flutter logs | grep "QR"dependencies:
flutter:
sdk: flutter
# State Management
provider: ^6.1.1
# Networking
dio: ^5.4.0
pretty_dio_logger: ^1.3.1
connectivity_plus: ^5.0.2
# Storage
flutter_secure_storage: ^9.0.0
shared_preferences: ^2.2.2
# UI Components
qr_flutter: ^4.1.0
pin_code_fields: ^8.0.1
intl_phone_field: ^3.2.0
flutter_spinkit: ^5.2.0
cached_network_image: ^3.3.1
# Navigation
go_router: ^13.0.0
# Utilities
logger: ^2.0.2
intl: ^0.18.1
equatable: ^2.0.5The app uses Provider for state management:
- AuthProvider: Manages authentication state, tokens, and login flow
- UserProvider: Manages user data, QR codes, and membership info
Example usage:
// Read state
final authProvider = context.read<AuthProvider>();
// Watch for changes
final user = context.watch<UserProvider>().user;
// Call methods
await authProvider.sendOtp(phoneNumber);- β Encrypted Storage: Tokens stored using platform-specific encryption
- β HTTPS Only: All API calls over secure connection
- β Token Expiry: Automatic token refresh before expiry
- β OTP Rate Limiting: 3 attempts per 30 minutes
- β QR Rotation: QR codes refresh every 5 minutes
- β No Sensitive Logs: No passwords or tokens in debug logs
- Fork the repository
- Create your feature branch (
git checkout -b feature/AmazingFeature) - Commit your changes (
git commit -m 'Add some AmazingFeature') - Push to the branch (
git push origin feature/AmazingFeature) - Open a Pull Request
- Follow Flutter style guide
- Add comments for complex logic
- Write unit tests for new features
- Update documentation for API changes
This project is proprietary and confidential. All rights reserved.
- Project Manager: [Name]
- Mobile Developer: [Name]
- Backend Developer: [Name]
- UI/UX Designer: [Name]
For support, email [email protected] or create an issue in the repository.
- β SMS Authentication
- β QR Code Generation
- β Token Persistence
- β Auto-refresh
- β Offline Support
- π Biometric Login (Coming Soon)
- π Multiple Gym Support (Coming Soon)
- π Guest Pass Feature (Coming Soon)
- App Size: ~15 MB (Android), ~25 MB (iOS)
- Startup Time: < 2 seconds
- QR Generation: < 100ms
- API Response: < 200ms average
- Token Refresh: Automatic, seamless
# Development
flutter run # Run in debug mode
flutter run --release # Run in release mode
flutter run --profile # Run in profile mode
# Testing
flutter test # Run all tests
flutter test test/widget_test.dart # Run specific test
# Building
flutter build apk # Build Android APK
flutter build ios # Build iOS
flutter build appbundle # Build for Play Store
# Cleaning
flutter clean # Clean build files
flutter pub cache clean # Clean pub cache
# Dependencies
flutter pub get # Get dependencies
flutter pub upgrade # Upgrade dependencies
flutter pub outdated # Check outdated packages
# Code Generation
flutter pub run build_runner build # Run code generation
# Formatting
flutter format . # Format all Dart files
flutter analyze # Analyze codeMade with β€οΈ by the GymPass Team
Last Updated: January 2025