0% found this document useful (0 votes)
17 views18 pages

API (Simple)

The document outlines a Flutter application that manages places associated with cities, including models for Place and API interactions for fetching, adding, and deleting places. It features an Add Place screen where users can input place names and select cities from a dropdown, as well as a Place Detail screen for displaying and managing places. The application utilizes HTTP requests to communicate with a backend server for data operations.

Uploaded by

M Tech Solutions
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
17 views18 pages

API (Simple)

The document outlines a Flutter application that manages places associated with cities, including models for Place and API interactions for fetching, adding, and deleting places. It features an Add Place screen where users can input place names and select cities from a dropdown, as well as a Place Detail screen for displaying and managing places. The application utilizes HTTP requests to communicate with a backend server for data operations.

Uploaded by

M Tech Solutions
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 18

MODEL

class Place {

int? id; // Nullable, because the ID will be auto-generated by the database

String name;

int city_id;

// Constructor to create a Place object directly with a name

Place({required this.name, required this.city_id});

// Constructor to create a Place from a Map (e.g., from a database row)

Place.fromMap(Map<String, dynamic> map)

: id = map['id'],

name = map['name'],

city_id = map['city_id'];

// Method to convert a City object back to a Map (useful for inserting/updating)

Map<String, dynamic> toMap() {

return {'name': name, 'city_id': city_id};

API

class API {

static final String _baseurl = 'http://127.0.0.1:4321';

Future<http.Response> getAllCities() async {

String url =

'$_baseurl/city'; // Assuming the endpoint for cities is /cities

var response = await http.get(Uri.parse(url));

return response;

Future<http.Response> getAllplaces(String name) async {

String url =

'$_baseurl/place?name=$name'; // Assuming 'name' is a query parameter

try {

var response = await http.get(

Uri.parse(url),
headers: {"Content-Type": "application/json"},

);

return response;

} catch (e) {

throw Exception('Error fetching places: $e');

Future<bool> deleteplace(String placename, String cityname) async {

String url = '$_baseurl/deleteplace';

try {

var response = await http.delete(

Uri.parse(url),

headers: {"Content-Type": "application/json"},

body: json.encode({

'placename': placename,

'cityname': cityname

}), // Send the city data

);

if (response.statusCode == 201) {

return true; // Success

} else {

return false; // Failed to add city

} catch (e) {

throw Exception('Error Deleting city: $e');

Future<bool> addplace(String placename, String cityname) async {

String url = '$_baseurl/addplace';

try {

var response = await http.post(

Uri.parse(url),

headers: {"Content-Type": "application/json"},

body: json.encode({

'placename': placename,
'cityname': cityname

}), // Send the city data

);

if (response.statusCode == 200) {

return true; // Success

} else {

return false; // Failed to add city

} catch (e) {

throw Exception('Error adding city: $e');

Add Place Screen

class AddPLace extends StatefulWidget {

const AddPLace({super.key});

@override

State<AddPLace> createState() => _AddPLaceState();

class _AddPLaceState extends State<AddPLace> {

API api = API();

bool _isLoading = false;

List<City> cityList = [];

final TextEditingController _placecontroller = TextEditingController();

String? selectedCity;

Future<void> _addplace() async {

if (selectedCity == null || _placecontroller.text.isEmpty) {

ScaffoldMessenger.of(context).showSnackBar(

SnackBar(content: Text('Please Select city name or Enter Place Name')),

);

return;
}

setState(() {

_isLoading = true;

});

try {

// Call the API method to save the city

bool success = await api.addplace(_placecontroller.text, selectedCity!);

if (success) {

// Show success message

ScaffoldMessenger.of(context).showSnackBar(

SnackBar(content: Text('Place added successfully')),

);

_placecontroller.clear();

} else {

ScaffoldMessenger.of(context).showSnackBar(

SnackBar(content: Text('Failed to add Place')),

);

} catch (e) {

ScaffoldMessenger.of(context).showSnackBar(

SnackBar(content: Text('Error: $e')),

);

} finally {

setState(() {

_isLoading = false;

});

// Fetching cities from the API

Future<void> _getCities() async {

setState(() {

_isLoading = true;

});
try {

var response = await api.getAllCities();

if (response.statusCode == 200) {

List<dynamic> mapList = jsonDecode(response.body);

cityList = mapList.map((e) => City.fromMap(e)).toList();

// Set the first city as the selected city by default

selectedCity = cityList.isNotEmpty ? cityList[0].name : null;

// Fetch places for the default selected city

// if (selectedCity != null) {

// _getplaces(selectedCity!);

// }

ScaffoldMessenger.of(context).showSnackBar(

SnackBar(content: Text('Cities fetched successfully')),

);

} else {

ScaffoldMessenger.of(context).showSnackBar(

SnackBar(content: Text('Failed to fetch cities')),

);

} catch (e) {

ScaffoldMessenger.of(context).showSnackBar(

SnackBar(content: Text('Error: $e')),

);

} finally {

setState(() {

_isLoading = false;

});

@override

void initState() {

super.initState();

_getCities(); // Fetch the cities when the screen loads


}

@override

Widget build(BuildContext context) {

return Scaffold(

appBar: PreferredSize(

preferredSize:

const Size.fromHeight(150), // Adjusted height for better spacing

child: AppBar(

automaticallyImplyLeading: false, // Removes default back button

flexibleSpace: Container(

decoration: BoxDecoration(

gradient: LinearGradient(

colors: [Colors.teal.shade700, Colors.teal.shade400],

begin: Alignment.topLeft,

end: Alignment.bottomRight,

),

),

child: Center(

// Ensures content is centered

child: Column(

mainAxisAlignment:

MainAxisAlignment.center, // Centers content vertically

children: [

const Text(

"Add Place",

style: TextStyle(

color: Colors.white,

fontSize: 22,

fontWeight: FontWeight.bold,

),

),

const SizedBox(height: 10),

Text(

"Set up and manage a new traffic control post location",

textAlign: TextAlign.center, // Centers text horizontally

style: TextStyle(

color: Colors
.grey[200], // Use light grey for better visibility

fontSize: 16,

fontWeight: FontWeight.normal,

),

),

],

),

),

),

),

),

body: Stack(

children: [

// Main content

Padding(

padding: const EdgeInsets.all(16.0),

child: Column(

crossAxisAlignment: CrossAxisAlignment.start,

children: [

const Text('Enter place name:'),

const SizedBox(height: 10),

TextFormField(

controller: _placecontroller, // Connect the controller

decoration: const InputDecoration(

labelText: 'Enter place name',

border: OutlineInputBorder(),

prefixIcon: Icon(Icons.location_city_rounded),

),

),

const SizedBox(height: 10),

// Dropdown for Place

const Text('Select City:'),

const SizedBox(height: 10),

Container(

width: double.infinity,

child: DropdownButton<String?>(

isExpanded: true,
hint: const Text(

'Choose City',

style: TextStyle(fontSize: 12),

),

value: selectedCity,

items: cityList.isEmpty

?[

const DropdownMenuItem(

value: null,

child: Text('No cities available'),

),

] : cityList.map((e) => DropdownMenuItem<String>(

value: e

.name, // The value should be a String, representing the city name

child: Text(e.name),

))

.toList(),

onChanged: (String? value) {

setState(() {

selectedCity =

value; // Update the selected city to the string value

});

}, ), ), ], ), ),

// Save Button Positioned at bottom

Positioned(

bottom: 90, // Adjust the distance from the bottom

left: 16,

right: 16,

child: SizedBox(

width: double.infinity,

child: ElevatedButton(

style: ElevatedButton.styleFrom(

backgroundColor: Colors.teal,

minimumSize: const Size.fromHeight(50),

elevation: 5,

),

onPressed: () {

_addplace();
setState(() {});

print('Save button pressed');

},

child: const Text(

'Save',

style: TextStyle(fontSize: 16, color: Colors.white),

), ), ), ),

// Back Button Positioned at bottom

Positioned(

bottom: 30, // Adjust the distance from the bottom

left: 16,

right: 16,

child: SizedBox(

width: double.infinity,

child: ElevatedButton(

style: ElevatedButton.styleFrom(

backgroundColor: Colors.teal,

minimumSize: const Size.fromHeight(50),

elevation: 5,

),

onPressed: () {

// Add functionality for 'Back'

Navigator.pop(context); // Go back to the previous screen

},

child: const Text(

'Back',

style: TextStyle(fontSize: 16, color: Colors.white),

), ), ), ), ],

),

bottomNavigationBar: BottomNavigationBar(

items: const [

BottomNavigationBarItem(

icon: Icon(Icons.home),

label: 'Home',

),

BottomNavigationBarItem(

icon: Icon(Icons.notifications),

label: 'Notifications',
),

BottomNavigationBarItem(

icon: Icon(Icons.person),

label: 'Profile',

),

BottomNavigationBarItem(

icon: Icon(Icons.settings),

label: 'Settings',

),

],

currentIndex: 1,

selectedItemColor: Colors.teal,

unselectedItemColor: Colors.grey,

showUnselectedLabels: true,

onTap: (index) {

setState(() {});

}, ), ); }}

PlaceDetailScreen

class PlaceDetailScreen extends StatefulWidget {

const PlaceDetailScreen({super.key});

@override

State<PlaceDetailScreen> createState() => _PlaceDetailScreenState();

class _PlaceDetailScreenState extends State<PlaceDetailScreen> {

API api = API();

bool _isLoading = false;

List<Place> placeList = [];

List<City> cityList = [];

String? selectedCity; // To hold the selected city for the dropdown

// Fetching the places based on the selected city

Future<void> _getplaces(String name) async {

if (name.isEmpty) {

ScaffoldMessenger.of(context).showSnackBar(

SnackBar(content: Text('Please Pass a city name')),


);

return;

setState(() {

_isLoading = true;

});

try {

var response = await api.getAllplaces(name);

if (response.statusCode == 200) {

List<dynamic> placemap = json.decode(response.body);

placeList = placemap.map((e) => Place.fromMap(e)).toList();

ScaffoldMessenger.of(context).showSnackBar(

SnackBar(content: Text('Place fetched successfully')),

);

} else if (response.statusCode == 404) {

placeList = [];

ScaffoldMessenger.of(context).showSnackBar(

SnackBar(content: Text('No places found for the specified city')),

);

} else {

placeList = [];

ScaffoldMessenger.of(context).showSnackBar(

SnackBar(content: Text('Failed to fetch places')),

);

} catch (e) {

ScaffoldMessenger.of(context).showSnackBar(

SnackBar(content: Text('Error: $e')),

);

} finally {

setState(() {

_isLoading = false;

});

} }
Future<void> _deleteplace(String placename, String cityname) async {

if (placename.isEmpty || cityname.isEmpty) {

ScaffoldMessenger.of(context).showSnackBar(

SnackBar(content: Text('Please Pass a city name and placename')),

);

return;

setState(() {

_isLoading = true;

});

try {

// Call the API method to delete the city

bool success = await api.deleteplace(placename, cityname);

if (success) {

// Show success message

ScaffoldMessenger.of(context).showSnackBar(

SnackBar(content: Text('Place deleted successfully')),

);

} else {

ScaffoldMessenger.of(context).showSnackBar(

SnackBar(content: Text('Failed to Delete Place')),

);

} catch (e) {

ScaffoldMessenger.of(context).showSnackBar(

SnackBar(content: Text('Error: $e')),

);

} finally {

setState(() {

_isLoading = false;

});

} }

// Fetching cities from the API


Future<void> _getCities() async {

setState(() {

_isLoading = true;

});

try {

var response = await api.getAllCities();

if (response.statusCode == 200) {

List<dynamic> mapList = jsonDecode(response.body);

cityList = mapList.map((e) => City.fromMap(e)).toList();

// Set the first city as the selected city by default

selectedCity = cityList.isNotEmpty ? cityList[0].name : null;

// Fetch places for the default selected city

if (selectedCity != null) {

_getplaces(selectedCity!);

ScaffoldMessenger.of(context).showSnackBar(

SnackBar(content: Text('Cities fetched successfully')),

);

} else {

ScaffoldMessenger.of(context).showSnackBar(

SnackBar(content: Text('Failed to fetch cities')),

);

} catch (e) {

ScaffoldMessenger.of(context).showSnackBar(

SnackBar(content: Text('Error: $e')),

);

} finally {

setState(() {

_isLoading = false;

});

} }
@override

void initState() {

super.initState();

_getCities(); // Fetch the cities when the screen loads

@override

Widget build(BuildContext context) {

return Scaffold(

appBar: PreferredSize(

preferredSize: const Size.fromHeight(150),

child: AppBar(

automaticallyImplyLeading: false,

flexibleSpace: Container(

decoration: BoxDecoration(

gradient: LinearGradient(

colors: [Colors.teal.shade700, Colors.teal.shade400],

begin: Alignment.topLeft,

end: Alignment.bottomRight,

), ),

child: Center(

child: Column(

mainAxisAlignment: MainAxisAlignment.center,

children: [

const Text(

"Place",

style: TextStyle(

color: Colors.white,

fontSize: 22,

fontWeight: FontWeight.bold,

), ),

const SizedBox(height: 10),

Text(

"Set up and manage Places",

textAlign: TextAlign.center,

style: TextStyle(

color: Colors.grey[200],

fontSize: 16,

fontWeight: FontWeight.normal,
), ), ], ), ), ), ),

),

floatingActionButton: FloatingActionButton(

backgroundColor: Colors.teal,

onPressed: () async {

Navigator.push(

context,

MaterialPageRoute(builder: (context) => AddPLace()),

);

},

child: const Text(

'+',

style: TextStyle(

fontSize: 30,

color: Colors.white,

), ), ),

body: Stack(

children: [

Padding(

padding: const EdgeInsets.all(8.0),

child: Column(

children: [

// Dropdown for selecting a city

Container(

decoration: BoxDecoration(

borderRadius: BorderRadius.circular(12),

border: Border.all(

color: Colors.black, // Set the border color

),

color: Colors.white, // Set the background color

),

padding: EdgeInsets.symmetric(

horizontal: 10,

vertical: 5), // Add padding inside the container

child: DropdownButton<String>(

value: selectedCity,

hint: Text("Select City",

style: TextStyle(color: Colors.black)),


onChanged: (newValue) {

setState(() {

selectedCity = newValue;

});

if (selectedCity != null) {

_getplaces(

selectedCity!); // Fetch places for selected city

},

isExpanded:

true, // Make the dropdown expand to fit the container width

items: cityList.map((city) {

return DropdownMenuItem<String>(

value: city.name,

child: Text(

city.name,

style:

TextStyle(color: Colors.black), // Set text color

),

);

}).toList(),

),

),

// Show loading indicator while fetching data

if (_isLoading)

const Center(child: CircularProgressIndicator()),

// Display the list of places

Expanded(

child: placeList.length > 0

? ListView.builder(

itemCount: placeList.length,

itemBuilder: (context, index) {

Place place = placeList[index];

return Card(

margin: const EdgeInsets.all(8.0),

child: Padding(

padding: const EdgeInsets.all(16.0),


child: Row(

crossAxisAlignment:

CrossAxisAlignment.start,

children: [

Column(

crossAxisAlignment:

CrossAxisAlignment.start,

children: [

Text(

'Place ID: ${place.id} \nPlace Name: ${place.name}',

style: TextStyle(

fontSize: 16,

fontWeight: FontWeight.bold,

), ),

SizedBox(height: 8),

], ),

SizedBox(

width: 50,

),

IconButton(

icon: const Icon(Icons.delete,

color: Colors.teal),

onPressed: () {

showDialog(

context: context,

builder: (BuildContext context) {

return AlertDialog(

title:

const Text("Delete place"),

content: const Text(

"Are you sure you want to Delete Place ?",

),

actions: [

TextButton(

onPressed: () {

Navigator.pop(context);

},

child: const Text("Cancel"), ),


TextButton(

onPressed: () {

_deleteplace(place.name,

selectedCity!);

setState(() {

_getplaces(

selectedCity!);

});

Navigator.pop(context);

},

child: const Text(

"Delete",

style: TextStyle(

color: Colors.red),

), ), ], ); }, ); }, ), ], ), ),

); },

: Center(

child: Text('No Place Found'),

)), ], ),

),

Positioned(

bottom: 30,

left: 16,

right: 16,

child: SizedBox(

width: double.infinity,

child: ElevatedButton(

style: ElevatedButton.styleFrom(

backgroundColor: Colors.teal,

minimumSize: const Size.fromHeight(50),

elevation: 5,

),

onPressed: () {

Navigator.pop(context);

},

child: const Text( 'Back',style: TextStyle(fontSize: 16, color: Colors.white),), ), ), ), ],

),

You might also like