Tutorial LAravel API
Published
•3 min readINi 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
| test | hds | sd |
| sj | hsd | shj |
| sjdh | hsjd | jhd |