kooza_flutter 2.0.5 copy "kooza_flutter: ^2.0.5" to clipboard
kooza_flutter: ^2.0.5 copied to clipboard

A blazingly fast, reactive, fully asynchronous and easy to use local database for flutter

example/lib/main.dart

import 'dart:async';

import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:kooza_flutter/kooza_flutter.dart';
import 'package:provider/provider.dart';

class Product {
  final String? id;
  final String? name;
  final double? price;
  const Product({this.id, this.name, this.price});

  Product copyWith({
    String? id,
    String? name,
    double? price,
  }) {
    return Product(
      id: id ?? this.id,
      name: name ?? this.name,
      price: price ?? this.price,
    );
  }

  factory Product.fromMap(Map<String, dynamic>? map, [String? id]) {
    if (map == null) return const Product();
    return Product(
      id: id,
      name: map['name'],
      price: (map['price'] as num?)?.toDouble(),
    );
  }

  Map<String, dynamic> toMap() {
    var map = <String, dynamic>{
      'id': id,
      'name': name,
      'price': price,
    };
    map.removeWhere((key, value) => value == null);
    return map;
  }
}

class ProductsState {
  final bool isDarkMode;
  final Product product;
  final List<Product> products;

  const ProductsState({
    this.isDarkMode = false,
    this.product = const Product(),
    this.products = const [],
  });

  ProductsState copyWith({
    bool? isDarkMode,
    Product? product,
    List<Product>? products,
  }) {
    return ProductsState(
      isDarkMode: isDarkMode ?? this.isDarkMode,
      product: product ?? this.product,
      products: products ?? this.products,
    );
  }
}

class ProductsBloc extends Cubit<ProductsState> {
  final Kooza _kooza;
  ProductsBloc(Kooza kooza)
      : _kooza = kooza,
        super(const ProductsState()) {
    streamDarkMode();
    streamProducts();
  }

  void setProductId(String? id) {
    emit(state.copyWith(product: state.product.copyWith(id: id)));
  }

  void setProductName(String? name) {
    emit(state.copyWith(product: state.product.copyWith(name: name)));
  }

  void setProductPrice(String? price) {
    final newPrice = double.tryParse(price ?? '0.0');
    emit(state.copyWith(product: state.product.copyWith(price: newPrice)));
  }

  StreamSubscription<List<Product>>? _producstsSub;
  void streamProducts() {
    final ref = _kooza.collection('my_products').snapshots();
    final productsStream = ref.map((collection) => collection.docs
        .map((doc) => Product.fromMap(doc.data, doc.id))
        .toList());
    _producstsSub?.cancel();

    int counter = 0;
    _producstsSub = productsStream.listen((products) {
      emit(state.copyWith(products: products));
      // ignore: avoid_print
      print('List of products: $products $counter');
      counter++;
    }, onError: (e) => kDebugMode ? print('Error: $e') : null);
  }

  void fetchProducts() async {
    try {
      await _producstsSub?.cancel();
      final ref = await _kooza.collection('my_products').get();
      final result =
          ref.docs.map((doc) => Product.fromMap(doc.data, doc.id)).toList();
      emit(state.copyWith(products: result));
    } catch (e) {
      if (kDebugMode) print('Error fetching products: $e');
    }
  }

  void saveProduct() async {
    try {
      final id = await _kooza
          .collection('my_products')
          .add(state.product.toMap(), ttl: const Duration(milliseconds: 3000));
      emit(state.copyWith(product: state.product.copyWith(id: id)));
    } catch (e) {
      if (kDebugMode) print('Error saving products: $e');
    }
  }

  void deleteProduct(String? id) async {
    try {
      if (id == null) return;
      await _kooza.collection('my_products').doc(id).delete();
    } catch (e) {
      if (kDebugMode) print('Error saving products: $e');
    }
  }

  void deleteAll() async {
    try {
      await _kooza.clear();
    } catch (e) {
      if (kDebugMode) print('Error saving products: $e');
    }
  }

  StreamSubscription? _darkmodeSub;
  void streamDarkMode() {
    _darkmodeSub?.cancel();
    _darkmodeSub = _kooza
        .singleDoc('appThemeData1')
        .snapshots<Map<String, dynamic>?>()
        .listen((event) {
      emit(state.copyWith(isDarkMode: event.data?['value']));
    });
  }

  void setDarkMode(bool value) async {
    try {
      await _kooza.singleDoc('appThemeData1').set<Map<String, dynamic>>(
          {'value': value},
          ttl: const Duration(milliseconds: 3000));
    } catch (e) {
      if (kDebugMode) print(e);
    }
  }

  @override
  Future<void> close() async {
    await _producstsSub?.cancel();
    return super.close();
  }
}

void main() async {
  final kooza = await Kooza.getInstance('example');
  runApp(AppDataProvider(kooza: kooza));
}

class AppDataProvider extends StatefulWidget {
  final Kooza kooza;
  const AppDataProvider({super.key, required this.kooza});

  @override
  State<AppDataProvider> createState() => _AppDataProviderState();
}

class _AppDataProviderState extends State<AppDataProvider> {
  @override
  void dispose() {
    widget.kooza.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return FutureProvider<int?>(
      initialData: null,
      create: (context) =>
          Future.delayed(const Duration(milliseconds: 5000), () => 20),
      child: BlocProvider(
        create: (c) => ProductsBloc(widget.kooza),
        child: const AppGeneralSetup(),
      ),
    );
  }
}

class AppGeneralSetup extends StatelessWidget {
  const AppGeneralSetup({super.key});
  @override
  Widget build(BuildContext context) {
    return BlocSelector<ProductsBloc, ProductsState, bool>(
      selector: (state) => state.isDarkMode,
      builder: (context, isDarkMode) => MaterialApp(
        debugShowCheckedModeBanner: false,
        title: 'Kooza Example App',
        theme: isDarkMode ? ThemeData.dark() : ThemeData.light(),
        home: const KoozaHomePage(),
      ),
    );
  }
}

class FormCreateProduct extends StatefulWidget {
  const FormCreateProduct({super.key});

  @override
  State<FormCreateProduct> createState() => _FormCreateProductState();
}

class _FormCreateProductState extends State<FormCreateProduct> {
  final _formKey = GlobalKey<FormState>();

  void _saveProduct(BuildContext context) {
    final formState = _formKey.currentState;
    if (formState?.validate() == true) {
      formState?.save();
      context.read<ProductsBloc>().saveProduct();
      formState?.reset();
    }
  }

  @override
  Widget build(BuildContext context) {
    final idField = BlocSelector<ProductsBloc, ProductsState, String?>(
      selector: (state) => state.product.id,
      builder: (context, id) => TextFormField(
        decoration: const InputDecoration(hintText: 'Product ID'),
        initialValue: id,
        onSaved: context.read<ProductsBloc>().setProductId,
      ),
    );

    final nameField = BlocSelector<ProductsBloc, ProductsState, String?>(
      selector: (state) => state.product.name,
      builder: (context, name) => TextFormField(
        decoration: const InputDecoration(hintText: 'Product Name'),
        initialValue: name,
        validator: (v) => (v?.trim().isEmpty ?? true) ? 'Add Name' : null,
        onSaved: context.read<ProductsBloc>().setProductName,
      ),
    );

    final priceField = BlocSelector<ProductsBloc, ProductsState, double?>(
      selector: (state) => state.product.price,
      builder: (context, price) => TextFormField(
        decoration: const InputDecoration(hintText: 'Product Price'),
        initialValue: price?.toString(),
        onSaved: context.read<ProductsBloc>().setProductPrice,
      ),
    );

    final saveBtn = TextButton(
      onPressed: () => _saveProduct(context),
      child: const Padding(padding: EdgeInsets.all(8.0), child: Text("Save")),
    );

    final fields = Padding(
      padding: const EdgeInsets.all(40.0),
      child: Column(children: [idField, nameField, priceField, saveBtn]),
    );

    return Form(key: _formKey, child: fields);
  }
}

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

  @override
  Widget build(BuildContext context) {
    return BlocSelector<ProductsBloc, ProductsState, List<Product>>(
      selector: (state) => state.products,
      builder: (context, products) => ListView.builder(
        itemCount: products.length,
        itemBuilder: (context, index) => ListTile(
          leading: IconButton(
            onPressed: () =>
                context.read<ProductsBloc>().deleteProduct(products[index].id),
            icon: const Icon(Icons.delete),
          ),
          trailing: Text(products[index].price?.toString() ?? '0.0'),
          title: Text(products[index].name ?? ''),
          subtitle: Text(products[index].id ?? ''),
        ),
      ),
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    final darkModeBtn = BlocSelector<ProductsBloc, ProductsState, bool>(
      selector: (state) => state.isDarkMode,
      builder: (context, state) => Switch(
        onChanged: (v) => context.read<ProductsBloc>().setDarkMode(v),
        value: state,
      ),
    );

    final deleteAllBtn = IconButton(
      onPressed: () => context.read<ProductsBloc>().deleteAll(),
      icon: const Icon(Icons.delete),
    );

    final data = context.watch<int?>();
    return Scaffold(
      appBar: AppBar(
        title: Text('Kooza Example App $data'),
        actions: [darkModeBtn, deleteAllBtn],
      ),
      body: Column(
        children: const [
          FormCreateProduct(),
          Expanded(child: ListProducts()),
        ],
      ),
    );
  }
}

class ProductInputField extends StatelessWidget {
  final void Function(String? value) onSaved;
  final String hint;

  const ProductInputField({
    super.key,
    required this.onSaved,
    required this.hint,
  });

  @override
  Widget build(BuildContext context) {
    return TextFormField(
      decoration: InputDecoration(hintText: hint),
      onSaved: onSaved,
    );
  }
}
1
likes
140
pub points
36%
popularity

Publisher

verified publisherlaams.io

A blazingly fast, reactive, fully asynchronous and easy to use local database for flutter

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (LICENSE)

Dependencies

flutter, hive, hive_flutter, rxdart, shared_preferences

More

Packages that depend on kooza_flutter