flutter_data_sync 0.0.4 copy "flutter_data_sync: ^0.0.4" to clipboard
flutter_data_sync: ^0.0.4 copied to clipboard

flutter_data_sync simplifies the mapping between Flutter app models and external data sources (API, DB). Easily transform JSON data into Dart objects and manage HTTP requests, reducing development tim [...]

example/lib/main.dart

// ignore_for_file: avoid_print, use_build_context_synchronously, must_be_immutable

import 'package:flutter/material.dart';
import 'package:flutter_data_sync/flutter_data_sync.dart';

void main() {
  runApp(const MyApp());
}

DataSync dataSync = DataSync(baseApiUrl: "http://127.0.0.1:8080/api/");

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Todo list -- Flutter data sync demo'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int deletingID = 0;
  int validatingID = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
        title: Text(widget.title),
      ),
      body: Padding(
        padding: const EdgeInsets.all(30.0),
        child: DataSyncGetWidget<List<Todo>>(
            setIntervallCall: false,
            setIntervallCallDuration: const Duration(seconds: 2),
            onSetIntervall: (timer) {},
            promise: () => dataSync.index<Todo>(
                  context: context,
                  fromJson: Todo.fromJson,
                  url: "todos",
                ),
            hasDataWidget: (data) {
              return ListView.builder(
                  shrinkWrap: true,
                  itemCount: data.length,
                  itemBuilder: (BuildContext context, int index) {
                    Todo todo = data[index];

                    return ListTile(
                      leading: validatingID == todo.id
                          ? SizedBox(
                              width: 15,
                              height: 15,
                              child: DataSyncLoading.loadingBallRotate(
                                  color: Colors.blue[800]!))
                          : Checkbox(
                              value: todo.isValid,
                              onChanged: (value) async {
                                setState(() {
                                  validatingID = todo.id ?? 0;
                                });
                                todo.isValid = value!;
                                await valideCheckTodo(todo);
                              }),
                      title: Text(todo.libelle),
                      subtitle: Text(todo.description),
                      trailing: Wrap(
                        children: [
                          IconButton(
                            onPressed: () async {
                              if (await showAddTodoModal(
                                      context: context, todo: todo) !=
                                  null) {
                                setState(() {});
                              }
                            },
                            icon: Icon(
                              Icons.edit,
                              color: Colors.green[800],
                            ),
                          ),
                          deletingID == todo.id
                              ? SizedBox(
                                  width: 20,
                                  height: 20,
                                  child: DataSyncLoading.loadingBallRotate(
                                      color: Colors.red[800]!))
                              : IconButton(
                                  onPressed: () async {
                                    setState(() {
                                      deletingID = todo.id ?? 0;
                                    });
                                    await valideDeleteTodo(todo);
                                  },
                                  icon: Icon(
                                    Icons.delete_forever_outlined,
                                    color: Colors.red[800],
                                  ),
                                ),
                        ],
                      ),
                      onTap: () {
                        print('Item $index tapped');
                      },
                    );
                  });
            }),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          if (await showAddTodoModal(
                  context: context, todo: Todo.fromJson({})) !=
              null) {
            setState(() {});
          }
        },
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }

  valideDeleteTodo(Todo todo) async {
    bool etat = await dataSync.delete<Todo, bool>(
      context: context,
      fromJson: (map, statusCode) =>
          statusCode == 200 || statusCode == 201 ? true : false,
      url: "todos/${todo.id}",
    );
    if (etat) {
      setState(() {
        deletingID = 0;
      });
      Navigator.pop(context);
    } else {
      setState(() {
        deletingID = 0;
      });
    }
  }

  valideCheckTodo(Todo todo) async {
    bool etat = await dataSync.put<Todo, bool>(
        context: context,
        fromJson: (map, statusCode) =>
            statusCode == 200 || statusCode == 201 ? true : false,
        url: "todos/${todo.id}",
        data: todo.toJSon());
    if (etat) {
      setState(() {
        validatingID = 0;
      });
    } else {
      setState(() {
        validatingID = 0;
      });
    }
  }
}

showAddTodoModal({required context, required Todo todo}) async {
  await showDialog(
      barrierDismissible: false,
      context: context,
      builder: (context) {
        return AlertDialog(
          backgroundColor: Colors.white,
          shape: const RoundedRectangleBorder(
            borderRadius: BorderRadius.all(Radius.circular(5)),
          ),
          title: Row(
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              const Text(
                "Ajouter une Todo",
                style: TextStyle(
                    color: Colors.black87,
                    fontSize: 17,
                    fontWeight: FontWeight.bold),
              ),
              const SizedBox(width: 300),
              IconButton(
                  onPressed: () {
                    Navigator.pop(context);
                  },
                  icon: Icon(Icons.close, color: Colors.blueGrey[400]))
            ],
          ),
          titlePadding:
              const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
          contentPadding:
              const EdgeInsets.symmetric(horizontal: 20, vertical: 10),
          content: AddTodo(todo: todo),
          elevation: 1,
        );
      });
  return Todo;
}

class AddTodo extends StatefulWidget {
  Todo todo;
  AddTodo({super.key, required this.todo});

  @override
  State<AddTodo> createState() => _AddTodoState();
}

class _AddTodoState extends State<AddTodo> {
  final _keyForm = GlobalKey<FormState>();
  bool _isloading = false;
  bool updateState = false;

  @override
  void initState() {
    super.initState();
    if (widget.todo.id != null) {
      updateState = true;
    } else {
      updateState = false;
    }
  }

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Container(
        constraints: const BoxConstraints(minWidth: 300, maxWidth: 500),
        width: 500,
        child: Form(
          key: _keyForm,
          child: Card(
            color: Colors.transparent,
            elevation: 0,
            child: Column(
              children: [
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: TextFormField(
                    initialValue: widget.todo.libelle,
                    decoration: const InputDecoration(hintText: "Libellé"),
                    validator: (val) => val.toString().isEmpty
                        ? "veuillez entrer un nom de Todo valide !"
                        : null,
                    onChanged: (val) {
                      widget.todo.libelle = val;
                    },
                  ),
                ),
                Padding(
                  padding: const EdgeInsets.all(8.0),
                  child: TextFormField(
                    initialValue: widget.todo.description,
                    maxLines: 3,
                    decoration: const InputDecoration(hintText: "Description"),
                    onChanged: (val) {
                      widget.todo.description = val;
                    },
                  ),
                ),
                Padding(
                    padding: const EdgeInsets.all(8.0),
                    child: CheckboxListTile(
                        title: const Text("Cette tâche est achevée !"),
                        value: widget.todo.isValid,
                        onChanged: (value) {
                          setState(() {
                            widget.todo.isValid = value!;
                          });
                        })),
                const SizedBox(
                  height: 15,
                ),
                Center(
                  child: Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      Expanded(
                        child: MaterialButton(
                            onPressed: () {
                              Navigator.pop(context);
                            },
                            elevation: 0,
                            color: const Color.fromARGB(255, 240, 240, 240),
                            shape: RoundedRectangleBorder(
                              borderRadius: BorderRadius.circular(7),
                            ),
                            padding: const EdgeInsets.symmetric(
                                horizontal: 20, vertical: 17),
                            child: const Row(
                              mainAxisAlignment: MainAxisAlignment.center,
                              children: [
                                Text(
                                  "Annuler",
                                  style: TextStyle(
                                    color: Colors.black87,
                                    fontSize: 15,
                                  ),
                                ),
                              ],
                            )),
                      ),
                      const SizedBox(
                        width: 8,
                      ),
                      Expanded(
                        child: MaterialButton(
                            onPressed: () async {
                              FocusScope.of(context).unfocus();
                              if (_keyForm.currentState!.validate()) {
                                setState(() {
                                  _isloading = true;
                                });
                                if (!updateState) {
                                  await valideAddTodo();
                                } else {
                                  valideUpdateTodo();
                                }
                              }
                            },
                            elevation: 0,
                            color: updateState
                                ? Colors.green[700]
                                : Colors.blue[700],
                            shape: RoundedRectangleBorder(
                              borderRadius: BorderRadius.circular(7),
                            ),
                            padding: const EdgeInsets.symmetric(
                                horizontal: 20, vertical: 17),
                            child: _isloading
                                ? Center(
                                    child: DataSyncLoading.loadingPulse(
                                        color: Colors.white,
                                        bg: Colors.transparent))
                                : Row(
                                    mainAxisAlignment: MainAxisAlignment.center,
                                    children: [
                                      Text(
                                        updateState ? "Modifier" : "Ajouter",
                                        style: const TextStyle(
                                          color: Colors.white,
                                          fontSize: 15,
                                        ),
                                      ),
                                    ],
                                  )),
                      ),
                    ],
                  ),
                ),
                const SizedBox(
                  height: 15,
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }

  valideAddTodo() async {
    bool state = await dataSync.post<Todo, bool>(
        context: context,
        fromJson: (map, statusCode) =>
            statusCode == 200 || statusCode == 201 ? true : false,
        url: "todos",
        data: widget.todo.toJSon());
    if (state) {
      setState(() {
        _isloading = false;
      });
      Navigator.pop(context);
    } else {
      setState(() {
        _isloading = false;
      });
    }
  }

  valideUpdateTodo() async {
    bool etat = await dataSync.put<Todo, bool>(
        context: context,
        fromJson: (map, statusCode) =>
            statusCode == 200 || statusCode == 201 ? true : false,
        url: "todos/${widget.todo.id}",
        data: widget.todo.toJSon());
    if (etat) {
      setState(() {
        _isloading = false;
      });
      Navigator.pop(context);
    } else {
      setState(() {
        _isloading = false;
      });
    }
  }
}

class Todo {
  int? id;
  String libelle = "";
  String description = "";
  bool isValid = false;

  Todo({required this.libelle, required this.description});

  factory Todo.fromJson(json) {
    Todo todo = Todo(
        libelle: json['libelle'] ?? "", description: json['description'] ?? "");
    todo.id = json['id'];
    todo.isValid = json['isValid'] ?? false;
    return todo;
  }

  Map<String, dynamic> toJSon() => {
        'libelle': libelle,
        'description': description,
        'isValid': isValid ? 1 : 0
      };
}
7
likes
140
pub points
0%
popularity

Publisher

unverified uploader

flutter_data_sync simplifies the mapping between Flutter app models and external data sources (API, DB). Easily transform JSON data into Dart objects and manage HTTP requests, reducing development time and improving maintainability.

Repository (GitLab)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

dio, flutter, fluttertoast, loading_indicator

More

Packages that depend on flutter_data_sync