Skip to content

Instantly share code, notes, and snippets.

@stephanedeluca
Last active May 31, 2023 17:24
Show Gist options
  • Save stephanedeluca/a629879ae8cb08d429757d784a36ce10 to your computer and use it in GitHub Desktop.
Save stephanedeluca/a629879ae8cb08d429757d784a36ce10 to your computer and use it in GitHub Desktop.
Shokaze category details form designer

Shokaze category details form designer

Created with <3 with dartpad.dev.

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
const Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(
scaffoldBackgroundColor: darkBlue,
),
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar:AppBar(title:const Text("Shokaze category details form designer")),
body: Center(
child: CategoryTesterWidget(),
),
),
);
}
}
class CategoryTesterWidget extends StatefulWidget {
@override State<CategoryTesterWidget> createState() => _CategoryTesterWidgetState();
}
class _CategoryTesterWidgetState extends State<CategoryTesterWidget> {
ClassifiedAdCategory _category = ClassifiedAdCategory.car;
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(20),
child: Column(
children:[
ListTile(
onTap:(){
showModalBottomSheet(
context: context,
builder: (context) => //Center(child:Text("bottom sheet"))
//ClassifiedAdCategory.showModalBottomSheetListPicker
ClassifiedAdCategory.foldingSuperCategoryListPicker
(context,
value:_category,
onTap:(value)=> setState(()=>_category=value)
),
);
},
title: const Text(
'Pick the category to test:',
//style: Theme.of(context).textTheme.headlineMedium
),
trailing: Text("${_category.name} >")
),
Card(
child: Padding(
padding: const EdgeInsets.all(20),
child:AdFormCategoryDetail(category: _category),
),
),
]),
);
}
}
/*
/// The main form for the classified ad
class _AdFormMain extends StatefulWidget {
final Key formKey;
//final ClassifiedAd ad;
const _AdFormMain({super.key, required this.formKey, //required this.ad
});
@override
State<_AdFormMain> createState() => _AdFormMainState();
}
class _AdFormMainState extends State<_AdFormMain> {
// static const form = {
// "title": {"type": "string"},
// "category": {
// "type": "enum",
// "values": ["realEstate", "furniture", "vehicle", "computer"],
// },
// "address": {"type": "address"},
// "price": {"type": "price"},
// };
// Limitation à 10 charactères: 2 caractères; => B24 (// B23: retour AVI du dimanche 6 mars 2023 à 16 h 29)
static const titleCharacterCountMinLimit = 2;
/// Whether the value have been loaded from the persistence
bool _loaded = false;
@override
void initState() {
loadValues();
super.initState();
}
void loadValues() async {
/*
final sharedPreferences = await SharedPreferences.getInstance();
widget.ad.title =
sharedPreferences.getString("$persistenceKey.title") ?? "";
try {
final catergoryValue =
sharedPreferences.getString("$persistenceKey.category") ?? "other";
widget.ad.category = ClassifiedAdCategory.fromName(catergoryValue);
} catch (e) {
widget.ad.category = ClassifiedAdCategory.other;
}
final price = sharedPreferences.getDouble("$persistenceKey.price") ?? 0;
widget.ad.price = price;
*/
setState(() => _loaded = true);
}
static const persistenceKey = "AdFormMain";
void saveValues() async {
/*
final ad = widget.ad;
final sharedPreferences = await SharedPreferences.getInstance();
await sharedPreferences.setString("$persistenceKey.title", ad.title);
await sharedPreferences.setString(
"$persistenceKey.category", ad.category.name);
// final city = widget.ad.;
// if (city == null){
// sharedPreferences.remove("$peristenceKey.city");
//}
// else {
// sharedPreferences.setString("$peristenceKey.city", city);
//}
final price = ad.price;
if (price == null) {
await sharedPreferences.remove("$persistenceKey.price");
} else {
await sharedPreferences.setDouble("$persistenceKey.price", price);
}
*/
}
@override
Widget build(BuildContext context) {
if (!_loaded) return const LinearProgressIndicator();
final formKey = widget.formKey;
//final ad = widget.ad;
return Form(
key: formKey,
autovalidateMode: AutovalidateMode.always,
onChanged: () {
saveValues();
},
// onWillPop: () async {
// saveValues();
// return true;
// },
child: Column(
//mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
// == The ad list widget
//ad.listWidget(context, withAction: ClassifiedAdAction.none),
// == The title
TextFormField(
decoration: InputDecoration(
labelText: "Title",
),
validator: (value) {
if (value == null) return "Title is mandatory";
if (value.trim().length < titleCharacterCountMinLimit) {
return "You must provide a title of at least $titleCharacterCountMinLimit characters"
;
}
return null;
},
onChanged: (newValue) {
setState(() {
//ad.title = newValue;
});
},
),
// == Ad category
ClassifiedAdPropertyEditor(
isSignedInUserIsAdOwner: true,
icon: Icons.category,
caption: "Category",
value: ad.category.toString(),
onPressed: () =>
ClassifiedAdCategory.showModalBottomSheetListPicker(context,
value: ad.category,
onTap: (value) => setState(() {
ad.category = value;
})),
onChanged: (value) {}),
// TextFormField(
// decoration: const InputDecoration(
// labelText: 'City',
// ),
// onChanged: (newValue) {
// //setState(() {
// // ad.city = newValue!;
// //});
// },
// ),
// == Ad price
PriceInputField(
price: ad.price,
currency: ad.priceCurrency,
onChanged: (price, currency) {
setState(() {
ad.price = price;
ad.priceCurrency = currency;
});
}),
// == Description
TextFormField(
maxLines: 8,
decoration: InputDecoration(
labelText: "Description"
),
validator: (value) {
//if (value == null) return i18n_Title_is_mandatory.i18n;
// if (value.trim().length < titleMinCharacterCount) {
// return i18n_You_must_provide_a_title_of_at_least_d_characters
// .i18n
// .fill([titleMinCharacterCount]);
// }
return null;
},
onChanged: (newValue) {
setState(() {
ad.description = newValue;
});
},
),
],
));
}
}
*/
/// The form that takes the style from the classified [ad]
class AdFormCategoryDetail extends StatelessWidget {
//final Key formKey;
final ClassifiedAdCategory category;
const AdFormCategoryDetail(
{super.key, //required this.formKey,
required this.category});
@override
Widget build(BuildContext context) {
final style = category.metaData();
List<Widget> children = [];
style.forEach(((name, fieldDefinition) {
final w =
GenericFormInputField(name: name, fieldDefinition: fieldDefinition);
children.add(w);
}));
return Column(children: children);
}
}
/// The form that takes the fields from [fieldsDefinition]
class GenericForm extends StatelessWidget {
final Key formKey;
final Map<String, Map<String, dynamic>> fieldsDefinition;
const GenericForm(
{Key? key, required this.formKey, required this.fieldsDefinition})
: super(key: key);
@override
Widget build(BuildContext context) {
List<Widget> children = [];
fieldsDefinition.forEach(((name, fieldDefinition) {
final w =
GenericFormInputField(name: name, fieldDefinition: fieldDefinition);
children.add(w);
}));
return Form(
key: formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: children));
}
}
/// The form input field that takes its [name] and json definition
class GenericFormInputField extends StatefulWidget {
final String name;
final Map<String, dynamic> fieldDefinition;
const GenericFormInputField(
{Key? key, required this.name, required this.fieldDefinition})
: super(key: key);
@override
State<GenericFormInputField> createState() => _GenericFormInputField();
}
class _GenericFormInputField extends State<GenericFormInputField> {
final controller = TextEditingController();
// @override
// void initState() {
// super.initState();
// }
/*
{
"surface": {"type": double, "unit": "m2"},
"buildDate": {
"type": DateTime,
},
"price": {"type": double, "unit": "€"},
"type": {
"type": Enum,
"values": ["Maison", "Appart", "Terrain", "Appart", null]
},
}*/
String? _initialValue;
int? _maxLines;
@override
initState() {
final def = widget.fieldDefinition;
final value = def["value"];
if (value != null) {
controller.text = "$value";
}
if (def["maxLines"] != null) {
_maxLines = def["maxLines"];
}
super.initState();
}
@override
Widget build(BuildContext context) {
final name = widget.name;
final fieldDefinition = widget.fieldDefinition;
TextInputType tit = TextInputType.text;
final type = fieldDefinition["type"];
final prefixIcon = fieldDefinition["icon"] is IconData
? Padding(padding: const EdgeInsets.only(top:20),child:Icon(fieldDefinition["icon"]))
: null;
final unit = fieldDefinition["unit"] is String
? Padding(
padding: const EdgeInsets.only(
top: 20),
child: Text(fieldDefinition["unit"]),
)
: null;
switch (type) {
case "enum":
Set<String> set = fieldDefinition["values"];
/*
// == Build a set to prevent multiple same values
final Set<String> set = {};
for (final value in values) {
set.add(value);
}
*/
return ListTile(
leading:prefixIcon,
title:Text(name),
trailing:DropdownButton<String>(
value: set.first,
onChanged: (newValue) {
//setState(() {
final _ = newValue!;
//});
},
items: set.map((value) {
return DropdownMenuItem<String>(
value: value, child: Text(value));
}).toList()),
);
case "dateTime":
case "date":
DateTime dateMin = DateTime(1900);
DateTime? dateMax;
if (fieldDefinition["ageMin"] != null) {
late final int ageMin;
try {
ageMin = fieldDefinition["ageMin"] ?? 15;
} catch (e) {
ageMin = 15;
}
dateMax = DateTime.now().subtract(Duration(days: 365 * ageMin));
}
return
ListTile(
title:TextFormField(
controller: controller,
readOnly: true,
decoration: InputDecoration(
icon: Padding(padding: const EdgeInsets.only(top:20),child:const Icon(Icons.calendar_today)), //icon of text field
labelText: fieldDefinition["label"] ?? name,
),
onTap: () async {
final pickedDate = await showDatePicker(
context: context,
initialDate: dateMax ?? DateTime.now(),
firstDate:
dateMin, //DateTime.now() - not to allow to choose before today.
lastDate: dateMax ?? DateTime.now());
if (pickedDate != null) {
//debugPrint(pickedDate); //pickedDate output format => 2021-03-10 00:00:00.000
String formattedDate =
DateFormat('yyyy-MM-dd').format(pickedDate);
//formatted date output using intl package => 2021-03-16
debugPrint(formattedDate);
fieldDefinition["value"] = formattedDate;
if (!mounted) return;
setState(() {
controller.text = formattedDate;
});
}
}));
case "int":
tit = const TextInputType.numberWithOptions(decimal: false);
break;
case "double":
tit = const TextInputType.numberWithOptions(decimal: true);
break;
case "string":
_maxLines = fieldDefinition["maxLines"];
break;
default:
break;
}
return Padding(
padding: const EdgeInsets.symmetric(vertical: 10),
child:
ListTile(
//leading:prefixIcon,
trailing: unit,
title:TextFormField(
controller: controller,
keyboardType: tit,
maxLines: _maxLines,
decoration: InputDecoration(
labelText: fieldDefinition["label"] ?? name,
icon: prefixIcon,
// suffixIcon:unit,
),
/// Saves new value
onChanged: (value) {
fieldDefinition["value"] = value;
},
)));
}
}
/*
/// The category widget in a gallery
class CategoryGalleryWidget extends StatelessWidget {
final String? imageUrl;
final ClassifiedAdSuperCategory? superCategory;
final ClassifiedAdCategory? category;
final int index;
final void Function()? onTap;
const CategoryGalleryWidget({
super.key,
required this.superCategory,
required this.category,
required this.imageUrl,
required this.index,
this.onTap,
});
@override
Widget build(BuildContext context) {
final size = GalleryOptions.categorySize(context);
final name = category?.toString() ?? superCategory?.toString();
final List<ClassifiedAdCategory> listOfCategories = category == null
? (superCategory == null ? [] : superCategory!.allCategories)
: [category!];
final int friezeIndex = index % 4;
const scale = 1.65;
// 0 1 2 3
const List<double?> backgroundTop = [0, null, 0, null];
const List<double?> backgroundBottom = [null, 0, null, 0];
const List<double?> backgroundLeft = [null, null, 0, null];
const List<double?> backgroundRight = [0, 0, null, 0];
const List<double?> foregroundTop = [null, 0, null, 0];
const List<double?> foregroundBottom = [0, null, 0, null];
const List<double?> foregroundLeft = [0, 0, 0, 0];
const List<double?> foregroundRight = [null, null, null, null];
return GestureDetector(
onTap: onTap ??
() => Navigator.of(context).push(MaterialPageRoute(
builder: (context) => listOfCategories.length == 1
? ClassifiedAdGalleryScreen(categories: listOfCategories)
: SuperCategoryGalleryScreen(
superCategory: superCategory!))),
child: Container(
color: AppTheme.nightBlue.color,
width: size.width,
height: size.height,
margin: const EdgeInsets.only(right: 4),
padding: const EdgeInsets.all(0),
child: Stack(children: [
// == Background image
if (true)
Positioned(
top: backgroundTop[friezeIndex],
bottom: backgroundBottom[friezeIndex],
right: backgroundRight[friezeIndex],
left: backgroundLeft[friezeIndex],
child: Image.asset(
"assets/images/category-frieze-$friezeIndex-background@2x.png",
// width: size.width,
// height: size.height,
scale: scale // backgroundScale[friezeIndex],
//fit: BoxFit.none,
)),
// Transform.rotate(
// angle: -5,
// child: Container(
// decoration: BoxDecoration(
// borderRadius: BorderRadius.circular(20),
// color: AppTheme.green.color,
// ),
// width: size.width,
// height: size.height,
// ),
// ),
// == Simple image
if (imageUrl != null)
Positioned(
top: backgroundTop[friezeIndex],
bottom: backgroundBottom[friezeIndex],
right: backgroundRight[friezeIndex],
left: backgroundLeft[friezeIndex],
child: Image.asset(
imageUrl!,
// width: size.width,
// height: size.height,
scale: scale,
//fit: BoxFit.scaleDown,
)),
// == Foreground image
if (true)
Positioned(
top: foregroundTop[friezeIndex],
bottom: foregroundBottom[friezeIndex],
right: foregroundRight[friezeIndex],
left: foregroundLeft[friezeIndex],
child: Image.asset(
"assets/images/category-frieze-$friezeIndex-foreground@2x.png",
// width: size.width,
// height: size.height,
scale: scale, //foregroundScale[friezeIndex],
//fit: BoxFit.,
)),
// == Add title is required
if (name != null)
// Padding(
// padding: const EdgeInsets.all(5),
Center(
child: Text(
name.toUpperCase(),
textAlign: TextAlign.center,
style: Format.overlayTextStyle(
context,
style: Theme.of(context)
.textTheme
.titleSmall
?.copyWith(fontWeight: FontWeight.bold),
),
)),
])));
}
}
*/
//Avi's categories
// The classified ad category
enum ClassifiedAdSuperCategory {
vehicle,
realEstate,
vacation,
job,
fashion,
home,
multimedia,
hobby,
animal,
professional,
service,
food,
donation,
other,
;
factory ClassifiedAdSuperCategory.fromName(String name) =>
values.firstWhere((x) => x.name == name, orElse: () => other);
/// Returns the name corresponding to the enum
@override
String toString()
=> this.name;
/*{
switch (this) {
case vehicle:
return i18n_vehicle.i18n;
case realEstate:
return i18n_realEstate.i18n;
case job:
return i18n_job.i18n;
case vacation:
return i18n_vacation.i18n;
case fashion:
return i18n_fashion.i18n;
case home:
return i18n_home.i18n;
case multimedia:
return i18n_multimedia.i18n;
case hobby:
return i18n_hobby.i18n;
case animal:
return i18n_animal.i18n;
case professional:
return i18n_professional.i18n;
case service:
return i18n_service.i18n;
case food:
return i18n_food.i18n;
case donation:
return i18n_donation.i18n;
case other:
return i18n_other.i18n;
}
}
*/
/// Returns the icon
IconData get iconData {
switch (this) {
case vehicle:
return Icons.drive_eta_sharp;
case realEstate:
return Icons.house;
case job:
return Icons.work;
case vacation:
return Icons.surfing;
case fashion:
return Icons.accessibility;
case home:
return Icons.blender;
case multimedia:
return Icons.devices_other;
case hobby:
return Icons.catching_pokemon;
case animal:
return Icons.bug_report;
case professional:
return Icons.agriculture;
case service:
return Icons.room_service;
case food:
return Icons.food_bank;
case donation:
return Icons.money;
case other:
return Icons.miscellaneous_services;
}
}
/// Returns the image url of the related image
String? get imageUrl {
switch (this) {
case vehicle:
return null;
//'assets/images/vehicle.jpg';
case realEstate:
return 'assets/images/supercategory-realEstate@2x.png'; //assets/images/realEstate.jpeg';
case job:
return null;
//'assets/images/job.jpg';
case vacation:
return null;
//"assets/images/other.jpg";
case fashion:
return "assets/images/supercategory-fashion@2x.png"; //"assets/images/man.jpg";
case home:
return null;
//'assets/images/house.jpg';
case multimedia:
return "assets/images/supercategory-multimedia@2x.png"; //'assets/images/entertainment.jpg';
case hobby:
return null;
//"assets/images/other.jpg";
case animal:
return null;
//"assets/images/animal.jpg";
case professional:
case service:
case food:
case donation:
case other:
return null;
//"assets/images/other.jpg";
}
}
/// Returns the list of all categories for this super category
List<ClassifiedAdCategory> get allCategories {
return ClassifiedAdCategory.values
.where((c) => c.superCategory == this)
.toList();
}
/*
/// Returns the gallery widgets of the category ad
Widget asGalleryWidget(
BuildContext context, {
required int index,
void Function()? onTap,
}) {
return CategoryGalleryWidget(
superCategory: this,
category: null,
imageUrl: imageUrl,
index: index,
onTap: onTap,
);
}*/
}
/// The classified ad category
enum ClassifiedAdCategory {
// vehicle
car,
motorcycle,
caravanning,
utility,
electricScooter,
bike,
truck,
boat,
autoMotoEquipment,
// realEstate
realEstateSale,
rental,
flatsharing,
officeAndShop,
// vacation
rentalAndGite,
guestRoom,
campsite,
unusualAccommodation,
hotel,
//Job
jobOffer,
application,
//Fashion
clothe,
shoe,
accessoryAndJewelry,
//home
furnishing,
homeAppliance,
tableArt,
decoration,
householdLinen,
diy,
gardening,
//multimedia
computerScience,
consoleAndVideoGame,
pictureAndSound,
telephone,
//Hobbies
cdDvd,
book,
musicInstrument,
gameAndToy,
animal,
//professionnalHArdware
professionalMaterial,
medicalEquipment,
agriculturalMaterial,
constructionEquipmentStructuralWork,
officeSupply,
//services,
plumber,
locksmith,
glazier,
gardener,
cleaning,
//restoration
fastFood,
gastronomy,
donation,
other,
;
factory ClassifiedAdCategory.fromName(String name) =>
values.firstWhere((x) => x.name == name, orElse: () => other);
/// Returns the name corresponding to the enum
@override
String toString()
=> this.name;
/*{
switch (this) {
// vehicle
case car:
return i18n_car.i18n;
case motorcycle:
return i18n_motorcycle.i18n;
case caravanning:
return i18n_caravanning.i18n;
case utility:
return i18n_utility.i18n;
case electricScooter:
return i18n_electricScooter.i18n;
case bike:
return i18n_bike.i18n;
case truck:
return i18n_truck.i18n;
case boat:
return i18n_boat.i18n;
case autoMotoEquipment:
return i18n_autoMotoEquipment.i18n;
// realEstate
case realEstateSale:
return i18n_realEstateSale.i18n;
case rental:
return i18n_rental.i18n;
case flatsharing:
return i18n_flatsharing.i18n;
case officeAndShop:
return i18n_officeAndShop.i18n;
// vacation
case rentalAndGite:
return i18n_rentalAndGite.i18n;
case guestRoom:
return i18n_guestRoom.i18n;
case campsite:
return i18n_campsite.i18n;
case unusualAccommodation:
return i18n_unusualAccommodation.i18n;
case hotel:
return i18n_hotel.i18n;
//Job
case jobOffer:
return i18n_jobOffer.i18n;
case application:
return i18n_application.i18n;
//Fashion
case clothe:
return i18n_clothe.i18n;
case shoe:
return i18n_shoe.i18n;
case accessoryAndJewelry:
return i18n_accessoryAndJewelry.i18n;
//home
case furnishing:
return i18n_furnishing.i18n;
case homeAppliance:
return i18n_homeAppliance.i18n;
case tableArt:
return i18n_tableArt.i18n;
case decoration:
return i18n_decoration.i18n;
case householdLinen:
return i18n_householdLinen.i18n;
case diy:
return i18n_diy.i18n;
case gardening:
return i18n_gardening.i18n;
//multimedia
case computerScience:
return i18n_computerScience.i18n;
case consoleAndVideoGame:
return i18n_consoleAndVideoGame.i18n;
case pictureAndSound:
return i18n_pictureAndSound.i18n;
case telephone:
return i18n_telephone.i18n;
//Hobbies
case cdDvd:
return i18n_cdDvd.i18n;
case book:
return i18n_book.i18n;
case musicInstrument:
return i18n_musicInstrument.i18n;
case gameAndToy:
return i18n_gameAndToy.i18n;
//animal,
case animal:
return i18n_animal.i18n;
// professionnalHardware
case professionalMaterial:
return i18n_professionalHardware.i18n;
case medicalEquipment:
return i18n_medicalEquipment.i18n;
case agriculturalMaterial:
return i18n_agriculturalHardware.i18n;
case constructionEquipmentStructuralWork:
return i18n_constructionEquipmentStructuralWork.i18n;
case officeSupply:
return i18n_officeSupply.i18n;
//services,
case plumber:
return i18n_plumber.i18n;
case locksmith:
return i18n_locksmith.i18n;
case glazier:
return i18n_glazier.i18n;
case gardener:
return i18n_gardener.i18n;
case cleaning:
return i18n_cleaning.i18n;
//restoration
case fastFood:
return i18n_fastFood.i18n;
case gastronomy:
return i18n_gastronomy.i18n;
// donation
case donation:
return i18n_donation.i18n;
// other
case other:
return i18n_other.i18n;
}
}
*/
/// Returns the super category of the category
ClassifiedAdSuperCategory get superCategory {
switch (this) {
// vehicle
case car:
case motorcycle:
case caravanning:
case utility:
case electricScooter:
case bike:
case truck:
case boat:
case autoMotoEquipment:
return ClassifiedAdSuperCategory.vehicle;
// realEstate
case realEstateSale:
case rental:
case flatsharing:
case officeAndShop:
return ClassifiedAdSuperCategory.realEstate;
// vacation
case rentalAndGite:
case guestRoom:
case campsite:
case unusualAccommodation:
case hotel:
return ClassifiedAdSuperCategory.vacation;
//Job
case jobOffer:
case application:
return ClassifiedAdSuperCategory.job;
//Fashion
case clothe:
case shoe:
case accessoryAndJewelry:
return ClassifiedAdSuperCategory.fashion;
//home
case furnishing:
case homeAppliance:
case tableArt:
case decoration:
case householdLinen:
case diy:
case gardening:
return ClassifiedAdSuperCategory.home;
//multimedia
case computerScience:
case consoleAndVideoGame:
case pictureAndSound:
case telephone:
return ClassifiedAdSuperCategory.multimedia;
//Hobbies
case cdDvd:
case book:
case musicInstrument:
case gameAndToy:
return ClassifiedAdSuperCategory.hobby;
//animal,
case animal:
return ClassifiedAdSuperCategory.animal;
// professional
case professionalMaterial:
case medicalEquipment:
case agriculturalMaterial:
case constructionEquipmentStructuralWork:
case officeSupply:
return ClassifiedAdSuperCategory.professional;
//services,
case plumber:
case locksmith:
case glazier:
case gardener:
case cleaning:
return ClassifiedAdSuperCategory.service;
//food
case fastFood:
case gastronomy:
return ClassifiedAdSuperCategory.food;
// donation
case donation:
return ClassifiedAdSuperCategory.donation;
// other
case other:
return ClassifiedAdSuperCategory.other;
}
}
/// Returns the image url of the related image
String? get imageUrl {
final category = superCategory;
return category.imageUrl;
}
/// Returns the enum picker widget
static Widget dropDownPicker(
{required ClassifiedAdCategory? value,
required void Function(ClassifiedAdCategory?)? onChanged}) {
return DropdownButton<ClassifiedAdCategory>(
hint: const Text("Category"),
value: value,
items: ClassifiedAdCategory.values.map((value) {
return DropdownMenuItem<ClassifiedAdCategory>(
value: value,
child: Text(value.toString()),
);
}).toList(),
onChanged: onChanged,
);
}
/// Retuns the wheel enum picker
static Widget wheelPicker(
{required ClassifiedAdCategory? value,
required void Function(ClassifiedAdCategory?)? onChanged}) {
const list = ClassifiedAdCategory.values;
return ListWheelScrollView(
physics: const BouncingScrollPhysics(),
itemExtent: 50,
diameterRatio: 0.6,
//offAxisFraction: -0.4,
squeeze: 1.8,
//useMagnifier: true,
//overAndUnderCenterOpacity: 0.8,
clipBehavior: Clip.antiAlias,
onSelectedItemChanged: (value) => onChanged?.call(list[value]),
children: list.map((c) => Text("$c")).toList());
}
/// Returns the list picker with folding super category
static Widget foldingSuperCategoryListPicker(BuildContext context,
{ClassifiedAdCategory? value,
required Function(ClassifiedAdCategory) onTap}) {
return /*Expanded(
child:*/ ListView(
physics: const BouncingScrollPhysics(),
children: ClassifiedAdSuperCategory.values.map((s) {
// == The categories
final children = ClassifiedAdCategory.values
.where((c) => c.superCategory == s)
.map((c) => ListTile(
leading: Icon(s.iconData),
title: Text("$c",
style: Theme.of(context).textTheme.headline6),
onTap: () {
Navigator.of(context).pop();
onTap(c);
}))
.toList();
// == The super category
bool initiallyExpanded = false;
if (value != null) {
initiallyExpanded = value.superCategory == s;
}
return ExpansionTile(
initiallyExpanded: initiallyExpanded,
leading: Icon(s.iconData),
childrenPadding: const EdgeInsets.only(left: 20),
title:
Text("$s", style: Theme.of(context).textTheme.headline6),
children: children);
}).toList(),
//)
);
}
/// Open the list picker in a modal bottom sheet with super category being unfoldable by the user
static showModalBottomSheetListPicker(BuildContext context,
{ClassifiedAdCategory? value,
required Function(ClassifiedAdCategory) onTap}) {
showModalBottomSheet(context:context, builder:(context)=>
Column(children:[
Text("Select a category",style:Theme.of(context).textTheme.headlineSmall),
foldingSuperCategoryListPicker(context, value: value, onTap: (c) {
Navigator.pop(context);
// == Tell the caller
onTap(c);
// == Tell the user
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text("You selected the ”$c” (${c.name}) category",
style: const TextStyle(color: Colors.white)),
backgroundColor: Colors.green,
));
}),
]));
}
/// ================== NATHAN ====================
/// ================== NATHAN ====================
/// ================== NATHAN ====================
/// Returns category deinition metadata
Map<String, Map<String, dynamic>> metaData() {
final colors = {
"type": "enum",
"values": [
"black",
"white",
"grey",
"blue",
"red",
"green",
"pink",
"orange",
"yellow",
"brown",
"purple"
]
};
final states = {
"type": "enum",
"values": [
"used",
"new",
]
};
switch (this) {
case car:
const energies = {
"type": "enum",
"values": {
"electric",
"hybrid",
"reloaded hybrid",
"diesel",
"gas",
"hydrogen",
"gpl",
"lng",
"other"
},
};
const brands = {
"type": "enum",
"values": {
"mercedes-benz",
"bmw",
"renault",
"citroën",
"peugeot",
"opel",
"vw",
"simca",
"ford",
"gm",
"cadillac",
"other"
},
};
const categories = {
"type": "enum",
"values": {
"sedan",
"suv",
"pickup",
"truck",
"semi truck",
"bicycle",
"motocycle",
"other"
},
};
return {
"category": categories,
"energy": energies,
"brand": brands,
"model": {"type": "string"},
"date": {
"type": "dateTime",
},
};
case realEstateSale:
const roomSizes = {
"type": "enum",
"values": {"1", "2", "3", "4", "5", "6", "more than 6"},
"unit": "room"
};
return {
"surface": {
"type": "double",
"unit": "m2",
"icon": Icons.shopping_cart_outlined,
},
"build date": {
"type": "dateTime",
},
//"price": {"type": "double", "unit": "€"},
"categories": {
"house": roomSizes,
"appartement": roomSizes,
"terrain": {
"type": "enum",
"values": {"buildable", "not buildable"}
},
"parking": {
"size": {
"type": "enum",
"values": {"normal", "disabled", "double"}
}
},
"exception": roomSizes,
},
};
case jobOffer:
case application:
return {
"type": {
"type": "enum",
"values": [
"CDI",
"CDD",
"stage",
"freelance",
]
}
};
case computerScience:
return {
"brand": {"type": "string"},
"build date": {
"type": "dateTime",
},
//"price": {"type": "double", "unit": "€"},
"type": {
"type": "enum",
"values": [
"laptop",
"desktop",
"tablet",
"phone",
"watch",
"headphone",
"others",
]
}
};
case furnishing:
return {
"long": {
"type": "double",
},
"width": {"type": "double"},
"height": {"type": "double"},
};
case clothe:
//case man:
final shoeSizes = {
"type": "enum",
"values": List<int>.generate(47 - 36, (index) => 36 + index)
.map((e) => "EU: $e")
.toList()
};
const clotheSize = {
"type": "enum",
"values": [
"XXS",
"XS",
"S",
"M",
"L",
"XL",
"XXL",
]
};
final shoeSettings = {
"color": colors,
"size": shoeSizes,
"state": states
};
final clotheSettings = {
"color": colors,
"size": clotheSize,
"state": states
};
final snearkerBrand = {
"addidas": shoeSettings,
"nike": shoeSettings,
"new balance": shoeSettings,
"le coc sportif": shoeSettings
};
//.map((brand) => e: shoeSettings)
final c = {
"shoe": {
"sneaker": snearkerBrand,
"boot": shoeSettings,
"others": shoeSettings,
},
"jeans": clotheSettings,
"trousses": clotheSettings,
"jacket": clotheSettings,
"accessories": {
"glasses": {"state": states},
"cape": {"state": states},
"casket": {"state": states},
}
};
return c;
/*
case baby:
return {
"size": {
"type": "enum",
"values": [
"0 month",
"1 month",
"3 months",
"6 months",
"9 months",
"12 months",
"18 months",
"24 months",
"36 months"
],
"unit": "months"
},
"color": {
"type": "color",
},
"type": {
"type": "enum",
"values": [
"used",
"new",
]
},
};*/
case animal:
return {
"type": {
"type": "enum",
"values": [
"cat",
"dog",
"rodent",
"bird",
"reptile",
"insect",
"other"
]
},
"color": {
"type": "color",
},
}; /*
case hobby:
return {
"type": {
"type": "enum",
"values": [
"disk",
"book",
"video game",
"game",
"concert",
"sport",
"other"
]
},
};*/
case other:
default:
return {};
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment