woowww josssjissss
This commit is contained in:
parent
1239b39e30
commit
adaeff826f
Binary file not shown.
|
After Width: | Height: | Size: 9.8 KiB |
|
|
@ -24,6 +24,7 @@ class SignInBloc extends Bloc<SignInEvent, SignInState> {
|
||||||
await _userRepository.signInWithGoogle();
|
await _userRepository.signInWithGoogle();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(SignInFailure());
|
emit(SignInFailure());
|
||||||
|
emit(SignInInitial());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,15 +20,5 @@ class SignUpBloc extends Bloc<SignUpEvent, SignUpState> {
|
||||||
emit(SignUpFailure(e.toString()));
|
emit(SignUpFailure(e.toString()));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
on<GoogleSignInRequired>((event, emit) async {
|
|
||||||
emit(SignUpProcess());
|
|
||||||
try {
|
|
||||||
await _userRepository.signInWithGoogle();
|
|
||||||
emit(SignUpSuccess());
|
|
||||||
} catch (e) {
|
|
||||||
emit(SignUpFailure(e.toString()));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,19 +25,20 @@ class _SignInScreenState extends State<SignInScreen> {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocListener<SignInBloc, SignInState>(
|
return BlocListener<SignInBloc, SignInState>(
|
||||||
listener: (context, state) {
|
listener: (context, state) {
|
||||||
if (state is SignInSuccess) {
|
if (state is SignInProcess) {
|
||||||
setState(() {
|
|
||||||
signInRequired = false;
|
|
||||||
});
|
|
||||||
} else if (state is SignInProcess) {
|
|
||||||
setState(() {
|
setState(() {
|
||||||
signInRequired = true;
|
signInRequired = true;
|
||||||
});
|
});
|
||||||
} else if (state is SignInFailure) {
|
} else {
|
||||||
setState(() {
|
setState(() {
|
||||||
signInRequired = false;
|
signInRequired = false;
|
||||||
_errorMsg = 'Invalid email or password';
|
|
||||||
});
|
});
|
||||||
|
if (state is SignInFailure) {
|
||||||
|
setState(() {
|
||||||
|
// PERUBAHAN: Pesan error lebih umum karena Google gagal belum tentu soal password
|
||||||
|
_errorMsg = 'Sign in failed. Please try again.';
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Form(
|
child: Form(
|
||||||
|
|
|
||||||
|
|
@ -3,10 +3,13 @@ import 'package:user_repository/user_repository.dart';
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import '../../../components/my_text_field.dart';
|
import '../../../components/my_text_field.dart';
|
||||||
import '../blocs/sign_up_bloc/sign_up_bloc.dart';
|
import '../blocs/sign_up_bloc/sign_up_bloc.dart' as signUp;
|
||||||
|
// import '../../../blocs/authentication_bloc/authentication_bloc.dart';
|
||||||
|
import '../blocs/sign_in_bloc/sign_in_bloc.dart' as signIn;
|
||||||
|
|
||||||
class SignUpScreen extends StatefulWidget {
|
class SignUpScreen extends StatefulWidget {
|
||||||
const SignUpScreen({super.key});
|
final VoidCallback? onSignInTap;
|
||||||
|
const SignUpScreen({super.key, this.onSignInTap});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<SignUpScreen> createState() => _SignUpScreenState();
|
State<SignUpScreen> createState() => _SignUpScreenState();
|
||||||
|
|
@ -30,18 +33,26 @@ class _SignUpScreenState extends State<SignUpScreen> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocListener<SignUpBloc, SignUpState>(
|
return BlocListener<signUp.SignUpBloc, signUp.SignUpState>(
|
||||||
listener: (context, state) {
|
listener: (context, state) {
|
||||||
if (state is SignUpSuccess) {
|
if (state is signUp.SignUpProcess) {
|
||||||
setState(() {
|
|
||||||
signUpRequired = false;
|
|
||||||
});
|
|
||||||
} else if (state is SignUpProcess) {
|
|
||||||
setState(() {
|
setState(() {
|
||||||
signUpRequired = true;
|
signUpRequired = true;
|
||||||
});
|
});
|
||||||
} else if (state is SignUpFailure) {
|
} else if (state is signUp.SignUpFailure) {
|
||||||
return;
|
setState(() {
|
||||||
|
signUpRequired = false; // Matikan loading!
|
||||||
|
});
|
||||||
|
// Tampilkan pesan error lewat Snackbar biar user tahu kenapa gagal
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(
|
||||||
|
content: Text(state.message ?? 'An error ocurred'),
|
||||||
|
backgroundColor: Colors.red),
|
||||||
|
);
|
||||||
|
} else if (state is signUp.SignUpSuccess) {
|
||||||
|
setState(() {
|
||||||
|
signUpRequired = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Form(
|
child: Form(
|
||||||
|
|
@ -181,10 +192,13 @@ class _SignUpScreenState extends State<SignUpScreen> {
|
||||||
|
|
||||||
const SizedBox(height: 18),
|
const SizedBox(height: 18),
|
||||||
|
|
||||||
|
/// == Sign Up == ///
|
||||||
// Button
|
// Button
|
||||||
!signUpRequired
|
!signUpRequired
|
||||||
? SizedBox(
|
? Center(
|
||||||
width: MediaQuery.of(context).size.width * 0.92,
|
child: SizedBox(
|
||||||
|
width:
|
||||||
|
MediaQuery.of(context).size.width * 0.5,
|
||||||
child: ElevatedButton(
|
child: ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (_formKey.currentState!.validate()) {
|
if (_formKey.currentState!.validate()) {
|
||||||
|
|
@ -193,8 +207,8 @@ class _SignUpScreenState extends State<SignUpScreen> {
|
||||||
myUser.name = nameController.text;
|
myUser.name = nameController.text;
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
context.read<SignUpBloc>().add(
|
context.read<signUp.SignUpBloc>().add(
|
||||||
SignUpRequired(
|
signUp.SignUpRequired(
|
||||||
myUser,
|
myUser,
|
||||||
passwordController.text,
|
passwordController.text,
|
||||||
),
|
),
|
||||||
|
|
@ -202,22 +216,26 @@ class _SignUpScreenState extends State<SignUpScreen> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
style: ElevatedButton.styleFrom(
|
style: TextButton.styleFrom(
|
||||||
backgroundColor: Colors.black87,
|
backgroundColor:
|
||||||
|
Theme.of(context).colorScheme.primary,
|
||||||
foregroundColor: Colors.white,
|
foregroundColor: Colors.white,
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
vertical: 16),
|
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(8),
|
borderRadius: BorderRadius.circular(60),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 25, vertical: 5),
|
||||||
child: const Text(
|
child: const Text(
|
||||||
'Daftar',
|
'Sign Up',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.w600),
|
fontWeight: FontWeight.w600),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
: const CircularProgressIndicator(),
|
: const CircularProgressIndicator(),
|
||||||
|
|
||||||
|
|
@ -225,39 +243,7 @@ class _SignUpScreenState extends State<SignUpScreen> {
|
||||||
Center(
|
Center(
|
||||||
child: Text('Atau'),
|
child: Text('Atau'),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 12),
|
|
||||||
SizedBox(
|
|
||||||
width: MediaQuery.of(context).size.width * 0.92,
|
|
||||||
child: TextButton.icon(
|
|
||||||
onPressed: () {
|
|
||||||
context
|
|
||||||
.read<SignUpBloc>()
|
|
||||||
.add(GoogleSignInRequired());
|
|
||||||
},
|
|
||||||
icon: SizedBox(
|
|
||||||
height: 20,
|
|
||||||
width: 20,
|
|
||||||
child: Image.asset(
|
|
||||||
'images/google-icon-logo.png',
|
|
||||||
fit: BoxFit.contain,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
label: const Text(
|
|
||||||
'Sign In With Google',
|
|
||||||
style: TextStyle(
|
|
||||||
color: Colors.black,
|
|
||||||
fontSize: 16,
|
|
||||||
fontWeight: FontWeight.w600),
|
|
||||||
),
|
|
||||||
style: TextButton.styleFrom(
|
|
||||||
backgroundColor: Colors.white,
|
|
||||||
shape: RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
side: const BorderSide(color: Colors.grey)),
|
|
||||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
Center(
|
Center(
|
||||||
child: Row(
|
child: Row(
|
||||||
|
|
@ -266,9 +252,12 @@ class _SignUpScreenState extends State<SignUpScreen> {
|
||||||
const Text('Sudah punya akun? '),
|
const Text('Sudah punya akun? '),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop();
|
widget.onSignInTap?.call();
|
||||||
},
|
},
|
||||||
child: const Text('Login di sini'),
|
child: const Text(
|
||||||
|
'Login di sini',
|
||||||
|
style: TextStyle(fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -13,20 +13,16 @@ class WelcomeScreen extends StatefulWidget {
|
||||||
State<WelcomeScreen> createState() => _WelcomeScreenState();
|
State<WelcomeScreen> createState() => _WelcomeScreenState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _WelcomeScreenState extends State<WelcomeScreen> with TickerProviderStateMixin {
|
class _WelcomeScreenState extends State<WelcomeScreen>
|
||||||
|
with TickerProviderStateMixin {
|
||||||
late TabController tabController;
|
late TabController tabController;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
tabController = TabController(
|
tabController = TabController(initialIndex: 0, length: 2, vsync: this);
|
||||||
initialIndex: 0,
|
|
||||||
length: 2,
|
|
||||||
vsync: this
|
|
||||||
);
|
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
|
|
@ -46,8 +42,12 @@ class _WelcomeScreenState extends State<WelcomeScreen> with TickerProviderStateM
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 50.0),
|
padding: const EdgeInsets.symmetric(horizontal: 50.0),
|
||||||
child: TabBar(
|
child: TabBar(
|
||||||
controller: tabController,
|
controller: tabController,
|
||||||
unselectedLabelColor: Theme.of(context).colorScheme.onBackground.withOpacity(0.5),
|
unselectedLabelColor: Theme.of(context)
|
||||||
labelColor: Theme.of(context).colorScheme.onBackground,
|
.colorScheme
|
||||||
|
.onBackground
|
||||||
|
.withOpacity(0.5),
|
||||||
|
labelColor:
|
||||||
|
Theme.of(context).colorScheme.onBackground,
|
||||||
tabs: const [
|
tabs: const [
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.all(12.0),
|
padding: EdgeInsets.all(12.0),
|
||||||
|
|
@ -75,20 +75,22 @@ class _WelcomeScreenState extends State<WelcomeScreen> with TickerProviderStateM
|
||||||
controller: tabController,
|
controller: tabController,
|
||||||
children: [
|
children: [
|
||||||
BlocProvider<SignInBloc>(
|
BlocProvider<SignInBloc>(
|
||||||
create: (context) => SignInBloc(
|
create: (context) => SignInBloc(context
|
||||||
context.read<AuthenticationBloc>().userRepository
|
.read<AuthenticationBloc>()
|
||||||
),
|
.userRepository),
|
||||||
child: const SignInScreen(),
|
child: const SignInScreen(),
|
||||||
),
|
),
|
||||||
BlocProvider<SignUpBloc>(
|
BlocProvider<SignUpBloc>(
|
||||||
create: (context) => SignUpBloc(
|
create: (context) => SignUpBloc(context
|
||||||
context.read<AuthenticationBloc>().userRepository
|
.read<AuthenticationBloc>()
|
||||||
),
|
.userRepository),
|
||||||
child: const SignUpScreen(),
|
child: SignUpScreen(onSignInTap: () {
|
||||||
|
tabController.animateTo(
|
||||||
|
0); // Ini yang bikin dia pindah ke tab Login
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
))
|
||||||
)
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,11 @@ class MainDrawer extends StatelessWidget {
|
||||||
|
|
||||||
// Daftar Menu
|
// Daftar Menu
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.speed),
|
leading: Image.asset(
|
||||||
|
'images/windy.png',
|
||||||
|
height: 20,
|
||||||
|
width: 20,
|
||||||
|
),
|
||||||
title: const Text("Wind Speed"),
|
title: const Text("Wind Speed"),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
// Navigasi ke Wind Speed
|
// Navigasi ke Wind Speed
|
||||||
|
|
@ -52,7 +56,7 @@ class MainDrawer extends StatelessWidget {
|
||||||
height: 20,
|
height: 20,
|
||||||
width: 20,
|
width: 20,
|
||||||
),
|
),
|
||||||
title: const Text("Udara"),
|
title: const Text("Tekanan Udara"),
|
||||||
onTap: () {},
|
onTap: () {},
|
||||||
),
|
),
|
||||||
const Spacer(), // Dorong menu logout ke paling bawah
|
const Spacer(), // Dorong menu logout ke paling bawah
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import 'package:fl_chart/fl_chart.dart';
|
||||||
import 'package:firebase_database/firebase_database.dart';
|
import 'package:firebase_database/firebase_database.dart';
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'shared/widgets/monitoring_shared.dart';
|
import '../../shared/widgets/monitoring_shared.dart';
|
||||||
|
|
||||||
/// EVAPORASI MONITORING SCREEN
|
/// EVAPORASI MONITORING SCREEN
|
||||||
class EvaporasiMonitoringScreen extends StatefulWidget {
|
class EvaporasiMonitoringScreen extends StatefulWidget {
|
||||||
|
|
@ -2,34 +2,44 @@ import 'dart:async';
|
||||||
import 'package:bloc/bloc.dart';
|
import 'package:bloc/bloc.dart';
|
||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:monitoring_repository/monitoring_repository.dart';
|
import 'package:monitoring_repository/monitoring_repository.dart';
|
||||||
|
import 'package:bloc_concurrency/bloc_concurrency.dart';
|
||||||
part 'wind_speed_event.dart';
|
part 'wind_speed_event.dart';
|
||||||
part 'wind_speed_state.dart';
|
part 'wind_speed_state.dart';
|
||||||
|
|
||||||
class WindSpeedBloc extends Bloc<WindSpeedEvent, WindSpeedState> {
|
class WindSpeedBloc extends Bloc<WindSpeedEvent, WindSpeedState> {
|
||||||
final MonitoringRepository _repository;
|
final MonitoringRepository _repository;
|
||||||
StreamSubscription? _subscription;
|
|
||||||
|
|
||||||
WindSpeedBloc({required MonitoringRepository repository})
|
WindSpeedBloc({required MonitoringRepository repository})
|
||||||
: _repository = repository,
|
: _repository = repository,
|
||||||
super(const WindSpeedState()) {
|
super(const WindSpeedState()) {
|
||||||
// Handler saat aplikasi minta mulai monitoring
|
// Handler saat aplikasi minta mulai monitoring
|
||||||
on<WatchWindSpeedStarted>((event, emit) {
|
on<WatchWindSpeedStarted>(
|
||||||
_subscription?.cancel();
|
(event, emit) async {
|
||||||
_subscription = _repository
|
emit(state.copyWith(isLoading: true));
|
||||||
.getSensorStream(
|
|
||||||
'anemometer/realtime', (json) => MyWindSpeed.fromJson(json))
|
|
||||||
.listen((data) => add(_WindSpeedUpdated(data)));
|
|
||||||
});
|
|
||||||
|
|
||||||
// Handler saat ada data baru masuk (Pindahan logika dari Screen)
|
await emit.forEach<MyWindSpeed>(
|
||||||
on<_WindSpeedUpdated>((event, emit) {
|
_repository.getSensorStream(
|
||||||
// Di sini kamu bisa tambahkan logika hitung rata-rata/grafik harian
|
'anemometer/realtime', (json) => MyWindSpeed.fromJson(json)),
|
||||||
emit(state.copyWith(
|
onData: (data) {
|
||||||
currentSpeed: event.data.speed,
|
// Mengambil list lama dan menambah data baru untuk grafik
|
||||||
|
final updatedSpeeds = List<double>.from(state.dailySpeeds)
|
||||||
|
..add(data.speed);
|
||||||
|
// Batasi jumlah data di grafik (misal cuma simpan 20 data terakhir agar tidak berat)
|
||||||
|
if (updatedSpeeds.length > 20) {
|
||||||
|
updatedSpeeds.removeAt(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return state.copyWith(
|
||||||
|
currentSpeed: data.speed,
|
||||||
|
dailySpeeds: updatedSpeeds, // Update list grafik
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
));
|
);
|
||||||
});
|
},
|
||||||
|
onError: (error, stackTrace) => state.copyWith(isLoading: false),
|
||||||
|
); // emit forEach
|
||||||
|
},
|
||||||
|
transformer: restartable(),
|
||||||
|
);
|
||||||
|
|
||||||
on<WindSpeedPeriodChanged>((event, emit) {
|
on<WindSpeedPeriodChanged>((event, emit) {
|
||||||
emit(state.copyWith(selectedPeriod: event.period));
|
emit(state.copyWith(selectedPeriod: event.period));
|
||||||
|
|
@ -38,7 +48,6 @@ class WindSpeedBloc extends Bloc<WindSpeedEvent, WindSpeedState> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<void> close() {
|
Future<void> close() {
|
||||||
_subscription?.cancel(); // Supaya tidak bocor memorinya
|
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class WindSpeedScreen extends StatelessWidget {
|
||||||
|
const WindSpeedScreen({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,205 +0,0 @@
|
||||||
# Generated by pub
|
|
||||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
|
||||||
packages:
|
|
||||||
async:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: async
|
|
||||||
sha256: "758e6d74e971c3e5aceb4110bfd6698efc7f501675bcfe0c775459a8140750eb"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.13.0"
|
|
||||||
boolean_selector:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: boolean_selector
|
|
||||||
sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.1.2"
|
|
||||||
characters:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: characters
|
|
||||||
sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.4.0"
|
|
||||||
clock:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: clock
|
|
||||||
sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.1.2"
|
|
||||||
collection:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: collection
|
|
||||||
sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.19.1"
|
|
||||||
fake_async:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: fake_async
|
|
||||||
sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.3.3"
|
|
||||||
flutter:
|
|
||||||
dependency: "direct main"
|
|
||||||
description: flutter
|
|
||||||
source: sdk
|
|
||||||
version: "0.0.0"
|
|
||||||
flutter_lints:
|
|
||||||
dependency: "direct dev"
|
|
||||||
description:
|
|
||||||
name: flutter_lints
|
|
||||||
sha256: a25a15ebbdfc33ab1cd26c63a6ee519df92338a9c10f122adda92938253bef04
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.0.3"
|
|
||||||
flutter_test:
|
|
||||||
dependency: "direct dev"
|
|
||||||
description: flutter
|
|
||||||
source: sdk
|
|
||||||
version: "0.0.0"
|
|
||||||
leak_tracker:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: leak_tracker
|
|
||||||
sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "11.0.2"
|
|
||||||
leak_tracker_flutter_testing:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: leak_tracker_flutter_testing
|
|
||||||
sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.0.10"
|
|
||||||
leak_tracker_testing:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: leak_tracker_testing
|
|
||||||
sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.0.2"
|
|
||||||
lints:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: lints
|
|
||||||
sha256: "0a217c6c989d21039f1498c3ed9f3ed71b354e69873f13a8dfc3c9fe76f1b452"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.1.1"
|
|
||||||
matcher:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: matcher
|
|
||||||
sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.12.17"
|
|
||||||
material_color_utilities:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: material_color_utilities
|
|
||||||
sha256: f7142bb1154231d7ea5f96bc7bde4bda2a0945d2806bb11670e30b850d56bdec
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.11.1"
|
|
||||||
meta:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: meta
|
|
||||||
sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.17.0"
|
|
||||||
path:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: path
|
|
||||||
sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.9.1"
|
|
||||||
sky_engine:
|
|
||||||
dependency: transitive
|
|
||||||
description: flutter
|
|
||||||
source: sdk
|
|
||||||
version: "0.0.0"
|
|
||||||
source_span:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: source_span
|
|
||||||
sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.10.1"
|
|
||||||
stack_trace:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: stack_trace
|
|
||||||
sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.12.1"
|
|
||||||
stream_channel:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: stream_channel
|
|
||||||
sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.1.4"
|
|
||||||
string_scanner:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: string_scanner
|
|
||||||
sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.4.1"
|
|
||||||
term_glyph:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: term_glyph
|
|
||||||
sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.2.2"
|
|
||||||
test_api:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: test_api
|
|
||||||
sha256: ab2726c1a94d3176a45960b6234466ec367179b87dd74f1611adb1f3b5fb9d55
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.7.7"
|
|
||||||
vector_math:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: vector_math
|
|
||||||
sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.2.0"
|
|
||||||
vm_service:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: vm_service
|
|
||||||
sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "15.0.2"
|
|
||||||
sdks:
|
|
||||||
dart: ">=3.8.0-0 <4.0.0"
|
|
||||||
flutter: ">=3.18.0-18.0.pre.54"
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
name: module_repository
|
|
||||||
description: The Repo that handles modules
|
|
||||||
publish_to: 'none'
|
|
||||||
version: 0.0.1
|
|
||||||
|
|
||||||
environment:
|
|
||||||
sdk: '>=3.1.0 <4.0.0'
|
|
||||||
|
|
||||||
dependencies:
|
|
||||||
flutter:
|
|
||||||
sdk: flutter
|
|
||||||
|
|
||||||
# equatable: ^2.0.5
|
|
||||||
# firebase_auth: ^4.16.0
|
|
||||||
# cloud_firestore: ^4.9.2
|
|
||||||
# firebase_storage: ^11.6.0
|
|
||||||
# rxdart: ^0.27.7
|
|
||||||
# path: ^1.8.3
|
|
||||||
|
|
||||||
dev_dependencies:
|
|
||||||
flutter_test:
|
|
||||||
sdk: flutter
|
|
||||||
flutter_lints: ^2.0.0
|
|
||||||
|
|
||||||
flutter:
|
|
||||||
uses-material-design: true
|
|
||||||
|
|
@ -17,11 +17,14 @@ class FirebaseMonitoringRepo implements MonitoringRepository {
|
||||||
) {
|
) {
|
||||||
/// === ambil data mentah dari firebase === ///
|
/// === ambil data mentah dari firebase === ///
|
||||||
return _db.ref(path).onValue.map((event) {
|
return _db.ref(path).onValue.map((event) {
|
||||||
/// == ambil value-nya dan pastikan tipenya map == ///
|
final Object? value = event.snapshot.value;
|
||||||
final data = event.snapshot.value as Map<dynamic, dynamic>? ?? {};
|
|
||||||
|
|
||||||
/// == masukan ke dalam "pabrik" (mapper) agar jadi objek == ///
|
if (value is Map) {
|
||||||
return mapper(data);
|
return mapper(value);
|
||||||
|
} else {
|
||||||
|
// Jika data kosong atau bukan Map, berikan Map kosong agar mapper tidak crash
|
||||||
|
return mapper({});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ class FirebaseUserRepo implements UserRepository {
|
||||||
FirebaseAuth? firebaseAuth,
|
FirebaseAuth? firebaseAuth,
|
||||||
}) : _firebaseAuth = firebaseAuth ?? FirebaseAuth.instance;
|
}) : _firebaseAuth = firebaseAuth ?? FirebaseAuth.instance;
|
||||||
|
|
||||||
|
/// == Melakukan Implement User == ///
|
||||||
@override
|
@override
|
||||||
Stream<MyUser?> get user {
|
Stream<MyUser?> get user {
|
||||||
return _firebaseAuth.authStateChanges().flatMap((firebaseUser) async* {
|
return _firebaseAuth.authStateChanges().flatMap((firebaseUser) async* {
|
||||||
|
|
@ -42,6 +43,7 @@ class FirebaseUserRepo implements UserRepository {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// == Melakukan Implement Sign in == ///
|
||||||
@override
|
@override
|
||||||
Future<void> signIn(String email, String password) async {
|
Future<void> signIn(String email, String password) async {
|
||||||
try {
|
try {
|
||||||
|
|
@ -53,6 +55,7 @@ class FirebaseUserRepo implements UserRepository {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// == Melakukan Implement Sign Up == ///
|
||||||
@override
|
@override
|
||||||
Future<MyUser> signUp(MyUser myUser, String password) async {
|
Future<MyUser> signUp(MyUser myUser, String password) async {
|
||||||
try {
|
try {
|
||||||
|
|
@ -66,6 +69,7 @@ class FirebaseUserRepo implements UserRepository {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// == Melakukan Implement Log Out == ///
|
||||||
@override
|
@override
|
||||||
Future<void> logOut() async {
|
Future<void> logOut() async {
|
||||||
await _firebaseAuth.signOut();
|
await _firebaseAuth.signOut();
|
||||||
|
|
@ -85,6 +89,7 @@ class FirebaseUserRepo implements UserRepository {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// == Sign in with Google == ///
|
||||||
@override
|
@override
|
||||||
Future<void> signInWithGoogle() async {
|
Future<void> signInWithGoogle() async {
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
16
pubspec.lock
16
pubspec.lock
|
|
@ -33,6 +33,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "8.1.4"
|
version: "8.1.4"
|
||||||
|
bloc_concurrency:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: bloc_concurrency
|
||||||
|
sha256: "456b7a3616a7c1ceb975c14441b3f198bf57d81cb95b7c6de5cb0c60201afcd8"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.5"
|
||||||
boolean_selector:
|
boolean_selector:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
@ -596,6 +604,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.4"
|
version: "2.1.4"
|
||||||
|
stream_transform:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: stream_transform
|
||||||
|
sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.1.1"
|
||||||
string_scanner:
|
string_scanner:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ environment:
|
||||||
sdk: ^3.1.0
|
sdk: ^3.1.0
|
||||||
dependencies:
|
dependencies:
|
||||||
bloc: ^8.1.0
|
bloc: ^8.1.0
|
||||||
|
bloc_concurrency: ^0.2.5
|
||||||
cloud_firestore: ^6.1.1
|
cloud_firestore: ^6.1.1
|
||||||
cupertino_icons: ^1.0.8
|
cupertino_icons: ^1.0.8
|
||||||
equatable: ^2.0.5
|
equatable: ^2.0.5
|
||||||
|
|
@ -19,11 +20,11 @@ dependencies:
|
||||||
google_fonts: ^8.0.2
|
google_fonts: ^8.0.2
|
||||||
google_sign_in: ^7.2.0
|
google_sign_in: ^7.2.0
|
||||||
intl: ^0.20.2
|
intl: ^0.20.2
|
||||||
|
monitoring_repository:
|
||||||
|
path: packages/monitoring_repository
|
||||||
rxdart: ^0.27.7
|
rxdart: ^0.27.7
|
||||||
user_repository:
|
user_repository:
|
||||||
path: packages/user_repository
|
path: packages/user_repository
|
||||||
monitoring_repository:
|
|
||||||
path: packages/monitoring_repository
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_lints: ^3.0.0
|
flutter_lints: ^3.0.0
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<!--
|
<!--
|
||||||
If you are serving your web app in a path other than the root, change the
|
If you are serving your web app in a path other than the root, change the
|
||||||
href value below to reflect the base path you are serving from.
|
href value below to reflect the base path you are serving from.
|
||||||
|
|
@ -14,25 +14,31 @@
|
||||||
This is a placeholder for base href that will be replaced by the value of
|
This is a placeholder for base href that will be replaced by the value of
|
||||||
the `--base-href` argument provided to `flutter build`.
|
the `--base-href` argument provided to `flutter build`.
|
||||||
-->
|
-->
|
||||||
<base href="$FLUTTER_BASE_HREF">
|
<base href="$FLUTTER_BASE_HREF" />
|
||||||
|
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8" />
|
||||||
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
|
<meta content="IE=Edge" http-equiv="X-UA-Compatible" />
|
||||||
<meta name="description" content="A new Flutter project.">
|
<meta name="description" content="A new Flutter project." />
|
||||||
|
|
||||||
<!-- iOS meta tags & icons -->
|
<!-- iOS meta tags & icons -->
|
||||||
<meta name="mobile-web-app-capable" content="yes">
|
<meta name="mobile-web-app-capable" content="yes" />
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
|
||||||
<meta name="apple-mobile-web-app-title" content="klimatologiot">
|
<meta name="apple-mobile-web-app-title" content="klimatologiot" />
|
||||||
<link rel="apple-touch-icon" href="icons/Icon-192.png">
|
<link rel="apple-touch-icon" href="icons/Icon-192.png" />
|
||||||
|
|
||||||
<!-- Favicon -->
|
<!-- Favicon -->
|
||||||
<link rel="icon" type="image/png" href="favicon.png"/>
|
<link rel="icon" type="image/png" href="favicon.png" />
|
||||||
|
|
||||||
<title>klimatologiot</title>
|
<title>klimatologiot</title>
|
||||||
<link rel="manifest" href="manifest.json">
|
<link rel="manifest" href="manifest.json" />
|
||||||
</head>
|
|
||||||
<body>
|
<!-- Google -->
|
||||||
|
<meta
|
||||||
|
name="google-signin-client_id"
|
||||||
|
content="219079385989-8hkp1kg2pprs5k269s4c08r6rpdj1gjd.apps.googleusercontent.com"
|
||||||
|
/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
<script src="flutter_bootstrap.js" async></script>
|
<script src="flutter_bootstrap.js" async></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue