update processing,customer and staff
This commit is contained in:
@@ -24,7 +24,7 @@ class DeliveryAddressDataProvider {
|
||||
|
||||
Future<void> selectDefalutDeliveryAddress(
|
||||
DeliveryAddress deliveryAddress) async {
|
||||
return await requestAPI("/delivery_address/defalut", "PUT",
|
||||
payload: deliveryAddress.toMap(), token: await getToken());
|
||||
return await requestAPI("/delivery_address/default", "PUT",
|
||||
payload: deliveryAddress.toMapForDefault(), token: await getToken());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,6 +73,8 @@ const privilege_invoice = "inv";
|
||||
const privilege_processing = "pr";
|
||||
const privilege_receiving = "rc";
|
||||
const privilege_pickup = "pku";
|
||||
const privilege_collect ="col";
|
||||
const privilege_report ="rpt";
|
||||
|
||||
// Pickup types
|
||||
const shipment_local_pickup = "Local pickup";
|
||||
|
||||
@@ -91,7 +91,7 @@ class Package {
|
||||
userName: map['user_name'],
|
||||
phoneNumber: map['phone_number'],
|
||||
remark: map['remark'],
|
||||
desc: map['desc'],
|
||||
desc: map['desc'] ?? "",
|
||||
status: map['status'],
|
||||
senderFCSID: map['sender_fcs_id'],
|
||||
senderName: map['sender_name'],
|
||||
@@ -134,11 +134,12 @@ class Package {
|
||||
}
|
||||
|
||||
bool isChangedForEditProcessing(Package package) {
|
||||
return package.trackingID != this.trackingID ||
|
||||
package.fcsID != this.fcsID ||
|
||||
return package.fcsID != this.fcsID ||
|
||||
package.senderFCSID != this.senderFCSID ||
|
||||
package.market != this.market ||
|
||||
package.desc != this.desc ||
|
||||
package.remark != this.remark;
|
||||
package.remark != this.remark ||
|
||||
package.photoUrls != this.photoUrls;
|
||||
}
|
||||
|
||||
@override
|
||||
|
||||
@@ -29,7 +29,7 @@ class DeliveryAddress {
|
||||
city: map['city'],
|
||||
state: map['state'],
|
||||
phoneNumber: map['phone_number'],
|
||||
isDefault: map['is_defalut'] ?? false,
|
||||
isDefault: map['is_default'] ?? false,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -46,6 +46,10 @@ class DeliveryAddress {
|
||||
};
|
||||
}
|
||||
|
||||
Map<String, dynamic> toMapForDefault() {
|
||||
return {"id": id};
|
||||
}
|
||||
|
||||
bool isChangedForEdit(DeliveryAddress deliveryAddress) {
|
||||
return deliveryAddress.fullName != this.fullName ||
|
||||
deliveryAddress.phoneNumber != this.phoneNumber ||
|
||||
|
||||
@@ -45,6 +45,10 @@ class Privilege {
|
||||
iconData = MaterialCommunityIcons.inbox_arrow_down;
|
||||
} else if (this.id == privilege_pickup) {
|
||||
iconData = SimpleLineIcons.direction;
|
||||
} else if (this.id == privilege_collect) {
|
||||
iconData = MaterialCommunityIcons.layers;
|
||||
} else if (this.id == privilege_report) {
|
||||
iconData = Feather.file_text;
|
||||
} else {
|
||||
iconData = MaterialCommunityIcons.account_question;
|
||||
}
|
||||
|
||||
@@ -205,7 +205,7 @@ class _CargoTableState extends State<CargoTable> {
|
||||
alignment: Alignment.centerRight,
|
||||
child: InkWell(
|
||||
onTap: () async {
|
||||
String _t = await showDialog(
|
||||
String? _t = await showDialog(
|
||||
context: context,
|
||||
builder: (_) => DialogInput(
|
||||
label: "shipment.cargo.total",
|
||||
|
||||
@@ -853,7 +853,7 @@ class _CartonEditorState extends State<CartonEditor> {
|
||||
carton.deliveryAddress = _carton!.deliveryAddress;
|
||||
|
||||
try {
|
||||
Carton _c = await Navigator.push(
|
||||
Carton? _c = await Navigator.push(
|
||||
context,
|
||||
CupertinoPageRoute(
|
||||
builder: (context) => PackageCartonEditor(
|
||||
|
||||
@@ -38,7 +38,7 @@ class MessageModel extends BaseModel {
|
||||
}
|
||||
|
||||
Future<void> load() async {
|
||||
if (prevSnap == null) return;
|
||||
// if (prevSnap == null) return;
|
||||
Query _query =
|
||||
prevSnap != null ? query.startAfterDocument(prevSnap!) : query;
|
||||
QuerySnapshot snapshot =
|
||||
@@ -62,8 +62,8 @@ class MessageModel extends BaseModel {
|
||||
|
||||
listener = FirebaseFirestore.instance
|
||||
.collection("$user_collection/$userID/$messages_collection")
|
||||
.endBeforeDocument(snap)
|
||||
.orderBy('date', descending: true)
|
||||
.endBeforeDocument(snap)
|
||||
.snapshots(includeMetadataChanges: true)
|
||||
.listen((qs) {
|
||||
qs.docChanges.forEach((c) {
|
||||
|
||||
@@ -141,8 +141,8 @@ class FcsShipmentModel extends BaseModel {
|
||||
.where("pending_invoice_user_count", isGreaterThan: 0)
|
||||
.get(const GetOptions(source: Source.server));
|
||||
fcsShipments = snaps.docs.map((documentSnapshot) {
|
||||
var fcs = FcsShipment.fromMap(
|
||||
documentSnapshot.data as Map<String, dynamic>, documentSnapshot.id);
|
||||
var fcs =
|
||||
FcsShipment.fromMap(documentSnapshot.data(), documentSnapshot.id);
|
||||
return fcs;
|
||||
}).toList();
|
||||
} catch (e) {
|
||||
|
||||
@@ -299,7 +299,7 @@ class _HomePageState extends State<HomePage> {
|
||||
|
||||
final staffBtn = TaskButton(
|
||||
"staff.title",
|
||||
icon: MaterialCommunityIcons.account_tie,
|
||||
icon: MaterialCommunityIcons.account_hard_hat,
|
||||
btnCallback: () => Navigator.of(context).push<void>(CupertinoPageRoute(
|
||||
builder: (context) => StaffList(),
|
||||
)),
|
||||
@@ -335,12 +335,12 @@ class _HomePageState extends State<HomePage> {
|
||||
widgets.add(notiBtn);
|
||||
if (user.joined) {
|
||||
widgets.add(packagesBtn);
|
||||
widgets.add(shipmentBtn);
|
||||
// widgets.add(shipmentBtn);
|
||||
widgets.add(invoicesBtn);
|
||||
|
||||
if (user.hasAdmin() || user.hasSupport()) widgetsFcs.add(rateBtnFcs);
|
||||
if (user.hasPackages()) widgetsFcs.add(packagesBtnFcs);
|
||||
if (user.hasShipment()) widgetsFcs.add(shipmentBtnFcs);
|
||||
// if (user.hasShipment()) widgetsFcs.add(shipmentBtnFcs);
|
||||
if (user.hasShipment()) widgetsFcs.add(pickupBtnFcs);
|
||||
if (user.hasInvoices()) widgetsFcs.add(invoicesBtnFcs);
|
||||
|
||||
|
||||
@@ -222,8 +222,7 @@ class PackageModel extends BaseModel {
|
||||
.where("is_deleted", isEqualTo: false)
|
||||
.get(const GetOptions(source: Source.server));
|
||||
packages = snaps.docs.map((documentSnapshot) {
|
||||
var p = Package.fromMap(
|
||||
documentSnapshot.data as Map<String, dynamic>, documentSnapshot.id);
|
||||
var p = Package.fromMap(documentSnapshot.data(), documentSnapshot.id);
|
||||
return p;
|
||||
}).toList();
|
||||
} catch (e) {
|
||||
|
||||
@@ -65,8 +65,8 @@ class _PackageEditorState extends State<PackageEditor> {
|
||||
}
|
||||
setState(() {
|
||||
selectedMarket = _package!.market ?? "";
|
||||
_descCtl.text = _package!.desc!;
|
||||
_remarkCtl.text = _package!.remark!;
|
||||
_descCtl.text = _package!.desc ?? "";
|
||||
_remarkCtl.text = _package!.remark ?? "";
|
||||
multiImgController.setImageUrls = _package!.photoUrls;
|
||||
});
|
||||
}
|
||||
@@ -180,7 +180,7 @@ class _PackageEditorState extends State<PackageEditor> {
|
||||
List<String?> markets = _markets.map((e) => e.name).toList();
|
||||
markets.insert(0, MANAGE_MARKET);
|
||||
if (!markets.contains(selectedMarket)) {
|
||||
markets.insert(0, selectedMarket!);
|
||||
markets.insert(0, selectedMarket);
|
||||
}
|
||||
|
||||
return Row(
|
||||
@@ -254,13 +254,13 @@ class _PackageEditorState extends State<PackageEditor> {
|
||||
PackageModel packageModel =
|
||||
Provider.of<PackageModel>(context, listen: false);
|
||||
try {
|
||||
_package!.market = selectedMarket!;
|
||||
_package!.market = selectedMarket ?? "";
|
||||
_package!.desc = _descCtl.text;
|
||||
_package!.remark = _remarkCtl.text;
|
||||
_package!.photoFiles = multiImgController.getUpdatedFile;
|
||||
_package!.fcsID = widget.consignee!.fcsID;
|
||||
_package!.fcsID = widget.consignee?.fcsID;
|
||||
_package!.senderFCSID =
|
||||
widget.sender!.fcsID != null ? widget.sender!.fcsID : "";
|
||||
widget.sender?.fcsID != null ? widget.sender?.fcsID : "";
|
||||
|
||||
await packageModel.updateProcessing(_package!,
|
||||
multiImgController.getAddedFile, multiImgController.getDeletedUrl);
|
||||
@@ -276,9 +276,10 @@ class _PackageEditorState extends State<PackageEditor> {
|
||||
}
|
||||
|
||||
isDataChanged() {
|
||||
return selectedMarket != null ||
|
||||
return _package?.trackingID != null ||
|
||||
_descCtl.text != "" ||
|
||||
_remarkCtl.text != "" ||
|
||||
multiImgController.getAddedFile.isNotEmpty;
|
||||
multiImgController.getAddedFile.isNotEmpty ||
|
||||
selectedMarket != null && selectedMarket != "";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,8 @@ class _ProcessingEditEditorState extends State<ProcessingEditEditor> {
|
||||
TextEditingController _descCtl = new TextEditingController();
|
||||
|
||||
Package? _package;
|
||||
User? _user;
|
||||
User? _consignee;
|
||||
User? _sender;
|
||||
bool _isLoading = false;
|
||||
|
||||
@override
|
||||
@@ -45,10 +46,15 @@ class _ProcessingEditEditorState extends State<ProcessingEditEditor> {
|
||||
_descCtl.text = _package!.desc ?? "";
|
||||
_remarkCtl.text = _package!.remark ?? "";
|
||||
multiImgController.setImageUrls = _package!.photoUrls;
|
||||
_user = User(
|
||||
_consignee = User(
|
||||
fcsID: _package!.fcsID ?? "",
|
||||
name: _package!.userName ?? "",
|
||||
phoneNumber: _package!.phoneNumber ?? "");
|
||||
|
||||
_sender = User(
|
||||
fcsID: _package!.senderFCSID ?? "",
|
||||
name: _package!.senderName ?? "",
|
||||
phoneNumber: _package!.senderPhoneNumber ?? "");
|
||||
}
|
||||
|
||||
final DateFormat dateFormat = DateFormat("d MMM yyyy");
|
||||
@@ -62,7 +68,7 @@ class _ProcessingEditEditorState extends State<ProcessingEditEditor> {
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: DisplayText(
|
||||
text: _user!.fcsID,
|
||||
text: _consignee!.fcsID,
|
||||
labelTextKey: "processing.fcs.id",
|
||||
icon: FcsIDIcon(),
|
||||
)),
|
||||
@@ -70,18 +76,18 @@ class _ProcessingEditEditorState extends State<ProcessingEditEditor> {
|
||||
icon: Icon(Icons.search, color: primaryColor),
|
||||
onPressed: () => searchUser(context, onUserSelect: (u) {
|
||||
setState(() {
|
||||
this._user = u;
|
||||
this._consignee = u;
|
||||
});
|
||||
})),
|
||||
],
|
||||
);
|
||||
final namebox = DisplayText(
|
||||
text: _user!.name,
|
||||
labelTextKey: "processing.name",
|
||||
text: _consignee!.name,
|
||||
labelTextKey: "processing.consignee.name",
|
||||
iconData: Icons.person,
|
||||
);
|
||||
final phoneNumberBox = DisplayText(
|
||||
text: _user!.phoneNumber,
|
||||
text: _consignee!.phoneNumber,
|
||||
labelTextKey: "processing.phone",
|
||||
iconData: Icons.phone,
|
||||
);
|
||||
@@ -110,6 +116,59 @@ class _ProcessingEditEditorState extends State<ProcessingEditEditor> {
|
||||
controller: multiImgController,
|
||||
title: "Receipt File",
|
||||
);
|
||||
|
||||
final consigneeBox = Container(
|
||||
child: Column(
|
||||
children: [
|
||||
fcsIDBox,
|
||||
phoneNumberBox,
|
||||
namebox,
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
var shipperIDBox = Row(
|
||||
children: <Widget>[
|
||||
Expanded(
|
||||
child: DisplayText(
|
||||
text: _sender != null ? _sender!.fcsID : "",
|
||||
labelTextKey: "processing.fcs.id",
|
||||
icon: FcsIDIcon(),
|
||||
)),
|
||||
IconButton(
|
||||
icon: Icon(Icons.search, color: primaryColor),
|
||||
onPressed: () => searchUser(context, onUserSelect: (u) {
|
||||
setState(() {
|
||||
this._sender = u;
|
||||
});
|
||||
}, popPage: true)),
|
||||
],
|
||||
);
|
||||
|
||||
final shipperPhoneNumberBox = DisplayText(
|
||||
text: _sender != null ? _sender!.phoneNumber : "",
|
||||
labelTextKey: "processing.phone",
|
||||
maxLines: 2,
|
||||
iconData: Icons.phone,
|
||||
);
|
||||
|
||||
final shipperNamebox = DisplayText(
|
||||
text: _sender != null ? _sender!.name : "",
|
||||
labelTextKey: "processing.shipper.name",
|
||||
maxLines: 2,
|
||||
iconData: Icons.person,
|
||||
);
|
||||
|
||||
final shipperBox = Container(
|
||||
child: Column(
|
||||
children: [
|
||||
shipperIDBox,
|
||||
shipperPhoneNumberBox,
|
||||
shipperNamebox,
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
return LocalProgress(
|
||||
inAsyncCall: _isLoading,
|
||||
child: Scaffold(
|
||||
@@ -141,9 +200,12 @@ class _ProcessingEditEditorState extends State<ProcessingEditEditor> {
|
||||
child: ListView(
|
||||
children: [
|
||||
trackingIdBox,
|
||||
fcsIDBox,
|
||||
namebox,
|
||||
phoneNumberBox,
|
||||
Row(
|
||||
children: [
|
||||
Flexible(child: consigneeBox),
|
||||
Flexible(child: shipperBox)
|
||||
],
|
||||
),
|
||||
marketDropdown(),
|
||||
descBox,
|
||||
remarkBox,
|
||||
@@ -165,11 +227,11 @@ class _ProcessingEditEditorState extends State<ProcessingEditEditor> {
|
||||
List<String?> markets = _markets.map((e) => e.name).toList();
|
||||
markets.insert(0, MANAGE_MARKET);
|
||||
if (!markets.contains(selectedMarket)) {
|
||||
markets.insert(0, selectedMarket!);
|
||||
markets.insert(0, selectedMarket);
|
||||
}
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(left: 5.0, right: 0),
|
||||
padding: const EdgeInsets.only(left: 5.0, right: 0, top: 10),
|
||||
child: Row(
|
||||
children: [
|
||||
Padding(
|
||||
@@ -236,7 +298,7 @@ class _ProcessingEditEditorState extends State<ProcessingEditEditor> {
|
||||
}
|
||||
|
||||
_completeProcessing() async {
|
||||
if (_user!.fcsID == null || _user!.fcsID == "") {
|
||||
if (_consignee!.fcsID == null || _consignee!.fcsID == "") {
|
||||
showMsgDialog(context, "Error", "Expected FCS-ID");
|
||||
return;
|
||||
}
|
||||
@@ -246,10 +308,11 @@ class _ProcessingEditEditorState extends State<ProcessingEditEditor> {
|
||||
PackageModel packageModel =
|
||||
Provider.of<PackageModel>(context, listen: false);
|
||||
try {
|
||||
_package!.fcsID = _user!.fcsID;
|
||||
_package!.fcsID = _consignee!.fcsID;
|
||||
_package!.senderFCSID = _sender!.fcsID;
|
||||
_package!.desc = _descCtl.text;
|
||||
_package!.remark = _remarkCtl.text;
|
||||
_package!.market = selectedMarket!;
|
||||
_package!.market = selectedMarket ?? "";
|
||||
await packageModel.updateProcessing(_package!,
|
||||
multiImgController.getAddedFile, multiImgController.getDeletedUrl);
|
||||
Navigator.pop(context);
|
||||
@@ -264,16 +327,16 @@ class _ProcessingEditEditorState extends State<ProcessingEditEditor> {
|
||||
|
||||
isDataChanged() {
|
||||
if (isNew) {
|
||||
return _user!.fcsID != "" ||
|
||||
return _consignee!.fcsID != "" ||
|
||||
selectedMarket != null ||
|
||||
_descCtl.text != "" ||
|
||||
_remarkCtl.text != "" ||
|
||||
multiImgController.getAddedFile.isNotEmpty;
|
||||
} else {
|
||||
var _package = Package(
|
||||
trackingID: widget.package!.trackingID,
|
||||
fcsID: _user!.fcsID,
|
||||
market: selectedMarket!,
|
||||
fcsID: _consignee!.fcsID,
|
||||
senderFCSID: _sender!.fcsID,
|
||||
market: selectedMarket,
|
||||
desc: _descCtl.text ,
|
||||
remark: _remarkCtl.text,
|
||||
photoUrls: widget.package!.photoUrls);
|
||||
|
||||
@@ -160,7 +160,8 @@ class _ProcesingEditorState extends State<ProcesingEditor> {
|
||||
consignee: this.consignee,
|
||||
)),
|
||||
);
|
||||
_addPackage(_package!);
|
||||
|
||||
_addPackage(_package);
|
||||
// _savePackage(_package);
|
||||
}),
|
||||
],
|
||||
@@ -244,14 +245,14 @@ class _ProcesingEditorState extends State<ProcesingEditor> {
|
||||
}).toList();
|
||||
}
|
||||
|
||||
_addPackage(Package package) {
|
||||
_addPackage(Package? package) {
|
||||
if (package == null) return;
|
||||
|
||||
this.packages.add(package);
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
_savePackage(Package package) {
|
||||
_savePackage(Package? package) {
|
||||
if (package == null) return;
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
@@ -215,15 +215,14 @@ class _ProcessingInfoState extends State<ProcessingInfo> {
|
||||
bool? deleted = await Navigator.push<bool>(
|
||||
context,
|
||||
CupertinoPageRoute(
|
||||
builder: (context) => ProcessingEditEditor(
|
||||
package: widget.package,
|
||||
)));
|
||||
builder: (context) => ProcessingEditEditor(package: _package)));
|
||||
if (deleted ?? false) {
|
||||
Navigator.pop(context);
|
||||
} else {
|
||||
PackageModel packageModel =
|
||||
Provider.of<PackageModel>(context, listen: false);
|
||||
Package? p = await packageModel.getPackage(_package!.id!);
|
||||
if(p == null)return;
|
||||
initPackage(p);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import 'package:provider/provider.dart';
|
||||
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
|
||||
|
||||
import '../../helpers/theme.dart';
|
||||
import 'package:collection/collection.dart';
|
||||
|
||||
typedef void ProfileCallback();
|
||||
|
||||
@@ -202,9 +203,11 @@ class _ProfileState extends State<Profile> {
|
||||
Provider.of<StaffModel>(context, listen: false).privileges;
|
||||
|
||||
if (user == null || user.isCustomer()) return Container();
|
||||
|
||||
List<Privilege> privileges = [];
|
||||
user.privileges.forEach((e) {
|
||||
var p = _privileges.firstWhere((p) => p.id == e);
|
||||
Privilege? p = _privileges.firstWhereOrNull((p) => p.id == e);
|
||||
|
||||
if (p != null) {
|
||||
privileges.add(p);
|
||||
}
|
||||
|
||||
@@ -105,6 +105,10 @@ class _CargoEditorState extends State<CargoEditor> {
|
||||
}
|
||||
|
||||
_save() async {
|
||||
if (_rateController.text == "") {
|
||||
showMsgDialog(context, "Error", "Please insert rate");
|
||||
return;
|
||||
}
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
|
||||
@@ -118,6 +118,16 @@ class _CustomEditorState extends State<CustomEditor> {
|
||||
}
|
||||
|
||||
_save() async {
|
||||
if (_feeController.text == "") {
|
||||
showMsgDialog(context, "Error", "Please insert fee");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_shipmentRateController.text == "") {
|
||||
showMsgDialog(context, "Error", "Please insert shipment rate");
|
||||
return;
|
||||
}
|
||||
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
|
||||
@@ -107,6 +107,16 @@ class _DiscountByWeightEditorState extends State<DiscountByWeightEditor> {
|
||||
}
|
||||
|
||||
_save() async {
|
||||
if (_weightController.text == "") {
|
||||
showMsgDialog(context, "Error", "Please insert weight");
|
||||
return;
|
||||
}
|
||||
|
||||
if (_discountController.text == "") {
|
||||
showMsgDialog(context, "Error", "Please insert discount rate");
|
||||
return;
|
||||
}
|
||||
|
||||
setState(() {
|
||||
_isLoading = true;
|
||||
});
|
||||
|
||||
@@ -144,9 +144,7 @@ class _ReceivingInfoState extends State<ReceivingInfo> {
|
||||
await Navigator.push(
|
||||
context,
|
||||
CupertinoPageRoute(
|
||||
builder: (context) => ReceivingEditor(
|
||||
package: widget.package,
|
||||
)),
|
||||
builder: (context) => ReceivingEditor(package: _package)),
|
||||
);
|
||||
PackageModel packageModel =
|
||||
Provider.of<PackageModel>(context, listen: false);
|
||||
|
||||
@@ -5,6 +5,7 @@ import 'package:fcs/pages/widgets/local_text.dart';
|
||||
import 'package:fcs/pages/widgets/progress.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_vector_icons/flutter_vector_icons.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
@@ -83,7 +84,7 @@ class _StaffListState extends State<StaffList> {
|
||||
padding: new EdgeInsets.symmetric(
|
||||
horizontal: 32.0 - dotSize / 2),
|
||||
child: Icon(
|
||||
Icons.person,
|
||||
MaterialCommunityIcons.account_hard_hat,
|
||||
color: primaryColor,
|
||||
size: 40,
|
||||
),
|
||||
|
||||
@@ -8,7 +8,6 @@ import 'package:fcs/pages/widgets/local_text.dart';
|
||||
import 'package:fcs/pages/widgets/progress.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_icons_null_safety/flutter_icons_null_safety.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:zefyrka/zefyrka.dart';
|
||||
// import 'package:zefyr/zefyr.dart';
|
||||
|
||||
Reference in New Issue
Block a user