smart_design_system 0.0.9 copy "smart_design_system: ^0.0.9" to clipboard
smart_design_system: ^0.0.9 copied to clipboard

Design system for SmartDash.

example/lib/main.dart

import 'dart:async';
import 'dart:developer';

import 'package:dartz/dartz.dart';
import 'package:flutter/material.dart';
import 'package:smart_design_system/generic_features/core/domain/entities/feature_initial_action.dart';
import 'package:smart_design_system/generic_features/core/domain/entities/smart_controller.dart';
import 'package:smart_design_system/generic_features/core/domain/repositories/smart_repository.dart';
import 'package:smart_design_system/generic_features/smart/smart_feature_builder.dart';
import 'package:smart_design_system/theme/extensions/custom_theme.dart';
import 'package:smart_design_system/theme/theme_data/custom_text_styles.dart';
import 'package:smart_design_system/theme/theme_data/smart_color.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(extensions: [MyTheme().themeExtension]),
      title: 'Flutter Demo',
      home: ExamplePage(),
    );
  }
}

class ExamplePage extends StatelessWidget {
  ExamplePage({super.key});

  final listController = SmartController<void, List<String>>(
    listener: (state) => log(state.toString()),
  );

  final submitController = SmartController<int, String>(
    listener: (state) => log(state.toString()),
  );

  final submitControllerWithDS = SmartController<int, String>(
    listener: (state) => log(state.toString()),
  );

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Personas Page')),
      body: Column(
        children: [
          const Text('Submit data without dialog using DS - rebuilding the button'),
          _buildSubmitDSButtonWithoutDialog(),
          const Text('Submit data without dialog - rebuilding the button'),
          _buildSubmitButtonWithoutDialog(),
          const Text('Dialog button using DS'),
          _buildSubmitDSButton(context),
          const Text('Dialog button using builder'),
          _buildSubmitButton(context),
          const Text('List of Personas'),
          TextButton(
            onPressed: () => listController.call(null),
            child: const Text('Refresh'),
          ),
          Expanded(child: _buildPersonasList()),
        ],
      ),
    );
  }

  Widget _buildPersonasList() {
    return SmartFeatureBuilder.build<void, List<String>>(
      repository: MockPersonasRepository(),
      initialAction: const FeatureInitialAction.call(null),
      controller: listController,
      builder: (context, state) {
        return state.when(
          initial: () => const Center(child: Text('Press the button to load data')),
          fail: () => const Center(child: Text('Failed to load')),
          loading: () => const CircularProgressIndicator.adaptive(),
          success: (data) => ListView.builder(
            itemCount: data.length,
            itemBuilder: (context, index) => ListTile(title: Text(data[index])),
          ),
        );
      },
    );
  }

  Widget _buildSubmitDSButtonWithoutDialog() {
    return TextButton(
      onPressed: () => submitControllerWithDS.call(1),
      child: SmartFeatureBuilder.buildWithDesignSystem<int, String>(
        repository: MockSubmitRepository(),
        controller: submitControllerWithDS,
        listener: (context, state) {
          state.whenOrNull(
            success: (data) => ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(data))),
            fail: () => ScaffoldMessenger.of(context).showSnackBar(
              const SnackBar(content: Text('Failed to submit data')),
            ),
          );
        },
        initial: (context) => const Center(child: Text('Press to submit data')),
        success: (context, result) => const Center(child: Text('Press to submit data')),
      ),
    );
  }

  Widget _buildSubmitButtonWithoutDialog() {
    return TextButton(
      onPressed: () => submitController.call(1),
      child: SmartFeatureBuilder.build<int, String>(
        repository: MockSubmitRepository(),
        controller: submitController,
        listener: (context, state) {
          state.whenOrNull(
            success: (data) => ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(data))),
            fail: () => ScaffoldMessenger.of(context).showSnackBar(
              const SnackBar(content: Text('Failed to submit data')),
            ),
          );
        },
        builder: (context, state) {
          return state.maybeWhen(
            orElse: () => const Center(child: Text('Press to submit data')),
            loading: () => const CircularProgressIndicator.adaptive(),
          );
        },
      ),
    );
  }

  Widget _buildSubmitDSButton(BuildContext context) {
    return TextButton(
      onPressed: () {
        SmartFeatureBuilder.submitDialogWithDesignSystem<int, String>(
          context: context,
          repository: MockSubmitRepository(),
          initialAction: const FeatureInitialAction.call(1),
          dismissible: true,
          listener: (context, state) {
            state.whenOrNull(
              success: (data) => ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(data))),
              fail: () => ScaffoldMessenger.of(context).showSnackBar(
                const SnackBar(content: Text('Failed to submit data')),
              ),
            );
          },
        );
      },
      child: const Text('submit dialog'),
    );
  }

  Widget _buildSubmitButton(BuildContext context) {
    return TextButton(
      child: const Text('submit dialog'),
      onPressed: () {
        SmartFeatureBuilder.submitDialog<int, String>(
          context: context,
          repository: MockSubmitRepository(),
          initialAction: const FeatureInitialAction.call(1),
          dismissible: true,
          builder: (context, state, onClose) {
            return state.when(
              initial: SizedBox.shrink,
              loading: () => const CircularProgressIndicator.adaptive(),
              fail: () => const Center(child: Text('Failed to submit data')),
              success: (data) => Column(
                mainAxisSize: MainAxisSize.min,
                children: [const Text('Success'), TextButton(onPressed: onClose, child: const Text('Close'))],
              ),
            );
          },
        );
      },
    );
  }
}

class MockPersonasRepository implements SmartRepository<void, List<String>> {
  @override
  Future<Either<SmartFailure, List<String>>> call(void data) async {
    await Future.delayed(const Duration(seconds: 2));
    return const Right(['Person 1', 'Person 2', 'Person 3']);
  }
}

class MockSubmitRepository implements SmartRepository<int, String> {
  @override
  Future<Either<SmartFailure, String>> call(int data) async {
    await Future.delayed(const Duration(seconds: 2));
    // return Left(SmartFailure());
    return const Right('Data submitted');
  }
}

class MyTheme extends CustomTheme {
  @override
  CustomThemeExtension get themeExtension {
    return CustomThemeExtension(
      primary: SmartColor(main: Colors.deepPurple),
      secondary: SmartColor(main: Colors.deepPurpleAccent),
      success: SmartColor(main: Colors.green),
      danger: SmartColor(main: Colors.red),
      warning: SmartColor(main: Colors.orange),
      info: SmartColor(main: Colors.cyan),
      neutral: SmartOpacityColor(main: Colors.black),
      textStyles: CustomTextStyles(
        h1: CustomTextStyle(value: const TextStyle(fontSize: 64)),
        h2: CustomTextStyle(value: const TextStyle(fontSize: 48)),
        h3: CustomTextStyle(value: const TextStyle(fontSize: 40)),
        h4: CustomTextStyle(value: const TextStyle(fontSize: 36)),
        h5: CustomTextStyle(value: const TextStyle(fontSize: 32)),
        h6: CustomTextStyle(value: const TextStyle(fontSize: 24)),
        title: CustomTextStyle(value: const TextStyle(fontSize: 20)),
        subtitle: CustomTextStyle(value: const TextStyle(fontSize: 18)),
        body: CustomTextStyle(value: const TextStyle(fontSize: 14)),
        label: CustomTextStyle(value: const TextStyle(fontSize: 12)),
        caption: CustomTextStyle(value: const TextStyle(fontSize: 10)),
        button: CustomTextStyle(value: const TextStyle(fontSize: 10)),
      ),
    );
  }
}