init: rough companion app stub

This commit is contained in:
2026-05-07 18:35:58 +02:00
commit 5f017ac05d
73 changed files with 3520 additions and 0 deletions
@@ -0,0 +1,60 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import '../../providers.dart';
class SensorDetailScreen extends ConsumerWidget {
const SensorDetailScreen({super.key, required this.sensorId});
final String sensorId;
@override
Widget build(BuildContext context, WidgetRef ref) {
// TODO: fetch sensor via sensorRepositoryProvider.getSensor(sensorId).
return Scaffold(
appBar: AppBar(title: Text('Sensor $sensorId')),
body: Padding(
padding: const EdgeInsets.all(24),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
// TODO: display sensor fields (name, status, position, last seen).
const Placeholder(fallbackHeight: 200),
const SizedBox(height: 24),
OutlinedButton.icon(
icon: const Icon(Icons.map_outlined),
label: const Text('Locate on floor plan'),
onPressed: () {
ref.read(selectedSensorIdProvider.notifier).state = sensorId;
context.go('/floorplan');
},
),
const SizedBox(height: 12),
// TODO: re-provision button → show BleProvisionSheet pre-filled.
OutlinedButton.icon(
icon: const Icon(Icons.bluetooth),
label: const Text('Re-provision WiFi'),
onPressed: () {}, // TODO
),
const SizedBox(height: 12),
OutlinedButton.icon(
icon: const Icon(Icons.edit_outlined),
label: const Text('Rename'),
onPressed: () {}, // TODO
),
const Spacer(),
TextButton(
style: TextButton.styleFrom(
foregroundColor: Theme.of(context).colorScheme.error,
),
onPressed: () {}, // TODO: confirm dialog then delete
child: const Text('Delete sensor'),
),
],
),
),
);
}
}
@@ -0,0 +1,52 @@
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import '../../providers.dart';
import '../ble_provision/ble_provision_sheet.dart';
class SensorListScreen extends ConsumerWidget {
const SensorListScreen({super.key});
@override
Widget build(BuildContext context, WidgetRef ref) {
// TODO: replace Placeholder with AsyncValue-driven list.
// final sensors = ref.watch(sensorsProvider); // define a FutureProvider
final selectedId = ref.watch(selectedSensorIdProvider);
return Scaffold(
appBar: AppBar(title: const Text('Sensors')),
body: Column(
children: [
if (selectedId != null)
MaterialBanner(
content: Text('Sensor $selectedId selected on floor plan'),
actions: [
TextButton(
onPressed: () =>
ref.read(selectedSensorIdProvider.notifier).state = null,
child: const Text('Dismiss'),
),
TextButton(
onPressed: () => context.push('/sensors/$selectedId'),
child: const Text('Open'),
),
],
),
// TODO: ListView.builder with sensor tiles.
// Highlight tile whose id == selectedId.
const Expanded(child: Placeholder()),
],
),
floatingActionButton: FloatingActionButton(
onPressed: () => showModalBottomSheet<void>(
context: context,
isScrollControlled: true,
builder: (_) => const BleProvisionSheet(),
),
child: const Icon(Icons.add),
),
);
}
}