GoPaddi is an iOS application designed to help users create and manage trips. The app closely follows the provided Figma UI design and integrates with a CRUD API for trip management. The project demonstrates best practices in UIKit (both programmatic and storyboard), SwiftUI, and modern iOS architecture.
- Trip Creation: Create trips with location, dates, trip name, travel style, and description
- Trip Management: View and manage all your planned trips
- Activities Planning: Plan activities, hotels, and flights for your trips
- Pull-to-Refresh: Refresh trip list with pull-to-refresh gesture
- Loading Indicators: Visual feedback during API operations
- Form Validation: Comprehensive validation before trip creation
- Custom UI Components: Reusable, styled components following design system
Others:
- **UI Fidelity:** Pixel-perfect recreation of the Figma design, including spacing, fonts, colors, and layout.
- **Responsiveness:** Adapts to various iPhone screen sizes.
- **UIKit & SwiftUI:**
- At least one screen implemented with programmatic UIKit.
- At least one screen implemented with SwiftUI.
- **API Integration:** Full CRUD operations for trips using the provided API.
- **Error Handling:** Graceful handling of API errors and form validation.
- **User Feedback:** Clear success/failure messages for user actions.
- Xcode: Version 14.0 or later
- iOS: Deployment target iOS 15.0+
- Swift: Swift 5.0+
- macOS: macOS 12.0 or later (for development)
- Clone the repository:
git clone https://github.com/omokagbo/GoPaddi-Assessment.git cd GoPaddi - Open
GoPaddi.xcodeprojin Xcode (version 14 or later recommended). - The app majorly uses native frameworks
- Select a simulator or device and press
Cmd+Rto build and run the app.
-
Architecture:
The app uses the MVVM (Model-View-ViewModel) pattern for clear separation of concerns. Routing is handled by dedicated router classes (e.g.,HomeRouter) to manage navigation logic. Dependency Injection is used for modularity and testability (seeHomeDI). -
Key Technologies:
- UIKit: Used for main navigation and core screens, with both storyboard and programmatic approaches.
- SwiftUI: At least one major screen is implemented using SwiftUI for modern declarative UI.
- Networking: API integration is handled via
URLSessionwith async/await for CRUD operations. - Accessibility: Dynamic type, VoiceOver support, and color contrast are considered.
- Testing: Includes unit and UI tests for reliability.
This structure ensures maintainability, scalability, and a robust user experience.
https://gopaddi-trips.free.beeceptor.com/api
- Endpoint:
/trips/ - Method:
GET - Response: Array of
Tripobjects - Example:
NetworkService.shared.fetchTrips { result in switch result { case .success(let trips): // Handle trips array case .failure(let error): // Handle error } }
- Endpoint:
/trips/ - Method:
POST - Request Body:
CreateTripRequest{ "location": "Laghouat Algeria", "startDate": "Sun, March 15", "endDate": "Sun, Mar 22", "tripName": "Algeria 2026 trip", "travelStyle": "Solo", "description": "Relaxation trip" } - Response: Single
Tripobject - Example:
let request = CreateTripRequest( location: "Laghouat Algeria", startDate: "Sun, March 15", endDate: "Sun, Mar 22", tripName: "Algeria 2026 trip", travelStyle: "Solo", description: "Relaxation trip" ) NetworkService.shared.createTrip(request) { result in switch result { case .success(let trip): // Handle created trip case .failure(let error): // Handle error } }
The NetworkService provides generic methods for any API endpoint:
// GET request
NetworkService.shared.get(
endpoint: "/custom-endpoint/",
queryParameters: ["key": "value"],
responseType: YourModel.self
) { result in
// Handle result
}
// POST request
NetworkService.shared.post(
endpoint: "/custom-endpoint/",
body: YourRequestModel(),
responseType: YourResponseModel.self
) { result in
// Handle result
}The NetworkError enum covers various error scenarios:
invalidURL: Malformed URLnoData: Empty responsedecodingError(Error): JSON decoding failureencodingError(Error): Request encoding failureserverError(Int): HTTP error status codesunknown(Error): Other network errors
- Swift 6.0+: Primary programming language
- UIKit: Main UI framework for view controllers
- SwiftUI: Used for forms and pickers (integrated via
UIHostingController) - Foundation: Core framework for networking and data handling
- MVVM: Model-View-ViewModel architecture
- Routers: for navigation in the application
- Singleton:
NetworkService.shared - Delegate:
TripCardTableViewCellDelegatefor cell actions - Callback/Closure: ViewModel callbacks for state updates
- URLSession: Native iOS networking
- JSON Encoding/Decoding:
Codableprotocol - Generic Programming: Type-safe API requests
- Auto Layout: Programmatic constraints
- Color Assets: Named colors in Asset Catalog
- Sheet Presentations: Custom detents for modal presentations
The majority of the app uses UIKit with programmatic Auto Layout:
- HomeViewController: Main screen with scroll view, form, and trip list
- TripDetailsViewController: Activities planning screen
- TripCardTableViewCell: Custom table view cell
- Custom Components: All reusable components (buttons, labels, inputs) are UIKit-based
SwiftUI is used selectively for specific features:
- CreateTripDetailsView: Trip creation form (presented as sheet)
- DatePickerView: Date selection calendar
- LocationView: Location picker interface
SwiftUI views are integrated into UIKit using UIHostingController:
let createTripDetailsView = CreateTripDetailsView(...)
let hostingController = UIHostingController(rootView: tripDetailsView)
hostingController.modalPresentationStyle = .pageSheet
present(hostingController, animated: true)- UIKit: Better control over complex layouts, table views, and existing codebase
- SwiftUI: Faster development for forms and simple views, modern declarative syntax
- Hybrid: Leverages strengths of both frameworks
- PrimaryLabel: Bold, 18px,
PrimaryTextColor - SecondaryLabel: Medium, 14px,
SecondaryTextColor
- AppPrimaryButton: Primary action button with:
AppPrimaryColorbackground- White text
- Satoshi Bold, 14px
- 4px corner radius
- Custom padding and letter spacing
- CreateTripInputField: Custom input field with:
- Icon support
- Title and value labels
BackgroundColorbackground- 1px border
- Satoshi font family
-
Date Format
- Dates are stored as strings in format:
"Mon, Jan 21" - Duration calculation may fail if date format doesn't match
- Consider using ISO 8601 or
Dateobjects for production
- Dates are stored as strings in format:
-
Error Handling
- Network errors are displayed as alerts
- No retry mechanism for failed requests
- Consider implementing exponential backoff for production
-
State Management
- ViewModel uses callbacks instead of Combine or RxSwift
- Simple but may not scale for complex state
- Consider Combine for reactive programming
-
API
- Beeceptor endpoint may have rate limits
-
Memory Management
- Weak references used in closures to prevent retain cycles
- No explicit memory management issues observed
- Monitor for leaks in production
No third-party dependencies - The project uses only native iOS frameworks:
- UIKit
- SwiftUI
- Foundation
- URLSession
This keeps the app lightweight and avoids dependency management complexity.
- Persistence: Add Core Data or UserDefaults for offline support
- Image Loading: Implement remote image loading with caching
- Error Recovery: Add retry logic and offline queue
- Testing: Add comprehensive unit and UI tests
- Accessibility: Add VoiceOver support and accessibility labels
- Localization: Support multiple languages
- Dark Mode: Implement dark mode support
- Animations: Add smooth transitions and loading animations
- Separation of Concerns: Clear MVVM architecture
- Reusability: Custom components for consistency
- Type Safety: Strong typing with Swift generics
- Error Handling: Comprehensive error types
- Code Organization: Feature-based folder structure
- Lazy Loading: Table view cells are reused efficiently
- Main Thread: All UI updates dispatched to main queue
- Network: Single URLSession instance (shared)
- Memory: Weak references prevent retain cycles