From 151bfa1bd3e7c9e83f99fba50cf5edf982c9254b Mon Sep 17 00:00:00 2001
From: allez_ryan_venga <120065584+MiAmigoRyan@users.noreply.github.com>
Date: Tue, 22 Jul 2025 13:52:55 -0600
Subject: [PATCH 1/2] Ryan Arment Interview Project PR
---
.vscode/settings.json | 3 +
.../reports/problems/problems-report.html | 663 ++++++++++++++++++
devtools_options.yaml | 3 +
lib/home.dart | 126 ++++
lib/home_wrapper.dart | 19 +
lib/main.dart | 9 +-
lib/sensor_bloc.dart | 66 ++
lib/sensor_event.dart | 54 ++
lib/sensor_state.dart | 20 +
9 files changed, 958 insertions(+), 5 deletions(-)
create mode 100644 .vscode/settings.json
create mode 100644 android/build/reports/problems/problems-report.html
create mode 100644 devtools_options.yaml
create mode 100644 lib/home.dart
create mode 100644 lib/home_wrapper.dart
create mode 100644 lib/sensor_bloc.dart
create mode 100644 lib/sensor_event.dart
create mode 100644 lib/sensor_state.dart
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..0e14d8e
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,3 @@
+{
+ "java.configuration.updateBuildConfiguration": "disabled"
+}
\ No newline at end of file
diff --git a/android/build/reports/problems/problems-report.html b/android/build/reports/problems/problems-report.html
new file mode 100644
index 0000000..3993393
--- /dev/null
+++ b/android/build/reports/problems/problems-report.html
@@ -0,0 +1,663 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ Gradle Configuration Cache
+
+
+
+
+
+
+ Loading...
+
+
+
+
+
+
+
diff --git a/devtools_options.yaml b/devtools_options.yaml
new file mode 100644
index 0000000..fa0b357
--- /dev/null
+++ b/devtools_options.yaml
@@ -0,0 +1,3 @@
+description: This file stores settings for Dart & Flutter DevTools.
+documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
+extensions:
diff --git a/lib/home.dart b/lib/home.dart
new file mode 100644
index 0000000..0c4d3fb
--- /dev/null
+++ b/lib/home.dart
@@ -0,0 +1,126 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'sensor_bloc.dart';
+import 'sensor_state.dart';
+import 'sensor_event.dart';
+import 'model/sensor.dart';
+
+class HomeScreen extends StatefulWidget {
+ const HomeScreen({super.key});
+
+ @override
+ State createState() => _HomeScreenState();
+}
+
+class _HomeScreenState extends State {
+ String searchQuery = '';
+
+
+
+ @override
+ Widget build(BuildContext context) {
+
+
+ void _showEditDialog(Sensor sensor) {
+
+ final nameController = TextEditingController(text: sensor.name);
+ final descController = TextEditingController(text: sensor.description);
+
+ final bloc = context.read();
+
+
+ showDialog(
+ context: context,
+ builder: (context) => AlertDialog(
+ title: Text('Edit Sensor ${sensor.id}'),
+ content: Column(
+ mainAxisSize: MainAxisSize.min,
+ children: [
+ TextField(controller: nameController, decoration: const InputDecoration(labelText: 'Name')),
+ TextField(controller: descController, decoration: const InputDecoration(labelText: 'Description')),
+ ],
+ ),
+ actions: [
+ TextButton(
+ onPressed: () => Navigator.pop(context),
+ child: const Text('Cancel'),
+ ),
+ ElevatedButton(
+ onPressed: () {
+
+
+ bloc.add(
+ EditSensorDetails(sensor.id, nameController.text, descController.text),
+ ); print('pressed');
+
+ Navigator.pop(context);
+ },
+ child: const Text('Save'),
+ ),
+ ],
+ ),
+ );
+ }
+ return Scaffold(
+ appBar: AppBar(
+ title: const Text('Thermal Sensors'),
+ bottom: PreferredSize(
+ preferredSize: const Size.fromHeight(50),
+ child: Padding(
+ padding: const EdgeInsets.all(8.0),
+ child: TextField(
+ onChanged: (val) => setState(() => searchQuery = val),
+ decoration: InputDecoration(
+ hintText: 'Search by name or description...',
+ prefixIcon: const Icon(Icons.search),
+ border: OutlineInputBorder(borderRadius: BorderRadius.circular(8)),
+ ),
+ ),
+ ),
+ ),
+ ),
+ body: BlocBuilder(
+ builder: (context, state) {
+ final filteredSensors = state.sensors.where((sensor) {
+ final q = searchQuery.toLowerCase();
+ return sensor.name.toLowerCase().contains(q) ||
+ sensor.description.toLowerCase().contains(q);
+ }).toList();
+
+ if (filteredSensors.isEmpty) {
+ return const Center(child: Text('No sensors found.'));
+ }
+
+ return ListView.builder(
+ itemCount: filteredSensors.length,
+ itemBuilder: (context, index) {
+ final sensor = filteredSensors[index];
+ return ListTile(
+ title: Text('${sensor.name} (${sensor.id})'),
+ subtitle: Text('Value: ${sensor.value.toStringAsFixed(2)}\n${sensor.description}'),
+ isThreeLine: true,
+ trailing: Wrap(
+ spacing: 8,
+ children: [
+ IconButton(
+ icon: const Icon(Icons.refresh),
+ tooltip: 'Update Sensor',
+ onPressed: () {
+ context.read().add(UpdateSensorValue(sensor));
+ },
+ ),
+ IconButton(
+ icon: const Icon(Icons.edit),
+ tooltip: 'Edit Sensor',
+ onPressed: () => _showEditDialog(sensor),
+ ),
+ ],
+ ),
+ );
+ },
+ );
+ },
+ ),
+ );
+ }
+}
diff --git a/lib/home_wrapper.dart b/lib/home_wrapper.dart
new file mode 100644
index 0000000..ce58129
--- /dev/null
+++ b/lib/home_wrapper.dart
@@ -0,0 +1,19 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'sensor_bloc.dart';
+import 'repository/sensor_repository.dart';
+import 'sensor_event.dart';
+import 'home.dart';
+
+class HomeWrapper extends StatelessWidget {
+ const HomeWrapper({super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return BlocProvider(
+ create: (context) => SensorBloc(SensorRepository())
+ ..add(StartSensorUpdates()),
+ child: const HomeScreen(),
+ );
+ }
+}
diff --git a/lib/main.dart b/lib/main.dart
index 927a1e0..69e69cb 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
+import 'home_wrapper.dart';
void main() {
runApp(const MyApp());
@@ -10,11 +11,9 @@ class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
- title: 'Flutter Demo',
- theme: ThemeData(
- colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
- ),
- home: Placeholder(),
+ title: 'Sensor App',
+ theme: ThemeData(primarySwatch: Colors.blue),
+ home: const HomeWrapper(),
);
}
}
diff --git a/lib/sensor_bloc.dart b/lib/sensor_bloc.dart
new file mode 100644
index 0000000..a34fe9a
--- /dev/null
+++ b/lib/sensor_bloc.dart
@@ -0,0 +1,66 @@
+import 'dart:async';
+import 'package:flutter_bloc/flutter_bloc.dart';
+import 'sensor_event.dart';
+import 'sensor_state.dart';
+import 'repository/sensor_repository.dart';
+import 'model/sensor.dart';
+import 'dart:math';
+
+class SensorBloc extends Bloc {
+
+ final SensorRepository repository;
+ late final StreamSubscription _sensorSub;
+
+ SensorBloc(this.repository) : super(const SensorState()) {
+ on((event, emit) {
+ repository.initializeSensors();
+ _sensorSub = repository.sensorsStream.listen(
+ (sensorList) => add(SensorsUpdated(sensorList)),
+ );
+ });
+
+ on((event, emit) {
+ emit(state.copyWith(
+ sensors: event.sensors,
+ searchQuery: state.searchQuery
+ ));
+ });
+
+ on((event, emit) {
+ repository.updateSensor(event.sensor);
+ final updatedSensors = List.from(state.sensors);
+ final index = updatedSensors.indexWhere((s) => s.id == event.sensor.id);
+ if (index != -1) {
+ updatedSensors[index] = event.sensor;
+ emit(state.copyWith(
+ sensors: updatedSensors,
+ searchQuery: state.searchQuery,
+ ));
+ }
+ });
+
+ on((event, emit) {
+ repository.updateSensor(event.sensor.copyWith(value: 72));
+ });
+
+
+ on((event,emit){
+ emit(state.copyWith(searchQuery: event.query));
+ });
+
+ on((event, emit) {
+ final sensor = state.sensors.firstWhere((s) => s.id == event.sensorId);
+ final updated = sensor.copyWith(
+ name: event.sensorName,
+ description: event.sensorDescription
+ );
+ repository.updateSensor(updated);
+ });
+
+ @override
+ Future close() {
+ _sensorSub.cancel();
+ return super.close();
+ }
+}
+}
\ No newline at end of file
diff --git a/lib/sensor_event.dart b/lib/sensor_event.dart
new file mode 100644
index 0000000..f4531f8
--- /dev/null
+++ b/lib/sensor_event.dart
@@ -0,0 +1,54 @@
+import 'package:equatable/equatable.dart';
+import 'model/sensor.dart';
+
+abstract class SensorEvent extends Equatable {
+ const SensorEvent();
+ @override
+ List