Skip to main content

Command Palette

Search for a command to run...

Tutorial LAravel API

Published
3 min read

INi kode Client Dart nya:

import 'package:app/widgets/custom_rounded_button.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

import '../bloc/rfid_shared_bloc.dart';

abstract class RfidSharedWidget {
  static void showConfig({
    required BuildContext context,
    required String keyConfig,
    RfidSharedBloc? bloc
  }) {
    showModalBottomSheet(
      context: context,
      isScrollControlled: true,
      backgroundColor: Colors.transparent,
      builder: (_) {
        if (bloc != null) {
          return BlocProvider.value(
            value: bloc..add(OnCheckSupport(keyConfig: keyConfig)),
            child: _RfidConfigView(),
          );
        }
        return BlocProvider(
          create: (_) => RfidSharedBloc()
            ..add(OnCheckSupport(keyConfig: keyConfig, )),
          child:  _RfidConfigView(),
        );
      },
    );
  }
}

class _RfidConfigView extends StatelessWidget {
  const _RfidConfigView();


  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);

    return Container(
      padding: EdgeInsets.only(
        left: 16,
        right: 16,
        top: 12,
        bottom: MediaQuery.of(context).viewInsets.bottom + 16,
      ),
      decoration: BoxDecoration(
        color: theme.colorScheme.surface,
        borderRadius: const BorderRadius.vertical(
          top: Radius.circular(20),
        ),
      ),
      child: BlocBuilder<RfidSharedBloc, RfidSharedState>(
        builder: (context, state) {
          if (state.isLoadingCheck) {
            return const SizedBox(
              height: 220,
              child: Center(child: CircularProgressIndicator()),
            );
          }

          if (!state.isRfidSupported) {
            return const Padding(
              padding: EdgeInsets.all(24),
              child: Center(
                child: Text(
                  'RFID tidak didukung di device ini',
                  style: TextStyle(fontSize: 16),
                ),
              ),
            );
          }

          final isDirty =
              state.draftWorkArea != state.currentWorkArea ||
                  state.draftPower != state.currentPower;

          return Column(
            mainAxisSize: MainAxisSize.min,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              // Drag handle
              Center(
                child: Container(
                  width: 40,
                  height: 4,
                  margin: const EdgeInsets.only(bottom: 12),
                  decoration: BoxDecoration(
                    color: Colors.grey.shade400,
                    borderRadius: BorderRadius.circular(4),
                  ),
                ),
              ),

              const Center(
                child: Text(
                  'RFID Configuration',
                  style: TextStyle(
                    fontSize: 18,
                    fontWeight: FontWeight.w600,
                  ),
                ),
              ),

              const SizedBox(height: 12),
              const Divider(),

              _section(
                title: 'Work Area',
                child: _buildDropdown(
                  value: state.draftWorkArea,
                  items: state.workAreas,
                  onChanged: (v) {
                    context.read<RfidSharedBloc>().add(
                      OnUpdateDraft(area: v),
                    );
                  },
                ),
              ),
              _section(
                title: 'Power',
                child: _buildPowerDropdown(
                  context,
                  value: state.draftPower,
                  powers: state.powers,
                ),
              ),

              const SizedBox(height: 16),
              _buildActionButtons(context, isDirty, ),
            ],
          );
        },
      ),
    );
  }

  // ================= UI Helpers =================

  static Widget _section({
    required String title,
    required Widget child,
  }) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 8),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Text(
            title,
            style: const TextStyle(
              fontWeight: FontWeight.w500,
              fontSize: 14,
            ),
          ),
          const SizedBox(height: 6),
          child,
        ],
      ),
    );
  }

  static Widget _buildDropdown({
    required int value,
    required Map<String, int> items,
    required ValueChanged<int?> onChanged,
  }) {
    return DropdownButtonFormField<int>(
      initialValue: value,
      isExpanded: true,
      decoration: const InputDecoration(
        border: OutlineInputBorder(),
        isDense: true,
      ),
      items: items.entries
          .map(
            (e) => DropdownMenuItem(
          value: e.value,
          child: Text(e.key),
        ),
      )
          .toList(),
      onChanged: onChanged,
    );
  }

  static Widget _buildPowerDropdown(
      BuildContext context, {
        required int value,
        required List<int> powers,
      }) {
    return DropdownButtonFormField<int>(
      initialValue: value,
      isExpanded: true,
      decoration: const InputDecoration(
        border: OutlineInputBorder(),
        isDense: true,
      ),
      items: powers
          .map(
            (p) => DropdownMenuItem(
          value: p,
          child: Text('$p dBm'),
        ),
      )
          .toList(),
      onChanged: (v) {
        context.read<RfidSharedBloc>().add(
          OnUpdateDraft(power: v),
        );
      },
    );
  }

  // ================= Action Buttons =================

  static Widget _buildActionButtons(
      BuildContext context,
      bool isDirty,
      ) {
    return Row(
      children: [
        Expanded(
          child: CustomRoundedButton(
            color: Colors.orange,
            onPressed: () {
              // Cancel → rollback automatically
              Navigator.of(context).pop();
            },
            label: 'Cancel',
          ),
        ),
        const SizedBox(width: 12),
        Expanded(
          child: CustomRoundedButton(
            onPressed: () {
              context.read<RfidSharedBloc>().add(
                const OnResetDraft(),
              );
            },
            isSecondary: true,
            label: 'Reset',
          ),
        ),
        const SizedBox(width: 12),
        Expanded(
          child: CustomRoundedButton(
            onPressed: isDirty
                ? () {
              context.read<RfidSharedBloc>().add(
                 OnApplyConfig(),
              );
              Navigator.of(context).pop();
            }
                : null,
            label: 'Save',
          ),
        ),
      ],
    );
  }
}

hz kan

aok

sip sip

Hello

testhdssd
sjhsdshj
sjdhhsjdjhd