187 lines
6.1 KiB
Dart
187 lines
6.1 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
|
import '../providers/dashboard_providers.dart';
|
|
import '../../../widgets/error_view.dart';
|
|
|
|
class SettingsScreen extends ConsumerWidget {
|
|
const SettingsScreen({super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
final async = ref.watch(brandSettingsProvider);
|
|
|
|
return Scaffold(
|
|
appBar: AppBar(title: const Text('Brand Settings')),
|
|
body: async.when(
|
|
loading: () => const Center(child: CircularProgressIndicator()),
|
|
error: (e, _) => ErrorView(
|
|
message: 'Failed to load settings',
|
|
onRetry: () => ref.invalidate(brandSettingsProvider),
|
|
),
|
|
data: (settings) => _SettingsForm(settings: settings),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class _SettingsForm extends ConsumerStatefulWidget {
|
|
final dynamic settings;
|
|
|
|
const _SettingsForm({required this.settings});
|
|
|
|
@override
|
|
ConsumerState<_SettingsForm> createState() => _SettingsFormState();
|
|
}
|
|
|
|
class _SettingsFormState extends ConsumerState<_SettingsForm> {
|
|
final _formKey = GlobalKey<FormState>();
|
|
bool _loading = false;
|
|
|
|
late final _displayName =
|
|
TextEditingController(text: widget.settings.displayName as String);
|
|
late final _tagline =
|
|
TextEditingController(text: widget.settings.tagline as String?);
|
|
late final _email =
|
|
TextEditingController(text: widget.settings.publicEmail as String?);
|
|
late final _phone =
|
|
TextEditingController(text: widget.settings.publicPhone as String?);
|
|
late final _city =
|
|
TextEditingController(text: widget.settings.publicCity as String?);
|
|
late final _country =
|
|
TextEditingController(text: widget.settings.publicCountry as String?);
|
|
late final _website =
|
|
TextEditingController(text: widget.settings.websiteUrl as String?);
|
|
late final _whatsapp =
|
|
TextEditingController(text: widget.settings.whatsappNumber as String?);
|
|
late bool _listed = widget.settings.isListedOnMarketplace as bool;
|
|
|
|
@override
|
|
void dispose() {
|
|
for (final c in [
|
|
_displayName, _tagline, _email, _phone, _city, _country, _website, _whatsapp
|
|
]) {
|
|
c.dispose();
|
|
}
|
|
super.dispose();
|
|
}
|
|
|
|
Future<void> _submit() async {
|
|
if (!_formKey.currentState!.validate()) return;
|
|
setState(() => _loading = true);
|
|
try {
|
|
await ref.read(settingsServiceProvider).updateBrand({
|
|
'displayName': _displayName.text.trim(),
|
|
if (_tagline.text.isNotEmpty) 'tagline': _tagline.text.trim(),
|
|
if (_email.text.isNotEmpty) 'publicEmail': _email.text.trim(),
|
|
if (_phone.text.isNotEmpty) 'publicPhone': _phone.text.trim(),
|
|
if (_city.text.isNotEmpty) 'publicCity': _city.text.trim(),
|
|
if (_country.text.isNotEmpty) 'publicCountry': _country.text.trim(),
|
|
if (_website.text.isNotEmpty) 'websiteUrl': _website.text.trim(),
|
|
if (_whatsapp.text.isNotEmpty) 'whatsappNumber': _whatsapp.text.trim(),
|
|
'isListedOnMarketplace': _listed,
|
|
});
|
|
ref.invalidate(brandSettingsProvider);
|
|
if (mounted) {
|
|
ScaffoldMessenger.of(context).showSnackBar(
|
|
const SnackBar(content: Text('Settings saved')));
|
|
}
|
|
} catch (e) {
|
|
if (mounted) {
|
|
ScaffoldMessenger.of(context)
|
|
.showSnackBar(SnackBar(content: Text('Error: $e')));
|
|
}
|
|
} finally {
|
|
if (mounted) setState(() => _loading = false);
|
|
}
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Form(
|
|
key: _formKey,
|
|
child: ListView(
|
|
padding: const EdgeInsets.all(16),
|
|
children: [
|
|
_section('Brand', [
|
|
_field('Display Name', _displayName, required: true),
|
|
_field('Tagline', _tagline),
|
|
]),
|
|
const SizedBox(height: 16),
|
|
_section('Contact', [
|
|
_field('Public Email', _email,
|
|
inputType: TextInputType.emailAddress),
|
|
_field('Public Phone', _phone, inputType: TextInputType.phone),
|
|
_field('WhatsApp Number', _whatsapp,
|
|
inputType: TextInputType.phone),
|
|
_field('Website URL', _website, inputType: TextInputType.url),
|
|
]),
|
|
const SizedBox(height: 16),
|
|
_section('Location', [
|
|
_field('City', _city),
|
|
_field('Country', _country),
|
|
]),
|
|
const SizedBox(height: 16),
|
|
Card(
|
|
child: SwitchListTile(
|
|
title: const Text('Listed on Marketplace'),
|
|
subtitle: const Text(
|
|
'Show your fleet on the public marketplace',
|
|
),
|
|
value: _listed,
|
|
onChanged: (v) => setState(() => _listed = v),
|
|
),
|
|
),
|
|
const SizedBox(height: 24),
|
|
ElevatedButton(
|
|
onPressed: _loading ? null : _submit,
|
|
style: ElevatedButton.styleFrom(
|
|
minimumSize: const Size.fromHeight(48),
|
|
),
|
|
child: _loading
|
|
? const SizedBox(
|
|
width: 20,
|
|
height: 20,
|
|
child: CircularProgressIndicator(strokeWidth: 2))
|
|
: const Text('Save Settings'),
|
|
),
|
|
],
|
|
),
|
|
);
|
|
}
|
|
|
|
Widget _section(String title, List<Widget> children) {
|
|
return Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Text(title,
|
|
style: const TextStyle(
|
|
fontSize: 13,
|
|
fontWeight: FontWeight.w600,
|
|
color: Color(0xFF6B7280))),
|
|
const SizedBox(height: 10),
|
|
Card(
|
|
child: Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
|
child: Column(children: children),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
}
|
|
|
|
Widget _field(String label, TextEditingController ctrl,
|
|
{bool required = false, TextInputType? inputType}) {
|
|
return Padding(
|
|
padding: const EdgeInsets.symmetric(vertical: 8),
|
|
child: TextFormField(
|
|
controller: ctrl,
|
|
keyboardType: inputType,
|
|
decoration: InputDecoration(labelText: label),
|
|
validator: required
|
|
? (v) => v == null || v.isEmpty ? 'Required' : null
|
|
: null,
|
|
),
|
|
);
|
|
}
|
|
}
|