Compare commits

...

20 Commits

Author SHA1 Message Date
534eed98e9 Setup new firebase project in the web platform. 2025-07-13 13:30:35 +03:00
4fd46d820d Dev (#335)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Jira Ticket


## Description

hot fix thermostat as requested by Talal

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ]  New feature (non-breaking change which adds functionality)
- [x] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-07-02 08:38:23 +03:00
8534cb3045 Created decorators for energy management charts to divide values by 100, and modified the intervals. 2025-07-01 18:56:17 +03:00
fcaed3e4e3 Divide energy consumption chart values by hundred (#333)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Description

Divide energy consumption chart values by hundred

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ]  New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [x]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-07-01 16:33:43 +03:00
445d4facab Refactor TotalEnergyConsumptionBloc to use DividedTotalEnergyConsumptionDecorator for adjusted energy values and update chart data handling in TotalEnergyConsumptionChart. 2025-07-01 16:28:52 +03:00
b159c4f052 Dev (#326)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->


## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [x]  New feature (non-breaking change which adds functionality)
- [x] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-06-30 15:57:06 +03:00
6afebdfef8 Analytics empty state (#320)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Description

Analytics Empty State.

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [x]  New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-06-30 15:31:12 +03:00
a24630b3eb Dev (#324)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Description

<!--- Describe your changes in detail -->

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ]  New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-06-30 15:26:10 +03:00
4768b4a89e fix touch gangs realtime. (#322)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Jira Ticket
[SP-0000](https://syncrow.atlassian.net/browse/SP-0000)

## Description

<!--- Describe your changes in detail -->

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ]  New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-06-30 13:58:33 +03:00
11cf992a1a Dev (#319)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [x]  New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-06-30 11:57:35 +03:00
774a1533f5 Dev (#314)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Description

Release


## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [x]  New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-06-29 16:47:14 +03:00
403b45c826 show aqi tab on analytics page. 2025-06-29 10:58:16 +03:00
ed2b91d380 MVP release (#306)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Description

MVP Release

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [x]  New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-06-29 10:56:48 +03:00
5bb3688a51 Dev (#276)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->
## Description

analytics hotfixes.

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ]  New feature (non-breaking change which adds functionality)
- [x] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-06-19 11:26:43 +03:00
d6fcf051c6 Dev (#273)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Jira Ticket
remove duplicate Feature from space Management  

## Description

no need for feature of duplicate now

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ]  New feature (non-breaking change which adds functionality)
- [x] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-06-19 09:25:51 +03:00
5544430efa Dev (#270)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Jira Ticket
[SP-1661](https://syncrow.atlassian.net/browse/SP-1661)

## Description

Includes a few critical hot fixes.

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [x]  New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore 


[SP-1661]:
https://syncrow.atlassian.net/browse/SP-1661?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
2025-06-18 16:02:53 +03:00
ae89a24a4b Dev (#265)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Description

<!--- Describe your changes in detail -->

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [x]  New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-06-18 11:01:09 +03:00
ecc01a1eb3 hides air quality tab. (#262)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Description

Hides AQI tab in analytics dashboard for release purposes.

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ]  New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [x]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-06-17 13:30:36 +03:00
921da20d3f hides air quality tab. 2025-06-17 13:28:22 +03:00
2fed2d9de3 Sprint 20 STG Release (#261)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Description

Sprint 20 staging release.
## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [x]  New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ]  Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ]  Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-06-17 13:26:01 +03:00
21 changed files with 240 additions and 268 deletions

View File

@ -1,2 +1,3 @@
ENV_NAME=development
BASE_URL=https://syncrow-dev.azurewebsites.net
BASE_URL=https://syncrow-dev.azurewebsites.net
RTDB_URL=https://syncrow-dev-79446.asia-southeast1.firebasedatabase.app/

View File

@ -1,2 +1,3 @@
ENV_NAME=production
BASE_URL=https://syncrow-staging.azurewebsites.net
BASE_URL=https://syncrow-staging.azurewebsites.net
RTDB_URL=https://syncrow-prod-79446.asia-southeast1.firebasedatabase.app/

View File

@ -1,2 +1,3 @@
ENV_NAME=staging
BASE_URL=https://syncrow-staging.azurewebsites.net
BASE_URL=https://syncrow-staging.azurewebsites.net
RTDB_URL=https://syncrow-staging-79446.asia-southeast1.firebasedatabase.app/

112
.vscode/launch.json vendored
View File

@ -1,67 +1,49 @@
{
"configurations": [
{
"name": "DEVELOPMENT",
"request": "launch",
"type": "dart",
"args": [
"-d",
"chrome",
"--web-port",
"3000",
"-t",
"lib/main_dev.dart",
"--web-experimental-hot-reload",
],
"flutterMode": "debug"
},{
"name": "STAGING",
"request": "launch",
"type": "dart",
"args": [
"-d",
"chrome",
"--web-port",
"3000",
"-t",
"lib/main_staging.dart",
"--web-experimental-hot-reload",
],
"flutterMode": "debug"
},{
"name": "PRODUCTION",
"request": "launch",
"type": "dart",
"args": [
"-d",
"chrome",
"--web-port",
"3000",
"-t",
"lib/main.dart",
"--web-experimental-hot-reload",
],
"flutterMode": "debug"
},
]
"configurations": [
{
"name": "DEVELOPMENT",
"request": "launch",
"type": "dart",
"args": [
"-d",
"chrome",
"--web-port",
"3000",
"-t",
"lib/main_dev.dart",
"--web-experimental-hot-reload"
],
"flutterMode": "debug"
},
{
"name": "STAGING",
"request": "launch",
"type": "dart",
"args": [
"-d",
"chrome",
"--web-port",
"3000",
"-t",
"lib/main_staging.dart",
"--web-experimental-hot-reload"
],
"flutterMode": "debug"
},
{
"name": "PRODUCTION",
"request": "launch",
"type": "dart",
"args": [
"-d",
"chrome",
"--web-port",
"3000",
"-t",
"lib/main.dart",
"--web-experimental-hot-reload"
],
"flutterMode": "debug"
}
]
}

View File

@ -1 +1 @@
{"flutter":{"platforms":{"android":{"default":{"projectId":"test2-8a3d2","appId":"1:427332280600:android:2bc36fbe82994a3e0c7e6d","fileOutput":"android/app/google-services.json"}},"ios":{"default":{"projectId":"test2-8a3d2","appId":"1:427332280600:ios:14346b200780dc760c7e6d","uploadDebugSymbols":true,"fileOutput":"ios/Runner/GoogleService-Info.plist"}},"macos":{"default":{"projectId":"test2-8a3d2","appId":"1:427332280600:ios:14346b200780dc760c7e6d","uploadDebugSymbols":true,"fileOutput":"macos/Runner/GoogleService-Info.plist"}},"dart":{"lib/firebase_options.dart":{"projectId":"test2-8a3d2","configurations":{"android":"1:427332280600:android:2bc36fbe82994a3e0c7e6d","ios":"1:427332280600:ios:14346b200780dc760c7e6d","macos":"1:427332280600:ios:14346b200780dc760c7e6d","web":"1:427332280600:web:ad50516a87a35a1a0c7e6d","windows":"1:427332280600:web:f7a25537ccd5a7bd0c7e6d"}}}}}}
{"flutter":{"platforms":{"android":{"default":{"projectId":"test2-8a3d2","appId":"1:427332280600:android:2bc36fbe82994a3e0c7e6d","fileOutput":"android/app/google-services.json"}},"ios":{"default":{"projectId":"test2-8a3d2","appId":"1:427332280600:ios:14346b200780dc760c7e6d","uploadDebugSymbols":true,"fileOutput":"ios/Runner/GoogleService-Info.plist"}},"macos":{"default":{"projectId":"test2-8a3d2","appId":"1:427332280600:ios:14346b200780dc760c7e6d","uploadDebugSymbols":true,"fileOutput":"macos/Runner/GoogleService-Info.plist"}},"dart":{"lib/firebase_options.dart":{"projectId":"syncrow-prod-79446","configurations":{"web":"1:255001682464:web:a03e2d6214c13101561245"}}}}}}

16
lib/firebase_options.dart Normal file
View File

@ -0,0 +1,16 @@
import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
final class DefaultFirebaseOptions extends FirebaseOptions {
const DefaultFirebaseOptions({
required String databaseUrl,
}) : super(
apiKey: 'AIzaSyDgq5ywsnFVbbQO-Xz1Z4sR5bBcuiDaS9g',
appId: '1:255001682464:web:a03e2d6214c13101561245',
messagingSenderId: '255001682464',
projectId: 'syncrow-prod-79446',
authDomain: 'syncrow-prod-79446.firebaseapp.com',
storageBucket: 'syncrow-prod-79446.firebasestorage.app',
databaseURL: databaseUrl,
measurementId: 'G-1850Q89RMK',
);
}

View File

@ -1,93 +0,0 @@
// File generated by FlutterFire CLI.
// ignore_for_file: type=lint
import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
import 'package:flutter/foundation.dart'
show defaultTargetPlatform, kIsWeb, TargetPlatform;
/// Default [FirebaseOptions] for use with your Firebase apps.
///
/// Example:
/// ```dart
/// import 'firebase_options.dart';
/// // ...
/// await Firebase.initializeApp(
/// options: DefaultFirebaseOptions.currentPlatform,
/// );
/// ```
class DefaultFirebaseOptionsDev {
static FirebaseOptions get currentPlatform {
if (kIsWeb) {
return web;
}
switch (defaultTargetPlatform) {
case TargetPlatform.android:
return android;
case TargetPlatform.iOS:
return ios;
case TargetPlatform.macOS:
return macos;
case TargetPlatform.windows:
return windows;
case TargetPlatform.linux:
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for linux - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
default:
throw UnsupportedError(
'DefaultFirebaseOptions are not supported for this platform.',
);
}
}
static const FirebaseOptions web = FirebaseOptions(
apiKey: 'AIzaSyCVEvKsJYzhWDFM-9Od68FE0nPpP933st0',
appId: '1:427332280600:web:ad50516a87a35a1a0c7e6d',
messagingSenderId: '427332280600',
projectId: 'test2-8a3d2',
authDomain: 'test2-8a3d2.firebaseapp.com',
databaseURL: 'https://test2-8a3d2-default-rtdb.firebaseio.com',
storageBucket: 'test2-8a3d2.firebasestorage.app',
measurementId: 'G-Z1RTTTV5H9',
);
static const FirebaseOptions android = FirebaseOptions(
apiKey: 'AIzaSyA5qOErxdm0zJmoHIB0TixfebYEsNRpwV0',
appId: '1:427332280600:android:2bc36fbe82994a3e0c7e6d',
messagingSenderId: '427332280600',
projectId: 'test2-8a3d2',
databaseURL: 'https://test2-8a3d2-default-rtdb.firebaseio.com',
storageBucket: 'test2-8a3d2.firebasestorage.app',
);
static const FirebaseOptions ios = FirebaseOptions(
apiKey: 'AIzaSyABnpH6yo2RRjtkp4PlvtK84hKwRm2DhBw',
appId: '1:427332280600:ios:14346b200780dc760c7e6d',
messagingSenderId: '427332280600',
projectId: 'test2-8a3d2',
databaseURL: 'https://test2-8a3d2-default-rtdb.firebaseio.com',
storageBucket: 'test2-8a3d2.firebasestorage.app',
iosBundleId: 'com.example.syncrowWeb',
);
static const FirebaseOptions macos = FirebaseOptions(
apiKey: 'AIzaSyABnpH6yo2RRjtkp4PlvtK84hKwRm2DhBw',
appId: '1:427332280600:ios:14346b200780dc760c7e6d',
messagingSenderId: '427332280600',
projectId: 'test2-8a3d2',
databaseURL: 'https://test2-8a3d2-default-rtdb.firebaseio.com',
storageBucket: 'test2-8a3d2.firebasestorage.app',
iosBundleId: 'com.example.syncrowWeb',
);
static const FirebaseOptions windows = FirebaseOptions(
apiKey: 'AIzaSyDizKjPC5rdkEjDxwXjM-RU5unB0Ziq3iw',
appId: '1:427332280600:web:f7a25537ccd5a7bd0c7e6d',
messagingSenderId: '427332280600',
projectId: 'test2-8a3d2',
authDomain: 'test2-8a3d2.firebaseapp.com',
databaseURL: 'https://test2-8a3d2-default-rtdb.firebaseio.com',
storageBucket: 'test2-8a3d2.firebasestorage.app',
measurementId: 'G-4LFVXEXWKY',
);
}

View File

@ -1,77 +0,0 @@
// File generated by FlutterFire CLI.
// ignore_for_file: type=lint
import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
import 'package:flutter/foundation.dart' show defaultTargetPlatform, kIsWeb, TargetPlatform;
/// Default [FirebaseOptions] for use with your Firebase apps.
///
/// Example:
/// ```dart
/// import 'firebase_options.dart';
/// // ...
/// await Firebase.initializeApp(
/// options: DefaultFirebaseOptions.currentPlatform,
/// );
/// ```
class DefaultFirebaseOptionsStaging {
static FirebaseOptions get currentPlatform {
if (kIsWeb) {
return web;
}
switch (defaultTargetPlatform) {
case TargetPlatform.android:
return android;
case TargetPlatform.iOS:
return ios;
case TargetPlatform.macOS:
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for macos - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
case TargetPlatform.windows:
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for windows - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
case TargetPlatform.linux:
throw UnsupportedError(
'DefaultFirebaseOptions have not been configured for linux - '
'you can reconfigure this by running the FlutterFire CLI again.',
);
default:
throw UnsupportedError(
'DefaultFirebaseOptions are not supported for this platform.',
);
}
}
static const FirebaseOptions android = FirebaseOptions(
apiKey: 'AIzaSyDP9GpYfLE8gHTj3kZ1hW8fx_FkJqOqSQk',
appId: '1:786692570726:android:0ef7079c2b978d4417b7a7',
messagingSenderId: '786692570726',
projectId: 'syncrow-staging',
databaseURL: 'https://syncrow-staging-default-rtdb.firebaseio.com',
storageBucket: 'syncrow-staging.appspot.com',
);
static const FirebaseOptions ios = FirebaseOptions(
apiKey: 'AIzaSyAWlRiuJ75FMlf2_UDdri1voWKvkaSHtRg',
appId: '1:786692570726:ios:455a6fcff77e130f17b7a7',
messagingSenderId: '786692570726',
projectId: 'syncrow-staging',
databaseURL: 'https://syncrow-staging-default-rtdb.firebaseio.com',
storageBucket: 'syncrow-staging.appspot.com',
iosBundleId: 'com.example.syncrow.app',
);
static const FirebaseOptions web = FirebaseOptions(
apiKey: 'AIzaSyDyGaQ3sZhb4meaY6sGke-YglhdhJ2is8Q',
appId: '1:786692570726:web:93c931e6701797b317b7a7',
messagingSenderId: '786692570726',
projectId: 'syncrow-staging',
authDomain: 'syncrow-staging.firebaseapp.com',
databaseURL: 'https://syncrow-staging-default-rtdb.firebaseio.com',
storageBucket: 'syncrow-staging.appspot.com',
measurementId: 'G-CZ3J3G6LMQ',
);
}

View File

@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:go_router/go_router.dart';
import 'package:syncrow_web/firebase_options_prod.dart';
import 'package:syncrow_web/firebase_options.dart';
import 'package:syncrow_web/pages/auth/bloc/auth_bloc.dart';
import 'package:syncrow_web/pages/home/bloc/home_bloc.dart';
import 'package:syncrow_web/pages/home/bloc/home_event.dart';
@ -27,7 +27,9 @@ Future<void> main() async {
await dotenv.load(fileName: '.env.$environment');
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptionsStaging.currentPlatform,
options: DefaultFirebaseOptions(
databaseUrl: dotenv.env['RTDB_URL']!,
),
);
initialSetup();
} catch (_) {}
@ -59,7 +61,7 @@ class MyApp extends StatelessWidget {
BlocProvider<CreateRoutineBloc>(
create: (context) => CreateRoutineBloc(),
),
BlocProvider(create: (context) => HomeBloc()..add(FetchUserInfo())),
BlocProvider(create: (context) => HomeBloc()..add(const FetchUserInfo())),
BlocProvider<VisitorPasswordBloc>(
create: (context) => VisitorPasswordBloc(),
),

View File

@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:go_router/go_router.dart';
import 'package:syncrow_web/firebase_options_dev.dart';
import 'package:syncrow_web/firebase_options.dart';
import 'package:syncrow_web/pages/auth/bloc/auth_bloc.dart';
import 'package:syncrow_web/pages/home/bloc/home_bloc.dart';
import 'package:syncrow_web/pages/home/bloc/home_event.dart';
@ -27,7 +27,9 @@ Future<void> main() async {
await dotenv.load(fileName: '.env.$environment');
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptionsDev.currentPlatform,
options: DefaultFirebaseOptions(
databaseUrl: dotenv.env['RTDB_URL']!,
),
);
initialSetup();
} catch (_) {}
@ -59,7 +61,7 @@ class MyApp extends StatelessWidget {
BlocProvider<CreateRoutineBloc>(
create: (context) => CreateRoutineBloc(),
),
BlocProvider(create: (context) => HomeBloc()..add(FetchUserInfo())),
BlocProvider(create: (context) => HomeBloc()..add(const FetchUserInfo())),
BlocProvider<VisitorPasswordBloc>(
create: (context) => VisitorPasswordBloc(),
),

View File

@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'package:go_router/go_router.dart';
import 'package:syncrow_web/firebase_options_prod.dart';
import 'package:syncrow_web/firebase_options.dart';
import 'package:syncrow_web/pages/auth/bloc/auth_bloc.dart';
import 'package:syncrow_web/pages/home/bloc/home_bloc.dart';
import 'package:syncrow_web/pages/home/bloc/home_event.dart';
@ -24,7 +24,9 @@ Future<void> main() async {
await dotenv.load(fileName: '.env.$environment');
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options: DefaultFirebaseOptionsStaging.currentPlatform,
options: DefaultFirebaseOptions(
databaseUrl: dotenv.env['RTDB_URL']!,
),
);
initialSetup();
} catch (_) {}
@ -56,7 +58,7 @@ class MyApp extends StatelessWidget {
BlocProvider<CreateRoutineBloc>(
create: (context) => CreateRoutineBloc(),
),
BlocProvider(create: (context) => HomeBloc()..add(FetchUserInfo())),
BlocProvider(create: (context) => HomeBloc()..add(const FetchUserInfo())),
BlocProvider<VisitorPasswordBloc>(
create: (context) => VisitorPasswordBloc(),
),

View File

@ -22,7 +22,9 @@ import 'package:syncrow_web/pages/analytics/services/analytics_devices/remote_en
import 'package:syncrow_web/pages/analytics/services/analytics_devices/remote_occupancy_analytics_devices_service.dart';
import 'package:syncrow_web/pages/analytics/services/device_location/device_location_details_service_decorator.dart';
import 'package:syncrow_web/pages/analytics/services/device_location/remote_device_location_service.dart';
import 'package:syncrow_web/pages/analytics/services/energy_consumption_by_phases/energy_consumption_by_phases_value_divider_decorator.dart';
import 'package:syncrow_web/pages/analytics/services/energy_consumption_by_phases/remote_energy_consumption_by_phases_service.dart';
import 'package:syncrow_web/pages/analytics/services/energy_consumption_per_device/energy_consumption_per_device_value_divider_decorator.dart';
import 'package:syncrow_web/pages/analytics/services/energy_consumption_per_device/remote_energy_consumption_per_device_service.dart';
import 'package:syncrow_web/pages/analytics/services/occupacy/remote_occupancy_service.dart';
import 'package:syncrow_web/pages/analytics/services/occupancy_heat_map/remote_occupancy_heat_map_service.dart';
@ -62,17 +64,23 @@ class _AnalyticsPageState extends State<AnalyticsPage> {
),
BlocProvider(
create: (context) => TotalEnergyConsumptionBloc(
RemoteTotalEnergyConsumptionService(_httpService),
DividedTotalEnergyConsumptionDecorator(
RemoteTotalEnergyConsumptionService(_httpService),
),
),
),
BlocProvider(
create: (context) => EnergyConsumptionByPhasesBloc(
RemoteEnergyConsumptionByPhasesService(_httpService),
EnergyConsumptionByPhasesValueDividerDecorator(
RemoteEnergyConsumptionByPhasesService(_httpService),
),
),
),
BlocProvider(
create: (context) => EnergyConsumptionPerDeviceBloc(
RemoteEnergyConsumptionPerDeviceService(_httpService),
EnergyConsumptionPerDeviceValueDividerDecorator(
RemoteEnergyConsumptionPerDeviceService(_httpService),
),
),
),
BlocProvider(
@ -145,6 +153,7 @@ class _AnalyticsPageFormState extends State<AnalyticsPageForm> {
context.read<SpaceTreeBloc>().add(InitialEvent());
super.initState();
}
@override
Widget build(BuildContext context) {
return WebScaffold(

View File

@ -13,15 +13,15 @@ class EnergyConsumptionByPhasesChart extends StatelessWidget {
});
final List<PhasesEnergyConsumption> energyData;
static const _kLeftTitlesInterval = 4.0;
@override
Widget build(BuildContext context) {
return BarChart(
BarChartData(
gridData: EnergyManagementChartsHelper.gridData().copyWith(
checkToShowHorizontalLine: (value) => true,
horizontalInterval: 250,
horizontalInterval: _kLeftTitlesInterval,
),
borderData: EnergyManagementChartsHelper.borderData(),
barTouchData: _barTouchData(context),
@ -100,11 +100,11 @@ class EnergyConsumptionByPhasesChart extends StatelessWidget {
}) {
final data = energyData;
final date = DateFormat('dd/MM/yyyy').format(data[group.x.toInt()].date);
final phaseA = data[group.x.toInt()].energyConsumedA;
final phaseB = data[group.x.toInt()].energyConsumedB;
final phaseC = data[group.x.toInt()].energyConsumedC;
final total = data[group.x.toInt()].energyConsumedKw;
final date = DateFormat('dd/MM/yyyy').format(data[group.x].date);
final phaseA = data[group.x].energyConsumedA;
final phaseB = data[group.x].energyConsumedB;
final phaseC = data[group.x].energyConsumedC;
final total = data[group.x].energyConsumedKw;
return BarTooltipItem(
'$date\n',
@ -149,7 +149,7 @@ class EnergyConsumptionByPhasesChart extends StatelessWidget {
FlTitlesData _titlesData(BuildContext context) {
final titlesData = EnergyManagementChartsHelper.titlesData(
context,
leftTitlesInterval: 250,
leftTitlesInterval: _kLeftTitlesInterval,
);
final leftTitles = titlesData.leftTitles.copyWith(

View File

@ -7,6 +7,7 @@ class EnergyConsumptionPerDeviceChart extends StatelessWidget {
const EnergyConsumptionPerDeviceChart({super.key, required this.chartData});
final List<DeviceEnergyDataModel> chartData;
static const _kLeftTitlesInterval = 2.5;
@override
Widget build(BuildContext context) {
@ -15,12 +16,11 @@ class EnergyConsumptionPerDeviceChart extends StatelessWidget {
clipData: const FlClipData.vertical(),
titlesData: EnergyManagementChartsHelper.titlesData(
context,
leftTitlesInterval: 250,
leftTitlesInterval: _kLeftTitlesInterval,
),
gridData: EnergyManagementChartsHelper.gridData().copyWith(
checkToShowHorizontalLine: (value) => true,
horizontalInterval: 250,
horizontalInterval: _kLeftTitlesInterval,
),
borderData: EnergyManagementChartsHelper.borderData(),
lineTouchData: EnergyManagementChartsHelper.lineTouchData(),

View File

@ -9,22 +9,24 @@ class TotalEnergyConsumptionChart extends StatelessWidget {
final List<EnergyDataModel> chartData;
static const _leftTitlesInterval = 5.0;
@override
Widget build(BuildContext context) {
return Expanded(
child: LineChart(
LineChartData(
maxY: chartData.isEmpty
? null
: chartData.map((e) => e.value).reduce((a, b) => a > b ? a : b) + 250,
maxY: chartData.isNotEmpty
? chartData.map((e) => e.value).reduce((a, b) => a > b ? a : b) +
_leftTitlesInterval
: null,
clipData: const FlClipData.vertical(),
titlesData: EnergyManagementChartsHelper.titlesData(
context,
leftTitlesInterval: 500,
leftTitlesInterval: _leftTitlesInterval,
),
gridData: EnergyManagementChartsHelper.gridData().copyWith(
checkToShowHorizontalLine: (value) => true,
horizontalInterval: 500,
horizontalInterval: _leftTitlesInterval,
),
borderData: EnergyManagementChartsHelper.borderData(),
lineTouchData: EnergyManagementChartsHelper.lineTouchData(),

View File

@ -0,0 +1,34 @@
import 'package:syncrow_web/pages/analytics/models/phases_energy_consumption.dart';
import 'package:syncrow_web/pages/analytics/params/get_energy_consumption_by_phases_param.dart';
import 'package:syncrow_web/pages/analytics/services/energy_consumption_by_phases/energy_consumption_by_phases_service.dart';
import 'package:syncrow_web/utils/helpers/safe_division_helper.dart';
class EnergyConsumptionByPhasesValueDividerDecorator
implements EnergyConsumptionByPhasesService {
const EnergyConsumptionByPhasesValueDividerDecorator(
this._decoratee, {
this.divider = 100,
});
final EnergyConsumptionByPhasesService _decoratee;
final double divider;
@override
Future<List<PhasesEnergyConsumption>> load(
GetEnergyConsumptionByPhasesParam param) async {
final result = await _decoratee.load(param);
return result.map((e) {
return PhasesEnergyConsumption(
date: e.date,
energyConsumedA: SafeDivisionHelper.divide(e.energyConsumedA, divider),
energyConsumedB: SafeDivisionHelper.divide(e.energyConsumedB, divider),
energyConsumedC: SafeDivisionHelper.divide(e.energyConsumedC, divider),
energyConsumedKw: SafeDivisionHelper.divide(e.energyConsumedKw, divider),
uuid: e.uuid,
createdAt: e.createdAt,
updatedAt: e.updatedAt,
deviceUuid: e.deviceUuid,
);
}).toList();
}
}

View File

@ -0,0 +1,36 @@
import 'package:syncrow_web/pages/analytics/models/device_energy_data_model.dart';
import 'package:syncrow_web/pages/analytics/models/energy_data_model.dart';
import 'package:syncrow_web/pages/analytics/params/get_energy_consumption_per_device_param.dart';
import 'package:syncrow_web/pages/analytics/services/energy_consumption_per_device/energy_consumption_per_device_service.dart';
import 'package:syncrow_web/utils/helpers/safe_division_helper.dart';
class EnergyConsumptionPerDeviceValueDividerDecorator
implements EnergyConsumptionPerDeviceService {
const EnergyConsumptionPerDeviceValueDividerDecorator(
this._decoratee, {
this.divider = 100,
});
final EnergyConsumptionPerDeviceService _decoratee;
final double divider;
@override
Future<List<DeviceEnergyDataModel>> load(
GetEnergyConsumptionPerDeviceParam param,
) async {
final result = await _decoratee.load(param);
return result.map((device) {
return DeviceEnergyDataModel(
deviceId: device.deviceId,
deviceName: device.deviceName,
color: device.color,
energy: device.energy.map((e) {
return EnergyDataModel(
date: e.date,
value: SafeDivisionHelper.divide(e.value, divider),
);
}).toList(),
);
}).toList();
}
}

View File

@ -0,0 +1,26 @@
import 'package:syncrow_web/pages/analytics/models/energy_data_model.dart';
import 'package:syncrow_web/pages/analytics/params/get_total_energy_consumption_param.dart';
import 'package:syncrow_web/pages/analytics/services/total_energy_consumption/total_energy_consumption_service.dart';
import 'package:syncrow_web/utils/helpers/safe_division_helper.dart';
class DividedTotalEnergyConsumptionDecorator
implements TotalEnergyConsumptionService {
const DividedTotalEnergyConsumptionDecorator(
this._decoratee, {
this.divider = 100,
});
final TotalEnergyConsumptionService _decoratee;
final double divider;
@override
Future<List<EnergyDataModel>> load(GetTotalEnergyConsumptionParam param) async {
final result = await _decoratee.load(param);
return result.map((e) {
return EnergyDataModel(
date: e.date,
value: SafeDivisionHelper.divide(e.value, divider),
);
}).toList();
}
}

View File

@ -59,3 +59,23 @@ abstract final class _TotalEnergyConsumptionResponseMapper {
}).toList();
}
}
class DividedTotalEnergyConsumptionDecorator
implements TotalEnergyConsumptionService {
const DividedTotalEnergyConsumptionDecorator(this._decoratee);
final TotalEnergyConsumptionService _decoratee;
@override
Future<List<EnergyDataModel>> load(
GetTotalEnergyConsumptionParam param,
) async {
final result = await _decoratee.load(param);
final dividedResult = result.map((e) {
return EnergyDataModel(
date: e.date,
value: e.value / 100,
);
});
return dividedResult.toList();
}
}

View File

@ -105,7 +105,7 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
color: const Color(0xFF0026A2),
),
HomeItemModel(
title: 'Devices Management',
title: 'Device Management',
icon: Assets.devicesIcon,
active: true,
onPress: (context) {

View File

@ -0,0 +1,8 @@
abstract final class SafeDivisionHelper {
const SafeDivisionHelper._();
static double divide(num value, num divider) {
if (divider == 0) return 0;
return value / divider;
}
}