tests , readme,file names convention and search companies fix

main
Nadezda Kloos 2023-06-23 12:12:02 +02:00
parent bb8600d2f9
commit e954f240ef
28 changed files with 655 additions and 327 deletions

5
.firebaserc 100644
View File

@ -0,0 +1,5 @@
{
"projects": {
"default": "cpd-last-try"
}
}

View File

@ -1,16 +1,26 @@
# cpd_ss23
A new Flutter project.
##
## cpd_ss23
Sehr geehrter Herr Giess,
Hier ist Job Finder App , entwickelt von 2020633 und 1920881
## Getting Started
This project is a starting point for a Flutter application.
Die von uns entwickelte JobFinder Application verfügt über verschiedene Funktionalitäten, darunter :
Login/Logout,
Account erstellen/ändern,
Job Posten,
Kommentieren
Bewerben/ Kontakt aufnehmen
A few resources to get you started if this is your first Flutter project:
Als Backend haben wir uns für Firebase entschieden: wir wollten die Gelegenheit nutzen, um den Umgang und die Integration von Firebase zu lernen.
## Vorgeschlagene Test flow
- [Lab: Write your first Flutter app](https://docs.flutter.dev/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://docs.flutter.dev/cookbook)
1. Erstellen Sie einene Account. Sie müssen nicht unbedingt ein Bild hochladen. Es wird ein Default Bild zugewiesen.
2. Kommentieren/Bewerben Sie sich auf eine offene Jobstelle( zB . n3 Softwareentwickler)
3. Clicken Sie auf Profile eines anderes, der es auch kommentierte
4. Ändern Sie ihren Account
5. Kontaktieren Sie jmd
For help getting started with Flutter development, view the
[online documentation](https://docs.flutter.dev/), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
![img.png](img.png)
Wir haben ein Problem mit dem Bildanzeige in web.

15
firebase.json 100644
View File

@ -0,0 +1,15 @@
{
"firestore": {
"rules": "firestore.rules",
"indexes": "firestore.indexes.json"
},
"emulators": {
"functions": {
"port": 5001
},
"ui": {
"enabled": true
},
"singleProjectMode": true
}
}

View File

@ -0,0 +1,51 @@
{
"indexes": [
{
"collectionGroup": "jobs",
"queryScope": "COLLECTION",
"fields": [
{
"fieldPath": "jobCategory",
"order": "ASCENDING"
},
{
"fieldPath": "recruitment",
"order": "ASCENDING"
},
{
"fieldPath": "createdAt",
"order": "ASCENDING"
}
]
},
{
"collectionGroup": "jobs",
"queryScope": "COLLECTION",
"fields": [
{
"fieldPath": "recruitment",
"order": "ASCENDING"
},
{
"fieldPath": "createdAt",
"order": "ASCENDING"
}
]
},
{
"collectionGroup": "jobs",
"queryScope": "COLLECTION",
"fields": [
{
"fieldPath": "recruitment",
"order": "ASCENDING"
},
{
"fieldPath": "jobTitle",
"order": "ASCENDING"
}
]
}
],
"fieldOverrides": []
}

19
firestore.rules 100644
View File

@ -0,0 +1,19 @@
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
// This rule allows anyone with your Firestore database reference to view, edit,
// and delete all data in your Firestore database. It is useful for getting
// started, but it is configured to expire after 30 days because it
// leaves your app open to attackers. At that time, all client
// requests to your Firestore database will be denied.
//
// Make sure to write security rules for your app before that time, or else
// all client requests to your Firestore database will be denied until you Update
// your rules
match /{document=**} {
allow read, write: if request.time < timestamp.date(2023, 6, 29);
}
}
}

BIN
img.png 100644

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -3,7 +3,7 @@ import 'package:firebase_auth/firebase_auth.dart';
import '../services/global_variables.dart';
class Persistent{
class Persistent {
static List<String> jobCategoryList = [
"Architecture and Construction",
"Education and Training",
@ -16,13 +16,13 @@ class Persistent{
"Accounting"
];
void getMyData() async{
final DocumentSnapshot userDoc = await FirebaseFirestore.instance.collection("users").doc(FirebaseAuth.instance.currentUser!.uid)
void getMyData() async {
final DocumentSnapshot userDoc = await FirebaseFirestore.instance
.collection("users")
.doc(FirebaseAuth.instance.currentUser!.uid)
.get();
name = userDoc.get("name");
userImage = userDoc.get("userImage");
location = userDoc.get("location");
name = userDoc.get("name");
userImage = userDoc.get("userImage");
location = userDoc.get("location");
}
}
}

View File

@ -45,8 +45,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
final Uri params = Uri(
scheme: "mailto",
path: email,
query:
"subject=Hey from JobFinder",
query: "subject=Hey from JobFinder",
);
final url = params.toString();
launchUrlString(url);
@ -175,14 +174,13 @@ class _ProfileScreenState extends State<ProfileScreen> {
),
),
child: Stack(
children: [
Image.network(
signupUrlImage,
fit: BoxFit.cover,
width: double.infinity,
height: double.infinity,
),
Image.network(
signupUrlImage,
fit: BoxFit.cover,
width: double.infinity,
height: double.infinity,
),
SingleChildScrollView(
child: Column(
children: [

View File

@ -10,7 +10,7 @@ class AllWorkersScreen extends StatefulWidget {
class _AllWorkersScreenState extends State<AllWorkersScreen> {
final TextEditingController _searchQueryController = TextEditingController();
String searchQuery = 'Search Query';
String searchQuery = ' ';
Widget _buildSearchField() {
return TextField(
@ -60,8 +60,7 @@ class _AllWorkersScreenState extends State<AllWorkersScreen> {
begin: Alignment.centerLeft,
end: Alignment.centerRight,
stops: [0.2, 0.9],
)
),
)),
child: Scaffold(
bottomNavigationBar: BottomNavigationBarForApp(
indexNum: 1,

View File

@ -27,8 +27,7 @@ class _AllWorkersWidgetState extends State<AllWorkersWidget> {
final Uri params = Uri(
scheme: "mailto",
path: widget.userEmail,
query:
"subject=Hey from JobFinder",
query: "subject=Hey from JobFinder",
);
final url = params.toString();
launchUrlString(url);

View File

@ -9,7 +9,6 @@ import 'package:flutter/material.dart';
import '../jobs/jobs_screen.dart';
class BottomNavigationBarForApp extends StatelessWidget {
int indexNum = 0;
BottomNavigationBarForApp({required this.indexNum});
@ -19,91 +18,113 @@ class BottomNavigationBarForApp extends StatelessWidget {
showDialog(
context: context,
builder: (context){
builder: (context) {
return AlertDialog(
backgroundColor: Colors.black54,
title: const Row(
children: [
Padding(
padding: EdgeInsets.all(8.0),
child: Icon(
Icons.logout,
color: Colors.white,
size: 36
),
child: Icon(Icons.logout, color: Colors.white, size: 36),
),
Padding(
padding: EdgeInsets.all(8.0),
padding: EdgeInsets.all(8.0),
child: Text(
"Sign Out",
style: TextStyle(color: Colors.white, fontSize: 28),
),
),
),
],
),
content: const Text(
"Do you want to Log Out?",
style: TextStyle(
color: Colors.white, fontSize: 20
),
),
content: const Text(
"Do you want to Log Out?",
style: TextStyle(color: Colors.white, fontSize: 20),
),
actions: [
TextButton(
onPressed: (){
onPressed: () {
Navigator.canPop(context) ? Navigator.pop(context) : null;
},
child: const Text("No", style: TextStyle(color: Colors.green, fontSize: 18),),
child: const Text(
"No",
style: TextStyle(color: Colors.green, fontSize: 18),
),
),
TextButton(
onPressed: (){
onPressed: () {
_auth.signOut();
Navigator.canPop(context) ? Navigator.pop(context) : null;
Navigator.pushReplacement(context, MaterialPageRoute(builder: (_) => UserState()));
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (_) => UserState()));
},
child: const Text("Yes", style: TextStyle(color: Colors.green, fontSize: 18),),
child: const Text(
"Yes",
style: TextStyle(color: Colors.green, fontSize: 18),
),
)
],
);
}
);
});
}
@override
Widget build(BuildContext context) {
return CurvedNavigationBar(
color: Colors.cyan,
backgroundColor: Colors.black,
buttonBackgroundColor: Colors.white,
height: 50,
index: indexNum,
items: const [
Icon(Icons.list, size: 19, color: Colors.black,),
Icon(Icons.search, size: 19, color: Colors.black,),
Icon(Icons.add, size: 19, color: Colors.black,),
Icon(Icons.person_pin, size: 19, color: Colors.black,),
Icon(Icons.exit_to_app, size: 19, color: Colors.black,),
],
backgroundColor: Colors.black,
buttonBackgroundColor: Colors.white,
height: 50,
index: indexNum,
items: const [
Icon(
Icons.list,
size: 19,
color: Colors.black,
),
Icon(
Icons.search,
size: 19,
color: Colors.black,
),
Icon(
Icons.add,
size: 19,
color: Colors.black,
),
Icon(
Icons.person_pin,
size: 19,
color: Colors.black,
),
Icon(
Icons.exit_to_app,
size: 19,
color: Colors.black,
),
],
animationDuration: const Duration(
milliseconds: 300,
),
animationCurve: Curves.bounceInOut,
onTap: (index){
if(index == 0){
Navigator.pushReplacement(context, MaterialPageRoute(builder: (_) => JobScreen()));
} else if (index == 1){
Navigator.pushReplacement(context, MaterialPageRoute(builder: (_) => AllWorkersScreen()));
} else if (index == 2){
Navigator.pushReplacement(context, MaterialPageRoute(builder: (_) => UploadJobNow()));
} else if (index == 3){
final FirebaseAuth _auth = FirebaseAuth.instance;
onTap: (index) {
if (index == 0) {
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (_) => JobScreen()));
} else if (index == 1) {
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (_) => AllWorkersScreen()));
} else if (index == 2) {
Navigator.pushReplacement(
context, MaterialPageRoute(builder: (_) => UploadJobNow()));
} else if (index == 3) {
final FirebaseAuth _auth = FirebaseAuth.instance;
final User? user = _auth.currentUser;
final String uid = user!.uid;
Navigator.pushReplacement(context,
MaterialPageRoute(builder: (_) => ProfileScreen(userID: uid)));
} else if (index == 4) {
_logout(context);
}
else if (index == 4){
_logout(context);
}
},
);
}

View File

@ -46,19 +46,30 @@ class _JobWidgetState extends State<JobWidget> {
return AlertDialog(
actions: [
TextButton(
onPressed: () async{
try{
if(widget.uploadedBy == _uid){
await FirebaseFirestore.instance.collection("jobs").doc(widget.jobId).delete();
await Fluttertoast.showToast(msg: "Job has been deleted", toastLength: Toast.LENGTH_LONG, backgroundColor: Colors.grey, fontSize: 18.0);
Navigator.canPop(context) ? Navigator.pop(context) : null;
onPressed: () async {
try {
if (widget.uploadedBy == _uid) {
await FirebaseFirestore.instance
.collection("jobs")
.doc(widget.jobId)
.delete();
await Fluttertoast.showToast(
msg: "Job has been deleted",
toastLength: Toast.LENGTH_LONG,
backgroundColor: Colors.grey,
fontSize: 18.0);
Navigator.canPop(context)
? Navigator.pop(context)
: null;
} else {
GlobalMethod.showErrorDialog(error: "You cannot perform this action!", ctx: ctx);
GlobalMethod.showErrorDialog(
error: "You cannot perform this action!", ctx: ctx);
}
} catch (error){
} catch (error) {
//TODO Error kommt immer beim löschen fon Job aber funktioniert trotzdem
GlobalMethod.showErrorDialog(error: "This task cannot be deleted", ctx: ctx);
} finally{}
GlobalMethod.showErrorDialog(
error: "This task cannot be deleted", ctx: ctx);
} finally {}
},
child: const Row(
mainAxisAlignment: MainAxisAlignment.center,

View File

@ -43,7 +43,8 @@ class ForgetPasswort extends StatelessWidget {
),
Center(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 80),
padding:
const EdgeInsets.symmetric(horizontal: 16, vertical: 80),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.stretch,
@ -111,4 +112,4 @@ class ForgetPasswort extends StatelessWidget {
),
);
}
}
}

View File

@ -102,7 +102,7 @@ class _JobDetailsScreenState extends State<JobDetailsScreen> {
}
applyForJob() {
final Uri params = Uri(
final Uri params = Uri(
scheme: "mailto",
path: emailCompany,
query: "subject=Hey from JobFinder",
@ -539,33 +539,55 @@ class _JobDetailsScreenState extends State<JobDetailsScreen> {
horizontal: 8),
child: MaterialButton(
onPressed: () async {
if(_commentController.text.length < 7){
GlobalMethod.showErrorDialog(error: "Komment > 7 chars", ctx: context);
}
else{
final _generatedId= Uuid().v4();
await FirebaseFirestore.instance.collection('jobs').doc(widget.jobID).update({
'jobComments':
FieldValue.arrayUnion([
{'userId':FirebaseAuth.instance.currentUser!.uid,
'commentId':_generatedId,
'name': name,
'userImage':userImage,
'commentBody': _commentController.text,
'time': Timestamp.now(),}
if (_commentController
.text.length <
7) {
GlobalMethod.showErrorDialog(
error:
"Komment > 7 chars",
ctx: context);
} else {
final _generatedId =
Uuid().v4();
await FirebaseFirestore
.instance
.collection('jobs')
.doc(widget.jobID)
.update({
'jobComments': FieldValue
.arrayUnion([
{
'userId': FirebaseAuth
.instance
.currentUser!
.uid,
'commentId':
_generatedId,
'name': name,
'userImage':
userImage,
'commentBody':
_commentController
.text,
'time':
Timestamp.now(),
}
])
});
await Fluttertoast.showToast(
msg: 'Kommentaar wurde uploaded',
toastLength: Toast.LENGTH_LONG,
backgroundColor: Colors.grey,
await Fluttertoast
.showToast(
msg:
'Kommentaar wurde uploaded',
toastLength:
Toast.LENGTH_LONG,
backgroundColor:
Colors.grey,
fontSize: 18.0,
);
_commentController.clear();
setState(() {
showComment = true;
});
}
},
color: Colors.blueAccent,
@ -587,11 +609,10 @@ class _JobDetailsScreenState extends State<JobDetailsScreen> {
TextButton(
onPressed: () {
setState(() {
_isCommenting=!_isCommenting;
_isCommenting =
!_isCommenting;
showComment = false;
});
},
child: const Text("Cancel"),
)
@ -606,9 +627,8 @@ class _JobDetailsScreenState extends State<JobDetailsScreen> {
IconButton(
onPressed: () {
setState(() {
_isCommenting=!_isCommenting;
_isCommenting = !_isCommenting;
});
},
icon: const Icon(
Icons.add_comment,
@ -621,7 +641,6 @@ class _JobDetailsScreenState extends State<JobDetailsScreen> {
),
IconButton(
onPressed: () {
setState(() {
showComment = true;
});
@ -634,47 +653,61 @@ class _JobDetailsScreenState extends State<JobDetailsScreen> {
),
],
)),
showComment == false ?
Container()
showComment == false
? Container()
: Padding(
padding:EdgeInsets.all(16.0),
child: FutureBuilder<DocumentSnapshot>(
future: FirebaseFirestore.instance.collection('jobs').doc(widget.jobID).get(),
builder:(context,snapshot){
if(snapshot.connectionState == ConnectionState.waiting){
return const Center(child:CircularProgressIndicator(),);
}
else {
if(snapshot.data == null){
return const Center(child:Text("Keine kommentare"),);
}
}
return ListView.separated(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
return CommentWidget(
commentId: snapshot.data!['jobComments'][index]['commentId'],
commenterId: snapshot.data!['jobComments'][index]['userId'],
commentBody: snapshot.data!['jobComments'][index]['commentBody'],
commenterImageUrl: snapshot.data!['jobComments'][index]['userImage'],
commenterName: snapshot.data!['jobComments'][index]['name'],
);
},
separatorBuilder: (context, index) {
return const Divider(
thickness: 1,
color: Colors.grey,
);
},
itemCount: snapshot.data!['jobComments'].length,
);
}
)
)
padding: EdgeInsets.all(16.0),
child: FutureBuilder<DocumentSnapshot>(
future: FirebaseFirestore.instance
.collection('jobs')
.doc(widget.jobID)
.get(),
builder: (context, snapshot) {
if (snapshot.connectionState ==
ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
} else {
if (snapshot.data == null) {
return const Center(
child: Text("Keine kommentare"),
);
}
}
return ListView.separated(
shrinkWrap: true,
physics:
const NeverScrollableScrollPhysics(),
itemBuilder: (context, index) {
return CommentWidget(
commentId:
snapshot.data!['jobComments']
[index]['commentId'],
commenterId:
snapshot.data!['jobComments']
[index]['userId'],
commentBody:
snapshot.data!['jobComments']
[index]['commentBody'],
commenterImageUrl:
snapshot.data!['jobComments']
[index]['userImage'],
commenterName:
snapshot.data!['jobComments']
[index]['name'],
);
},
separatorBuilder: (context, index) {
return const Divider(
thickness: 1,
color: Colors.grey,
);
},
itemCount: snapshot
.data!['jobComments'].length,
);
}))
],
),
),

View File

@ -42,7 +42,8 @@ class _JobScreenState extends State<JobScreen> {
jobCategoryFilter = Persistent.jobCategoryList[index];
});
Navigator.canPop(context) ? Navigator.pop(context) : null;
print("jobCategoryList[index], ${Persistent.jobCategoryList[index]}");
print(
"jobCategoryList[index], ${Persistent.jobCategoryList[index]}");
},
child: Row(
children: [
@ -157,7 +158,8 @@ class _JobScreenState extends State<JobScreen> {
.orderBy("createdAt", descending: false)
.snapshots(),
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
if (snapshot.connectionState ==
ConnectionState.waiting) {
return const Center(
child: CircularProgressIndicator(),
);
@ -169,15 +171,21 @@ class _JobScreenState extends State<JobScreen> {
itemCount: snapshot.data?.docs.length,
itemBuilder: (BuildContext context, int index) {
return JobWidget(
jobTitle: snapshot.data?.docs[index]["jobTitle"],
jobDescription: snapshot.data!.docs[index]["jobDescription"],
jobTitle: snapshot.data?.docs[index]
["jobTitle"],
jobDescription: snapshot.data!.docs[index]
["jobDescription"],
jobId: snapshot.data?.docs[index]["jobId"],
uploadedBy: snapshot.data?.docs[index]["uploadedBy"],
userImage: snapshot.data?.docs[index]["userImage"],
uploadedBy: snapshot.data?.docs[index]
["uploadedBy"],
userImage: snapshot.data?.docs[index]
["userImage"],
name: snapshot.data?.docs[index]["name"],
recruitment: snapshot.data?.docs[index]["recruitment"],
recruitment: snapshot.data?.docs[index]
["recruitment"],
email: snapshot.data?.docs[index]["email"],
location: snapshot.data?.docs[index]["location"],
location: snapshot.data?.docs[index]
["location"],
);
},
);
@ -200,7 +208,6 @@ class _JobScreenState extends State<JobScreen> {
),
),
const SizedBox(height: 10),
],
),
),

View File

@ -31,7 +31,7 @@ class _UploadJobNowState extends State<UploadJobNow> {
bool _isLoading = false;
@override
void dispose(){
void dispose() {
super.dispose();
_jobCategoryController.dispose();
_jobTitleController.dispose();
@ -242,9 +242,6 @@ class _UploadJobNowState extends State<UploadJobNow> {
}
}
@override
Widget build(BuildContext context) {
Size size = MediaQuery.of(context).size;

View File

@ -4,8 +4,6 @@ import 'package:cpd_ss23/services/global_methods.dart';
import 'package:cpd_ss23/services/global_variables.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import '../forget_passwort/forget_pass_screen.dart';
import '../signup_page/signup_screen.dart';
class Login extends StatefulWidget {

View File

@ -1,37 +1,15 @@
import 'package:cpd_ss23/login_page/login_screen.dart';
import 'package:cpd_ss23/test.dart';
import 'package:cpd_ss23/user_state.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:cpd_ss23/firebase_options.dart'; // Importieren Sie die Firebase-Optionen
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';
void main() async {/*
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Firebase Test',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: FirebaseTestPage(),
);
}
}*/
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
runApp(MyApp());
}
class MyApp extends StatelessWidget {
final Future<FirebaseApp> _initialisation = Firebase.initializeApp();
@ -89,4 +67,3 @@ class MyApp extends StatelessWidget {
);
}
}

View File

@ -2,14 +2,15 @@
import 'package:flutter/material.dart';
class GlobalMethod{
static void showErrorDialog({required String error, required BuildContext ctx}) {
class GlobalMethod {
static void showErrorDialog(
{required String error, required BuildContext ctx}) {
showDialog(
context: ctx,
builder: (context) {
return AlertDialog(
title: Row (
children: const [
title: Row(
children: const [
Padding(
padding: EdgeInsets.all(8.0),
child: Icon(Icons.logout, color: Colors.grey, size: 35),
@ -31,8 +32,9 @@ class GlobalMethod{
actions: [
TextButton(
onPressed: () {
Navigator.canPop(context) ? Navigator.pop(context) : null; // Zurücknavigieren, falls möglich
Navigator.canPop(context)
? Navigator.pop(context)
: null; // Zurücknavigieren, falls möglich
},
child: const Text(
'oki doki',
@ -44,7 +46,6 @@ class GlobalMethod{
},
);
}
static void getPicture(){
}
static void getPicture() {}
}

View File

@ -1,6 +1,9 @@
String loginUrlImage = "https://images.unsplash.com/photo-1523050854058-8df90110c9f1?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxzZWFyY2h8Mnx8dW5pdmVyc2l0eXxlbnwwfHwwfHw%3D&w=1000&q=80";
String signupUrlImage= 'https://images.unsplash.com/photo-1575330734740-21b22ac7bf5e?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxleHBsb3JlLWZlZWR8MXx8fGVufDB8fHx8fA%3D%3D&w=1000&q=80';
String signupGenericImage = 'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSeqUFP0nU4pUnNncq4dy7M6X6xYRYwUQduFcLkQ9yEAYMzORlw5eHddyCPMUY4yK2PBJ8&usqp=CAU';
String loginUrlImage =
"https://images.unsplash.com/photo-1523050854058-8df90110c9f1?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxzZWFyY2h8Mnx8dW5pdmVyc2l0eXxlbnwwfHwwfHw%3D&w=1000&q=80";
String signupUrlImage =
'https://images.unsplash.com/photo-1575330734740-21b22ac7bf5e?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxleHBsb3JlLWZlZWR8MXx8fGVufDB8fHx8fA%3D%3D&w=1000&q=80';
String signupGenericImage =
'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcSeqUFP0nU4pUnNncq4dy7M6X6xYRYwUQduFcLkQ9yEAYMzORlw5eHddyCPMUY4yK2PBJ8&usqp=CAU';
String? name = "";
String? userImage = "";
String? location = "";
String? location = "";

View File

@ -12,8 +12,6 @@ import 'package:firebase_auth/firebase_auth.dart';
import 'package:path_provider/path_provider.dart';
import 'package:flutter/foundation.dart' show kIsWeb;
class SignUp extends StatefulWidget {
@override
State<SignUp> createState() => _SignUpState();
@ -27,7 +25,8 @@ class _SignUpState extends State<SignUp> {
final TextEditingController _nameTextController = TextEditingController();
final TextEditingController _cityTextController = TextEditingController();
final TextEditingController _emailTextController = TextEditingController();
final TextEditingController _phoneNumberTextController = TextEditingController();
final TextEditingController _phoneNumberTextController =
TextEditingController();
final TextEditingController _passwordTextController = TextEditingController();
bool _isLoading = false;
final FirebaseAuth _auth = FirebaseAuth.instance;
@ -71,18 +70,18 @@ class _SignUpState extends State<SignUp> {
void _submitFormSignup() async {
final isValid = _signUpFormKey.currentState!.validate();
if (isValid) {
if (imageFile == null) {
if (kIsWeb) {
//hier sollte eine methode zum erstellen des Files aus internet geben( weil in web path_provider.dart'; nicht realoisiert ist) , aber es ist mir zu viel
} else {
final appDir = await getApplicationDocumentsDirectory();
final defaultImagePath = '${appDir.path}/default_profile_image.jpg';
final defaultImageAsset = await rootBundle.load(
'assets/images/genericProfile.jpg');
final bytes = defaultImageAsset.buffer.asUint8List();
await File(defaultImagePath).writeAsBytes(bytes);
imageFile = File(defaultImagePath);
}
if (imageFile == null) {
if (kIsWeb) {
//hier sollte eine methode zum erstellen des Files aus internet geben( weil in web path_provider.dart'; nicht realoisiert ist) , aber es ist mir zu viel
} else {
final appDir = await getApplicationDocumentsDirectory();
final defaultImagePath = '${appDir.path}/default_profile_image.jpg';
final defaultImageAsset =
await rootBundle.load('assets/images/genericProfile.jpg');
final bytes = defaultImageAsset.buffer.asUint8List();
await File(defaultImagePath).writeAsBytes(bytes);
imageFile = File(defaultImagePath);
}
}
}
setState(() {
@ -90,36 +89,40 @@ class _SignUpState extends State<SignUp> {
});
try {
await _auth.createUserWithEmailAndPassword(
await _auth.createUserWithEmailAndPassword(
email: _emailTextController.text.trim(),
password: _passwordTextController.text.trim(),
);
final User? user = _auth.currentUser;
final _uid = user!.uid;
if (kIsWeb) {
imageUrl= "https://firebasestorage.googleapis.com/v0/b/cpd-last-try.appspot.com/o/userImages%2Fweb_foto.jpeg?alt=media&token=41db34c9-ce68-4d5f-a10b-e45802479999";
}
else{
final ref = FirebaseStorage.instance.ref().child('userImages').child('$_uid.jpg');
await ref.putFile(imageFile!);
imageUrl = await ref.getDownloadURL();}
FirebaseFirestore.instance.collection('users').doc(_uid).set({
'id': _uid,
'name': _nameTextController.text,
'email': _emailTextController.text,
'userImage':imageUrl,
'phone':_phoneNumberTextController.text,
'location': _cityTextController.text,
'createdAt': Timestamp.now(),
});
Navigator.canPop(context) ? Navigator.pop(context) : null;
} catch (e) {
final User? user = _auth.currentUser;
final _uid = user!.uid;
if (kIsWeb) {
imageUrl =
"https://firebasestorage.googleapis.com/v0/b/cpd-last-try.appspot.com/o/userImages%2Fweb_foto.jpeg?alt=media&token=41db34c9-ce68-4d5f-a10b-e45802479999";
} else {
final ref = FirebaseStorage.instance
.ref()
.child('userImages')
.child('$_uid.jpg');
await ref.putFile(imageFile!);
imageUrl = await ref.getDownloadURL();
}
FirebaseFirestore.instance.collection('users').doc(_uid).set({
'id': _uid,
'name': _nameTextController.text,
'email': _emailTextController.text,
'userImage': imageUrl,
'phone': _phoneNumberTextController.text,
'location': _cityTextController.text,
'createdAt': Timestamp.now(),
});
Navigator.canPop(context) ? Navigator.pop(context) : null;
} catch (e) {
// Handle any errors that occur during sign-up
setState(){
setState() {
_isLoading = false;
}
GlobalMethod.showErrorDialog(error: e.toString(), ctx: context);
GlobalMethod.showErrorDialog(error: e.toString(), ctx: context);
}
setState(() {
_isLoading = false;
@ -146,7 +149,8 @@ class _SignUpState extends State<SignUp> {
children: [
Form(
key: _signUpFormKey,
autovalidateMode: AutovalidateMode.always, // Enable immediate validation
autovalidateMode:
AutovalidateMode.always, // Enable immediate validation
child: Column(
children: [
GestureDetector(
@ -163,21 +167,22 @@ class _SignUpState extends State<SignUp> {
width: size.width * 0.44,
height: size.width * 0.44,
decoration: BoxDecoration(
border: Border.all(width: 5, color: Colors.cyan),
border:
Border.all(width: 5, color: Colors.cyan),
borderRadius: BorderRadius.circular(100),
),
child: ClipRRect(
borderRadius: BorderRadius.circular(100),
child: imageFile == null
? const Icon(
Icons.camera_alt_rounded,
color: Colors.cyan,
size: 120,
)
Icons.camera_alt_rounded,
color: Colors.cyan,
size: 120,
)
: Image.file(
imageFile!,
fit: BoxFit.fill,
),
imageFile!,
fit: BoxFit.fill,
),
),
),
),
@ -241,32 +246,33 @@ class _SignUpState extends State<SignUp> {
),
_isLoading
? Center(
child: Container(
width: 70,
height: 70,
child: const CircularProgressIndicator(),
),
)
: MaterialButton(
onPressed: _submitFormSignup, color: Colors.cyan,
elevation: 8,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(13)),
child: const Padding(
padding: EdgeInsets.symmetric(vertical: 14),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Sign Up',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold),
child: Container(
width: 70,
height: 70,
child: const CircularProgressIndicator(),
),
],
),
),
),
)
: MaterialButton(
onPressed: _submitFormSignup,
color: Colors.cyan,
elevation: 8,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(13)),
child: const Padding(
padding: EdgeInsets.symmetric(vertical: 14),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Sign Up',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold),
),
],
),
),
),
const SizedBox(
height: 15,
),

View File

@ -33,8 +33,10 @@ class _FirebaseTestPageState extends State<FirebaseTestPage> {
Future<void> testFirebaseAuth() async {
try {
UserCredential userCredential = await FirebaseAuth.instance.signInAnonymously();
print('Firebase Authentication Successful. User ID: ${userCredential.user?.uid}');
UserCredential userCredential =
await FirebaseAuth.instance.signInAnonymously();
print(
'Firebase Authentication Successful. User ID: ${userCredential.user?.uid}');
} catch (e) {
print('Firebase Authentication Error: $e');
}

View File

@ -5,40 +5,36 @@ import 'package:flutter/material.dart';
import 'login_page/login_screen.dart';
class UserState extends StatelessWidget {// enthält keine internen Variablen, die sich während der Laufzeit ändern können.
class UserState extends StatelessWidget {
// enthält keine internen Variablen, die sich während der Laufzeit ändern können.
@override
Widget build(BuildContext context) {
return StreamBuilder(
stream:FirebaseAuth.instance.authStateChanges(),builder: (context, userSnapshot){
if(userSnapshot.data == null){
stream: FirebaseAuth.instance.authStateChanges(),
builder: (context, userSnapshot) {
if (userSnapshot.data == null) {
print('user isnt logged in yet');
return Login();
}
else if(userSnapshot.hasData){
} else if (userSnapshot.hasData) {
print('user is already logged in ');
return JobScreen();
}
else if(userSnapshot.hasError){
return const Scaffold(
body: Center(
child:Text("An Error ossured"),
)
);
}
else if(userSnapshot.connectionState == ConnectionState.waiting){
} else if (userSnapshot.hasError) {
return const Scaffold(
body: Center(
child:CircularProgressIndicator(),
)
);
child: Text("An Error ossured"),
));
} else if (userSnapshot.connectionState == ConnectionState.waiting) {
return const Scaffold(
body: Center(
child: CircularProgressIndicator(),
));
}
return const Scaffold(body:Center(
child:Text( "Smt went wrong"),
return const Scaffold(
body: Center(
child: Text("Smt went wrong"),
));
},
},
);
}
}

View File

@ -1,6 +1,14 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
_fe_analyzer_shared:
dependency: transitive
description:
name: _fe_analyzer_shared
sha256: ae92f5d747aee634b87f89d9946000c2de774be1d6ac3e58268224348cd0101a
url: "https://pub.dev"
source: hosted
version: "61.0.0"
_flutterfire_internals:
dependency: transitive
description:
@ -9,6 +17,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.3.3"
analyzer:
dependency: transitive
description:
name: analyzer
sha256: ea3d8652bda62982addfd92fdc2d0214e5f82e43325104990d4f4c4a2a313562
url: "https://pub.dev"
source: hosted
version: "5.13.0"
archive:
dependency: transitive
description:
@ -17,6 +33,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.3.7"
args:
dependency: transitive
description:
name: args
sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
url: "https://pub.dev"
source: hosted
version: "2.4.2"
async:
dependency: transitive
description:
@ -33,6 +57,30 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.1"
build:
dependency: transitive
description:
name: build
sha256: "43865b79fbb78532e4bff7c33087aa43b1d488c4fdef014eaef568af6d8016dc"
url: "https://pub.dev"
source: hosted
version: "2.4.0"
built_collection:
dependency: transitive
description:
name: built_collection
sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100"
url: "https://pub.dev"
source: hosted
version: "5.1.1"
built_value:
dependency: transitive
description:
name: built_value
sha256: "598a2a682e2a7a90f08ba39c0aaa9374c5112340f0a2e275f61b59389543d166"
url: "https://pub.dev"
source: hosted
version: "8.6.1"
cached_network_image:
dependency: "direct main"
description:
@ -97,6 +145,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.6.1"
code_builder:
dependency: transitive
description:
name: code_builder
sha256: "4ad01d6e56db961d29661561effde45e519939fdaeb46c351275b182eac70189"
url: "https://pub.dev"
source: hosted
version: "4.5.0"
collection:
dependency: transitive
description:
@ -145,6 +201,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.3"
dart_style:
dependency: transitive
description:
name: dart_style
sha256: f4f1f73ab3fd2afcbcca165ee601fe980d966af6a21b5970c6c9376955c528ad
url: "https://pub.dev"
source: hosted
version: "2.3.1"
fake_async:
dependency: transitive
description:
@ -273,6 +337,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.6.3"
fixnum:
dependency: transitive
description:
name: fixnum
sha256: "25517a4deb0c03aa0f32fd12db525856438902d9c16536311e76cdc57b31d7d1"
url: "https://pub.dev"
source: hosted
version: "1.1.0"
flutter:
dependency: "direct main"
description: flutter
@ -336,6 +408,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "8.2.2"
glob:
dependency: transitive
description:
name: glob
sha256: "0e7014b3b7d4dac1ca4d6114f82bf1782ee86745b9b42a92c9289c23d8a0ab63"
url: "https://pub.dev"
source: hosted
version: "2.1.2"
http:
dependency: "direct main"
description:
@ -396,10 +476,10 @@ packages:
dependency: transitive
description:
name: image_picker_android
sha256: "216dbfb6609e46f78613b8913d046a162588ad4f34909ae7bf85e9f94ea6d922"
sha256: d2bab152deb2547ea6f53d82ebca9b7e77386bb706e5789e815d37e08ea475bb
url: "https://pub.dev"
source: hosted
version: "0.8.7"
version: "0.8.7+3"
image_picker_for_web:
dependency: transitive
description:
@ -472,6 +552,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.0.1"
logging:
dependency: transitive
description:
name: logging
sha256: "623a88c9594aa774443aa3eb2d41807a48486b5613e67599fb4c41c0ad47c340"
url: "https://pub.dev"
source: hosted
version: "1.2.0"
matcher:
dependency: transitive
description:
@ -504,6 +592,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.4"
mockito:
dependency: "direct dev"
description:
name: mockito
sha256: dd61809f04da1838a680926de50a9e87385c1de91c6579629c3d1723946e8059
url: "https://pub.dev"
source: hosted
version: "5.4.0"
octo_image:
dependency: transitive
description:
@ -512,6 +608,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.2"
package_config:
dependency: transitive
description:
name: package_config
sha256: "1c5b77ccc91e4823a5af61ee74e6b972db1ef98c2ff5a18d3161c982a55448bd"
url: "https://pub.dev"
source: hosted
version: "2.1.0"
path:
dependency: transitive
description:
@ -616,6 +720,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.2.4"
pub_semver:
dependency: transitive
description:
name: pub_semver
sha256: "40d3ab1bbd474c4c2328c91e3a7df8c6dd629b79ece4c4bd04bee496a224fb0c"
url: "https://pub.dev"
source: hosted
version: "2.1.4"
rxdart:
dependency: transitive
description:
@ -629,6 +741,14 @@ packages:
description: flutter
source: sdk
version: "0.0.99"
source_gen:
dependency: transitive
description:
name: source_gen
sha256: "373f96cf5a8744bc9816c1ff41cf5391bbdbe3d7a96fe98c622b6738a8a7bd33"
url: "https://pub.dev"
source: hosted
version: "1.3.2"
source_span:
dependency: transitive
description:
@ -789,6 +909,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "2.1.4"
watcher:
dependency: transitive
description:
name: watcher
sha256: "6a7f46926b01ce81bfc339da6a7f20afbe7733eff9846f6d6a5466aa4c6667c0"
url: "https://pub.dev"
source: hosted
version: "1.0.2"
win32:
dependency: transitive
description:
@ -813,6 +941,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "6.3.0"
yaml:
dependency: transitive
description:
name: yaml
sha256: "75769501ea3489fca56601ff33454fe45507ea3bfb014161abc3b43ae25989d5"
url: "https://pub.dev"
source: hosted
version: "3.1.2"
sdks:
dart: ">=3.0.0-378.0.dev <4.0.0"
flutter: ">=3.3.0"

View File

@ -33,6 +33,7 @@ dependencies:
dev_dependencies:
flutter_test:
sdk: flutter
mockito: ^5.0.0
flutter_lints: ^2.0.0
@ -42,6 +43,7 @@ flutter:
assets:
- assets/images/
- test/google-services-test.json
fonts:
- family: Signatra

View File

@ -0,0 +1,13 @@
{
"type": "service_account",
"project_id": "cpd-last-try",
"private_key_id": "a574c92606dc877fec4fa860e1584120a097fa99",
"private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCY/QbjHoU1i1qj\n2nOjJoBEw8SkoDp4g5iXoohAlsRwDJkSpA5xPeJhQ1V/R29bZUC1vqlTeSWt2AvV\n0TmZnObqRKcP0yzFwuZI8hgE17Excwc90lQDbEgku9ZsiryYvCzI2iFJyV/gjzd6\nJB4Hd7FFxwFmF4Dh2qhD4XcY6WwQkNFY73yLbUAZUkL3mfb36sbDR28KX04Z32TQ\n+Lq8FqbAuq9TotpvkInjspdu1OYkDuc9XQezSulAz7zcOmz9fLFBsrJSojx2ppK8\nRPUuckIJPLAec0jeGT6IfLiODXPxwmTuSSPc51Yx1of7qY1gnEGR64f20eiXY6C0\nMLFESuA7AgMBAAECggEABGbn+9NHRoVr+IZpv6pQgfMpPC7W7ZMSoO7lbwieYu1D\nA20nT4P6nUQeJjtlrXAertLrUOuNvpCERqmTE0hywQ90EWvtiUxUoa3VmfKj/7g/\nljxd6ekDs4rhzAJNXTMfMjFv/zHObiVnp9CdqAJ+OZhU3WaUTH2lAvOS+/2pIKMj\nQpGLtUqI2+zm49u/EIGx/OHJLM0ivjLfIW94sdqmEQrCaQpC2SEG5vIxKwnOtyvw\nYoZ4Rbb4qx8cPJ6A8RTqmw38TzXiLZL4YauvIiRDcsGeu/3QY9Donk7FaMxCXcQD\nMnPqFmXq9THPyo7xU+3pZGwRmAM1Wqyndn0W0Yw/gQKBgQDTAEaiTkMt/AnXZnoa\noYOIq7uKEwROcZ1+JGjNjboj+2QfSCBBACdIgfCrP+2Q/2DQNPlemUEz8T5JGsK4\n8+58sjaW/dqsXXsyzcMAm/ID+cOd/iMHE0iBWa1Jz7+7zdOi9CqFWxDMdOtcYjrk\n6/O9WU7ErO/4rdxLYfYRORDOrQKBgQC5nYPZnv5CQ+jGYekpLkVkJGCPg6/F9CPa\nm69xgCNFS5ZTpAKxLbiwUaDcHPeyGeytHhxgY19C1c3kqknMm4iVsHOo5lMCwFgu\nRhTuCm/36O2K2RoiimgHwxAXc5q12TbteP+/jQIbUCFqxfo7dbFCHryHKAc4gBAy\nc28fJJDPhwKBgBnc4cuJLkDXsNkfLX5QJ9A7xIwDErcOxBAvJE11vsgkSzxuWc29\n2BLSIo7LEjKAqvw6UgqfXFeijVDmn9GNzMCqE3jkesY/2xb6E5nig4KrPagC+4Yl\nffCk7lGqzkSV0QgbR476/48gEa1MOQ3QQhsGdFo1HGDt5p+yzTeFOCMtAoGBAKiB\nfvlJhbnSvLecm3dvMj+/ZonjGueyw/np7FQ1588417gG5QrEXy5ybH5nLdbaAisH\ncutuS0T5pHk6vtSpPk3mapmivyl4RJV9ufKANzXwl/W9MiS5Ucf6JdmkcYc1MtBT\nUJotAQSasjukj477QXitPqnUhPmeCRZEBVVYdL5xAoGAX7xuakEjjzOtRfz1U57p\nhtoD8CzPQYuT5Tq2HSTiKhi7WB5HQPOGoKLw+oq7HZxAun/sZ0wbZZj3uvEX6FDJ\n7Ail+qibInlp1VtPlwbXRT7kB0b4fGNEONd75YHWeCagHuU7VFGh2FPnbmFN4XU/\nyxxRe2fJ62GzrO7WcwSeyM8=\n-----END PRIVATE KEY-----\n",
"client_email": "firebase-adminsdk-fi8et@cpd-last-try.iam.gserviceaccount.com",
"client_id": "103781669883338209830",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-fi8et%40cpd-last-try.iam.gserviceaccount.com",
"universe_domain": "googleapis.com"
}

22
test/mock.dart 100644
View File

@ -0,0 +1,22 @@
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:firebase_core_platform_interface/firebase_core_platform_interface.dart';
import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart';
typedef Callback = void Function(MethodCall call);
void setupFirebaseAuthMocks([Callback? customHandlers]) {
TestWidgetsFlutterBinding.ensureInitialized();
setupFirebaseCoreMocks();
}
Future<T> neverEndingFuture<T>() async {
// ignore: literal_only_boolean_expressions
while (true) {
await Future.delayed(const Duration(minutes: 5));
}
}

View File

@ -1,30 +1,36 @@
// This is a basic Flutter widget test.
//
// To perform an interaction with a widget in your test, use the WidgetTester
// utility in the flutter_test package. For example, you can send tap and scroll
// gestures. You can also use WidgetTester to find child widgets in the widget
// tree, read text, and verify that the values of widget properties are correct.
import 'package:cpd_ss23/jobs/jobs_screen.dart';
import 'package:cpd_ss23/login_page/login_screen.dart';
import 'package:cpd_ss23/user_state.dart';
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:cpd_ss23/main.dart';
import 'package:firebase_core/firebase_core.dart';
import './mock.dart';
void main() {
testWidgets('Counter increments smoke test', (WidgetTester tester) async {
// Build our app and trigger a frame.
await tester.pumpWidget(MyApp());
setupFirebaseAuthMocks();
// Verify that our counter starts at 0.
expect(find.text('0'), findsOneWidget);
expect(find.text('1'), findsNothing);
setUpAll(() async {
await Firebase.initializeApp();
});
// Tap the '+' icon and trigger a frame.
await tester.tap(find.byIcon(Icons.add));
await tester.pump();
testWidgets('Firebase Initialization Test', (WidgetTester tester) async {
// Initialize Firebase
// Verify that our counter has incremented.
expect(find.text('0'), findsNothing);
expect(find.text('1'), findsOneWidget);
// Check if Firebase is initialized
final isFirebaseInitialized = Firebase.apps.isNotEmpty;
// Perform your test assertions
expect(isFirebaseInitialized, isTrue);
});
testWidgets('UserState Widget - User not logged in',
(WidgetTester tester) async {
await tester.pumpWidget(MaterialApp(home: UserState()));
// Überprüfen, ob das Login-Widget angezeigt wird
expect(find.byType(Login), findsOneWidget);
// Überprüfen, ob das JobScreen-Widget nicht angezeigt wird
expect(find.byType(JobScreen), findsNothing);
});
}