Frontend - User Wallet App¶
Overview¶
The User Wallet App is a React TypeScript web application that allows golf club members to: - View their wallet balance (giftcards, range tokens, greenfee tickets) - Redeem value from wallet items - Claim giftcards using codes - Track recent transactions
Technology Stack¶
- Framework: React 18 with TypeScript
- Build Tool: Create React App (Webpack)
- State Management: React Hooks + Context (minimal, no Redux)
- HTTP Client: Axios
- Routing: React Router v6
- Authentication: Firebase Auth
- Styling: Vanilla CSS with responsive design
Project Structure¶
webapp/
├── public/ # Static files
├── src/
│ ├── config/ # Configuration
│ │ ├── firebase.ts # Firebase initialization
│ │ └── api.ts # API endpoints config
│ │
│ ├── services/ # API integration layer
│ │ └── walletApi.ts # Wallet API client
│ │
│ ├── hooks/ # Custom React hooks
│ │ ├── useAuth.ts # Auth state management
│ │ └── useWalletProjection.ts # Wallet data fetching
│ │
│ ├── pages/ # Page components
│ │ ├── LoginPage.tsx # Authentication UI
│ │ └── WalletPage.tsx # Main wallet dashboard
│ │
│ ├── types/ # TypeScript definitions
│ │ └── index.ts # All API types
│ │
│ ├── styles/ # CSS stylesheets
│ │ ├── Auth.css
│ │ └── Wallet.css
│ │
│ ├── App.tsx # Main app + routing
│ ├── index.tsx # React root
│ └── App.css # Global styles
│
├── .env.example # Environment template
├── package.json
├── tsconfig.json
└── README.md
Key Features¶
1. Authentication¶
- Email/Password sign-up and login
- Firebase Authentication
- Session persistence
- Automatic token refresh
File: src/pages/LoginPage.tsx
2. Wallet Dashboard¶
- Real-time balance display
- Four card summary (Giftcards, Tokens, 9-hole tickets, 18-hole tickets)
- Recent transaction history
- Pull-to-refresh capability
File: src/pages/WalletPage.tsx
3. Redemption¶
- Select wallet item to redeem from
- Enter amount
- Automatic balance update
API Call: POST /wallet_redeem
4. Code-Based Claims¶
- Enter claim code (e.g., ABCD-EFGH-IJKL-MNOP)
- Automatic wallet item creation
- Prevents duplicate claims (backend idempotency)
API Call: POST /wallet_claim
5. Real-time Sync¶
- Automatic refresh every 30 seconds
- Manual refresh button
- Optimistic UI updates
Hook: useWalletProjection
API Integration¶
The app communicates with the backend REST API:
Configuration¶
// src/config/api.ts
export const FUNCTIONS = {
GIFTCARDS_ISSUE: `${API_BASE_URL}/giftcards_issue`,
WALLET_REDEEM: `${API_BASE_URL}/wallet_redeem`,
WALLET_CLAIM: `${API_BASE_URL}/wallet_claim`,
WALLET_PROJECTIONS: `${API_BASE_URL}/wallet_projections`,
HEALTH_CHECK: `${API_BASE_URL}/healthCheck`,
};
Authentication¶
All API calls include Firebase ID token:
const headers = {
Authorization: `Bearer ${idToken}`,
"Content-Type": "application/json"
};
Error Handling¶
- Automatic retry logic for network errors
- User-friendly error messages
- Detailed error logging to console
Setup Instructions¶
1. Clone & Install¶
cd Gavekort-multitennenant/webapp
npm install
2. Configure Environment¶
Create .env.local:
cp .env.example .env.local
Fill in your Firebase project credentials:
REACT_APP_FIREBASE_API_KEY=your-api-key
REACT_APP_FIREBASE_AUTH_DOMAIN=your-project.firebaseapp.com
REACT_APP_FIREBASE_PROJECT_ID=your-project-id
REACT_APP_FIREBASE_STORAGE_BUCKET=your-project.appspot.com
REACT_APP_FIREBASE_MESSAGING_SENDER_ID=your-sender-id
REACT_APP_FIREBASE_APP_ID=your-app-id
REACT_APP_API_BASE_URL=https://us-central1-your-project.cloudfunctions.net
3. Run Development Server¶
npm start
Opens at http://localhost:3000
4. Build for Production¶
npm run build
Creates optimized bundle in build/ directory (128.88 kB gzipped)
Development Guide¶
Custom Hooks¶
useAuth()¶
const { user, loading, error } = useAuth();
// Returns:
// - user: { uid, email, displayName, photoURL }
// - loading: boolean (initial auth check)
// - error: Error | null
useWalletProjection(userId)¶
const { projection, loading, error, refresh } = useWalletProjection(userId);
// Returns:
// - projection: WalletProjection | null
// - loading: boolean
// - error: Error | null
// - refresh: () => Promise<void> // Manual refresh
API Service¶
// src/services/walletApi.ts
// Get wallet balance
await getWalletProjection(userId);
// Redeem value
await redeemValue(walletItemId, amount, reason);
// Claim code
await claimCode(code, externalAccountId);
// Check health
await checkHealth();
Adding a New Page¶
- Create component in
src/pages/NewPage.tsx - Add route in
App.tsx:typescript <Route path="/new" element={<NewPage />} /> - Create styles in
src/styles/NewPage.css - Use hooks for data fetching
Adding a Component¶
- Create in
src/components/MyComponent.tsx - Create styles in
src/styles/MyComponent.css - Export from component file
- Use in pages
Styling¶
Color Scheme¶
- Primary:
#667eea(Purple) - Secondary:
#764ba2(Dark Purple) - Success:
#3a3(Green) - Error:
#c33(Red) - Background:
#f5f5f5(Light Gray)
Responsive Breakpoints¶
/* Tablet */
@media (max-width: 768px) { }
/* Mobile */
@media (max-width: 480px) { }
CSS Grid¶
Balance cards use CSS Grid for responsive layout:
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
Security Features¶
- Protected Routes
- Login redirect for unauthenticated users
-
Session persistence
-
API Authentication
- Firebase ID tokens included in all requests
-
Automatic token refresh before expiry
-
CORS
- Cloud Functions configured for public CORS
-
API endpoints validated in
config/api.ts -
Input Validation
- Client-side form validation
- Server-side validation on backend
Testing¶
Unit Tests (Recommended Setup)¶
npm test
Integration Testing¶
# With Firebase Emulator
firebase emulators:start
# In another terminal
npm start
Test user: test@example.com / password123
Deployment¶
Firebase Hosting¶
# Install Firebase tools
npm install -g firebase-tools
# Login
firebase login
# Deploy
firebase deploy --only hosting
Environment-Specific Builds¶
# Development
REACT_APP_API_BASE_URL=http://localhost:5001 npm build
# Production
REACT_APP_API_BASE_URL=https://prod.example.com npm build
Performance Optimization¶
Current Optimizations¶
- Code splitting via React Router
- CSS minification
- Gzipped bundle size: 128.88 kB
Recommended Enhancements¶
- Add React.memo() for expensive components
- Lazy load pages with React.lazy()
- Cache API responses with SWR or React Query
- PWA capabilities for offline support
Browser Support¶
- Chrome/Edge 90+
- Firefox 88+
- Safari 14+
- Mobile browsers (iOS Safari, Chrome Mobile)
Troubleshooting¶
Build Fails with TypeScript Errors¶
npm run build -- --verbose
Check error output and fix type issues.
API Calls Return 401 (Unauthorized)¶
- Verify
.env.localhas correct Firebase credentials - Check Firebase project has Authentication enabled
- Verify ID token is valid:
auth.currentUser?.getIdToken()
"Cannot find module" Errors¶
rm -rf node_modules package-lock.json
npm install
Dev Server Won't Start¶
# Kill existing process on port 3000
lsof -ti:3000 | xargs kill -9
# Or use different port
PORT=3001 npm start
Next Steps¶
- Add Admin Features (if user is ADMIN role)
- Implement Transaction Filtering
- Add Dark Mode
- Setup CI/CD Pipeline
- Add Analytics
- Multi-language Support (i18n)
- QR Code Scanner for claiming codes