Skip to content
This repository was archived by the owner on Aug 9, 2024. It is now read-only.

Flutter test by Andres Chia #24

Open
wants to merge 19 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
YELP_API_KEY=
3 changes: 1 addition & 2 deletions .fvm/fvm_config.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
{
"flutterSdkVersion": "3.13.9",
"flavors": {}
"flutterSdkVersion": "stable"
}
3 changes: 3 additions & 0 deletions .fvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"flutter": "stable"
}
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,9 @@ app.*.map.json
/android/app/release

# fvm
.fvm/flutter_sdk

# FVM Version Cache
.fvm/

# env
*.env
14 changes: 7 additions & 7 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"dart.flutterSdkPath": ".fvm/flutter_sdk",
"search.exclude": {
"**/.fvm": true
},
"files.watcherExclude": {
"**/.fvm": true
}
"dart.flutterSdkPath": ".fvm\\versions\\stable",
"search.exclude": {
"**/.fvm": true
},
"files.watcherExclude": {
"**/.fvm": true
}
}
14 changes: 5 additions & 9 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
plugins {
id "com.android.application"
id "kotlin-android"
id "dev.flutter.flutter-gradle-plugin"
}
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
Expand All @@ -6,11 +11,6 @@ if (localPropertiesFile.exists()) {
}
}

def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}

def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
Expand All @@ -21,10 +21,6 @@ if (flutterVersionName == null) {
flutterVersionName = '1.0'
}

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

android {
compileSdkVersion flutter.compileSdkVersion

Expand Down
6 changes: 3 additions & 3 deletions android/build.gradle
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@

buildscript {
ext.kotlin_version = '1.3.50'
ext.kotlin_version = '1.7.10'
repositories {
google()
mavenCentral()
}

dependencies {
classpath 'com.android.tools.build:gradle:4.1.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
Expand All @@ -26,6 +26,6 @@ subprojects {
project.evaluationDependsOn(':app')
}

task clean(type: Delete) {
tasks.register("clean", Delete) {
delete rootProject.buildDir
}
2 changes: 1 addition & 1 deletion android/gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-all.zip
34 changes: 26 additions & 8 deletions android/settings.gradle
Original file line number Diff line number Diff line change
@@ -1,11 +1,29 @@
include ':app'
pluginManagement {
def flutterSdkPath = {
def properties = new Properties()
file("local.properties").withInputStream { properties.load(it) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
return flutterSdkPath
}
settings.ext.flutterSdkPath = flutterSdkPath()

def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
def properties = new Properties()
includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle")

assert localPropertiesFile.exists()
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
repositories {
google()
mavenCentral()
gradlePluginPortal()
}

def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
plugins {
id "dev.flutter.flutter-gradle-plugin" version "1.0.0" apply false
}
}

plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version "7.3.0" apply false
}

include ":app"
29 changes: 29 additions & 0 deletions lib/application/list_restaurants_provider.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import 'package:flutter/foundation.dart';

import '../models/restaurant.dart';

class ListRestaurantsProvider with ChangeNotifier {
List<Restaurant>? _restaurants;
String? _selectedRestaurantId;
bool _isLoading = false;

List<Restaurant>? get restaurants => _restaurants;
bool get isLoading => _isLoading;

String? get selectedRestaurantId => _selectedRestaurantId;

void addRestaurants(List<Restaurant> list) {
_restaurants = list;
notifyListeners();
}

void changeIsLoading(bool loading) {
_isLoading = loading;
notifyListeners();
}

void setCurrentRestaurant(String? r) {
_selectedRestaurantId = r;
notifyListeners();
}
}
8 changes: 8 additions & 0 deletions lib/config/get_it.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import 'package:get_it/get_it.dart';
import 'package:restaurantour/repositories/yelp_repository.dart';

final getIt = GetIt.instance;

void setup() {
getIt.registerSingleton<YelpRepository>(YelpRepository());
}
61 changes: 19 additions & 42 deletions lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,56 +1,33 @@
import 'package:flutter/material.dart';
import 'package:restaurantour/repositories/yelp_repository.dart';
import 'package:provider/provider.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';

void main() {
import 'application/list_restaurants_provider.dart';
import 'config/get_it.dart';
import 'presentation/pages/package.dart';

void main() async {
await dotenv.load(fileName: ".env");
setup();
runApp(const Restaurantour());
}

class Restaurantour extends StatelessWidget {
// This widget is the root of your application.
const Restaurantour({Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'RestauranTour',
theme: ThemeData(
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: const HomePage(),
);
}
}

class HomePage extends StatelessWidget {
const HomePage({Key? key}) : super(key: key);
const Restaurantour({super.key});

@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text('Restaurantour'),
ElevatedButton(
child: const Text('Fetch Restaurants'),
onPressed: () async {
final yelpRepo = YelpRepository();

try {
final result = await yelpRepo.getRestaurants();
if (result != null) {
print('Fetched ${result.restaurants!.length} restaurants');
} else {
print('No restaurants fetched');
}
} catch (e) {
print('Failed to fetch restaurants: $e');
}
},
),
],
return MultiProvider(
providers: [
ChangeNotifierProvider(create: (_) => ListRestaurantsProvider()),
],
child: MaterialApp(
title: 'RestauranTour',
theme: ThemeData(
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: const ListViewPage(),
),
);
}
Expand Down
2 changes: 2 additions & 0 deletions lib/presentation/atomic/atomic.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export 'molecules/package.dart';
export 'atoms/package.dart';
60 changes: 60 additions & 0 deletions lib/presentation/atomic/atoms/animated_container_atom.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
part of 'package.dart';

class AnimatedScrollableContainerAtom extends StatefulWidget {
final double width;
final double height;
final ScrollController controller;
final Widget child;
const AnimatedScrollableContainerAtom({
super.key,
this.width = 50,
this.height = 50,
required this.controller,
required this.child,
});

@override
State<AnimatedScrollableContainerAtom> createState() =>
_AnimatedScrollableContainerAtomState();
}

class _AnimatedScrollableContainerAtomState
extends State<AnimatedScrollableContainerAtom> {
late double _width;
late double _height;
late double _offset;
@override
void initState() {
super.initState();
_width = widget.width;
_height = widget.height;
_offset = widget.controller.offset;
widget.controller.addListener(() {
setState(() {
if (widget.controller.offset > _offset) {
_height++;
} else {
_height--;
}
});
});
}

@override
Widget build(BuildContext context) {
return AnimatedContainer(
// Use the properties stored in the State class.
width: _width,
height: _height,
// decoration: BoxDecoration(
// color: _color,
// borderRadius: _borderRadius,
// ),
// Define how long the animation should take.
duration: const Duration(seconds: 1),
// Provide an optional curve to make the animation feel smoother.
curve: Curves.fastOutSlowIn,
child: widget.child,
);
}
}
23 changes: 23 additions & 0 deletions lib/presentation/atomic/atoms/circle_avatar_atom.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
part of 'package.dart';

class CircleAvatarAtom extends StatelessWidget {
final String? url;
final double? radius;
const CircleAvatarAtom({super.key, this.url, this.radius});

@override
Widget build(BuildContext context) {
if (url != null) {
return CircleAvatar(
radius: radius,
backgroundImage: NetworkImage(
url!,
),
);
}
return const CircleAvatar(
radius: 40,
child: Icon(Icons.person),
);
}
}
42 changes: 42 additions & 0 deletions lib/presentation/atomic/atoms/image_rounded_atom.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
part of 'package.dart';

class ImageRoundedAtom extends StatefulWidget {
final String url;
final double height;
final double width;
const ImageRoundedAtom({
super.key,
required this.url,
required this.height,
required this.width,
});

@override
State<ImageRoundedAtom> createState() => _ImageRoundedAtomState();
}

class _ImageRoundedAtomState extends State<ImageRoundedAtom> {
bool isLoading = true;

@override
Widget build(BuildContext context) {
return ClipRRect(
borderRadius: const BorderRadius.all(
Radius.circular(10),
),
child: Image.network(
widget.url,
height: widget.height,
width: widget.width,
fit: BoxFit.fitWidth,
loadingBuilder: (context, child, loadingProgress) {
if (loadingProgress == null) return child;
return ShimmerAtom(
height: widget.height,
width: widget.width,
);
},
),
);
}
}
8 changes: 8 additions & 0 deletions lib/presentation/atomic/atoms/package.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import 'package:flutter/material.dart';
import 'package:shimmer/shimmer.dart';

part 'image_rounded_atom.dart';
part 'star_atom.dart';
part 'shimmer_atom.dart';
part 'animated_container_atom.dart';
part 'circle_avatar_atom.dart';
Loading