nitaniayevana / foodfinds

0 stars 0 forks source link

sign in menggnakan google, search, favorite, add post #1

Open nitaniayevana opened 3 days ago

nitaniayevana commented 3 days ago

sign in menggnakan google, search, favorite, add post

nitaniayevana commented 3 days ago

1. sign_in_screen

import 'package:flutter/material.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:cloud_firestore/cloud_firestore.dart'; // Add this import import 'package:foodfinds/screens/home_screen.dart'; import 'package:foodfinds/screens/sign_up_screen.dart'; import 'package:google_sign_in/google_sign_in.dart';

class SignInScreen extends StatefulWidget { const SignInScreen({Key? key});

@override SignInScreenState createState() => SignInScreenState(); }

class SignInScreenState extends State { final _emailController = TextEditingController(); final _passwordController = TextEditingController(); String _errorMessage = '';

ValueNotifier userCredential = ValueNotifier('');

Future signInWithGoogle() async { try { final GoogleSignInAccount? googleUser = await GoogleSignIn( scopes: [ 'email', ], clientId: //'37974253661-bf7jutp8u17m02uf1jbi9r6p5gfnfus8.apps.googleusercontent.com', //ANDROID CLIENT ID '37974253661-6f2242raggt8urteh7kp6uvr1n1mk7bt.apps.googleusercontent.com', // WEB CLIENT ID ).signIn();

  final GoogleSignInAuthentication? googleAuth =
  await googleUser?.authentication;

  final credential = GoogleAuthProvider.credential(
    accessToken: googleAuth?.accessToken,
    idToken: googleAuth?.idToken,
  );

  return await FirebaseAuth.instance.signInWithCredential(credential);
} on Exception catch (e) {
  // TODO
  print('exception->$e');
}

}

@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Sign In'), ), body: Padding( padding: const EdgeInsets.all(16.0), child: SingleChildScrollView( child: Column( children: [ const SizedBox(height: 32.0), TextField( controller: _emailController, decoration: const InputDecoration( labelText: 'Email', border: OutlineInputBorder(), ), ), const SizedBox(height: 16.0), TextField( controller: _passwordController, decoration: const InputDecoration( labelText: 'Password', border: OutlineInputBorder(), ), obscureText: true, ), const SizedBox(height: 16.0), ElevatedButton( onPressed: () async { final email = _emailController.text.trim(); final password = _passwordController.text; // Validasi email if (email.isEmpty || !isValidEmail(email)) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Please enter a valid email')), ); return; } // Validasi password if (password.isEmpty) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Please enter your password')), ); return; } try { // Lakukan sign in dengan email dan password await FirebaseAuth.instance.signInWithEmailAndPassword( email: email, password: password, ); // Jika berhasil sign in, navigasi ke halaman beranda Navigator.of(context).pushReplacement( MaterialPageRoute(builder: (context) => HomeScreen()), ); } on FirebaseAuthException catch (error) { print('Error code: ${error.code}'); if (error.code == 'user-not-found') { // Jika email tidak terdaftar, tampilkan pesan kesalahan ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('No user found with that email')), ); } else if (error.code == 'wrong-password') { // Jika password salah, tampilkan pesan kesalahan ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('Wrong password. Please try again.')), ); } else { // Jika terjadi kesalahan lain, tampilkan pesan kesalahan umum setState(() { _errorMessage = error.message ?? 'An error occurred'; }); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(_errorMessage), ), ); } } catch (error) { // Tangani kesalahan lain yang tidak terkait dengan otentikasi setState(() { _errorMessage = error.toString(); }); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text(_errorMessage), ), ); } }, child: const Text('Sign In'), ), const SizedBox(height: 32.0), TextButton( onPressed: () { Navigator.push( context, MaterialPageRoute( builder: (context) => const SignUpScreen()), ); }, child: const Text('Don\'t have an account? Sign up'), ), const SizedBox(height: 32.0), const Text( "--- Or Sign In With ---", style: TextStyle(color: Colors.black54), ), const SizedBox(height: 32.0), ValueListenableBuilder( valueListenable: userCredential, builder: (context, value, child) { return Center( child: ElevatedButton( style: ElevatedButton.styleFrom(elevation: 5), onPressed: () async { userCredential.value = await signInWithGoogle(); if (userCredential.value != null) print(userCredential.value.user!.email); Navigator.of(context).pushReplacement( MaterialPageRoute( builder: (context) => HomeScreen()), ); }, child: Row( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center, children: [ Image.asset( 'images/googleicon.png', ), Text('Sign in with Google') ], ), ), ); }, ), ], ), ), ), ); } // Fungsi untuk memeriksa validitas email bool isValidEmail(String email) { String emailRegex = r"^[a-zA-Z0-9.!#$%&'*+/=?^`{|}~-]+@[a-zA-Z0-9-]+(?:.[a-zA-Z0-9-]+)*$"; RegExp regex = RegExp(emailRegex); return regex.hasMatch(email); } }

2. Sign up screen

import 'package:cloud_firestore/cloud_firestore.dart'; // Add this import import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/material.dart'; import 'home_screen.dart';

class SignUpScreen extends StatefulWidget { const SignUpScreen({super.key}); @override SignUpScreenState createState() => SignUpScreenState(); }

class SignUpScreenState extends State { final _nameController = TextEditingController(); final _emailController = TextEditingController(); final _passwordController = TextEditingController();

@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Fasum'), centerTitle: true, ), body: Padding( padding: const EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 32.0), Center( child: Text( 'SIGN UP', style: TextStyle( fontSize: 42, fontWeight: FontWeight.bold, ), ), ), const SizedBox(height: 32.0), TextField( controller: _nameController, decoration: InputDecoration( labelText: 'NAMA LENGKAP', border: OutlineInputBorder( borderRadius: BorderRadius.circular(20.0), ), ), ), const SizedBox(height: 16.0), TextField( controller: _emailController, decoration: InputDecoration( labelText: 'EMAIL', border: OutlineInputBorder( borderRadius: BorderRadius.circular(20.0), ), ), ), const SizedBox(height: 16.0), TextField( controller: _passwordController, obscureText: true, decoration: InputDecoration( labelText: 'SANDI', border: OutlineInputBorder( borderRadius: BorderRadius.circular(20.0), ), ), ), const SizedBox(height: 16.0), Center( child: ElevatedButton( onPressed: () async { try { UserCredential userCredential = await FirebaseAuth.instance.createUserWithEmailAndPassword( email: _emailController.text, password: _passwordController.text, );

                // Save additional user info in Firestore
                await FirebaseFirestore.instance.collection('users').doc(userCredential.user!.uid).set({
                  'full_name': _nameController.text,
                  'email': _emailController.text,
                });

                Navigator.of(context).pushReplacement(
                  MaterialPageRoute(
                    builder: (context) => HomeScreen(),
                  ),
                );
              } catch (error) {
                print(error.toString());
              }
            },
            child: const Text('Sign Up'),
          ),
        ),
      ],
    ),
  ),
);

} }

3. Search

import 'package:flutter/material.dart'; import 'package:cloud_firestore/cloud_firestore.dart';

class SearchTab extends StatefulWidget { @override _SearchTabState createState() => _SearchTabState(); }

class _SearchTabState extends State { String searchQuery = ''; List<Map<String, dynamic>> searchResults = [];

void _searchPosts(String query) async { if (query.isNotEmpty) { QuerySnapshot snapshot = await FirebaseFirestore.instance .collection('posts') .where('content', isGreaterThanOrEqualTo: query) .get();

  setState(() {
    searchResults = snapshot.docs.map((doc) => doc.data() as Map<String, dynamic>).toList();
  });
} else {
  setState(() {
    searchResults = [];
  });
}

}

@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Search'), ), body: Column( children: [ Padding( padding: const EdgeInsets.all(8.0), child: TextField( decoration: InputDecoration( labelText: 'Search', border: OutlineInputBorder( borderRadius: BorderRadius.circular(8.0), ), prefixIcon: Icon(Icons.search), ), onChanged: (value) { setState(() { searchQuery = value; }); _searchPosts(value); }, ), ), Expanded( child: searchResults.isEmpty ? Center(child: Text('No results found')) : ListView.builder( itemCount: searchResults.length, itemBuilder: (context, index) { final post = searchResults[index]; return ListTile( title: Text(post['location']['name']), subtitle: Text(post['content']), onTap: () { // You can add navigation to post details if needed }, ); }, ), ), ], ), ); } }

4. favorite

import 'package:flutter/material.dart'; import 'post.dart'; // Assuming you have a separate file for the Post class

class LoveTab extends StatelessWidget { final List likedPosts;

LoveTab({required this.likedPosts});

@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Love'), backgroundColor: Colors.brown, ), body: likedPosts.isEmpty ? Center(child: Text('No liked posts')) : ListView.builder( itemCount: likedPosts.length, itemBuilder: (BuildContext context, int index) { return _buildLikedPostItem(likedPosts[index]); }, ), ); }

Widget _buildLikedPostItem(Post post) { return Card( color: Colors.brown[50], margin: EdgeInsets.all(8.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ ListTile( leading: CircleAvatar( backgroundColor: Colors.brown, backgroundImage: NetworkImage(post.userImage), // Use NetworkImage for network images ), title: Text(post.userName, style: TextStyle(color: Colors.brown[900])), ), Padding( padding: const EdgeInsets.all(8.0), child: Image.asset( post.postImage, fit: BoxFit.cover, ), ), Padding( padding: const EdgeInsets.symmetric(horizontal: 8.0), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text('Rating: ${post.rating}', style: TextStyle(color: Colors.brown[700])), Text('Review: ${post.review}', style: TextStyle(color: Colors.brown[700])), SizedBox(height: 8), Text('Comments:', style: TextStyle( color: Colors.brown[700], fontWeight: FontWeight.bold)), SizedBox(height: 4), for (var comment in post.commentList) Text(comment, style: TextStyle(color: Colors.brown[700])), ], ), ), ], ), ); } }

5. Add post

import 'dart:io'; import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:firebase_storage/firebase_storage.dart'; import 'package:flutter/material.dart'; import 'package:firebase_auth/firebase_auth.dart'; import 'package:flutter/foundation.dart' show kIsWeb; import 'package:image_picker/image_picker.dart'; import 'package:geolocator/geolocator.dart'; import 'package:url_launcher/url_launcher.dart'; import 'home_screen.dart';

class AddPostScreen extends StatefulWidget { @override _AddPostScreenState createState() => _AddPostScreenState(); }

class _AddPostScreenState extends State { TextEditingController _postTextController = TextEditingController(); String? _imageUrl; XFile? _image; final User? user = FirebaseAuth.instance.currentUser; Position? _currentPosition;

Future _getImageFromCamera() async { final ImagePicker _picker = ImagePicker(); final XFile? image = await _picker.pickImage(source: ImageSource.camera);

if (image != null) {
  setState(() {
    _image = image;
  });

  if (!kIsWeb) {
    String? imageUrl = await _uploadImage(image);
    setState(() {
      _imageUrl = imageUrl;
    });
  } else {
    setState(() {
      _imageUrl = image.path;
    });
  }
}

}

Future<String?> _uploadImage(XFile image) async { try { final ref = FirebaseStorage.instance .ref() .child('post_images') .child('${DateTime.now().toIso8601String()}.jpg'); await ref.putFile(File(image.path)); return await ref.getDownloadURL(); } catch (e) { print('Error uploading image: $e'); return null; } }

Future _getCurrentLocation() async { bool serviceEnabled; LocationPermission permission;

serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) {
  ScaffoldMessenger.of(context).showSnackBar(
    SnackBar(content: Text('Location services are disabled.')),
  );
  return;
}

permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied) {
  permission = await Geolocator.requestPermission();
  if (permission == LocationPermission.denied) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text('Location permissions are denied')),
    );
    return;
  }
}

if (permission == LocationPermission.deniedForever) {
  ScaffoldMessenger.of(context).showSnackBar(
    SnackBar(
        content: Text(
            'Location permissions are permanently denied, we cannot request permissions.')),
  );
  return;
}

Position position = await Geolocator.getCurrentPosition(
    desiredAccuracy: LocationAccuracy.high);
setState(() {
  _currentPosition = position;
});

}

Future _showOnMap() async { if (_currentPosition != null) { final url = 'https://www.google.com/maps/search/?api=1&query=${_currentPosition!.latitude},${_currentPosition!.longitude}'; if (await canLaunch(url)) { await launch(url); } else { throw 'Could not launch $url'; } } }

@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Tambah Postingan'), ), body: SingleChildScrollView( padding: EdgeInsets.all(16.0), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ GestureDetector( onTap: _getImageFromCamera, child: Container( height: 200, color: Colors.grey[200], child: _image != null ? kIsWeb ? Image.network( _imageUrl!, fit: BoxFit.cover, ) : Image.file( File(_image!.path), fit: BoxFit.cover, ) : Icon( Icons.camera_alt, size: 100, color: Colors.grey[400], ), alignment: Alignment.center, ), ), SizedBox(height: 20), TextField( controller: _postTextController, maxLines: null, decoration: InputDecoration( hintText: 'Tulis postingan Anda di sini...', border: OutlineInputBorder(), ), ), SizedBox(height: 20), _currentPosition != null ? Text( 'Latitude: ${_currentPosition!.latitude}, Longitude: ${_currentPosition!.longitude}', textAlign: TextAlign.center, ) : Container(), ElevatedButton( onPressed: _getCurrentLocation, child: Text('Get Location'), ), ElevatedButton( onPressed: _showOnMap, child: Text('Show on Map'), ), ElevatedButton( onPressed: () async { if (_postTextController.text.isNotEmpty && _image != null) { if (_imageUrl == null) { _imageUrl = await _uploadImage(_image!); } if (_imageUrl != null) { await FirebaseFirestore.instance.collection('posts').add({ 'text': _postTextController.text, 'image_url': _imageUrl, 'timestamp': Timestamp.now(), 'username': user?.displayName ?? 'Anonymous', 'userId': user?.uid, 'latitude': _currentPosition?.latitude, 'longitude': currentPosition?.longitude, }).then(() { Navigator.of(context).pushReplacement( MaterialPageRoute( builder: (context) => HomeScreen(), ), ); }).catchError((error) { print('Error saving post: $error'); ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( 'Gagal menyimpan postingan. Silakan coba lagi.'), ), ); }); } else { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Gagal mengunggah gambar. Silakan coba lagi.'), ), ); } } else { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text('Silakan tulis postingan dan pilih gambar.'), ), ); } }, child: Text('Posting'), ), ], ), ), ); } }

6. select location

import 'package:flutter/material.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart';

class SelectLocationScreen extends StatefulWidget { @override _SelectLocationScreenState createState() => _SelectLocationScreenState(); }

class _SelectLocationScreenState extends State { GoogleMapController? _controller; LatLng _initialPosition = LatLng(-6.200000, 106.816666); // Jakarta, Indonesia LatLng? _selectedPosition;

void _onMapCreated(GoogleMapController controller) { _controller = controller; }

void _onTap(LatLng position) { setState(() { _selectedPosition = position; }); }

@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Select Location'), actions: [ if (_selectedPosition != null) IconButton( icon: const Icon(Icons.check), onPressed: () { Navigator.of(context).pop(_selectedPosition); }, ), ], ), body: GoogleMap( onMapCreated: _onMapCreated, initialCameraPosition: CameraPosition( target: _initialPosition, zoom: 10.0, ), onTap: _onTap, markers: _selectedPosition == null ? {} : { Marker( markerId: MarkerId('selected-location'), position: _selectedPosition!, ), }, ), ); } }