https://github.com/thecodedaniel/tech_gadol
Tech Gadol mobile app
https://github.com/thecodedaniel/tech_gadol
Last synced: 8 days ago
JSON representation
Tech Gadol mobile app
- Host: GitHub
- URL: https://github.com/thecodedaniel/tech_gadol
- Owner: TheCodeDaniel
- Created: 2026-03-15T23:38:12.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2026-03-16T02:45:48.000Z (3 months ago)
- Last Synced: 2026-03-16T11:39:49.639Z (3 months ago)
- Language: Dart
- Size: 342 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# Tech Gadol — Product Catalog App
A Flutter application that displays a product catalog using a custom design system, consuming data from the DummyJSON Products API.
## 1. Setup & Run Instructions
**Flutter version:** 3.35.3 (stable channel)
```bash
# Clone the repository
git clone
cd tech_gadol
# Install dependencies
flutter pub get
# Run the app
flutter run
# Run tests
flutter test
# Run analysis
flutter analyze
```
No additional setup is required. The app uses the public DummyJSON API (`https://dummyjson.com`) — no API keys or environment variables needed.
## 2. Architecture Overview
### Folder Structure
```
lib/
├── core/
│ ├── extensions/ # BuildContext extensions (responsive breakpoints)
│ ├── routing/ # GoRouter config + centralized route paths
│ ├── services/
│ │ ├── api_services/ # Dio HTTP client, connectivity wrapper, API constants
│ │ └── local_storage_services/ # Hive-based product cache
│ ├── theme/ # AppColors, LightTheme, DarkTheme
│ └── widgets/ # Design system components (reusable across features)
├── features/
│ ├── products/
│ │ ├── data/
│ │ │ ├── models/ # ProductModel, ProductsResponse
│ │ │ └── repositories/ # ProductRepository (API + cache integration)
│ │ └── presentation/
│ │ ├── bloc/ # ProductsBloc, events, state
│ │ └── views/ # Screens (list, detail, responsive layout)
│ └── showcase/
│ └── presentation/views/ # Component showcase screen
├── app.dart # Root widget with BLoC providers + MaterialApp.router
└── main.dart # Entry point + Hive init
```
### Architecture Pattern
**Feature-first** with clean separation of data and presentation layers per feature:
- **Data layer:** Models with JSON parsing + validation, Repository pattern wrapping API calls with caching
- **Presentation layer:** BLoC for state management, screens consume state via `BlocBuilder`
### State Management
**BLoC (flutter_bloc)** with Equatable for predictable, testable state:
- Single `ProductsBloc` manages products, categories, search, pagination, and product selection
- All states handled explicitly: `initial`, `loading`, `loaded`, `error`
- Timer-based search debounce (300ms) — no extra dependency
- Combined search + category filtering (client-side filtering when both active, since DummyJSON doesn't support this server-side)
### Navigation
**GoRouter** with centralized route definitions in `AppRoutes`:
- `/products` — product list (responsive layout)
- `/products/:id` — product detail (deep linking supported)
- `/showcase` — component showcase (debug)
- Responsive master-detail layout handled at the routing level: wide screens (≥768px) show side-by-side, narrow screens use push navigation
### Networking
**Dio** singleton with:
- Per-request cancel tokens
- Comprehensive error mapping (`ErrorEntity`)
- Connectivity check before every request (via `connectivity_plus`)
- Toast notification when offline
- Repository-level `try/catch` with `debugPrintStack` for traceability
## 3. Design System Rationale
### Component API
All design system widgets live in `core/widgets/` and are theme-aware (they read colors/styles from `Theme.of(context)` rather than hardcoding values):
| Component | Purpose |
|---|---|
| `AppSearchBar` | Text field with clear button, delegates debounce to BLoC |
| `CategoryChip` | `FilterChip` that formats slug labels (e.g. `smart-phones` → `Smart Phones`) |
| `ProductCard` | Horizontal card with thumbnail, title, brand, price, rating, stock indicator |
| `PriceTag` | Displays price with discount badge; shows "Price unavailable" for invalid prices |
| `RatingBar` | 5-star display with half-star support |
| `CachedImage` | `CachedNetworkImage` wrapper with loading spinner and error placeholder |
| `ShimmerLoading` | Skeleton placeholder cards matching `ProductCard` layout |
| `ErrorState` | Error icon + message + retry button |
| `EmptyState` | Empty results icon + message |
| `StaggeredListItem` | Fade+slide animation wrapper for list items |
### Theming
- Full light and dark themes using Material 3 (`ColorScheme`, text theme, card/chip/input decoration themes)
- System theme mode by default (`ThemeMode.system`)
- Showcase screen includes an independent light/dark toggle for testing
### Data Validation
Handled in `ProductModel.fromJson` with sensible defaults:
- Missing brand → `"Unknown brand"` + warning log
- Missing/negative price → stored as `-1`, UI shows `"Price unavailable"` + error log
- Invalid image URLs → filtered out + warning log
- Missing title → `"Untitled Product"`
- Rating → clamped between 0–5
## 4. Limitations
With more time, I would improve:
- **Domain layer:** Add use cases (e.g. `GetProductsUseCase`) and repository interfaces for full clean architecture
- **Theme:** Better custom animations with better optimization (I was not the most productive in this few hours)
- **Dependency injection:** Use `get_it` or `injectable` instead of manual constructor injection
- **Search + category:** Currently does client-side filtering when both are active. Ideally the API would support this natively
- **Offline support depth:** Currently only caches the first page of products and categories. Could cache all paginated pages and individual product details
- **Test coverage:** Add integration tests, golden tests for design system components, and test the responsive layout breakpoints
- **Accessibility:** Add semantic labels to images, ensure proper contrast ratios
- **Error messages:** Make user-facing error messages more specific (network timeout vs server error vs no internet)
## 5. AI Tools Usage
The AI mainly used was claude,
it was a fair experience, used to help me cut down development time alot,
but it made the following mistakes:
- Wrong theme usage on the app
- Incomplete error handling on API calls
- Wrong use of Hero widgets that threw exceptions all of the console
So, for some, I had to manually edit or re-query giving out specific guideliness on how to edit and go about them.