I created a page for user to add more posts than one for their content , the only problem is when I add the information it only appears one post ( with the next post information added) I will let a video down: https://imgur.com/a/D2qoOSu
Any idea what I should change to the code or add? Or how I can generate more posts than one
class WorkoutContentPage extends StatefulWidget {
const WorkoutContentPage({super.key});
@override
WorkoutContentPageState createState() => WorkoutContentPageState();
}
class WorkoutContentPageState extends State<WorkoutContentPage> {
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
Stream<QuerySnapshot<Map>>? stream;
String? userId;
String? nameprogram;
String? typeprogram;
String? typeequipment;
TextEditingController nameprogramController = TextEditingController();
TextEditingController typeprogramController = TextEditingController();
TextEditingController typeequipmentController = TextEditingController();
XFile? image;
Future pickImage() async {
try {
image = await ImagePicker().pickImage(source: ImageSource.gallery);
} on PlatformException catch (e) {
print('Failed to pick image: $e');
}
}
@override
void initState() {
userId = FirebaseAuth.instance.currentUser!.uid;
FirebaseFirestore.instance
.collection("Users")
.doc(userId)
.get()
.then((value) {
var data = value.data() as Map<String, dynamic>;
nameprogram = data["nameprogram"];
typeprogram = data["typeprogram"];
typeequipment = data["typeequipment"];
// Populate TextEditingControllers with existing data
nameprogramController.text = nameprogram ?? '';
typeprogramController.text = typeprogram ?? '';
typeequipmentController.text = typeequipment ?? '';
});
super.initState();
}
@override
void dispose() {
// Dispose of the controllers when the widget is disposed
nameprogramController.dispose();
typeprogramController.dispose();
typeequipmentController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
title: Text(
'Workout Content',
style: TextStyle(fontWeight: FontWeight.bold, color: Colors.white),
),
centerTitle: true,
backgroundColor: Colors.black,
),
body: Padding(
padding: const EdgeInsets.all(18.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.center,
children: [
SizedBox(
height: 30,
),
Center(
child: Column(children: [
Text(
'Add details about your entire workout program',
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 15),
),
SizedBox(
height: 20,
),
TextField(
controller: nameprogramController,
decoration: InputDecoration(
hintText: "Name of the program",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(18),
borderSide: BorderSide.none),
fillColor: Colors.black.withOpacity(0.1),
filled: true,
),
),
SizedBox(
height: 20,
),
TextField(
controller: typeprogramController,
decoration: InputDecoration(
hintText: "Type of program(ex: strength, cardio, yoga",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(18),
borderSide: BorderSide.none),
fillColor: Colors.black.withOpacity(0.1),
filled: true,
),
),
SizedBox(
height: 20,
),
TextField(
controller: typeequipmentController,
decoration: InputDecoration(
hintText: "Type of equipment used",
border: OutlineInputBorder(
borderRadius: BorderRadius.circular(18),
borderSide: BorderSide.none),
fillColor: Colors.black.withOpacity(0.1),
filled: true,
),
),
SizedBox(
height: 20,
),
Container(
width: 250,
height: 70,
child: ElevatedButton(
onPressed: () {
pickImage();
},
style: ElevatedButton.styleFrom(
shape: const StadiumBorder(),
padding: const EdgeInsets.symmetric(vertical: 16),
backgroundColor: Colors.black,
),
child: const Text(
"+Add photo/video for cover",
style: TextStyle(fontSize: 15, color: Colors.white),
),
),
),
SizedBox(
height: 20,
),
Text(
'We suggest you to do a short video of 10-15 sec with some exercise that your program has so the user can get an idea of what to expect'),
SizedBox(
height: 40,
),
Container(
width: 250,
height: 70,
child: ElevatedButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => WorkoutContentPage()),
);
},
style: ElevatedButton.styleFrom(
shape: const StadiumBorder(),
padding: const EdgeInsets.symmetric(vertical: 16),
backgroundColor: Colors.black,
),
child: const Text(
"Set price",
style: TextStyle(fontSize: 15, color: Colors.white),
),
),
),
]))
],
),
),
bottomNavigationBar: BottomAppBar(
color: const Color.fromARGB(255, 240, 240, 240),
child: Container(
width: 50,
child: ElevatedButton(
onPressed: () {
FirebaseFirestore.instance.collection("Users").doc(userId).set({
"nameprogram": nameprogramController.text,
"typeprogram": typeprogramController.text,
"typeequipment": typeequipmentController.text,
}).then((_) {
// Navigate to the user profile page
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => UserProfilePage(
imageFile: File(image!.path),
)),
);
});
},
style: ElevatedButton.styleFrom(
shape: const StadiumBorder(),
padding: const EdgeInsets.symmetric(vertical: 16),
backgroundColor: Colors.black,
),
child: Text(
'Continue',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.white,
),
)),
),
),
);
// ignore: dead_code
}
void _alertNoText(BuildContext context) {
Alert(
context: context,
type: AlertType.warning,
title: "Post",
desc: "You have not written any text",
buttons: [
DialogButton(
onPressed: () => Navigator.pop(context),
width: 120,
child: const Text(
"Close",
style: TextStyle(color: Colors.white, fontSize: 20),
),
)
],
).show();
}
}
class UserProfilePage extends StatefulWidget {
final imageFile;
const UserProfilePage({super.key, this.imageFile});
@override
State<UserProfilePage> createState() => _UserProfilePageState();
}
class _UserProfilePageState extends State<UserProfilePage> {
@override
Widget build(BuildContext context) {
final userId = FirebaseAuth.instance.currentUser!.uid;
return Scaffold(
appBar: AppBar(
title: const Text('User Profile'),
),
body: FutureBuilder<DocumentSnapshot<Map<String, dynamic>>>(
future:
FirebaseFirestore.instance.collection("Users").doc(userId).get(),
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return const Center(child: CircularProgressIndicator());
}
if (snapshot.hasError) {
return const Center(child: Text('Error fetching data'));
}
if (!snapshot.hasData || !snapshot.data!.exists) {
return const Center(child: Text('No data found'));
}
final data = snapshot.data!.data()!;
final nameprogram = data["nameprogram"];
final typeprogram = data["typeprogram"];
final typeequipment = data["typeequipment"];
return Padding(
padding: EdgeInsets.only(top: 20, left: 10, right: 10),
child: Container(
height: 135,
width: MediaQuery.of(context).size.width * 0.90,
decoration: ShapeDecoration(
shape: RoundedRectangleBorder(
borderRadius:
new BorderRadius.all(new Radius.circular(10))),
color: Colors.white,
shadows: [
BoxShadow(
color: Colors.grey.shade400,
blurRadius: 5,
spreadRadius: 2,
),
],
),
child: Row(mainAxisSize: MainAxisSize.min, children: [
SizedBox(
width: 10,
),
widget.imageFile != null
? Image.file(
widget.imageFile,
height: 80,
width: 80,
)
: Text("No image selected"),
const SizedBox(width: 10), // space between image & Column
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
SizedBox(
height: 25,
),
Text('$nameprogram',
style: TextStyle(fontWeight: FontWeight.bold)),
SizedBox(
height: 5,
),
Text('type: $typeprogram',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.grey)),
SizedBox(
height: 5,
),
Text('equipment: $typeequipment',
style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.grey)),
],
)),
])));
},
),
);
}
}