feat : map
This commit is contained in:
@@ -1,4 +1,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
|
||||
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
|
||||
<application
|
||||
android:label="rasadyar_app"
|
||||
android:name="${applicationName}"
|
||||
|
||||
1
assets/icons/map_marker.svg
Normal file
1
assets/icons/map_marker.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg id="Capa_1" enable-background="new 0 0 512 512" height="512" viewBox="0 0 512 512" width="512" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="212.562" x2="256.62" y1="372.319" y2="372.319"><stop offset="0" stop-color="#a996eb"/><stop offset="1" stop-color="#d7d1eb"/></linearGradient><linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="263.927" x2="230.973" y1="227.163" y2="272.151"><stop offset="0" stop-color="#7662bd"/><stop offset="1" stop-color="#7662bd" stop-opacity="0"/></linearGradient><radialGradient id="SVGID_3_" cx="258.197" cy="91.638" gradientUnits="userSpaceOnUse" r="125.028"><stop offset="0" stop-color="#ff4757"/><stop offset="1" stop-color="#ab2c37"/></radialGradient><radialGradient id="SVGID_4_" cx="298.176" cy="59.42" gradientUnits="userSpaceOnUse" r="125.028"><stop offset="0" stop-color="#fff"/><stop offset="1" stop-color="#fff" stop-opacity="0"/></radialGradient><g><path d="m219.855 232.637 28.848 272.797c.926 8.755 13.668 8.755 14.594 0l28.848-272.797z" fill="url(#SVGID_1_)"/><path d="m292.145 232.637h-72.291l2.913 27.54c36.405-3.856 68.056-15.04 68.056-15.04z" fill="url(#SVGID_2_)"/><g><circle cx="256" cy="125.028" fill="url(#SVGID_3_)" r="125.028"/><circle cx="256" cy="125.028" fill="url(#SVGID_4_)" opacity=".5" r="125.028"/></g></g></svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
109
features/supervision/lib/data/utils/cluster_generator.dart
Normal file
109
features/supervision/lib/data/utils/cluster_generator.dart
Normal file
@@ -0,0 +1,109 @@
|
||||
import 'dart:math';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:latlong2/latlong.dart';
|
||||
|
||||
class ClusterParams {
|
||||
final List<LatLng> points;
|
||||
final double clusterRadiusMeters;
|
||||
|
||||
ClusterParams({
|
||||
required this.points,
|
||||
required this.clusterRadiusMeters,
|
||||
});
|
||||
}
|
||||
|
||||
class Cluster {
|
||||
final LatLng center;
|
||||
final List<LatLng> members;
|
||||
|
||||
Cluster(this.center, this.members);
|
||||
}
|
||||
// Use a more efficient quadtree-based clustering algorithm
|
||||
Future<List<Cluster>> clusterMarkersQuadtreeIsolate(ClusterParams params) async {
|
||||
return compute(_clusterMarkersQuadtree, params);
|
||||
}
|
||||
|
||||
List<Cluster> _clusterMarkersQuadtree(ClusterParams params) {
|
||||
final points = params.points;
|
||||
final radius = params.clusterRadiusMeters;
|
||||
final distance = const Distance();
|
||||
final List<Cluster> clusters = [];
|
||||
|
||||
// Skip clustering if we have a small number of points
|
||||
if (points.length < 100) {
|
||||
return points.map((p) => Cluster(p, [p])).toList();
|
||||
}
|
||||
|
||||
// Find bounds
|
||||
double minLat = points[0].latitude;
|
||||
double maxLat = points[0].latitude;
|
||||
double minLng = points[0].longitude;
|
||||
double maxLng = points[0].longitude;
|
||||
|
||||
for (final point in points) {
|
||||
minLat = min(minLat, point.latitude);
|
||||
maxLat = max(maxLat, point.latitude);
|
||||
minLng = min(minLng, point.longitude);
|
||||
maxLng = max(maxLng, point.longitude);
|
||||
}
|
||||
|
||||
// Build spatial grid for faster lookups (simple spatial index)
|
||||
// Convert geographic distance to approximate degrees
|
||||
final double radiusDegLat = radius / 111000; // ~111km per degree latitude
|
||||
final double radiusDegLng = radius / (111000 * cos(minLat * pi / 180)); // Adjust for longitude
|
||||
|
||||
final int gridLatSize = ((maxLat - minLat) / radiusDegLat).ceil();
|
||||
final int gridLngSize = ((maxLng - minLng) / radiusDegLng).ceil();
|
||||
|
||||
// Create spatial grid
|
||||
final List<List<List<LatLng>>> grid = List.generate(
|
||||
gridLatSize + 1,
|
||||
(_) => List.generate(gridLngSize + 1, (_) => <LatLng>[])
|
||||
);
|
||||
|
||||
// Add points to grid cells
|
||||
for (final point in points) {
|
||||
final int latIdx = ((point.latitude - minLat) / radiusDegLat).floor();
|
||||
final int lngIdx = ((point.longitude - minLng) / radiusDegLng).floor();
|
||||
grid[latIdx][lngIdx].add(point);
|
||||
}
|
||||
|
||||
// Process grid cells in batches
|
||||
final Set<LatLng> processed = {};
|
||||
|
||||
for (int latIdx = 0; latIdx < gridLatSize; latIdx++) {
|
||||
for (int lngIdx = 0; lngIdx < gridLngSize; lngIdx++) {
|
||||
final cellPoints = grid[latIdx][lngIdx];
|
||||
|
||||
for (final point in cellPoints) {
|
||||
if (processed.contains(point)) continue;
|
||||
|
||||
// Find nearby points
|
||||
final List<LatLng> neighbors = [];
|
||||
neighbors.add(point);
|
||||
processed.add(point);
|
||||
|
||||
// Check current and adjacent cells for neighbors
|
||||
for (int adjLat = max(0, latIdx - 1); adjLat <= min(gridLatSize - 1, latIdx + 1); adjLat++) {
|
||||
for (int adjLng = max(0, lngIdx - 1); adjLng <= min(gridLngSize - 1, lngIdx + 1); adjLng++) {
|
||||
for (final neighbor in grid[adjLat][adjLng]) {
|
||||
if (!processed.contains(neighbor) && distance(point, neighbor) <= radius) {
|
||||
neighbors.add(neighbor);
|
||||
processed.add(neighbor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate cluster center
|
||||
if (neighbors.isNotEmpty) {
|
||||
final avgLat = neighbors.map((p) => p.latitude).reduce((a, b) => a + b) / neighbors.length;
|
||||
final avgLng = neighbors.map((p) => p.longitude).reduce((a, b) => a + b) / neighbors.length;
|
||||
clusters.add(Cluster(LatLng(avgLat, avgLng), neighbors));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return clusters;
|
||||
}
|
||||
57
features/supervision/lib/data/utils/marker_generator.dart
Normal file
57
features/supervision/lib/data/utils/marker_generator.dart
Normal file
@@ -0,0 +1,57 @@
|
||||
import 'dart:math';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:latlong2/latlong.dart';
|
||||
|
||||
class GridGenParams {
|
||||
final LatLng center;
|
||||
final int count;
|
||||
final double spacingMeters;
|
||||
|
||||
const GridGenParams({
|
||||
required this.center,
|
||||
required this.count,
|
||||
required this.spacingMeters,
|
||||
});
|
||||
}Future<List<LatLng>> generateGridMarkersIsolate(GridGenParams params) async {
|
||||
return compute(_generateGridMarkersOptimized, params);
|
||||
}
|
||||
|
||||
List<LatLng> _generateGridMarkersOptimized(GridGenParams params) {
|
||||
final List<LatLng> result = [];
|
||||
final Distance distance = const Distance();
|
||||
|
||||
// Pre-calculate the grid dimensions
|
||||
final int gridSize = sqrt(params.count).ceil();
|
||||
final double halfWidth = (gridSize * params.spacingMeters) / 2;
|
||||
final double halfHeight = (gridSize * params.spacingMeters) / 2;
|
||||
|
||||
// Calculate top-left corner of the grid
|
||||
final LatLng topLeft = distance.offset(
|
||||
distance.offset(params.center, -halfHeight, 0), // south
|
||||
-halfWidth, 270 // west
|
||||
);
|
||||
|
||||
// Generate grid in batches for better memory management
|
||||
const int batchSize = 10000;
|
||||
for (int batch = 0; batch < (params.count / batchSize).ceil(); batch++) {
|
||||
final int startIdx = batch * batchSize;
|
||||
final int endIdx = min((batch + 1) * batchSize, params.count);
|
||||
|
||||
for (int i = startIdx; i < endIdx; i++) {
|
||||
final int row = i ~/ gridSize;
|
||||
final int col = i % gridSize;
|
||||
|
||||
final double dx = col * params.spacingMeters;
|
||||
final double dy = row * params.spacingMeters;
|
||||
|
||||
final LatLng point = distance.offset(
|
||||
distance.offset(topLeft, dy, 180), // south
|
||||
dx, 90 // east
|
||||
);
|
||||
|
||||
result.add(point);
|
||||
}
|
||||
}
|
||||
|
||||
return result.sublist(0, min(result.length, params.count));
|
||||
}
|
||||
16
features/supervision/lib/presentation/routes/app_pages.dart
Normal file
16
features/supervision/lib/presentation/routes/app_pages.dart
Normal file
@@ -0,0 +1,16 @@
|
||||
import 'package:rasadyar_core/core.dart';
|
||||
import 'package:supervision/presentation/filter/logic.dart';
|
||||
import 'package:supervision/presentation/filter/view.dart';
|
||||
import 'package:supervision/presentation/routes/app_routes.dart';
|
||||
|
||||
sealed class SupervisionPages {
|
||||
SupervisionPages._();
|
||||
|
||||
static final pages = [
|
||||
GetPage(
|
||||
name: SupervisionRoutes.supervision,
|
||||
page: () => SupervisionFilterPage(),
|
||||
binding: BindingsBuilder.put(() => BazresiLogic()),
|
||||
),
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
sealed class SupervisionRoutes {
|
||||
SupervisionRoutes._();
|
||||
|
||||
|
||||
static const supervision = '/supervision';
|
||||
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class AnimatedClusterMarker extends StatefulWidget {
|
||||
final int count;
|
||||
|
||||
const AnimatedClusterMarker({super.key, required this.count});
|
||||
|
||||
@override
|
||||
State<AnimatedClusterMarker> createState() => _AnimatedClusterMarkerState();
|
||||
}
|
||||
|
||||
class _AnimatedClusterMarkerState extends State<AnimatedClusterMarker>
|
||||
with SingleTickerProviderStateMixin {
|
||||
late AnimationController _controller;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
_controller = AnimationController(
|
||||
vsync: this,
|
||||
duration: const Duration(milliseconds: 300),
|
||||
)..forward(); // start animation
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ScaleTransition(
|
||||
scale: CurvedAnimation(parent: _controller, curve: Curves.easeOutBack),
|
||||
child: Opacity(
|
||||
opacity: _controller.value,
|
||||
child: Container(
|
||||
width: 40,
|
||||
height: 40,
|
||||
alignment: Alignment.center,
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.blueAccent,
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(color: Colors.white, width: 2),
|
||||
),
|
||||
child: Text(
|
||||
widget.count.toString(),
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
7
features/supervision/lib/supervision.dart
Normal file
7
features/supervision/lib/supervision.dart
Normal file
@@ -0,0 +1,7 @@
|
||||
library;
|
||||
|
||||
export 'presentation/filter/logic.dart';
|
||||
export 'presentation/filter/view.dart';
|
||||
export 'presentation/routes/app_pages.dart';
|
||||
export 'presentation/routes/app_routes.dart';
|
||||
|
||||
17
features/supervision/pubspec.yaml
Normal file
17
features/supervision/pubspec.yaml
Normal file
@@ -0,0 +1,17 @@
|
||||
name: supervision
|
||||
description: "A new Flutter project."
|
||||
publish_to: 'none'
|
||||
version: 1.0.0
|
||||
|
||||
environment:
|
||||
sdk: ^3.7.0
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
rasadyar_core:
|
||||
path: ./../../packages/core
|
||||
flutter_map: ^8.1.1
|
||||
location: ^8.0.0
|
||||
latlong2: ^0.9.1
|
||||
geolocator: ^13.0.4
|
||||
3
flutter_ddd_module/CHANGELOG.md
Normal file
3
flutter_ddd_module/CHANGELOG.md
Normal file
@@ -0,0 +1,3 @@
|
||||
# 0.1.0+1
|
||||
|
||||
- TODO: Describe initial release.
|
||||
1
flutter_ddd_module/HELLO.md
Normal file
1
flutter_ddd_module/HELLO.md
Normal file
@@ -0,0 +1 @@
|
||||
Hello moji
|
||||
1
flutter_ddd_module/LICENSE
Normal file
1
flutter_ddd_module/LICENSE
Normal file
@@ -0,0 +1 @@
|
||||
TODO: Add your license here.
|
||||
27
flutter_ddd_module/README.md
Normal file
27
flutter_ddd_module/README.md
Normal file
@@ -0,0 +1,27 @@
|
||||
# flutter_ddd_module
|
||||
|
||||
[](https://github.com/felangel/mason)
|
||||
|
||||
A new brick created with the Mason CLI.
|
||||
|
||||
_Generated by [mason][1] 🧱_
|
||||
|
||||
## Getting Started 🚀
|
||||
|
||||
This is a starting point for a new brick.
|
||||
A few resources to get you started if this is your first brick template:
|
||||
|
||||
- [Official Mason Documentation][2]
|
||||
- [Code generation with Mason Blog][3]
|
||||
- [Very Good Livestream: Felix Angelov Demos Mason][4]
|
||||
- [Flutter Package of the Week: Mason][5]
|
||||
- [Observable Flutter: Building a Mason brick][6]
|
||||
- [Meet Mason: Flutter Vikings 2022][7]
|
||||
|
||||
[1]: https://github.com/felangel/mason
|
||||
[2]: https://docs.brickhub.dev
|
||||
[3]: https://verygood.ventures/blog/code-generation-with-mason
|
||||
[4]: https://youtu.be/G4PTjA6tpTU
|
||||
[5]: https://youtu.be/qjA0JFiPMnQ
|
||||
[6]: https://youtu.be/o8B1EfcUisw
|
||||
[7]: https://youtu.be/LXhgiF5HiQg
|
||||
1
flutter_ddd_module/__brick__/HELLO.md
Normal file
1
flutter_ddd_module/__brick__/HELLO.md
Normal file
@@ -0,0 +1 @@
|
||||
Hello {{name}}!
|
||||
0
flutter_ddd_module/__brick__/lib/data/.gitkeep
Normal file
0
flutter_ddd_module/__brick__/lib/data/.gitkeep
Normal file
20
flutter_ddd_module/__brick__/pubspec.yaml
Normal file
20
flutter_ddd_module/__brick__/pubspec.yaml
Normal file
@@ -0,0 +1,20 @@
|
||||
name: {{feature_name}}
|
||||
description: {{feature_name}} feature module
|
||||
version: 0.0.1
|
||||
publish_to: 'none'
|
||||
|
||||
environment:
|
||||
sdk: '>=3.0.0 <4.0.0'
|
||||
flutter: ">=3.10.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^5.0.0
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
33
flutter_ddd_module/brick.yaml
Normal file
33
flutter_ddd_module/brick.yaml
Normal file
@@ -0,0 +1,33 @@
|
||||
name: flutter_ddd_module
|
||||
description: A new brick created with the Mason CLI.
|
||||
|
||||
# The following defines the brick repository url.
|
||||
# Uncomment and update the following line before publishing the brick.
|
||||
# repository: https://github.com/my_org/my_repo
|
||||
|
||||
# The following defines the version and build number for your brick.
|
||||
# A version number is three numbers separated by dots, like 1.2.34
|
||||
# followed by an optional build number (separated by a +).
|
||||
version: 0.1.0+1
|
||||
|
||||
# The following defines the environment for the current brick.
|
||||
# It includes the version of mason that the brick requires.
|
||||
environment:
|
||||
mason: ^0.1.1
|
||||
|
||||
# Variables specify dynamic values that your brick depends on.
|
||||
# Zero or more variables can be specified for a given brick.
|
||||
# Each variable has:
|
||||
# * a type (string, number, boolean, enum, array, or list)
|
||||
# * an optional short description
|
||||
# * an optional default value
|
||||
# * an optional list of default values (array only)
|
||||
# * an optional prompt phrase used when asking for the variable
|
||||
# * a list of values (enums only)
|
||||
# * an optional separator (list only)
|
||||
vars:
|
||||
name:
|
||||
type: string
|
||||
description: Your name
|
||||
default: Dash
|
||||
prompt: What is your name?
|
||||
20
flutter_ddd_module/pubspec.yaml
Normal file
20
flutter_ddd_module/pubspec.yaml
Normal file
@@ -0,0 +1,20 @@
|
||||
name:
|
||||
description: feature module
|
||||
version: 0.0.1
|
||||
publish_to: 'none'
|
||||
|
||||
environment:
|
||||
sdk: '>=3.0.0 <4.0.0'
|
||||
flutter: ">=3.10.0"
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^5.0.0
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
@@ -45,5 +45,7 @@
|
||||
<true/>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>NSLocationWhenInUseUsageDescription</key>
|
||||
<string>This app needs access to your location.</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
@@ -11,70 +11,84 @@ class AppFonts {
|
||||
static const FontWeight bold = FontWeight.w600;
|
||||
static const double _height = 1.20;
|
||||
|
||||
static const TextStyle yekan61Regular = TextStyle(
|
||||
static const TextStyle yekan61 = TextStyle(
|
||||
fontFamily: yekan,
|
||||
fontWeight: regular,
|
||||
fontSize: 61,
|
||||
height: _height,
|
||||
);
|
||||
|
||||
static const TextStyle yekan49Regular = TextStyle(
|
||||
static const TextStyle yekan49 = TextStyle(
|
||||
fontFamily: yekan,
|
||||
fontWeight: regular,
|
||||
fontSize: 48,
|
||||
height: _height,
|
||||
);
|
||||
|
||||
static const TextStyle yekan39Regular = TextStyle(
|
||||
static const TextStyle yekan39 = TextStyle(
|
||||
fontFamily: yekan,
|
||||
fontWeight: regular,
|
||||
fontSize: 39,
|
||||
height: _height,
|
||||
);
|
||||
|
||||
static const TextStyle yekan31Regular = TextStyle(
|
||||
static const TextStyle yekan31 = TextStyle(
|
||||
fontFamily: yekan,
|
||||
fontWeight: regular,
|
||||
fontSize: 31,
|
||||
height: _height,
|
||||
);
|
||||
|
||||
static const TextStyle yekan25Regular = TextStyle(
|
||||
static const TextStyle yekan25 = TextStyle(
|
||||
fontFamily: yekan,
|
||||
fontWeight: regular,
|
||||
fontSize: 25,
|
||||
height: _height,
|
||||
);
|
||||
|
||||
static const TextStyle yekan24Regular = TextStyle(
|
||||
static const TextStyle yekan24 = TextStyle(
|
||||
fontFamily: yekan,
|
||||
fontWeight: regular,
|
||||
fontSize: 24,
|
||||
height: _height,
|
||||
);
|
||||
|
||||
static const TextStyle yekan20Regular = TextStyle(
|
||||
static const TextStyle yekan20 = TextStyle(
|
||||
fontFamily: yekan,
|
||||
fontWeight: regular,
|
||||
fontSize: 20,
|
||||
height: _height,
|
||||
);
|
||||
|
||||
static const TextStyle yekan16Regular = TextStyle(
|
||||
static const TextStyle yekan18 = TextStyle(
|
||||
fontFamily: yekan,
|
||||
fontWeight: regular,
|
||||
fontSize: 18,
|
||||
height: _height,
|
||||
);
|
||||
|
||||
static const TextStyle yekan16 = TextStyle(
|
||||
fontFamily: yekan,
|
||||
fontWeight: regular,
|
||||
fontSize: 16,
|
||||
height: _height,
|
||||
);
|
||||
|
||||
static const TextStyle yekan13Regular = TextStyle(
|
||||
static const TextStyle yekan14 = TextStyle(
|
||||
fontFamily: yekan,
|
||||
fontWeight: regular,
|
||||
fontSize: 13,
|
||||
height: _height,
|
||||
);
|
||||
|
||||
static const TextStyle yekan10Regular = TextStyle(
|
||||
static const TextStyle yekan13 = TextStyle(
|
||||
fontFamily: yekan,
|
||||
fontWeight: regular,
|
||||
fontSize: 13,
|
||||
height: _height,
|
||||
);
|
||||
|
||||
static const TextStyle yekan10 = TextStyle(
|
||||
// Rounded from 10.24
|
||||
fontFamily: yekan,
|
||||
fontWeight: regular,
|
||||
|
||||
@@ -10,6 +10,7 @@ class Assets {
|
||||
static const String iconsEdit = 'assets/icons/edit.svg';
|
||||
static const String iconsFilter = 'assets/icons/filter.svg';
|
||||
static const String iconsKey = 'assets/icons/key.svg';
|
||||
static const String iconsMapMarker = 'assets/icons/map_marker.svg';
|
||||
static const String iconsScan = 'assets/icons/scan.svg';
|
||||
static const String iconsTrash = 'assets/icons/trash.svg';
|
||||
static const String iconsUser = 'assets/icons/user.svg';
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
import 'package:get/get.dart';
|
||||
|
||||
class AuthWithOtpLogic extends GetxController {
|
||||
@override
|
||||
void onReady() {
|
||||
// TODO: implement onReady
|
||||
super.onReady();
|
||||
}
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
// TODO: implement onClose
|
||||
super.onClose();
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
|
||||
import 'logic.dart';
|
||||
|
||||
class AuthWithOtpPage extends StatelessWidget {
|
||||
const AuthWithOtpPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final AuthWithOtpLogic logic = Get.put(AuthWithOtpLogic());
|
||||
|
||||
return Container();
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,60 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:rasadyar_app/presentation/widget/captcha/captcha_widget.dart';
|
||||
|
||||
enum AuthType { useAndPass, otp }
|
||||
|
||||
enum AuthStatus { init }
|
||||
|
||||
enum OtpStatus { init, sent, verified, reSend }
|
||||
|
||||
class AuthWithUseAndPassLogic extends GetxController {
|
||||
Rx<GlobalKey<FormState>> formKey = GlobalKey<FormState>().obs;
|
||||
Rx<GlobalKey<FormState>> formKeyOtp = GlobalKey<FormState>().obs;
|
||||
Rx<GlobalKey<FormState>> formKeySentOtp = GlobalKey<FormState>().obs;
|
||||
Rx<TextEditingController> phoneNumberController = TextEditingController().obs;
|
||||
Rx<TextEditingController> passwordController = TextEditingController().obs;
|
||||
Rx<TextEditingController> phoneOtpNumberController =
|
||||
TextEditingController().obs;
|
||||
Rx<TextEditingController> otpCodeController = TextEditingController().obs;
|
||||
CaptchaController captchaController = CaptchaController();
|
||||
CaptchaController captchaOtpController = CaptchaController();
|
||||
|
||||
RxnString phoneNumber = RxnString(null);
|
||||
RxnString password = RxnString(null);
|
||||
RxBool isOnError = false.obs;
|
||||
RxBool hidePassword = true.obs;
|
||||
Rx<AuthType> authType = AuthType.useAndPass.obs;
|
||||
Rx<AuthStatus> authStatus = AuthStatus.init.obs;
|
||||
Rx<OtpStatus> otpStatus = OtpStatus.init.obs;
|
||||
|
||||
RxInt secondsRemaining = 120.obs;
|
||||
Timer? _timer;
|
||||
|
||||
void startTimer() {
|
||||
_timer?.cancel();
|
||||
secondsRemaining.value = 120;
|
||||
|
||||
_timer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||
if (secondsRemaining.value > 0) {
|
||||
secondsRemaining.value--;
|
||||
} else {
|
||||
timer.cancel();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void stopTimer() {
|
||||
_timer?.cancel();
|
||||
}
|
||||
|
||||
String get timeFormatted {
|
||||
final minutes = secondsRemaining.value ~/ 60;
|
||||
final seconds = secondsRemaining.value % 60;
|
||||
return '${minutes.toString().padLeft(2, '0')}:${seconds.toString().padLeft(2, '0')}';
|
||||
}
|
||||
|
||||
@override
|
||||
void onReady() {
|
||||
@@ -21,7 +64,7 @@ class AuthWithUseAndPassLogic extends GetxController {
|
||||
|
||||
@override
|
||||
void onClose() {
|
||||
// TODO: implement onClose
|
||||
_timer?.cancel();
|
||||
super.onClose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:logger/logger.dart';
|
||||
@@ -9,25 +10,89 @@ import 'package:rasadyar_app/presentation/common/assets.dart';
|
||||
import 'package:rasadyar_app/presentation/widget/buttons/elevated.dart';
|
||||
import 'package:rasadyar_app/presentation/widget/captcha/captcha_widget.dart';
|
||||
import 'package:rasadyar_app/presentation/widget/vec_widget.dart';
|
||||
|
||||
import 'package:supervision/supervision.dart';
|
||||
import 'logic.dart';
|
||||
|
||||
class AuthWithUseAndPassPage extends GetView<AuthWithUseAndPassLogic> {
|
||||
AuthWithUseAndPassPage({super.key});
|
||||
const AuthWithUseAndPassPage({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final AuthWithUseAndPassLogic logic = Get.put(AuthWithUseAndPassLogic());
|
||||
return Scaffold(
|
||||
body: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [SizedBox(height: 80), logoWidget(), loginForm()],
|
||||
children: [
|
||||
SizedBox(height: 80),
|
||||
logoWidget(),
|
||||
ObxValue((types) {
|
||||
switch (types.value) {
|
||||
case AuthType.otp:
|
||||
return otpForm();
|
||||
case AuthType.useAndPass:
|
||||
return useAndPassFrom();
|
||||
}
|
||||
}, controller.authType),
|
||||
|
||||
SizedBox(height: 50),
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: 'مطالعه بیانیه ',
|
||||
style: AppFonts.yekan14.copyWith(
|
||||
color: AppColor.darkGreyDark,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
recognizer: TapGestureRecognizer()..onTap = () {},
|
||||
text: 'حریم خصوصی',
|
||||
style: AppFonts.yekan14.copyWith(
|
||||
color: AppColor.blueNormal,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 18),
|
||||
|
||||
ObxValue((types) {
|
||||
return RichText(
|
||||
text: TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
recognizer:
|
||||
TapGestureRecognizer()
|
||||
..onTap = () {
|
||||
if (controller.authType.value == AuthType.otp) {
|
||||
controller.authType.value = AuthType.useAndPass;
|
||||
if (controller.otpStatus.value !=
|
||||
OtpStatus.init) {
|
||||
controller.otpStatus.value = OtpStatus.init;
|
||||
}
|
||||
} else {
|
||||
controller.authType.value = AuthType.otp;
|
||||
}
|
||||
},
|
||||
text:
|
||||
controller.authType.value == AuthType.otp
|
||||
? 'ورود با رمز ثابت'
|
||||
: 'ورود با رمز یکبار مصرف',
|
||||
|
||||
style: AppFonts.yekan14.copyWith(
|
||||
color: AppColor.blueNormal,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}, controller.authType),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget loginForm() {
|
||||
Widget useAndPassFrom() {
|
||||
return ObxValue((data) {
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 30, vertical: 50),
|
||||
@@ -44,8 +109,8 @@ class AuthWithUseAndPassPage extends GetView<AuthWithUseAndPassLogic> {
|
||||
gapPadding: 11,
|
||||
),
|
||||
labelText: 'شماره موبایل',
|
||||
labelStyle: AppFonts.yekan13Regular,
|
||||
errorStyle: AppFonts.yekan13Regular.copyWith(
|
||||
labelStyle: AppFonts.yekan13,
|
||||
errorStyle: AppFonts.yekan13.copyWith(
|
||||
color: AppColor.redNormal,
|
||||
),
|
||||
|
||||
@@ -79,6 +144,7 @@ class AuthWithUseAndPassPage extends GetView<AuthWithUseAndPassLogic> {
|
||||
if (controller.isOnError.value) {
|
||||
controller.isOnError.value = !controller.isOnError.value;
|
||||
data.value.currentState?.reset();
|
||||
|
||||
data.refresh();
|
||||
phoneController.value.text = value;
|
||||
}
|
||||
@@ -93,7 +159,7 @@ class AuthWithUseAndPassPage extends GetView<AuthWithUseAndPassLogic> {
|
||||
}
|
||||
return null;
|
||||
},
|
||||
style: AppFonts.yekan13Regular,
|
||||
style: AppFonts.yekan13,
|
||||
);
|
||||
}, controller.phoneNumberController),
|
||||
|
||||
@@ -109,8 +175,8 @@ class AuthWithUseAndPassPage extends GetView<AuthWithUseAndPassLogic> {
|
||||
gapPadding: 11,
|
||||
),
|
||||
labelText: 'رمز عبور',
|
||||
labelStyle: AppFonts.yekan13Regular,
|
||||
errorStyle: AppFonts.yekan13Regular.copyWith(
|
||||
labelStyle: AppFonts.yekan13,
|
||||
errorStyle: AppFonts.yekan13.copyWith(
|
||||
color: AppColor.redNormal,
|
||||
),
|
||||
|
||||
@@ -157,10 +223,9 @@ class AuthWithUseAndPassPage extends GetView<AuthWithUseAndPassLogic> {
|
||||
}
|
||||
return null;
|
||||
},
|
||||
style: AppFonts.yekan13Regular,
|
||||
style: AppFonts.yekan13,
|
||||
);
|
||||
}, controller.passwordController),
|
||||
|
||||
SizedBox(height: 26),
|
||||
|
||||
CaptchaWidget(controller: controller.captchaController),
|
||||
@@ -173,7 +238,7 @@ class AuthWithUseAndPassPage extends GetView<AuthWithUseAndPassLogic> {
|
||||
di.get<Logger>().t(controller.captchaController.validate());
|
||||
if (data.value.currentState?.validate() == true &&
|
||||
controller.captchaController.validate()) {
|
||||
print("==============>ssakldjaskljdklasjd");
|
||||
Get.toNamed(SupervisionRoutes.supervision);
|
||||
}
|
||||
},
|
||||
width: Get.width,
|
||||
@@ -186,6 +251,257 @@ class AuthWithUseAndPassPage extends GetView<AuthWithUseAndPassLogic> {
|
||||
}, controller.formKey);
|
||||
}
|
||||
|
||||
Widget otpForm() {
|
||||
return ObxValue((status) {
|
||||
switch (status.value) {
|
||||
case OtpStatus.init:
|
||||
return sendCodeForm();
|
||||
case OtpStatus.sent:
|
||||
case OtpStatus.verified:
|
||||
case OtpStatus.reSend:
|
||||
return confirmCodeForm();
|
||||
}
|
||||
}, controller.otpStatus);
|
||||
}
|
||||
|
||||
Widget sendCodeForm() {
|
||||
return ObxValue((data) {
|
||||
return Form(
|
||||
key: data.value,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 30, vertical: 50),
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(height: 26),
|
||||
ObxValue((phoneController) {
|
||||
return TextFormField(
|
||||
controller: phoneController.value,
|
||||
decoration: InputDecoration(
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
gapPadding: 11,
|
||||
),
|
||||
labelText: 'شماره موبایل',
|
||||
labelStyle: AppFonts.yekan13,
|
||||
errorStyle: AppFonts.yekan13.copyWith(
|
||||
color: AppColor.redNormal,
|
||||
),
|
||||
prefixIconConstraints: BoxConstraints(
|
||||
maxHeight: 40,
|
||||
minHeight: 40,
|
||||
maxWidth: 40,
|
||||
minWidth: 40,
|
||||
),
|
||||
prefixIcon: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(0, 8, 6, 8),
|
||||
child: vecWidget(Assets.vecCallSvg),
|
||||
),
|
||||
suffix:
|
||||
phoneController.value.text.trim().isNotEmpty
|
||||
? clearButton(() {
|
||||
phoneController.value.clear();
|
||||
phoneController.refresh();
|
||||
})
|
||||
: null,
|
||||
counterText: '',
|
||||
),
|
||||
keyboardType: TextInputType.numberWithOptions(
|
||||
decimal: false,
|
||||
signed: false,
|
||||
),
|
||||
maxLines: 1,
|
||||
maxLength: 11,
|
||||
onChanged: (value) {
|
||||
if (controller.isOnError.value) {
|
||||
controller.isOnError.value = !controller.isOnError.value;
|
||||
data.value.currentState?.reset();
|
||||
data.refresh();
|
||||
phoneController.value.text = value;
|
||||
}
|
||||
phoneController.refresh();
|
||||
},
|
||||
textInputAction: TextInputAction.next,
|
||||
validator: (value) {
|
||||
if (value == null) {
|
||||
return '⚠️ شماره موبایل را وارد کنید';
|
||||
} else if (value.length < 11) {
|
||||
return '⚠️ شماره موبایل باید 11 رقم باشد';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
style: AppFonts.yekan13,
|
||||
);
|
||||
}, controller.phoneOtpNumberController),
|
||||
|
||||
SizedBox(height: 26),
|
||||
|
||||
CaptchaWidget(controller: controller.captchaOtpController),
|
||||
|
||||
SizedBox(height: 23),
|
||||
RElevated(
|
||||
text: 'ارسال رمز یکبار مصرف',
|
||||
onPressed: () {
|
||||
if (data.value.currentState?.validate() == true &&
|
||||
controller.captchaOtpController.validate()) {
|
||||
controller.otpStatus.value = OtpStatus.sent;
|
||||
controller.startTimer();
|
||||
}
|
||||
},
|
||||
width: Get.width,
|
||||
height: 48,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}, controller.formKeyOtp);
|
||||
}
|
||||
|
||||
Widget confirmCodeForm() {
|
||||
return ObxValue((data) {
|
||||
return Form(
|
||||
key: data.value,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 30, vertical: 50),
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(height: 26),
|
||||
|
||||
ObxValue((passwordController) {
|
||||
return TextFormField(
|
||||
controller: passwordController.value,
|
||||
obscureText: controller.hidePassword.value,
|
||||
decoration: InputDecoration(
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
gapPadding: 11,
|
||||
),
|
||||
labelText: 'رمز عبور',
|
||||
labelStyle: AppFonts.yekan13,
|
||||
errorStyle: AppFonts.yekan13.copyWith(
|
||||
color: AppColor.redNormal,
|
||||
),
|
||||
|
||||
prefixIconConstraints: BoxConstraints(
|
||||
maxHeight: 34,
|
||||
minHeight: 34,
|
||||
maxWidth: 34,
|
||||
minWidth: 34,
|
||||
),
|
||||
prefixIcon: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(0, 8, 8, 8),
|
||||
child: vecWidget(Assets.vecKeySvg),
|
||||
),
|
||||
suffix:
|
||||
passwordController.value.text.trim().isNotEmpty
|
||||
? GestureDetector(
|
||||
onTap: () {
|
||||
controller.hidePassword.value =
|
||||
!controller.hidePassword.value;
|
||||
},
|
||||
child: Icon(
|
||||
controller.hidePassword.value
|
||||
? CupertinoIcons.eye
|
||||
: CupertinoIcons.eye_slash,
|
||||
),
|
||||
)
|
||||
: null,
|
||||
counterText: '',
|
||||
),
|
||||
textInputAction: TextInputAction.done,
|
||||
keyboardType: TextInputType.visiblePassword,
|
||||
maxLines: 1,
|
||||
onChanged: (value) {
|
||||
if (controller.isOnError.value) {
|
||||
controller.isOnError.value = !controller.isOnError.value;
|
||||
data.value.currentState?.reset();
|
||||
passwordController.value.text = value;
|
||||
}
|
||||
passwordController.refresh();
|
||||
},
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return '⚠️ رمز عبور را وارد کنید'; // "Please enter the password"
|
||||
}
|
||||
return null;
|
||||
},
|
||||
style: AppFonts.yekan13,
|
||||
);
|
||||
}, controller.passwordController),
|
||||
|
||||
SizedBox(height: 23),
|
||||
|
||||
ObxValue((timer) {
|
||||
if (timer.value == 0) {
|
||||
return TextButton(
|
||||
onPressed: () {
|
||||
controller.otpStatus.value = OtpStatus.reSend;
|
||||
controller.startTimer();
|
||||
},
|
||||
child: Text(
|
||||
style: AppFonts.yekan13.copyWith(
|
||||
color: AppColor.blueNormal,
|
||||
),
|
||||
'ارسال مجدد کد یکبار مصرف',
|
||||
),
|
||||
);
|
||||
} else {
|
||||
return Text(
|
||||
'اعتبار رمز ارسال شده ${controller.timeFormatted}',
|
||||
style: AppFonts.yekan13,
|
||||
);
|
||||
}
|
||||
}, controller.secondsRemaining),
|
||||
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
children: [
|
||||
TextSpan(
|
||||
text: ' کد ارسال شده به شماره ',
|
||||
style: AppFonts.yekan14.copyWith(
|
||||
color: AppColor.darkGreyDark,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
text: controller.phoneOtpNumberController.value.text,
|
||||
style: AppFonts.yekan13Bold.copyWith(
|
||||
color: AppColor.darkGreyDark,
|
||||
),
|
||||
),
|
||||
TextSpan(
|
||||
recognizer:
|
||||
TapGestureRecognizer()
|
||||
..onTap = () {
|
||||
controller.otpStatus.value = OtpStatus.init;
|
||||
controller.captchaOtpController.clear();
|
||||
},
|
||||
text: ' ویرایش',
|
||||
style: AppFonts.yekan14.copyWith(
|
||||
color: AppColor.blueNormal,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(height: 23),
|
||||
RElevated(
|
||||
text: 'ورود',
|
||||
onPressed: () {
|
||||
if (controller.formKeyOtp.value.currentState?.validate() ==
|
||||
true &&
|
||||
controller.captchaOtpController.validate()) {}
|
||||
},
|
||||
width: Get.width,
|
||||
height: 48,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}, controller.formKeySentOtp);
|
||||
}
|
||||
|
||||
Widget logoWidget() {
|
||||
return Column(
|
||||
children: [
|
||||
@@ -193,9 +509,7 @@ class AuthWithUseAndPassPage extends GetView<AuthWithUseAndPassLogic> {
|
||||
Image.asset(Assets.imagesInnerSplash, width: 120, height: 120),
|
||||
Text(
|
||||
'سامانه رصدیار',
|
||||
style: AppFonts.yekan16Regular.copyWith(
|
||||
color: AppColor.darkGreyNormal,
|
||||
),
|
||||
style: AppFonts.yekan16.copyWith(color: AppColor.darkGreyNormal),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/animation.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:rasadyar_app/presentation/routes/app_pages.dart';
|
||||
import 'package:supervision/supervision.dart';
|
||||
|
||||
class SplashLogic extends GetxController with GetTickerProviderStateMixin {
|
||||
late final AnimationController scaleController;
|
||||
@@ -54,7 +55,7 @@ class SplashLogic extends GetxController with GetTickerProviderStateMixin {
|
||||
void onReady() {
|
||||
super.onReady();
|
||||
Future.delayed(const Duration(seconds: 1), () {
|
||||
Get.offAllNamed(AppPaths.authWithUserAndPass);
|
||||
Get.offAllNamed(SupervisionRoutes.supervision);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ class _SystemDesignPageState extends State<SystemDesignPage> {
|
||||
return ListTile(
|
||||
title: Text(
|
||||
"inputs",
|
||||
style: AppFonts.yekan20Regular.copyWith(color: Colors.red),
|
||||
style: AppFonts.yekan20.copyWith(color: Colors.red),
|
||||
),
|
||||
);
|
||||
},
|
||||
@@ -79,11 +79,11 @@ class _SystemDesignPageState extends State<SystemDesignPage> {
|
||||
children: [
|
||||
RTextField(
|
||||
hintText: 'حجم کشتار را در روز به قطعه وارد کنید',
|
||||
hintStyle: AppFonts.yekan13Regular,
|
||||
hintStyle: AppFonts.yekan13,
|
||||
),
|
||||
RTextField(
|
||||
label: 'تلفن مرغداری',
|
||||
labelStyle: AppFonts.yekan10Regular,
|
||||
labelStyle: AppFonts.yekan10,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -98,7 +98,7 @@ class _SystemDesignPageState extends State<SystemDesignPage> {
|
||||
return ListTile(
|
||||
title: Text(
|
||||
"tab",
|
||||
style: AppFonts.yekan20Regular.copyWith(color: Colors.red),
|
||||
style: AppFonts.yekan20.copyWith(color: Colors.red),
|
||||
),
|
||||
);
|
||||
},
|
||||
@@ -119,7 +119,7 @@ class _SystemDesignPageState extends State<SystemDesignPage> {
|
||||
return ListTile(
|
||||
title: Text(
|
||||
"پیجینیشن",
|
||||
style: AppFonts.yekan20Regular.copyWith(color: Colors.red),
|
||||
style: AppFonts.yekan20.copyWith(color: Colors.red),
|
||||
),
|
||||
);
|
||||
},
|
||||
@@ -134,7 +134,7 @@ class _SystemDesignPageState extends State<SystemDesignPage> {
|
||||
return ListTile(
|
||||
title: Text(
|
||||
"Outlined Fab ",
|
||||
style: AppFonts.yekan20Regular.copyWith(color: Colors.green),
|
||||
style: AppFonts.yekan20.copyWith(color: Colors.green),
|
||||
),
|
||||
);
|
||||
},
|
||||
@@ -166,7 +166,7 @@ class _SystemDesignPageState extends State<SystemDesignPage> {
|
||||
return ListTile(
|
||||
title: Text(
|
||||
"Fab",
|
||||
style: AppFonts.yekan20Regular.copyWith(color: Colors.green),
|
||||
style: AppFonts.yekan20.copyWith(color: Colors.green),
|
||||
),
|
||||
);
|
||||
},
|
||||
@@ -234,7 +234,7 @@ class _SystemDesignPageState extends State<SystemDesignPage> {
|
||||
return ListTile(
|
||||
title: Text(
|
||||
"دکمه ها",
|
||||
style: AppFonts.yekan20Regular.copyWith(color: Colors.green),
|
||||
style: AppFonts.yekan20.copyWith(color: Colors.green),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import 'package:get/get.dart';
|
||||
import 'package:rasadyar_app/presentation/pages/auth/auth_with_otp/logic.dart';
|
||||
import 'package:rasadyar_app/presentation/pages/auth/auth_with_otp/view.dart';
|
||||
import 'package:rasadyar_app/presentation/pages/auth/auth_with_use_and_pass/logic.dart';
|
||||
import 'package:rasadyar_app/presentation/pages/auth/auth_with_use_and_pass/view.dart';
|
||||
import 'package:rasadyar_app/presentation/pages/splash/logic.dart';
|
||||
import 'package:rasadyar_app/presentation/pages/splash/view.dart';
|
||||
import 'package:supervision/supervision.dart';
|
||||
|
||||
part 'app_paths.dart';
|
||||
|
||||
@@ -19,15 +18,12 @@ sealed class AppPages {
|
||||
page: () => SplashPage(),
|
||||
binding: BindingsBuilder.put(() => SplashLogic()),
|
||||
),
|
||||
GetPage(
|
||||
name: AppPaths.authWithOtp,
|
||||
page: () => AuthWithOtpPage(),
|
||||
binding: BindingsBuilder.put(() => AuthWithOtpLogic()),
|
||||
),
|
||||
GetPage(
|
||||
name: AppPaths.authWithUserAndPass,
|
||||
page: () => AuthWithUseAndPassPage(),
|
||||
binding: BindingsBuilder.put(() => AuthWithUseAndPassLogic()),
|
||||
),
|
||||
|
||||
...SupervisionPages.pages,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ class _RElevatedState extends State<RElevated> {
|
||||
),
|
||||
fixedSize: Size(widget.width, widget.height),
|
||||
padding: EdgeInsets.zero,
|
||||
textStyle: widget.textStyle ?? AppFonts.yekan24Regular,
|
||||
textStyle: widget.textStyle ?? AppFonts.yekan24,
|
||||
),
|
||||
child: Text(widget.text),
|
||||
);
|
||||
|
||||
@@ -92,7 +92,7 @@ class _ROutlinedElevatedState extends State<ROutlinedElevated> {
|
||||
padding: WidgetStatePropertyAll(EdgeInsets.zero),
|
||||
textStyle: WidgetStatePropertyAll(
|
||||
widget.textStyle ??
|
||||
AppFonts.yekan24Regular.copyWith(color: AppColor.blueNormal),
|
||||
AppFonts.yekan24.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
),
|
||||
child: Text(widget.text),
|
||||
|
||||
@@ -7,12 +7,12 @@ class RTextButton extends StatefulWidget {
|
||||
super.key,
|
||||
required this.text,
|
||||
required this.onPressed,
|
||||
foregroundColor,
|
||||
backgroundColor,
|
||||
borderColor,
|
||||
disabledBackgroundColor,
|
||||
radius,
|
||||
textStyle,
|
||||
this.foregroundColor,
|
||||
this.backgroundColor,
|
||||
this.borderColor,
|
||||
this.disabledBackgroundColor,
|
||||
this.radius,
|
||||
this.textStyle,
|
||||
this.width = 150.0,
|
||||
this.height = 56.0,
|
||||
});
|
||||
@@ -67,7 +67,7 @@ class _RTextButtonState extends State<RTextButton> {
|
||||
padding: WidgetStatePropertyAll(EdgeInsets.zero),
|
||||
textStyle: WidgetStatePropertyAll(
|
||||
widget.textStyle ??
|
||||
AppFonts.yekan24Regular.copyWith(color: AppColor.blueNormal),
|
||||
AppFonts.yekan24.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
),
|
||||
onPressed:widget.onPressed,
|
||||
|
||||
@@ -177,7 +177,7 @@ class _CaptchaWidgetState extends State<CaptchaWidget> {
|
||||
),
|
||||
Text(
|
||||
widget.controller.captchaCode.toString(),
|
||||
style: AppFonts.yekan24Regular,
|
||||
style: AppFonts.yekan24,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -203,8 +203,8 @@ class _CaptchaWidgetState extends State<CaptchaWidget> {
|
||||
gapPadding: 11,
|
||||
),
|
||||
labelText: 'کد امنیتی',
|
||||
labelStyle: AppFonts.yekan13Regular,
|
||||
errorStyle: AppFonts.yekan10Regular.copyWith(
|
||||
labelStyle: AppFonts.yekan13,
|
||||
errorStyle: AppFonts.yekan10.copyWith(
|
||||
color: AppColor.redNormal,
|
||||
fontSize: 8,
|
||||
),
|
||||
@@ -249,7 +249,7 @@ class _CaptchaWidgetState extends State<CaptchaWidget> {
|
||||
}
|
||||
return null;
|
||||
},
|
||||
style: AppFonts.yekan13Regular,
|
||||
style: AppFonts.yekan13,
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
@@ -45,7 +45,7 @@ class _PaginationFromUntilState extends State<PaginationFromUntil> {
|
||||
'$current از $total',
|
||||
textAlign: TextAlign.center,
|
||||
textDirection: TextDirection.rtl,
|
||||
style: AppFonts.yekan16Regular.copyWith(
|
||||
style: AppFonts.yekan16.copyWith(
|
||||
color: AppColor.blueNormal,
|
||||
),
|
||||
),
|
||||
|
||||
@@ -64,7 +64,7 @@ class _RShowMoreState extends State<RShowMore>
|
||||
child: Text(
|
||||
_toggled ? 'کمتر' : 'مشاهده بیشتر',
|
||||
key: ValueKey(_toggled),
|
||||
style: AppFonts.yekan10Regular.copyWith(color: AppColor.blueNormal),
|
||||
style: AppFonts.yekan10.copyWith(color: AppColor.blueNormal),
|
||||
),
|
||||
),
|
||||
SizedBox(height: 50,)
|
||||
|
||||
@@ -70,14 +70,14 @@ class _CupertinoSegmentedControlDemoState2
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(50)
|
||||
),
|
||||
child: Text('لاشه', style: AppFonts.yekan13Regular),
|
||||
child: Text('لاشه', style: AppFonts.yekan13),
|
||||
),
|
||||
1: Container(
|
||||
padding: EdgeInsets.all(10),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(50)
|
||||
),
|
||||
child: Text('زنده', style: AppFonts.yekan13Regular),
|
||||
child: Text('زنده', style: AppFonts.yekan13),
|
||||
),
|
||||
};
|
||||
|
||||
|
||||
3
packages/core/lib/core.dart
Normal file
3
packages/core/lib/core.dart
Normal file
@@ -0,0 +1,3 @@
|
||||
library ;
|
||||
|
||||
export 'package:get/get.dart';
|
||||
61
packages/core/pubspec.yaml
Normal file
61
packages/core/pubspec.yaml
Normal file
@@ -0,0 +1,61 @@
|
||||
name: rasadyar_core
|
||||
description: "A new Flutter project."
|
||||
publish_to: 'none'
|
||||
version: 1.0.0+1
|
||||
|
||||
environment:
|
||||
sdk: ^3.7.0
|
||||
|
||||
dependencies:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
|
||||
|
||||
cupertino_icons: ^1.0.8
|
||||
|
||||
##Log
|
||||
logger: ^2.5.0
|
||||
|
||||
## reactive
|
||||
dartx: ^1.2.0
|
||||
rxdart: ^0.28.0
|
||||
|
||||
## local storage
|
||||
hive_ce: ^2.10.1
|
||||
hive_ce_flutter: ^2.2.0
|
||||
|
||||
##code generation
|
||||
freezed_annotation: ^3.0.0
|
||||
json_annotation: ^4.9.0
|
||||
|
||||
|
||||
#SVG
|
||||
flutter_svg: ^2.0.17
|
||||
|
||||
##state manger
|
||||
get: ^4.7.2
|
||||
|
||||
##Di
|
||||
get_it: ^8.0.3
|
||||
|
||||
|
||||
permission_handler: ^11.4.0
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^5.0.0
|
||||
##code generation
|
||||
build_runner: ^2.4.15
|
||||
hive_ce_generator: ^1.8.2
|
||||
freezed: ^3.0.3
|
||||
json_serializable: ^6.9.4
|
||||
|
||||
##test
|
||||
mocktail: ^1.0.4
|
||||
get_test: ^4.0.1
|
||||
|
||||
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
235
pubspec.lock
235
pubspec.lock
@@ -169,6 +169,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.8"
|
||||
dart_earcut:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: dart_earcut
|
||||
sha256: e485001bfc05dcbc437d7bfb666316182e3522d4c3f9668048e004d0eb2ce43b
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.0"
|
||||
dart_style:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -230,6 +238,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.0.0"
|
||||
flutter_map:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_map
|
||||
sha256: f7d0379477274f323c3f3bc12d369a2b42eb86d1e7bd2970ae1ea3cff782449a
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.1.1"
|
||||
flutter_svg:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -243,6 +259,11 @@ packages:
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_web_plugins:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
freezed:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
@@ -267,6 +288,54 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.0.0"
|
||||
geolocator:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: geolocator
|
||||
sha256: f62bcd90459e63210bbf9c35deb6a51c521f992a78de19a1fe5c11704f9530e2
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "13.0.4"
|
||||
geolocator_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: geolocator_android
|
||||
sha256: fcb1760a50d7500deca37c9a666785c047139b5f9ee15aa5469fae7dbbe3170d
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.6.2"
|
||||
geolocator_apple:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: geolocator_apple
|
||||
sha256: dbdd8789d5aaf14cf69f74d4925ad1336b4433a6efdf2fce91e8955dc921bf22
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.13"
|
||||
geolocator_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: geolocator_platform_interface
|
||||
sha256: "30cb64f0b9adcc0fb36f628b4ebf4f731a2961a0ebd849f4b56200205056fe67"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.2.6"
|
||||
geolocator_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: geolocator_web
|
||||
sha256: b1ae9bdfd90f861fde8fd4f209c37b953d65e92823cb73c7dee1fa021b06f172
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.1.3"
|
||||
geolocator_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: geolocator_windows
|
||||
sha256: "175435404d20278ffd220de83c2ca293b73db95eafbdc8131fe8609be1421eb6"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.5"
|
||||
get:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -355,6 +424,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.1.2"
|
||||
intl:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: intl
|
||||
sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.20.2"
|
||||
io:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -387,6 +464,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.9.4"
|
||||
latlong2:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: latlong2
|
||||
sha256: "98227922caf49e6056f91b6c56945ea1c7b166f28ffcd5fb8e72fc0b453cc8fe"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.9.1"
|
||||
leak_tracker:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -419,6 +504,38 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.1.1"
|
||||
lists:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: lists
|
||||
sha256: "4ca5c19ae4350de036a7e996cdd1ee39c93ac0a2b840f4915459b7d0a7d4ab27"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
location:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: location
|
||||
sha256: c2c4304071ec860525d5c50d142410072f8620c1d9f74874811af2e804e1a9c8
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.0.0"
|
||||
location_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: location_platform_interface
|
||||
sha256: a3404ea6d74e89b121630be62ed8edcc7b39fd108bd19805d0ae55c397135dd7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.0.0"
|
||||
location_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: location_web
|
||||
sha256: "744bdff53dc455a2dc9a34474c49cde364d4fbef2aee009f8b0b4b68570c27a1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.0.0"
|
||||
logger:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -459,6 +576,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.16.0"
|
||||
mgrs_dart:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: mgrs_dart
|
||||
sha256: fb89ae62f05fa0bb90f70c31fc870bcbcfd516c843fb554452ab3396f78586f7
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
mime:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -555,6 +680,54 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.0"
|
||||
permission_handler:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler
|
||||
sha256: "59adad729136f01ea9e35a48f5d1395e25cba6cea552249ddbe9cf950f5d7849"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "11.4.0"
|
||||
permission_handler_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_android
|
||||
sha256: d3971dcdd76182a0c198c096b5db2f0884b0d4196723d21a866fc4cdea057ebc
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "12.1.0"
|
||||
permission_handler_apple:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_apple
|
||||
sha256: f84a188e79a35c687c132a0a0556c254747a08561e99ab933f12f6ca71ef3c98
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "9.4.6"
|
||||
permission_handler_html:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_html
|
||||
sha256: "38f000e83355abb3392140f6bc3030660cfaef189e1f87824facb76300b4ff24"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.3+5"
|
||||
permission_handler_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_platform_interface
|
||||
sha256: eb99b295153abce5d683cac8c02e22faab63e50679b937fa1bf67d58bb282878
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.3.0"
|
||||
permission_handler_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: permission_handler_windows
|
||||
sha256: "1a790728016f79a41216d88672dbc5df30e686e811ad4e698bfc51f76ad91f1e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.1"
|
||||
petitparser:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -579,6 +752,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.8"
|
||||
polylabel:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: polylabel
|
||||
sha256: "41b9099afb2aa6c1730bdd8a0fab1400d287694ec7615dd8516935fa3144214b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.1"
|
||||
pool:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -587,6 +768,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.5.1"
|
||||
proj4dart:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: proj4dart
|
||||
sha256: c8a659ac9b6864aa47c171e78d41bbe6f5e1d7bd790a5814249e6b68bc44324e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
pub_semver:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -603,6 +792,13 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.5.0"
|
||||
rasadyar_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
path: "packages/core"
|
||||
relative: true
|
||||
source: path
|
||||
version: "1.0.0+1"
|
||||
rxdart:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@@ -656,6 +852,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.10.1"
|
||||
sprintf:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: sprintf
|
||||
sha256: "1fc9ffe69d4df602376b52949af107d8f5703b77cda567c4d7d86a0693120f23"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.0"
|
||||
stack_trace:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -688,6 +892,13 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.1"
|
||||
supervision:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
path: "features/supervision"
|
||||
relative: true
|
||||
source: path
|
||||
version: "1.0.0"
|
||||
term_glyph:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -728,6 +939,22 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
unicode:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: unicode
|
||||
sha256: "0f69e46593d65245774d4f17125c6084d2c20b4e473a983f6e21b7d7762218f1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.3.1"
|
||||
uuid:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: uuid
|
||||
sha256: a5be9ef6618a7ac1e964353ef476418026db906c4facdedaa299b7a2e71690ff
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.5.1"
|
||||
vector_graphics:
|
||||
dependency: transitive
|
||||
description:
|
||||
@@ -800,6 +1027,14 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.2"
|
||||
wkt_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: wkt_parser
|
||||
sha256: "8a555fc60de3116c00aad67891bcab20f81a958e4219cc106e3c037aa3937f13"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.0"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
name: rasadyar_app
|
||||
description: "A new Flutter project."
|
||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
publish_to: 'none'
|
||||
version: 1.0.0+1
|
||||
|
||||
environment:
|
||||
@@ -38,6 +38,10 @@ dependencies:
|
||||
##Di
|
||||
get_it: ^8.0.3
|
||||
|
||||
|
||||
supervision:
|
||||
path: ./features/supervision
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
@@ -54,6 +58,9 @@ dev_dependencies:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
|
||||
|
||||
Reference in New Issue
Block a user