# Looking - Frontend Application > **Ionic 3 / Angular 5 mobile application for browsing dating app profiles and stories** This is the frontend mobile application for the "Looking" art project. Built with Ionic 3 and Angular 5, it provides an interactive interface for exploring user profiles, stories, and messages about modern gay dating culture. --- ## πŸ“‹ Table of Contents - [Overview](#overview) - [Tech Stack](#tech-stack) - [Project Structure](#project-structure) - [Pages & Components](#pages--components) - [Services](#services) - [Data Flow](#data-flow) - [Development](#development) - [Building](#building) - [Troubleshooting](#troubleshooting) --- ## 🎯 Overview The frontend is a **hybrid mobile application** that can run as: - Web application (development mode on port 8100) - iOS native app (requires Xcode) - Android native app (requires Android Studio) **Key Features:** - Grid-based profile browsing (Tinder-like swipe interface) - Detailed profile views with images and user stories - Message threads with conversation history - Story submission form ("Tell Your Story") - Tab-based navigation - Offline support with local JSON fallback --- ## πŸ›  Tech Stack | Technology | Version | Purpose | | ------------------- | ------- | ---------------------------------------- | | **Ionic Framework** | 3.9.2 | Hybrid mobile framework | | **Angular** | 5.0.3 | Component framework | | **TypeScript** | 2.4.2 | Type-safe JavaScript | | **RxJS** | 5.5.2 | Reactive programming | | **@angular/http** | 5.0.3 | HTTP client (deprecated, pre-HttpClient) | | **ionic-swipe-all** | 1.2.0 | Swipe gesture library | | **moment** | 2.21.0 | Date/time formatting | | **@ionic/storage** | 2.1.3 | Local storage abstraction | | **ionicons** | 3.0.0 | Icon library | **Build Tool**: `@ionic/app-scripts` 3.2.4 (Ionic's custom webpack wrapper) --- ## πŸ“ Project Structure ``` app/ β”œβ”€β”€ src/ β”‚ β”œβ”€β”€ app/ # Root application module β”‚ β”‚ β”œβ”€β”€ app.component.ts # Root component (title: "Urnings") β”‚ β”‚ β”œβ”€β”€ app.module.ts # Main NgModule with declarations β”‚ β”‚ β”œβ”€β”€ app.html # Root template β”‚ β”‚ β”œβ”€β”€ app.scss # Global styles β”‚ β”‚ └── main.ts # Bootstrap entry point β”‚ β”‚ β”‚ β”œβ”€β”€ pages/ # Page components (routable views) β”‚ β”‚ β”œβ”€β”€ tabs/ # Tab navigation container β”‚ β”‚ β”‚ β”œβ”€β”€ tabs.ts # TabsPage component β”‚ β”‚ β”‚ └── tabs.html # Tab layout (3 tabs) β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ grid/ # Profile grid view (main browse page) β”‚ β”‚ β”‚ β”œβ”€β”€ grid.ts # Grid logic with swipe handling β”‚ β”‚ β”‚ β”œβ”€β”€ grid.html # Grid layout with profile cards β”‚ β”‚ β”‚ └── grid.scss # Grid styles β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ profile/ # Detailed profile view β”‚ β”‚ β”‚ β”œβ”€β”€ profile.ts # Profile display logic β”‚ β”‚ β”‚ β”œβ”€β”€ profile.html # Profile template (name, age, about, pics) β”‚ β”‚ β”‚ └── profile.scss # Profile styles β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ chat/ # Individual conversation view β”‚ β”‚ β”‚ β”œβ”€β”€ chat.ts # Chat message display β”‚ β”‚ β”‚ β”œβ”€β”€ chat.html # Message thread UI β”‚ β”‚ β”‚ └── chat.scss # Chat bubble styles β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ messages/ # Message list/inbox view β”‚ β”‚ β”‚ β”œβ”€β”€ messages.ts # Message list logic β”‚ β”‚ β”‚ β”œβ”€β”€ messages.html # List of conversations β”‚ β”‚ β”‚ └── messages.scss # Message list styles β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ users/ # User list view β”‚ β”‚ β”‚ β”œβ”€β”€ users.ts # User list logic β”‚ β”‚ β”‚ β”œβ”€β”€ users.html # User grid/list β”‚ β”‚ β”‚ └── users.scss # User list styles β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ lightbox/ # Full-screen image viewer β”‚ β”‚ β”‚ β”œβ”€β”€ lightbox.ts # Image zoom/pan logic β”‚ β”‚ β”‚ β”œβ”€β”€ lightbox.html # Fullscreen image display β”‚ β”‚ β”‚ └── lightbox.scss # Lightbox styles β”‚ β”‚ β”‚ β”‚ β”‚ β”œβ”€β”€ information/ # Info/about page β”‚ β”‚ β”‚ β”œβ”€β”€ information.ts # Static info page β”‚ β”‚ β”‚ β”œβ”€β”€ information.html # Project information β”‚ β”‚ β”‚ └── information.scss # Info page styles β”‚ β”‚ β”‚ β”‚ β”‚ └── tell/ # Story submission form β”‚ β”‚ β”œβ”€β”€ tell.ts # Form submission logic β”‚ β”‚ β”œβ”€β”€ tell.html # Story submission form β”‚ β”‚ └── tell.scss # Form styles β”‚ β”‚ β”‚ β”œβ”€β”€ services/ # Shared services β”‚ β”‚ └── profiles.ts # ProfileService for data management β”‚ β”‚ β”‚ β”œβ”€β”€ theme/ # Global theme configuration β”‚ β”‚ └── variables.scss # Ionic theme variables β”‚ β”‚ β”‚ β”œβ”€β”€ assets/ # Static assets β”‚ β”‚ β”œβ”€β”€ data/ # Local JSON data files (fallback) β”‚ β”‚ β”‚ β”œβ”€β”€ profiles.json # All profiles β”‚ β”‚ β”‚ β”œβ”€β”€ profiles initial.json # Initial seed data β”‚ β”‚ β”‚ └── cruises.json # Additional data β”‚ β”‚ β”œβ”€β”€ icon/ # App icons β”‚ β”‚ β”œβ”€β”€ images/ # Profile, message images β”‚ β”‚ β”‚ β”œβ”€β”€ profile/ # Profile photos β”‚ β”‚ β”‚ β”œβ”€β”€ message/ # Message attachments β”‚ β”‚ β”‚ └── cruise/ # Cruise-related images β”‚ β”‚ └── imgs/ # UI images and icons β”‚ β”‚ β”‚ β”œβ”€β”€ index.html # Main HTML entry β”‚ β”œβ”€β”€ manifest.json # PWA manifest β”‚ └── service-worker.js # Service worker for offline support β”‚ β”œβ”€β”€ www/ # Build output directory β”‚ β”œβ”€β”€ build/ # Compiled JS/CSS bundles β”‚ β”‚ β”œβ”€β”€ main.js # Application code β”‚ β”‚ β”œβ”€β”€ vendor.js # Third-party libraries β”‚ β”‚ β”œβ”€β”€ polyfills.js # Browser polyfills β”‚ β”‚ └── main.css # Compiled styles β”‚ └── assets/ # Copied static assets β”‚ β”œβ”€β”€ package.json # Dependencies and scripts β”œβ”€β”€ ionic.config.json # Ionic CLI configuration β”œβ”€β”€ tsconfig.json # TypeScript compiler config β”œβ”€β”€ tslint.json # TSLint rules (deprecated) └── .editorconfig # Editor formatting rules ``` --- ## πŸ“„ Pages & Components ### TabsPage (`pages/tabs/`) **Root navigation container** with three tabs: ```typescript // tabs.ts - Tab configuration tabs = [ { root: GridPage, tabTitle: "Grid", tabIcon: "grid" }, { root: UsersPage, tabTitle: "Users", tabIcon: "people" }, { root: MessagesPage, tabTitle: "Messages", tabIcon: "chatboxes" }, ]; ``` ### GridPage (`pages/grid/`) **Main profile browsing interface** - Tinder-like grid: - Displays profile thumbnails in grid layout - Supports swipe gestures (using `ionic-swipe-all`) - Taps open detailed profile view - Loads profiles from ProfileService - Falls back to local JSON if API unavailable **Key Features:** - Swipe left/right for navigation - Pull-to-refresh - Infinite scroll - Click thumbnail β†’ ProfilePage ### ProfilePage (`pages/profile/`) **Detailed profile view** with: - Profile photo (large detail image) - Name, age, location - "About" section with user story - Multiple photos in gallery - Message thread (if profile has messages) - Navigation to previous/next profile **Navigation:** - Receives profile ID via NavParams - "Next" and "Previous" buttons - Photo gallery opens LightboxPage ### ChatPage (`pages/chat/`) **Message thread view**: - Displays conversation history - Question/answer format - User responses vs. interviewer questions - Image attachments supported - Timestamps with moment.js **Message Types:** - `isUser: false` β†’ Questions (left-aligned) - `isUser: true` β†’ User responses (right-aligned) ### MessagesPage (`pages/messages/`) **Inbox/conversation list**: - Shows all profiles with messages - Displays message preview - Unread indicators - Tap to open ChatPage with full thread ### UsersPage (`pages/users/`) **User list view**: - Alternative view to grid - List format with thumbnails - Quick access to profiles - Filter/search options (if implemented) ### LightboxPage (`pages/lightbox/`) **Full-screen image viewer**: - Zoom and pan gestures - Swipe between photos - Close button returns to profile - Supports pinch-to-zoom ### InformationPage (`pages/information/`) **Static information page**: - About the art project - Artist statement - Project goals - Credits and acknowledgments ### TellPage (`pages/tell/`) **Story submission form**: - Users can submit their own stories - Form fields: name, age, location, story - Photo upload - Submission sends to API (if connected) --- ## πŸ”Œ Services ### ProfileService (`services/profiles.ts`) **Central data management service** for profiles. **Endpoints:** ```typescript endpoint: "http://localhost:27017/urnings/profiles"; // Primary API fallback: "assets/data/profiles.json"; // Local fallback epSubmitted: "/submitted"; // Submitted profiles epVerified: "/verified"; // Verified profiles ``` **Methods:** ```typescript load(); // Load all profiles loadSubmitted(); // Load submitted (pending) profiles loadVerified(); // Load verified (approved) profiles getProfiles(); // Get cached profiles getProfileById(id); // Get specific profile getNextProfile(id); // Navigate to next profile getPreviousProfile(id); // Navigate to previous ``` **Data Flow:** 1. Tries to fetch from API endpoint 2. On error, falls back to local `assets/data/profiles.json` 3. Caches data in memory 4. Builds IDβ†’index map for navigation **Fallback Behavior:** ```typescript doGetRequest(endpoint, resolve, type) { this.http.get(endpoint).subscribe( (data) => { /* Use API data */ }, (error) => { // API failed β†’ use local JSON this.doGetRequest(this.fallback, resolve, type); } ); } ``` --- ## πŸ”„ Data Flow ### Profile Loading Flow ```mermaid graph TD A[GridPage loads] --> B{ProfileService.load} B --> C[Try API: http://localhost:27017/urnings/profiles] C --> D{API Success?} D -->|Yes| E[Store profiles in memory] D -->|No| F[Fallback to assets/data/profiles.json] F --> E E --> G[Build ID-to-index map] G --> H[Return profiles to GridPage] H --> I[Display grid of thumbnails] I --> J[User taps profile] J --> K[Navigate to ProfilePage with ID] K --> L[ProfilePage fetches profile from service] L --> M[Display full profile details] ``` ### Message Loading Flow ```mermaid graph TD A[ProfilePage loads] --> B[Get profile by ID] B --> C{Profile has messages?} C -->|Yes| D[Extract messages array] C -->|No| E[Show 'No messages'] D --> F[Display in ChatPage] F --> G[Format with moment.js] G --> H[Render question/answer pairs] ``` --- ## πŸ’» Development ### Start Dev Server ```bash # From project root npm run dev:app # Or from app directory cd app ionic serve --host=0.0.0.0 --port=8100 ``` **Access**: http://localhost:8100 ### Live Reload Ionic's dev server watches for file changes and automatically: - Recompiles TypeScript - Rebuilds SCSS - Reloads browser - Preserves dev tools open ### Chrome DevTools Open Chrome DevTools to: - Inspect components - Debug TypeScript (source maps enabled) - Test responsive layouts - Simulate mobile devices - Monitor network requests ### API Configuration To switch between local and remote API: **Edit `services/profiles.ts`:** ```typescript // Local API (backend running on port 3069) endpoint: "http://localhost:3069/profiles"; // Remote API (production) endpoint: "https://api.pfosi.mifi.dev/profiles"; // Fallback (always local) fallback: "assets/data/profiles.json"; ``` --- ## πŸ—οΈ Building ### Development Build ```bash npm run build # or ionic build ``` Output: `www/` directory ### Production Build ```bash ionic build --prod ``` **Optimizations:** - Minification - Tree shaking - Ahead-of-time (AOT) compilation - CSS purging - Source map generation (optional) ### Build for Mobile Platforms **iOS**: ```bash ionic cordova build ios --prod --release # Requires Xcode and iOS development certificates ``` **Android**: ```bash ionic cordova build android --prod --release # Requires Android Studio and signing keys ``` **Note**: Mobile builds require additional Cordova setup not covered here. --- ## πŸ”§ Troubleshooting ### `node-sass` Build Failed **Error:** ``` Error: `gyp` failed with exit code: 1 Module 'node-sass' not found ``` **Solution:** ```bash # node-sass requires Python 2.7 (included in DevContainer) # If running locally: npm rebuild node-sass --force # Or use legacy peer deps npm install --legacy-peer-deps ``` **Why?** `node-sass` is a native module that requires Python 2.7 and build tools. The DevContainer includes these dependencies via symlinks. --- ### Peer Dependency Warnings **Error:** ``` npm WARN ERESOLVE overriding peer dependency ``` **Solution:** ```bash # Use legacy peer dependency resolution (npm 7+) npm install --legacy-peer-deps ``` **Why?** Ionic 3 and Angular 5 were built before npm 7's strict peer dependency checking. The `--legacy-peer-deps` flag uses npm 6 behavior. --- ### Module Not Found Errors **Error:** ``` Error: Cannot find module '@angular/core' ``` **Solution:** ```bash # Remove node_modules and reinstall rm -rf node_modules package-lock.json npm install --legacy-peer-deps ``` --- ### JavaScript Heap Out of Memory **Error:** ``` FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed ``` **Solution:** ```bash # Increase Node.js memory limit export NODE_OPTIONS="--max-old-space-size=4096" npm run ionic:serve ``` --- ### Ionic Serve Port Already in Use **Error:** ``` Error: Port 8100 is already in use ``` **Solution:** ```bash # Find process using port 8100 lsof -i :8100 # Kill the process kill -9 # Or use different port ionic serve --port=8101 ``` --- ### TypeScript Compilation Errors **Error:** ``` Error: TS2304: Cannot find name 'Promise' ``` **Solution:** ```bash # Verify TypeScript version matches project npm install typescript@2.4.2 --save-dev --save-exact ``` **Check `tsconfig.json`:** ```json { "compilerOptions": { "lib": ["es2015", "dom"], "target": "es5" } } ``` --- ### CORS Errors in Browser **Error:** ``` Access to XMLHttpRequest at 'http://localhost:3069/profiles' blocked by CORS policy ``` **Solution:** **Option 1**: Backend already allows all origins: ```javascript // backend/src/app.js res.header("Access-Control-Allow-Origin", "*"); ``` **Option 2**: Use Ionic's proxy (for dev server): **Edit `ionic.config.json`:** ```json { "proxies": [ { "path": "/api", "proxyUrl": "http://localhost:3069" } ] } ``` **Update service:** ```typescript endpoint: "/api/profiles"; // Proxied through dev server ``` --- ### Images Not Loading **Error:** ``` 404 Not Found: http://localhost:8100/assets/images/profile/john.png ``` **Solutions:** 1. **Verify image exists:** ```bash ls -la src/assets/images/profile/ ``` 2. **Check path in data:** ```json // Should be relative to assets/images/ "pic": { "thumb": "profile/john_thumbnail.png", // βœ… Correct "detail": "/profile/john_detail.png" // ❌ Leading slash breaks it } ``` 3. **Rebuild to copy assets:** ```bash ionic build ``` --- ### Service Worker Issues (Offline Mode) **Problem**: Stale data cached, changes not appearing **Solution:** ```bash # Clear service worker cache in Chrome DevTools Application β†’ Storage β†’ Clear site data # Or disable service worker during development # Comment out service worker registration in index.html ``` --- ### Ionic CLI Not Found **Error:** ``` ionic: command not found ``` **Solution:** ```bash # Install Ionic CLI globally (included in DevContainer) npm install -g @ionic/cli # Verify installation ionic --version ``` --- ## πŸ“š Additional Resources - **Ionic 3 Documentation**: https://ionicframework.com/docs/v3/ - **Angular 5 Documentation**: https://v5.angular.io/docs - **TypeScript Documentation**: https://www.typescriptlang.org/docs/handbook/basic-types.html - **RxJS 5 Documentation**: https://rxjs-dev.firebaseapp.com/api --- ## πŸ”— Related Documentation - [Root README](../README.md) - Project overview and quick start - [Backend README](../backend/README.md) - API server documentation - [API Reference](../backend/API.md) - REST API endpoints - [Database Schema](../backend/SCHEMA.md) - MongoDB collections - [DevContainer Guide](../.devcontainer/README.md) - Development environment - [Deployment Guide](../DEPLOYMENT.md) - Production deployment --- **Need Help?** Check the [root troubleshooting section](../README.md#troubleshooting) or backend documentation for API-related issues.