Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Flutter-based gym access app: OTP login, dynamic QR generation, mock/real API support, secure storage, and turnstile integration.

Notifications You must be signed in to change notification settings

sebahattinn/GymPassQr

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

14 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ’ͺ GymPass QR - Digital Gym Access System

Flutter Dart License Platform

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.

πŸ“± Screenshots

Phone Input OTP Verification Home Screen (Active) Home Screen (Inactive)
Phone Input OTP Verification Home Screen Active Home Screen Inactive

✨ Features

  • πŸ“² 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

πŸš€ Quick Start

Prerequisites

  • 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

Installation

  1. Clone the repository
git clone https://github.com/your-company/gympass-qr.git
cd gympass-qr
  1. Install dependencies
flutter pub get
  1. Run the app
# For development with hot reload
flutter run

# For specific device
flutter run -d device_id

# List available devices
flutter devices

πŸ§ͺ Testing

Test Accounts (Mock Mode)

The 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

How to Test

  1. Run the app in debug mode
  2. Click on any test number in the phone input screen (they're clickable!)
  3. Use OTP: 123456 for all test accounts
  4. Test persistence: Login β†’ Close app β†’ Reopen (should skip login)
  5. Test logout: Click logout β†’ Confirm β†’ Returns to login

πŸ”§ Configuration

Switch Between Mock and Real API

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';

API Endpoints Configuration

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';

Environment Variables

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;
}

πŸ“ Project Structure

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

πŸ”Œ API Integration

Expected API Response Formats

Your backend should return data in these formats:

Send OTP Response

{
  "success": true,
  "message": "OTP sent successfully"
}

Verify OTP Response

{
  "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
  }
}

Generate QR Response

{
  "userId": "user_001",
  "token": "qr_token_abc123",
  "validUntil": "2024-01-15T14:30:00Z",
  "metadata": {
    "gymId": "gym_001",
    "location": "Main Branch"
  }
}

πŸ—οΈ Building for Production

Android

  1. Update version in pubspec.yaml:
version: 1.0.0+1  # Increment for each release
  1. Build APK:
flutter build apk --release

# Output: build/app/outputs/flutter-apk/app-release.apk
  1. Build App Bundle (for Play Store):
flutter build appbundle --release

# Output: build/app/outputs/bundle/release/app-release.aab

iOS

  1. Update version in Xcode or pubspec.yaml

  2. Build for iOS:

flutter build ios --release

# Then open Xcode and archive
open ios/Runner.xcworkspace
  1. Archive and upload through Xcode

πŸ› Debugging

Enable Debug Logs

// In lib/utils/logger.dart
AppLogger.debug('Your debug message');
AppLogger.info('Info message');
AppLogger.error('Error message', error);

Common Issues & Solutions

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 Logs

# View all logs
flutter logs

# Filter logs
flutter logs | grep "QR"

πŸ“¦ Dependencies

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.5

πŸ”„ State Management

The 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);

πŸ›‘οΈ Security

  • βœ… 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

🀝 Contributing

  1. Fork the repository
  2. Create your feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

Coding Standards

  • Follow Flutter style guide
  • Add comments for complex logic
  • Write unit tests for new features
  • Update documentation for API changes

πŸ“ License

This project is proprietary and confidential. All rights reserved.

πŸ‘₯ Team

  • Project Manager: [Name]
  • Mobile Developer: [Name]
  • Backend Developer: [Name]
  • UI/UX Designer: [Name]

πŸ“ž Support

For support, email [email protected] or create an issue in the repository.

🚦 Project Status

Status

  • βœ… 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)

πŸ“Š Performance

  • App Size: ~15 MB (Android), ~25 MB (iOS)
  • Startup Time: < 2 seconds
  • QR Generation: < 100ms
  • API Response: < 200ms average
  • Token Refresh: Automatic, seamless

πŸ”— Useful Links


🎯 Quick Commands Reference

# 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 code

Made with ❀️ by the GymPass Team

Last Updated: January 2025

About

Flutter-based gym access app: OTP login, dynamic QR generation, mock/real API support, secure storage, and turnstile integration.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published