🎮cubit - class - api - create
Last updated
Last updated
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_lessons_in_the_evening/grocery_store/cubit/grocery_cubit.dart';
import 'package:flutter_lessons_in_the_evening/grocery_store/ui/add_scree.dart';
import 'package:flutter_lessons_in_the_evening/grocery_store/widgets/loading_widget.dart';
import '../model/grocery_model.dart';
class MainScreen extends StatefulWidget {
const MainScreen({super.key});
@override
State<MainScreen> createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
@override
void initState() {
// TODO: implement initState
super.initState();
context.read<GroceryCubit>().getAllCategory();
}
void deleteCategory({required String id}) {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text('Вы действительно хотите удалить'),
actions: [
TextButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('NO'),
),
TextButton(
onPressed: () {
context.read<GroceryCubit>().deleteCategory(id: id);
Navigator.pop(context);
},
child: Text('Yes'),
),
],
);
},
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Find products'),
),
body: SingleChildScrollView(
child: Column(
children: [
TextField(),
BlocBuilder<GroceryCubit, GroceryState>(
builder: (context, state) {
return switch (state) {
GroceryInitial() => Container(),
GroceryLoading() => GridView.builder(
shrinkWrap: true,
itemCount: 10,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
childAspectRatio: 0.6,
),
itemBuilder: (context, index) {
return LoadingWidget();
},
),
GroceryError(error: String error) => Center(
child: Text(error),
),
GrocerySuccess(
categoryData: List<GroceryModel> data,
) =>
data.isEmpty
? Center(
child: Text('Нету данных'),
)
: GridView.builder(
shrinkWrap: true,
itemCount: data.length,
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
childAspectRatio: 0.6,
),
itemBuilder: (context, index) {
final db = data[index];
final color = int.tryParse(db.color);
return Container(
decoration: BoxDecoration(
color: Color(color!),
),
child: Column(
children: [
Image.network(db.image),
Text(db.name),
ElevatedButton(
onPressed: () {
deleteCategory(id: db.id!);
},
child: Text('Удалить'),
),
],
),
);
},
),
};
},
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => AddScree()),
);
},
child: Icon(Icons.add),
),
);
}
}import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_lessons_in_the_evening/grocery_store/cubit/grocery_cubit.dart';
import 'package:flutter_lessons_in_the_evening/grocery_store/model/grocery_model.dart';
import 'package:flutter_lessons_in_the_evening/grocery_store/widgets/text_form_field_widget.dart';
class AddScree extends StatefulWidget {
const AddScree({super.key});
@override
State<AddScree> createState() => _AddScreeState();
}
class _AddScreeState extends State<AddScree> {
TextEditingController imageController = TextEditingController();
TextEditingController nameController = TextEditingController();
final _formKey = GlobalKey<FormState>();
int _selectedColor = 0;
List<int> colors = [
0xFFF44336, // Красный (Red)
0xFFE91E63, // Розовый (Pink)
0xFF9C27B0, // Фиолетовый (Purple)
0xFF673AB7, // Глубокий фиолетовый (Deep Purple)
0xFF3F51B5, // Индиго (Indigo)
0xFF2196F3, // Синий (Blue)
0xFF03A9F4, // Светло-синий (Light Blue)
0xFF00BCD4, // Циан (Cyan)
0xFF009688, // Бирюзовый (Teal)
0xFF4CAF50, // Зеленый (Green)
0xFF8BC34A, // Лайм (Light Green)
0xFFFFEB3B, // Желтый (Yellow)
0xFFFFC107, // Янтарный (Amber)
0xFFFF9800, // Оранжевый (Orange)
0xFF795548, // Коричневый (Brown)
];
@override
void dispose() {
// TODO: implement dispose
super.dispose();
imageController.dispose();
nameController.dispose();
}
void _saveCategory() {
if (_formKey.currentState!.validate()) {
context.read<GroceryCubit>().saveCategory(
groceryModel: GroceryModel(
id: '',
createdAt: DateTime.now().toString(),
name: nameController.text,
image: imageController.text,
color: colors[_selectedColor].toString(),
),
);
Navigator.pop(context);
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar(
backgroundColor: Colors.white,
),
body: Padding(
padding: const EdgeInsets.symmetric(horizontal: 15),
child: Form(
key: _formKey,
child: Column(
spacing: 20,
children: [
TextFormFieldWidget(
controller: imageController,
hintText: 'Вставьте картину',
validator: (value) {
if (value!.isEmpty) {
return 'Картина не может быть пустым';
}
return null;
},
),
TextFormFieldWidget(
controller: nameController,
hintText: 'Название',
validator: (value) {
if (value!.isEmpty) {
return 'Название не может быть пустым';
}
return null;
},
),
GridView.builder(
shrinkWrap: true,
itemCount: colors.length,
physics: NeverScrollableScrollPhysics(),
gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 7,
mainAxisSpacing: 10,
crossAxisSpacing: 10,
),
itemBuilder: (context, index) {
return GestureDetector(
onTap: () {
setState(() {
_selectedColor = index;
});
},
child: CircleAvatar(
radius: 30,
backgroundColor: _selectedColor == index
? Colors.black
: Colors.white,
child: CircleAvatar(
backgroundColor: Color(colors[index]),
),
),
);
},
),
BlocBuilder<GroceryCubit, GroceryState>(
builder: (context, state) {
if (state is GroceryError) {
return Text(state.error);
}
return ElevatedButton(
style: ElevatedButton.styleFrom(
minimumSize: Size(double.infinity, 45),
),
onPressed: () {
_saveCategory();
},
child: state is GroceryLoading
? CircularProgressIndicator()
: Text('Добавить'),
);
},
),
],
),
),
),
);
}
}import 'package:dio/dio.dart';
import 'package:flutter_lessons_in_the_evening/grocery_store/model/grocery_model.dart';
abstract class GroceryRepository {
Future<List<GroceryModel>> getAllCategory();
Future<void> saveCategory({required GroceryModel groceryModel});
Future<void> deleteCategory({required String id});
}
class GroceryRepositoryImpl extends GroceryRepository {
final Dio _dio;
GroceryRepositoryImpl({required Dio dio}) : _dio = dio;
@override
Future<List<GroceryModel>> getAllCategory() async {
try {
final response = await _dio.get(
'https://69987a2cd66520f95f17aeab.mockapi.io/category',
);
if (response.statusCode == 200) {
List<dynamic> data = response.data;
return data
.map((json) => GroceryModel.fromJson(json))
.toList();
} else {
throw Exception('ошибка сервера');
}
} on DioException catch (e) {
throw Exception('ошибка сети $e');
} catch (e) {
throw Exception('неизвестная ошибка $e');
}
}
@override
Future<void> saveCategory({required GroceryModel groceryModel}) async{
try {
await _dio.post('https://69987a2cd66520f95f17aeab.mockapi.io/category', data: groceryModel.toJson());
} catch(e){
throw Exception('Ошибка при сохранение $e');
}
}
@override
Future<void> deleteCategory({required String id}) async{
try{
await _dio.delete('https://69987a2cd66520f95f17aeab.mockapi.io/category/$id');
} catch(e){
throw Exception('Ошибка при удаление $e');
}
}
}class GroceryModel {
final String? id;
final String createdAt;
final String name;
final String image;
final String color;
GroceryModel({
this.id,
required this.createdAt,
required this.name,
required this.image,
required this.color,
});
factory GroceryModel.fromJson(Map<String, dynamic> json) {
return GroceryModel(
id: json['id'] ?? '',
createdAt: json['createdAt'] ?? '',
name: json['name'] ?? '',
image: json['image'] ?? '',
color: json['color'] ?? '',
);
}
Map<String, dynamic> toJson() => {
'createdAt': createdAt.toString(),
'name': name,
'image': image,
'color': color,
};
}import 'package:bloc/bloc.dart';
import 'package:equatable/equatable.dart';
import 'package:flutter_lessons_in_the_evening/grocery_store/model/grocery_model.dart';
import 'package:flutter_lessons_in_the_evening/grocery_store/repository/grocery_repository.dart';
part 'grocery_state.dart';
class GroceryCubit extends Cubit<GroceryState> {
final GroceryRepository _groceryRepository;
GroceryCubit({required GroceryRepository groceryRepository})
: _groceryRepository = groceryRepository,
super(GroceryInitial());
void getAllCategory() async {
emit(GroceryLoading());
try {
final newData = await _groceryRepository.getAllCategory();
emit(GrocerySuccess(categoryData: newData));
} catch (e) {
emit(GroceryError(error: '$e'));
}
}
void saveCategory({required GroceryModel groceryModel}) async {
emit(GroceryLoading());
try {
await _groceryRepository.saveCategory(
groceryModel: groceryModel,
);
getAllCategory();
} catch (e) {
emit(GroceryError(error: '$e'));
print('$e');
}
}
void deleteCategory({required String id}) async {
emit(GroceryLoading());
try {
await _groceryRepository.deleteCategory(id: id);
getAllCategory();
} catch (e) {
emit(GroceryError(error: '$e'));
}
}
}part of 'grocery_cubit.dart';
sealed class GroceryState extends Equatable {
const GroceryState();
@override
List<Object> get props => [];
}
final class GroceryInitial extends GroceryState {
}
final class GroceryLoading extends GroceryState{}
final class GrocerySuccess extends GroceryState{
final List<GroceryModel> categoryData;
const GrocerySuccess({required this.categoryData});
@override
List<Object> get props => [categoryData];
}
final class GroceryError extends GroceryState{
final String error;
const GroceryError({required this.error});
@override
List<Object> get props => [error];
}