feat:更新api模块
This commit is contained in:
@@ -56,6 +56,74 @@ class _HomePage extends State<HomePage> {
|
||||
|
||||
List<Widget> get tabPages => navItems.map((item) => item.page).toList();
|
||||
|
||||
// 显示底部弹窗
|
||||
void _showBottomSheet() {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.vertical(
|
||||
top: Radius.circular(16),
|
||||
),
|
||||
),
|
||||
builder: (context) => Container(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Text(
|
||||
'请选择操作',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
ListTile(
|
||||
leading: Icon(Icons.book, color: Theme.of(context).primaryColor),
|
||||
title: const Text('新增菜谱'),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
_handleAddRecipe();
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
leading: Icon(Icons.note_add, color: Theme.of(context).primaryColor),
|
||||
title: const Text('新增记录'),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
Navigator.pushNamed(context, "/recordForm");
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
leading: Icon(Icons.group, color: Theme.of(context).primaryColor),
|
||||
title: const Text('发布朋友圈'),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
_handleAddRecord();
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// 处理添加菜谱
|
||||
void _handleAddRecipe() {
|
||||
// 这里添加跳转或处理添加菜谱的逻辑
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('添加菜谱功能')),
|
||||
);
|
||||
}
|
||||
|
||||
// 处理添加记录
|
||||
void _handleAddRecord() {
|
||||
// 这里添加跳转或处理添加记录的逻辑
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text('添加记录功能')),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
@@ -77,6 +145,13 @@ class _HomePage extends State<HomePage> {
|
||||
backgroundColor: Color(0xFFF5F5F5),
|
||||
drawer: const SettingsDrawer(),
|
||||
body: tabPages[_currentIndex],
|
||||
floatingActionButton: FloatingActionButton(
|
||||
backgroundColor: Theme.of(context).primaryColor,
|
||||
onPressed: _showBottomSheet,
|
||||
shape: const CircleBorder(),
|
||||
child: const Icon(Icons.add, color: Colors.white, size: 30),
|
||||
),
|
||||
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
|
||||
bottomNavigationBar: NavBar(
|
||||
navItems: bottomNavItems,
|
||||
currentIndex: _currentIndex,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_form_builder/flutter_form_builder.dart';
|
||||
import 'package:food_hub_app/api/session.dart';
|
||||
import 'package:food_hub_app/apis/session.dart';
|
||||
import 'package:food_hub_app/models/session.dart';
|
||||
import 'package:food_hub_app/utils/sp_util.dart';
|
||||
import 'package:food_hub_app/widgets/common/index.dart';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import 'package:easy_refresh/easy_refresh.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:food_hub_app/api/moment.dart';
|
||||
import 'package:food_hub_app/apis/moment.dart';
|
||||
import 'package:food_hub_app/models/moment.dart';
|
||||
import 'package:food_hub_app/widgets/moment/card.dart';
|
||||
import 'package:tdesign_flutter/tdesign_flutter.dart';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:food_hub_app/api/recipe.dart';
|
||||
import 'package:food_hub_app/apis/recipe.dart';
|
||||
import 'package:food_hub_app/models/recipe.dart';
|
||||
import 'package:food_hub_app/widgets/common/index.dart';
|
||||
|
||||
|
||||
@@ -1,205 +1,194 @@
|
||||
import 'dart:async';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_form_builder/flutter_form_builder.dart';
|
||||
import 'package:food_hub_app/utils/index.dart';
|
||||
import 'package:food_hub_app/widgets/common/index.dart';
|
||||
import 'package:food_hub_app/widgets/common/form.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:tdesign_flutter/tdesign_flutter.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'dart:io';
|
||||
|
||||
class RecordFormPage extends StatefulWidget {
|
||||
const RecordFormPage({super.key});
|
||||
|
||||
@override
|
||||
State<RecordFormPage> createState() => _RecordFormPage();
|
||||
State<RecordFormPage> createState() => _RecordFormPageState();
|
||||
}
|
||||
|
||||
class _RecordFormPage extends State<RecordFormPage> {
|
||||
class _RecordFormPageState extends State<RecordFormPage> {
|
||||
final _formKey = GlobalKey<FormBuilderState>();
|
||||
|
||||
List<TextEditingController> _controller = [];
|
||||
FormController _formController = FormController();
|
||||
|
||||
String _selected_1 = '';
|
||||
String _selected_2 = '';
|
||||
String? _initLocalData;
|
||||
final _focusNode = FocusNode();
|
||||
static const String _nameField = 'name';
|
||||
static const String _dateField = 'date';
|
||||
|
||||
final ImagePicker _picker = ImagePicker();
|
||||
XFile? _selectedImage;
|
||||
|
||||
/// 整个表单存放的数据
|
||||
Map<String, dynamic> _formData = {"name": '', "date": '', "photo": ''};
|
||||
|
||||
/// 定义整个校验规则
|
||||
final Map<String, TDFormValidation> _validationRules = {
|
||||
'name': TDFormValidation(
|
||||
validate: (value) => value == null || value.isEmpty ? 'empty' : null,
|
||||
errorMessage: '输入不能为空',
|
||||
type: TDFormItemType.input,
|
||||
),
|
||||
"birth": TDFormValidation(
|
||||
validate: (value) => value == null || value.isEmpty ? 'empty' : null,
|
||||
errorMessage: '不能为空',
|
||||
type: TDFormItemType.dateTimePicker,
|
||||
),
|
||||
"photo": TDFormValidation(
|
||||
validate: (value) => value == null || value.isEmpty ? 'empty' : null,
|
||||
errorMessage: '不能为空',
|
||||
type: TDFormItemType.upLoadImg,
|
||||
),
|
||||
};
|
||||
|
||||
List<TDUploadFile> files = [];
|
||||
|
||||
List<TDUploadFile> _onValueChanged(
|
||||
List<TDUploadFile> fileList,
|
||||
List<TDUploadFile> value,
|
||||
TDUploadType event,
|
||||
) {
|
||||
switch (event) {
|
||||
case TDUploadType.add:
|
||||
fileList.addAll(value);
|
||||
break;
|
||||
case TDUploadType.remove:
|
||||
fileList.removeWhere((element) => element.key == value[0].key);
|
||||
break;
|
||||
case TDUploadType.replace:
|
||||
final firstReplaceFile = value.first;
|
||||
final index = fileList.indexWhere(
|
||||
(file) => file.key == firstReplaceFile.key,
|
||||
);
|
||||
if (index != -1) {
|
||||
fileList[index] = firstReplaceFile;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return fileList;
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
File? imageUrl; // 改为单张图片变量
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_focusNode.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _confirmClick(BuildContext context) {
|
||||
if (_formKey.currentState?.saveAndValidate() ?? false) {
|
||||
// showSuccessToast("新增记录成功");
|
||||
print(_formData);
|
||||
} else {
|
||||
TDMessage.showMessage(
|
||||
context: context,
|
||||
visible: true,
|
||||
icon: true,
|
||||
content: "请先输入信息",
|
||||
theme: MessageTheme.error,
|
||||
duration: 3000,
|
||||
);
|
||||
}
|
||||
}
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
|
||||
TDFormItem buildNameItem() {
|
||||
return TDFormItem(
|
||||
label: '菜谱名称',
|
||||
name: 'name',
|
||||
type: TDFormItemType.input,
|
||||
labelWidth: 82.0,
|
||||
showErrorMessage: true,
|
||||
requiredMark: true,
|
||||
child: TDInput(
|
||||
leftContentSpace: 0,
|
||||
inputDecoration: InputDecoration(
|
||||
hintText: "请输入菜谱名称",
|
||||
border: InputBorder.none,
|
||||
hintStyle: TextStyle(color: TDTheme.of(context).grayColor6),
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('新增记录', style: TextStyle(color: Colors.white)),
|
||||
backgroundColor: theme.primaryColor,
|
||||
leading: IconButton(
|
||||
icon: const Icon(Icons.arrow_back, color: Colors.white),
|
||||
onPressed: () => Navigator.pop(context),
|
||||
),
|
||||
),
|
||||
backgroundColor: const Color(0xFFF5F5F5),
|
||||
body: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(5),
|
||||
child: Card(
|
||||
elevation: 0,
|
||||
color: Colors.white,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: _buildFormBuilder(),
|
||||
),
|
||||
),
|
||||
),
|
||||
backgroundColor: Colors.white,
|
||||
additionInfoColor: TDTheme.of(context).errorColor6,
|
||||
showBottomDivider: false,
|
||||
onChanged: (value) {
|
||||
_formData['name'] = value;
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
TDFormItem buildDateItem() {
|
||||
return TDFormItem(
|
||||
label: '完成时间',
|
||||
name: 'date',
|
||||
labelWidth: 82.0,
|
||||
type: TDFormItemType.dateTimePicker,
|
||||
contentAlign: TextAlign.left,
|
||||
tipAlign: TextAlign.left,
|
||||
hintText: '请选择完成时间',
|
||||
select: _formData['date'],
|
||||
selectFn: (BuildContext context) {
|
||||
DateTime now = DateTime.now();
|
||||
TDPicker.showDatePicker(
|
||||
context,
|
||||
title: '选择时间',
|
||||
onConfirm: (selected) {
|
||||
setState(() {
|
||||
_formData['date'] = parseDatePickerSelected(selected);
|
||||
});
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
dateStart: [2000, 01, 01],
|
||||
dateEnd: [2100, 12, 31],
|
||||
initialDate: [now.year, now.month, now.day],
|
||||
);
|
||||
Widget _buildFormBuilder() {
|
||||
return FormBuilder(
|
||||
key: _formKey,
|
||||
autovalidateMode: AutovalidateMode.onUserInteraction,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
buildFormLabel('菜谱名称', required: true),
|
||||
const SizedBox(height: 8),
|
||||
_buildNameTextField(),
|
||||
const SizedBox(height: 10),
|
||||
|
||||
buildFormLabel('完成时间', required: true),
|
||||
const SizedBox(height: 8),
|
||||
_buildDateTextField(),
|
||||
const SizedBox(height: 10),
|
||||
|
||||
buildFormLabel('上传图片', required: true),
|
||||
const SizedBox(height: 10),
|
||||
_buildImageUploadArea(),
|
||||
|
||||
const SizedBox(height: 10),
|
||||
buildFormButtonGroup(context: context, onConfirm: () => _submitForm),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// 菜谱名称输入框
|
||||
Widget _buildNameTextField() {
|
||||
return FormBuilderTextField(
|
||||
name: _nameField,
|
||||
focusNode: _focusNode,
|
||||
decoration: buildInputDecoration(context: context, hintText: '请输入菜谱名称'),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return '请输入菜谱名称';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
TDFormItem buildImageItem() {
|
||||
return TDFormItem(
|
||||
label: '上传图片',
|
||||
name: 'photo',
|
||||
labelWidth: 82.0,
|
||||
type: TDFormItemType.upLoadImg,
|
||||
child: TDUpload(
|
||||
files: files,
|
||||
onError: print,
|
||||
onValidate: print,
|
||||
onChange: ((imgList, type) {
|
||||
files = _onValueChanged(files ?? [], imgList, type);
|
||||
List imgs = files.map((e) => e.remotePath ?? e.assetPath).toList();
|
||||
setState(() {});
|
||||
}),
|
||||
/// 完成时间选择框
|
||||
Widget _buildDateTextField() {
|
||||
return FormBuilderTextField(
|
||||
name: _dateField,
|
||||
readOnly: true,
|
||||
decoration: buildInputDecoration(
|
||||
context: context,
|
||||
hintText: '请选择完成时间',
|
||||
prefixIcon: const Icon(
|
||||
Icons.calendar_month,
|
||||
size: 20,
|
||||
color: Color(0xFF86909C),
|
||||
),
|
||||
),
|
||||
onTap: () => _onSelectDate(),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return '请选择完成时间';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildFormBtnGroup() {
|
||||
/// 图片上传区域(预览+上传按钮)
|
||||
Widget _buildImageUploadArea() {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (imageUrl != null)
|
||||
_buildImagePreviewItem()
|
||||
else
|
||||
_buildImageUploadButton(),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildImagePreviewItem() {
|
||||
return Container(
|
||||
decoration: BoxDecoration(color: TDTheme.of(context).whiteColor1),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: Row(
|
||||
decoration: BoxDecoration(borderRadius: BorderRadius.circular(8)),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: Stack(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TDButton(
|
||||
text: '取消',
|
||||
type: TDButtonType.fill,
|
||||
theme: TDButtonTheme.light,
|
||||
shape: TDButtonShape.rectangle,
|
||||
onTap: () => Navigator.pop(context),
|
||||
GestureDetector(
|
||||
onTap: () => _showImagePreview(),
|
||||
child: Image(
|
||||
image: FileImage(imageUrl!),
|
||||
width: 120,
|
||||
height: 120,
|
||||
fit: BoxFit.cover,
|
||||
loadingBuilder: (context, child, loadingProgress) {
|
||||
if (loadingProgress == null) return child;
|
||||
return Container(
|
||||
width: 120,
|
||||
height: 120,
|
||||
color: Colors.grey[100],
|
||||
child: const Center(
|
||||
child: CircularProgressIndicator(strokeWidth: 2),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(width: 20),
|
||||
Expanded(
|
||||
child: TDButton(
|
||||
text: '提交',
|
||||
type: TDButtonType.fill,
|
||||
theme: TDButtonTheme.primary,
|
||||
shape: TDButtonShape.rectangle,
|
||||
onTap: () => _confirmClick(context),
|
||||
|
||||
Positioned(
|
||||
top: 6,
|
||||
right: 6,
|
||||
child: GestureDetector(
|
||||
onTap: _removeImage,
|
||||
child: Container(
|
||||
width: 24,
|
||||
height: 24,
|
||||
decoration: const BoxDecoration(
|
||||
color: Colors.red,
|
||||
shape: BoxShape.circle,
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.black26,
|
||||
blurRadius: 2,
|
||||
spreadRadius: 0,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: const Icon(Icons.close, color: Colors.white, size: 16),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
@@ -208,36 +197,137 @@ class _RecordFormPage extends State<RecordFormPage> {
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('新增记录', style: TextStyle(color: Colors.white)),
|
||||
backgroundColor: Theme.of(context).primaryColor,
|
||||
leading: IconButton(
|
||||
icon: Icon(Icons.arrow_back, color: Colors.white),
|
||||
onPressed: () => Navigator.pop(context)
|
||||
),
|
||||
),
|
||||
backgroundColor: Color(0xFFF5F5F5),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(10),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
child: SingleChildScrollView(
|
||||
child: TDForm(
|
||||
formController: _formController,
|
||||
data: _formData,
|
||||
rules: _validationRules,
|
||||
formContentAlign: TextAlign.left,
|
||||
formShowErrorMessage: true,
|
||||
onSubmit: () => {},
|
||||
items: [buildNameItem(), buildDateItem(), buildImageItem()],
|
||||
btnGroup: [buildFormBtnGroup()],
|
||||
void _showImagePreview() {
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierColor: Colors.black87, // 半透明黑色背景
|
||||
builder:
|
||||
(context) => Dialog(
|
||||
backgroundColor: Colors.transparent,
|
||||
elevation: 0,
|
||||
insetPadding: const EdgeInsets.all(16),
|
||||
child: GestureDetector(
|
||||
onTap: () => Navigator.pop(context), // 点击空白处关闭
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
// 预览图添加轻微阴影
|
||||
boxShadow: [BoxShadow(color: Colors.black38, blurRadius: 10)],
|
||||
),
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
child: Image.file(
|
||||
imageUrl!,
|
||||
fit: BoxFit.contain, // 保持图片比例
|
||||
height: MediaQuery.of(context).size.height * 0.7, // 限制最大高度
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// 图片上传按钮
|
||||
Widget _buildImageUploadButton() {
|
||||
return InkWell(
|
||||
onTap: _pickImage,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: Container(
|
||||
width: 96,
|
||||
height: 96,
|
||||
decoration: BoxDecoration(
|
||||
color: const Color(0xFFF2F3F5),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
border: Border.all(color: const Color(0xFFDCDFE6), width: 1),
|
||||
),
|
||||
child: const Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(Icons.add, color: Color(0xFF86909C), size: 24),
|
||||
SizedBox(height: 6),
|
||||
Text(
|
||||
'添加图片',
|
||||
style: TextStyle(color: Color(0xFF86909C), fontSize: 13),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// 选择日期
|
||||
Future<void> _onSelectDate() async {
|
||||
final DateTime? picked = await showDatePicker(
|
||||
context: context,
|
||||
initialDate: DateTime.now(),
|
||||
firstDate: DateTime(2000),
|
||||
lastDate: DateTime(2100),
|
||||
builder:
|
||||
(context, child) => Theme(
|
||||
data: ThemeData.light().copyWith(
|
||||
primaryColor: Theme.of(context).primaryColor,
|
||||
colorScheme: ColorScheme.light(
|
||||
primary: Theme.of(context).primaryColor,
|
||||
),
|
||||
buttonTheme: const ButtonThemeData(
|
||||
textTheme: ButtonTextTheme.primary,
|
||||
),
|
||||
),
|
||||
child: child!,
|
||||
),
|
||||
);
|
||||
|
||||
if (picked != null) {
|
||||
_formKey.currentState?.fields[_dateField]?.didChange(
|
||||
DateFormat('yyyy-MM-dd').format(picked),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/// 选择图片(限制单张)
|
||||
Future<void> _pickImage() async {
|
||||
final XFile? image = await _picker.pickImage(source: ImageSource.gallery);
|
||||
if (image != null) {
|
||||
setState(() {
|
||||
imageUrl = File(image.path); // 直接覆盖现有图片
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// 移除图片
|
||||
void _removeImage() {
|
||||
setState(() {
|
||||
imageUrl = null;
|
||||
});
|
||||
}
|
||||
|
||||
/// 提交表单
|
||||
void _submitForm() {
|
||||
if (_formKey.currentState?.saveAndValidate() ?? false) {
|
||||
if (imageUrl == null) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('请上传图片'),
|
||||
backgroundColor: Colors.red,
|
||||
behavior: SnackBarBehavior.floating,
|
||||
),
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
final formData = {
|
||||
..._formKey.currentState!.value,
|
||||
'imageUrl': imageUrl?.path, // 单张图片路径
|
||||
};
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('提交成功!'),
|
||||
behavior: SnackBarBehavior.floating,
|
||||
),
|
||||
);
|
||||
print('表单数据: $formData');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:food_hub_app/api/stats.dart';
|
||||
import 'package:food_hub_app/apis/stats.dart';
|
||||
import 'package:food_hub_app/models/stats.dart';
|
||||
import 'package:food_hub_app/widgets/common/chart.dart';
|
||||
import 'package:food_hub_app/widgets/stats/card.dart';
|
||||
|
||||
Reference in New Issue
Block a user