mnemo_cards/mnemo_cards_admin/old/add_discount_campaign.dart
2025-12-03 02:17:15 +03:00

383 lines
16 KiB
Dart

import 'dart:async';
import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:mnemo_cards/admin/admin_api.dart';
import 'package:mnemo_cards_common/mnemo_cards_common.dart';
import 'package:mnemo_cards_frontend_common/mnemo_cards_frontend_common.dart';
import '../di/injector.dart';
import '../main.dart';
import 'date_param.dart';
import 'enum_param.dart';
import 'int_param.dart';
import 'text_param.dart';
class AddDiscountCampaign {
late DiscountCampaignDto campaignDto;
late AdminApi adminApi;
List<DiscountCampaignDto> _campaigns = [];
AddDiscountCampaign() {
this.adminApi = getIt.get<AdminApi>();
_init(null);
}
void _init(DiscountCampaignDto? dto) {
final now = DateTime.now();
campaignDto = dto ??
DiscountCampaignDto(
start: now,
finish: now.add(Duration(days: 30)),
status: DiscountCampaignStatus.disabled,
name: null,
tags: [],
discounts: [],
);
}
Future<bool> _loadCampaigns() async {
try {
_campaigns = await adminApi.getDiscountCampaigns();
} catch (e, s) {
log('Error', error: e, stackTrace: s);
print('Error $e');
return false;
}
return true;
}
void _savePromoCodeCampaign() async {
for (final d in campaignDto.discounts) {
final products = d.products.map((p) => p.toProduct());
d.products.replaceRange(0, products.length, products);
}
final result = await adminApi.addDiscountCampaign(campaignDto);
if (!result) {
ScaffoldMessenger.of(scaffoldKey.currentContext!).showSnackBar(SnackBar(
content: Text('ERROR'),
));
} else {
ScaffoldMessenger.of(scaffoldKey.currentContext!).showSnackBar(SnackBar(
content: Text('Success!!!'),
));
appRouter.maybePop();
}
}
void _deleteDiscountCampaign() async {
if (campaignDto.id == null) return;
final result =
await adminApi.deleteDiscountCampaign(campaignDto.id.toString());
if (result != null) {
ScaffoldMessenger.of(scaffoldKey.currentContext!).showSnackBar(SnackBar(
content: Text('ERROR'),
));
} else {
ScaffoldMessenger.of(scaffoldKey.currentContext!).showSnackBar(SnackBar(
content: Text('Success!!!'),
));
appRouter.maybePop();
}
}
void addCampaign(BuildContext context) {
showDialog(
context: context,
builder: (c) {
return FutureBuilder(
future: _loadCampaigns(),
builder: (context, snapshot) {
if (snapshot.data != true) {
return Center(
child: Material(
child: Center(child: CircularProgressIndicator()),
),
);
}
return Center(
child: Scaffold(
body: Material(
child: StatefulBuilder(builder: (context, setCampaign) {
return ListView(
children: [
Header(
'${campaignDto.id}',
hasPopButton: true,
trail: Row(
children: [
IconButton(
onPressed: _savePromoCodeCampaign,
icon: Icon(Icons.save),
),
if (campaignDto.id != null)
IconButton(
onPressed: () async {
campaignDto =
campaignDto.copyWith(id: null);
_savePromoCodeCampaign();
},
icon: Icon(Icons.copy),
),
if (campaignDto.id != null)
GestureDetector(
onLongPress: _deleteDiscountCampaign,
child: Icon(Icons.delete),
)
],
),
),
DropdownMenu<int?>(
initialSelection: null,
onSelected: (int? value) {
setCampaign(() {
_init(
_campaigns
.firstWhereOrNull((v) => v.id == value),
);
});
},
dropdownMenuEntries: [
..._campaigns,
null,
].map((campaign) {
return DropdownMenuEntry(
value: campaign?.id,
label: campaign == null
? 'New'
: '${campaign.name ?? campaign.id} ${campaign.status.name}',
);
}).toList(),
),
StatefulBuilder(builder: (context, setState) {
return Padding(
padding: EdgeInsets.all(8.0),
child: Column(
children: [
TextParam(
'Name',
campaignDto.name,
(v) {
campaignDto = campaignDto.copyWith(
name: v,
);
},
),
DateParam(
'Start',
campaignDto.start,
(v) {
setState(() {
campaignDto =
campaignDto.copyWith(start: v);
});
},
),
DateParam(
'Finish',
campaignDto.finish,
(v) {
setState(() {
campaignDto =
campaignDto.copyWith(finish: v);
});
},
),
EnumParam(
'Status',
DiscountCampaignStatus.values,
campaignDto.status, (v) {
setState(() {
campaignDto =
campaignDto.copyWith(status: v);
});
}),
Text(
'Created to create or change\n'
'Disabled to disable\n'
'Dont use other statuses!',
style: TextStyle(fontSize: 12),
),
Text('Discounts:'),
ListView.builder(
shrinkWrap: true,
itemCount:
campaignDto.discounts.length + 1,
itemBuilder: (context, index) {
if (index ==
campaignDto.discounts.length) {
return Container(
child: SimpleTile(
title: Text('Add'),
onTap: () async {
final discount =
await _showDiscountDialog(
context, null);
if (discount != null) {
setState(() {
final ex = campaignDto
.discounts
.firstWhereOrNull((d) =>
d.id ==
discount.id);
if (ex != null) {
campaignDto.discounts
.remove(ex);
}
campaignDto.discounts
.add(discount);
});
}
},
),
);
}
final item =
campaignDto.discounts[index];
return ListTile(
title: Text(
'${item.type.name} ${item.id ?? ''}'),
onTap: () async {
final p = await _showDiscountDialog(
context,
item,
);
if (p != null) {
setState(() {
campaignDto.discounts.add(p);
});
}
},
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () {
setState(() {
campaignDto.discounts
.remove(item);
});
},
),
);
},
),
],
),
);
}),
],
);
}),
),
),
);
});
});
}
Future<DiscountDto?> _showDiscountDialog(
BuildContext context,
DiscountDto? initialDiscount,
) async {
var prod = initialDiscount ?? DiscountDto(discountPercent: 0, products: []);
final result = await showDialog<DiscountDto?>(
context: context,
builder: (c) => Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Material(
child: FutureBuilder(
future: () async {
final allPacks = await adminApi.packs();
final allPlans = await adminApi.getSubscriptionPlans();
return [...allPacks, ...allPlans];
}.call(),
builder: (context, snapshot) {
if (!snapshot.hasData) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Text('Loading products...'),
);
}
final products = snapshot.requireData;
return SingleChildScrollView(
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text('Adding discount'),
TextParam(
'Id',
prod.id,
(v) {
prod = prod.copyWith(id: v);
},
description: 'Leave empty for new',
),
IntParam('Discount 0-100', prod.discountPercent.toInt(),
(v) {
prod = prod.copyWith(
discountPercent: v?.toDouble() ?? 0.0);
}),
StatefulBuilder(builder: (context, ss) {
return ListView.builder(
shrinkWrap: true,
itemCount: prod.products.length + 1,
itemBuilder: (BuildContext context, int index) {
if (index == prod.products.length) {
return EnumParam(
'Add product',
products,
null,
(p) {
if (p != null) {
ss(() {
prod.products.add(p);
});
}
},
getName: (p) => _productName(p, products),
);
}
final p = prod.products[index];
return ListTile(
title: Text(_productName(p, products)),
onTap: () async {
ss(() {
prod.products.remove(p);
});
},
);
},
);
}),
MaterialButton(
onPressed: () {
Navigator.of(context).pop(prod);
},
child: Text('Save'),
),
],
),
);
}),
),
),
),
);
return result;
}
String _productName(MnemoCardsProductDto? p, List<MnemoCardsProductDto> products) {
if (p is CardPackPreviewDto) {
return '${p.id} ${p.title} ${p.price} pack';
} else if (p is SubscriptionPlanAdminDto) {
return '${p.id} ${p.ui.titleLead ?? ''} ${p.ui.title ?? ''} ${p.paymentSystem.name} ${p.price} plan';
}
final matchedProduct = products.firstWhereOrNull((m) => m.productEquals(p));
if (matchedProduct != null) {
return _productName(matchedProduct, []);
}
return '${p?.type.name} ${p?.id}';
}
}