Code changes by azmat
This commit is contained in:
@@ -0,0 +1,52 @@
|
||||
import 'dart:math' as math;
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Attendance math + filter rules (shared by UI and background service).
|
||||
//
|
||||
// Simple version:
|
||||
// - Wake every 5 min, take ONE gps reading, sleep again (battery safe).
|
||||
// - Throw away weak readings (error > 50 m).
|
||||
// - Throw away tiny jumps (< 20 m) so sitting still never invents fake km.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// How often the background service takes one GPS reading.
|
||||
const Duration kFixInterval = Duration(minutes: 5);
|
||||
|
||||
/// Max seconds to wait for a single GPS fix before giving up.
|
||||
const Duration kFixTimeout = Duration(seconds: 30);
|
||||
|
||||
/// Discard any fix whose own accuracy error is worse than this (meters).
|
||||
const double kMaxAcceptableAccuracyMeters = 50.0;
|
||||
|
||||
/// Ignore movement smaller than this (meters) - kills stationary drift.
|
||||
const double kMinMoveMeters = 20.0;
|
||||
|
||||
/// Straight-line distance between two lat/lng points, in meters.
|
||||
double haversineMeters(double lat1, double lon1, double lat2, double lon2) {
|
||||
const double earthRadius = 6371000.0; // meters
|
||||
final double dLat = _toRadians(lat2 - lat1);
|
||||
final double dLon = _toRadians(lon2 - lon1);
|
||||
final double a = math.sin(dLat / 2) * math.sin(dLat / 2) +
|
||||
math.cos(_toRadians(lat1)) *
|
||||
math.cos(_toRadians(lat2)) *
|
||||
math.sin(dLon / 2) *
|
||||
math.sin(dLon / 2);
|
||||
final double c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a));
|
||||
return earthRadius * c;
|
||||
}
|
||||
|
||||
double _toRadians(double degrees) => degrees * math.pi / 180.0;
|
||||
|
||||
/// Decides whether a new fix is worth storing. Returns true only when the
|
||||
/// reading is strong enough AND the person actually moved.
|
||||
bool shouldStorePoint({
|
||||
required double accuracy,
|
||||
required double distanceFromLastMeters,
|
||||
required bool isFirstPoint,
|
||||
}) {
|
||||
if (accuracy > kMaxAcceptableAccuracyMeters) return false; // weak signal
|
||||
if (!isFirstPoint && distanceFromLastMeters < kMinMoveMeters) {
|
||||
return false; // standing still (drift)
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,284 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_foreground_task/flutter_foreground_task.dart';
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
import 'package:permission_handler/permission_handler.dart' as ph;
|
||||
|
||||
import 'attendance_math.dart';
|
||||
import 'attendance_storage.dart';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Background attendance tracking (wake every 5 min -> one GPS fix -> sleep).
|
||||
//
|
||||
// The task handler runs in a background isolate. It reads the open session id
|
||||
// that the UI saved, takes one fix, applies the accuracy/drift filters and
|
||||
// stores accepted dots in sqflite. It also pings the UI with live totals.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Entry point for the background isolate. Must stay top-level.
|
||||
@pragma('vm:entry-point')
|
||||
void attendanceCallback() {
|
||||
FlutterForegroundTask.setTaskHandler(AttendanceTaskHandler());
|
||||
}
|
||||
|
||||
class AttendanceTaskHandler extends TaskHandler {
|
||||
String? _sessionId;
|
||||
|
||||
@override
|
||||
Future<void> onStart(DateTime timestamp, TaskStarter starter) async {
|
||||
try {
|
||||
_sessionId =
|
||||
await FlutterForegroundTask.getData(key: 'attendance_session_id')
|
||||
as String?;
|
||||
} catch (_) {
|
||||
_sessionId = null;
|
||||
}
|
||||
// Fallback: SharedPreferences is visible from this isolate too.
|
||||
_sessionId ??= await AttendanceStorage.getActiveSession();
|
||||
}
|
||||
|
||||
@override
|
||||
void onRepeatEvent(DateTime timestamp) async {
|
||||
final String? sessionId = _sessionId ?? await _refreshSessionId();
|
||||
if (sessionId == null) return; // punched out already, nothing to do
|
||||
|
||||
try {
|
||||
final Position pos = await Geolocator.getCurrentPosition(
|
||||
locationSettings: LocationSettings(
|
||||
accuracy: LocationAccuracy.high,
|
||||
timeLimit: kFixTimeout,
|
||||
),
|
||||
);
|
||||
|
||||
final List<Map<String, dynamic>> existing =
|
||||
await AttendanceStorage.getPoints(sessionId);
|
||||
final bool isFirst = existing.isEmpty;
|
||||
double distanceFromLast = 0;
|
||||
if (!isFirst) {
|
||||
final last = existing.last;
|
||||
distanceFromLast = haversineMeters(
|
||||
(last['lat'] as num).toDouble(),
|
||||
(last['lng'] as num).toDouble(),
|
||||
pos.latitude,
|
||||
pos.longitude,
|
||||
);
|
||||
}
|
||||
|
||||
final bool keep = shouldStorePoint(
|
||||
accuracy: pos.accuracy,
|
||||
distanceFromLastMeters: distanceFromLast,
|
||||
isFirstPoint: isFirst,
|
||||
);
|
||||
|
||||
if (keep) {
|
||||
await AttendanceStorage.insertPoint(
|
||||
sessionId: sessionId,
|
||||
lat: pos.latitude,
|
||||
lng: pos.longitude,
|
||||
accuracy: pos.accuracy,
|
||||
isMocked: pos.isMocked,
|
||||
timestamp: pos.timestamp,
|
||||
);
|
||||
}
|
||||
|
||||
// Live totals for the open punch page (harmless if nobody listens).
|
||||
final updated = await AttendanceStorage.getPoints(sessionId);
|
||||
final double km = _totalKm(updated);
|
||||
FlutterForegroundTask.sendDataToMain({
|
||||
'sessionId': sessionId,
|
||||
'points': updated.length,
|
||||
'km': km,
|
||||
});
|
||||
try {
|
||||
await FlutterForegroundTask.updateService(
|
||||
notificationTitle: 'Duty tracking ON',
|
||||
notificationText:
|
||||
'${updated.length} points • ${km.toStringAsFixed(2)} km',
|
||||
);
|
||||
} catch (_) {}
|
||||
} catch (_) {
|
||||
// GPS off / timeout / no fix this round - just wait for next 5-min tick.
|
||||
}
|
||||
}
|
||||
|
||||
Future<String?> _refreshSessionId() async {
|
||||
_sessionId = await AttendanceStorage.getActiveSession();
|
||||
return _sessionId;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> onDestroy(DateTime timestamp, bool isTimeout) async {}
|
||||
|
||||
double _totalKm(List<Map<String, dynamic>> points) {
|
||||
double meters = 0;
|
||||
for (int i = 1; i < points.length; i++) {
|
||||
meters += haversineMeters(
|
||||
(points[i - 1]['lat'] as num).toDouble(),
|
||||
(points[i - 1]['lng'] as num).toDouble(),
|
||||
(points[i]['lat'] as num).toDouble(),
|
||||
(points[i]['lng'] as num).toDouble(),
|
||||
);
|
||||
}
|
||||
return meters / 1000.0;
|
||||
}
|
||||
}
|
||||
|
||||
/// Small result for the permission flow so the UI can explain, not just fail.
|
||||
class PermissionResult {
|
||||
final bool ok;
|
||||
final String message;
|
||||
PermissionResult(this.ok, this.message);
|
||||
}
|
||||
|
||||
class AttendanceService {
|
||||
static bool _initialized = false;
|
||||
|
||||
/// Call once from main() before runApp().
|
||||
static void initService() {
|
||||
if (_initialized) return;
|
||||
FlutterForegroundTask.init(
|
||||
androidNotificationOptions: AndroidNotificationOptions(
|
||||
channelId: 'attendance_tracking',
|
||||
channelName: 'Duty tracking',
|
||||
channelDescription:
|
||||
'Shows while your duty location is being recorded.',
|
||||
),
|
||||
iosNotificationOptions: const IOSNotificationOptions(
|
||||
showNotification: true,
|
||||
),
|
||||
foregroundTaskOptions: ForegroundTaskOptions(
|
||||
eventAction: ForegroundTaskEventAction.repeat(
|
||||
kFixInterval.inMilliseconds,
|
||||
),
|
||||
allowWakeLock: true,
|
||||
allowWifiLock: false,
|
||||
autoRunOnBoot: false,
|
||||
// Swiping the app away from recents must NOT stop duty tracking.
|
||||
stopWithTask: false,
|
||||
),
|
||||
);
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
/// Asks (in order): location -> always/background -> notifications + GPS on.
|
||||
static Future<PermissionResult> ensurePermissions() async {
|
||||
final bool serviceOn = await Geolocator.isLocationServiceEnabled();
|
||||
if (!serviceOn) {
|
||||
return PermissionResult(
|
||||
false, 'Please switch ON location (GPS) and try again.');
|
||||
}
|
||||
|
||||
ph.PermissionStatus loc = await ph.Permission.location.request();
|
||||
if (!loc.isGranted) {
|
||||
return PermissionResult(
|
||||
false, 'Location permission is needed for punch in.');
|
||||
}
|
||||
|
||||
// Android 10+: background needs its own grant (may open Settings).
|
||||
ph.PermissionStatus always = await ph.Permission.locationAlways.request();
|
||||
if (!always.isGranted) {
|
||||
return PermissionResult(true,
|
||||
'Background not granted - tracking works only while the app is open.');
|
||||
}
|
||||
|
||||
await ph.Permission.notification.request(); // for the tracking notice
|
||||
return PermissionResult(true, ' granted');
|
||||
}
|
||||
|
||||
static Future<bool> get isPunchedIn async {
|
||||
if (!await FlutterForegroundTask.isRunningService) {
|
||||
// Service dead but prefs say open (reboot/crash) -> still show open.
|
||||
return await AttendanceStorage.getActiveSession() != null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Starts a duty session + background tracking. Returns the session id.
|
||||
static Future<String> punchIn() async {
|
||||
final String sessionId =
|
||||
'SES-${DateTime.now().millisecondsSinceEpoch}';
|
||||
final DateTime now = DateTime.now();
|
||||
await AttendanceStorage.createSession(sessionId, now);
|
||||
await AttendanceStorage.setActiveSession(sessionId);
|
||||
await FlutterForegroundTask.saveData(
|
||||
key: 'attendance_session_id', value: sessionId);
|
||||
|
||||
await FlutterForegroundTask.startService(
|
||||
serviceId: 1001,
|
||||
serviceTypes: [ForegroundServiceTypes.location],
|
||||
notificationTitle: 'Duty tracking ON',
|
||||
notificationText: 'Punched in at ${_hhmm(now)} • recording location',
|
||||
callback: attendanceCallback,
|
||||
);
|
||||
return sessionId;
|
||||
}
|
||||
|
||||
/// Stops tracking and closes the session. Returns a summary for the UI.
|
||||
static Future<Map<String, dynamic>> punchOut() async {
|
||||
final String? sessionId = await AttendanceStorage.getActiveSession();
|
||||
try {
|
||||
await FlutterForegroundTask.stopService();
|
||||
} catch (_) {}
|
||||
await FlutterForegroundTask.clearAllData();
|
||||
await AttendanceStorage.clearActiveSession();
|
||||
|
||||
if (sessionId == null) {
|
||||
return {'points': 0, 'km': 0.0};
|
||||
}
|
||||
final List<Map<String, dynamic>> points =
|
||||
await AttendanceStorage.getPoints(sessionId);
|
||||
double meters = 0;
|
||||
for (int i = 1; i < points.length; i++) {
|
||||
meters += haversineMeters(
|
||||
(points[i - 1]['lat'] as num).toDouble(),
|
||||
(points[i - 1]['lng'] as num).toDouble(),
|
||||
(points[i]['lat'] as num).toDouble(),
|
||||
(points[i]['lng'] as num).toDouble(),
|
||||
);
|
||||
}
|
||||
final double km = meters / 1000.0;
|
||||
final Map<String, dynamic>? session =
|
||||
await AttendanceStorage.getSession(sessionId);
|
||||
await AttendanceStorage.closeSession(sessionId, DateTime.now(), km);
|
||||
return {
|
||||
'sessionId': sessionId,
|
||||
'punchIn': session?['punch_in'],
|
||||
'points': points.length,
|
||||
'km': km,
|
||||
};
|
||||
}
|
||||
|
||||
static String _hhmm(DateTime t) =>
|
||||
'${t.hour.toString().padLeft(2, '0')}:${t.minute.toString().padLeft(2, '0')}';
|
||||
|
||||
/// Nudge to exempt the app from battery optimization (OEMs kill trackers).
|
||||
static Future<void> maybeAskBatteryExemption(BuildContext context) async {
|
||||
try {
|
||||
final bool ignoring =
|
||||
await FlutterForegroundTask.isIgnoringBatteryOptimizations;
|
||||
if (ignoring || !context.mounted) return;
|
||||
final bool? go = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (c) => AlertDialog(
|
||||
title: const Text('Keep tracking running'),
|
||||
content: const Text(
|
||||
'Xiaomi, Oppo, Vivo and Samsung phones stop background tracking '
|
||||
'to save battery. Allow "Unrestricted" battery use for this app '
|
||||
'so duty tracking keeps working when the screen is off?'),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(c).pop(false),
|
||||
child: const Text('Later')),
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(c).pop(true),
|
||||
child: const Text('Open settings')),
|
||||
],
|
||||
),
|
||||
);
|
||||
if (go == true) {
|
||||
await FlutterForegroundTask.requestIgnoreBatteryOptimization();
|
||||
}
|
||||
} catch (_) {}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
import 'package:path/path.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:sqflite/sqflite.dart';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Phone-only storage for attendance (no backend yet).
|
||||
//
|
||||
// - SharedPreferences keeps ONE value: the currently open session id
|
||||
// (so UI, background service and reboot recovery all agree).
|
||||
// - sqflite keeps every session + every GPS dot.
|
||||
//
|
||||
// NOTE: the database handle is opened per-isolate (statics are per-isolate),
|
||||
// so the background service gets its own safe handle.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class AttendanceStorage {
|
||||
static const String _dbName = 'attendance.db';
|
||||
static const String _prefsActiveSessionKey = 'attendance_active_session';
|
||||
|
||||
static Database? _db;
|
||||
|
||||
static Future<Database> get _database async {
|
||||
if (_db != null) return _db!;
|
||||
final String path = join(await getDatabasesPath(), _dbName);
|
||||
_db = await openDatabase(
|
||||
path,
|
||||
version: 1,
|
||||
onCreate: (Database db, int version) async {
|
||||
await db.execute('''
|
||||
CREATE TABLE attendance_sessions(
|
||||
session_id TEXT PRIMARY KEY,
|
||||
punch_in TEXT NOT NULL,
|
||||
punch_out TEXT,
|
||||
status TEXT NOT NULL,
|
||||
total_km_haversine REAL DEFAULT 0
|
||||
)
|
||||
''');
|
||||
await db.execute('''
|
||||
CREATE TABLE attendance_points(
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
session_id TEXT NOT NULL,
|
||||
lat REAL NOT NULL,
|
||||
lng REAL NOT NULL,
|
||||
accuracy REAL NOT NULL,
|
||||
is_mocked INTEGER NOT NULL DEFAULT 0,
|
||||
timestamp TEXT NOT NULL
|
||||
)
|
||||
''');
|
||||
await db.execute('''
|
||||
CREATE INDEX idx_points_session ON attendance_points(session_id)
|
||||
''');
|
||||
},
|
||||
);
|
||||
return _db!;
|
||||
}
|
||||
|
||||
// ---------------- active session (SharedPreferences) ----------------
|
||||
|
||||
static Future<void> setActiveSession(String sessionId) async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString(_prefsActiveSessionKey, sessionId);
|
||||
}
|
||||
|
||||
static Future<String?> getActiveSession() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
return prefs.getString(_prefsActiveSessionKey);
|
||||
}
|
||||
|
||||
static Future<void> clearActiveSession() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.remove(_prefsActiveSessionKey);
|
||||
}
|
||||
|
||||
// ---------------- sessions ----------------
|
||||
|
||||
static Future<void> createSession(String sessionId, DateTime punchIn) async {
|
||||
final db = await _database;
|
||||
await db.insert('attendance_sessions', {
|
||||
'session_id': sessionId,
|
||||
'punch_in': punchIn.toIso8601String(),
|
||||
'punch_out': null,
|
||||
'status': 'OPEN',
|
||||
'total_km_haversine': 0,
|
||||
});
|
||||
}
|
||||
|
||||
static Future<Map<String, dynamic>?> getSession(String sessionId) async {
|
||||
final db = await _database;
|
||||
final rows = await db.query(
|
||||
'attendance_sessions',
|
||||
where: 'session_id = ?',
|
||||
whereArgs: [sessionId],
|
||||
limit: 1,
|
||||
);
|
||||
if (rows.isEmpty) return null;
|
||||
return rows.first;
|
||||
}
|
||||
|
||||
static Future<void> closeSession(
|
||||
String sessionId,
|
||||
DateTime punchOut,
|
||||
double totalKmHaversine,
|
||||
) async {
|
||||
final db = await _database;
|
||||
await db.update(
|
||||
'attendance_sessions',
|
||||
{
|
||||
'punch_out': punchOut.toIso8601String(),
|
||||
'status': 'CLOSED',
|
||||
'total_km_haversine': totalKmHaversine,
|
||||
},
|
||||
where: 'session_id = ?',
|
||||
whereArgs: [sessionId],
|
||||
);
|
||||
}
|
||||
|
||||
static Future<List<Map<String, dynamic>>> getRecentSessions(
|
||||
{int limit = 20}) async {
|
||||
final db = await _database;
|
||||
return db.query(
|
||||
'attendance_sessions',
|
||||
orderBy: 'punch_in DESC',
|
||||
limit: limit,
|
||||
);
|
||||
}
|
||||
|
||||
// ---------------- points ----------------
|
||||
|
||||
static Future<void> insertPoint({
|
||||
required String sessionId,
|
||||
required double lat,
|
||||
required double lng,
|
||||
required double accuracy,
|
||||
required bool isMocked,
|
||||
required DateTime timestamp,
|
||||
}) async {
|
||||
final db = await _database;
|
||||
await db.insert('attendance_points', {
|
||||
'session_id': sessionId,
|
||||
'lat': lat,
|
||||
'lng': lng,
|
||||
'accuracy': accuracy,
|
||||
'is_mocked': isMocked ? 1 : 0,
|
||||
'timestamp': timestamp.toIso8601String(),
|
||||
});
|
||||
}
|
||||
|
||||
static Future<List<Map<String, dynamic>>> getPoints(
|
||||
String sessionId) async {
|
||||
final db = await _database;
|
||||
return db.query(
|
||||
'attendance_points',
|
||||
where: 'session_id = ?',
|
||||
whereArgs: [sessionId],
|
||||
orderBy: 'timestamp ASC',
|
||||
);
|
||||
}
|
||||
|
||||
static Future<int> countPoints(String sessionId) async {
|
||||
final db = await _database;
|
||||
final rows = await db.rawQuery(
|
||||
'SELECT COUNT(*) AS c FROM attendance_points WHERE session_id = ?',
|
||||
[sessionId],
|
||||
);
|
||||
return (rows.first['c'] as int?) ?? 0;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,281 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_foreground_task/flutter_foreground_task.dart';
|
||||
|
||||
import '../../Utils/image_constant.dart';
|
||||
import '../../Utils/size_utils.dart';
|
||||
import '../../theme/app_style.dart';
|
||||
import '../../widgets/app_bar/appbar_image.dart';
|
||||
import '../../widgets/app_bar/appbar_title.dart';
|
||||
import '../../widgets/app_bar/custom_app_bar.dart';
|
||||
import '../../widgets/custom_button.dart';
|
||||
import 'attendance_math.dart';
|
||||
import 'attendance_service.dart';
|
||||
import 'attendance_storage.dart';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Duty punch page: Punch In -> background records one GPS dot every 5 min ->
|
||||
// Punch Out -> summary (points + km). Sessions stay on the phone (sqflite).
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
class PunchScreen extends StatefulWidget {
|
||||
const PunchScreen({super.key});
|
||||
|
||||
@override
|
||||
State<PunchScreen> createState() => _PunchScreenState();
|
||||
}
|
||||
|
||||
class _PunchScreenState extends State<PunchScreen> {
|
||||
bool _punchedIn = false;
|
||||
bool _busy = false;
|
||||
String? _sessionId;
|
||||
String? _punchInTime;
|
||||
int _points = 0;
|
||||
double _km = 0;
|
||||
List<Map<String, dynamic>> _history = [];
|
||||
Timer? _clock;
|
||||
|
||||
void _onTaskData(Object data) {
|
||||
if (data is Map && mounted) {
|
||||
setState(() {
|
||||
_points = (data['points'] as num?)?.toInt() ?? _points;
|
||||
_km = (data['km'] as num?)?.toDouble() ?? _km;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
FlutterForegroundTask.addTaskDataCallback(_onTaskData);
|
||||
_refresh();
|
||||
_clock = Timer.periodic(const Duration(seconds: 30), (_) {
|
||||
if (mounted && _punchedIn) setState(() {});
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
FlutterForegroundTask.removeTaskDataCallback(_onTaskData);
|
||||
_clock?.cancel();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
Future<void> _refresh() async {
|
||||
final bool open = await AttendanceService.isPunchedIn;
|
||||
final String? sid = await AttendanceStorage.getActiveSession();
|
||||
List<Map<String, dynamic>> history =
|
||||
await AttendanceStorage.getRecentSessions(limit: 10);
|
||||
int points = 0;
|
||||
double km = 0;
|
||||
String? punchIn;
|
||||
if (open && sid != null) {
|
||||
final session = await AttendanceStorage.getSession(sid);
|
||||
punchIn = session?['punch_in'] as String?;
|
||||
final pts = await AttendanceStorage.getPoints(sid);
|
||||
points = pts.length;
|
||||
km = _sumKm(pts);
|
||||
}
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
_punchedIn = open;
|
||||
_sessionId = sid;
|
||||
_punchInTime = punchIn;
|
||||
_points = points;
|
||||
_km = km;
|
||||
_history = history;
|
||||
});
|
||||
}
|
||||
|
||||
double _sumKm(List<Map<String, dynamic>> pts) {
|
||||
double meters = 0;
|
||||
for (int i = 1; i < pts.length; i++) {
|
||||
meters += haversineMeters(
|
||||
(pts[i - 1]['lat'] as num).toDouble(),
|
||||
(pts[i - 1]['lng'] as num).toDouble(),
|
||||
(pts[i]['lat'] as num).toDouble(),
|
||||
(pts[i]['lng'] as num).toDouble(),
|
||||
);
|
||||
}
|
||||
return meters / 1000.0;
|
||||
}
|
||||
|
||||
Future<void> _onPunchIn() async {
|
||||
setState(() => _busy = true);
|
||||
try {
|
||||
final PermissionResult perm =
|
||||
await AttendanceService.ensurePermissions();
|
||||
if (!perm.ok) {
|
||||
_msg(perm.message, true);
|
||||
return;
|
||||
}
|
||||
if (perm.message != ' granted') _msg(perm.message, false);
|
||||
await AttendanceService.punchIn();
|
||||
if (mounted) {
|
||||
await AttendanceService.maybeAskBatteryExemption(context);
|
||||
}
|
||||
await _refresh();
|
||||
_msg('Punched in - tracking every 5 min', false);
|
||||
} catch (e) {
|
||||
_msg('Punch in failed: $e', true);
|
||||
} finally {
|
||||
if (mounted) setState(() => _busy = false);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onPunchOut() async {
|
||||
setState(() => _busy = true);
|
||||
try {
|
||||
final Map<String, dynamic> summary = await AttendanceService.punchOut();
|
||||
await _refresh();
|
||||
if (!mounted) return;
|
||||
final double km = (summary['km'] as num).toDouble();
|
||||
final int pts = summary['points'] as int;
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (c) => AlertDialog(
|
||||
title: const Text('Duty summary'),
|
||||
content: Text(
|
||||
'Points recorded: $pts\n'
|
||||
'Distance (straight line): ${km.toStringAsFixed(2)} km\n'
|
||||
'Road distance: coming in step 4 (free API).',
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(c).pop(),
|
||||
child: const Text('OK'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
} catch (e) {
|
||||
_msg('Punch out failed: $e', true);
|
||||
} finally {
|
||||
if (mounted) setState(() => _busy = false);
|
||||
}
|
||||
}
|
||||
|
||||
void _msg(String text, bool isError) {
|
||||
if (!mounted) return;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(text),
|
||||
backgroundColor: isError ? Colors.red : Colors.green,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: CustomAppBar(
|
||||
height: getVerticalSize(49),
|
||||
leadingWidth: 40,
|
||||
leading: AppbarImage(
|
||||
height: getSize(24),
|
||||
width: getSize(24),
|
||||
svgPath: ImageConstant.imgArrowleftBlueGray900,
|
||||
margin: getMargin(left: 16, top: 12, bottom: 13),
|
||||
onTap: () => Navigator.pop(context),
|
||||
),
|
||||
centerTitle: true,
|
||||
title: AppbarTitle(text: 'Duty Punch'),
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
_statusCard(),
|
||||
const SizedBox(height: 16),
|
||||
CustomButton(
|
||||
height: getVerticalSize(50),
|
||||
text: _busy
|
||||
? 'Please wait...'
|
||||
: (_punchedIn ? 'Punch Out' : 'Punch In'),
|
||||
margin: getMargin(top: 8, bottom: 5),
|
||||
onTap: _busy ? () {} : (_punchedIn ? _onPunchOut : _onPunchIn),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'Keeps recording one location every 5 min, even with the app '
|
||||
'minimized. For Xiaomi/Oppo/Vivo/Samsung allow Unrestricted '
|
||||
'battery use or tracking may pause.',
|
||||
style: AppStyle.txtGilroyMedium16Bluegray900.copyWith(
|
||||
fontSize: 12,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Text('Recent duties',
|
||||
style: AppStyle.txtGilroyMedium16Bluegray900.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
)),
|
||||
const SizedBox(height: 8),
|
||||
..._history.map(_historyTile),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _statusCard() {
|
||||
final Color dot = _punchedIn ? Colors.green : Colors.grey;
|
||||
return Card(
|
||||
elevation: 2,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Container(
|
||||
width: 12,
|
||||
height: 12,
|
||||
decoration:
|
||||
BoxDecoration(color: dot, shape: BoxShape.circle),
|
||||
),
|
||||
const SizedBox(width: 8),
|
||||
Text(
|
||||
_punchedIn ? 'Punched IN' : 'Punched OUT',
|
||||
style: const TextStyle(
|
||||
fontSize: 18, fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
Text('Session: ${_sessionId ?? '-'}'),
|
||||
if (_punchInTime != null) Text('Since: $_punchInTime'),
|
||||
const SizedBox(height: 8),
|
||||
Text('Points: $_points',
|
||||
style:
|
||||
const TextStyle(fontSize: 16, fontWeight: FontWeight.w600)),
|
||||
Text('Distance: ${_km.toStringAsFixed(2)} km',
|
||||
style:
|
||||
const TextStyle(fontSize: 16, fontWeight: FontWeight.w600)),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _historyTile(Map<String, dynamic> s) {
|
||||
final String status = (s['status'] ?? '') as String;
|
||||
final double km = ((s['total_km_haversine'] ?? 0) as num).toDouble();
|
||||
return Card(
|
||||
child: ListTile(
|
||||
title: Text('${s['punch_in']}',
|
||||
style: const TextStyle(fontSize: 12)),
|
||||
subtitle: Text(
|
||||
'Out: ${s['punch_out'] ?? '-'} • ${km.toStringAsFixed(2)} km',
|
||||
style: const TextStyle(fontSize: 11)),
|
||||
trailing: Text(status,
|
||||
style: TextStyle(
|
||||
color: status == 'OPEN' ? Colors.green : Colors.grey,
|
||||
fontWeight: FontWeight.bold,
|
||||
)),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,106 +1,106 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:http_parser/http_parser.dart';
|
||||
import 'dart:typed_data';
|
||||
import 'dart:convert';
|
||||
|
||||
import '../../resources/api_constants.dart';
|
||||
import '../LogoutService/Logoutservice.dart';
|
||||
|
||||
class ApiService {
|
||||
final String baseUrl = ApiConstants.baseUrl;
|
||||
final Dio dio = Dio();
|
||||
|
||||
Future<List<Map<String, dynamic>>> getEntities(String token) async {
|
||||
try {
|
||||
dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
final response = await dio.get('$baseUrl/Bookmarks/Bookmarks');
|
||||
|
||||
if (response.statusCode == 401) {
|
||||
LogoutService.logout();
|
||||
}
|
||||
final entities = (response.data as List).cast<Map<String, dynamic>>();
|
||||
return entities;
|
||||
} catch (e) {
|
||||
throw Exception('Failed to get all entities: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> createEntity(
|
||||
String token, Map<String, dynamic> fData, dynamic selectedFile) async {
|
||||
try {
|
||||
String apiUrl = "$baseUrl/Bookmarks/Bookmarks";
|
||||
|
||||
final Uint8List fileBytes = selectedFile.bytes!;
|
||||
final mimeType = lookupMimeType(selectedFile.name!);
|
||||
|
||||
FormData formData = FormData.fromMap({
|
||||
'file': MultipartFile.fromBytes(
|
||||
fileBytes,
|
||||
filename: selectedFile.name!,
|
||||
contentType: MediaType.parse(mimeType!),
|
||||
),
|
||||
'data': jsonEncode(
|
||||
fData), // Convert the map to JSON and include it as a parameter
|
||||
});
|
||||
|
||||
Dio dio = Dio(); // Create a new Dio instance
|
||||
dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
|
||||
final response = await dio.post(apiUrl, data: formData);
|
||||
if (response.statusCode == 401) {
|
||||
LogoutService.logout();
|
||||
}
|
||||
if (response.statusCode == 200) {
|
||||
// Handle successful response
|
||||
print('File uploaded successfully');
|
||||
} else {
|
||||
print('Failed to upload file with status: ${response.statusCode}');
|
||||
}
|
||||
} catch (error) {
|
||||
print('Error occurred during form submission: $error');
|
||||
}
|
||||
}
|
||||
|
||||
String lookupMimeType(String filePath) {
|
||||
final ext = filePath.split('.').last;
|
||||
switch (ext) {
|
||||
case 'jpg':
|
||||
case 'jpeg':
|
||||
return 'image/jpeg';
|
||||
case 'png':
|
||||
return 'image/png';
|
||||
case 'pdf':
|
||||
return 'application/pdf';
|
||||
// Add more cases for other file types as needed
|
||||
default:
|
||||
return 'application/octet-stream'; // Default MIME type
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> updateEntity(
|
||||
String token, int entityId, Map<String, dynamic> entity) async {
|
||||
try {
|
||||
dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
var response =
|
||||
await dio.put('$baseUrl/Bookmarks/Bookmarks/$entityId', data: entity);
|
||||
if (response.statusCode == 401) {
|
||||
LogoutService.logout();
|
||||
}
|
||||
print(entity);
|
||||
} catch (e) {
|
||||
throw Exception('Failed to update entity: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> deleteEntity(String token, int entityId) async {
|
||||
try {
|
||||
dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
var response = await dio.delete('$baseUrl/Bookmarks/Bookmarks/$entityId');
|
||||
if (response.statusCode == 401) {
|
||||
LogoutService.logout();
|
||||
}
|
||||
} catch (e) {
|
||||
throw Exception('Failed to delete entity: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:http_parser/http_parser.dart';
|
||||
import 'dart:typed_data';
|
||||
import 'dart:convert';
|
||||
|
||||
import '../../resources/api_constants.dart';
|
||||
import '../LogoutService/Logoutservice.dart';
|
||||
|
||||
class ApiService {
|
||||
final String baseUrl = ApiConstants.baseUrl;
|
||||
final Dio dio = Dio();
|
||||
|
||||
Future<List<Map<String, dynamic>>> getEntities(String token) async {
|
||||
try {
|
||||
dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
final response = await dio.get('$baseUrl/Bookmarks/Bookmarks');
|
||||
|
||||
if (response.statusCode == 401) {
|
||||
LogoutService.logout();
|
||||
}
|
||||
final entities = (response.data as List).cast<Map<String, dynamic>>();
|
||||
return entities;
|
||||
} catch (e) {
|
||||
throw Exception('Failed to get all entities: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> createEntity(
|
||||
String token, Map<String, dynamic> fData, dynamic selectedFile) async {
|
||||
try {
|
||||
String apiUrl = "$baseUrl/Bookmarks/Bookmarks";
|
||||
|
||||
final Uint8List fileBytes = selectedFile.bytes!;
|
||||
final mimeType = lookupMimeType(selectedFile.name!);
|
||||
|
||||
FormData formData = FormData.fromMap({
|
||||
'file': MultipartFile.fromBytes(
|
||||
fileBytes,
|
||||
filename: selectedFile.name!,
|
||||
contentType: MediaType.parse(mimeType!),
|
||||
),
|
||||
'data': jsonEncode(
|
||||
fData), // Convert the map to JSON and include it as a parameter
|
||||
});
|
||||
|
||||
Dio dio = Dio(); // Create a new Dio instance
|
||||
dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
|
||||
final response = await dio.post(apiUrl, data: formData);
|
||||
if (response.statusCode == 401) {
|
||||
LogoutService.logout();
|
||||
}
|
||||
if (response.statusCode == 200) {
|
||||
// Handle successful response
|
||||
print('File uploaded successfully');
|
||||
} else {
|
||||
print('Failed to upload file with status: ${response.statusCode}');
|
||||
}
|
||||
} catch (error) {
|
||||
print('Error occurred during form submission: $error');
|
||||
}
|
||||
}
|
||||
|
||||
String lookupMimeType(String filePath) {
|
||||
final ext = filePath.split('.').last;
|
||||
switch (ext) {
|
||||
case 'jpg':
|
||||
case 'jpeg':
|
||||
return 'image/jpeg';
|
||||
case 'png':
|
||||
return 'image/png';
|
||||
case 'pdf':
|
||||
return 'application/pdf';
|
||||
// Add more cases for other file types as needed
|
||||
default:
|
||||
return 'application/octet-stream'; // Default MIME type
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> updateEntity(
|
||||
String token, int entityId, Map<String, dynamic> entity) async {
|
||||
try {
|
||||
dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
var response =
|
||||
await dio.put('$baseUrl/Bookmarks/Bookmarks/$entityId', data: entity);
|
||||
if (response.statusCode == 401) {
|
||||
LogoutService.logout();
|
||||
}
|
||||
print(entity);
|
||||
} catch (e) {
|
||||
throw Exception('Failed to update entity: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> deleteEntity(String token, int entityId) async {
|
||||
try {
|
||||
dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
var response = await dio.delete('$baseUrl/Bookmarks/Bookmarks/$entityId');
|
||||
if (response.statusCode == 401) {
|
||||
LogoutService.logout();
|
||||
}
|
||||
} catch (e) {
|
||||
throw Exception('Failed to delete entity: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,111 +1,111 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import '../../providers/token_manager.dart';
|
||||
import 'Bookmarks_api_service.dart';
|
||||
|
||||
class CreateEntityScreen extends StatefulWidget {
|
||||
const CreateEntityScreen({super.key});
|
||||
|
||||
@override
|
||||
_CreateEntityScreenState createState() => _CreateEntityScreenState();
|
||||
}
|
||||
|
||||
class _CreateEntityScreenState extends State<CreateEntityScreen> {
|
||||
final ApiService apiService = ApiService();
|
||||
final Map<String, dynamic> formData = {};
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
var selectedFileupload_Field;
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Create Bookmarks')),
|
||||
body: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
children: [
|
||||
TextFormField(
|
||||
decoration:
|
||||
const InputDecoration(labelText: 'bookmark_firstletter'),
|
||||
onSaved: (value) => formData['bookmark_firstletter'] = value,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(labelText: 'bookmark_link'),
|
||||
onSaved: (value) => formData['bookmark_link'] = value,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextFormField(
|
||||
decoration:
|
||||
const InputDecoration(labelText: 'fileupload_field'),
|
||||
onSaved: (value) => formData['fileupload_field'] = value,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Container(
|
||||
margin: const EdgeInsets.symmetric(vertical: 5), // Add margin
|
||||
child: ElevatedButton(
|
||||
onPressed: () async {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
_formKey.currentState!.save();
|
||||
|
||||
final token = await TokenManager.getToken();
|
||||
try {
|
||||
print("token is : $token");
|
||||
print(formData);
|
||||
|
||||
await apiService.createEntity(
|
||||
token!, formData, selectedFileupload_Field);
|
||||
|
||||
Navigator.pop(context);
|
||||
} catch (e) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: const Text('Error'),
|
||||
content: Text('Failed to create entity: $e'),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: const Text('OK'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
height: 50,
|
||||
child: const Center(
|
||||
child: Text(
|
||||
'SUBMIT',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import '../../providers/token_manager.dart';
|
||||
import 'Bookmarks_api_service.dart';
|
||||
|
||||
class CreateEntityScreen extends StatefulWidget {
|
||||
const CreateEntityScreen({super.key});
|
||||
|
||||
@override
|
||||
_CreateEntityScreenState createState() => _CreateEntityScreenState();
|
||||
}
|
||||
|
||||
class _CreateEntityScreenState extends State<CreateEntityScreen> {
|
||||
final ApiService apiService = ApiService();
|
||||
final Map<String, dynamic> formData = {};
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
var selectedFileupload_Field;
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Create Bookmarks')),
|
||||
body: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
children: [
|
||||
TextFormField(
|
||||
decoration:
|
||||
const InputDecoration(labelText: 'bookmark_firstletter'),
|
||||
onSaved: (value) => formData['bookmark_firstletter'] = value,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(labelText: 'bookmark_link'),
|
||||
onSaved: (value) => formData['bookmark_link'] = value,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextFormField(
|
||||
decoration:
|
||||
const InputDecoration(labelText: 'fileupload_field'),
|
||||
onSaved: (value) => formData['fileupload_field'] = value,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Container(
|
||||
margin: const EdgeInsets.symmetric(vertical: 5), // Add margin
|
||||
child: ElevatedButton(
|
||||
onPressed: () async {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
_formKey.currentState!.save();
|
||||
|
||||
final token = await TokenManager.getToken();
|
||||
try {
|
||||
print("token is : $token");
|
||||
print(formData);
|
||||
|
||||
await apiService.createEntity(
|
||||
token!, formData, selectedFileupload_Field);
|
||||
|
||||
Navigator.pop(context);
|
||||
} catch (e) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: const Text('Error'),
|
||||
content: Text('Failed to create entity: $e'),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: const Text('OK'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
height: 50,
|
||||
child: const Center(
|
||||
child: Text(
|
||||
'SUBMIT',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,140 +1,140 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import '../../providers/token_manager.dart';
|
||||
import 'Bookmarks_api_service.dart';
|
||||
|
||||
class UpdateEntityScreen extends StatefulWidget {
|
||||
final Map<String, dynamic> entity;
|
||||
|
||||
UpdateEntityScreen({required this.entity});
|
||||
|
||||
@override
|
||||
_UpdateEntityScreenState createState() => _UpdateEntityScreenState();
|
||||
}
|
||||
|
||||
class _UpdateEntityScreenState extends State<UpdateEntityScreen> {
|
||||
final ApiService apiService = ApiService();
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Update Bookmarks')),
|
||||
body: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
children: [
|
||||
TextFormField(
|
||||
initialValue: widget.entity['bookmark_firstletter'],
|
||||
decoration:
|
||||
const InputDecoration(labelText: 'bookmark_firstletter'),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter a bookmark_firstletter';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
onSaved: (value) {
|
||||
widget.entity['bookmark_firstletter'] = value;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextFormField(
|
||||
initialValue: widget.entity['bookmark_link'],
|
||||
decoration: const InputDecoration(labelText: 'bookmark_link'),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter a bookmark_link';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
onSaved: (value) {
|
||||
widget.entity['bookmark_link'] = value;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextFormField(
|
||||
initialValue: widget.entity['fileupload_field'],
|
||||
decoration:
|
||||
const InputDecoration(labelText: 'fileupload_field'),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter a fileupload_field';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
onSaved: (value) {
|
||||
widget.entity['fileupload_field'] = value;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Container(
|
||||
margin: const EdgeInsets.symmetric(vertical: 5), // Add margin
|
||||
child: ElevatedButton(
|
||||
onPressed: () async {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
_formKey.currentState!.save();
|
||||
|
||||
final token = await TokenManager.getToken();
|
||||
try {
|
||||
await apiService.updateEntity(
|
||||
token!,
|
||||
widget.entity[
|
||||
'id'], // Assuming 'id' is the key in your entity map
|
||||
widget.entity);
|
||||
Navigator.pop(context);
|
||||
} catch (e) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: const Text('Error'),
|
||||
content: Text('Failed to update entity: $e'),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: const Text('OK'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
height: 50,
|
||||
child: const Center(
|
||||
child: Text(
|
||||
'UPDATE',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
import 'package:flutter/material.dart';
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import '../../providers/token_manager.dart';
|
||||
import 'Bookmarks_api_service.dart';
|
||||
|
||||
class UpdateEntityScreen extends StatefulWidget {
|
||||
final Map<String, dynamic> entity;
|
||||
|
||||
UpdateEntityScreen({required this.entity});
|
||||
|
||||
@override
|
||||
_UpdateEntityScreenState createState() => _UpdateEntityScreenState();
|
||||
}
|
||||
|
||||
class _UpdateEntityScreenState extends State<UpdateEntityScreen> {
|
||||
final ApiService apiService = ApiService();
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Update Bookmarks')),
|
||||
body: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
children: [
|
||||
TextFormField(
|
||||
initialValue: widget.entity['bookmark_firstletter'],
|
||||
decoration:
|
||||
const InputDecoration(labelText: 'bookmark_firstletter'),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter a bookmark_firstletter';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
onSaved: (value) {
|
||||
widget.entity['bookmark_firstletter'] = value;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextFormField(
|
||||
initialValue: widget.entity['bookmark_link'],
|
||||
decoration: const InputDecoration(labelText: 'bookmark_link'),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter a bookmark_link';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
onSaved: (value) {
|
||||
widget.entity['bookmark_link'] = value;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextFormField(
|
||||
initialValue: widget.entity['fileupload_field'],
|
||||
decoration:
|
||||
const InputDecoration(labelText: 'fileupload_field'),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter a fileupload_field';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
onSaved: (value) {
|
||||
widget.entity['fileupload_field'] = value;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Container(
|
||||
margin: const EdgeInsets.symmetric(vertical: 5), // Add margin
|
||||
child: ElevatedButton(
|
||||
onPressed: () async {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
_formKey.currentState!.save();
|
||||
|
||||
final token = await TokenManager.getToken();
|
||||
try {
|
||||
await apiService.updateEntity(
|
||||
token!,
|
||||
widget.entity[
|
||||
'id'], // Assuming 'id' is the key in your entity map
|
||||
widget.entity);
|
||||
Navigator.pop(context);
|
||||
} catch (e) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: const Text('Error'),
|
||||
content: Text('Failed to update entity: $e'),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: const Text('OK'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
height: 50,
|
||||
child: const Center(
|
||||
child: Text(
|
||||
'UPDATE',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,293 +1,293 @@
|
||||
import 'dart:io';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'dart:convert';
|
||||
|
||||
import '../../Utils/image_constant.dart';
|
||||
import '../../Utils/size_utils.dart';
|
||||
import '../../providers/token_manager.dart';
|
||||
import '../../resources/api_constants.dart';
|
||||
import '../../theme/app_style.dart';
|
||||
import '../../widgets/app_bar/appbar_image.dart';
|
||||
import '../../widgets/app_bar/appbar_title.dart';
|
||||
import '../../widgets/app_bar/custom_app_bar.dart';
|
||||
import '../../widgets/custom_button.dart';
|
||||
import '../../widgets/custom_text_form_field.dart';
|
||||
import '../LogoutService/Logoutservice.dart';
|
||||
|
||||
class RaisedTicketScreen extends StatefulWidget {
|
||||
final Map<String, dynamic> userData;
|
||||
|
||||
const RaisedTicketScreen({Key? key, required this.userData})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
_RaisedTicketScreenState createState() => _RaisedTicketScreenState();
|
||||
}
|
||||
|
||||
class _RaisedTicketScreenState extends State<RaisedTicketScreen> {
|
||||
List<Map<String, dynamic>> tickets = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
fetchTickets();
|
||||
}
|
||||
|
||||
Future<void> fetchTickets() async {
|
||||
int userid = widget.userData['userId'];
|
||||
String baseUrl = ApiConstants.baseUrl;
|
||||
final token = await TokenManager.getToken();
|
||||
String apiUrl = '$baseUrl/gettickets/$userid';
|
||||
final response = await http.get(Uri.parse(apiUrl), headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer $token',
|
||||
});
|
||||
if (response.statusCode == 401) {
|
||||
LogoutService.logout();
|
||||
}
|
||||
if (response.statusCode == 200) {
|
||||
List<dynamic> data = json.decode(response.body);
|
||||
setState(() {
|
||||
tickets = data.cast<Map<String, dynamic>>();
|
||||
});
|
||||
} else {
|
||||
print('Failed to fetch data');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: CustomAppBar(
|
||||
height: getVerticalSize(49),
|
||||
leadingWidth: 40,
|
||||
leading: AppbarImage(
|
||||
height: getSize(24),
|
||||
width: getSize(24),
|
||||
svgPath: ImageConstant.imgArrowleftBlueGray900,
|
||||
margin: getMargin(left: 16, top: 12, bottom: 13),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
}),
|
||||
actions: [
|
||||
GestureDetector(
|
||||
child: Icon(
|
||||
Icons.add,
|
||||
color: Colors.black,
|
||||
size: 20,
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.of(context)
|
||||
.push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => TicketFormScreen(
|
||||
userData: widget.userData,
|
||||
)),
|
||||
)
|
||||
.then((value) => {fetchTickets()});
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
width: 20,
|
||||
)
|
||||
],
|
||||
centerTitle: true,
|
||||
title: AppbarTitle(text: "Raised Tickets")),
|
||||
body: ListView.builder(
|
||||
itemCount: tickets.length,
|
||||
itemBuilder: (context, index) {
|
||||
final ticket = tickets[index];
|
||||
return ListTile(
|
||||
title: Text(
|
||||
'Ticket ID: ${ticket['ticketid']}',
|
||||
style: const TextStyle(fontSize: 12),
|
||||
),
|
||||
subtitle: Text('Ticket Name: ${ticket['ticketname']}',
|
||||
style: const TextStyle(fontSize: 10)),
|
||||
// Add more fields as needed
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class TicketFormScreen extends StatefulWidget {
|
||||
final Map<String, dynamic> userData;
|
||||
|
||||
const TicketFormScreen({Key? key, required this.userData}) : super(key: key);
|
||||
@override
|
||||
_TicketFormScreenState createState() => _TicketFormScreenState();
|
||||
}
|
||||
|
||||
class _TicketFormScreenState extends State<TicketFormScreen> {
|
||||
final TextEditingController titleController = TextEditingController();
|
||||
final TextEditingController descriptionController = TextEditingController();
|
||||
TextEditingController projectNameController = TextEditingController();
|
||||
var screenshot;
|
||||
|
||||
Future<void> submitTicket(File file) async {
|
||||
print(widget.userData);
|
||||
String title = titleController.text;
|
||||
String description = descriptionController.text;
|
||||
String baseUrl = ApiConstants.baseUrl;
|
||||
final token = await TokenManager.getToken();
|
||||
String apiUrl = '$baseUrl/service_request/raise_ticket';
|
||||
|
||||
// Create a multipart request
|
||||
var request = http.MultipartRequest('POST', Uri.parse(apiUrl));
|
||||
request.headers['Authorization'] = 'Bearer $token';
|
||||
|
||||
// Add text fields to the request
|
||||
request.fields['title'] = title;
|
||||
request.fields['description'] = description;
|
||||
request.fields['userid'] = widget.userData['userId'].toString();
|
||||
request.fields['username'] = widget.userData['fullname'];
|
||||
|
||||
// Add file to the request
|
||||
if (file != null) {
|
||||
request.files.add(
|
||||
await http.MultipartFile.fromPath('file', file.path),
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
// Send the request
|
||||
final response = await request.send();
|
||||
|
||||
if (response.statusCode == 401) {
|
||||
LogoutService.logout();
|
||||
}
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
Fluttertoast.showToast(
|
||||
msg: 'Ticket submitted successfully',
|
||||
backgroundColor: Colors.green,
|
||||
);
|
||||
print('Ticket submitted successfully');
|
||||
Navigator.pop(context);
|
||||
} else {
|
||||
Fluttertoast.showToast(
|
||||
msg: 'Failed to submit ticket.',
|
||||
backgroundColor: Colors.red,
|
||||
);
|
||||
print('Failed to submit ticket. Status code: ${response.statusCode}');
|
||||
}
|
||||
} catch (e) {
|
||||
// Handle exceptions
|
||||
print('Error: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _pickImage() async {
|
||||
final picker = ImagePicker();
|
||||
final pickedFile = await picker.pickImage(source: ImageSource.gallery);
|
||||
|
||||
setState(() {
|
||||
if (pickedFile != null) {
|
||||
screenshot = File(pickedFile.path);
|
||||
} else {
|
||||
print('No image selected.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: CustomAppBar(
|
||||
height: getVerticalSize(49),
|
||||
leadingWidth: 40,
|
||||
leading: AppbarImage(
|
||||
height: getSize(24),
|
||||
width: getSize(24),
|
||||
svgPath: ImageConstant.imgArrowleftBlueGray900,
|
||||
margin: getMargin(left: 16, top: 12, bottom: 13),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
}),
|
||||
centerTitle: true,
|
||||
title: AppbarTitle(text: "Raise a Ticket")),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text("Title",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroyMedium16Bluegray900),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
hintText: "Enter Title",
|
||||
controller: titleController,
|
||||
margin: getMargin(top: 6))
|
||||
])),
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text("Description",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroyMedium16Bluegray900),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
hintText: "Enter Description",
|
||||
controller: descriptionController,
|
||||
margin: getMargin(top: 6))
|
||||
])),
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text("Project Name",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroyMedium16Bluegray900),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
hintText: "Enter Project Name",
|
||||
controller: projectNameController,
|
||||
margin: getMargin(top: 6))
|
||||
])), // Adjusted the spacing
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Text('Pick Screenshot of issue'),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
_pickImage(); // Call the function to pick an image
|
||||
},
|
||||
icon: Icon(Icons.file_copy),
|
||||
),
|
||||
SizedBox(width: 8.0),
|
||||
// Display the selected screenshot file name
|
||||
Text(screenshot != null ? screenshot.path.split('/').last : ''),
|
||||
],
|
||||
),
|
||||
CustomButton(
|
||||
height: getVerticalSize(50),
|
||||
text: "Submit",
|
||||
margin: getMargin(top: 24, bottom: 5),
|
||||
onTap: () async {
|
||||
submitTicket(screenshot);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
import 'dart:io';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'dart:convert';
|
||||
|
||||
import '../../Utils/image_constant.dart';
|
||||
import '../../Utils/size_utils.dart';
|
||||
import '../../providers/token_manager.dart';
|
||||
import '../../resources/api_constants.dart';
|
||||
import '../../theme/app_style.dart';
|
||||
import '../../widgets/app_bar/appbar_image.dart';
|
||||
import '../../widgets/app_bar/appbar_title.dart';
|
||||
import '../../widgets/app_bar/custom_app_bar.dart';
|
||||
import '../../widgets/custom_button.dart';
|
||||
import '../../widgets/custom_text_form_field.dart';
|
||||
import '../LogoutService/Logoutservice.dart';
|
||||
|
||||
class RaisedTicketScreen extends StatefulWidget {
|
||||
final Map<String, dynamic> userData;
|
||||
|
||||
const RaisedTicketScreen({Key? key, required this.userData})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
_RaisedTicketScreenState createState() => _RaisedTicketScreenState();
|
||||
}
|
||||
|
||||
class _RaisedTicketScreenState extends State<RaisedTicketScreen> {
|
||||
List<Map<String, dynamic>> tickets = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
fetchTickets();
|
||||
}
|
||||
|
||||
Future<void> fetchTickets() async {
|
||||
int userid = widget.userData['userId'];
|
||||
String baseUrl = ApiConstants.baseUrl;
|
||||
final token = await TokenManager.getToken();
|
||||
String apiUrl = '$baseUrl/gettickets/$userid';
|
||||
final response = await http.get(Uri.parse(apiUrl), headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': 'Bearer $token',
|
||||
});
|
||||
if (response.statusCode == 401) {
|
||||
LogoutService.logout();
|
||||
}
|
||||
if (response.statusCode == 200) {
|
||||
List<dynamic> data = json.decode(response.body);
|
||||
setState(() {
|
||||
tickets = data.cast<Map<String, dynamic>>();
|
||||
});
|
||||
} else {
|
||||
print('Failed to fetch data');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: CustomAppBar(
|
||||
height: getVerticalSize(49),
|
||||
leadingWidth: 40,
|
||||
leading: AppbarImage(
|
||||
height: getSize(24),
|
||||
width: getSize(24),
|
||||
svgPath: ImageConstant.imgArrowleftBlueGray900,
|
||||
margin: getMargin(left: 16, top: 12, bottom: 13),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
}),
|
||||
actions: [
|
||||
GestureDetector(
|
||||
child: Icon(
|
||||
Icons.add,
|
||||
color: Colors.black,
|
||||
size: 20,
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.of(context)
|
||||
.push(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => TicketFormScreen(
|
||||
userData: widget.userData,
|
||||
)),
|
||||
)
|
||||
.then((value) => {fetchTickets()});
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
width: 20,
|
||||
)
|
||||
],
|
||||
centerTitle: true,
|
||||
title: AppbarTitle(text: "Raised Tickets")),
|
||||
body: ListView.builder(
|
||||
itemCount: tickets.length,
|
||||
itemBuilder: (context, index) {
|
||||
final ticket = tickets[index];
|
||||
return ListTile(
|
||||
title: Text(
|
||||
'Ticket ID: ${ticket['ticketid']}',
|
||||
style: const TextStyle(fontSize: 12),
|
||||
),
|
||||
subtitle: Text('Ticket Name: ${ticket['ticketname']}',
|
||||
style: const TextStyle(fontSize: 10)),
|
||||
// Add more fields as needed
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class TicketFormScreen extends StatefulWidget {
|
||||
final Map<String, dynamic> userData;
|
||||
|
||||
const TicketFormScreen({Key? key, required this.userData}) : super(key: key);
|
||||
@override
|
||||
_TicketFormScreenState createState() => _TicketFormScreenState();
|
||||
}
|
||||
|
||||
class _TicketFormScreenState extends State<TicketFormScreen> {
|
||||
final TextEditingController titleController = TextEditingController();
|
||||
final TextEditingController descriptionController = TextEditingController();
|
||||
TextEditingController projectNameController = TextEditingController();
|
||||
var screenshot;
|
||||
|
||||
Future<void> submitTicket(File file) async {
|
||||
print(widget.userData);
|
||||
String title = titleController.text;
|
||||
String description = descriptionController.text;
|
||||
String baseUrl = ApiConstants.baseUrl;
|
||||
final token = await TokenManager.getToken();
|
||||
String apiUrl = '$baseUrl/service_request/raise_ticket';
|
||||
|
||||
// Create a multipart request
|
||||
var request = http.MultipartRequest('POST', Uri.parse(apiUrl));
|
||||
request.headers['Authorization'] = 'Bearer $token';
|
||||
|
||||
// Add text fields to the request
|
||||
request.fields['title'] = title;
|
||||
request.fields['description'] = description;
|
||||
request.fields['userid'] = widget.userData['userId'].toString();
|
||||
request.fields['username'] = widget.userData['fullname'];
|
||||
|
||||
// Add file to the request
|
||||
if (file != null) {
|
||||
request.files.add(
|
||||
await http.MultipartFile.fromPath('file', file.path),
|
||||
);
|
||||
}
|
||||
|
||||
try {
|
||||
// Send the request
|
||||
final response = await request.send();
|
||||
|
||||
if (response.statusCode == 401) {
|
||||
LogoutService.logout();
|
||||
}
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
Fluttertoast.showToast(
|
||||
msg: 'Ticket submitted successfully',
|
||||
backgroundColor: Colors.green,
|
||||
);
|
||||
print('Ticket submitted successfully');
|
||||
Navigator.pop(context);
|
||||
} else {
|
||||
Fluttertoast.showToast(
|
||||
msg: 'Failed to submit ticket.',
|
||||
backgroundColor: Colors.red,
|
||||
);
|
||||
print('Failed to submit ticket. Status code: ${response.statusCode}');
|
||||
}
|
||||
} catch (e) {
|
||||
// Handle exceptions
|
||||
print('Error: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _pickImage() async {
|
||||
final picker = ImagePicker();
|
||||
final pickedFile = await picker.pickImage(source: ImageSource.gallery);
|
||||
|
||||
setState(() {
|
||||
if (pickedFile != null) {
|
||||
screenshot = File(pickedFile.path);
|
||||
} else {
|
||||
print('No image selected.');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: CustomAppBar(
|
||||
height: getVerticalSize(49),
|
||||
leadingWidth: 40,
|
||||
leading: AppbarImage(
|
||||
height: getSize(24),
|
||||
width: getSize(24),
|
||||
svgPath: ImageConstant.imgArrowleftBlueGray900,
|
||||
margin: getMargin(left: 16, top: 12, bottom: 13),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
}),
|
||||
centerTitle: true,
|
||||
title: AppbarTitle(text: "Raise a Ticket")),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text("Title",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroyMedium16Bluegray900),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
hintText: "Enter Title",
|
||||
controller: titleController,
|
||||
margin: getMargin(top: 6))
|
||||
])),
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text("Description",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroyMedium16Bluegray900),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
hintText: "Enter Description",
|
||||
controller: descriptionController,
|
||||
margin: getMargin(top: 6))
|
||||
])),
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text("Project Name",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroyMedium16Bluegray900),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
hintText: "Enter Project Name",
|
||||
controller: projectNameController,
|
||||
margin: getMargin(top: 6))
|
||||
])), // Adjusted the spacing
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Text('Pick Screenshot of issue'),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
_pickImage(); // Call the function to pick an image
|
||||
},
|
||||
icon: Icon(Icons.file_copy),
|
||||
),
|
||||
SizedBox(width: 8.0),
|
||||
// Display the selected screenshot file name
|
||||
Text(screenshot != null ? screenshot.path.split('/').last : ''),
|
||||
],
|
||||
),
|
||||
CustomButton(
|
||||
height: getVerticalSize(50),
|
||||
text: "Submit",
|
||||
margin: getMargin(top: 24, bottom: 5),
|
||||
onTap: () async {
|
||||
submitTicket(screenshot);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,342 +1,342 @@
|
||||
import 'dart:convert';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import '../../Utils/color_constants.dart';
|
||||
import '../../providers/token_manager.dart';
|
||||
import '../../utilities/make_api_request.dart';
|
||||
import '../main_app_screen/tabbed_layout_component.dart';
|
||||
|
||||
class LoginFormComponent extends StatefulWidget {
|
||||
const LoginFormComponent({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
LoginFormComponentState createState() {
|
||||
return LoginFormComponentState();
|
||||
}
|
||||
}
|
||||
|
||||
class LoginFormComponentState extends State<LoginFormComponent> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
String errorMessage1 = "";
|
||||
String errorMessage2 = "";
|
||||
String userInput = "";
|
||||
String password = "";
|
||||
bool isPasswordVisible = false;
|
||||
bool stayLoggedIn = false;
|
||||
|
||||
void errorMessageSetter(int fieldNumber, String message) {
|
||||
setState(() {
|
||||
if (fieldNumber == 1) {
|
||||
errorMessage1 = message;
|
||||
} else {
|
||||
errorMessage2 = message;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void tryLoggingIn() async {
|
||||
final dataReceived = await sendData(
|
||||
urlPath: "/token/session",
|
||||
data: {"email": userInput, "password": password},
|
||||
);
|
||||
|
||||
if (dataReceived.containsValue('ERROR')) {
|
||||
var error = dataReceived['operationMessage'].toString();
|
||||
// ignore: use_build_context_synchronously
|
||||
ScaffoldMessenger.of(context)
|
||||
.showSnackBar(SnackBar(
|
||||
content: Text(error),
|
||||
backgroundColor: Colors.redAccent,
|
||||
))
|
||||
.closed;
|
||||
} else {
|
||||
var token = dataReceived['item']['token'];
|
||||
var user = dataReceived['item'];
|
||||
await TokenManager.setToken(token);
|
||||
|
||||
if (stayLoggedIn) {
|
||||
await _saveLoggedInUserData(token, user);
|
||||
}
|
||||
// ignore: use_build_context_synchronously
|
||||
ScaffoldMessenger.of(context)
|
||||
.showSnackBar(const SnackBar(
|
||||
content: Text("Login Successful"),
|
||||
backgroundColor: Colors.green,
|
||||
))
|
||||
.closed
|
||||
.then(
|
||||
(value) => Navigator.of(context).pushAndRemoveUntil(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => TabbedLayoutComponent(),
|
||||
),
|
||||
(route) => false,
|
||||
),
|
||||
);
|
||||
|
||||
print('after login');
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> _saveLoggedInUserData(
|
||||
String loggedInUserAuthKey, Map<String, dynamic> user) async {
|
||||
try {
|
||||
var userId = user['userId'].toString();
|
||||
var firstName = user['firstName'].toString();
|
||||
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString('userData', json.encode(user));
|
||||
await prefs.setBool('isLoggedIn', true);
|
||||
await prefs.setString('token', loggedInUserAuthKey);
|
||||
|
||||
print('userId ....$userId');
|
||||
print('firstName ....$firstName');
|
||||
|
||||
if (mounted) {
|
||||
debugPrint("user data saved");
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
margin: const EdgeInsets.all(5),
|
||||
padding: const EdgeInsets.all(5),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
border: Border.all(width: 1.0, color: const Color(0xFFF5F7FA)),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
boxShadow: [
|
||||
const BoxShadow(
|
||||
blurRadius: 6.18,
|
||||
spreadRadius: 0.618,
|
||||
offset: Offset(-4, -4),
|
||||
color: Color(0xFFF5F7FA),
|
||||
),
|
||||
BoxShadow(
|
||||
blurRadius: 6.18,
|
||||
spreadRadius: 0.618,
|
||||
offset: const Offset(4, 4),
|
||||
color: Colors.blueGrey.shade100,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: TextFormField(
|
||||
textInputAction: TextInputAction.next,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
errorMessageSetter(
|
||||
1, 'You must provide an email or username');
|
||||
} else {
|
||||
errorMessageSetter(1, "");
|
||||
|
||||
setState(() {
|
||||
userInput = value;
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
autocorrect: false,
|
||||
decoration: const InputDecoration(
|
||||
fillColor: Colors.white,
|
||||
border: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
errorBorder: InputBorder.none,
|
||||
disabledBorder: InputBorder.none,
|
||||
contentPadding:
|
||||
EdgeInsets.only(left: 15, bottom: 11, top: 11, right: 15),
|
||||
hintText: "Username or email address",
|
||||
hintStyle: TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
|
||||
),
|
||||
style: const TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
|
||||
),
|
||||
),
|
||||
if (errorMessage1 != '')
|
||||
Container(
|
||||
margin: const EdgeInsets.all(2),
|
||||
padding: const EdgeInsets.all(2),
|
||||
child: Text(
|
||||
"\t\t\t\t$errorMessage1",
|
||||
style: const TextStyle(fontSize: 10, color: Colors.red),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
margin: const EdgeInsets.all(5),
|
||||
padding: const EdgeInsets.all(5),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(width: 1.0, color: const Color(0xFFF5F7FA)),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
color: Colors.white,
|
||||
boxShadow: [
|
||||
const BoxShadow(
|
||||
spreadRadius: 0.618,
|
||||
blurRadius: 6.18,
|
||||
offset: Offset(-4, -4),
|
||||
color: Color(0xFFF5F7FA),
|
||||
),
|
||||
BoxShadow(
|
||||
blurRadius: 6.18,
|
||||
spreadRadius: 0.618,
|
||||
offset: const Offset(4, 4),
|
||||
color: Colors.blueGrey.shade100,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: TextFormField(
|
||||
textInputAction: TextInputAction.done,
|
||||
onFieldSubmitted: (value) => _validateLoginDetails(),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
errorMessageSetter(2, 'Password cannot be empty');
|
||||
} else {
|
||||
errorMessageSetter(2, "");
|
||||
setState(() {
|
||||
password = value;
|
||||
});
|
||||
}
|
||||
return null;
|
||||
},
|
||||
obscureText: !isPasswordVisible,
|
||||
enableSuggestions: false,
|
||||
autocorrect: false,
|
||||
decoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
errorBorder: InputBorder.none,
|
||||
disabledBorder: InputBorder.none,
|
||||
contentPadding: const EdgeInsets.only(
|
||||
left: 15, bottom: 11, top: 11, right: 15),
|
||||
hintText: "Password",
|
||||
hintStyle:
|
||||
const TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
|
||||
suffixIcon: IconButton(
|
||||
icon: Icon(
|
||||
isPasswordVisible ? Icons.visibility : Icons.visibility_off,
|
||||
),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
isPasswordVisible = !isPasswordVisible;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (errorMessage2 != '')
|
||||
Container(
|
||||
margin: const EdgeInsets.all(2),
|
||||
padding: const EdgeInsets.all(2),
|
||||
child: Text(
|
||||
"\t\t\t\t$errorMessage2",
|
||||
style: const TextStyle(fontSize: 10, color: Colors.red),
|
||||
),
|
||||
),
|
||||
CheckboxListTile(
|
||||
activeColor: ColorConstant.blue700,
|
||||
title: const Text('Stay Logged In'),
|
||||
value: stayLoggedIn,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
stayLoggedIn = value!;
|
||||
});
|
||||
},
|
||||
),
|
||||
Container(
|
||||
margin: const EdgeInsets.symmetric(vertical: 16.0),
|
||||
width: double.infinity,
|
||||
height: 64,
|
||||
child: ElevatedButton(
|
||||
onPressed: _validateLoginDetails,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: ColorConstant.blue700,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
),
|
||||
child: const Text(
|
||||
'Log in',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
// Container(
|
||||
// margin: const EdgeInsets.symmetric(vertical: 16.0),
|
||||
// width: double.infinity,
|
||||
// height: 64,
|
||||
// decoration: BoxDecoration(
|
||||
// boxShadow: [
|
||||
// BoxShadow(
|
||||
// color: Colors.blueGrey.shade100,
|
||||
// offset: const Offset(0, 4),
|
||||
// blurRadius: 5.0,
|
||||
// ),
|
||||
// ],
|
||||
// gradient: const RadialGradient(
|
||||
// colors: [Color(0xff0070BA), Color(0xff1546A0)],
|
||||
// radius: 8.4,
|
||||
// center: Alignment(-0.24, -0.36),
|
||||
// ),
|
||||
// borderRadius: BorderRadius.circular(20),
|
||||
// ),
|
||||
// child: ElevatedButton(
|
||||
// onPressed: _validateLoginDetails,
|
||||
// style: ElevatedButton.styleFrom(
|
||||
// primary: Colors.transparent,
|
||||
// shadowColor: Colors.transparent,
|
||||
// shape: RoundedRectangleBorder(
|
||||
// borderRadius: BorderRadius.circular(20),
|
||||
// ),
|
||||
// ),
|
||||
// child: const Text(
|
||||
// 'Log in',
|
||||
// style: TextStyle(
|
||||
// fontSize: 16,
|
||||
// fontWeight: FontWeight.w600,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _validateLoginDetails() {
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
if (_formKey.currentState!.validate()) {
|
||||
if (errorMessage1 != "" || errorMessage2 != "") {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Please provide all required details'),
|
||||
backgroundColor: Colors.red,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
onVisible: tryLoggingIn,
|
||||
content: const Text('Processing...'),
|
||||
backgroundColor: Colors.blue,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
import 'dart:convert';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
import '../../Utils/color_constants.dart';
|
||||
import '../../providers/token_manager.dart';
|
||||
import '../../utilities/make_api_request.dart';
|
||||
import '../main_app_screen/tabbed_layout_component.dart';
|
||||
|
||||
class LoginFormComponent extends StatefulWidget {
|
||||
const LoginFormComponent({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
LoginFormComponentState createState() {
|
||||
return LoginFormComponentState();
|
||||
}
|
||||
}
|
||||
|
||||
class LoginFormComponentState extends State<LoginFormComponent> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
String errorMessage1 = "";
|
||||
String errorMessage2 = "";
|
||||
String userInput = "";
|
||||
String password = "";
|
||||
bool isPasswordVisible = false;
|
||||
bool stayLoggedIn = false;
|
||||
|
||||
void errorMessageSetter(int fieldNumber, String message) {
|
||||
setState(() {
|
||||
if (fieldNumber == 1) {
|
||||
errorMessage1 = message;
|
||||
} else {
|
||||
errorMessage2 = message;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void tryLoggingIn() async {
|
||||
final dataReceived = await sendData(
|
||||
urlPath: "/token/session",
|
||||
data: {"email": userInput, "password": password},
|
||||
);
|
||||
|
||||
if (dataReceived.containsValue('ERROR')) {
|
||||
var error = dataReceived['operationMessage'].toString();
|
||||
// ignore: use_build_context_synchronously
|
||||
ScaffoldMessenger.of(context)
|
||||
.showSnackBar(SnackBar(
|
||||
content: Text(error),
|
||||
backgroundColor: Colors.redAccent,
|
||||
))
|
||||
.closed;
|
||||
} else {
|
||||
var token = dataReceived['item']['token'];
|
||||
var user = dataReceived['item'];
|
||||
await TokenManager.setToken(token);
|
||||
|
||||
if (stayLoggedIn) {
|
||||
await _saveLoggedInUserData(token, user);
|
||||
}
|
||||
// ignore: use_build_context_synchronously
|
||||
ScaffoldMessenger.of(context)
|
||||
.showSnackBar(const SnackBar(
|
||||
content: Text("Login Successful"),
|
||||
backgroundColor: Colors.green,
|
||||
))
|
||||
.closed
|
||||
.then(
|
||||
(value) => Navigator.of(context).pushAndRemoveUntil(
|
||||
MaterialPageRoute(
|
||||
builder: (context) => TabbedLayoutComponent(),
|
||||
),
|
||||
(route) => false,
|
||||
),
|
||||
);
|
||||
|
||||
print('after login');
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> _saveLoggedInUserData(
|
||||
String loggedInUserAuthKey, Map<String, dynamic> user) async {
|
||||
try {
|
||||
var userId = user['userId'].toString();
|
||||
var firstName = user['firstName'].toString();
|
||||
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setString('userData', json.encode(user));
|
||||
await prefs.setBool('isLoggedIn', true);
|
||||
await prefs.setString('token', loggedInUserAuthKey);
|
||||
|
||||
print('userId ....$userId');
|
||||
print('firstName ....$firstName');
|
||||
|
||||
if (mounted) {
|
||||
debugPrint("user data saved");
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
margin: const EdgeInsets.all(5),
|
||||
padding: const EdgeInsets.all(5),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
border: Border.all(width: 1.0, color: const Color(0xFFF5F7FA)),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
boxShadow: [
|
||||
const BoxShadow(
|
||||
blurRadius: 6.18,
|
||||
spreadRadius: 0.618,
|
||||
offset: Offset(-4, -4),
|
||||
color: Color(0xFFF5F7FA),
|
||||
),
|
||||
BoxShadow(
|
||||
blurRadius: 6.18,
|
||||
spreadRadius: 0.618,
|
||||
offset: const Offset(4, 4),
|
||||
color: Colors.blueGrey.shade100,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: TextFormField(
|
||||
textInputAction: TextInputAction.next,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
errorMessageSetter(
|
||||
1, 'You must provide an email or username');
|
||||
} else {
|
||||
errorMessageSetter(1, "");
|
||||
|
||||
setState(() {
|
||||
userInput = value;
|
||||
});
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
autocorrect: false,
|
||||
decoration: const InputDecoration(
|
||||
fillColor: Colors.white,
|
||||
border: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
errorBorder: InputBorder.none,
|
||||
disabledBorder: InputBorder.none,
|
||||
contentPadding:
|
||||
EdgeInsets.only(left: 15, bottom: 11, top: 11, right: 15),
|
||||
hintText: "Username or email address",
|
||||
hintStyle: TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
|
||||
),
|
||||
style: const TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
|
||||
),
|
||||
),
|
||||
if (errorMessage1 != '')
|
||||
Container(
|
||||
margin: const EdgeInsets.all(2),
|
||||
padding: const EdgeInsets.all(2),
|
||||
child: Text(
|
||||
"\t\t\t\t$errorMessage1",
|
||||
style: const TextStyle(fontSize: 10, color: Colors.red),
|
||||
),
|
||||
),
|
||||
Container(
|
||||
margin: const EdgeInsets.all(5),
|
||||
padding: const EdgeInsets.all(5),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(width: 1.0, color: const Color(0xFFF5F7FA)),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
color: Colors.white,
|
||||
boxShadow: [
|
||||
const BoxShadow(
|
||||
spreadRadius: 0.618,
|
||||
blurRadius: 6.18,
|
||||
offset: Offset(-4, -4),
|
||||
color: Color(0xFFF5F7FA),
|
||||
),
|
||||
BoxShadow(
|
||||
blurRadius: 6.18,
|
||||
spreadRadius: 0.618,
|
||||
offset: const Offset(4, 4),
|
||||
color: Colors.blueGrey.shade100,
|
||||
),
|
||||
],
|
||||
),
|
||||
child: TextFormField(
|
||||
textInputAction: TextInputAction.done,
|
||||
onFieldSubmitted: (value) => _validateLoginDetails(),
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
errorMessageSetter(2, 'Password cannot be empty');
|
||||
} else {
|
||||
errorMessageSetter(2, "");
|
||||
setState(() {
|
||||
password = value;
|
||||
});
|
||||
}
|
||||
return null;
|
||||
},
|
||||
obscureText: !isPasswordVisible,
|
||||
enableSuggestions: false,
|
||||
autocorrect: false,
|
||||
decoration: InputDecoration(
|
||||
border: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
errorBorder: InputBorder.none,
|
||||
disabledBorder: InputBorder.none,
|
||||
contentPadding: const EdgeInsets.only(
|
||||
left: 15, bottom: 11, top: 11, right: 15),
|
||||
hintText: "Password",
|
||||
hintStyle:
|
||||
const TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
|
||||
suffixIcon: IconButton(
|
||||
icon: Icon(
|
||||
isPasswordVisible ? Icons.visibility : Icons.visibility_off,
|
||||
),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
isPasswordVisible = !isPasswordVisible;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (errorMessage2 != '')
|
||||
Container(
|
||||
margin: const EdgeInsets.all(2),
|
||||
padding: const EdgeInsets.all(2),
|
||||
child: Text(
|
||||
"\t\t\t\t$errorMessage2",
|
||||
style: const TextStyle(fontSize: 10, color: Colors.red),
|
||||
),
|
||||
),
|
||||
CheckboxListTile(
|
||||
activeColor: ColorConstant.blue700,
|
||||
title: const Text('Stay Logged In'),
|
||||
value: stayLoggedIn,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
stayLoggedIn = value!;
|
||||
});
|
||||
},
|
||||
),
|
||||
Container(
|
||||
margin: const EdgeInsets.symmetric(vertical: 16.0),
|
||||
width: double.infinity,
|
||||
height: 64,
|
||||
child: ElevatedButton(
|
||||
onPressed: _validateLoginDetails,
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: ColorConstant.blue700,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
),
|
||||
),
|
||||
child: const Text(
|
||||
'Log in',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
// Container(
|
||||
// margin: const EdgeInsets.symmetric(vertical: 16.0),
|
||||
// width: double.infinity,
|
||||
// height: 64,
|
||||
// decoration: BoxDecoration(
|
||||
// boxShadow: [
|
||||
// BoxShadow(
|
||||
// color: Colors.blueGrey.shade100,
|
||||
// offset: const Offset(0, 4),
|
||||
// blurRadius: 5.0,
|
||||
// ),
|
||||
// ],
|
||||
// gradient: const RadialGradient(
|
||||
// colors: [Color(0xff0070BA), Color(0xff1546A0)],
|
||||
// radius: 8.4,
|
||||
// center: Alignment(-0.24, -0.36),
|
||||
// ),
|
||||
// borderRadius: BorderRadius.circular(20),
|
||||
// ),
|
||||
// child: ElevatedButton(
|
||||
// onPressed: _validateLoginDetails,
|
||||
// style: ElevatedButton.styleFrom(
|
||||
// primary: Colors.transparent,
|
||||
// shadowColor: Colors.transparent,
|
||||
// shape: RoundedRectangleBorder(
|
||||
// borderRadius: BorderRadius.circular(20),
|
||||
// ),
|
||||
// ),
|
||||
// child: const Text(
|
||||
// 'Log in',
|
||||
// style: TextStyle(
|
||||
// fontSize: 16,
|
||||
// fontWeight: FontWeight.w600,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _validateLoginDetails() {
|
||||
FocusManager.instance.primaryFocus?.unfocus();
|
||||
if (_formKey.currentState!.validate()) {
|
||||
if (errorMessage1 != "" || errorMessage2 != "") {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Please provide all required details'),
|
||||
backgroundColor: Colors.red,
|
||||
),
|
||||
);
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
onVisible: tryLoggingIn,
|
||||
content: const Text('Processing...'),
|
||||
backgroundColor: Colors.blue,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,21 +1,21 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import '../../main.dart';
|
||||
import '../Login Screen/login_screen.dart';
|
||||
|
||||
class LogoutService {
|
||||
static Future<void> logout() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
await prefs.remove('userData');
|
||||
await prefs.remove('isLoggedIn');
|
||||
const storage = FlutterSecureStorage();
|
||||
await storage.delete(key: 'token');
|
||||
navigatorKey.currentState!.pushAndRemoveUntil(
|
||||
MaterialPageRoute(builder: (context) => LoginScreen()),
|
||||
(route) => false, // Remove all routes from the stack
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import '../../main.dart';
|
||||
import '../Login Screen/login_screen.dart';
|
||||
|
||||
class LogoutService {
|
||||
static Future<void> logout() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
await prefs.remove('userData');
|
||||
await prefs.remove('isLoggedIn');
|
||||
const storage = FlutterSecureStorage();
|
||||
await storage.delete(key: 'token');
|
||||
navigatorKey.currentState!.pushAndRemoveUntil(
|
||||
MaterialPageRoute(builder: (context) => LoginScreen()),
|
||||
(route) => false, // Remove all routes from the stack
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,85 +1,85 @@
|
||||
// ignore_for_file: use_build_context_synchronously
|
||||
import 'package:flutter/material.dart';
|
||||
// OLD: import 'package:flutter_barcode_scanner/flutter_barcode_scanner.dart'; // removed no namespace AGP8 - by Azmat
|
||||
import 'package:mobile_scanner/mobile_scanner.dart'; // migrated for AGP8 Java17 - by Azmat
|
||||
|
||||
class BarcodeScreen extends StatefulWidget {
|
||||
const BarcodeScreen({super.key});
|
||||
|
||||
@override
|
||||
_BarcodeScreenState createState() => _BarcodeScreenState();
|
||||
}
|
||||
|
||||
class _BarcodeScreenState extends State<BarcodeScreen> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
String scannedbar_code_scanner = 'No data';
|
||||
|
||||
// OLD scanBarcode via FlutterBarcodeScanner - removed no namespace AGP8 - by Azmat
|
||||
final MobileScannerController barCodeController = MobileScannerController(); // mobile_scanner controller - by Azmat
|
||||
Future<void> scanBarcode() async {
|
||||
final String? result = await Navigator.push<String>(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => Scaffold(
|
||||
appBar: AppBar(title: const Text('Scan Barcode')),
|
||||
body: MobileScanner(
|
||||
controller: barCodeController,
|
||||
onDetect: (capture) => Navigator.pop(
|
||||
context,
|
||||
capture.barcodes.isNotEmpty ? (capture.barcodes.first.rawValue ?? '') : '',
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
scannedbar_code_scanner = result ?? '';
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('BAR CODE')),
|
||||
body: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Center(
|
||||
child: Column(
|
||||
children: [
|
||||
const Text(
|
||||
'Scanned Barcode:',
|
||||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
scannedbar_code_scanner,
|
||||
style: const TextStyle(fontSize: 16),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
scanBarcode(); // Trigger barcode scanning
|
||||
},
|
||||
icon: const Icon(Icons.camera_alt), // Camera icon
|
||||
label: const Text('Scan Barcode'),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
// ignore_for_file: use_build_context_synchronously
|
||||
import 'package:flutter/material.dart';
|
||||
// OLD: import 'package:flutter_barcode_scanner/flutter_barcode_scanner.dart'; // removed no namespace AGP8 - by Azmat
|
||||
import 'package:mobile_scanner/mobile_scanner.dart'; // migrated for AGP8 Java17 - by Azmat
|
||||
|
||||
class BarcodeScreen extends StatefulWidget {
|
||||
const BarcodeScreen({super.key});
|
||||
|
||||
@override
|
||||
_BarcodeScreenState createState() => _BarcodeScreenState();
|
||||
}
|
||||
|
||||
class _BarcodeScreenState extends State<BarcodeScreen> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
String scannedbar_code_scanner = 'No data';
|
||||
|
||||
// OLD scanBarcode via FlutterBarcodeScanner - removed no namespace AGP8 - by Azmat
|
||||
final MobileScannerController barCodeController = MobileScannerController(); // mobile_scanner controller - by Azmat
|
||||
Future<void> scanBarcode() async {
|
||||
final String? result = await Navigator.push<String>(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => Scaffold(
|
||||
appBar: AppBar(title: const Text('Scan Barcode')),
|
||||
body: MobileScanner(
|
||||
controller: barCodeController,
|
||||
onDetect: (capture) => Navigator.pop(
|
||||
context,
|
||||
capture.barcodes.isNotEmpty ? (capture.barcodes.first.rawValue ?? '') : '',
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
scannedbar_code_scanner = result ?? '';
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('BAR CODE')),
|
||||
body: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Center(
|
||||
child: Column(
|
||||
children: [
|
||||
const Text(
|
||||
'Scanned Barcode:',
|
||||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
scannedbar_code_scanner,
|
||||
style: const TextStyle(fontSize: 16),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
scanBarcode(); // Trigger barcode scanning
|
||||
},
|
||||
icon: const Icon(Icons.camera_alt), // Camera icon
|
||||
label: const Text('Scan Barcode'),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,170 +1,170 @@
|
||||
// ignore_for_file: use_build_context_synchronously
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:qr_flutter/qr_flutter.dart';
|
||||
// import 'package:qr_code_scanner/qr_code_scanner.dart';
|
||||
import 'package:barcode_widget/barcode_widget.dart';
|
||||
|
||||
import '../Barcode/Barcode_create_entity_screen.dart';
|
||||
import '../Qrcode/Qrcode_create_entity_screen.dart';
|
||||
|
||||
class QrBarCodeScreen extends StatefulWidget {
|
||||
const QrBarCodeScreen({super.key});
|
||||
|
||||
@override
|
||||
_QrBarCodeScreenState createState() => _QrBarCodeScreenState();
|
||||
}
|
||||
|
||||
class _QrBarCodeScreenState extends State<QrBarCodeScreen> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
TextEditingController qr_code_dataController = TextEditingController();
|
||||
|
||||
// Function to show the QR code in a dialog
|
||||
void _showqr_code_dataDialog() {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: const Text('Generated QR Code'),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 200, // Set a fixed width for the QR code
|
||||
height: 200, // Set a fixed height for the QR code
|
||||
child: QrImageView(
|
||||
data: qr_code_dataController.text,
|
||||
version: QrVersions.auto,
|
||||
embeddedImageStyle:
|
||||
const QrEmbeddedImageStyle(size: Size(100, 100)),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(); // Close the dialog
|
||||
},
|
||||
child: const Text('Close'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
TextEditingController bar_code_dataController = TextEditingController();
|
||||
|
||||
// Function to show the barcode in a dialog
|
||||
void _show_bar_code_dataDialog(String barcodeData) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: const Text('Generated Bar Code'),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Card(
|
||||
color: Colors.white,
|
||||
elevation: 6,
|
||||
shadowColor: Colors.amber,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: BarcodeWidget(
|
||||
data: barcodeData,
|
||||
barcode: Barcode.code128(),
|
||||
color: Colors.black,
|
||||
width: 200,
|
||||
height: 100,
|
||||
drawText: false,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(); // Close the dialog
|
||||
},
|
||||
child: const Text('Close'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('QR AND BAR CODE')),
|
||||
body: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
children: [
|
||||
// GENERATE QR CODE
|
||||
TextFormField(
|
||||
controller: qr_code_dataController,
|
||||
decoration: const InputDecoration(labelText: 'qr_code_data'),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
_showqr_code_dataDialog();
|
||||
},
|
||||
child: const Text('Generate Qr')),
|
||||
|
||||
// GENERATE BAR CODE
|
||||
TextFormField(
|
||||
controller: bar_code_dataController,
|
||||
decoration: const InputDecoration(labelText: 'Bar Code Data'),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
_show_bar_code_dataDialog(bar_code_dataController.text);
|
||||
},
|
||||
child: const Text('Generate Bar code'),
|
||||
),
|
||||
// QR CODE SCANNER
|
||||
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const qrcodeScreen()));
|
||||
},
|
||||
child: const Text('QR Code Scanner'),
|
||||
),
|
||||
// BAR CODE SCANNER
|
||||
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const BarcodeScreen()));
|
||||
},
|
||||
child: const Text('Bar Code Scanner'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
// ignore_for_file: use_build_context_synchronously
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:qr_flutter/qr_flutter.dart';
|
||||
// import 'package:qr_code_scanner/qr_code_scanner.dart';
|
||||
import 'package:barcode_widget/barcode_widget.dart';
|
||||
|
||||
import '../Barcode/Barcode_create_entity_screen.dart';
|
||||
import '../Qrcode/Qrcode_create_entity_screen.dart';
|
||||
|
||||
class QrBarCodeScreen extends StatefulWidget {
|
||||
const QrBarCodeScreen({super.key});
|
||||
|
||||
@override
|
||||
_QrBarCodeScreenState createState() => _QrBarCodeScreenState();
|
||||
}
|
||||
|
||||
class _QrBarCodeScreenState extends State<QrBarCodeScreen> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
TextEditingController qr_code_dataController = TextEditingController();
|
||||
|
||||
// Function to show the QR code in a dialog
|
||||
void _showqr_code_dataDialog() {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: const Text('Generated QR Code'),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 200, // Set a fixed width for the QR code
|
||||
height: 200, // Set a fixed height for the QR code
|
||||
child: QrImageView(
|
||||
data: qr_code_dataController.text,
|
||||
version: QrVersions.auto,
|
||||
embeddedImageStyle:
|
||||
const QrEmbeddedImageStyle(size: Size(100, 100)),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(); // Close the dialog
|
||||
},
|
||||
child: const Text('Close'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
TextEditingController bar_code_dataController = TextEditingController();
|
||||
|
||||
// Function to show the barcode in a dialog
|
||||
void _show_bar_code_dataDialog(String barcodeData) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: const Text('Generated Bar Code'),
|
||||
content: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Card(
|
||||
color: Colors.white,
|
||||
elevation: 6,
|
||||
shadowColor: Colors.amber,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: BarcodeWidget(
|
||||
data: barcodeData,
|
||||
barcode: Barcode.code128(),
|
||||
color: Colors.black,
|
||||
width: 200,
|
||||
height: 100,
|
||||
drawText: false,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(); // Close the dialog
|
||||
},
|
||||
child: const Text('Close'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('QR AND BAR CODE')),
|
||||
body: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
children: [
|
||||
// GENERATE QR CODE
|
||||
TextFormField(
|
||||
controller: qr_code_dataController,
|
||||
decoration: const InputDecoration(labelText: 'qr_code_data'),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
_showqr_code_dataDialog();
|
||||
},
|
||||
child: const Text('Generate Qr')),
|
||||
|
||||
// GENERATE BAR CODE
|
||||
TextFormField(
|
||||
controller: bar_code_dataController,
|
||||
decoration: const InputDecoration(labelText: 'Bar Code Data'),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
_show_bar_code_dataDialog(bar_code_dataController.text);
|
||||
},
|
||||
child: const Text('Generate Bar code'),
|
||||
),
|
||||
// QR CODE SCANNER
|
||||
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const qrcodeScreen()));
|
||||
},
|
||||
child: const Text('QR Code Scanner'),
|
||||
),
|
||||
// BAR CODE SCANNER
|
||||
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const BarcodeScreen()));
|
||||
},
|
||||
child: const Text('Bar Code Scanner'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,85 +1,85 @@
|
||||
// ignore_for_file: use_build_context_synchronously
|
||||
import 'package:flutter/material.dart';
|
||||
// OLD: import 'package:flutter_barcode_scanner/flutter_barcode_scanner.dart'; // removed no namespace AGP8 - by Azmat
|
||||
import 'package:mobile_scanner/mobile_scanner.dart'; // migrated for AGP8 Java17 - by Azmat
|
||||
|
||||
class qrcodeScreen extends StatefulWidget {
|
||||
const qrcodeScreen({super.key});
|
||||
|
||||
@override
|
||||
_qrcodeScreenState createState() => _qrcodeScreenState();
|
||||
}
|
||||
|
||||
class _qrcodeScreenState extends State<qrcodeScreen> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
String scannedqr_code_scanner = 'No data';
|
||||
|
||||
// OLD scanQRcode via FlutterBarcodeScanner - removed no namespace AGP8 - by Azmat
|
||||
final MobileScannerController qrCodeController = MobileScannerController(); // mobile_scanner controller - by Azmat
|
||||
Future<void> scanQRcode() async {
|
||||
final String? result = await Navigator.push<String>(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => Scaffold(
|
||||
appBar: AppBar(title: const Text('Scan QR')),
|
||||
body: MobileScanner(
|
||||
controller: qrCodeController,
|
||||
onDetect: (capture) => Navigator.pop(
|
||||
context,
|
||||
capture.barcodes.isNotEmpty ? (capture.barcodes.first.rawValue ?? '') : '',
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
scannedqr_code_scanner = result ?? '';
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('QR Code')),
|
||||
body: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Center(
|
||||
child: Column(
|
||||
children: [
|
||||
const Text(
|
||||
'Scanned QRcode:',
|
||||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
scannedqr_code_scanner,
|
||||
style: const TextStyle(fontSize: 16),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
scanQRcode(); // Trigger barcode scanning
|
||||
},
|
||||
icon: const Icon(Icons.camera_alt), // Camera icon
|
||||
label: const Text('Scan QRcode'),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
// ignore_for_file: use_build_context_synchronously
|
||||
import 'package:flutter/material.dart';
|
||||
// OLD: import 'package:flutter_barcode_scanner/flutter_barcode_scanner.dart'; // removed no namespace AGP8 - by Azmat
|
||||
import 'package:mobile_scanner/mobile_scanner.dart'; // migrated for AGP8 Java17 - by Azmat
|
||||
|
||||
class qrcodeScreen extends StatefulWidget {
|
||||
const qrcodeScreen({super.key});
|
||||
|
||||
@override
|
||||
_qrcodeScreenState createState() => _qrcodeScreenState();
|
||||
}
|
||||
|
||||
class _qrcodeScreenState extends State<qrcodeScreen> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
String scannedqr_code_scanner = 'No data';
|
||||
|
||||
// OLD scanQRcode via FlutterBarcodeScanner - removed no namespace AGP8 - by Azmat
|
||||
final MobileScannerController qrCodeController = MobileScannerController(); // mobile_scanner controller - by Azmat
|
||||
Future<void> scanQRcode() async {
|
||||
final String? result = await Navigator.push<String>(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => Scaffold(
|
||||
appBar: AppBar(title: const Text('Scan QR')),
|
||||
body: MobileScanner(
|
||||
controller: qrCodeController,
|
||||
onDetect: (capture) => Navigator.pop(
|
||||
context,
|
||||
capture.barcodes.isNotEmpty ? (capture.barcodes.first.rawValue ?? '') : '',
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
if (!mounted) return;
|
||||
setState(() {
|
||||
scannedqr_code_scanner = result ?? '';
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('QR Code')),
|
||||
body: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Center(
|
||||
child: Column(
|
||||
children: [
|
||||
const Text(
|
||||
'Scanned QRcode:',
|
||||
style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
Text(
|
||||
scannedqr_code_scanner,
|
||||
style: const TextStyle(fontSize: 16),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
scanQRcode(); // Trigger barcode scanning
|
||||
},
|
||||
icon: const Icon(Icons.camera_alt), // Camera icon
|
||||
label: const Text('Scan QRcode'),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
+127
-127
@@ -1,127 +1,127 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../Utils/image_constant.dart';
|
||||
import '../../Utils/size_utils.dart';
|
||||
import '../../widgets/app_bar/appbar_image.dart';
|
||||
import '../../widgets/app_bar/appbar_title.dart';
|
||||
import '../../widgets/app_bar/custom_app_bar.dart';
|
||||
import '../SysParameters/SystemParameterScreen.dart';
|
||||
|
||||
class SetupScreen extends StatelessWidget {
|
||||
const SetupScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: CustomAppBar(
|
||||
height: getVerticalSize(49),
|
||||
leadingWidth: 40,
|
||||
leading: AppbarImage(
|
||||
height: getSize(24),
|
||||
width: getSize(24),
|
||||
svgPath: ImageConstant.imgArrowleftBlueGray900,
|
||||
margin: getMargin(left: 16, top: 12, bottom: 13),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
}),
|
||||
centerTitle: true,
|
||||
title: AppbarTitle(text: "Setup Screen")),
|
||||
body: SingleChildScrollView(
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
buildSetupBlock(context, 'User Maintenance', SysParameter()),
|
||||
buildSetupBlock(context, 'User Group Maintenance', SysParameter()),
|
||||
buildSetupBlock(context, 'Menu Maintenance', SysParameter()),
|
||||
buildSetupBlock(context, 'Menu Access', SysParameter()),
|
||||
buildSetupBlock(context, 'System Parameter', SysParameter()),
|
||||
buildSetupBlock(context, 'Access Type', SysParameter()),
|
||||
// buildSetupBlock(context, 'Report', ReportPage()),
|
||||
buildSetupBlock(context, 'Dashboard', SysParameter()),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildSetupBlock(BuildContext context, String title, Widget screen) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => screen),
|
||||
);
|
||||
},
|
||||
child: Card(
|
||||
color: Colors.white,
|
||||
elevation: 0.0,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(20, 40, 20, 40),
|
||||
child: Column(
|
||||
children: [
|
||||
// Container(
|
||||
// height: getSize(
|
||||
// 55,
|
||||
// ),
|
||||
// width: getSize(
|
||||
// 55,
|
||||
// ),
|
||||
// margin: getMargin(
|
||||
// top: 2,
|
||||
// ),
|
||||
// child: Stack(
|
||||
// alignment: Alignment.center,
|
||||
// children: [
|
||||
// Align(
|
||||
// alignment: Alignment.center,
|
||||
// child: Container(
|
||||
// height: getSize(
|
||||
// 55,
|
||||
// ),
|
||||
// width: getSize(
|
||||
// 55,
|
||||
// ),
|
||||
// child: CircularProgressIndicator(
|
||||
// value: 0.5,
|
||||
// backgroundColor: ColorConstant.gray30099,
|
||||
// color: ColorConstant.blueA700,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// Align(
|
||||
// alignment: Alignment.center,
|
||||
// child: Text(
|
||||
// myProjectcount.toString(),
|
||||
// overflow: TextOverflow.ellipsis,
|
||||
// textAlign: TextAlign.left,
|
||||
// style: AppStyle.txtGilroyBold18,
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// Text(
|
||||
// myProjectcount.toString(),
|
||||
// style: const TextStyle(
|
||||
// color: Colors.black,
|
||||
// fontSize: 12,
|
||||
// ),
|
||||
// ),
|
||||
const SizedBox(height: 3,),
|
||||
Text(
|
||||
title,
|
||||
style: const TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 10,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../Utils/image_constant.dart';
|
||||
import '../../Utils/size_utils.dart';
|
||||
import '../../widgets/app_bar/appbar_image.dart';
|
||||
import '../../widgets/app_bar/appbar_title.dart';
|
||||
import '../../widgets/app_bar/custom_app_bar.dart';
|
||||
import '../SysParameters/SystemParameterScreen.dart';
|
||||
|
||||
class SetupScreen extends StatelessWidget {
|
||||
const SetupScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: CustomAppBar(
|
||||
height: getVerticalSize(49),
|
||||
leadingWidth: 40,
|
||||
leading: AppbarImage(
|
||||
height: getSize(24),
|
||||
width: getSize(24),
|
||||
svgPath: ImageConstant.imgArrowleftBlueGray900,
|
||||
margin: getMargin(left: 16, top: 12, bottom: 13),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
}),
|
||||
centerTitle: true,
|
||||
title: AppbarTitle(text: "Setup Screen")),
|
||||
body: SingleChildScrollView(
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
buildSetupBlock(context, 'User Maintenance', SysParameter()),
|
||||
buildSetupBlock(context, 'User Group Maintenance', SysParameter()),
|
||||
buildSetupBlock(context, 'Menu Maintenance', SysParameter()),
|
||||
buildSetupBlock(context, 'Menu Access', SysParameter()),
|
||||
buildSetupBlock(context, 'System Parameter', SysParameter()),
|
||||
buildSetupBlock(context, 'Access Type', SysParameter()),
|
||||
// buildSetupBlock(context, 'Report', ReportPage()),
|
||||
buildSetupBlock(context, 'Dashboard', SysParameter()),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildSetupBlock(BuildContext context, String title, Widget screen) {
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => screen),
|
||||
);
|
||||
},
|
||||
child: Card(
|
||||
color: Colors.white,
|
||||
elevation: 0.0,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(20, 40, 20, 40),
|
||||
child: Column(
|
||||
children: [
|
||||
// Container(
|
||||
// height: getSize(
|
||||
// 55,
|
||||
// ),
|
||||
// width: getSize(
|
||||
// 55,
|
||||
// ),
|
||||
// margin: getMargin(
|
||||
// top: 2,
|
||||
// ),
|
||||
// child: Stack(
|
||||
// alignment: Alignment.center,
|
||||
// children: [
|
||||
// Align(
|
||||
// alignment: Alignment.center,
|
||||
// child: Container(
|
||||
// height: getSize(
|
||||
// 55,
|
||||
// ),
|
||||
// width: getSize(
|
||||
// 55,
|
||||
// ),
|
||||
// child: CircularProgressIndicator(
|
||||
// value: 0.5,
|
||||
// backgroundColor: ColorConstant.gray30099,
|
||||
// color: ColorConstant.blueA700,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// Align(
|
||||
// alignment: Alignment.center,
|
||||
// child: Text(
|
||||
// myProjectcount.toString(),
|
||||
// overflow: TextOverflow.ellipsis,
|
||||
// textAlign: TextAlign.left,
|
||||
// style: AppStyle.txtGilroyBold18,
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
// Text(
|
||||
// myProjectcount.toString(),
|
||||
// style: const TextStyle(
|
||||
// color: Colors.black,
|
||||
// fontSize: 12,
|
||||
// ),
|
||||
// ),
|
||||
const SizedBox(height: 3,),
|
||||
Text(
|
||||
title,
|
||||
style: const TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 10,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,77 +1,77 @@
|
||||
import 'dart:typed_data';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:http_parser/http_parser.dart';
|
||||
|
||||
import '../../resources/api_constants.dart';
|
||||
import '../LogoutService/Logoutservice.dart';
|
||||
|
||||
class SystemParameterApiService {
|
||||
final String baseUrl = ApiConstants.baseUrl;
|
||||
final Dio dio = Dio();
|
||||
|
||||
Future<Map<String, dynamic>> getsystemparameters(String token, int id) async {
|
||||
try {
|
||||
dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
final response = await dio.get('$baseUrl/sysparam/getSysParams/$id');
|
||||
if (response.statusCode == 401) {
|
||||
LogoutService.logout();
|
||||
}
|
||||
final entities = (response.data);
|
||||
return entities;
|
||||
} catch (e) {
|
||||
throw Exception('Failed to get all projects: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> updateParameter(
|
||||
String token, int entityId, Map<String, dynamic> entity) async {
|
||||
try {
|
||||
dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
var response = await dio
|
||||
.put('$baseUrl/sysparam/updateSysParams/$entityId', data: entity);
|
||||
if (response.statusCode == 401) {
|
||||
LogoutService.logout();
|
||||
}
|
||||
print(entity);
|
||||
} catch (e) {
|
||||
throw Exception('Failed to update projects: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> createFile(
|
||||
Uint8List fileBytes, String fileName, String token) async {
|
||||
try {
|
||||
String apiUrl = "$baseUrl/api/logos/upload?ref=test";
|
||||
|
||||
final mimeType = 'image/jpeg'; // You can set the appropriate MIME type
|
||||
|
||||
FormData formData = FormData.fromMap({
|
||||
'file': MultipartFile.fromBytes(
|
||||
fileBytes,
|
||||
filename: fileName,
|
||||
contentType: MediaType.parse(mimeType),
|
||||
),
|
||||
});
|
||||
|
||||
Dio dio = Dio(); // Create a new Dio instance
|
||||
dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
|
||||
final response = await dio.post(apiUrl, data: formData);
|
||||
if (response.statusCode == 401) {
|
||||
LogoutService.logout();
|
||||
}
|
||||
if (response.statusCode == 200) {
|
||||
print('File uploaded successfully');
|
||||
return response.data; // Return the response data on success
|
||||
} else {
|
||||
print('Failed to upload file with status: ${response.statusCode}');
|
||||
// You might want to handle this error case more explicitly
|
||||
throw Exception('Failed to upload file');
|
||||
}
|
||||
} catch (error) {
|
||||
print('Error occurred during form submission: $error');
|
||||
// You might want to handle this error case more explicitly
|
||||
throw Exception('Error during file upload: $error');
|
||||
}
|
||||
}
|
||||
}
|
||||
import 'dart:typed_data';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:http_parser/http_parser.dart';
|
||||
|
||||
import '../../resources/api_constants.dart';
|
||||
import '../LogoutService/Logoutservice.dart';
|
||||
|
||||
class SystemParameterApiService {
|
||||
final String baseUrl = ApiConstants.baseUrl;
|
||||
final Dio dio = Dio();
|
||||
|
||||
Future<Map<String, dynamic>> getsystemparameters(String token, int id) async {
|
||||
try {
|
||||
dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
final response = await dio.get('$baseUrl/sysparam/getSysParams/$id');
|
||||
if (response.statusCode == 401) {
|
||||
LogoutService.logout();
|
||||
}
|
||||
final entities = (response.data);
|
||||
return entities;
|
||||
} catch (e) {
|
||||
throw Exception('Failed to get all projects: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> updateParameter(
|
||||
String token, int entityId, Map<String, dynamic> entity) async {
|
||||
try {
|
||||
dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
var response = await dio
|
||||
.put('$baseUrl/sysparam/updateSysParams/$entityId', data: entity);
|
||||
if (response.statusCode == 401) {
|
||||
LogoutService.logout();
|
||||
}
|
||||
print(entity);
|
||||
} catch (e) {
|
||||
throw Exception('Failed to update projects: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<Map<String, dynamic>> createFile(
|
||||
Uint8List fileBytes, String fileName, String token) async {
|
||||
try {
|
||||
String apiUrl = "$baseUrl/api/logos/upload?ref=test";
|
||||
|
||||
final mimeType = 'image/jpeg'; // You can set the appropriate MIME type
|
||||
|
||||
FormData formData = FormData.fromMap({
|
||||
'file': MultipartFile.fromBytes(
|
||||
fileBytes,
|
||||
filename: fileName,
|
||||
contentType: MediaType.parse(mimeType),
|
||||
),
|
||||
});
|
||||
|
||||
Dio dio = Dio(); // Create a new Dio instance
|
||||
dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
|
||||
final response = await dio.post(apiUrl, data: formData);
|
||||
if (response.statusCode == 401) {
|
||||
LogoutService.logout();
|
||||
}
|
||||
if (response.statusCode == 200) {
|
||||
print('File uploaded successfully');
|
||||
return response.data; // Return the response data on success
|
||||
} else {
|
||||
print('Failed to upload file with status: ${response.statusCode}');
|
||||
// You might want to handle this error case more explicitly
|
||||
throw Exception('Failed to upload file');
|
||||
}
|
||||
} catch (error) {
|
||||
print('Error occurred during form submission: $error');
|
||||
// You might want to handle this error case more explicitly
|
||||
throw Exception('Error during file upload: $error');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,279 +1,279 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../providers/token_manager.dart';
|
||||
import 'dynamic_form_service.dart';
|
||||
|
||||
class EditForm extends StatefulWidget {
|
||||
final Map<String, dynamic> formData;
|
||||
|
||||
EditForm({required this.formData});
|
||||
|
||||
@override
|
||||
_EditFormState createState() => _EditFormState();
|
||||
}
|
||||
|
||||
class _EditFormState extends State<EditForm> {
|
||||
TextEditingController formNameController = TextEditingController();
|
||||
TextEditingController formDescController = TextEditingController();
|
||||
TextEditingController relatedToController = TextEditingController();
|
||||
TextEditingController pageEventController = TextEditingController();
|
||||
TextEditingController buttonCaptionController = TextEditingController();
|
||||
|
||||
final DynamicForApiService apiService = DynamicForApiService();
|
||||
|
||||
List<dynamic> components = []; // List to store table data
|
||||
List<dynamic> relatedToFixedDropdown = ['Menu', 'Related To',];
|
||||
List<dynamic> pageEventFixedDropdown = ['OnClick', 'OnBlur',];
|
||||
|
||||
List<dynamic> typeFixedDropdown = ['text', 'dropdown','date','checkbox','textarea','togglebutton'];
|
||||
List<dynamic> mappingFixedDropdown = ['TEXTFIELD1', 'TEXTFIELD2','TEXTFIELD3','TEXTFIELD4','TEXTFIELD5','TEXTFIELD6','TEXTFIELD7','TEXTFIELD8','TEXTFIELD9','TEXTFIELD10','TEXTFIELD11','TEXTFIELD12','TEXTFIELD13','TEXTFIELD14','TEXTFIELD15','TEXTFIELD16','TEXTFIELD17','TEXTFIELD18','TEXTFIELD19','TEXTFIELD20','TEXTFIELD21','TEXTFIELD22','TEXTFIELD23',
|
||||
'TEXTFIELD24','TEXTFIELD25','TEXTFIELD26','LONGTEXT1','LONGTEXT2','LONGTEXT3','LONGTEXT4',];
|
||||
List<dynamic> truefalseFixedDropdown = ['true', 'false',];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// Initialize text controllers with the data from the selected row
|
||||
formNameController.text = widget.formData['form_name'] ?? '';
|
||||
formDescController.text = widget.formData['form_desc'] ?? '';
|
||||
relatedToController.text = widget.formData['related_to'] ?? '';
|
||||
pageEventController.text = widget.formData['page_event'] ?? '';
|
||||
buttonCaptionController.text = widget.formData['button_caption'] ?? '';
|
||||
|
||||
// Initialize the components data, or you can load it from formData['components'].
|
||||
// For this example, we'll use an empty list.
|
||||
components = widget.formData['components'] ?? [];
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('Edit Form'),
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
children: [
|
||||
TextFormField(
|
||||
controller: formNameController,
|
||||
decoration: InputDecoration(labelText: 'Form Name'),
|
||||
),
|
||||
TextFormField(
|
||||
controller: formDescController,
|
||||
decoration: InputDecoration(labelText: 'Form Description'),
|
||||
),
|
||||
DropdownButtonFormField<String>(
|
||||
value: relatedToController.text,
|
||||
decoration:
|
||||
const InputDecoration(labelText: 'Select Related To'),
|
||||
items: [
|
||||
...relatedToFixedDropdown.map<DropdownMenuItem<String>>(
|
||||
(item) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: item.toString(),
|
||||
child: Text(item),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
relatedToController.text = value!;
|
||||
});
|
||||
},
|
||||
),
|
||||
DropdownButtonFormField<String>(
|
||||
value: pageEventController.text,
|
||||
decoration:
|
||||
const InputDecoration(labelText: 'Select Page Event'),
|
||||
items: [
|
||||
...pageEventFixedDropdown.map<DropdownMenuItem<String>>(
|
||||
(item) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: item.toString(),
|
||||
child: Text(item),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
pageEventController.text = value!;
|
||||
});
|
||||
},
|
||||
),
|
||||
TextFormField(
|
||||
controller: buttonCaptionController,
|
||||
decoration: InputDecoration(labelText: 'Button Caption'),
|
||||
),
|
||||
|
||||
const Text('Components Details'),
|
||||
SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: DataTable(
|
||||
columns: const <DataColumn>[
|
||||
DataColumn(label: Text('Label')),
|
||||
DataColumn(label: Text('Type')),
|
||||
DataColumn(label: Text('Mapping')),
|
||||
DataColumn(label: Text('Mandatory')),
|
||||
DataColumn(label: Text('Readonly')),
|
||||
DataColumn(label: Text('Drop Values')),
|
||||
DataColumn(label: Text('SP')),
|
||||
DataColumn(label: Text('Actions'), numeric: false), // Add Actions column
|
||||
],
|
||||
rows: components.asMap().entries.map((entry) {
|
||||
final index = entry.key;
|
||||
final component = entry.value;
|
||||
|
||||
return DataRow(
|
||||
cells: <DataCell>[
|
||||
DataCell(TextField(
|
||||
controller: TextEditingController(text: component['label'] ?? ''),
|
||||
onChanged: (value){
|
||||
component['label']=value;
|
||||
},
|
||||
)),
|
||||
DataCell(
|
||||
DropdownButtonFormField<String>(
|
||||
value: component['type'],
|
||||
decoration:
|
||||
const InputDecoration(labelText: 'Select Type'),
|
||||
items: [
|
||||
...typeFixedDropdown.map<DropdownMenuItem<String>>(
|
||||
(item) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: item.toString(),
|
||||
child: Text(item),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
component['type'] = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
|
||||
),
|
||||
DataCell(
|
||||
DropdownButtonFormField<String>(
|
||||
value: component['mapping'],
|
||||
decoration:
|
||||
const InputDecoration(labelText: 'Select Mapping'),
|
||||
items: [
|
||||
...mappingFixedDropdown.map<DropdownMenuItem<String>>(
|
||||
(item) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: item.toString(),
|
||||
child: Text(item),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
component['mapping'] = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
|
||||
),
|
||||
DataCell(TextField(
|
||||
controller: TextEditingController(text: component['mandatory'] ?? ''),
|
||||
onChanged: (value){
|
||||
component['mandatory']=value;
|
||||
},
|
||||
)),
|
||||
DataCell(
|
||||
DropdownButtonFormField<String>(
|
||||
value: component['readonly'],
|
||||
decoration:
|
||||
const InputDecoration(labelText: 'Select Read Only'),
|
||||
items: [
|
||||
...truefalseFixedDropdown.map<DropdownMenuItem<String>>(
|
||||
(item) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: item.toString(),
|
||||
child: Text(item),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
component['readonly'] = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
DataCell(TextField(
|
||||
controller: TextEditingController(text: component['drop_values'] ?? ''),
|
||||
onChanged: (value){
|
||||
component['drop_values']=value;
|
||||
},
|
||||
)),
|
||||
DataCell(TextField(
|
||||
controller: TextEditingController(text: component['sp'] ?? ''),
|
||||
onChanged: (value){
|
||||
component['sp']=value;
|
||||
},
|
||||
)),
|
||||
DataCell(
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
components.removeAt(index);
|
||||
});
|
||||
},
|
||||
child: Text('Delete'),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
// Add a new row to the components table
|
||||
components.add({
|
||||
'label': '',
|
||||
'type': null,
|
||||
'mapping': null,
|
||||
'mandatory': '',
|
||||
'readonly': null,
|
||||
'drop_values': '',
|
||||
'sp': '',
|
||||
});
|
||||
setState(() {}); // Refresh the UI to show the new row
|
||||
},
|
||||
child: Text('Add Row'),
|
||||
),
|
||||
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
// Save the updated data back to the original data list
|
||||
widget.formData['form_name'] = formNameController.text;
|
||||
widget.formData['form_desc'] = formDescController.text;
|
||||
widget.formData['related_to'] = relatedToController.text;
|
||||
widget.formData['page_event'] = pageEventController.text;
|
||||
widget.formData['button_caption'] = buttonCaptionController.text;
|
||||
widget.formData['components'] = components;
|
||||
final token = await TokenManager.getToken();
|
||||
apiService.updateDynamicForm(token!, widget.formData['form_id'], widget.formData);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text('Update'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../providers/token_manager.dart';
|
||||
import 'dynamic_form_service.dart';
|
||||
|
||||
class EditForm extends StatefulWidget {
|
||||
final Map<String, dynamic> formData;
|
||||
|
||||
EditForm({required this.formData});
|
||||
|
||||
@override
|
||||
_EditFormState createState() => _EditFormState();
|
||||
}
|
||||
|
||||
class _EditFormState extends State<EditForm> {
|
||||
TextEditingController formNameController = TextEditingController();
|
||||
TextEditingController formDescController = TextEditingController();
|
||||
TextEditingController relatedToController = TextEditingController();
|
||||
TextEditingController pageEventController = TextEditingController();
|
||||
TextEditingController buttonCaptionController = TextEditingController();
|
||||
|
||||
final DynamicForApiService apiService = DynamicForApiService();
|
||||
|
||||
List<dynamic> components = []; // List to store table data
|
||||
List<dynamic> relatedToFixedDropdown = ['Menu', 'Related To',];
|
||||
List<dynamic> pageEventFixedDropdown = ['OnClick', 'OnBlur',];
|
||||
|
||||
List<dynamic> typeFixedDropdown = ['text', 'dropdown','date','checkbox','textarea','togglebutton'];
|
||||
List<dynamic> mappingFixedDropdown = ['TEXTFIELD1', 'TEXTFIELD2','TEXTFIELD3','TEXTFIELD4','TEXTFIELD5','TEXTFIELD6','TEXTFIELD7','TEXTFIELD8','TEXTFIELD9','TEXTFIELD10','TEXTFIELD11','TEXTFIELD12','TEXTFIELD13','TEXTFIELD14','TEXTFIELD15','TEXTFIELD16','TEXTFIELD17','TEXTFIELD18','TEXTFIELD19','TEXTFIELD20','TEXTFIELD21','TEXTFIELD22','TEXTFIELD23',
|
||||
'TEXTFIELD24','TEXTFIELD25','TEXTFIELD26','LONGTEXT1','LONGTEXT2','LONGTEXT3','LONGTEXT4',];
|
||||
List<dynamic> truefalseFixedDropdown = ['true', 'false',];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// Initialize text controllers with the data from the selected row
|
||||
formNameController.text = widget.formData['form_name'] ?? '';
|
||||
formDescController.text = widget.formData['form_desc'] ?? '';
|
||||
relatedToController.text = widget.formData['related_to'] ?? '';
|
||||
pageEventController.text = widget.formData['page_event'] ?? '';
|
||||
buttonCaptionController.text = widget.formData['button_caption'] ?? '';
|
||||
|
||||
// Initialize the components data, or you can load it from formData['components'].
|
||||
// For this example, we'll use an empty list.
|
||||
components = widget.formData['components'] ?? [];
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('Edit Form'),
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
children: [
|
||||
TextFormField(
|
||||
controller: formNameController,
|
||||
decoration: InputDecoration(labelText: 'Form Name'),
|
||||
),
|
||||
TextFormField(
|
||||
controller: formDescController,
|
||||
decoration: InputDecoration(labelText: 'Form Description'),
|
||||
),
|
||||
DropdownButtonFormField<String>(
|
||||
value: relatedToController.text,
|
||||
decoration:
|
||||
const InputDecoration(labelText: 'Select Related To'),
|
||||
items: [
|
||||
...relatedToFixedDropdown.map<DropdownMenuItem<String>>(
|
||||
(item) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: item.toString(),
|
||||
child: Text(item),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
relatedToController.text = value!;
|
||||
});
|
||||
},
|
||||
),
|
||||
DropdownButtonFormField<String>(
|
||||
value: pageEventController.text,
|
||||
decoration:
|
||||
const InputDecoration(labelText: 'Select Page Event'),
|
||||
items: [
|
||||
...pageEventFixedDropdown.map<DropdownMenuItem<String>>(
|
||||
(item) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: item.toString(),
|
||||
child: Text(item),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
pageEventController.text = value!;
|
||||
});
|
||||
},
|
||||
),
|
||||
TextFormField(
|
||||
controller: buttonCaptionController,
|
||||
decoration: InputDecoration(labelText: 'Button Caption'),
|
||||
),
|
||||
|
||||
const Text('Components Details'),
|
||||
SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: DataTable(
|
||||
columns: const <DataColumn>[
|
||||
DataColumn(label: Text('Label')),
|
||||
DataColumn(label: Text('Type')),
|
||||
DataColumn(label: Text('Mapping')),
|
||||
DataColumn(label: Text('Mandatory')),
|
||||
DataColumn(label: Text('Readonly')),
|
||||
DataColumn(label: Text('Drop Values')),
|
||||
DataColumn(label: Text('SP')),
|
||||
DataColumn(label: Text('Actions'), numeric: false), // Add Actions column
|
||||
],
|
||||
rows: components.asMap().entries.map((entry) {
|
||||
final index = entry.key;
|
||||
final component = entry.value;
|
||||
|
||||
return DataRow(
|
||||
cells: <DataCell>[
|
||||
DataCell(TextField(
|
||||
controller: TextEditingController(text: component['label'] ?? ''),
|
||||
onChanged: (value){
|
||||
component['label']=value;
|
||||
},
|
||||
)),
|
||||
DataCell(
|
||||
DropdownButtonFormField<String>(
|
||||
value: component['type'],
|
||||
decoration:
|
||||
const InputDecoration(labelText: 'Select Type'),
|
||||
items: [
|
||||
...typeFixedDropdown.map<DropdownMenuItem<String>>(
|
||||
(item) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: item.toString(),
|
||||
child: Text(item),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
component['type'] = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
|
||||
),
|
||||
DataCell(
|
||||
DropdownButtonFormField<String>(
|
||||
value: component['mapping'],
|
||||
decoration:
|
||||
const InputDecoration(labelText: 'Select Mapping'),
|
||||
items: [
|
||||
...mappingFixedDropdown.map<DropdownMenuItem<String>>(
|
||||
(item) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: item.toString(),
|
||||
child: Text(item),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
component['mapping'] = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
|
||||
),
|
||||
DataCell(TextField(
|
||||
controller: TextEditingController(text: component['mandatory'] ?? ''),
|
||||
onChanged: (value){
|
||||
component['mandatory']=value;
|
||||
},
|
||||
)),
|
||||
DataCell(
|
||||
DropdownButtonFormField<String>(
|
||||
value: component['readonly'],
|
||||
decoration:
|
||||
const InputDecoration(labelText: 'Select Read Only'),
|
||||
items: [
|
||||
...truefalseFixedDropdown.map<DropdownMenuItem<String>>(
|
||||
(item) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: item.toString(),
|
||||
child: Text(item),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
component['readonly'] = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
DataCell(TextField(
|
||||
controller: TextEditingController(text: component['drop_values'] ?? ''),
|
||||
onChanged: (value){
|
||||
component['drop_values']=value;
|
||||
},
|
||||
)),
|
||||
DataCell(TextField(
|
||||
controller: TextEditingController(text: component['sp'] ?? ''),
|
||||
onChanged: (value){
|
||||
component['sp']=value;
|
||||
},
|
||||
)),
|
||||
DataCell(
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
components.removeAt(index);
|
||||
});
|
||||
},
|
||||
child: Text('Delete'),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
// Add a new row to the components table
|
||||
components.add({
|
||||
'label': '',
|
||||
'type': null,
|
||||
'mapping': null,
|
||||
'mandatory': '',
|
||||
'readonly': null,
|
||||
'drop_values': '',
|
||||
'sp': '',
|
||||
});
|
||||
setState(() {}); // Refresh the UI to show the new row
|
||||
},
|
||||
child: Text('Add Row'),
|
||||
),
|
||||
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
// Save the updated data back to the original data list
|
||||
widget.formData['form_name'] = formNameController.text;
|
||||
widget.formData['form_desc'] = formDescController.text;
|
||||
widget.formData['related_to'] = relatedToController.text;
|
||||
widget.formData['page_event'] = pageEventController.text;
|
||||
widget.formData['button_caption'] = buttonCaptionController.text;
|
||||
widget.formData['components'] = components;
|
||||
final token = await TokenManager.getToken();
|
||||
apiService.updateDynamicForm(token!, widget.formData['form_id'], widget.formData);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
child: Text('Update'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,333 +1,333 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../Utils/image_constant.dart';
|
||||
import '../../Utils/size_utils.dart';
|
||||
import '../../providers/token_manager.dart';
|
||||
import '../../theme/app_style.dart';
|
||||
import '../../widgets/app_bar/appbar_image.dart';
|
||||
import '../../widgets/app_bar/appbar_title.dart';
|
||||
import '../../widgets/app_bar/custom_app_bar.dart';
|
||||
import '../../widgets/custom_button.dart';
|
||||
import '../../widgets/custom_dropdown_field.dart';
|
||||
import '../../widgets/custom_text_form_field.dart';
|
||||
import 'dynamic_form_service.dart';
|
||||
|
||||
class CreateForm extends StatefulWidget {
|
||||
@override
|
||||
_CreateFormState createState() => _CreateFormState();
|
||||
}
|
||||
|
||||
class _CreateFormState extends State<CreateForm> {
|
||||
TextEditingController formNameController = TextEditingController();
|
||||
TextEditingController formDescController = TextEditingController();
|
||||
TextEditingController relatedToController = TextEditingController();
|
||||
TextEditingController pageEventController = TextEditingController();
|
||||
TextEditingController buttonCaptionController = TextEditingController();
|
||||
|
||||
final DynamicForApiService apiService = DynamicForApiService();
|
||||
|
||||
List<Map<String, dynamic>> components = [];
|
||||
|
||||
List<dynamic> relatedToFixedDropdown = ['Menu', 'Related To',];
|
||||
List<dynamic> pageEventFixedDropdown = ['OnClick', 'OnBlur',];
|
||||
|
||||
List<dynamic> typeFixedDropdown = ['text', 'dropdown','date','checkbox','textarea','togglebutton'];
|
||||
List<dynamic> mappingFixedDropdown = ['TEXTFIELD1', 'TEXTFIELD2','TEXTFIELD3','TEXTFIELD4','TEXTFIELD5','TEXTFIELD6','TEXTFIELD7','TEXTFIELD8','TEXTFIELD9','TEXTFIELD10','TEXTFIELD11','TEXTFIELD12','TEXTFIELD13','TEXTFIELD14','TEXTFIELD15','TEXTFIELD16','TEXTFIELD17','TEXTFIELD18','TEXTFIELD19','TEXTFIELD20','TEXTFIELD21','TEXTFIELD22','TEXTFIELD23',
|
||||
'TEXTFIELD24','TEXTFIELD25','TEXTFIELD26','LONGTEXT1','LONGTEXT2','LONGTEXT3','LONGTEXT4',];
|
||||
List<dynamic> truefalseFixedDropdown = ['true', 'false',];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: CustomAppBar(
|
||||
height: getVerticalSize(49),
|
||||
leadingWidth: 40,
|
||||
leading: AppbarImage(
|
||||
height: getSize(24),
|
||||
width: getSize(24),
|
||||
svgPath: ImageConstant.imgArrowleft,
|
||||
margin: getMargin(left: 16, top: 12, bottom: 13),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
}),
|
||||
centerTitle: true,
|
||||
title: AppbarTitle(text: "Create Dynamic Form"),),
|
||||
body: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text("Form Name",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle
|
||||
.txtGilroyMedium16Bluegray900),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
hintText: "Enter Form Name",
|
||||
controller: formNameController,
|
||||
margin: getMargin(top: 6))
|
||||
])),
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text("Form Description",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle
|
||||
.txtGilroyMedium16Bluegray900),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
hintText: "Enter Form Description",
|
||||
controller: formDescController,
|
||||
margin: getMargin(top: 6))
|
||||
])),
|
||||
|
||||
Padding(
|
||||
padding: getPadding(top: 18),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Select Related To",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroyMedium16Bluegray900,
|
||||
),
|
||||
CustomDropdownFormField(
|
||||
items: [
|
||||
...relatedToFixedDropdown.map<DropdownMenuItem<String>>(
|
||||
(item) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: item.toString(),
|
||||
child: Text(item, style: AppStyle.txtGilroyMedium16Bluegray900),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
relatedToController.text = value!;
|
||||
});
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Padding(
|
||||
padding: getPadding(top: 18),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Select Page Event",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroyMedium16Bluegray900,
|
||||
),
|
||||
CustomDropdownFormField(
|
||||
items: [
|
||||
...pageEventFixedDropdown.map<DropdownMenuItem<String>>(
|
||||
(item) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: item.toString(),
|
||||
child: Text(item,style: AppStyle.txtGilroyMedium16Bluegray900),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
pageEventController.text = value!;
|
||||
});
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text("Button Caption",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle
|
||||
.txtGilroyMedium16Bluegray900),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
hintText: "Enter Button Caption",
|
||||
controller: buttonCaptionController,
|
||||
margin: getMargin(top: 6))
|
||||
])),
|
||||
const Text('Components Details'),
|
||||
SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: DataTable(
|
||||
columns: const <DataColumn>[
|
||||
DataColumn(label: Text('Label')),
|
||||
DataColumn(label: Text('Type')),
|
||||
DataColumn(label: Text('Mapping')),
|
||||
DataColumn(label: Text('Mandatory')),
|
||||
DataColumn(label: Text('Readonly')),
|
||||
DataColumn(label: Text('Drop Values')),
|
||||
DataColumn(label: Text('SP')),
|
||||
],
|
||||
rows: components.asMap().entries.map((entry) {
|
||||
final index = entry.key;
|
||||
final component = entry.value;
|
||||
bool? isReadonly = false;
|
||||
return DataRow(
|
||||
cells: <DataCell>[
|
||||
DataCell(TextField(
|
||||
controller: TextEditingController(text: component['label'] ?? ''),
|
||||
onChanged: (value) {
|
||||
component['label'] = value;
|
||||
},
|
||||
)),
|
||||
DataCell(
|
||||
DropdownButtonFormField<String>(
|
||||
decoration:
|
||||
const InputDecoration(labelText: 'Select Type'),
|
||||
items: [
|
||||
...typeFixedDropdown.map<DropdownMenuItem<String>>(
|
||||
(item) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: item.toString(),
|
||||
child: Text(item,style: AppStyle.txtGilroyMedium16Bluegray900),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
component['type'] = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
|
||||
),
|
||||
DataCell(
|
||||
DropdownButtonFormField<String>(
|
||||
decoration:
|
||||
const InputDecoration(labelText: 'Select Mapping'),
|
||||
items: [
|
||||
...mappingFixedDropdown.map<DropdownMenuItem<String>>(
|
||||
(item) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: item.toString(),
|
||||
child: Text(item,style: AppStyle.txtGilroyMedium16Bluegray900),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
component['mapping'] = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
|
||||
),
|
||||
DataCell(TextField(
|
||||
controller: TextEditingController(text: component['mandatory'] ?? ''),
|
||||
onChanged: (value) {
|
||||
component['mandatory'] = value;
|
||||
},
|
||||
)),
|
||||
DataCell(
|
||||
DropdownButtonFormField<String>(
|
||||
decoration:
|
||||
const InputDecoration(labelText: 'Select Read Only'),
|
||||
items: [
|
||||
...truefalseFixedDropdown.map<DropdownMenuItem<String>>(
|
||||
(item) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: item.toString(),
|
||||
child: Text(item,style: AppStyle.txtGilroyMedium16Bluegray900),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
component['readonly'] = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
|
||||
),
|
||||
DataCell(TextField(
|
||||
controller: TextEditingController(text: component['drop_values'] ?? ''),
|
||||
onChanged: (value) {
|
||||
component['drop_values'] = value;
|
||||
},
|
||||
)),
|
||||
DataCell(TextField(
|
||||
controller: TextEditingController(text: component['sp'] ?? ''),
|
||||
onChanged: (value) {
|
||||
component['sp'] = value;
|
||||
},
|
||||
)),
|
||||
],
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
CustomButton(
|
||||
height: getVerticalSize(50),
|
||||
text: "Add Row",
|
||||
margin: getMargin(top: 24, bottom: 5),
|
||||
onTap: () async {
|
||||
components.add({
|
||||
'label': '',
|
||||
'type': '',
|
||||
'mapping': '',
|
||||
'mandatory': '',
|
||||
'readonly': '',
|
||||
'drop_values': '',
|
||||
'sp': '',
|
||||
});
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
|
||||
CustomButton(
|
||||
height: getVerticalSize(50),
|
||||
text: "Create Dynamic Form",
|
||||
margin: getMargin(top: 24, bottom: 5),
|
||||
onTap: () async {
|
||||
final dynamicFormData = {
|
||||
'form_name': formNameController.text,
|
||||
'form_desc': formDescController.text,
|
||||
'related_to': relatedToController.text,
|
||||
'page_event': pageEventController.text,
|
||||
'button_caption': buttonCaptionController.text,
|
||||
'components': components,
|
||||
};
|
||||
final token = await TokenManager.getToken();
|
||||
apiService.createDynamicForm(token!, dynamicFormData);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../Utils/image_constant.dart';
|
||||
import '../../Utils/size_utils.dart';
|
||||
import '../../providers/token_manager.dart';
|
||||
import '../../theme/app_style.dart';
|
||||
import '../../widgets/app_bar/appbar_image.dart';
|
||||
import '../../widgets/app_bar/appbar_title.dart';
|
||||
import '../../widgets/app_bar/custom_app_bar.dart';
|
||||
import '../../widgets/custom_button.dart';
|
||||
import '../../widgets/custom_dropdown_field.dart';
|
||||
import '../../widgets/custom_text_form_field.dart';
|
||||
import 'dynamic_form_service.dart';
|
||||
|
||||
class CreateForm extends StatefulWidget {
|
||||
@override
|
||||
_CreateFormState createState() => _CreateFormState();
|
||||
}
|
||||
|
||||
class _CreateFormState extends State<CreateForm> {
|
||||
TextEditingController formNameController = TextEditingController();
|
||||
TextEditingController formDescController = TextEditingController();
|
||||
TextEditingController relatedToController = TextEditingController();
|
||||
TextEditingController pageEventController = TextEditingController();
|
||||
TextEditingController buttonCaptionController = TextEditingController();
|
||||
|
||||
final DynamicForApiService apiService = DynamicForApiService();
|
||||
|
||||
List<Map<String, dynamic>> components = [];
|
||||
|
||||
List<dynamic> relatedToFixedDropdown = ['Menu', 'Related To',];
|
||||
List<dynamic> pageEventFixedDropdown = ['OnClick', 'OnBlur',];
|
||||
|
||||
List<dynamic> typeFixedDropdown = ['text', 'dropdown','date','checkbox','textarea','togglebutton'];
|
||||
List<dynamic> mappingFixedDropdown = ['TEXTFIELD1', 'TEXTFIELD2','TEXTFIELD3','TEXTFIELD4','TEXTFIELD5','TEXTFIELD6','TEXTFIELD7','TEXTFIELD8','TEXTFIELD9','TEXTFIELD10','TEXTFIELD11','TEXTFIELD12','TEXTFIELD13','TEXTFIELD14','TEXTFIELD15','TEXTFIELD16','TEXTFIELD17','TEXTFIELD18','TEXTFIELD19','TEXTFIELD20','TEXTFIELD21','TEXTFIELD22','TEXTFIELD23',
|
||||
'TEXTFIELD24','TEXTFIELD25','TEXTFIELD26','LONGTEXT1','LONGTEXT2','LONGTEXT3','LONGTEXT4',];
|
||||
List<dynamic> truefalseFixedDropdown = ['true', 'false',];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: CustomAppBar(
|
||||
height: getVerticalSize(49),
|
||||
leadingWidth: 40,
|
||||
leading: AppbarImage(
|
||||
height: getSize(24),
|
||||
width: getSize(24),
|
||||
svgPath: ImageConstant.imgArrowleft,
|
||||
margin: getMargin(left: 16, top: 12, bottom: 13),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
}),
|
||||
centerTitle: true,
|
||||
title: AppbarTitle(text: "Create Dynamic Form"),),
|
||||
body: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text("Form Name",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle
|
||||
.txtGilroyMedium16Bluegray900),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
hintText: "Enter Form Name",
|
||||
controller: formNameController,
|
||||
margin: getMargin(top: 6))
|
||||
])),
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text("Form Description",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle
|
||||
.txtGilroyMedium16Bluegray900),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
hintText: "Enter Form Description",
|
||||
controller: formDescController,
|
||||
margin: getMargin(top: 6))
|
||||
])),
|
||||
|
||||
Padding(
|
||||
padding: getPadding(top: 18),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Select Related To",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroyMedium16Bluegray900,
|
||||
),
|
||||
CustomDropdownFormField(
|
||||
items: [
|
||||
...relatedToFixedDropdown.map<DropdownMenuItem<String>>(
|
||||
(item) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: item.toString(),
|
||||
child: Text(item, style: AppStyle.txtGilroyMedium16Bluegray900),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
relatedToController.text = value!;
|
||||
});
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
Padding(
|
||||
padding: getPadding(top: 18),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Select Page Event",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroyMedium16Bluegray900,
|
||||
),
|
||||
CustomDropdownFormField(
|
||||
items: [
|
||||
...pageEventFixedDropdown.map<DropdownMenuItem<String>>(
|
||||
(item) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: item.toString(),
|
||||
child: Text(item,style: AppStyle.txtGilroyMedium16Bluegray900),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
pageEventController.text = value!;
|
||||
});
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text("Button Caption",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle
|
||||
.txtGilroyMedium16Bluegray900),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
hintText: "Enter Button Caption",
|
||||
controller: buttonCaptionController,
|
||||
margin: getMargin(top: 6))
|
||||
])),
|
||||
const Text('Components Details'),
|
||||
SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: DataTable(
|
||||
columns: const <DataColumn>[
|
||||
DataColumn(label: Text('Label')),
|
||||
DataColumn(label: Text('Type')),
|
||||
DataColumn(label: Text('Mapping')),
|
||||
DataColumn(label: Text('Mandatory')),
|
||||
DataColumn(label: Text('Readonly')),
|
||||
DataColumn(label: Text('Drop Values')),
|
||||
DataColumn(label: Text('SP')),
|
||||
],
|
||||
rows: components.asMap().entries.map((entry) {
|
||||
final index = entry.key;
|
||||
final component = entry.value;
|
||||
bool? isReadonly = false;
|
||||
return DataRow(
|
||||
cells: <DataCell>[
|
||||
DataCell(TextField(
|
||||
controller: TextEditingController(text: component['label'] ?? ''),
|
||||
onChanged: (value) {
|
||||
component['label'] = value;
|
||||
},
|
||||
)),
|
||||
DataCell(
|
||||
DropdownButtonFormField<String>(
|
||||
decoration:
|
||||
const InputDecoration(labelText: 'Select Type'),
|
||||
items: [
|
||||
...typeFixedDropdown.map<DropdownMenuItem<String>>(
|
||||
(item) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: item.toString(),
|
||||
child: Text(item,style: AppStyle.txtGilroyMedium16Bluegray900),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
component['type'] = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
|
||||
),
|
||||
DataCell(
|
||||
DropdownButtonFormField<String>(
|
||||
decoration:
|
||||
const InputDecoration(labelText: 'Select Mapping'),
|
||||
items: [
|
||||
...mappingFixedDropdown.map<DropdownMenuItem<String>>(
|
||||
(item) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: item.toString(),
|
||||
child: Text(item,style: AppStyle.txtGilroyMedium16Bluegray900),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
component['mapping'] = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
|
||||
),
|
||||
DataCell(TextField(
|
||||
controller: TextEditingController(text: component['mandatory'] ?? ''),
|
||||
onChanged: (value) {
|
||||
component['mandatory'] = value;
|
||||
},
|
||||
)),
|
||||
DataCell(
|
||||
DropdownButtonFormField<String>(
|
||||
decoration:
|
||||
const InputDecoration(labelText: 'Select Read Only'),
|
||||
items: [
|
||||
...truefalseFixedDropdown.map<DropdownMenuItem<String>>(
|
||||
(item) {
|
||||
return DropdownMenuItem<String>(
|
||||
value: item.toString(),
|
||||
child: Text(item,style: AppStyle.txtGilroyMedium16Bluegray900),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
component['readonly'] = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
|
||||
),
|
||||
DataCell(TextField(
|
||||
controller: TextEditingController(text: component['drop_values'] ?? ''),
|
||||
onChanged: (value) {
|
||||
component['drop_values'] = value;
|
||||
},
|
||||
)),
|
||||
DataCell(TextField(
|
||||
controller: TextEditingController(text: component['sp'] ?? ''),
|
||||
onChanged: (value) {
|
||||
component['sp'] = value;
|
||||
},
|
||||
)),
|
||||
],
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
CustomButton(
|
||||
height: getVerticalSize(50),
|
||||
text: "Add Row",
|
||||
margin: getMargin(top: 24, bottom: 5),
|
||||
onTap: () async {
|
||||
components.add({
|
||||
'label': '',
|
||||
'type': '',
|
||||
'mapping': '',
|
||||
'mandatory': '',
|
||||
'readonly': '',
|
||||
'drop_values': '',
|
||||
'sp': '',
|
||||
});
|
||||
setState(() {});
|
||||
},
|
||||
),
|
||||
|
||||
CustomButton(
|
||||
height: getVerticalSize(50),
|
||||
text: "Create Dynamic Form",
|
||||
margin: getMargin(top: 24, bottom: 5),
|
||||
onTap: () async {
|
||||
final dynamicFormData = {
|
||||
'form_name': formNameController.text,
|
||||
'form_desc': formDescController.text,
|
||||
'related_to': relatedToController.text,
|
||||
'page_event': pageEventController.text,
|
||||
'button_caption': buttonCaptionController.text,
|
||||
'components': components,
|
||||
};
|
||||
final token = await TokenManager.getToken();
|
||||
apiService.createDynamicForm(token!, dynamicFormData);
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,100 +1,100 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import '../../resources/api_constants.dart';
|
||||
import '../LogoutService/Logoutservice.dart';
|
||||
|
||||
class DynamicForApiService {
|
||||
final String baseUrl = ApiConstants.baseUrl;
|
||||
final Dio dio = Dio();
|
||||
//api/dynamic_form_build
|
||||
Future<void> BuildForms(String token, int id) async {
|
||||
try {
|
||||
dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
final response =
|
||||
await dio.get('$baseUrl/api/dynamic_form_build?form_id=$id');
|
||||
if (response.statusCode == 401) {
|
||||
LogoutService.logout();
|
||||
}
|
||||
if (response.statusCode! <= 209) {
|
||||
Fluttertoast.showToast(
|
||||
msg: 'Build success',
|
||||
backgroundColor: Colors.red,
|
||||
);
|
||||
} else {
|
||||
Fluttertoast.showToast(
|
||||
msg: 'Unable to build',
|
||||
backgroundColor: Colors.red,
|
||||
);
|
||||
throw Exception('Unexpected response type');
|
||||
}
|
||||
} catch (e) {
|
||||
throw Exception('Failed to Build form: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<Map<String, dynamic>>> getallDynamicForms(
|
||||
String token,
|
||||
) async {
|
||||
try {
|
||||
dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
final response = await dio.get('$baseUrl/api/form_setup');
|
||||
if (response.statusCode == 401) {
|
||||
LogoutService.logout();
|
||||
}
|
||||
final responseData = response.data['items'];
|
||||
if (responseData is List) {
|
||||
final entities = responseData.cast<Map<String, dynamic>>();
|
||||
return entities;
|
||||
} else if (responseData is Map<String, dynamic>) {
|
||||
return [responseData];
|
||||
} else {
|
||||
throw Exception('Unexpected response type');
|
||||
}
|
||||
} catch (e) {
|
||||
throw Exception('Failed to get modules by projectId: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> createDynamicForm(
|
||||
String token, Map<String, dynamic> entity) async {
|
||||
try {
|
||||
print("in post api...$entity");
|
||||
dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
var response = await dio.post('$baseUrl/api/form_setup', data: entity);
|
||||
if (response.statusCode == 401) {
|
||||
LogoutService.logout();
|
||||
}
|
||||
print(entity);
|
||||
} catch (e) {
|
||||
throw Exception('Failed to create Dynamic form: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> updateDynamicForm(
|
||||
String token, int entityId, Map<String, dynamic> entity) async {
|
||||
try {
|
||||
dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
var response =
|
||||
await dio.put('$baseUrl/api/form_setup/$entityId', data: entity);
|
||||
if (response.statusCode == 401) {
|
||||
LogoutService.logout();
|
||||
}
|
||||
print(entity);
|
||||
} catch (e) {
|
||||
throw Exception('Failed to update Dynamic form: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> deleteDynamicForm(String token, int entityId) async {
|
||||
try {
|
||||
dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
var response = await dio.delete('$baseUrl/api/form_setup/$entityId');
|
||||
if (response.statusCode == 401) {
|
||||
LogoutService.logout();
|
||||
}
|
||||
} catch (e) {
|
||||
throw Exception('Failed to delete Dynamic form: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import '../../resources/api_constants.dart';
|
||||
import '../LogoutService/Logoutservice.dart';
|
||||
|
||||
class DynamicForApiService {
|
||||
final String baseUrl = ApiConstants.baseUrl;
|
||||
final Dio dio = Dio();
|
||||
//api/dynamic_form_build
|
||||
Future<void> BuildForms(String token, int id) async {
|
||||
try {
|
||||
dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
final response =
|
||||
await dio.get('$baseUrl/api/dynamic_form_build?form_id=$id');
|
||||
if (response.statusCode == 401) {
|
||||
LogoutService.logout();
|
||||
}
|
||||
if (response.statusCode! <= 209) {
|
||||
Fluttertoast.showToast(
|
||||
msg: 'Build success',
|
||||
backgroundColor: Colors.red,
|
||||
);
|
||||
} else {
|
||||
Fluttertoast.showToast(
|
||||
msg: 'Unable to build',
|
||||
backgroundColor: Colors.red,
|
||||
);
|
||||
throw Exception('Unexpected response type');
|
||||
}
|
||||
} catch (e) {
|
||||
throw Exception('Failed to Build form: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<Map<String, dynamic>>> getallDynamicForms(
|
||||
String token,
|
||||
) async {
|
||||
try {
|
||||
dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
final response = await dio.get('$baseUrl/api/form_setup');
|
||||
if (response.statusCode == 401) {
|
||||
LogoutService.logout();
|
||||
}
|
||||
final responseData = response.data['items'];
|
||||
if (responseData is List) {
|
||||
final entities = responseData.cast<Map<String, dynamic>>();
|
||||
return entities;
|
||||
} else if (responseData is Map<String, dynamic>) {
|
||||
return [responseData];
|
||||
} else {
|
||||
throw Exception('Unexpected response type');
|
||||
}
|
||||
} catch (e) {
|
||||
throw Exception('Failed to get modules by projectId: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> createDynamicForm(
|
||||
String token, Map<String, dynamic> entity) async {
|
||||
try {
|
||||
print("in post api...$entity");
|
||||
dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
var response = await dio.post('$baseUrl/api/form_setup', data: entity);
|
||||
if (response.statusCode == 401) {
|
||||
LogoutService.logout();
|
||||
}
|
||||
print(entity);
|
||||
} catch (e) {
|
||||
throw Exception('Failed to create Dynamic form: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> updateDynamicForm(
|
||||
String token, int entityId, Map<String, dynamic> entity) async {
|
||||
try {
|
||||
dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
var response =
|
||||
await dio.put('$baseUrl/api/form_setup/$entityId', data: entity);
|
||||
if (response.statusCode == 401) {
|
||||
LogoutService.logout();
|
||||
}
|
||||
print(entity);
|
||||
} catch (e) {
|
||||
throw Exception('Failed to update Dynamic form: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> deleteDynamicForm(String token, int entityId) async {
|
||||
try {
|
||||
dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
var response = await dio.delete('$baseUrl/api/form_setup/$entityId');
|
||||
if (response.statusCode == 401) {
|
||||
LogoutService.logout();
|
||||
}
|
||||
} catch (e) {
|
||||
throw Exception('Failed to delete Dynamic form: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,224 +1,224 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import '../../Utils/color_constants.dart';
|
||||
import '../../Utils/image_constant.dart';
|
||||
import '../../Utils/size_utils.dart';
|
||||
import '../../providers/token_manager.dart';
|
||||
import '../../widgets/app_bar/appbar_image.dart';
|
||||
import '../../widgets/app_bar/appbar_title.dart';
|
||||
import '../../widgets/app_bar/custom_app_bar.dart';
|
||||
import 'UpdatedynamicForm.dart';
|
||||
import 'create_dynamicform.dart';
|
||||
import 'dynamic_form_service.dart';
|
||||
|
||||
class DynamicForm extends StatefulWidget {
|
||||
@override
|
||||
_DynamicFormState createState() => _DynamicFormState();
|
||||
}
|
||||
|
||||
class _DynamicFormState extends State<DynamicForm> {
|
||||
final DynamicForApiService apiService = DynamicForApiService();
|
||||
|
||||
late List<Map<String, dynamic>> allData = [];
|
||||
|
||||
bool isLoading = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_loadDynamicForms();
|
||||
}
|
||||
|
||||
Future<void> _loadDynamicForms() async {
|
||||
final token = await TokenManager.getToken();
|
||||
try {
|
||||
final alData = await apiService.getallDynamicForms(token!);
|
||||
|
||||
setState(() {
|
||||
allData = alData;
|
||||
|
||||
print('allData fetched...');
|
||||
});
|
||||
isLoading = true;
|
||||
} catch (e) {
|
||||
isLoading = true;
|
||||
print('Failed to load allData: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> deleteEntity(Map<String, dynamic> entity) async {
|
||||
try {
|
||||
final token = await TokenManager.getToken();
|
||||
await apiService.deleteDynamicForm(token!, entity['form_id']);
|
||||
setState(() {
|
||||
allData.remove(entity);
|
||||
});
|
||||
} catch (e) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: const Text('Error'),
|
||||
content: Text('Failed to delete entity: $e'),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: const Text('OK'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: CustomAppBar(
|
||||
height: getVerticalSize(49),
|
||||
leadingWidth: 40,
|
||||
leading: AppbarImage(
|
||||
height: getSize(24),
|
||||
width: getSize(24),
|
||||
svgPath: ImageConstant.imgArrowleftBlueGray900,
|
||||
margin: getMargin(left: 16, top: 12, bottom: 13),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
}),
|
||||
actions: [
|
||||
GestureDetector(
|
||||
child: Icon(
|
||||
Icons.add,
|
||||
color: Colors.black,
|
||||
size: 20,
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => CreateForm(),
|
||||
),
|
||||
).then((value) => {_loadDynamicForms()});
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
width: 20,
|
||||
)
|
||||
],
|
||||
centerTitle: true,
|
||||
title: AppbarTitle(text: "Dynamic Form")),
|
||||
body: isLoading == false
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: allData.isEmpty
|
||||
? const Center(
|
||||
child: Text('No Services available.'),
|
||||
)
|
||||
: Scrollable(
|
||||
viewportBuilder:
|
||||
(BuildContext context, ViewportOffset position) {
|
||||
return SingleChildScrollView(
|
||||
scrollDirection: Axis.vertical,
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: DataTable(
|
||||
columns: [
|
||||
DataColumn(label: Text('Form Name')),
|
||||
DataColumn(label: Text('Form Description')),
|
||||
DataColumn(label: Text('Related To')),
|
||||
DataColumn(label: Text('Page Event')),
|
||||
DataColumn(label: Text('Button Caption')),
|
||||
DataColumn(label: Text('Build')),
|
||||
DataColumn(label: Text('Actions')),
|
||||
],
|
||||
rows: allData.map((module) {
|
||||
return DataRow(
|
||||
cells: [
|
||||
DataCell(
|
||||
Text('${module['form_name'] ?? 'N/A'}')),
|
||||
DataCell(
|
||||
Text('${module['form_desc'] ?? 'N/A'}')),
|
||||
DataCell(
|
||||
Text('${module['related_to'] ?? 'N/A'}')),
|
||||
DataCell(
|
||||
Text('${module['page_event'] ?? 'N/A'}')),
|
||||
DataCell(Text(
|
||||
'${module['button_caption'] ?? 'N/A'}')),
|
||||
DataCell(Row(
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
print(module);
|
||||
final token =
|
||||
await TokenManager.getToken();
|
||||
apiService.BuildForms(
|
||||
token!, module['form_id']);
|
||||
},
|
||||
child: Text("build"),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: ColorConstant.blue700,
|
||||
),
|
||||
)
|
||||
],
|
||||
)),
|
||||
DataCell(Row(
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
EditForm(formData: module),
|
||||
),
|
||||
).then(
|
||||
(value) => {_loadDynamicForms()});
|
||||
},
|
||||
icon: Icon(Icons.edit),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: const Text(
|
||||
'Confirm Deletion'),
|
||||
content: const Text(
|
||||
'Are you sure you want to delete this Module?'),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: const Text('Cancel'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('Delete'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
deleteEntity(module);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
icon: Icon(Icons.delete),
|
||||
),
|
||||
],
|
||||
)),
|
||||
],
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/rendering.dart';
|
||||
import '../../Utils/color_constants.dart';
|
||||
import '../../Utils/image_constant.dart';
|
||||
import '../../Utils/size_utils.dart';
|
||||
import '../../providers/token_manager.dart';
|
||||
import '../../widgets/app_bar/appbar_image.dart';
|
||||
import '../../widgets/app_bar/appbar_title.dart';
|
||||
import '../../widgets/app_bar/custom_app_bar.dart';
|
||||
import 'UpdatedynamicForm.dart';
|
||||
import 'create_dynamicform.dart';
|
||||
import 'dynamic_form_service.dart';
|
||||
|
||||
class DynamicForm extends StatefulWidget {
|
||||
@override
|
||||
_DynamicFormState createState() => _DynamicFormState();
|
||||
}
|
||||
|
||||
class _DynamicFormState extends State<DynamicForm> {
|
||||
final DynamicForApiService apiService = DynamicForApiService();
|
||||
|
||||
late List<Map<String, dynamic>> allData = [];
|
||||
|
||||
bool isLoading = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_loadDynamicForms();
|
||||
}
|
||||
|
||||
Future<void> _loadDynamicForms() async {
|
||||
final token = await TokenManager.getToken();
|
||||
try {
|
||||
final alData = await apiService.getallDynamicForms(token!);
|
||||
|
||||
setState(() {
|
||||
allData = alData;
|
||||
|
||||
print('allData fetched...');
|
||||
});
|
||||
isLoading = true;
|
||||
} catch (e) {
|
||||
isLoading = true;
|
||||
print('Failed to load allData: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> deleteEntity(Map<String, dynamic> entity) async {
|
||||
try {
|
||||
final token = await TokenManager.getToken();
|
||||
await apiService.deleteDynamicForm(token!, entity['form_id']);
|
||||
setState(() {
|
||||
allData.remove(entity);
|
||||
});
|
||||
} catch (e) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: const Text('Error'),
|
||||
content: Text('Failed to delete entity: $e'),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: const Text('OK'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: CustomAppBar(
|
||||
height: getVerticalSize(49),
|
||||
leadingWidth: 40,
|
||||
leading: AppbarImage(
|
||||
height: getSize(24),
|
||||
width: getSize(24),
|
||||
svgPath: ImageConstant.imgArrowleftBlueGray900,
|
||||
margin: getMargin(left: 16, top: 12, bottom: 13),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
}),
|
||||
actions: [
|
||||
GestureDetector(
|
||||
child: Icon(
|
||||
Icons.add,
|
||||
color: Colors.black,
|
||||
size: 20,
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => CreateForm(),
|
||||
),
|
||||
).then((value) => {_loadDynamicForms()});
|
||||
},
|
||||
),
|
||||
const SizedBox(
|
||||
width: 20,
|
||||
)
|
||||
],
|
||||
centerTitle: true,
|
||||
title: AppbarTitle(text: "Dynamic Form")),
|
||||
body: isLoading == false
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: allData.isEmpty
|
||||
? const Center(
|
||||
child: Text('No Services available.'),
|
||||
)
|
||||
: Scrollable(
|
||||
viewportBuilder:
|
||||
(BuildContext context, ViewportOffset position) {
|
||||
return SingleChildScrollView(
|
||||
scrollDirection: Axis.vertical,
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: DataTable(
|
||||
columns: [
|
||||
DataColumn(label: Text('Form Name')),
|
||||
DataColumn(label: Text('Form Description')),
|
||||
DataColumn(label: Text('Related To')),
|
||||
DataColumn(label: Text('Page Event')),
|
||||
DataColumn(label: Text('Button Caption')),
|
||||
DataColumn(label: Text('Build')),
|
||||
DataColumn(label: Text('Actions')),
|
||||
],
|
||||
rows: allData.map((module) {
|
||||
return DataRow(
|
||||
cells: [
|
||||
DataCell(
|
||||
Text('${module['form_name'] ?? 'N/A'}')),
|
||||
DataCell(
|
||||
Text('${module['form_desc'] ?? 'N/A'}')),
|
||||
DataCell(
|
||||
Text('${module['related_to'] ?? 'N/A'}')),
|
||||
DataCell(
|
||||
Text('${module['page_event'] ?? 'N/A'}')),
|
||||
DataCell(Text(
|
||||
'${module['button_caption'] ?? 'N/A'}')),
|
||||
DataCell(Row(
|
||||
children: [
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
print(module);
|
||||
final token =
|
||||
await TokenManager.getToken();
|
||||
apiService.BuildForms(
|
||||
token!, module['form_id']);
|
||||
},
|
||||
child: Text("build"),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: ColorConstant.blue700,
|
||||
),
|
||||
)
|
||||
],
|
||||
)),
|
||||
DataCell(Row(
|
||||
children: [
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
EditForm(formData: module),
|
||||
),
|
||||
).then(
|
||||
(value) => {_loadDynamicForms()});
|
||||
},
|
||||
icon: Icon(Icons.edit),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: const Text(
|
||||
'Confirm Deletion'),
|
||||
content: const Text(
|
||||
'Are you sure you want to delete this Module?'),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: const Text('Cancel'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('Delete'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
deleteEntity(module);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
icon: Icon(Icons.delete),
|
||||
),
|
||||
],
|
||||
)),
|
||||
],
|
||||
);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,130 +1,130 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import '../../Utils/color_constants.dart';
|
||||
import '../../Utils/image_constant.dart';
|
||||
import '../../Utils/size_utils.dart';
|
||||
import '../../providers/token_manager.dart';
|
||||
import '../../resources/api_constants.dart';
|
||||
import '../../theme/app_style.dart';
|
||||
import '../../widgets/app_bar/appbar_image.dart';
|
||||
import '../../widgets/app_bar/appbar_title.dart';
|
||||
import '../../widgets/app_bar/custom_app_bar.dart';
|
||||
import '../../widgets/custom_button.dart';
|
||||
import '../../widgets/custom_text_form_field.dart';
|
||||
import '../Login Screen/login_screen.dart';
|
||||
|
||||
class ForgotPasswordPage extends StatefulWidget {
|
||||
@override
|
||||
_ForgotPasswordPageState createState() => _ForgotPasswordPageState();
|
||||
}
|
||||
|
||||
class _ForgotPasswordPageState extends State<ForgotPasswordPage> {
|
||||
final TextEditingController emailController = TextEditingController();
|
||||
String message = '';
|
||||
bool isLoading = false; // Added to track loading state
|
||||
|
||||
Future<void> sendForgotPasswordRequest() async {
|
||||
setState(() {
|
||||
isLoading = true; // Show loading indicator when sending request
|
||||
});
|
||||
|
||||
final email = emailController.text;
|
||||
final token = await TokenManager.getToken();
|
||||
const String baseUrl = ApiConstants.baseUrl;
|
||||
|
||||
final response = await http.post(
|
||||
headers: {
|
||||
'Authorization': 'Bearer $token',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
Uri.parse('$baseUrl/api/resources/forgotpassword?email=$email'),
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
setState(() {
|
||||
message = 'An email with a reset link has been sent to $email.';
|
||||
});
|
||||
|
||||
// Delay for 3 seconds and then navigate to the login page
|
||||
Future.delayed(Duration(seconds: 3), () {
|
||||
Navigator.push(
|
||||
context, MaterialPageRoute(builder: (context) => LoginScreen()));
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
message = 'Failed to send the reset link. Please try again.';
|
||||
});
|
||||
}
|
||||
|
||||
setState(() {
|
||||
isLoading = false; // Hide loading indicator when the request is complete
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: CustomAppBar(
|
||||
height: getVerticalSize(49),
|
||||
leadingWidth: 40,
|
||||
leading: AppbarImage(
|
||||
height: getSize(24),
|
||||
width: getSize(24),
|
||||
svgPath: ImageConstant.imgArrowleftBlueGray900,
|
||||
margin: getMargin(left: 16, top: 12, bottom: 13),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
}),
|
||||
centerTitle: true,
|
||||
title: AppbarTitle(text: "Forgot Password")),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text("Email",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroyMedium16Bluegray900),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
hintText: "Enter Email",
|
||||
controller: emailController,
|
||||
margin: getMargin(top: 6))
|
||||
])),
|
||||
CustomButton(
|
||||
height: getVerticalSize(50),
|
||||
text: "Send me an access link",
|
||||
margin: getMargin(top: 24, bottom: 5),
|
||||
onTap: () async {
|
||||
sendForgotPasswordRequest();
|
||||
},
|
||||
),
|
||||
isLoading
|
||||
? CircularProgressIndicator(
|
||||
color: ColorConstant.blue700,
|
||||
) // Show loading indicator when isLoading is true
|
||||
: Text(message, style: AppStyle.txtGilroyMedium16Bluegray900),
|
||||
if (message.contains('An email with a reset link'))
|
||||
InkWell(
|
||||
child: Text('Click here to return to login',
|
||||
style: AppStyle.txtGilroyMedium16Bluegray900),
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const LoginScreen()));
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import '../../Utils/color_constants.dart';
|
||||
import '../../Utils/image_constant.dart';
|
||||
import '../../Utils/size_utils.dart';
|
||||
import '../../providers/token_manager.dart';
|
||||
import '../../resources/api_constants.dart';
|
||||
import '../../theme/app_style.dart';
|
||||
import '../../widgets/app_bar/appbar_image.dart';
|
||||
import '../../widgets/app_bar/appbar_title.dart';
|
||||
import '../../widgets/app_bar/custom_app_bar.dart';
|
||||
import '../../widgets/custom_button.dart';
|
||||
import '../../widgets/custom_text_form_field.dart';
|
||||
import '../Login Screen/login_screen.dart';
|
||||
|
||||
class ForgotPasswordPage extends StatefulWidget {
|
||||
@override
|
||||
_ForgotPasswordPageState createState() => _ForgotPasswordPageState();
|
||||
}
|
||||
|
||||
class _ForgotPasswordPageState extends State<ForgotPasswordPage> {
|
||||
final TextEditingController emailController = TextEditingController();
|
||||
String message = '';
|
||||
bool isLoading = false; // Added to track loading state
|
||||
|
||||
Future<void> sendForgotPasswordRequest() async {
|
||||
setState(() {
|
||||
isLoading = true; // Show loading indicator when sending request
|
||||
});
|
||||
|
||||
final email = emailController.text;
|
||||
final token = await TokenManager.getToken();
|
||||
const String baseUrl = ApiConstants.baseUrl;
|
||||
|
||||
final response = await http.post(
|
||||
headers: {
|
||||
'Authorization': 'Bearer $token',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
Uri.parse('$baseUrl/api/resources/forgotpassword?email=$email'),
|
||||
);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
setState(() {
|
||||
message = 'An email with a reset link has been sent to $email.';
|
||||
});
|
||||
|
||||
// Delay for 3 seconds and then navigate to the login page
|
||||
Future.delayed(Duration(seconds: 3), () {
|
||||
Navigator.push(
|
||||
context, MaterialPageRoute(builder: (context) => LoginScreen()));
|
||||
});
|
||||
} else {
|
||||
setState(() {
|
||||
message = 'Failed to send the reset link. Please try again.';
|
||||
});
|
||||
}
|
||||
|
||||
setState(() {
|
||||
isLoading = false; // Hide loading indicator when the request is complete
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: CustomAppBar(
|
||||
height: getVerticalSize(49),
|
||||
leadingWidth: 40,
|
||||
leading: AppbarImage(
|
||||
height: getSize(24),
|
||||
width: getSize(24),
|
||||
svgPath: ImageConstant.imgArrowleftBlueGray900,
|
||||
margin: getMargin(left: 16, top: 12, bottom: 13),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
}),
|
||||
centerTitle: true,
|
||||
title: AppbarTitle(text: "Forgot Password")),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text("Email",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroyMedium16Bluegray900),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
hintText: "Enter Email",
|
||||
controller: emailController,
|
||||
margin: getMargin(top: 6))
|
||||
])),
|
||||
CustomButton(
|
||||
height: getVerticalSize(50),
|
||||
text: "Send me an access link",
|
||||
margin: getMargin(top: 24, bottom: 5),
|
||||
onTap: () async {
|
||||
sendForgotPasswordRequest();
|
||||
},
|
||||
),
|
||||
isLoading
|
||||
? CircularProgressIndicator(
|
||||
color: ColorConstant.blue700,
|
||||
) // Show loading indicator when isLoading is true
|
||||
: Text(message, style: AppStyle.txtGilroyMedium16Bluegray900),
|
||||
if (message.contains('An email with a reset link'))
|
||||
InkWell(
|
||||
child: Text('Click here to return to login',
|
||||
style: AppStyle.txtGilroyMedium16Bluegray900),
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const LoginScreen()));
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,54 +1,54 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class CustomizedFooter extends StatelessWidget {
|
||||
final IconData homeIcon;
|
||||
final IconData squareIcon;
|
||||
final IconData addIcon;
|
||||
final List<String> labels;
|
||||
final List<Function()> onTapActions;
|
||||
|
||||
CustomizedFooter({
|
||||
required this.homeIcon,
|
||||
required this.squareIcon,
|
||||
required this.addIcon,
|
||||
required this.labels,
|
||||
required this.onTapActions,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
assert(labels.length == 3 && onTapActions.length == 3);
|
||||
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.grey.withOpacity(0.5),
|
||||
spreadRadius: 5,
|
||||
blurRadius: 7,
|
||||
offset: const Offset(0, 3),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: BottomNavigationBar(
|
||||
onTap: (index) {
|
||||
onTapActions[index]();
|
||||
},
|
||||
items: [
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(homeIcon),
|
||||
label: labels[0],
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(squareIcon),
|
||||
label: labels[1],
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(addIcon),
|
||||
label: labels[2],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class CustomizedFooter extends StatelessWidget {
|
||||
final IconData homeIcon;
|
||||
final IconData squareIcon;
|
||||
final IconData addIcon;
|
||||
final List<String> labels;
|
||||
final List<Function()> onTapActions;
|
||||
|
||||
CustomizedFooter({
|
||||
required this.homeIcon,
|
||||
required this.squareIcon,
|
||||
required this.addIcon,
|
||||
required this.labels,
|
||||
required this.onTapActions,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
assert(labels.length == 3 && onTapActions.length == 3);
|
||||
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
boxShadow: [
|
||||
BoxShadow(
|
||||
color: Colors.grey.withOpacity(0.5),
|
||||
spreadRadius: 5,
|
||||
blurRadius: 7,
|
||||
offset: const Offset(0, 3),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: BottomNavigationBar(
|
||||
onTap: (index) {
|
||||
onTapActions[index]();
|
||||
},
|
||||
items: [
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(homeIcon),
|
||||
label: labels[0],
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(squareIcon),
|
||||
label: labels[1],
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(addIcon),
|
||||
label: labels[2],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,339 +1,339 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg_provider/flutter_svg_provider.dart' as fs;
|
||||
import '../../Utils/color_constants.dart';
|
||||
import '../../Utils/image_constant.dart';
|
||||
import '../../Utils/size_utils.dart';
|
||||
import '../../providers/token_manager.dart';
|
||||
import '../../resources/api_constants.dart';
|
||||
import '../../theme/app_style.dart';
|
||||
import '../LogoutService/Logoutservice.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
class Listgroup524ItemWidget extends StatefulWidget {
|
||||
final Map<String, dynamic> userData;
|
||||
Listgroup524ItemWidget({required this.userData});
|
||||
|
||||
@override
|
||||
State<Listgroup524ItemWidget> createState() => _Listgroup524ItemWidgetState();
|
||||
}
|
||||
|
||||
class _Listgroup524ItemWidgetState extends State<Listgroup524ItemWidget> {
|
||||
int myProjectcount = 0;
|
||||
int sharedWithMeCount = 0;
|
||||
int allprojectCount = 0;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
fetchData();
|
||||
}
|
||||
|
||||
Future<void> fetchData() async {
|
||||
print("working");
|
||||
final token = await TokenManager.getToken();
|
||||
print(token);
|
||||
String baseUrl = ApiConstants.baseUrl;
|
||||
var myProjectcountres = await http.get(
|
||||
Uri.parse('$baseUrl/workspace/secworkspaceuser/count_myproject'),
|
||||
headers: {
|
||||
'Authorization': 'Bearer $token',
|
||||
'Content-Type':
|
||||
'application/json', // You may need to adjust the content type as needed
|
||||
},
|
||||
);
|
||||
var sharedWithMeCountres = await http.get(
|
||||
Uri.parse('$baseUrl/workspace/secworkspaceuser/count_sharedwithme'),
|
||||
headers: {
|
||||
'Authorization': 'Bearer $token',
|
||||
'Content-Type':
|
||||
'application/json', // You may need to adjust the content type as needed
|
||||
},
|
||||
);
|
||||
var allProjectsCountres = await http.get(
|
||||
Uri.parse('$baseUrl/workspace/secworkspaceuser/count_allproject'),
|
||||
headers: {
|
||||
'Authorization': 'Bearer $token',
|
||||
'Content-Type':
|
||||
'application/json', // You may need to adjust the content type as needed
|
||||
},
|
||||
);
|
||||
if (myProjectcountres.statusCode == 401) {
|
||||
LogoutService.logout();
|
||||
}
|
||||
print(myProjectcountres.statusCode);
|
||||
if (myProjectcountres.statusCode <= 209 &&
|
||||
sharedWithMeCountres.statusCode <= 209) {
|
||||
final myProjectData = jsonDecode(myProjectcountres.body);
|
||||
final sharedData = jsonDecode(sharedWithMeCountres.body);
|
||||
final allData = jsonDecode(allProjectsCountres.body);
|
||||
setState(() {
|
||||
myProjectcount = myProjectData;
|
||||
sharedWithMeCount = sharedData;
|
||||
allprojectCount = allData;
|
||||
});
|
||||
} else {
|
||||
// Handle errors
|
||||
print('Failed to fetch data');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: Container(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
// Navigator.push(
|
||||
// context,
|
||||
// MaterialPageRoute(
|
||||
// builder: (context) => ProjectListScreen(
|
||||
// userData: widget.userData,
|
||||
// type: "myproject"), // Get all projects
|
||||
// ),
|
||||
// );
|
||||
},
|
||||
child: Card(
|
||||
color: Colors.white,
|
||||
elevation: 0.0,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(20, 10, 20, 10),
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
height: getSize(
|
||||
55,
|
||||
),
|
||||
width: getSize(
|
||||
55,
|
||||
),
|
||||
margin: getMargin(
|
||||
top: 2,
|
||||
),
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: Container(
|
||||
height: getSize(
|
||||
55,
|
||||
),
|
||||
width: getSize(
|
||||
55,
|
||||
),
|
||||
child: CircularProgressIndicator(
|
||||
value: 0.5,
|
||||
backgroundColor: ColorConstant.gray30099,
|
||||
color: ColorConstant.blueA700,
|
||||
),
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
myProjectcount.toString(),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroyBold18,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// Text(
|
||||
// myProjectcount.toString(),
|
||||
// style: const TextStyle(
|
||||
// color: Colors.black,
|
||||
// fontSize: 12,
|
||||
// ),
|
||||
// ),
|
||||
const SizedBox(
|
||||
height: 3,
|
||||
),
|
||||
const Text(
|
||||
'My Projects',
|
||||
style: TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 10,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
// Navigator.push(
|
||||
// context,
|
||||
// MaterialPageRoute(
|
||||
// builder: (context) => ProjectListScreen(
|
||||
// userData: widget.userData,
|
||||
// type: "sharedproject"), // Get all projects
|
||||
// ),
|
||||
// );
|
||||
},
|
||||
child: Card(
|
||||
color: Colors.white,
|
||||
elevation: 0.0,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(20, 10, 20, 10),
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
height: getSize(
|
||||
55,
|
||||
),
|
||||
width: getSize(
|
||||
55,
|
||||
),
|
||||
margin: getMargin(
|
||||
top: 2,
|
||||
),
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: Container(
|
||||
height: getSize(
|
||||
55,
|
||||
),
|
||||
width: getSize(
|
||||
55,
|
||||
),
|
||||
child: CircularProgressIndicator(
|
||||
value: 0.5,
|
||||
backgroundColor: ColorConstant.gray30099,
|
||||
color: ColorConstant.blueA700,
|
||||
),
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
sharedWithMeCount.toString(),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroyBold18,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// Text(
|
||||
// myProjectcount.toString(),
|
||||
// style: const TextStyle(
|
||||
// color: Colors.black,
|
||||
// fontSize: 12,
|
||||
// ),
|
||||
// ),
|
||||
const SizedBox(
|
||||
height: 3,
|
||||
),
|
||||
const Text(
|
||||
'Shared with me',
|
||||
style: TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 10,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
// Navigator.push(
|
||||
// context,
|
||||
// MaterialPageRoute(
|
||||
// builder: (context) => ProjectListScreen(
|
||||
// userData: widget.userData,
|
||||
// type: "allproject"), // Get all projects
|
||||
// ),
|
||||
// );
|
||||
},
|
||||
child: Card(
|
||||
color: Colors.white,
|
||||
elevation: 0.0,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(20, 10, 20, 10),
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
height: getSize(
|
||||
55,
|
||||
),
|
||||
width: getSize(
|
||||
55,
|
||||
),
|
||||
margin: getMargin(
|
||||
top: 2,
|
||||
),
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: Container(
|
||||
height: getSize(
|
||||
55,
|
||||
),
|
||||
width: getSize(
|
||||
55,
|
||||
),
|
||||
child: CircularProgressIndicator(
|
||||
value: 0.5,
|
||||
backgroundColor: ColorConstant.gray30099,
|
||||
color: ColorConstant.blueA700,
|
||||
),
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
allprojectCount.toString(),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroyBold18,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// Text(
|
||||
// myProjectcount.toString(),
|
||||
// style: const TextStyle(
|
||||
// color: Colors.black,
|
||||
// fontSize: 12,
|
||||
// ),
|
||||
// ),
|
||||
const SizedBox(
|
||||
height: 3,
|
||||
),
|
||||
const Text(
|
||||
'All Projects',
|
||||
style: TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 10,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg_provider/flutter_svg_provider.dart' as fs;
|
||||
import '../../Utils/color_constants.dart';
|
||||
import '../../Utils/image_constant.dart';
|
||||
import '../../Utils/size_utils.dart';
|
||||
import '../../providers/token_manager.dart';
|
||||
import '../../resources/api_constants.dart';
|
||||
import '../../theme/app_style.dart';
|
||||
import '../LogoutService/Logoutservice.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
class Listgroup524ItemWidget extends StatefulWidget {
|
||||
final Map<String, dynamic> userData;
|
||||
Listgroup524ItemWidget({required this.userData});
|
||||
|
||||
@override
|
||||
State<Listgroup524ItemWidget> createState() => _Listgroup524ItemWidgetState();
|
||||
}
|
||||
|
||||
class _Listgroup524ItemWidgetState extends State<Listgroup524ItemWidget> {
|
||||
int myProjectcount = 0;
|
||||
int sharedWithMeCount = 0;
|
||||
int allprojectCount = 0;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
fetchData();
|
||||
}
|
||||
|
||||
Future<void> fetchData() async {
|
||||
print("working");
|
||||
final token = await TokenManager.getToken();
|
||||
print(token);
|
||||
String baseUrl = ApiConstants.baseUrl;
|
||||
var myProjectcountres = await http.get(
|
||||
Uri.parse('$baseUrl/workspace/secworkspaceuser/count_myproject'),
|
||||
headers: {
|
||||
'Authorization': 'Bearer $token',
|
||||
'Content-Type':
|
||||
'application/json', // You may need to adjust the content type as needed
|
||||
},
|
||||
);
|
||||
var sharedWithMeCountres = await http.get(
|
||||
Uri.parse('$baseUrl/workspace/secworkspaceuser/count_sharedwithme'),
|
||||
headers: {
|
||||
'Authorization': 'Bearer $token',
|
||||
'Content-Type':
|
||||
'application/json', // You may need to adjust the content type as needed
|
||||
},
|
||||
);
|
||||
var allProjectsCountres = await http.get(
|
||||
Uri.parse('$baseUrl/workspace/secworkspaceuser/count_allproject'),
|
||||
headers: {
|
||||
'Authorization': 'Bearer $token',
|
||||
'Content-Type':
|
||||
'application/json', // You may need to adjust the content type as needed
|
||||
},
|
||||
);
|
||||
if (myProjectcountres.statusCode == 401) {
|
||||
LogoutService.logout();
|
||||
}
|
||||
print(myProjectcountres.statusCode);
|
||||
if (myProjectcountres.statusCode <= 209 &&
|
||||
sharedWithMeCountres.statusCode <= 209) {
|
||||
final myProjectData = jsonDecode(myProjectcountres.body);
|
||||
final sharedData = jsonDecode(sharedWithMeCountres.body);
|
||||
final allData = jsonDecode(allProjectsCountres.body);
|
||||
setState(() {
|
||||
myProjectcount = myProjectData;
|
||||
sharedWithMeCount = sharedData;
|
||||
allprojectCount = allData;
|
||||
});
|
||||
} else {
|
||||
// Handle errors
|
||||
print('Failed to fetch data');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Center(
|
||||
child: Container(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
// Navigator.push(
|
||||
// context,
|
||||
// MaterialPageRoute(
|
||||
// builder: (context) => ProjectListScreen(
|
||||
// userData: widget.userData,
|
||||
// type: "myproject"), // Get all projects
|
||||
// ),
|
||||
// );
|
||||
},
|
||||
child: Card(
|
||||
color: Colors.white,
|
||||
elevation: 0.0,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(20, 10, 20, 10),
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
height: getSize(
|
||||
55,
|
||||
),
|
||||
width: getSize(
|
||||
55,
|
||||
),
|
||||
margin: getMargin(
|
||||
top: 2,
|
||||
),
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: Container(
|
||||
height: getSize(
|
||||
55,
|
||||
),
|
||||
width: getSize(
|
||||
55,
|
||||
),
|
||||
child: CircularProgressIndicator(
|
||||
value: 0.5,
|
||||
backgroundColor: ColorConstant.gray30099,
|
||||
color: ColorConstant.blueA700,
|
||||
),
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
myProjectcount.toString(),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroyBold18,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// Text(
|
||||
// myProjectcount.toString(),
|
||||
// style: const TextStyle(
|
||||
// color: Colors.black,
|
||||
// fontSize: 12,
|
||||
// ),
|
||||
// ),
|
||||
const SizedBox(
|
||||
height: 3,
|
||||
),
|
||||
const Text(
|
||||
'My Projects',
|
||||
style: TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 10,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
// Navigator.push(
|
||||
// context,
|
||||
// MaterialPageRoute(
|
||||
// builder: (context) => ProjectListScreen(
|
||||
// userData: widget.userData,
|
||||
// type: "sharedproject"), // Get all projects
|
||||
// ),
|
||||
// );
|
||||
},
|
||||
child: Card(
|
||||
color: Colors.white,
|
||||
elevation: 0.0,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(20, 10, 20, 10),
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
height: getSize(
|
||||
55,
|
||||
),
|
||||
width: getSize(
|
||||
55,
|
||||
),
|
||||
margin: getMargin(
|
||||
top: 2,
|
||||
),
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: Container(
|
||||
height: getSize(
|
||||
55,
|
||||
),
|
||||
width: getSize(
|
||||
55,
|
||||
),
|
||||
child: CircularProgressIndicator(
|
||||
value: 0.5,
|
||||
backgroundColor: ColorConstant.gray30099,
|
||||
color: ColorConstant.blueA700,
|
||||
),
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
sharedWithMeCount.toString(),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroyBold18,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// Text(
|
||||
// myProjectcount.toString(),
|
||||
// style: const TextStyle(
|
||||
// color: Colors.black,
|
||||
// fontSize: 12,
|
||||
// ),
|
||||
// ),
|
||||
const SizedBox(
|
||||
height: 3,
|
||||
),
|
||||
const Text(
|
||||
'Shared with me',
|
||||
style: TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 10,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
// Navigator.push(
|
||||
// context,
|
||||
// MaterialPageRoute(
|
||||
// builder: (context) => ProjectListScreen(
|
||||
// userData: widget.userData,
|
||||
// type: "allproject"), // Get all projects
|
||||
// ),
|
||||
// );
|
||||
},
|
||||
child: Card(
|
||||
color: Colors.white,
|
||||
elevation: 0.0,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(20, 10, 20, 10),
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
height: getSize(
|
||||
55,
|
||||
),
|
||||
width: getSize(
|
||||
55,
|
||||
),
|
||||
margin: getMargin(
|
||||
top: 2,
|
||||
),
|
||||
child: Stack(
|
||||
alignment: Alignment.center,
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: Container(
|
||||
height: getSize(
|
||||
55,
|
||||
),
|
||||
width: getSize(
|
||||
55,
|
||||
),
|
||||
child: CircularProgressIndicator(
|
||||
value: 0.5,
|
||||
backgroundColor: ColorConstant.gray30099,
|
||||
color: ColorConstant.blueA700,
|
||||
),
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
allprojectCount.toString(),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroyBold18,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
// Text(
|
||||
// myProjectcount.toString(),
|
||||
// style: const TextStyle(
|
||||
// color: Colors.black,
|
||||
// fontSize: 12,
|
||||
// ),
|
||||
// ),
|
||||
const SizedBox(
|
||||
height: 3,
|
||||
),
|
||||
const Text(
|
||||
'All Projects',
|
||||
style: TextStyle(
|
||||
color: Colors.black,
|
||||
fontSize: 10,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,54 +1,54 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../Utils/size_utils.dart';
|
||||
import '../../theme/app_style.dart';
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class ListtextItemWidget extends StatelessWidget {
|
||||
ListtextItemWidget();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Lorem ipsum",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroySemiBold16,
|
||||
),
|
||||
Padding(
|
||||
padding: getPadding(
|
||||
top: 10,
|
||||
),
|
||||
child: Text(
|
||||
"Lorem ipsum",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroyRegular14,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: getPadding(
|
||||
top: 11,
|
||||
bottom: 13,
|
||||
),
|
||||
child: Text(
|
||||
"7.5",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroySemiBold18,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../Utils/size_utils.dart';
|
||||
import '../../theme/app_style.dart';
|
||||
|
||||
// ignore: must_be_immutable
|
||||
class ListtextItemWidget extends StatelessWidget {
|
||||
ListtextItemWidget();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"Lorem ipsum",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroySemiBold16,
|
||||
),
|
||||
Padding(
|
||||
padding: getPadding(
|
||||
top: 10,
|
||||
),
|
||||
child: Text(
|
||||
"Lorem ipsum",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroyRegular14,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: getPadding(
|
||||
top: 11,
|
||||
bottom: 13,
|
||||
),
|
||||
child: Text(
|
||||
"7.5",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroySemiBold18,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,21 +1,21 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class LocalSplashScreenComponent extends StatelessWidget {
|
||||
const LocalSplashScreenComponent({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
color: Color(0xff2f73b9),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/images/hadwin_system/hadwin-splash-screen-logo.png',
|
||||
height: 128.0,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class LocalSplashScreenComponent extends StatelessWidget {
|
||||
const LocalSplashScreenComponent({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
color: Color(0xff2f73b9),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Image.asset(
|
||||
'assets/images/hadwin_system/hadwin-splash-screen-logo.png',
|
||||
height: 128.0,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,88 +1,88 @@
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../Utils/size_utils.dart';
|
||||
import '../../theme/app_style.dart';
|
||||
|
||||
class NotificationItem extends StatelessWidget {
|
||||
final Map<String, dynamic> notification;
|
||||
|
||||
const NotificationItem({required this.notification});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final notificationText = notification['notification'] as String;
|
||||
final time = notification['time'] as String;
|
||||
final timeDifference = calculateTimeDifference(time);
|
||||
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
// Text(
|
||||
// notificationText,
|
||||
// overflow: TextOverflow.ellipsis,
|
||||
// textAlign: TextAlign.left,
|
||||
// style: AppStyle.txtGilroySemiBold16,
|
||||
// ),
|
||||
Padding(
|
||||
padding: getPadding(
|
||||
top: 10,
|
||||
),
|
||||
child: Text(
|
||||
notificationText,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroyRegular14,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: getPadding(
|
||||
top: 11,
|
||||
bottom: 13,
|
||||
),
|
||||
child: Text(
|
||||
timeDifference,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroySemiBold18,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
|
||||
ListTile(
|
||||
title: Text(notificationText),
|
||||
subtitle: Text(timeDifference),
|
||||
);
|
||||
}
|
||||
|
||||
String calculateTimeDifference(String time) {
|
||||
final currentTime = DateTime.now();
|
||||
final notificationTime = DateTime.parse(time);
|
||||
|
||||
final difference = currentTime.difference(notificationTime);
|
||||
|
||||
if (difference.inDays >= 365) {
|
||||
final years = (difference.inDays / 365).floor();
|
||||
return '${years} ${years == 1 ? 'year' : 'years'} ago';
|
||||
} else if (difference.inDays >= 30) {
|
||||
final months = (difference.inDays / 30).floor();
|
||||
return '${months} ${months == 1 ? 'month' : 'months'} ago';
|
||||
} else if (difference.inDays > 0) {
|
||||
return '${difference.inDays} ${difference.inDays == 1 ? 'day' : 'days'} ago';
|
||||
} else if (difference.inHours > 0) {
|
||||
return '${difference.inHours} ${difference.inHours == 1 ? 'hour' : 'hours'} ago';
|
||||
} else {
|
||||
return 'Just now';
|
||||
}
|
||||
}
|
||||
}
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../Utils/size_utils.dart';
|
||||
import '../../theme/app_style.dart';
|
||||
|
||||
class NotificationItem extends StatelessWidget {
|
||||
final Map<String, dynamic> notification;
|
||||
|
||||
const NotificationItem({required this.notification});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final notificationText = notification['notification'] as String;
|
||||
final time = notification['time'] as String;
|
||||
final timeDifference = calculateTimeDifference(time);
|
||||
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
// Text(
|
||||
// notificationText,
|
||||
// overflow: TextOverflow.ellipsis,
|
||||
// textAlign: TextAlign.left,
|
||||
// style: AppStyle.txtGilroySemiBold16,
|
||||
// ),
|
||||
Padding(
|
||||
padding: getPadding(
|
||||
top: 10,
|
||||
),
|
||||
child: Text(
|
||||
notificationText,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroyRegular14,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: getPadding(
|
||||
top: 11,
|
||||
bottom: 13,
|
||||
),
|
||||
child: Text(
|
||||
timeDifference,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroySemiBold18,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
|
||||
|
||||
ListTile(
|
||||
title: Text(notificationText),
|
||||
subtitle: Text(timeDifference),
|
||||
);
|
||||
}
|
||||
|
||||
String calculateTimeDifference(String time) {
|
||||
final currentTime = DateTime.now();
|
||||
final notificationTime = DateTime.parse(time);
|
||||
|
||||
final difference = currentTime.difference(notificationTime);
|
||||
|
||||
if (difference.inDays >= 365) {
|
||||
final years = (difference.inDays / 365).floor();
|
||||
return '${years} ${years == 1 ? 'year' : 'years'} ago';
|
||||
} else if (difference.inDays >= 30) {
|
||||
final months = (difference.inDays / 30).floor();
|
||||
return '${months} ${months == 1 ? 'month' : 'months'} ago';
|
||||
} else if (difference.inDays > 0) {
|
||||
return '${difference.inDays} ${difference.inDays == 1 ? 'day' : 'days'} ago';
|
||||
} else if (difference.inHours > 0) {
|
||||
return '${difference.inHours} ${difference.inHours == 1 ? 'hour' : 'hours'} ago';
|
||||
} else {
|
||||
return 'Just now';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,46 +1,46 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../Utils/image_constant.dart';
|
||||
import '../../Utils/size_utils.dart';
|
||||
import '../../theme/app_style.dart';
|
||||
import '../../widgets/app_bar/appbar_image.dart';
|
||||
import '../../widgets/app_bar/appbar_title.dart';
|
||||
import '../../widgets/app_bar/custom_app_bar.dart';
|
||||
|
||||
class AboutScreen extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: CustomAppBar(
|
||||
height: getVerticalSize(49),
|
||||
leadingWidth: 40,
|
||||
leading: AppbarImage(
|
||||
height: getSize(24),
|
||||
width: getSize(24),
|
||||
svgPath: ImageConstant.imgArrowleftBlueGray900,
|
||||
margin: getMargin(left: 16, top: 12, bottom: 13),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
}),
|
||||
centerTitle: true,
|
||||
title: AppbarTitle(text: "About Us")),
|
||||
body: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
'About Us',
|
||||
style: AppStyle.txtGilroyBold18Bluegray900,
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Text(
|
||||
'Create a new project if you have access, if you don\'t have access, then contact the admin.',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppStyle.txtGilroyBold16BlueA700,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../Utils/image_constant.dart';
|
||||
import '../../Utils/size_utils.dart';
|
||||
import '../../theme/app_style.dart';
|
||||
import '../../widgets/app_bar/appbar_image.dart';
|
||||
import '../../widgets/app_bar/appbar_title.dart';
|
||||
import '../../widgets/app_bar/custom_app_bar.dart';
|
||||
|
||||
class AboutScreen extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: CustomAppBar(
|
||||
height: getVerticalSize(49),
|
||||
leadingWidth: 40,
|
||||
leading: AppbarImage(
|
||||
height: getSize(24),
|
||||
width: getSize(24),
|
||||
svgPath: ImageConstant.imgArrowleftBlueGray900,
|
||||
margin: getMargin(left: 16, top: 12, bottom: 13),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
}),
|
||||
centerTitle: true,
|
||||
title: AppbarTitle(text: "About Us")),
|
||||
body: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
'About Us',
|
||||
style: AppStyle.txtGilroyBold18Bluegray900,
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
Text(
|
||||
'Create a new project if you have access, if you don\'t have access, then contact the admin.',
|
||||
textAlign: TextAlign.center,
|
||||
style: AppStyle.txtGilroyBold16BlueA700,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,57 +1,57 @@
|
||||
import 'dart:typed_data';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:http_parser/http_parser.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import '../../resources/api_constants.dart';
|
||||
|
||||
class ApiServiceProfileManagement {
|
||||
final String baseUrl = ApiConstants.baseUrl;
|
||||
final Dio dio = Dio();
|
||||
|
||||
Future<void> createFile(
|
||||
Uint8List fileBytes, String fileName, String token) async {
|
||||
try {
|
||||
String apiUrl = "$baseUrl/api/upload";
|
||||
|
||||
final mimeType = 'image/jpeg'; // You can set the appropriate MIME type
|
||||
|
||||
FormData formData = FormData.fromMap({
|
||||
'imageFile': MultipartFile.fromBytes(
|
||||
fileBytes,
|
||||
filename: fileName,
|
||||
contentType: MediaType.parse(mimeType),
|
||||
),
|
||||
});
|
||||
|
||||
Dio dio = Dio(); // Create a new Dio instance
|
||||
dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
|
||||
final response = await dio.post(apiUrl, data: formData);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
// Handle successful response
|
||||
print('File uploaded successfully');
|
||||
} else {
|
||||
print('Failed to upload file with status: ${response.statusCode}');
|
||||
}
|
||||
} catch (error) {
|
||||
print('Error occurred during form submission: $error');
|
||||
}
|
||||
}
|
||||
|
||||
String lookupMimeType(String filePath) {
|
||||
final ext = filePath.split('.').last;
|
||||
switch (ext) {
|
||||
case 'jpg':
|
||||
case 'jpeg':
|
||||
return 'image/jpeg';
|
||||
case 'png':
|
||||
return 'image/png';
|
||||
case 'pdf':
|
||||
return 'application/pdf';
|
||||
// Add more cases for other file types as needed
|
||||
default:
|
||||
return 'application/octet-stream'; // Default MIME type
|
||||
}
|
||||
}
|
||||
}
|
||||
import 'dart:typed_data';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:http_parser/http_parser.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import '../../resources/api_constants.dart';
|
||||
|
||||
class ApiServiceProfileManagement {
|
||||
final String baseUrl = ApiConstants.baseUrl;
|
||||
final Dio dio = Dio();
|
||||
|
||||
Future<void> createFile(
|
||||
Uint8List fileBytes, String fileName, String token) async {
|
||||
try {
|
||||
String apiUrl = "$baseUrl/api/upload";
|
||||
|
||||
final mimeType = 'image/jpeg'; // You can set the appropriate MIME type
|
||||
|
||||
FormData formData = FormData.fromMap({
|
||||
'imageFile': MultipartFile.fromBytes(
|
||||
fileBytes,
|
||||
filename: fileName,
|
||||
contentType: MediaType.parse(mimeType),
|
||||
),
|
||||
});
|
||||
|
||||
Dio dio = Dio(); // Create a new Dio instance
|
||||
dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
|
||||
final response = await dio.post(apiUrl, data: formData);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
// Handle successful response
|
||||
print('File uploaded successfully');
|
||||
} else {
|
||||
print('Failed to upload file with status: ${response.statusCode}');
|
||||
}
|
||||
} catch (error) {
|
||||
print('Error occurred during form submission: $error');
|
||||
}
|
||||
}
|
||||
|
||||
String lookupMimeType(String filePath) {
|
||||
final ext = filePath.split('.').last;
|
||||
switch (ext) {
|
||||
case 'jpg':
|
||||
case 'jpeg':
|
||||
return 'image/jpeg';
|
||||
case 'png':
|
||||
return 'image/png';
|
||||
case 'pdf':
|
||||
return 'application/pdf';
|
||||
// Add more cases for other file types as needed
|
||||
default:
|
||||
return 'application/octet-stream'; // Default MIME type
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,318 +1,318 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../Utils/image_constant.dart';
|
||||
import '../../Utils/size_utils.dart';
|
||||
import '../../providers/token_manager.dart';
|
||||
import '../../resources/api_constants.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
import '../../theme/app_style.dart';
|
||||
import '../../widgets/app_bar/appbar_image.dart';
|
||||
import '../../widgets/app_bar/appbar_title.dart';
|
||||
import '../../widgets/app_bar/custom_app_bar.dart';
|
||||
import '../../widgets/custom_button.dart';
|
||||
import '../../widgets/custom_text_form_field.dart';
|
||||
import '../Login Screen/login_screen.dart';
|
||||
import '../LogoutService/Logoutservice.dart';
|
||||
|
||||
class ResetPasswordScreen extends StatelessWidget {
|
||||
final String userEmail;
|
||||
|
||||
final Map<String, dynamic> userData;
|
||||
|
||||
ResetPasswordScreen({required this.userEmail,required this.userData});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar:
|
||||
CustomAppBar(
|
||||
height: getVerticalSize(49),
|
||||
leadingWidth: 40,
|
||||
leading: AppbarImage(
|
||||
height: getSize(24),
|
||||
width: getSize(24),
|
||||
svgPath: ImageConstant.imgArrowleftBlueGray900,
|
||||
margin: getMargin(left: 16, top: 12, bottom: 13),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
}),
|
||||
centerTitle: true,
|
||||
title: AppbarTitle(text: "Reset Password")),
|
||||
body: SingleChildScrollView(
|
||||
padding: EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
"You're signed in as $userEmail",
|
||||
style: AppStyle.txtGilroyMedium16Bluegray800
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
ResetPasswordForm(userData: userData,userEmail: userEmail),
|
||||
const SizedBox(height: 20),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => const LoginScreen()),
|
||||
(route) => false, // Remove all routes from the stack
|
||||
);
|
||||
},
|
||||
child: Text(
|
||||
'Wrong account? Log in instead.',
|
||||
style: AppStyle.txtGreenSemiBold16,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ResetPasswordForm extends StatefulWidget {
|
||||
final String userEmail;
|
||||
|
||||
final Map<String, dynamic> userData;
|
||||
|
||||
const ResetPasswordForm({super.key, required this.userEmail,required this.userData});
|
||||
|
||||
|
||||
|
||||
@override
|
||||
_ResetPasswordFormState createState() => _ResetPasswordFormState();
|
||||
}
|
||||
|
||||
class _ResetPasswordFormState extends State<ResetPasswordForm> {
|
||||
final TextEditingController oldPasswordController = TextEditingController();
|
||||
final TextEditingController newPasswordController = TextEditingController();
|
||||
final TextEditingController reEnterNewPasswordController =
|
||||
TextEditingController();
|
||||
|
||||
var responseMessage;
|
||||
var isVisible=false;
|
||||
bool issuccess = false;
|
||||
|
||||
bool isOldPasswordVisible = false;
|
||||
bool isNewPasswordVisible = false;
|
||||
bool isReEnterNewPasswordVisible = false;
|
||||
|
||||
bool _isPasswordValid1 = true;
|
||||
void _validatePassword1(String password) {
|
||||
setState(() {
|
||||
_isPasswordValid1 = password.isNotEmpty;
|
||||
});
|
||||
}
|
||||
|
||||
bool _isPasswordValid2 = true;
|
||||
void _validatePassword2(String password) {
|
||||
setState(() {
|
||||
_isPasswordValid2 = password.isNotEmpty;
|
||||
});
|
||||
}
|
||||
|
||||
bool _isPasswordValid3 = true;
|
||||
void _validatePassword3(String password) {
|
||||
setState(() {
|
||||
_isPasswordValid3 = password.isNotEmpty&&password==newPasswordController.text;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
isVisible?Text(responseMessage,style: TextStyle(
|
||||
color: issuccess?Colors.green:Colors.red, // Set the text color to red
|
||||
)):const Text(''),
|
||||
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Text("Enter Old Password",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style:
|
||||
AppStyle.txtGilroyMedium16Bluegray900)),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
controller: oldPasswordController,
|
||||
hintText: "Enter Old Password",
|
||||
margin: getMargin(top: 6),
|
||||
errorText:
|
||||
_isPasswordValid1 ? null : 'Please enter your old password',
|
||||
padding: TextFormFieldPadding.PaddingT12,
|
||||
textInputAction: TextInputAction.done,
|
||||
onChanged: _validatePassword1,
|
||||
validator: (value) {
|
||||
if (value!.isEmpty) {
|
||||
return 'Please enter your old password';
|
||||
}
|
||||
return null; // Return null to indicate no error
|
||||
},
|
||||
textInputType:TextInputType.visiblePassword,
|
||||
suffix: IconButton(
|
||||
icon: Icon(
|
||||
isOldPasswordVisible ? Icons.visibility : Icons.visibility_off,
|
||||
),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
isOldPasswordVisible = !isOldPasswordVisible;
|
||||
});
|
||||
},
|
||||
),
|
||||
suffixConstraints: BoxConstraints(
|
||||
maxHeight: getVerticalSize(44)),
|
||||
isObscureText: !isOldPasswordVisible),
|
||||
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Text("Enter New Password",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style:
|
||||
AppStyle.txtGilroyMedium16Bluegray900)),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
controller: newPasswordController,
|
||||
hintText: "Enter New Password",
|
||||
margin: getMargin(top: 6),
|
||||
padding: TextFormFieldPadding.PaddingT12,
|
||||
textInputAction: TextInputAction.done,
|
||||
suffix: IconButton(
|
||||
icon: Icon(
|
||||
isNewPasswordVisible ? Icons.visibility : Icons.visibility_off,
|
||||
),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
isNewPasswordVisible = !isNewPasswordVisible;
|
||||
});
|
||||
},
|
||||
),
|
||||
errorText:
|
||||
_isPasswordValid2 ? null : 'Please enter your new password',
|
||||
onChanged: _validatePassword2,
|
||||
validator: (value) {
|
||||
if (value!.isEmpty) {
|
||||
return 'Please enter your new password';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
suffixConstraints: BoxConstraints(
|
||||
maxHeight: getVerticalSize(44)),
|
||||
isObscureText:!isNewPasswordVisible,),
|
||||
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Text("Re-Enter New Password",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style:
|
||||
AppStyle.txtGilroyMedium16Bluegray900)),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
controller: reEnterNewPasswordController,
|
||||
hintText: "Re-Enter New Password",
|
||||
margin: getMargin(top: 6),
|
||||
padding: TextFormFieldPadding.PaddingT12,
|
||||
onChanged: _validatePassword3,
|
||||
validator: (value) {
|
||||
if (value!.isEmpty) {
|
||||
return 'Please re-enter your new password';
|
||||
}
|
||||
if (value != newPasswordController.text) {
|
||||
return 'Passwords do not match';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
suffix: IconButton(
|
||||
icon: Icon(
|
||||
isReEnterNewPasswordVisible
|
||||
? Icons.visibility
|
||||
: Icons.visibility_off,
|
||||
),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
isReEnterNewPasswordVisible = !isReEnterNewPasswordVisible;
|
||||
});
|
||||
},
|
||||
),
|
||||
errorText:
|
||||
_isPasswordValid3 ? null : 'Please re-enter your new password',
|
||||
textInputAction: TextInputAction.done,
|
||||
suffixConstraints: BoxConstraints(
|
||||
maxHeight: getVerticalSize(44)),
|
||||
isObscureText:!isReEnterNewPasswordVisible,),
|
||||
|
||||
CustomButton(
|
||||
height: getVerticalSize(50),
|
||||
text: "Continue",
|
||||
margin: getMargin(top: 24, bottom: 5),
|
||||
onTap: () async {
|
||||
if (oldPasswordController.text.isEmpty ||
|
||||
newPasswordController.text.isEmpty ||
|
||||
reEnterNewPasswordController.text.isEmpty) {
|
||||
print(oldPasswordController.text);
|
||||
print(newPasswordController.text);
|
||||
print(reEnterNewPasswordController.text);
|
||||
} else {
|
||||
Map<String, dynamic> passwordData = {
|
||||
"userId":widget.userData['userId'],
|
||||
"oldPassword": oldPasswordController.text,
|
||||
"newPassword": newPasswordController.text,
|
||||
"confirmPassword": reEnterNewPasswordController.text,
|
||||
};
|
||||
final token = await TokenManager.getToken();
|
||||
final String baseUrl = ApiConstants.baseUrl;
|
||||
final String apiUrl = '$baseUrl/api/reset_password';
|
||||
|
||||
try {
|
||||
final response = await http.post(Uri.parse(apiUrl),
|
||||
headers: {
|
||||
'Authorization': 'Bearer $token',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: json.encode(passwordData));
|
||||
if(response.statusCode==401){
|
||||
LogoutService.logout();
|
||||
}
|
||||
if (response.statusCode <= 209) {
|
||||
setState(() {
|
||||
isVisible=true;
|
||||
issuccess=true;
|
||||
responseMessage = "Password Changes Successfully";
|
||||
});
|
||||
print("success");
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => LoginScreen()),
|
||||
(route) => false,
|
||||
);
|
||||
} else {
|
||||
setState(() {
|
||||
isVisible=true;
|
||||
responseMessage = "Incorrect Password";
|
||||
});
|
||||
print(response.statusCode);
|
||||
}
|
||||
} catch (e) {
|
||||
throw Exception('Failed to Update: $e');
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
oldPasswordController.dispose();
|
||||
newPasswordController.dispose();
|
||||
reEnterNewPasswordController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../../Utils/image_constant.dart';
|
||||
import '../../Utils/size_utils.dart';
|
||||
import '../../providers/token_manager.dart';
|
||||
import '../../resources/api_constants.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
import '../../theme/app_style.dart';
|
||||
import '../../widgets/app_bar/appbar_image.dart';
|
||||
import '../../widgets/app_bar/appbar_title.dart';
|
||||
import '../../widgets/app_bar/custom_app_bar.dart';
|
||||
import '../../widgets/custom_button.dart';
|
||||
import '../../widgets/custom_text_form_field.dart';
|
||||
import '../Login Screen/login_screen.dart';
|
||||
import '../LogoutService/Logoutservice.dart';
|
||||
|
||||
class ResetPasswordScreen extends StatelessWidget {
|
||||
final String userEmail;
|
||||
|
||||
final Map<String, dynamic> userData;
|
||||
|
||||
ResetPasswordScreen({required this.userEmail,required this.userData});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar:
|
||||
CustomAppBar(
|
||||
height: getVerticalSize(49),
|
||||
leadingWidth: 40,
|
||||
leading: AppbarImage(
|
||||
height: getSize(24),
|
||||
width: getSize(24),
|
||||
svgPath: ImageConstant.imgArrowleftBlueGray900,
|
||||
margin: getMargin(left: 16, top: 12, bottom: 13),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
}),
|
||||
centerTitle: true,
|
||||
title: AppbarTitle(text: "Reset Password")),
|
||||
body: SingleChildScrollView(
|
||||
padding: EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
Text(
|
||||
"You're signed in as $userEmail",
|
||||
style: AppStyle.txtGilroyMedium16Bluegray800
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
ResetPasswordForm(userData: userData,userEmail: userEmail),
|
||||
const SizedBox(height: 20),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => const LoginScreen()),
|
||||
(route) => false, // Remove all routes from the stack
|
||||
);
|
||||
},
|
||||
child: Text(
|
||||
'Wrong account? Log in instead.',
|
||||
style: AppStyle.txtGreenSemiBold16,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ResetPasswordForm extends StatefulWidget {
|
||||
final String userEmail;
|
||||
|
||||
final Map<String, dynamic> userData;
|
||||
|
||||
const ResetPasswordForm({super.key, required this.userEmail,required this.userData});
|
||||
|
||||
|
||||
|
||||
@override
|
||||
_ResetPasswordFormState createState() => _ResetPasswordFormState();
|
||||
}
|
||||
|
||||
class _ResetPasswordFormState extends State<ResetPasswordForm> {
|
||||
final TextEditingController oldPasswordController = TextEditingController();
|
||||
final TextEditingController newPasswordController = TextEditingController();
|
||||
final TextEditingController reEnterNewPasswordController =
|
||||
TextEditingController();
|
||||
|
||||
var responseMessage;
|
||||
var isVisible=false;
|
||||
bool issuccess = false;
|
||||
|
||||
bool isOldPasswordVisible = false;
|
||||
bool isNewPasswordVisible = false;
|
||||
bool isReEnterNewPasswordVisible = false;
|
||||
|
||||
bool _isPasswordValid1 = true;
|
||||
void _validatePassword1(String password) {
|
||||
setState(() {
|
||||
_isPasswordValid1 = password.isNotEmpty;
|
||||
});
|
||||
}
|
||||
|
||||
bool _isPasswordValid2 = true;
|
||||
void _validatePassword2(String password) {
|
||||
setState(() {
|
||||
_isPasswordValid2 = password.isNotEmpty;
|
||||
});
|
||||
}
|
||||
|
||||
bool _isPasswordValid3 = true;
|
||||
void _validatePassword3(String password) {
|
||||
setState(() {
|
||||
_isPasswordValid3 = password.isNotEmpty&&password==newPasswordController.text;
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: <Widget>[
|
||||
isVisible?Text(responseMessage,style: TextStyle(
|
||||
color: issuccess?Colors.green:Colors.red, // Set the text color to red
|
||||
)):const Text(''),
|
||||
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Text("Enter Old Password",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style:
|
||||
AppStyle.txtGilroyMedium16Bluegray900)),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
controller: oldPasswordController,
|
||||
hintText: "Enter Old Password",
|
||||
margin: getMargin(top: 6),
|
||||
errorText:
|
||||
_isPasswordValid1 ? null : 'Please enter your old password',
|
||||
padding: TextFormFieldPadding.PaddingT12,
|
||||
textInputAction: TextInputAction.done,
|
||||
onChanged: _validatePassword1,
|
||||
validator: (value) {
|
||||
if (value!.isEmpty) {
|
||||
return 'Please enter your old password';
|
||||
}
|
||||
return null; // Return null to indicate no error
|
||||
},
|
||||
textInputType:TextInputType.visiblePassword,
|
||||
suffix: IconButton(
|
||||
icon: Icon(
|
||||
isOldPasswordVisible ? Icons.visibility : Icons.visibility_off,
|
||||
),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
isOldPasswordVisible = !isOldPasswordVisible;
|
||||
});
|
||||
},
|
||||
),
|
||||
suffixConstraints: BoxConstraints(
|
||||
maxHeight: getVerticalSize(44)),
|
||||
isObscureText: !isOldPasswordVisible),
|
||||
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Text("Enter New Password",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style:
|
||||
AppStyle.txtGilroyMedium16Bluegray900)),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
controller: newPasswordController,
|
||||
hintText: "Enter New Password",
|
||||
margin: getMargin(top: 6),
|
||||
padding: TextFormFieldPadding.PaddingT12,
|
||||
textInputAction: TextInputAction.done,
|
||||
suffix: IconButton(
|
||||
icon: Icon(
|
||||
isNewPasswordVisible ? Icons.visibility : Icons.visibility_off,
|
||||
),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
isNewPasswordVisible = !isNewPasswordVisible;
|
||||
});
|
||||
},
|
||||
),
|
||||
errorText:
|
||||
_isPasswordValid2 ? null : 'Please enter your new password',
|
||||
onChanged: _validatePassword2,
|
||||
validator: (value) {
|
||||
if (value!.isEmpty) {
|
||||
return 'Please enter your new password';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
suffixConstraints: BoxConstraints(
|
||||
maxHeight: getVerticalSize(44)),
|
||||
isObscureText:!isNewPasswordVisible,),
|
||||
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Text("Re-Enter New Password",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style:
|
||||
AppStyle.txtGilroyMedium16Bluegray900)),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
controller: reEnterNewPasswordController,
|
||||
hintText: "Re-Enter New Password",
|
||||
margin: getMargin(top: 6),
|
||||
padding: TextFormFieldPadding.PaddingT12,
|
||||
onChanged: _validatePassword3,
|
||||
validator: (value) {
|
||||
if (value!.isEmpty) {
|
||||
return 'Please re-enter your new password';
|
||||
}
|
||||
if (value != newPasswordController.text) {
|
||||
return 'Passwords do not match';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
suffix: IconButton(
|
||||
icon: Icon(
|
||||
isReEnterNewPasswordVisible
|
||||
? Icons.visibility
|
||||
: Icons.visibility_off,
|
||||
),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
isReEnterNewPasswordVisible = !isReEnterNewPasswordVisible;
|
||||
});
|
||||
},
|
||||
),
|
||||
errorText:
|
||||
_isPasswordValid3 ? null : 'Please re-enter your new password',
|
||||
textInputAction: TextInputAction.done,
|
||||
suffixConstraints: BoxConstraints(
|
||||
maxHeight: getVerticalSize(44)),
|
||||
isObscureText:!isReEnterNewPasswordVisible,),
|
||||
|
||||
CustomButton(
|
||||
height: getVerticalSize(50),
|
||||
text: "Continue",
|
||||
margin: getMargin(top: 24, bottom: 5),
|
||||
onTap: () async {
|
||||
if (oldPasswordController.text.isEmpty ||
|
||||
newPasswordController.text.isEmpty ||
|
||||
reEnterNewPasswordController.text.isEmpty) {
|
||||
print(oldPasswordController.text);
|
||||
print(newPasswordController.text);
|
||||
print(reEnterNewPasswordController.text);
|
||||
} else {
|
||||
Map<String, dynamic> passwordData = {
|
||||
"userId":widget.userData['userId'],
|
||||
"oldPassword": oldPasswordController.text,
|
||||
"newPassword": newPasswordController.text,
|
||||
"confirmPassword": reEnterNewPasswordController.text,
|
||||
};
|
||||
final token = await TokenManager.getToken();
|
||||
final String baseUrl = ApiConstants.baseUrl;
|
||||
final String apiUrl = '$baseUrl/api/reset_password';
|
||||
|
||||
try {
|
||||
final response = await http.post(Uri.parse(apiUrl),
|
||||
headers: {
|
||||
'Authorization': 'Bearer $token',
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: json.encode(passwordData));
|
||||
if(response.statusCode==401){
|
||||
LogoutService.logout();
|
||||
}
|
||||
if (response.statusCode <= 209) {
|
||||
setState(() {
|
||||
isVisible=true;
|
||||
issuccess=true;
|
||||
responseMessage = "Password Changes Successfully";
|
||||
});
|
||||
print("success");
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => LoginScreen()),
|
||||
(route) => false,
|
||||
);
|
||||
} else {
|
||||
setState(() {
|
||||
isVisible=true;
|
||||
responseMessage = "Incorrect Password";
|
||||
});
|
||||
print(response.statusCode);
|
||||
}
|
||||
} catch (e) {
|
||||
throw Exception('Failed to Update: $e');
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
oldPasswordController.dispose();
|
||||
newPasswordController.dispose();
|
||||
reEnterNewPasswordController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,102 +1,102 @@
|
||||
import 'package:fade_shimmer/fade_shimmer.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
Widget _creditsloadingTile(BuildContext context) {
|
||||
List<Widget> socialLinks = List.generate(
|
||||
6,
|
||||
(index) => Container(
|
||||
child: const FadeShimmer(
|
||||
radius: 16.18,
|
||||
height: 48,
|
||||
width: 48,
|
||||
fadeTheme: FadeTheme.light,
|
||||
),
|
||||
padding: const EdgeInsets.all(2),
|
||||
),
|
||||
);
|
||||
return Container(
|
||||
width: MediaQuery.of(context).size.width - 10,
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.blueGrey.shade100.withOpacity(0.1618),
|
||||
borderRadius: const BorderRadius.all(Radius.circular(16.18))),
|
||||
margin: const EdgeInsets.symmetric(vertical: 3, horizontal: 6.18),
|
||||
child: Wrap(
|
||||
direction: Axis.vertical,
|
||||
children: [
|
||||
Container(
|
||||
width: MediaQuery.of(context).size.width - 48,
|
||||
padding: const EdgeInsets.all(6.18),
|
||||
child: Wrap(
|
||||
alignment: WrapAlignment.spaceBetween,
|
||||
children: [
|
||||
Wrap(direction: Axis.vertical, children: [
|
||||
Container(
|
||||
child: const FadeShimmer(
|
||||
radius: 16.18,
|
||||
height: 27,
|
||||
width: 96,
|
||||
fadeTheme: FadeTheme.light,
|
||||
),
|
||||
padding: const EdgeInsets.all(2),
|
||||
),
|
||||
Container(
|
||||
child: const FadeShimmer(
|
||||
radius: 16.18,
|
||||
height: 20,
|
||||
width: 72,
|
||||
fadeTheme: FadeTheme.light,
|
||||
),
|
||||
padding: const EdgeInsets.all(2),
|
||||
),
|
||||
]),
|
||||
Container(
|
||||
child: const FadeShimmer(
|
||||
radius: 16.18,
|
||||
height: 64,
|
||||
width: 64,
|
||||
fadeTheme: FadeTheme.light,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
child: const FadeShimmer(
|
||||
radius: 16.18,
|
||||
height: 16,
|
||||
width: 96,
|
||||
fadeTheme: FadeTheme.light,
|
||||
),
|
||||
padding: const EdgeInsets.all(2),
|
||||
),
|
||||
Container(
|
||||
height: 72,
|
||||
width: MediaQuery.of(context).size.width - 48,
|
||||
padding: const EdgeInsets.all(0),
|
||||
color: Colors.transparent,
|
||||
child: ListView.separated(
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemBuilder: (_, index) => socialLinks[index],
|
||||
separatorBuilder: (_, b) => const SizedBox(
|
||||
width: 16.18,
|
||||
),
|
||||
itemCount: socialLinks.length),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget creditsLoadingList(int items, BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 5),
|
||||
child: ListView.builder(
|
||||
padding: const EdgeInsets.all(0),
|
||||
itemBuilder: (_, index) => Padding(
|
||||
padding: const EdgeInsets.all(5),
|
||||
child: _creditsloadingTile(context)),
|
||||
itemCount: items,
|
||||
),
|
||||
);
|
||||
}
|
||||
import 'package:fade_shimmer/fade_shimmer.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
Widget _creditsloadingTile(BuildContext context) {
|
||||
List<Widget> socialLinks = List.generate(
|
||||
6,
|
||||
(index) => Container(
|
||||
child: const FadeShimmer(
|
||||
radius: 16.18,
|
||||
height: 48,
|
||||
width: 48,
|
||||
fadeTheme: FadeTheme.light,
|
||||
),
|
||||
padding: const EdgeInsets.all(2),
|
||||
),
|
||||
);
|
||||
return Container(
|
||||
width: MediaQuery.of(context).size.width - 10,
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.blueGrey.shade100.withOpacity(0.1618),
|
||||
borderRadius: const BorderRadius.all(Radius.circular(16.18))),
|
||||
margin: const EdgeInsets.symmetric(vertical: 3, horizontal: 6.18),
|
||||
child: Wrap(
|
||||
direction: Axis.vertical,
|
||||
children: [
|
||||
Container(
|
||||
width: MediaQuery.of(context).size.width - 48,
|
||||
padding: const EdgeInsets.all(6.18),
|
||||
child: Wrap(
|
||||
alignment: WrapAlignment.spaceBetween,
|
||||
children: [
|
||||
Wrap(direction: Axis.vertical, children: [
|
||||
Container(
|
||||
child: const FadeShimmer(
|
||||
radius: 16.18,
|
||||
height: 27,
|
||||
width: 96,
|
||||
fadeTheme: FadeTheme.light,
|
||||
),
|
||||
padding: const EdgeInsets.all(2),
|
||||
),
|
||||
Container(
|
||||
child: const FadeShimmer(
|
||||
radius: 16.18,
|
||||
height: 20,
|
||||
width: 72,
|
||||
fadeTheme: FadeTheme.light,
|
||||
),
|
||||
padding: const EdgeInsets.all(2),
|
||||
),
|
||||
]),
|
||||
Container(
|
||||
child: const FadeShimmer(
|
||||
radius: 16.18,
|
||||
height: 64,
|
||||
width: 64,
|
||||
fadeTheme: FadeTheme.light,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Container(
|
||||
child: const FadeShimmer(
|
||||
radius: 16.18,
|
||||
height: 16,
|
||||
width: 96,
|
||||
fadeTheme: FadeTheme.light,
|
||||
),
|
||||
padding: const EdgeInsets.all(2),
|
||||
),
|
||||
Container(
|
||||
height: 72,
|
||||
width: MediaQuery.of(context).size.width - 48,
|
||||
padding: const EdgeInsets.all(0),
|
||||
color: Colors.transparent,
|
||||
child: ListView.separated(
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemBuilder: (_, index) => socialLinks[index],
|
||||
separatorBuilder: (_, b) => const SizedBox(
|
||||
width: 16.18,
|
||||
),
|
||||
itemCount: socialLinks.length),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget creditsLoadingList(int items, BuildContext context) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 5),
|
||||
child: ListView.builder(
|
||||
padding: const EdgeInsets.all(0),
|
||||
itemBuilder: (_, index) => Padding(
|
||||
padding: const EdgeInsets.all(5),
|
||||
child: _creditsloadingTile(context)),
|
||||
itemCount: items,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,263 +1,263 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import '../../Utils/size_utils.dart';
|
||||
import '../../theme/app_style.dart';
|
||||
import '../../widgets/custom_button.dart';
|
||||
import '../../widgets/custom_text_form_field.dart';
|
||||
import 'SignUpService.dart';
|
||||
|
||||
class CreateAccountScreen extends StatefulWidget {
|
||||
CreateAccountScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_CreateAccountScreenState createState() => _CreateAccountScreenState();
|
||||
}
|
||||
|
||||
class _CreateAccountScreenState extends State<CreateAccountScreen> {
|
||||
final SignUpApiService userService = SignUpApiService();
|
||||
|
||||
final Map<String, dynamic> formData = {};
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
late BuildContext _context; // Store the current context
|
||||
late var account_id; // Store the account_id
|
||||
|
||||
bool _isEmailValid = true;
|
||||
void _validateEmail(String email) {
|
||||
setState(() {
|
||||
_isEmailValid =
|
||||
RegExp(r'^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$').hasMatch(email);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_context = context; // Store the context
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Create Account')),
|
||||
body: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Text("Company Name",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style:
|
||||
AppStyle.txtGilroyMedium16Bluegray900)),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
onsaved: (value) => formData['companyName'] = value,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Company Name';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
hintText: "enter Company Name",
|
||||
margin: getMargin(top: 6),
|
||||
padding: TextFormFieldPadding.PaddingT12,
|
||||
textInputType: TextInputType.text
|
||||
),
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Text("Email",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style:
|
||||
AppStyle.txtGilroyMedium16Bluegray900)),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
onsaved: (value) => formData['email'] = value,
|
||||
onChanged: _validateEmail,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Email';
|
||||
}else if(!_isEmailValid){
|
||||
return 'Please enter a valid email';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
hintText: "enter Email",
|
||||
margin: getMargin(top: 6),
|
||||
padding: TextFormFieldPadding.PaddingT12,
|
||||
textInputType: TextInputType.text
|
||||
),
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Text("Mobile Number",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style:
|
||||
AppStyle.txtGilroyMedium16Bluegray900)),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
textInputType: TextInputType.phone,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp(r'[0-9]'))
|
||||
],
|
||||
onsaved: (value) => formData['mobile'] = value,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Mob No';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
hintText: "enter Mobile Number",
|
||||
margin: getMargin(top: 6),
|
||||
padding: TextFormFieldPadding.PaddingT12,
|
||||
),
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Text("Workspace",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style:
|
||||
AppStyle.txtGilroyMedium16Bluegray900)),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
onsaved: (value) => formData['workspace'] = value,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Workspace';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
hintText: "enter Workspace",
|
||||
margin: getMargin(top: 6),
|
||||
padding: TextFormFieldPadding.PaddingT12,
|
||||
textInputType: TextInputType.text
|
||||
),
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Text("Gst Number",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style:
|
||||
AppStyle.txtGilroyMedium16Bluegray900)),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
onsaved: (value) => formData['gstNumber'] = value,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Gst Number';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
hintText: "enter Gst Number",
|
||||
margin: getMargin(top: 6),
|
||||
padding: TextFormFieldPadding.PaddingT12,
|
||||
textInputType: TextInputType.text
|
||||
),
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Text("pancard",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style:
|
||||
AppStyle.txtGilroyMedium16Bluegray900)),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
onsaved: (value) => formData['pancard'] = value,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Pancard';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
hintText: "enter pancard",
|
||||
margin: getMargin(top: 6),
|
||||
padding: TextFormFieldPadding.PaddingT12,
|
||||
textInputType: TextInputType.text
|
||||
),
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Text("Working",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style:
|
||||
AppStyle.txtGilroyMedium16Bluegray900)),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
onsaved: (value) => formData['working'] = value,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Working';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
hintText: "enter Working",
|
||||
margin: getMargin(top: 6),
|
||||
padding: TextFormFieldPadding.PaddingT12,
|
||||
textInputType: TextInputType.text
|
||||
),
|
||||
Container(
|
||||
margin: const EdgeInsets.symmetric(vertical: 5), // Add margin
|
||||
child: CustomButton(
|
||||
height: getVerticalSize(50),
|
||||
width: getHorizontalSize(396),
|
||||
text: "SUBMIT",
|
||||
margin: getMargin(top: 25),
|
||||
onTap: () async {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
_formKey.currentState!.save();
|
||||
{
|
||||
try {
|
||||
print('form data is $formData');
|
||||
|
||||
final response =
|
||||
await userService.createAccount(formData);
|
||||
|
||||
account_id = response['account_id'].toString();
|
||||
print(
|
||||
'after create account account id is $account_id');
|
||||
// ignore: use_build_context_synchronously
|
||||
Navigator.pop(
|
||||
_context, account_id); // Pop with account_id
|
||||
|
||||
// Navigator.pop(context);
|
||||
} catch (e) {
|
||||
// ignore: use_build_context_synchronously
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: const Text('Error'),
|
||||
content: Text('Account Creation Failed: $e'),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: const Text('OK'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import '../../Utils/size_utils.dart';
|
||||
import '../../theme/app_style.dart';
|
||||
import '../../widgets/custom_button.dart';
|
||||
import '../../widgets/custom_text_form_field.dart';
|
||||
import 'SignUpService.dart';
|
||||
|
||||
class CreateAccountScreen extends StatefulWidget {
|
||||
CreateAccountScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_CreateAccountScreenState createState() => _CreateAccountScreenState();
|
||||
}
|
||||
|
||||
class _CreateAccountScreenState extends State<CreateAccountScreen> {
|
||||
final SignUpApiService userService = SignUpApiService();
|
||||
|
||||
final Map<String, dynamic> formData = {};
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
late BuildContext _context; // Store the current context
|
||||
late var account_id; // Store the account_id
|
||||
|
||||
bool _isEmailValid = true;
|
||||
void _validateEmail(String email) {
|
||||
setState(() {
|
||||
_isEmailValid =
|
||||
RegExp(r'^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$').hasMatch(email);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
_context = context; // Store the context
|
||||
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('Create Account')),
|
||||
body: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Text("Company Name",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style:
|
||||
AppStyle.txtGilroyMedium16Bluegray900)),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
onsaved: (value) => formData['companyName'] = value,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Company Name';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
hintText: "enter Company Name",
|
||||
margin: getMargin(top: 6),
|
||||
padding: TextFormFieldPadding.PaddingT12,
|
||||
textInputType: TextInputType.text
|
||||
),
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Text("Email",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style:
|
||||
AppStyle.txtGilroyMedium16Bluegray900)),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
onsaved: (value) => formData['email'] = value,
|
||||
onChanged: _validateEmail,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Email';
|
||||
}else if(!_isEmailValid){
|
||||
return 'Please enter a valid email';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
hintText: "enter Email",
|
||||
margin: getMargin(top: 6),
|
||||
padding: TextFormFieldPadding.PaddingT12,
|
||||
textInputType: TextInputType.text
|
||||
),
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Text("Mobile Number",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style:
|
||||
AppStyle.txtGilroyMedium16Bluegray900)),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
textInputType: TextInputType.phone,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp(r'[0-9]'))
|
||||
],
|
||||
onsaved: (value) => formData['mobile'] = value,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Mob No';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
hintText: "enter Mobile Number",
|
||||
margin: getMargin(top: 6),
|
||||
padding: TextFormFieldPadding.PaddingT12,
|
||||
),
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Text("Workspace",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style:
|
||||
AppStyle.txtGilroyMedium16Bluegray900)),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
onsaved: (value) => formData['workspace'] = value,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Workspace';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
hintText: "enter Workspace",
|
||||
margin: getMargin(top: 6),
|
||||
padding: TextFormFieldPadding.PaddingT12,
|
||||
textInputType: TextInputType.text
|
||||
),
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Text("Gst Number",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style:
|
||||
AppStyle.txtGilroyMedium16Bluegray900)),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
onsaved: (value) => formData['gstNumber'] = value,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Gst Number';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
hintText: "enter Gst Number",
|
||||
margin: getMargin(top: 6),
|
||||
padding: TextFormFieldPadding.PaddingT12,
|
||||
textInputType: TextInputType.text
|
||||
),
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Text("pancard",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style:
|
||||
AppStyle.txtGilroyMedium16Bluegray900)),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
onsaved: (value) => formData['pancard'] = value,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Pancard';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
hintText: "enter pancard",
|
||||
margin: getMargin(top: 6),
|
||||
padding: TextFormFieldPadding.PaddingT12,
|
||||
textInputType: TextInputType.text
|
||||
),
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Text("Working",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style:
|
||||
AppStyle.txtGilroyMedium16Bluegray900)),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
onsaved: (value) => formData['working'] = value,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Working';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
hintText: "enter Working",
|
||||
margin: getMargin(top: 6),
|
||||
padding: TextFormFieldPadding.PaddingT12,
|
||||
textInputType: TextInputType.text
|
||||
),
|
||||
Container(
|
||||
margin: const EdgeInsets.symmetric(vertical: 5), // Add margin
|
||||
child: CustomButton(
|
||||
height: getVerticalSize(50),
|
||||
width: getHorizontalSize(396),
|
||||
text: "SUBMIT",
|
||||
margin: getMargin(top: 25),
|
||||
onTap: () async {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
_formKey.currentState!.save();
|
||||
{
|
||||
try {
|
||||
print('form data is $formData');
|
||||
|
||||
final response =
|
||||
await userService.createAccount(formData);
|
||||
|
||||
account_id = response['account_id'].toString();
|
||||
print(
|
||||
'after create account account id is $account_id');
|
||||
// ignore: use_build_context_synchronously
|
||||
Navigator.pop(
|
||||
_context, account_id); // Pop with account_id
|
||||
|
||||
// Navigator.pop(context);
|
||||
} catch (e) {
|
||||
// ignore: use_build_context_synchronously
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: const Text('Error'),
|
||||
content: Text('Account Creation Failed: $e'),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: const Text('OK'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,328 +1,328 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'SignUpService.dart';
|
||||
|
||||
class CreateUserScreen extends StatefulWidget {
|
||||
CreateUserScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_CreateUserScreenState createState() => _CreateUserScreenState();
|
||||
}
|
||||
|
||||
class _CreateUserScreenState extends State<CreateUserScreen> {
|
||||
int _currentStep = 0;
|
||||
|
||||
// Create a global key for each step
|
||||
final GlobalKey<StepCreateAccountState> createAccountKey =
|
||||
GlobalKey<StepCreateAccountState>();
|
||||
|
||||
final GlobalKey<StepGetEmailVerificationState> emailVerificationKey =
|
||||
GlobalKey<StepGetEmailVerificationState>();
|
||||
|
||||
final GlobalKey<StepGetRegistrationState> registrationKey =
|
||||
GlobalKey<StepGetRegistrationState>();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('Sign Up - Step ${_currentStep + 1}'),
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
// Display the current step
|
||||
Expanded(
|
||||
child: _buildStep(_currentStep),
|
||||
),
|
||||
|
||||
// Navigation buttons
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
if (_currentStep > 0)
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_currentStep--;
|
||||
});
|
||||
},
|
||||
child: const Text('Previous'),
|
||||
),
|
||||
if (_currentStep < 2)
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
_proceedToNextStep();
|
||||
},
|
||||
child: const Text('Next'),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Function to build the appropriate step based on the current step index
|
||||
Widget _buildStep(int stepIndex) {
|
||||
switch (stepIndex) {
|
||||
case 0:
|
||||
return StepCreateAccount(
|
||||
key: createAccountKey,
|
||||
onNext: () {
|
||||
_proceedToNextStep();
|
||||
},
|
||||
);
|
||||
case 1:
|
||||
return StepGetEmailVerification(
|
||||
key: emailVerificationKey,
|
||||
onNext: () {
|
||||
_proceedToNextStep();
|
||||
},
|
||||
);
|
||||
case 2:
|
||||
return StepGetRegistration(
|
||||
key: registrationKey,
|
||||
onNext: () {
|
||||
_proceedToNextStep();
|
||||
},
|
||||
);
|
||||
default:
|
||||
return Container(); // Return an empty container by default
|
||||
}
|
||||
}
|
||||
|
||||
// Function to proceed to the next step
|
||||
void _proceedToNextStep() {
|
||||
if (_currentStep < 2) {
|
||||
setState(() {
|
||||
_currentStep++;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Define your individual step widgets here
|
||||
|
||||
class StepCreateAccount extends StatefulWidget {
|
||||
final Function onNext;
|
||||
|
||||
const StepCreateAccount({Key? key, required this.onNext}) : super(key: key);
|
||||
|
||||
@override
|
||||
StepCreateAccountState createState() => StepCreateAccountState();
|
||||
}
|
||||
|
||||
class StepCreateAccountState extends State<StepCreateAccount> {
|
||||
// Add your state variables for this step here
|
||||
String? accountId;
|
||||
final Map<String, dynamic> formData = {};
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final SignUpApiService userService = SignUpApiService();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
alignment: Alignment.center,
|
||||
child: Column(
|
||||
children: [
|
||||
const Text('Step 1: Create Account'),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(labelText: 'Company Name'),
|
||||
onSaved: (value) => formData['companyName'] = value,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Company Name';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(labelText: 'Email'),
|
||||
onSaved: (value) => formData['email'] = value,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Email';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(labelText: 'Mobile No'),
|
||||
onSaved: (value) => formData['mobile'] = value,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Mob No';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(labelText: 'Workspace'),
|
||||
onSaved: (value) => formData['workspace'] = value,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Workspace';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(labelText: 'Gst Number'),
|
||||
onSaved: (value) => formData['gstNumber'] = value,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Gst Number';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(labelText: 'pancard'),
|
||||
onSaved: (value) => formData['pancard'] = value,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Pancard';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(labelText: 'Working'),
|
||||
onSaved: (value) => formData['working'] = value,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Working';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Container(
|
||||
margin: const EdgeInsets.symmetric(vertical: 5), // Add margin
|
||||
child: ElevatedButton(
|
||||
onPressed: () async {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
_formKey.currentState!.save();
|
||||
{
|
||||
try {
|
||||
print('form data is $formData');
|
||||
|
||||
final response =
|
||||
await userService.createAccount(formData);
|
||||
|
||||
accountId = response['account_id'].toString();
|
||||
print('after create account account id is $accountId');
|
||||
// ignore: use_build_context_synchronously
|
||||
// Navigator.pop(
|
||||
// _context, accountId); // Pop with account_id
|
||||
|
||||
// Navigator.pop(context);
|
||||
} catch (e) {
|
||||
// ignore: use_build_context_synchronously
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: const Text('Error'),
|
||||
content: Text('Account Creation Failed: $e'),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: const Text('OK'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
child: const SizedBox(
|
||||
width: double.infinity,
|
||||
height: 50,
|
||||
child: Center(
|
||||
child: Text(
|
||||
'SUBMIT',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (accountId != null) Text('Selected Account ID: $accountId'),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class StepGetEmailVerification extends StatefulWidget {
|
||||
final Function onNext;
|
||||
|
||||
const StepGetEmailVerification({Key? key, required this.onNext})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
StepGetEmailVerificationState createState() =>
|
||||
StepGetEmailVerificationState();
|
||||
}
|
||||
|
||||
class StepGetEmailVerificationState extends State<StepGetEmailVerification> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
alignment: Alignment.center,
|
||||
child: Text('Step 2: Get Email Verification'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class StepGetRegistration extends StatefulWidget {
|
||||
final Function onNext;
|
||||
|
||||
const StepGetRegistration({Key? key, required this.onNext}) : super(key: key);
|
||||
|
||||
@override
|
||||
StepGetRegistrationState createState() => StepGetRegistrationState();
|
||||
}
|
||||
|
||||
class StepGetRegistrationState extends State<StepGetRegistration> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
alignment: Alignment.center,
|
||||
child: Text('Step 3: Get Registration'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Example of a dialog to create an account
|
||||
class CreateAccountDialog extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text('Create Account'),
|
||||
content: Text('Account created successfully!'),
|
||||
actions: [
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop('12345'); // Pass the created account ID
|
||||
},
|
||||
child: Text('OK'),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'SignUpService.dart';
|
||||
|
||||
class CreateUserScreen extends StatefulWidget {
|
||||
CreateUserScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_CreateUserScreenState createState() => _CreateUserScreenState();
|
||||
}
|
||||
|
||||
class _CreateUserScreenState extends State<CreateUserScreen> {
|
||||
int _currentStep = 0;
|
||||
|
||||
// Create a global key for each step
|
||||
final GlobalKey<StepCreateAccountState> createAccountKey =
|
||||
GlobalKey<StepCreateAccountState>();
|
||||
|
||||
final GlobalKey<StepGetEmailVerificationState> emailVerificationKey =
|
||||
GlobalKey<StepGetEmailVerificationState>();
|
||||
|
||||
final GlobalKey<StepGetRegistrationState> registrationKey =
|
||||
GlobalKey<StepGetRegistrationState>();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('Sign Up - Step ${_currentStep + 1}'),
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
// Display the current step
|
||||
Expanded(
|
||||
child: _buildStep(_currentStep),
|
||||
),
|
||||
|
||||
// Navigation buttons
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
if (_currentStep > 0)
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_currentStep--;
|
||||
});
|
||||
},
|
||||
child: const Text('Previous'),
|
||||
),
|
||||
if (_currentStep < 2)
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
_proceedToNextStep();
|
||||
},
|
||||
child: const Text('Next'),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Function to build the appropriate step based on the current step index
|
||||
Widget _buildStep(int stepIndex) {
|
||||
switch (stepIndex) {
|
||||
case 0:
|
||||
return StepCreateAccount(
|
||||
key: createAccountKey,
|
||||
onNext: () {
|
||||
_proceedToNextStep();
|
||||
},
|
||||
);
|
||||
case 1:
|
||||
return StepGetEmailVerification(
|
||||
key: emailVerificationKey,
|
||||
onNext: () {
|
||||
_proceedToNextStep();
|
||||
},
|
||||
);
|
||||
case 2:
|
||||
return StepGetRegistration(
|
||||
key: registrationKey,
|
||||
onNext: () {
|
||||
_proceedToNextStep();
|
||||
},
|
||||
);
|
||||
default:
|
||||
return Container(); // Return an empty container by default
|
||||
}
|
||||
}
|
||||
|
||||
// Function to proceed to the next step
|
||||
void _proceedToNextStep() {
|
||||
if (_currentStep < 2) {
|
||||
setState(() {
|
||||
_currentStep++;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Define your individual step widgets here
|
||||
|
||||
class StepCreateAccount extends StatefulWidget {
|
||||
final Function onNext;
|
||||
|
||||
const StepCreateAccount({Key? key, required this.onNext}) : super(key: key);
|
||||
|
||||
@override
|
||||
StepCreateAccountState createState() => StepCreateAccountState();
|
||||
}
|
||||
|
||||
class StepCreateAccountState extends State<StepCreateAccount> {
|
||||
// Add your state variables for this step here
|
||||
String? accountId;
|
||||
final Map<String, dynamic> formData = {};
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final SignUpApiService userService = SignUpApiService();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
alignment: Alignment.center,
|
||||
child: Column(
|
||||
children: [
|
||||
const Text('Step 1: Create Account'),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(labelText: 'Company Name'),
|
||||
onSaved: (value) => formData['companyName'] = value,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Company Name';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(labelText: 'Email'),
|
||||
onSaved: (value) => formData['email'] = value,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Email';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(labelText: 'Mobile No'),
|
||||
onSaved: (value) => formData['mobile'] = value,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Mob No';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(labelText: 'Workspace'),
|
||||
onSaved: (value) => formData['workspace'] = value,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Workspace';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(labelText: 'Gst Number'),
|
||||
onSaved: (value) => formData['gstNumber'] = value,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Gst Number';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(labelText: 'pancard'),
|
||||
onSaved: (value) => formData['pancard'] = value,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Pancard';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(labelText: 'Working'),
|
||||
onSaved: (value) => formData['working'] = value,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Working';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Container(
|
||||
margin: const EdgeInsets.symmetric(vertical: 5), // Add margin
|
||||
child: ElevatedButton(
|
||||
onPressed: () async {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
_formKey.currentState!.save();
|
||||
{
|
||||
try {
|
||||
print('form data is $formData');
|
||||
|
||||
final response =
|
||||
await userService.createAccount(formData);
|
||||
|
||||
accountId = response['account_id'].toString();
|
||||
print('after create account account id is $accountId');
|
||||
// ignore: use_build_context_synchronously
|
||||
// Navigator.pop(
|
||||
// _context, accountId); // Pop with account_id
|
||||
|
||||
// Navigator.pop(context);
|
||||
} catch (e) {
|
||||
// ignore: use_build_context_synchronously
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: const Text('Error'),
|
||||
content: Text('Account Creation Failed: $e'),
|
||||
actions: [
|
||||
TextButton(
|
||||
child: const Text('OK'),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
child: const SizedBox(
|
||||
width: double.infinity,
|
||||
height: 50,
|
||||
child: Center(
|
||||
child: Text(
|
||||
'SUBMIT',
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
if (accountId != null) Text('Selected Account ID: $accountId'),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class StepGetEmailVerification extends StatefulWidget {
|
||||
final Function onNext;
|
||||
|
||||
const StepGetEmailVerification({Key? key, required this.onNext})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
StepGetEmailVerificationState createState() =>
|
||||
StepGetEmailVerificationState();
|
||||
}
|
||||
|
||||
class StepGetEmailVerificationState extends State<StepGetEmailVerification> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
alignment: Alignment.center,
|
||||
child: Text('Step 2: Get Email Verification'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class StepGetRegistration extends StatefulWidget {
|
||||
final Function onNext;
|
||||
|
||||
const StepGetRegistration({Key? key, required this.onNext}) : super(key: key);
|
||||
|
||||
@override
|
||||
StepGetRegistrationState createState() => StepGetRegistrationState();
|
||||
}
|
||||
|
||||
class StepGetRegistrationState extends State<StepGetRegistration> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
alignment: Alignment.center,
|
||||
child: Text('Step 3: Get Registration'),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Example of a dialog to create an account
|
||||
class CreateAccountDialog extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text('Create Account'),
|
||||
content: Text('Account created successfully!'),
|
||||
actions: [
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop('12345'); // Pass the created account ID
|
||||
},
|
||||
child: Text('OK'),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,387 +1,387 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import '../../Utils/image_constant.dart';
|
||||
import '../../Utils/size_utils.dart';
|
||||
import '../../theme/app_style.dart';
|
||||
import '../../widgets/app_bar/appbar_image.dart';
|
||||
import '../../widgets/app_bar/appbar_title.dart';
|
||||
import '../../widgets/app_bar/custom_app_bar.dart';
|
||||
import '../../widgets/custom_button.dart';
|
||||
import '../../widgets/custom_text_form_field.dart';
|
||||
import '../Login Screen/login_screen.dart';
|
||||
import 'CreateAccount.dart';
|
||||
import 'SignUpService.dart';
|
||||
|
||||
class RegistrationDetailsScreen extends StatefulWidget {
|
||||
var email;
|
||||
RegistrationDetailsScreen({required this.email});
|
||||
|
||||
@override
|
||||
_RegistrationDetailsScreenState createState() =>
|
||||
_RegistrationDetailsScreenState();
|
||||
}
|
||||
|
||||
class _RegistrationDetailsScreenState extends State<RegistrationDetailsScreen> {
|
||||
final SignUpApiService userService = SignUpApiService();
|
||||
|
||||
final Map<String, dynamic> formData = {};
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
var account_id = null; // Initialize with null
|
||||
var selectedAccount; // Use nullable type
|
||||
|
||||
var newPassword = ''; // Store the value of the confirm password field
|
||||
var confirmPassword = ''; // Store the value of the confirm password field
|
||||
bool _isSubmitting = false;
|
||||
|
||||
late final FocusNode _firstNameNode;
|
||||
late final FocusNode _lastNameNode;
|
||||
late final FocusNode _mobileNode;
|
||||
late final FocusNode _newPasswordNode;
|
||||
late final FocusNode _confirmPasswordNode;
|
||||
// Validate that the passwords match
|
||||
String? _validatePasswordMatch(String value) {
|
||||
if (value != newPassword) {
|
||||
print('value is $value and new is $newPassword');
|
||||
return 'Passwords do not match';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
bool _newpasswordVisible = false;
|
||||
bool _confirmpasswordVisible = false;
|
||||
|
||||
bool _isPasswordValid = true;
|
||||
void _validatePassword(String password) {
|
||||
final valid = password.isNotEmpty;
|
||||
if (valid != _isPasswordValid) {
|
||||
setState(() {
|
||||
_isPasswordValid = valid;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
bool _isEmailValid = true;
|
||||
void _validateEmail(String email) {
|
||||
setState(() {
|
||||
_isEmailValid =
|
||||
RegExp(r'^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$').hasMatch(email);
|
||||
});
|
||||
}
|
||||
|
||||
void showSuccessMessage(String message) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(message),
|
||||
duration: const Duration(seconds: 2),
|
||||
backgroundColor: Colors.green,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void showErrorMessage(String error) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(error),
|
||||
duration: const Duration(seconds: 2),
|
||||
backgroundColor: Colors.red,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_firstNameNode = FocusNode();
|
||||
_lastNameNode = FocusNode();
|
||||
_mobileNode = FocusNode();
|
||||
_newPasswordNode = FocusNode();
|
||||
_confirmPasswordNode = FocusNode();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_firstNameNode.dispose();
|
||||
_lastNameNode.dispose();
|
||||
_mobileNode.dispose();
|
||||
_newPasswordNode.dispose();
|
||||
_confirmPasswordNode.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: CustomAppBar(
|
||||
height: getVerticalSize(54),
|
||||
leadingWidth: 40,
|
||||
leading: AppbarImage(
|
||||
height: getSize(24),
|
||||
width: getSize(24),
|
||||
svgPath: ImageConstant.imgArrowleft,
|
||||
margin: getMargin(left: 16, top: 13, bottom: 17),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
}),
|
||||
centerTitle: true,
|
||||
title: AppbarTitle(text: "Registration")),
|
||||
//AppBar(title: const Text('Registration')),
|
||||
body: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Text("First Name",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style:
|
||||
AppStyle.txtGilroyMedium16Bluegray900)),
|
||||
CustomTextFormField(
|
||||
focusNode: _firstNameNode,
|
||||
onsaved: (value) => formData['first_name'] = value,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter First Name';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
hintText: "enter First Name",
|
||||
margin: getMargin(top: 6),
|
||||
padding: TextFormFieldPadding.PaddingT12,
|
||||
textInputType: TextInputType.text
|
||||
),
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Text("Last Name",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style:
|
||||
AppStyle.txtGilroyMedium16Bluegray900)),
|
||||
CustomTextFormField(
|
||||
focusNode: _lastNameNode,
|
||||
onsaved: (value) => formData['last_name'] = value,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Last Name';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
hintText: "enter Last Name",
|
||||
margin: getMargin(top: 6),
|
||||
padding: TextFormFieldPadding.PaddingT12,
|
||||
textInputType: TextInputType.text
|
||||
),
|
||||
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Text("Mobile Number",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style:
|
||||
AppStyle.txtGilroyMedium16Bluegray900)),
|
||||
CustomTextFormField(
|
||||
focusNode: _mobileNode,
|
||||
textInputType: TextInputType.phone,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp(r'[0-9]'))
|
||||
],
|
||||
onsaved: (value) => formData['mob_no'] = value,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Mobile Number';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
hintText: "enter Mobile Number",
|
||||
margin: getMargin(top: 6),
|
||||
padding: TextFormFieldPadding.PaddingT12,
|
||||
),
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Text("New Password",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style:
|
||||
AppStyle.txtGilroyMedium16Bluegray900)),
|
||||
CustomTextFormField(
|
||||
focusNode: _newPasswordNode,
|
||||
hintText: "New Password",
|
||||
margin: getMargin(top: 6),
|
||||
padding: TextFormFieldPadding.PaddingT12,
|
||||
textInputAction: TextInputAction.done,
|
||||
textInputType:TextInputType.visiblePassword,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Password';
|
||||
}else if(!_isPasswordValid){
|
||||
return 'Please enter a valid password';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
suffix: IconButton(
|
||||
icon: Icon(
|
||||
_newpasswordVisible
|
||||
? Icons.visibility
|
||||
: Icons.visibility_off,
|
||||
),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_newpasswordVisible = !_newpasswordVisible;
|
||||
});
|
||||
},
|
||||
),
|
||||
onsaved: (value) => formData['new_password'] = value,
|
||||
onChanged: (value) {
|
||||
newPassword = value;
|
||||
_validatePassword(value);
|
||||
},
|
||||
suffixConstraints: BoxConstraints(
|
||||
maxHeight: getVerticalSize(44)),
|
||||
isObscureText: !_newpasswordVisible),
|
||||
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Text("Confirm Password",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style:
|
||||
AppStyle.txtGilroyMedium16Bluegray900)),
|
||||
CustomTextFormField(
|
||||
focusNode: _confirmPasswordNode,
|
||||
hintText: "Confirm Password",
|
||||
margin: getMargin(top: 6),
|
||||
padding: TextFormFieldPadding.PaddingT12,
|
||||
textInputAction: TextInputAction.done,
|
||||
textInputType:TextInputType.visiblePassword,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Password';
|
||||
}
|
||||
return _validatePasswordMatch(value);
|
||||
},
|
||||
onsaved: (value) => formData['confirm_password'] = value,
|
||||
onChanged: (value) {
|
||||
confirmPassword = value; // Update confirmPassword
|
||||
},
|
||||
suffix: IconButton(
|
||||
icon: Icon(
|
||||
_confirmpasswordVisible
|
||||
? Icons.visibility
|
||||
: Icons.visibility_off,
|
||||
),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_confirmpasswordVisible = !_confirmpasswordVisible;
|
||||
});
|
||||
},
|
||||
),
|
||||
suffixConstraints: BoxConstraints(
|
||||
maxHeight: getVerticalSize(44)),
|
||||
isObscureText: !_confirmpasswordVisible,),
|
||||
|
||||
|
||||
Row(
|
||||
children: [
|
||||
const Expanded(
|
||||
child: Text('Add Account'),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () async {
|
||||
final accountId = await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => CreateAccountScreen(),
|
||||
),
|
||||
);
|
||||
|
||||
if (accountId != null) {
|
||||
setState(() {
|
||||
selectedAccount = accountId;
|
||||
formData['account_id'] = accountId;
|
||||
account_id =
|
||||
accountId; // Update the account_id here
|
||||
});
|
||||
}
|
||||
},
|
||||
icon: const Icon(Icons.add),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
if (account_id == null)
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(top: 8),
|
||||
child: Text(
|
||||
'Tap + to create an account first, then SUBMIT will be enabled.',
|
||||
style: TextStyle(fontSize: 12, color: Colors.grey),
|
||||
),
|
||||
),
|
||||
|
||||
Container(
|
||||
margin:
|
||||
const EdgeInsets.symmetric(vertical: 5), // Add margin
|
||||
child: CustomButton(
|
||||
height: getVerticalSize(50),
|
||||
width: getHorizontalSize(396),
|
||||
text: _isSubmitting ? "PLEASE WAIT..." : "SUBMIT",
|
||||
margin: getMargin(top: 25),
|
||||
onTap: (account_id == null || _isSubmitting)
|
||||
? null
|
||||
: () async {
|
||||
final isValid =
|
||||
_formKey.currentState!.validate();
|
||||
if (!isValid) {
|
||||
showErrorMessage(
|
||||
'Please fix the red errors (check passwords match).');
|
||||
return;
|
||||
}
|
||||
_formKey.currentState!.save();
|
||||
|
||||
print('formdata is $formData');
|
||||
|
||||
formData['usrGrpId'] = 41;
|
||||
formData['account_id'] = account_id;
|
||||
formData['email'] = widget.email;
|
||||
|
||||
setState(() => _isSubmitting = true);
|
||||
try {
|
||||
print(formData);
|
||||
|
||||
await userService.createuser(formData);
|
||||
|
||||
if (!context.mounted) return;
|
||||
showSuccessMessage(
|
||||
'User created successfully');
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
const LoginScreen()),
|
||||
(route) => false);
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorMessage(
|
||||
'Failed to create User: $e');
|
||||
} finally {
|
||||
if (mounted) {
|
||||
setState(() => _isSubmitting = false);
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import '../../Utils/image_constant.dart';
|
||||
import '../../Utils/size_utils.dart';
|
||||
import '../../theme/app_style.dart';
|
||||
import '../../widgets/app_bar/appbar_image.dart';
|
||||
import '../../widgets/app_bar/appbar_title.dart';
|
||||
import '../../widgets/app_bar/custom_app_bar.dart';
|
||||
import '../../widgets/custom_button.dart';
|
||||
import '../../widgets/custom_text_form_field.dart';
|
||||
import '../Login Screen/login_screen.dart';
|
||||
import 'CreateAccount.dart';
|
||||
import 'SignUpService.dart';
|
||||
|
||||
class RegistrationDetailsScreen extends StatefulWidget {
|
||||
var email;
|
||||
RegistrationDetailsScreen({required this.email});
|
||||
|
||||
@override
|
||||
_RegistrationDetailsScreenState createState() =>
|
||||
_RegistrationDetailsScreenState();
|
||||
}
|
||||
|
||||
class _RegistrationDetailsScreenState extends State<RegistrationDetailsScreen> {
|
||||
final SignUpApiService userService = SignUpApiService();
|
||||
|
||||
final Map<String, dynamic> formData = {};
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
var account_id = null; // Initialize with null
|
||||
var selectedAccount; // Use nullable type
|
||||
|
||||
var newPassword = ''; // Store the value of the confirm password field
|
||||
var confirmPassword = ''; // Store the value of the confirm password field
|
||||
bool _isSubmitting = false;
|
||||
|
||||
late final FocusNode _firstNameNode;
|
||||
late final FocusNode _lastNameNode;
|
||||
late final FocusNode _mobileNode;
|
||||
late final FocusNode _newPasswordNode;
|
||||
late final FocusNode _confirmPasswordNode;
|
||||
// Validate that the passwords match
|
||||
String? _validatePasswordMatch(String value) {
|
||||
if (value != newPassword) {
|
||||
print('value is $value and new is $newPassword');
|
||||
return 'Passwords do not match';
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
bool _newpasswordVisible = false;
|
||||
bool _confirmpasswordVisible = false;
|
||||
|
||||
bool _isPasswordValid = true;
|
||||
void _validatePassword(String password) {
|
||||
final valid = password.isNotEmpty;
|
||||
if (valid != _isPasswordValid) {
|
||||
setState(() {
|
||||
_isPasswordValid = valid;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
bool _isEmailValid = true;
|
||||
void _validateEmail(String email) {
|
||||
setState(() {
|
||||
_isEmailValid =
|
||||
RegExp(r'^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$').hasMatch(email);
|
||||
});
|
||||
}
|
||||
|
||||
void showSuccessMessage(String message) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(message),
|
||||
duration: const Duration(seconds: 2),
|
||||
backgroundColor: Colors.green,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void showErrorMessage(String error) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(error),
|
||||
duration: const Duration(seconds: 2),
|
||||
backgroundColor: Colors.red,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_firstNameNode = FocusNode();
|
||||
_lastNameNode = FocusNode();
|
||||
_mobileNode = FocusNode();
|
||||
_newPasswordNode = FocusNode();
|
||||
_confirmPasswordNode = FocusNode();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_firstNameNode.dispose();
|
||||
_lastNameNode.dispose();
|
||||
_mobileNode.dispose();
|
||||
_newPasswordNode.dispose();
|
||||
_confirmPasswordNode.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: CustomAppBar(
|
||||
height: getVerticalSize(54),
|
||||
leadingWidth: 40,
|
||||
leading: AppbarImage(
|
||||
height: getSize(24),
|
||||
width: getSize(24),
|
||||
svgPath: ImageConstant.imgArrowleft,
|
||||
margin: getMargin(left: 16, top: 13, bottom: 17),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
}),
|
||||
centerTitle: true,
|
||||
title: AppbarTitle(text: "Registration")),
|
||||
//AppBar(title: const Text('Registration')),
|
||||
body: SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Text("First Name",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style:
|
||||
AppStyle.txtGilroyMedium16Bluegray900)),
|
||||
CustomTextFormField(
|
||||
focusNode: _firstNameNode,
|
||||
onsaved: (value) => formData['first_name'] = value,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter First Name';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
hintText: "enter First Name",
|
||||
margin: getMargin(top: 6),
|
||||
padding: TextFormFieldPadding.PaddingT12,
|
||||
textInputType: TextInputType.text
|
||||
),
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Text("Last Name",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style:
|
||||
AppStyle.txtGilroyMedium16Bluegray900)),
|
||||
CustomTextFormField(
|
||||
focusNode: _lastNameNode,
|
||||
onsaved: (value) => formData['last_name'] = value,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Last Name';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
hintText: "enter Last Name",
|
||||
margin: getMargin(top: 6),
|
||||
padding: TextFormFieldPadding.PaddingT12,
|
||||
textInputType: TextInputType.text
|
||||
),
|
||||
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Text("Mobile Number",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style:
|
||||
AppStyle.txtGilroyMedium16Bluegray900)),
|
||||
CustomTextFormField(
|
||||
focusNode: _mobileNode,
|
||||
textInputType: TextInputType.phone,
|
||||
inputFormatters: [
|
||||
FilteringTextInputFormatter.allow(RegExp(r'[0-9]'))
|
||||
],
|
||||
onsaved: (value) => formData['mob_no'] = value,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Mobile Number';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
hintText: "enter Mobile Number",
|
||||
margin: getMargin(top: 6),
|
||||
padding: TextFormFieldPadding.PaddingT12,
|
||||
),
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Text("New Password",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style:
|
||||
AppStyle.txtGilroyMedium16Bluegray900)),
|
||||
CustomTextFormField(
|
||||
focusNode: _newPasswordNode,
|
||||
hintText: "New Password",
|
||||
margin: getMargin(top: 6),
|
||||
padding: TextFormFieldPadding.PaddingT12,
|
||||
textInputAction: TextInputAction.done,
|
||||
textInputType:TextInputType.visiblePassword,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Password';
|
||||
}else if(!_isPasswordValid){
|
||||
return 'Please enter a valid password';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
suffix: IconButton(
|
||||
icon: Icon(
|
||||
_newpasswordVisible
|
||||
? Icons.visibility
|
||||
: Icons.visibility_off,
|
||||
),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_newpasswordVisible = !_newpasswordVisible;
|
||||
});
|
||||
},
|
||||
),
|
||||
onsaved: (value) => formData['new_password'] = value,
|
||||
onChanged: (value) {
|
||||
newPassword = value;
|
||||
_validatePassword(value);
|
||||
},
|
||||
suffixConstraints: BoxConstraints(
|
||||
maxHeight: getVerticalSize(44)),
|
||||
isObscureText: !_newpasswordVisible),
|
||||
|
||||
Padding(
|
||||
padding: getPadding(top: 19),
|
||||
child: Text("Confirm Password",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style:
|
||||
AppStyle.txtGilroyMedium16Bluegray900)),
|
||||
CustomTextFormField(
|
||||
focusNode: _confirmPasswordNode,
|
||||
hintText: "Confirm Password",
|
||||
margin: getMargin(top: 6),
|
||||
padding: TextFormFieldPadding.PaddingT12,
|
||||
textInputAction: TextInputAction.done,
|
||||
textInputType:TextInputType.visiblePassword,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Password';
|
||||
}
|
||||
return _validatePasswordMatch(value);
|
||||
},
|
||||
onsaved: (value) => formData['confirm_password'] = value,
|
||||
onChanged: (value) {
|
||||
confirmPassword = value; // Update confirmPassword
|
||||
},
|
||||
suffix: IconButton(
|
||||
icon: Icon(
|
||||
_confirmpasswordVisible
|
||||
? Icons.visibility
|
||||
: Icons.visibility_off,
|
||||
),
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
_confirmpasswordVisible = !_confirmpasswordVisible;
|
||||
});
|
||||
},
|
||||
),
|
||||
suffixConstraints: BoxConstraints(
|
||||
maxHeight: getVerticalSize(44)),
|
||||
isObscureText: !_confirmpasswordVisible,),
|
||||
|
||||
|
||||
Row(
|
||||
children: [
|
||||
const Expanded(
|
||||
child: Text('Add Account'),
|
||||
),
|
||||
IconButton(
|
||||
onPressed: () async {
|
||||
final accountId = await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => CreateAccountScreen(),
|
||||
),
|
||||
);
|
||||
|
||||
if (accountId != null) {
|
||||
setState(() {
|
||||
selectedAccount = accountId;
|
||||
formData['account_id'] = accountId;
|
||||
account_id =
|
||||
accountId; // Update the account_id here
|
||||
});
|
||||
}
|
||||
},
|
||||
icon: const Icon(Icons.add),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
if (account_id == null)
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(top: 8),
|
||||
child: Text(
|
||||
'Tap + to create an account first, then SUBMIT will be enabled.',
|
||||
style: TextStyle(fontSize: 12, color: Colors.grey),
|
||||
),
|
||||
),
|
||||
|
||||
Container(
|
||||
margin:
|
||||
const EdgeInsets.symmetric(vertical: 5), // Add margin
|
||||
child: CustomButton(
|
||||
height: getVerticalSize(50),
|
||||
width: getHorizontalSize(396),
|
||||
text: _isSubmitting ? "PLEASE WAIT..." : "SUBMIT",
|
||||
margin: getMargin(top: 25),
|
||||
onTap: (account_id == null || _isSubmitting)
|
||||
? null
|
||||
: () async {
|
||||
final isValid =
|
||||
_formKey.currentState!.validate();
|
||||
if (!isValid) {
|
||||
showErrorMessage(
|
||||
'Please fix the red errors (check passwords match).');
|
||||
return;
|
||||
}
|
||||
_formKey.currentState!.save();
|
||||
|
||||
print('formdata is $formData');
|
||||
|
||||
formData['usrGrpId'] = 41;
|
||||
formData['account_id'] = account_id;
|
||||
formData['email'] = widget.email;
|
||||
|
||||
setState(() => _isSubmitting = true);
|
||||
try {
|
||||
print(formData);
|
||||
|
||||
await userService.createuser(formData);
|
||||
|
||||
if (!context.mounted) return;
|
||||
showSuccessMessage(
|
||||
'User created successfully');
|
||||
Navigator.pushAndRemoveUntil(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
const LoginScreen()),
|
||||
(route) => false);
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
showErrorMessage(
|
||||
'Failed to create User: $e');
|
||||
} finally {
|
||||
if (mounted) {
|
||||
setState(() => _isSubmitting = false);
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,111 +1,111 @@
|
||||
import 'package:dio/dio.dart';
|
||||
|
||||
import '../../resources/api_constants.dart';
|
||||
|
||||
class SignUpApiService {
|
||||
final String baseUrl = ApiConstants.baseUrl;
|
||||
final Dio dio = Dio();
|
||||
|
||||
// get all account
|
||||
Future<List<Map<String, dynamic>>> getallAccount(String token) async {
|
||||
try {
|
||||
dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
final response = await dio.get('$baseUrl/users/sysaccount/sysaccount');
|
||||
|
||||
final responseData = response.data;
|
||||
|
||||
print('response data is ... $responseData');
|
||||
|
||||
if (responseData is List) {
|
||||
// If the response is a list, cast it to the expected type
|
||||
final entities = responseData.cast<Map<String, dynamic>>();
|
||||
return entities;
|
||||
} else if (responseData is Map<String, dynamic>) {
|
||||
// If the response is a single object, wrap it in a list
|
||||
return [responseData];
|
||||
} else {
|
||||
// Handle other unexpected response types here
|
||||
throw Exception('Unexpected response type');
|
||||
}
|
||||
} catch (e) {
|
||||
throw Exception('Failed to Account: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// Create account
|
||||
Future<Map<String, dynamic>> createAccount(
|
||||
Map<String, dynamic> entity) async {
|
||||
try {
|
||||
// dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
final response = await dio
|
||||
.post('$baseUrl/token/users/sysaccount/savesysaccount', data: entity);
|
||||
|
||||
print(' created account is $response');
|
||||
return response.data;
|
||||
} catch (e) {
|
||||
throw Exception('Failed To Create Account: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// SEND EMAIL FOR OTP
|
||||
Future<void> sendEmail(Map<String, dynamic> entity) async {
|
||||
try {
|
||||
print("in post api...$entity");
|
||||
// dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
await dio.post('$baseUrl/token/user/send_email', data: entity);
|
||||
print(entity);
|
||||
} catch (e) {
|
||||
throw Exception('Failed to Send Email: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// RESEND EMAIL FOR OTP
|
||||
Future<void> resendEmail(String email) async {
|
||||
try {
|
||||
// dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
await dio.post('$baseUrl/token/user/resend_otp?email=$email');
|
||||
} catch (e) {
|
||||
throw Exception('Failed to ReSend Email: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// OTP VEFICATION
|
||||
Future<void> otpverification(String email, String otp) async {
|
||||
try {
|
||||
// dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
await dio
|
||||
.post('$baseUrl/token/user/otp_verification?email=$email&otp=$otp');
|
||||
} catch (e) {
|
||||
throw Exception('Failed to Verify Otp: $e');
|
||||
}
|
||||
}
|
||||
Future<void> createuser(Map<String, dynamic> entity) async {
|
||||
try {
|
||||
print("in post api...$entity");
|
||||
await dio.post('$baseUrl/token/addOneAppUser', data: entity);
|
||||
print(entity);
|
||||
} catch (e) {
|
||||
throw Exception('Failed to create User: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> updateUser(
|
||||
String token, int entityId, Map<String, dynamic> entity) async {
|
||||
try {
|
||||
dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
await dio.put('$baseUrl/api/updateAppUserDto/$entityId', data: entity);
|
||||
print(entity);
|
||||
} catch (e) {
|
||||
throw Exception('Failed to update Backend: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> deleteUser(String token, int entityId) async {
|
||||
try {
|
||||
dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
await dio.delete('$baseUrl/api/delete_usr/$entityId');
|
||||
} catch (e) {
|
||||
throw Exception('Failed to delete User: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
import 'package:dio/dio.dart';
|
||||
|
||||
import '../../resources/api_constants.dart';
|
||||
|
||||
class SignUpApiService {
|
||||
final String baseUrl = ApiConstants.baseUrl;
|
||||
final Dio dio = Dio();
|
||||
|
||||
// get all account
|
||||
Future<List<Map<String, dynamic>>> getallAccount(String token) async {
|
||||
try {
|
||||
dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
final response = await dio.get('$baseUrl/users/sysaccount/sysaccount');
|
||||
|
||||
final responseData = response.data;
|
||||
|
||||
print('response data is ... $responseData');
|
||||
|
||||
if (responseData is List) {
|
||||
// If the response is a list, cast it to the expected type
|
||||
final entities = responseData.cast<Map<String, dynamic>>();
|
||||
return entities;
|
||||
} else if (responseData is Map<String, dynamic>) {
|
||||
// If the response is a single object, wrap it in a list
|
||||
return [responseData];
|
||||
} else {
|
||||
// Handle other unexpected response types here
|
||||
throw Exception('Unexpected response type');
|
||||
}
|
||||
} catch (e) {
|
||||
throw Exception('Failed to Account: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// Create account
|
||||
Future<Map<String, dynamic>> createAccount(
|
||||
Map<String, dynamic> entity) async {
|
||||
try {
|
||||
// dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
final response = await dio
|
||||
.post('$baseUrl/token/users/sysaccount/savesysaccount', data: entity);
|
||||
|
||||
print(' created account is $response');
|
||||
return response.data;
|
||||
} catch (e) {
|
||||
throw Exception('Failed To Create Account: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// SEND EMAIL FOR OTP
|
||||
Future<void> sendEmail(Map<String, dynamic> entity) async {
|
||||
try {
|
||||
print("in post api...$entity");
|
||||
// dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
await dio.post('$baseUrl/token/user/send_email', data: entity);
|
||||
print(entity);
|
||||
} catch (e) {
|
||||
throw Exception('Failed to Send Email: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// RESEND EMAIL FOR OTP
|
||||
Future<void> resendEmail(String email) async {
|
||||
try {
|
||||
// dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
await dio.post('$baseUrl/token/user/resend_otp?email=$email');
|
||||
} catch (e) {
|
||||
throw Exception('Failed to ReSend Email: $e');
|
||||
}
|
||||
}
|
||||
|
||||
// OTP VEFICATION
|
||||
Future<void> otpverification(String email, String otp) async {
|
||||
try {
|
||||
// dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
await dio
|
||||
.post('$baseUrl/token/user/otp_verification?email=$email&otp=$otp');
|
||||
} catch (e) {
|
||||
throw Exception('Failed to Verify Otp: $e');
|
||||
}
|
||||
}
|
||||
Future<void> createuser(Map<String, dynamic> entity) async {
|
||||
try {
|
||||
print("in post api...$entity");
|
||||
await dio.post('$baseUrl/token/addOneAppUser', data: entity);
|
||||
print(entity);
|
||||
} catch (e) {
|
||||
throw Exception('Failed to create User: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> updateUser(
|
||||
String token, int entityId, Map<String, dynamic> entity) async {
|
||||
try {
|
||||
dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
await dio.put('$baseUrl/api/updateAppUserDto/$entityId', data: entity);
|
||||
print(entity);
|
||||
} catch (e) {
|
||||
throw Exception('Failed to update Backend: $e');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> deleteUser(String token, int entityId) async {
|
||||
try {
|
||||
dio.options.headers['Authorization'] = 'Bearer $token';
|
||||
await dio.delete('$baseUrl/api/delete_usr/$entityId');
|
||||
} catch (e) {
|
||||
throw Exception('Failed to delete User: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,295 +1,295 @@
|
||||
// import 'package:flutter/material.dart';
|
||||
//
|
||||
// import 'package:flutter/services.dart';
|
||||
//
|
||||
// import 'RegistrationDetails.dart';
|
||||
// import 'SignUpService.dart';
|
||||
//
|
||||
// enum RegistrationStep {
|
||||
// SendOTP,
|
||||
// VerifyOTP,
|
||||
// EnterUserInfo,
|
||||
// SelectAccount,
|
||||
// }
|
||||
//
|
||||
// class SignUpUserScreen extends StatefulWidget {
|
||||
// SignUpUserScreen({Key? key}) : super(key: key);
|
||||
//
|
||||
// @override
|
||||
// _SignUpUserScreenState createState() => _SignUpUserScreenState();
|
||||
// }
|
||||
//
|
||||
// class _SignUpUserScreenState extends State<SignUpUserScreen> {
|
||||
// final SignUpApiService userService = SignUpApiService();
|
||||
//
|
||||
// final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
|
||||
// final Map<String, dynamic> formData = {};
|
||||
// final _formKey = GlobalKey<FormState>();
|
||||
//
|
||||
// var selectedAccount;
|
||||
// var email;
|
||||
// var otp;
|
||||
// var confirmPassword;
|
||||
//
|
||||
// bool _passwordVisible = false;
|
||||
// bool _isPasswordValid = true;
|
||||
// void _validatePassword(String password) {
|
||||
// setState(() {
|
||||
// _isPasswordValid = password.isNotEmpty;
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// RegistrationStep currentStep = RegistrationStep.SendOTP;
|
||||
//
|
||||
// void moveToNextStep() {
|
||||
// setState(() {
|
||||
// if (currentStep == RegistrationStep.SendOTP) {
|
||||
// currentStep = RegistrationStep.VerifyOTP;
|
||||
// } else if (currentStep == RegistrationStep.VerifyOTP) {
|
||||
// currentStep = RegistrationStep.EnterUserInfo;
|
||||
// } else if (currentStep == RegistrationStep.EnterUserInfo) {
|
||||
// currentStep = RegistrationStep.SelectAccount;
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// void showSuccessMessage(String message) {
|
||||
// ScaffoldMessenger.of(context).showSnackBar(
|
||||
// SnackBar(
|
||||
// content: Text(message),
|
||||
// duration: const Duration(seconds: 2),
|
||||
// backgroundColor: Colors.green,
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// void showErrorMessage(String error) {
|
||||
// ScaffoldMessenger.of(context).showSnackBar(
|
||||
// SnackBar(
|
||||
// content: Text(error),
|
||||
// duration: const Duration(seconds: 2),
|
||||
// backgroundColor: Colors.red,
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// return Scaffold(
|
||||
// key: _scaffoldKey,
|
||||
// appBar: AppBar(
|
||||
// title: const Text('Create User'),
|
||||
// ),
|
||||
// body: Builder(
|
||||
// builder: (BuildContext context) {
|
||||
// return SingleChildScrollView(
|
||||
// child: Padding(
|
||||
// padding: const EdgeInsets.all(16),
|
||||
// child: Form(
|
||||
// key: _formKey,
|
||||
// child: SizedBox(
|
||||
// height: MediaQuery.of(context).size.height *
|
||||
// 0.5, // Use 50% of the screen height
|
||||
// child: ListView.builder(
|
||||
// itemCount: 1,
|
||||
// itemBuilder: (BuildContext context, int index) {
|
||||
// if (currentStep == RegistrationStep.SendOTP) {
|
||||
// return Column(
|
||||
// children: [
|
||||
// const SizedBox(height: 16),
|
||||
// TextFormField(
|
||||
// decoration:
|
||||
// const InputDecoration(labelText: 'Email'),
|
||||
// keyboardType: TextInputType.emailAddress,
|
||||
// onSaved: (value) => email = value,
|
||||
// validator: (value) {
|
||||
// if (value == null || value.isEmpty) {
|
||||
// return 'Please enter Email';
|
||||
// }
|
||||
// return null;
|
||||
// },
|
||||
// ),
|
||||
// const SizedBox(height: 16),
|
||||
// Container(
|
||||
// margin: const EdgeInsets.symmetric(vertical: 5),
|
||||
// child: ElevatedButton(
|
||||
// onPressed: () async {
|
||||
// if (_formKey.currentState!.validate()) {
|
||||
// _formKey.currentState!.save();
|
||||
//
|
||||
// formData['usrGrpId'] = 46;
|
||||
// formData['email'] = email;
|
||||
// try {
|
||||
// print('send email data is $formData');
|
||||
//
|
||||
// await userService.sendEmail(formData);
|
||||
//
|
||||
// await Future.delayed(
|
||||
// const Duration(seconds: 2));
|
||||
//
|
||||
// moveToNextStep();
|
||||
// } catch (e) {
|
||||
// showErrorMessage(
|
||||
// 'Failed to send OTP: $e');
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// child: const SizedBox(
|
||||
// width: double.infinity,
|
||||
// height: 50,
|
||||
// child: Center(
|
||||
// child: Text(
|
||||
// 'Send OTP',
|
||||
// style: TextStyle(
|
||||
// fontSize: 16,
|
||||
// fontWeight: FontWeight.w600,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
// } else if (currentStep == RegistrationStep.VerifyOTP) {
|
||||
// return Column(
|
||||
// children: [
|
||||
// const SizedBox(height: 16),
|
||||
// TextFormField(
|
||||
// decoration:
|
||||
// const InputDecoration(labelText: 'Email'),
|
||||
// initialValue: email,
|
||||
// readOnly: true,
|
||||
// ),
|
||||
// const SizedBox(height: 16),
|
||||
// Row(
|
||||
// children: [
|
||||
// Container(
|
||||
// height: 100,
|
||||
// width: 250,
|
||||
// padding: const EdgeInsets.symmetric(
|
||||
// horizontal: 16),
|
||||
// decoration: BoxDecoration(
|
||||
// borderRadius: BorderRadius.circular(10),
|
||||
// border: Border.all(color: Colors.grey),
|
||||
// ),
|
||||
// child: TextFormField(
|
||||
// decoration:
|
||||
// const InputDecoration(labelText: 'OTP'),
|
||||
// onChanged: (value) {
|
||||
// otp = value;
|
||||
// },
|
||||
// onSaved: (value) => otp = value,
|
||||
// validator: (value) {
|
||||
// if (value == null || value.isEmpty) {
|
||||
// return 'Please enter OTP';
|
||||
// }
|
||||
// return null;
|
||||
// },
|
||||
// ),
|
||||
// ),
|
||||
// ElevatedButton(
|
||||
// onPressed: () async {
|
||||
// try {
|
||||
// await userService.resendEmail(email);
|
||||
//
|
||||
// await Future.delayed(
|
||||
// const Duration(seconds: 5));
|
||||
// showSuccessMessage('OTP RESEND');
|
||||
// } catch (e) {
|
||||
// showErrorMessage(
|
||||
// 'Failed to resend OTP: $e');
|
||||
// }
|
||||
// },
|
||||
// child: const SizedBox(
|
||||
// width: 100,
|
||||
// height: 50,
|
||||
// child: Center(
|
||||
// child: Text(
|
||||
// 'Resend OTP',
|
||||
// style: TextStyle(
|
||||
// fontSize: 16,
|
||||
// fontWeight: FontWeight.w600,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// const SizedBox(height: 16),
|
||||
// ElevatedButton(
|
||||
// onPressed: () async {
|
||||
// try {
|
||||
// print('email is $email and otp is $otp');
|
||||
// await userService.otpverification(email, otp);
|
||||
//
|
||||
// moveToNextStep();
|
||||
// showSuccessMessage(
|
||||
// 'Email verified successfully');
|
||||
// } catch (e) {
|
||||
// showErrorMessage('Failed to verify OTP: $e');
|
||||
// }
|
||||
// },
|
||||
// child: const SizedBox(
|
||||
// width: double.infinity,
|
||||
// height: 50,
|
||||
// child: Center(
|
||||
// child: Text(
|
||||
// 'VERIFY EMAIL',
|
||||
// style: TextStyle(
|
||||
// fontSize: 16,
|
||||
// fontWeight: FontWeight.w600,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
// } else if (currentStep ==
|
||||
// RegistrationStep.EnterUserInfo) {
|
||||
// return Column(
|
||||
// children: [
|
||||
// // Other widgets for user information entry
|
||||
// ElevatedButton(
|
||||
// onPressed: () async {
|
||||
// // Navigate to the RegistrationDetailsScreen when the button is pressed
|
||||
// Navigator.push(
|
||||
// context,
|
||||
// MaterialPageRoute(
|
||||
// builder: (context) =>
|
||||
// RegistrationDetailsScreen(email: email),
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
// child: const SizedBox(
|
||||
// width: double.infinity,
|
||||
// height: 50,
|
||||
// child: Center(
|
||||
// child: Text(
|
||||
// 'Go to Registration Details',
|
||||
// style: TextStyle(
|
||||
// fontSize: 16,
|
||||
// fontWeight: FontWeight.w600,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
// } else {
|
||||
// return Container(); // Return an empty container if none of the conditions match
|
||||
// }
|
||||
// },
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
// import 'package:flutter/material.dart';
|
||||
//
|
||||
// import 'package:flutter/services.dart';
|
||||
//
|
||||
// import 'RegistrationDetails.dart';
|
||||
// import 'SignUpService.dart';
|
||||
//
|
||||
// enum RegistrationStep {
|
||||
// SendOTP,
|
||||
// VerifyOTP,
|
||||
// EnterUserInfo,
|
||||
// SelectAccount,
|
||||
// }
|
||||
//
|
||||
// class SignUpUserScreen extends StatefulWidget {
|
||||
// SignUpUserScreen({Key? key}) : super(key: key);
|
||||
//
|
||||
// @override
|
||||
// _SignUpUserScreenState createState() => _SignUpUserScreenState();
|
||||
// }
|
||||
//
|
||||
// class _SignUpUserScreenState extends State<SignUpUserScreen> {
|
||||
// final SignUpApiService userService = SignUpApiService();
|
||||
//
|
||||
// final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
|
||||
// final Map<String, dynamic> formData = {};
|
||||
// final _formKey = GlobalKey<FormState>();
|
||||
//
|
||||
// var selectedAccount;
|
||||
// var email;
|
||||
// var otp;
|
||||
// var confirmPassword;
|
||||
//
|
||||
// bool _passwordVisible = false;
|
||||
// bool _isPasswordValid = true;
|
||||
// void _validatePassword(String password) {
|
||||
// setState(() {
|
||||
// _isPasswordValid = password.isNotEmpty;
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// RegistrationStep currentStep = RegistrationStep.SendOTP;
|
||||
//
|
||||
// void moveToNextStep() {
|
||||
// setState(() {
|
||||
// if (currentStep == RegistrationStep.SendOTP) {
|
||||
// currentStep = RegistrationStep.VerifyOTP;
|
||||
// } else if (currentStep == RegistrationStep.VerifyOTP) {
|
||||
// currentStep = RegistrationStep.EnterUserInfo;
|
||||
// } else if (currentStep == RegistrationStep.EnterUserInfo) {
|
||||
// currentStep = RegistrationStep.SelectAccount;
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// void showSuccessMessage(String message) {
|
||||
// ScaffoldMessenger.of(context).showSnackBar(
|
||||
// SnackBar(
|
||||
// content: Text(message),
|
||||
// duration: const Duration(seconds: 2),
|
||||
// backgroundColor: Colors.green,
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// void showErrorMessage(String error) {
|
||||
// ScaffoldMessenger.of(context).showSnackBar(
|
||||
// SnackBar(
|
||||
// content: Text(error),
|
||||
// duration: const Duration(seconds: 2),
|
||||
// backgroundColor: Colors.red,
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// @override
|
||||
// Widget build(BuildContext context) {
|
||||
// return Scaffold(
|
||||
// key: _scaffoldKey,
|
||||
// appBar: AppBar(
|
||||
// title: const Text('Create User'),
|
||||
// ),
|
||||
// body: Builder(
|
||||
// builder: (BuildContext context) {
|
||||
// return SingleChildScrollView(
|
||||
// child: Padding(
|
||||
// padding: const EdgeInsets.all(16),
|
||||
// child: Form(
|
||||
// key: _formKey,
|
||||
// child: SizedBox(
|
||||
// height: MediaQuery.of(context).size.height *
|
||||
// 0.5, // Use 50% of the screen height
|
||||
// child: ListView.builder(
|
||||
// itemCount: 1,
|
||||
// itemBuilder: (BuildContext context, int index) {
|
||||
// if (currentStep == RegistrationStep.SendOTP) {
|
||||
// return Column(
|
||||
// children: [
|
||||
// const SizedBox(height: 16),
|
||||
// TextFormField(
|
||||
// decoration:
|
||||
// const InputDecoration(labelText: 'Email'),
|
||||
// keyboardType: TextInputType.emailAddress,
|
||||
// onSaved: (value) => email = value,
|
||||
// validator: (value) {
|
||||
// if (value == null || value.isEmpty) {
|
||||
// return 'Please enter Email';
|
||||
// }
|
||||
// return null;
|
||||
// },
|
||||
// ),
|
||||
// const SizedBox(height: 16),
|
||||
// Container(
|
||||
// margin: const EdgeInsets.symmetric(vertical: 5),
|
||||
// child: ElevatedButton(
|
||||
// onPressed: () async {
|
||||
// if (_formKey.currentState!.validate()) {
|
||||
// _formKey.currentState!.save();
|
||||
//
|
||||
// formData['usrGrpId'] = 46;
|
||||
// formData['email'] = email;
|
||||
// try {
|
||||
// print('send email data is $formData');
|
||||
//
|
||||
// await userService.sendEmail(formData);
|
||||
//
|
||||
// await Future.delayed(
|
||||
// const Duration(seconds: 2));
|
||||
//
|
||||
// moveToNextStep();
|
||||
// } catch (e) {
|
||||
// showErrorMessage(
|
||||
// 'Failed to send OTP: $e');
|
||||
// }
|
||||
// }
|
||||
// },
|
||||
// child: const SizedBox(
|
||||
// width: double.infinity,
|
||||
// height: 50,
|
||||
// child: Center(
|
||||
// child: Text(
|
||||
// 'Send OTP',
|
||||
// style: TextStyle(
|
||||
// fontSize: 16,
|
||||
// fontWeight: FontWeight.w600,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
// } else if (currentStep == RegistrationStep.VerifyOTP) {
|
||||
// return Column(
|
||||
// children: [
|
||||
// const SizedBox(height: 16),
|
||||
// TextFormField(
|
||||
// decoration:
|
||||
// const InputDecoration(labelText: 'Email'),
|
||||
// initialValue: email,
|
||||
// readOnly: true,
|
||||
// ),
|
||||
// const SizedBox(height: 16),
|
||||
// Row(
|
||||
// children: [
|
||||
// Container(
|
||||
// height: 100,
|
||||
// width: 250,
|
||||
// padding: const EdgeInsets.symmetric(
|
||||
// horizontal: 16),
|
||||
// decoration: BoxDecoration(
|
||||
// borderRadius: BorderRadius.circular(10),
|
||||
// border: Border.all(color: Colors.grey),
|
||||
// ),
|
||||
// child: TextFormField(
|
||||
// decoration:
|
||||
// const InputDecoration(labelText: 'OTP'),
|
||||
// onChanged: (value) {
|
||||
// otp = value;
|
||||
// },
|
||||
// onSaved: (value) => otp = value,
|
||||
// validator: (value) {
|
||||
// if (value == null || value.isEmpty) {
|
||||
// return 'Please enter OTP';
|
||||
// }
|
||||
// return null;
|
||||
// },
|
||||
// ),
|
||||
// ),
|
||||
// ElevatedButton(
|
||||
// onPressed: () async {
|
||||
// try {
|
||||
// await userService.resendEmail(email);
|
||||
//
|
||||
// await Future.delayed(
|
||||
// const Duration(seconds: 5));
|
||||
// showSuccessMessage('OTP RESEND');
|
||||
// } catch (e) {
|
||||
// showErrorMessage(
|
||||
// 'Failed to resend OTP: $e');
|
||||
// }
|
||||
// },
|
||||
// child: const SizedBox(
|
||||
// width: 100,
|
||||
// height: 50,
|
||||
// child: Center(
|
||||
// child: Text(
|
||||
// 'Resend OTP',
|
||||
// style: TextStyle(
|
||||
// fontSize: 16,
|
||||
// fontWeight: FontWeight.w600,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// const SizedBox(height: 16),
|
||||
// ElevatedButton(
|
||||
// onPressed: () async {
|
||||
// try {
|
||||
// print('email is $email and otp is $otp');
|
||||
// await userService.otpverification(email, otp);
|
||||
//
|
||||
// moveToNextStep();
|
||||
// showSuccessMessage(
|
||||
// 'Email verified successfully');
|
||||
// } catch (e) {
|
||||
// showErrorMessage('Failed to verify OTP: $e');
|
||||
// }
|
||||
// },
|
||||
// child: const SizedBox(
|
||||
// width: double.infinity,
|
||||
// height: 50,
|
||||
// child: Center(
|
||||
// child: Text(
|
||||
// 'VERIFY EMAIL',
|
||||
// style: TextStyle(
|
||||
// fontSize: 16,
|
||||
// fontWeight: FontWeight.w600,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
// } else if (currentStep ==
|
||||
// RegistrationStep.EnterUserInfo) {
|
||||
// return Column(
|
||||
// children: [
|
||||
// // Other widgets for user information entry
|
||||
// ElevatedButton(
|
||||
// onPressed: () async {
|
||||
// // Navigate to the RegistrationDetailsScreen when the button is pressed
|
||||
// Navigator.push(
|
||||
// context,
|
||||
// MaterialPageRoute(
|
||||
// builder: (context) =>
|
||||
// RegistrationDetailsScreen(email: email),
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
// child: const SizedBox(
|
||||
// width: double.infinity,
|
||||
// height: 50,
|
||||
// child: Center(
|
||||
// child: Text(
|
||||
// 'Go to Registration Details',
|
||||
// style: TextStyle(
|
||||
// fontSize: 16,
|
||||
// fontWeight: FontWeight.w600,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
// } else {
|
||||
// return Container(); // Return an empty container if none of the conditions match
|
||||
// }
|
||||
// },
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// );
|
||||
// },
|
||||
// ),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -1,138 +1,138 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class StepGetEmailVerification extends StatefulWidget {
|
||||
final LabeledGlobalKey<FormState> emailPasswordFormKey;
|
||||
// final Function updateSignUpDetails;
|
||||
|
||||
// final String email;
|
||||
final Function proceedToNextStep;
|
||||
const StepGetEmailVerification(
|
||||
{Key? key,
|
||||
// required this.updateSignUpDetails,
|
||||
// required this.email,
|
||||
required this.emailPasswordFormKey,
|
||||
required this.proceedToNextStep})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
_StepGetEmailVerificationState createState() =>
|
||||
_StepGetEmailVerificationState();
|
||||
}
|
||||
|
||||
class _StepGetEmailVerificationState extends State<StepGetEmailVerification> {
|
||||
String email = "";
|
||||
String emailErrorMessage = "";
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// email = widget.email;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// widget.emailPasswordFormKey.currentState?.validate();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Form(
|
||||
key: widget.emailPasswordFormKey,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
width: double.infinity,
|
||||
margin: const EdgeInsets.all(5),
|
||||
padding: const EdgeInsets.all(5),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
border:
|
||||
Border.all(width: 1.0, color: const Color(0xFFF5F7FA)),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
boxShadow: [
|
||||
const BoxShadow(
|
||||
blurRadius: 6.18,
|
||||
spreadRadius: 0.618,
|
||||
offset: Offset(-4, -4),
|
||||
color: Colors.white38),
|
||||
BoxShadow(
|
||||
blurRadius: 6.18,
|
||||
spreadRadius: 0.618,
|
||||
offset: const Offset(4, 4),
|
||||
color: Colors.blueGrey.shade100)
|
||||
]),
|
||||
child: TextFormField(
|
||||
// initialValue: email,
|
||||
// validator: _validateNewPassword,
|
||||
autofocus: mounted,
|
||||
autocorrect: false,
|
||||
decoration: const InputDecoration(
|
||||
fillColor: Colors.white,
|
||||
border: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
errorBorder: InputBorder.none,
|
||||
disabledBorder: InputBorder.none,
|
||||
contentPadding:
|
||||
EdgeInsets.only(left: 15, bottom: 11, top: 11, right: 15),
|
||||
hintText: "email",
|
||||
hintStyle: TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
|
||||
),
|
||||
style: const TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
|
||||
keyboardType: TextInputType.name,
|
||||
textInputAction: TextInputAction.next,
|
||||
),
|
||||
),
|
||||
if (emailErrorMessage != '')
|
||||
Container(
|
||||
margin: const EdgeInsets.all(2),
|
||||
padding: const EdgeInsets.all(2),
|
||||
width: double.infinity,
|
||||
child: Text(
|
||||
"\t\t\t\t$emailErrorMessage",
|
||||
style: const TextStyle(fontSize: 10, color: Colors.red),
|
||||
),
|
||||
),
|
||||
// Email CODE END HERE
|
||||
],
|
||||
));
|
||||
}
|
||||
|
||||
// void errorMessageSetter(String fieldName, String message) {
|
||||
// setState(() {
|
||||
// switch (fieldName) {
|
||||
// case 'NEW-PASSWORD':
|
||||
// new_passwordErrorMessage = message;
|
||||
// break;
|
||||
|
||||
// case 'CONFIRM-PASSWORD':
|
||||
// confirm_passwordErrorMessage = message;
|
||||
// break;
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
// String? _validateNewPassword(String? value) {
|
||||
// if (value == null || value.isEmpty) {
|
||||
// errorMessageSetter('NEW-PASSWORD', 'password cannot be empty');
|
||||
// } else {
|
||||
// errorMessageSetter('NEW-PASSWORD', "");
|
||||
|
||||
// widget.updateSignUpDetails('new_password', value);
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
|
||||
// String? _validateConfirmpassword(String? value) {
|
||||
// if (value == null || value.isEmpty) {
|
||||
// errorMessageSetter(
|
||||
// 'CONFIRM-PASSWORD', 'you must provide a valid confirm-password');
|
||||
// } else {
|
||||
// errorMessageSetter('CONFIRM-PASSWORD', "");
|
||||
// widget.updateSignUpDetails('confirm_password', value);
|
||||
// }
|
||||
|
||||
// return null;
|
||||
// }
|
||||
}
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class StepGetEmailVerification extends StatefulWidget {
|
||||
final LabeledGlobalKey<FormState> emailPasswordFormKey;
|
||||
// final Function updateSignUpDetails;
|
||||
|
||||
// final String email;
|
||||
final Function proceedToNextStep;
|
||||
const StepGetEmailVerification(
|
||||
{Key? key,
|
||||
// required this.updateSignUpDetails,
|
||||
// required this.email,
|
||||
required this.emailPasswordFormKey,
|
||||
required this.proceedToNextStep})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
_StepGetEmailVerificationState createState() =>
|
||||
_StepGetEmailVerificationState();
|
||||
}
|
||||
|
||||
class _StepGetEmailVerificationState extends State<StepGetEmailVerification> {
|
||||
String email = "";
|
||||
String emailErrorMessage = "";
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
// email = widget.email;
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// widget.emailPasswordFormKey.currentState?.validate();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Form(
|
||||
key: widget.emailPasswordFormKey,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
width: double.infinity,
|
||||
margin: const EdgeInsets.all(5),
|
||||
padding: const EdgeInsets.all(5),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
border:
|
||||
Border.all(width: 1.0, color: const Color(0xFFF5F7FA)),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
boxShadow: [
|
||||
const BoxShadow(
|
||||
blurRadius: 6.18,
|
||||
spreadRadius: 0.618,
|
||||
offset: Offset(-4, -4),
|
||||
color: Colors.white38),
|
||||
BoxShadow(
|
||||
blurRadius: 6.18,
|
||||
spreadRadius: 0.618,
|
||||
offset: const Offset(4, 4),
|
||||
color: Colors.blueGrey.shade100)
|
||||
]),
|
||||
child: TextFormField(
|
||||
// initialValue: email,
|
||||
// validator: _validateNewPassword,
|
||||
autofocus: mounted,
|
||||
autocorrect: false,
|
||||
decoration: const InputDecoration(
|
||||
fillColor: Colors.white,
|
||||
border: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
errorBorder: InputBorder.none,
|
||||
disabledBorder: InputBorder.none,
|
||||
contentPadding:
|
||||
EdgeInsets.only(left: 15, bottom: 11, top: 11, right: 15),
|
||||
hintText: "email",
|
||||
hintStyle: TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
|
||||
),
|
||||
style: const TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
|
||||
keyboardType: TextInputType.name,
|
||||
textInputAction: TextInputAction.next,
|
||||
),
|
||||
),
|
||||
if (emailErrorMessage != '')
|
||||
Container(
|
||||
margin: const EdgeInsets.all(2),
|
||||
padding: const EdgeInsets.all(2),
|
||||
width: double.infinity,
|
||||
child: Text(
|
||||
"\t\t\t\t$emailErrorMessage",
|
||||
style: const TextStyle(fontSize: 10, color: Colors.red),
|
||||
),
|
||||
),
|
||||
// Email CODE END HERE
|
||||
],
|
||||
));
|
||||
}
|
||||
|
||||
// void errorMessageSetter(String fieldName, String message) {
|
||||
// setState(() {
|
||||
// switch (fieldName) {
|
||||
// case 'NEW-PASSWORD':
|
||||
// new_passwordErrorMessage = message;
|
||||
// break;
|
||||
|
||||
// case 'CONFIRM-PASSWORD':
|
||||
// confirm_passwordErrorMessage = message;
|
||||
// break;
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
// String? _validateNewPassword(String? value) {
|
||||
// if (value == null || value.isEmpty) {
|
||||
// errorMessageSetter('NEW-PASSWORD', 'password cannot be empty');
|
||||
// } else {
|
||||
// errorMessageSetter('NEW-PASSWORD', "");
|
||||
|
||||
// widget.updateSignUpDetails('new_password', value);
|
||||
// }
|
||||
// return null;
|
||||
// }
|
||||
|
||||
// String? _validateConfirmpassword(String? value) {
|
||||
// if (value == null || value.isEmpty) {
|
||||
// errorMessageSetter(
|
||||
// 'CONFIRM-PASSWORD', 'you must provide a valid confirm-password');
|
||||
// } else {
|
||||
// errorMessageSetter('CONFIRM-PASSWORD', "");
|
||||
// widget.updateSignUpDetails('confirm_password', value);
|
||||
// }
|
||||
|
||||
// return null;
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -1,393 +1,393 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class StepGetRegistration extends StatefulWidget {
|
||||
final LabeledGlobalKey<FormState> bankAccountFormKey;
|
||||
// final Function updateSignUpDetails;
|
||||
final Function showConfirmSignUpButton;
|
||||
final Function registrationDetails;
|
||||
final Function finalStepProccessing;
|
||||
const StepGetRegistration(
|
||||
{Key? key,
|
||||
// required this.updateSignUpDetails,
|
||||
required this.registrationDetails,
|
||||
required this.bankAccountFormKey,
|
||||
required this.showConfirmSignUpButton,
|
||||
required this.finalStepProccessing})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
_StepGetRegistrationState createState() => _StepGetRegistrationState();
|
||||
}
|
||||
|
||||
class _StepGetRegistrationState extends State<StepGetRegistration> {
|
||||
String firstname = "";
|
||||
String firstnameErrorMessage = "";
|
||||
|
||||
String lastName = "";
|
||||
String lastNameErrorMessage = "";
|
||||
|
||||
String mobNo = "";
|
||||
String mobNoErrorMessage = "";
|
||||
|
||||
String password = "";
|
||||
String passwordErrorMessage = "";
|
||||
|
||||
String confirmPassword = "";
|
||||
String confirmPasswordErrorMessage = "";
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
Map<String, String> signUpDetails = widget.registrationDetails();
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
firstname = signUpDetails['first_name']!;
|
||||
lastName = signUpDetails['last_name']!;
|
||||
mobNo = signUpDetails['mob_no']!;
|
||||
password = signUpDetails['new_password']!;
|
||||
confirmPassword = signUpDetails['confirm_password']!;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// widget.bankAccountFormKey.currentState?.validate();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Form(
|
||||
key: widget.bankAccountFormKey,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
width: double.infinity,
|
||||
margin: const EdgeInsets.all(5),
|
||||
padding: const EdgeInsets.all(5),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
border:
|
||||
Border.all(width: 1.0, color: const Color(0xFFF5F7FA)),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
boxShadow: [
|
||||
const BoxShadow(
|
||||
blurRadius: 6.18,
|
||||
spreadRadius: 0.618,
|
||||
offset: Offset(-4, -4),
|
||||
color: Colors.white38),
|
||||
BoxShadow(
|
||||
blurRadius: 6.18,
|
||||
spreadRadius: 0.618,
|
||||
offset: const Offset(4, 4),
|
||||
color: Colors.blueGrey.shade100)
|
||||
]),
|
||||
child: TextFormField(
|
||||
initialValue: firstname,
|
||||
onChanged: _toggleSignUpButtonVisibility,
|
||||
// validator: _validateEmailId,
|
||||
autofocus: mounted,
|
||||
autocorrect: false,
|
||||
onFieldSubmitted: (value) {
|
||||
if (value.isNotEmpty) {
|
||||
widget.finalStepProccessing();
|
||||
}
|
||||
},
|
||||
decoration: const InputDecoration(
|
||||
fillColor: Colors.white,
|
||||
border: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
errorBorder: InputBorder.none,
|
||||
disabledBorder: InputBorder.none,
|
||||
contentPadding:
|
||||
EdgeInsets.only(left: 15, bottom: 11, top: 11, right: 15),
|
||||
hintText: "first name",
|
||||
hintStyle: TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
|
||||
),
|
||||
style: const TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
|
||||
),
|
||||
),
|
||||
if (firstnameErrorMessage != '')
|
||||
Container(
|
||||
margin: const EdgeInsets.all(2),
|
||||
padding: const EdgeInsets.all(2),
|
||||
child: Text(
|
||||
"\t\t\t\t$firstnameErrorMessage",
|
||||
style: const TextStyle(fontSize: 10, color: Colors.red),
|
||||
),
|
||||
),
|
||||
|
||||
// first name code end here
|
||||
|
||||
Container(
|
||||
width: double.infinity,
|
||||
margin: const EdgeInsets.all(5),
|
||||
padding: const EdgeInsets.all(5),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
border:
|
||||
Border.all(width: 1.0, color: const Color(0xFFF5F7FA)),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
boxShadow: [
|
||||
const BoxShadow(
|
||||
blurRadius: 6.18,
|
||||
spreadRadius: 0.618,
|
||||
offset: Offset(-4, -4),
|
||||
color: Colors.white38),
|
||||
BoxShadow(
|
||||
blurRadius: 6.18,
|
||||
spreadRadius: 0.618,
|
||||
offset: const Offset(4, 4),
|
||||
color: Colors.blueGrey.shade100)
|
||||
]),
|
||||
child: TextFormField(
|
||||
initialValue: lastName,
|
||||
onChanged: _toggleSignUpButtonVisibility,
|
||||
// validator: _validateEmailId,
|
||||
autofocus: mounted,
|
||||
autocorrect: false,
|
||||
onFieldSubmitted: (value) {
|
||||
if (value.isNotEmpty) {
|
||||
widget.finalStepProccessing();
|
||||
}
|
||||
},
|
||||
decoration: const InputDecoration(
|
||||
fillColor: Colors.white,
|
||||
border: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
errorBorder: InputBorder.none,
|
||||
disabledBorder: InputBorder.none,
|
||||
contentPadding:
|
||||
EdgeInsets.only(left: 15, bottom: 11, top: 11, right: 15),
|
||||
hintText: "last name",
|
||||
hintStyle: TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
|
||||
),
|
||||
style: const TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
|
||||
),
|
||||
),
|
||||
if (lastNameErrorMessage != '')
|
||||
Container(
|
||||
margin: const EdgeInsets.all(2),
|
||||
padding: const EdgeInsets.all(2),
|
||||
child: Text(
|
||||
"\t\t\t\t$lastNameErrorMessage",
|
||||
style: const TextStyle(fontSize: 10, color: Colors.red),
|
||||
),
|
||||
),
|
||||
|
||||
// last name code
|
||||
|
||||
Container(
|
||||
width: double.infinity,
|
||||
margin: const EdgeInsets.all(5),
|
||||
padding: const EdgeInsets.all(5),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
border:
|
||||
Border.all(width: 1.0, color: const Color(0xFFF5F7FA)),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
boxShadow: [
|
||||
const BoxShadow(
|
||||
blurRadius: 6.18,
|
||||
spreadRadius: 0.618,
|
||||
offset: Offset(-4, -4),
|
||||
color: Colors.white38),
|
||||
BoxShadow(
|
||||
blurRadius: 6.18,
|
||||
spreadRadius: 0.618,
|
||||
offset: const Offset(4, 4),
|
||||
color: Colors.blueGrey.shade100)
|
||||
]),
|
||||
child: TextFormField(
|
||||
initialValue: mobNo,
|
||||
onChanged: _toggleSignUpButtonVisibility,
|
||||
// validator: _validateEmailId,
|
||||
autofocus: mounted,
|
||||
autocorrect: false,
|
||||
onFieldSubmitted: (value) {
|
||||
if (value.isNotEmpty) {
|
||||
widget.finalStepProccessing();
|
||||
}
|
||||
},
|
||||
decoration: const InputDecoration(
|
||||
fillColor: Colors.white,
|
||||
border: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
errorBorder: InputBorder.none,
|
||||
disabledBorder: InputBorder.none,
|
||||
contentPadding:
|
||||
EdgeInsets.only(left: 15, bottom: 11, top: 11, right: 15),
|
||||
hintText: "mob no",
|
||||
hintStyle: TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
|
||||
),
|
||||
style: const TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
|
||||
),
|
||||
),
|
||||
if (mobNoErrorMessage != '')
|
||||
Container(
|
||||
margin: const EdgeInsets.all(2),
|
||||
padding: const EdgeInsets.all(2),
|
||||
child: Text(
|
||||
"\t\t\t\t$mobNoErrorMessage",
|
||||
style: const TextStyle(fontSize: 10, color: Colors.red),
|
||||
),
|
||||
),
|
||||
|
||||
// mob no code end
|
||||
Container(
|
||||
width: double.infinity,
|
||||
margin: const EdgeInsets.all(5),
|
||||
padding: const EdgeInsets.all(5),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
border:
|
||||
Border.all(width: 1.0, color: const Color(0xFFF5F7FA)),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
boxShadow: [
|
||||
const BoxShadow(
|
||||
blurRadius: 6.18,
|
||||
spreadRadius: 0.618,
|
||||
offset: Offset(-4, -4),
|
||||
color: Colors.white38),
|
||||
BoxShadow(
|
||||
blurRadius: 6.18,
|
||||
spreadRadius: 0.618,
|
||||
offset: const Offset(4, 4),
|
||||
color: Colors.blueGrey.shade100)
|
||||
]),
|
||||
child: TextFormField(
|
||||
initialValue: password,
|
||||
onChanged: _toggleSignUpButtonVisibility,
|
||||
// validator: _validateEmailId,
|
||||
autofocus: mounted,
|
||||
autocorrect: false,
|
||||
onFieldSubmitted: (value) {
|
||||
if (value.isNotEmpty) {
|
||||
widget.finalStepProccessing();
|
||||
}
|
||||
},
|
||||
decoration: const InputDecoration(
|
||||
fillColor: Colors.white,
|
||||
border: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
errorBorder: InputBorder.none,
|
||||
disabledBorder: InputBorder.none,
|
||||
contentPadding:
|
||||
EdgeInsets.only(left: 15, bottom: 11, top: 11, right: 15),
|
||||
hintText: "password",
|
||||
hintStyle: TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
|
||||
),
|
||||
style: const TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
|
||||
),
|
||||
),
|
||||
if (passwordErrorMessage != '')
|
||||
Container(
|
||||
margin: const EdgeInsets.all(2),
|
||||
padding: const EdgeInsets.all(2),
|
||||
child: Text(
|
||||
"\t\t\t\t$passwordErrorMessage",
|
||||
style: const TextStyle(fontSize: 10, color: Colors.red),
|
||||
),
|
||||
),
|
||||
|
||||
// new password code end
|
||||
|
||||
Container(
|
||||
width: double.infinity,
|
||||
margin: const EdgeInsets.all(5),
|
||||
padding: const EdgeInsets.all(5),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
border:
|
||||
Border.all(width: 1.0, color: const Color(0xFFF5F7FA)),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
boxShadow: [
|
||||
const BoxShadow(
|
||||
blurRadius: 6.18,
|
||||
spreadRadius: 0.618,
|
||||
offset: Offset(-4, -4),
|
||||
color: Colors.white38),
|
||||
BoxShadow(
|
||||
blurRadius: 6.18,
|
||||
spreadRadius: 0.618,
|
||||
offset: const Offset(4, 4),
|
||||
color: Colors.blueGrey.shade100)
|
||||
]),
|
||||
child: TextFormField(
|
||||
initialValue: confirmPassword,
|
||||
onChanged: _toggleSignUpButtonVisibility,
|
||||
// validator: _validateEmailId,
|
||||
autofocus: mounted,
|
||||
autocorrect: false,
|
||||
onFieldSubmitted: (value) {
|
||||
if (value.isNotEmpty) {
|
||||
widget.finalStepProccessing();
|
||||
}
|
||||
},
|
||||
decoration: const InputDecoration(
|
||||
fillColor: Colors.white,
|
||||
border: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
errorBorder: InputBorder.none,
|
||||
disabledBorder: InputBorder.none,
|
||||
contentPadding:
|
||||
EdgeInsets.only(left: 15, bottom: 11, top: 11, right: 15),
|
||||
hintText: "confirmPassword",
|
||||
hintStyle: TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
|
||||
),
|
||||
style: const TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
|
||||
),
|
||||
),
|
||||
if (confirmPasswordErrorMessage != '')
|
||||
Container(
|
||||
margin: const EdgeInsets.all(2),
|
||||
padding: const EdgeInsets.all(2),
|
||||
child: Text(
|
||||
"\t\t\t\t$confirmPasswordErrorMessage",
|
||||
style: const TextStyle(fontSize: 10, color: Colors.red),
|
||||
),
|
||||
),
|
||||
|
||||
// confirm password code end here
|
||||
],
|
||||
));
|
||||
}
|
||||
|
||||
// void errorMessageSetter(String fieldName, String message) {
|
||||
// setState(() {
|
||||
// switch (fieldName) {
|
||||
// case 'EMAIL-Id':
|
||||
// emailErrorMessage = message;
|
||||
// break;
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
// String? _validateEmailId(String? value) {
|
||||
// if (value == null || value.isEmpty) {
|
||||
// errorMessageSetter('EMAIL-ID', 'you must provide a valid email-id');
|
||||
// } else if (!validEmailFormat.hasMatch(value)) {
|
||||
// errorMessageSetter('EMAIL-ID', 'format of your email address is invalid');
|
||||
// } else {
|
||||
// errorMessageSetter('EMAIL-ID', "");
|
||||
// widget.updateSignUpDetails('email', value);
|
||||
// }
|
||||
|
||||
// return null;
|
||||
// }
|
||||
|
||||
void _toggleSignUpButtonVisibility(String value) {
|
||||
widget.registrationDetails('confirmPassword', value);
|
||||
if (value.isNotEmpty) {
|
||||
widget.showConfirmSignUpButton(true);
|
||||
} else {
|
||||
widget.showConfirmSignUpButton(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class StepGetRegistration extends StatefulWidget {
|
||||
final LabeledGlobalKey<FormState> bankAccountFormKey;
|
||||
// final Function updateSignUpDetails;
|
||||
final Function showConfirmSignUpButton;
|
||||
final Function registrationDetails;
|
||||
final Function finalStepProccessing;
|
||||
const StepGetRegistration(
|
||||
{Key? key,
|
||||
// required this.updateSignUpDetails,
|
||||
required this.registrationDetails,
|
||||
required this.bankAccountFormKey,
|
||||
required this.showConfirmSignUpButton,
|
||||
required this.finalStepProccessing})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
_StepGetRegistrationState createState() => _StepGetRegistrationState();
|
||||
}
|
||||
|
||||
class _StepGetRegistrationState extends State<StepGetRegistration> {
|
||||
String firstname = "";
|
||||
String firstnameErrorMessage = "";
|
||||
|
||||
String lastName = "";
|
||||
String lastNameErrorMessage = "";
|
||||
|
||||
String mobNo = "";
|
||||
String mobNoErrorMessage = "";
|
||||
|
||||
String password = "";
|
||||
String passwordErrorMessage = "";
|
||||
|
||||
String confirmPassword = "";
|
||||
String confirmPasswordErrorMessage = "";
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
Map<String, String> signUpDetails = widget.registrationDetails();
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
firstname = signUpDetails['first_name']!;
|
||||
lastName = signUpDetails['last_name']!;
|
||||
mobNo = signUpDetails['mob_no']!;
|
||||
password = signUpDetails['new_password']!;
|
||||
confirmPassword = signUpDetails['confirm_password']!;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// widget.bankAccountFormKey.currentState?.validate();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Form(
|
||||
key: widget.bankAccountFormKey,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Container(
|
||||
width: double.infinity,
|
||||
margin: const EdgeInsets.all(5),
|
||||
padding: const EdgeInsets.all(5),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
border:
|
||||
Border.all(width: 1.0, color: const Color(0xFFF5F7FA)),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
boxShadow: [
|
||||
const BoxShadow(
|
||||
blurRadius: 6.18,
|
||||
spreadRadius: 0.618,
|
||||
offset: Offset(-4, -4),
|
||||
color: Colors.white38),
|
||||
BoxShadow(
|
||||
blurRadius: 6.18,
|
||||
spreadRadius: 0.618,
|
||||
offset: const Offset(4, 4),
|
||||
color: Colors.blueGrey.shade100)
|
||||
]),
|
||||
child: TextFormField(
|
||||
initialValue: firstname,
|
||||
onChanged: _toggleSignUpButtonVisibility,
|
||||
// validator: _validateEmailId,
|
||||
autofocus: mounted,
|
||||
autocorrect: false,
|
||||
onFieldSubmitted: (value) {
|
||||
if (value.isNotEmpty) {
|
||||
widget.finalStepProccessing();
|
||||
}
|
||||
},
|
||||
decoration: const InputDecoration(
|
||||
fillColor: Colors.white,
|
||||
border: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
errorBorder: InputBorder.none,
|
||||
disabledBorder: InputBorder.none,
|
||||
contentPadding:
|
||||
EdgeInsets.only(left: 15, bottom: 11, top: 11, right: 15),
|
||||
hintText: "first name",
|
||||
hintStyle: TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
|
||||
),
|
||||
style: const TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
|
||||
),
|
||||
),
|
||||
if (firstnameErrorMessage != '')
|
||||
Container(
|
||||
margin: const EdgeInsets.all(2),
|
||||
padding: const EdgeInsets.all(2),
|
||||
child: Text(
|
||||
"\t\t\t\t$firstnameErrorMessage",
|
||||
style: const TextStyle(fontSize: 10, color: Colors.red),
|
||||
),
|
||||
),
|
||||
|
||||
// first name code end here
|
||||
|
||||
Container(
|
||||
width: double.infinity,
|
||||
margin: const EdgeInsets.all(5),
|
||||
padding: const EdgeInsets.all(5),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
border:
|
||||
Border.all(width: 1.0, color: const Color(0xFFF5F7FA)),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
boxShadow: [
|
||||
const BoxShadow(
|
||||
blurRadius: 6.18,
|
||||
spreadRadius: 0.618,
|
||||
offset: Offset(-4, -4),
|
||||
color: Colors.white38),
|
||||
BoxShadow(
|
||||
blurRadius: 6.18,
|
||||
spreadRadius: 0.618,
|
||||
offset: const Offset(4, 4),
|
||||
color: Colors.blueGrey.shade100)
|
||||
]),
|
||||
child: TextFormField(
|
||||
initialValue: lastName,
|
||||
onChanged: _toggleSignUpButtonVisibility,
|
||||
// validator: _validateEmailId,
|
||||
autofocus: mounted,
|
||||
autocorrect: false,
|
||||
onFieldSubmitted: (value) {
|
||||
if (value.isNotEmpty) {
|
||||
widget.finalStepProccessing();
|
||||
}
|
||||
},
|
||||
decoration: const InputDecoration(
|
||||
fillColor: Colors.white,
|
||||
border: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
errorBorder: InputBorder.none,
|
||||
disabledBorder: InputBorder.none,
|
||||
contentPadding:
|
||||
EdgeInsets.only(left: 15, bottom: 11, top: 11, right: 15),
|
||||
hintText: "last name",
|
||||
hintStyle: TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
|
||||
),
|
||||
style: const TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
|
||||
),
|
||||
),
|
||||
if (lastNameErrorMessage != '')
|
||||
Container(
|
||||
margin: const EdgeInsets.all(2),
|
||||
padding: const EdgeInsets.all(2),
|
||||
child: Text(
|
||||
"\t\t\t\t$lastNameErrorMessage",
|
||||
style: const TextStyle(fontSize: 10, color: Colors.red),
|
||||
),
|
||||
),
|
||||
|
||||
// last name code
|
||||
|
||||
Container(
|
||||
width: double.infinity,
|
||||
margin: const EdgeInsets.all(5),
|
||||
padding: const EdgeInsets.all(5),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
border:
|
||||
Border.all(width: 1.0, color: const Color(0xFFF5F7FA)),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
boxShadow: [
|
||||
const BoxShadow(
|
||||
blurRadius: 6.18,
|
||||
spreadRadius: 0.618,
|
||||
offset: Offset(-4, -4),
|
||||
color: Colors.white38),
|
||||
BoxShadow(
|
||||
blurRadius: 6.18,
|
||||
spreadRadius: 0.618,
|
||||
offset: const Offset(4, 4),
|
||||
color: Colors.blueGrey.shade100)
|
||||
]),
|
||||
child: TextFormField(
|
||||
initialValue: mobNo,
|
||||
onChanged: _toggleSignUpButtonVisibility,
|
||||
// validator: _validateEmailId,
|
||||
autofocus: mounted,
|
||||
autocorrect: false,
|
||||
onFieldSubmitted: (value) {
|
||||
if (value.isNotEmpty) {
|
||||
widget.finalStepProccessing();
|
||||
}
|
||||
},
|
||||
decoration: const InputDecoration(
|
||||
fillColor: Colors.white,
|
||||
border: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
errorBorder: InputBorder.none,
|
||||
disabledBorder: InputBorder.none,
|
||||
contentPadding:
|
||||
EdgeInsets.only(left: 15, bottom: 11, top: 11, right: 15),
|
||||
hintText: "mob no",
|
||||
hintStyle: TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
|
||||
),
|
||||
style: const TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
|
||||
),
|
||||
),
|
||||
if (mobNoErrorMessage != '')
|
||||
Container(
|
||||
margin: const EdgeInsets.all(2),
|
||||
padding: const EdgeInsets.all(2),
|
||||
child: Text(
|
||||
"\t\t\t\t$mobNoErrorMessage",
|
||||
style: const TextStyle(fontSize: 10, color: Colors.red),
|
||||
),
|
||||
),
|
||||
|
||||
// mob no code end
|
||||
Container(
|
||||
width: double.infinity,
|
||||
margin: const EdgeInsets.all(5),
|
||||
padding: const EdgeInsets.all(5),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
border:
|
||||
Border.all(width: 1.0, color: const Color(0xFFF5F7FA)),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
boxShadow: [
|
||||
const BoxShadow(
|
||||
blurRadius: 6.18,
|
||||
spreadRadius: 0.618,
|
||||
offset: Offset(-4, -4),
|
||||
color: Colors.white38),
|
||||
BoxShadow(
|
||||
blurRadius: 6.18,
|
||||
spreadRadius: 0.618,
|
||||
offset: const Offset(4, 4),
|
||||
color: Colors.blueGrey.shade100)
|
||||
]),
|
||||
child: TextFormField(
|
||||
initialValue: password,
|
||||
onChanged: _toggleSignUpButtonVisibility,
|
||||
// validator: _validateEmailId,
|
||||
autofocus: mounted,
|
||||
autocorrect: false,
|
||||
onFieldSubmitted: (value) {
|
||||
if (value.isNotEmpty) {
|
||||
widget.finalStepProccessing();
|
||||
}
|
||||
},
|
||||
decoration: const InputDecoration(
|
||||
fillColor: Colors.white,
|
||||
border: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
errorBorder: InputBorder.none,
|
||||
disabledBorder: InputBorder.none,
|
||||
contentPadding:
|
||||
EdgeInsets.only(left: 15, bottom: 11, top: 11, right: 15),
|
||||
hintText: "password",
|
||||
hintStyle: TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
|
||||
),
|
||||
style: const TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
|
||||
),
|
||||
),
|
||||
if (passwordErrorMessage != '')
|
||||
Container(
|
||||
margin: const EdgeInsets.all(2),
|
||||
padding: const EdgeInsets.all(2),
|
||||
child: Text(
|
||||
"\t\t\t\t$passwordErrorMessage",
|
||||
style: const TextStyle(fontSize: 10, color: Colors.red),
|
||||
),
|
||||
),
|
||||
|
||||
// new password code end
|
||||
|
||||
Container(
|
||||
width: double.infinity,
|
||||
margin: const EdgeInsets.all(5),
|
||||
padding: const EdgeInsets.all(5),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
border:
|
||||
Border.all(width: 1.0, color: const Color(0xFFF5F7FA)),
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
boxShadow: [
|
||||
const BoxShadow(
|
||||
blurRadius: 6.18,
|
||||
spreadRadius: 0.618,
|
||||
offset: Offset(-4, -4),
|
||||
color: Colors.white38),
|
||||
BoxShadow(
|
||||
blurRadius: 6.18,
|
||||
spreadRadius: 0.618,
|
||||
offset: const Offset(4, 4),
|
||||
color: Colors.blueGrey.shade100)
|
||||
]),
|
||||
child: TextFormField(
|
||||
initialValue: confirmPassword,
|
||||
onChanged: _toggleSignUpButtonVisibility,
|
||||
// validator: _validateEmailId,
|
||||
autofocus: mounted,
|
||||
autocorrect: false,
|
||||
onFieldSubmitted: (value) {
|
||||
if (value.isNotEmpty) {
|
||||
widget.finalStepProccessing();
|
||||
}
|
||||
},
|
||||
decoration: const InputDecoration(
|
||||
fillColor: Colors.white,
|
||||
border: InputBorder.none,
|
||||
focusedBorder: InputBorder.none,
|
||||
enabledBorder: InputBorder.none,
|
||||
errorBorder: InputBorder.none,
|
||||
disabledBorder: InputBorder.none,
|
||||
contentPadding:
|
||||
EdgeInsets.only(left: 15, bottom: 11, top: 11, right: 15),
|
||||
hintText: "confirmPassword",
|
||||
hintStyle: TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
|
||||
),
|
||||
style: const TextStyle(fontSize: 16, color: Color(0xFF929BAB)),
|
||||
),
|
||||
),
|
||||
if (confirmPasswordErrorMessage != '')
|
||||
Container(
|
||||
margin: const EdgeInsets.all(2),
|
||||
padding: const EdgeInsets.all(2),
|
||||
child: Text(
|
||||
"\t\t\t\t$confirmPasswordErrorMessage",
|
||||
style: const TextStyle(fontSize: 10, color: Colors.red),
|
||||
),
|
||||
),
|
||||
|
||||
// confirm password code end here
|
||||
],
|
||||
));
|
||||
}
|
||||
|
||||
// void errorMessageSetter(String fieldName, String message) {
|
||||
// setState(() {
|
||||
// switch (fieldName) {
|
||||
// case 'EMAIL-Id':
|
||||
// emailErrorMessage = message;
|
||||
// break;
|
||||
// }
|
||||
// });
|
||||
// }
|
||||
|
||||
// String? _validateEmailId(String? value) {
|
||||
// if (value == null || value.isEmpty) {
|
||||
// errorMessageSetter('EMAIL-ID', 'you must provide a valid email-id');
|
||||
// } else if (!validEmailFormat.hasMatch(value)) {
|
||||
// errorMessageSetter('EMAIL-ID', 'format of your email address is invalid');
|
||||
// } else {
|
||||
// errorMessageSetter('EMAIL-ID', "");
|
||||
// widget.updateSignUpDetails('email', value);
|
||||
// }
|
||||
|
||||
// return null;
|
||||
// }
|
||||
|
||||
void _toggleSignUpButtonVisibility(String value) {
|
||||
widget.registrationDetails('confirmPassword', value);
|
||||
if (value.isNotEmpty) {
|
||||
widget.showConfirmSignUpButton(true);
|
||||
} else {
|
||||
widget.showConfirmSignUpButton(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,60 +1,60 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'sign_up_steps.dart';
|
||||
|
||||
class SignUpScreen extends StatefulWidget {
|
||||
const SignUpScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_SignUpScreenState createState() => _SignUpScreenState();
|
||||
}
|
||||
|
||||
class _SignUpScreenState extends State<SignUpScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return WillPopScope(
|
||||
child: Scaffold(
|
||||
body: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(45),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
SizedBox(
|
||||
height: 30,
|
||||
child: Image.asset('/images/hadwin_system/cldnsure.png'),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
const SignUpSteps(), // GO TO SIGN UP FORM
|
||||
const SizedBox(
|
||||
height: 27,
|
||||
),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
height: 16,
|
||||
child: Center(
|
||||
child: InkWell(
|
||||
child: const Text(
|
||||
'Already have an account? Sign in',
|
||||
style:
|
||||
TextStyle(fontSize: 14, color: Color(0xFF929BAB)),
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 3,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
onWillPop: () => Future.value(false));
|
||||
}
|
||||
}
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'sign_up_steps.dart';
|
||||
|
||||
class SignUpScreen extends StatefulWidget {
|
||||
const SignUpScreen({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_SignUpScreenState createState() => _SignUpScreenState();
|
||||
}
|
||||
|
||||
class _SignUpScreenState extends State<SignUpScreen> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return WillPopScope(
|
||||
child: Scaffold(
|
||||
body: SingleChildScrollView(
|
||||
padding: const EdgeInsets.all(45),
|
||||
child: Column(
|
||||
children: <Widget>[
|
||||
const SizedBox(
|
||||
height: 16,
|
||||
),
|
||||
SizedBox(
|
||||
height: 30,
|
||||
child: Image.asset('/images/hadwin_system/cldnsure.png'),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 30,
|
||||
),
|
||||
const SignUpSteps(), // GO TO SIGN UP FORM
|
||||
const SizedBox(
|
||||
height: 27,
|
||||
),
|
||||
SizedBox(
|
||||
width: double.infinity,
|
||||
height: 16,
|
||||
child: Center(
|
||||
child: InkWell(
|
||||
child: const Text(
|
||||
'Already have an account? Sign in',
|
||||
style:
|
||||
TextStyle(fontSize: 14, color: Color(0xFF929BAB)),
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
height: 3,
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
onWillPop: () => Future.value(false));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,398 +1,398 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:pinput/pinput.dart';
|
||||
|
||||
import '../../Utils/color_constants.dart';
|
||||
import '../../Utils/image_constant.dart';
|
||||
import '../../Utils/size_utils.dart';
|
||||
import '../../theme/app_style.dart';
|
||||
import '../../widgets/app_bar/appbar_image.dart';
|
||||
import '../../widgets/app_bar/appbar_title.dart';
|
||||
import '../../widgets/app_bar/custom_app_bar.dart';
|
||||
import '../../widgets/custom_button.dart';
|
||||
import '../../widgets/custom_image_view.dart';
|
||||
import '../../widgets/custom_text_form_field.dart';
|
||||
import 'RegistrationDetails.dart';
|
||||
import 'SignUpService.dart';
|
||||
|
||||
enum RegistrationStep {
|
||||
SendOTP,
|
||||
VerifyOTP,
|
||||
EnterUserInfo,
|
||||
SelectAccount,
|
||||
}
|
||||
|
||||
class SignUpUserScreenNew extends StatefulWidget {
|
||||
SignUpUserScreenNew({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_SignUpUserScreenState createState() => _SignUpUserScreenState();
|
||||
}
|
||||
|
||||
class _SignUpUserScreenState extends State<SignUpUserScreenNew> {
|
||||
final SignUpApiService userService = SignUpApiService();
|
||||
|
||||
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
|
||||
final Map<String, dynamic> formData = {};
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
var selectedAccount;
|
||||
TextEditingController emailcontroller = TextEditingController();
|
||||
var email;
|
||||
var otp;
|
||||
var confirmPassword;
|
||||
|
||||
bool _passwordVisible = false;
|
||||
bool _isPasswordValid = true;
|
||||
void _validatePassword(String password) {
|
||||
setState(() {
|
||||
_isPasswordValid = password.isNotEmpty;
|
||||
});
|
||||
}
|
||||
|
||||
RegistrationStep currentStep = RegistrationStep.SendOTP;
|
||||
|
||||
void moveToNextStep() {
|
||||
setState(() {
|
||||
if (currentStep == RegistrationStep.SendOTP) {
|
||||
currentStep = RegistrationStep.VerifyOTP;
|
||||
} else if (currentStep == RegistrationStep.VerifyOTP) {
|
||||
currentStep = RegistrationStep.EnterUserInfo;
|
||||
} else if (currentStep == RegistrationStep.EnterUserInfo) {
|
||||
currentStep = RegistrationStep.SelectAccount;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void showSuccessMessage(String message) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(message),
|
||||
duration: const Duration(seconds: 2),
|
||||
backgroundColor: Colors.green,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void showErrorMessage(String error) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(error),
|
||||
duration: const Duration(seconds: 2),
|
||||
backgroundColor: Colors.red,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
key: _scaffoldKey,
|
||||
appBar: CustomAppBar(
|
||||
height: getVerticalSize(54),
|
||||
leadingWidth: 40,
|
||||
leading: AppbarImage(
|
||||
height: getSize(24),
|
||||
width: getSize(24),
|
||||
svgPath: ImageConstant.imgArrowleft,
|
||||
margin: getMargin(left: 16, top: 13, bottom: 17),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
}),
|
||||
centerTitle: true,
|
||||
title: AppbarTitle(text: "Create User")),
|
||||
body: Builder(
|
||||
builder: (BuildContext context) {
|
||||
return SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: SizedBox(
|
||||
height: MediaQuery.of(context).size.height *
|
||||
0.5, // Use 50% of the screen height
|
||||
child: ListView.builder(
|
||||
itemCount: 1,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
if(currentStep == RegistrationStep.SendOTP) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text("Email",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroyMedium16Bluegray900),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
controller: emailcontroller,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Email';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
hintText: "Enter Your Email",
|
||||
margin: getMargin(top: 7),
|
||||
textInputType: TextInputType.emailAddress),
|
||||
CustomButton(
|
||||
height: getVerticalSize(50),
|
||||
width: getHorizontalSize(396),
|
||||
text: "Send OTP",
|
||||
margin: getMargin(top: 25),
|
||||
onTap: () async {
|
||||
|
||||
if (_formKey.currentState!.validate()) {
|
||||
_formKey.currentState!.save();
|
||||
|
||||
formData['usrGrpId'] = 41;
|
||||
formData['email'] = emailcontroller.text;
|
||||
try {
|
||||
print('send email data is $formData');
|
||||
|
||||
await userService.sendEmail(formData);
|
||||
|
||||
await Future.delayed(
|
||||
const Duration(seconds: 2));
|
||||
|
||||
moveToNextStep();
|
||||
} catch (e) {
|
||||
showErrorMessage(
|
||||
'Failed to send OTP: $e');
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: Padding(
|
||||
padding: getPadding(top: 28, bottom: 5),
|
||||
child: RichText(
|
||||
text: TextSpan(children: [
|
||||
TextSpan(
|
||||
text: "",
|
||||
style: TextStyle(
|
||||
color: ColorConstant.fromHex(
|
||||
"#ff12282a"),
|
||||
fontSize: getFontSize(16),
|
||||
fontFamily: 'Gilroy',
|
||||
fontWeight: FontWeight.w400)),
|
||||
TextSpan(
|
||||
text: " ",
|
||||
style: TextStyle(
|
||||
color: ColorConstant.fromHex(
|
||||
"#ff12282a"),
|
||||
fontSize: getFontSize(16),
|
||||
fontFamily: 'Gilroy',
|
||||
fontWeight: FontWeight.w700)),
|
||||
TextSpan(
|
||||
text: "",
|
||||
style: TextStyle(
|
||||
color: ColorConstant.fromHex(
|
||||
"#ff0061ff"),
|
||||
fontSize: getFontSize(16),
|
||||
fontFamily: 'Gilroy',
|
||||
fontWeight: FontWeight.w700,
|
||||
decoration:
|
||||
TextDecoration.underline))
|
||||
]),
|
||||
textAlign: TextAlign.left)))
|
||||
]);
|
||||
}
|
||||
else if(currentStep == RegistrationStep.VerifyOTP) {
|
||||
return Container(
|
||||
width: double.maxFinite,
|
||||
padding: getPadding(
|
||||
left: 16,
|
||||
top: 76,
|
||||
right: 16,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
CustomImageView(
|
||||
svgPath: ImageConstant.imgMobile,
|
||||
height: getVerticalSize(
|
||||
82,
|
||||
),
|
||||
width: getHorizontalSize(
|
||||
51,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: getPadding(
|
||||
top: 29,
|
||||
),
|
||||
child: Text(
|
||||
"Email Verification",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroySemiBold24,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
width: getHorizontalSize(
|
||||
302,
|
||||
),
|
||||
margin: getMargin(
|
||||
left: 46,
|
||||
top: 19,
|
||||
right: 46,
|
||||
),
|
||||
child: Text(
|
||||
"A mail with a 6-digit verification code was just sent to ${emailcontroller.text}",
|
||||
maxLines: null,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppStyle.txtGilroyMedium16,
|
||||
),
|
||||
),
|
||||
Pinput(
|
||||
length: 6,
|
||||
showCursor: true,
|
||||
defaultPinTheme: PinTheme(
|
||||
width: 50,
|
||||
height: 50,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(
|
||||
color: ColorConstant.blue50,
|
||||
),
|
||||
),
|
||||
textStyle: const TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
onCompleted: (value) {
|
||||
setState(() {
|
||||
otp = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
|
||||
CustomButton(
|
||||
height: getVerticalSize(
|
||||
50,
|
||||
),
|
||||
text: "Next",
|
||||
margin: getMargin(
|
||||
top: 40,
|
||||
),
|
||||
onTap: () async {
|
||||
try {
|
||||
print('email is $email and otp is $otp');
|
||||
await userService.otpverification(emailcontroller.text, otp);
|
||||
|
||||
moveToNextStep();
|
||||
showSuccessMessage(
|
||||
'Email verified successfully');
|
||||
} catch (e) {
|
||||
showErrorMessage('Failed to verify OTP: $e');
|
||||
}
|
||||
},
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () async {
|
||||
try {
|
||||
await userService.resendEmail(email);
|
||||
|
||||
await Future.delayed(
|
||||
const Duration(seconds: 5));
|
||||
showSuccessMessage('OTP RESEND');
|
||||
} catch (e) {
|
||||
showErrorMessage(
|
||||
'Failed to resend OTP: $e');
|
||||
}
|
||||
},
|
||||
child: Padding(
|
||||
padding: getPadding(top: 3),
|
||||
child: Text("Forgot Password?",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style:
|
||||
AppStyle.txtGilroyMedium14BlueA700)),
|
||||
),
|
||||
|
||||
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Padding(
|
||||
padding: getPadding(
|
||||
top: 18,
|
||||
bottom: 5,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Padding(
|
||||
padding: getPadding(
|
||||
top: 2,
|
||||
),
|
||||
child: Text(
|
||||
"Didn’t get the code?",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroyMedium16,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: getPadding(
|
||||
left: 12,
|
||||
bottom: 1,
|
||||
),
|
||||
child: Text(
|
||||
"Resend",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroySemiBold16BlueA700,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
else if (currentStep ==
|
||||
RegistrationStep.EnterUserInfo) {
|
||||
return Column(
|
||||
children: [
|
||||
CustomButton(
|
||||
height: getVerticalSize(
|
||||
50,
|
||||
),
|
||||
text: "Go to Registration Details",
|
||||
margin: getMargin(
|
||||
top: 40,
|
||||
),
|
||||
onTap: () async {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
RegistrationDetailsScreen(email: emailcontroller.text),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
else{
|
||||
return Container();
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:pinput/pinput.dart';
|
||||
|
||||
import '../../Utils/color_constants.dart';
|
||||
import '../../Utils/image_constant.dart';
|
||||
import '../../Utils/size_utils.dart';
|
||||
import '../../theme/app_style.dart';
|
||||
import '../../widgets/app_bar/appbar_image.dart';
|
||||
import '../../widgets/app_bar/appbar_title.dart';
|
||||
import '../../widgets/app_bar/custom_app_bar.dart';
|
||||
import '../../widgets/custom_button.dart';
|
||||
import '../../widgets/custom_image_view.dart';
|
||||
import '../../widgets/custom_text_form_field.dart';
|
||||
import 'RegistrationDetails.dart';
|
||||
import 'SignUpService.dart';
|
||||
|
||||
enum RegistrationStep {
|
||||
SendOTP,
|
||||
VerifyOTP,
|
||||
EnterUserInfo,
|
||||
SelectAccount,
|
||||
}
|
||||
|
||||
class SignUpUserScreenNew extends StatefulWidget {
|
||||
SignUpUserScreenNew({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_SignUpUserScreenState createState() => _SignUpUserScreenState();
|
||||
}
|
||||
|
||||
class _SignUpUserScreenState extends State<SignUpUserScreenNew> {
|
||||
final SignUpApiService userService = SignUpApiService();
|
||||
|
||||
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
|
||||
final Map<String, dynamic> formData = {};
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
var selectedAccount;
|
||||
TextEditingController emailcontroller = TextEditingController();
|
||||
var email;
|
||||
var otp;
|
||||
var confirmPassword;
|
||||
|
||||
bool _passwordVisible = false;
|
||||
bool _isPasswordValid = true;
|
||||
void _validatePassword(String password) {
|
||||
setState(() {
|
||||
_isPasswordValid = password.isNotEmpty;
|
||||
});
|
||||
}
|
||||
|
||||
RegistrationStep currentStep = RegistrationStep.SendOTP;
|
||||
|
||||
void moveToNextStep() {
|
||||
setState(() {
|
||||
if (currentStep == RegistrationStep.SendOTP) {
|
||||
currentStep = RegistrationStep.VerifyOTP;
|
||||
} else if (currentStep == RegistrationStep.VerifyOTP) {
|
||||
currentStep = RegistrationStep.EnterUserInfo;
|
||||
} else if (currentStep == RegistrationStep.EnterUserInfo) {
|
||||
currentStep = RegistrationStep.SelectAccount;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void showSuccessMessage(String message) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(message),
|
||||
duration: const Duration(seconds: 2),
|
||||
backgroundColor: Colors.green,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void showErrorMessage(String error) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(error),
|
||||
duration: const Duration(seconds: 2),
|
||||
backgroundColor: Colors.red,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
key: _scaffoldKey,
|
||||
appBar: CustomAppBar(
|
||||
height: getVerticalSize(54),
|
||||
leadingWidth: 40,
|
||||
leading: AppbarImage(
|
||||
height: getSize(24),
|
||||
width: getSize(24),
|
||||
svgPath: ImageConstant.imgArrowleft,
|
||||
margin: getMargin(left: 16, top: 13, bottom: 17),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
}),
|
||||
centerTitle: true,
|
||||
title: AppbarTitle(text: "Create User")),
|
||||
body: Builder(
|
||||
builder: (BuildContext context) {
|
||||
return SingleChildScrollView(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: SizedBox(
|
||||
height: MediaQuery.of(context).size.height *
|
||||
0.5, // Use 50% of the screen height
|
||||
child: ListView.builder(
|
||||
itemCount: 1,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
if(currentStep == RegistrationStep.SendOTP) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Text("Email",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroyMedium16Bluegray900),
|
||||
CustomTextFormField(
|
||||
focusNode: FocusNode(),
|
||||
controller: emailcontroller,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Please enter Email';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
hintText: "Enter Your Email",
|
||||
margin: getMargin(top: 7),
|
||||
textInputType: TextInputType.emailAddress),
|
||||
CustomButton(
|
||||
height: getVerticalSize(50),
|
||||
width: getHorizontalSize(396),
|
||||
text: "Send OTP",
|
||||
margin: getMargin(top: 25),
|
||||
onTap: () async {
|
||||
|
||||
if (_formKey.currentState!.validate()) {
|
||||
_formKey.currentState!.save();
|
||||
|
||||
formData['usrGrpId'] = 41;
|
||||
formData['email'] = emailcontroller.text;
|
||||
try {
|
||||
print('send email data is $formData');
|
||||
|
||||
await userService.sendEmail(formData);
|
||||
|
||||
await Future.delayed(
|
||||
const Duration(seconds: 2));
|
||||
|
||||
moveToNextStep();
|
||||
} catch (e) {
|
||||
showErrorMessage(
|
||||
'Failed to send OTP: $e');
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: Padding(
|
||||
padding: getPadding(top: 28, bottom: 5),
|
||||
child: RichText(
|
||||
text: TextSpan(children: [
|
||||
TextSpan(
|
||||
text: "",
|
||||
style: TextStyle(
|
||||
color: ColorConstant.fromHex(
|
||||
"#ff12282a"),
|
||||
fontSize: getFontSize(16),
|
||||
fontFamily: 'Gilroy',
|
||||
fontWeight: FontWeight.w400)),
|
||||
TextSpan(
|
||||
text: " ",
|
||||
style: TextStyle(
|
||||
color: ColorConstant.fromHex(
|
||||
"#ff12282a"),
|
||||
fontSize: getFontSize(16),
|
||||
fontFamily: 'Gilroy',
|
||||
fontWeight: FontWeight.w700)),
|
||||
TextSpan(
|
||||
text: "",
|
||||
style: TextStyle(
|
||||
color: ColorConstant.fromHex(
|
||||
"#ff0061ff"),
|
||||
fontSize: getFontSize(16),
|
||||
fontFamily: 'Gilroy',
|
||||
fontWeight: FontWeight.w700,
|
||||
decoration:
|
||||
TextDecoration.underline))
|
||||
]),
|
||||
textAlign: TextAlign.left)))
|
||||
]);
|
||||
}
|
||||
else if(currentStep == RegistrationStep.VerifyOTP) {
|
||||
return Container(
|
||||
width: double.maxFinite,
|
||||
padding: getPadding(
|
||||
left: 16,
|
||||
top: 76,
|
||||
right: 16,
|
||||
),
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
CustomImageView(
|
||||
svgPath: ImageConstant.imgMobile,
|
||||
height: getVerticalSize(
|
||||
82,
|
||||
),
|
||||
width: getHorizontalSize(
|
||||
51,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: getPadding(
|
||||
top: 29,
|
||||
),
|
||||
child: Text(
|
||||
"Email Verification",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroySemiBold24,
|
||||
),
|
||||
),
|
||||
Container(
|
||||
width: getHorizontalSize(
|
||||
302,
|
||||
),
|
||||
margin: getMargin(
|
||||
left: 46,
|
||||
top: 19,
|
||||
right: 46,
|
||||
),
|
||||
child: Text(
|
||||
"A mail with a 6-digit verification code was just sent to ${emailcontroller.text}",
|
||||
maxLines: null,
|
||||
textAlign: TextAlign.center,
|
||||
style: AppStyle.txtGilroyMedium16,
|
||||
),
|
||||
),
|
||||
Pinput(
|
||||
length: 6,
|
||||
showCursor: true,
|
||||
defaultPinTheme: PinTheme(
|
||||
width: 50,
|
||||
height: 50,
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(
|
||||
color: ColorConstant.blue50,
|
||||
),
|
||||
),
|
||||
textStyle: const TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
),
|
||||
onCompleted: (value) {
|
||||
setState(() {
|
||||
otp = value;
|
||||
});
|
||||
},
|
||||
),
|
||||
|
||||
CustomButton(
|
||||
height: getVerticalSize(
|
||||
50,
|
||||
),
|
||||
text: "Next",
|
||||
margin: getMargin(
|
||||
top: 40,
|
||||
),
|
||||
onTap: () async {
|
||||
try {
|
||||
print('email is $email and otp is $otp');
|
||||
await userService.otpverification(emailcontroller.text, otp);
|
||||
|
||||
moveToNextStep();
|
||||
showSuccessMessage(
|
||||
'Email verified successfully');
|
||||
} catch (e) {
|
||||
showErrorMessage('Failed to verify OTP: $e');
|
||||
}
|
||||
},
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () async {
|
||||
try {
|
||||
await userService.resendEmail(email);
|
||||
|
||||
await Future.delayed(
|
||||
const Duration(seconds: 5));
|
||||
showSuccessMessage('OTP RESEND');
|
||||
} catch (e) {
|
||||
showErrorMessage(
|
||||
'Failed to resend OTP: $e');
|
||||
}
|
||||
},
|
||||
child: Padding(
|
||||
padding: getPadding(top: 3),
|
||||
child: Text("Forgot Password?",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style:
|
||||
AppStyle.txtGilroyMedium14BlueA700)),
|
||||
),
|
||||
|
||||
|
||||
Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Padding(
|
||||
padding: getPadding(
|
||||
top: 18,
|
||||
bottom: 5,
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Padding(
|
||||
padding: getPadding(
|
||||
top: 2,
|
||||
),
|
||||
child: Text(
|
||||
"Didn’t get the code?",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroyMedium16,
|
||||
),
|
||||
),
|
||||
Padding(
|
||||
padding: getPadding(
|
||||
left: 12,
|
||||
bottom: 1,
|
||||
),
|
||||
child: Text(
|
||||
"Resend",
|
||||
overflow: TextOverflow.ellipsis,
|
||||
textAlign: TextAlign.left,
|
||||
style: AppStyle.txtGilroySemiBold16BlueA700,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
else if (currentStep ==
|
||||
RegistrationStep.EnterUserInfo) {
|
||||
return Column(
|
||||
children: [
|
||||
CustomButton(
|
||||
height: getVerticalSize(
|
||||
50,
|
||||
),
|
||||
text: "Go to Registration Details",
|
||||
margin: getMargin(
|
||||
top: 40,
|
||||
),
|
||||
onTap: () async {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) =>
|
||||
RegistrationDetailsScreen(email: emailcontroller.text),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
else{
|
||||
return Container();
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,84 +1,84 @@
|
||||
import 'dart:convert';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import '../Login Screen/login_screen.dart';
|
||||
import '../main_app_screen/tabbed_layout_component.dart';
|
||||
|
||||
class SplashScreen extends StatefulWidget {
|
||||
const SplashScreen({super.key});
|
||||
|
||||
@override
|
||||
State<SplashScreen> createState() => _SplashScreenState();
|
||||
}
|
||||
|
||||
class _SplashScreenState extends State<SplashScreen> {
|
||||
var isLogin = false;
|
||||
|
||||
Map<String, dynamic> userData = {};
|
||||
|
||||
|
||||
|
||||
Future<void> checkifLogin() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
bool? isLoggedIn = prefs.getBool('isLoggedIn');
|
||||
var userdatastr = prefs.getString('userData');
|
||||
|
||||
if (kDebugMode) {
|
||||
print('userData....$userdatastr');
|
||||
}
|
||||
if (isLoggedIn != null && isLoggedIn) {
|
||||
setState(() {
|
||||
isLogin = true;
|
||||
});
|
||||
}
|
||||
|
||||
if (userdatastr != null) {
|
||||
try{
|
||||
userData = json.decode(userdatastr);
|
||||
if (kDebugMode) {
|
||||
print(userData['token']);
|
||||
}
|
||||
}catch(e){
|
||||
if (kDebugMode) {
|
||||
print("error is ..................$e");
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
setState(() {
|
||||
isLogin = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
checkifLogin().then((value) async => {
|
||||
Future.delayed(const Duration(seconds: 2), () {
|
||||
Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => isLogin
|
||||
? TabbedLayoutComponent(): const LoginScreen()
|
||||
),);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: SingleChildScrollView(
|
||||
child: Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
height: MediaQuery.of(context).size.height,
|
||||
child: Center(
|
||||
child: SvgPicture.asset(
|
||||
'assets/images/cloudnsuresp.svg',
|
||||
width: 100,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
import 'dart:convert';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import '../Login Screen/login_screen.dart';
|
||||
import '../main_app_screen/tabbed_layout_component.dart';
|
||||
|
||||
class SplashScreen extends StatefulWidget {
|
||||
const SplashScreen({super.key});
|
||||
|
||||
@override
|
||||
State<SplashScreen> createState() => _SplashScreenState();
|
||||
}
|
||||
|
||||
class _SplashScreenState extends State<SplashScreen> {
|
||||
var isLogin = false;
|
||||
|
||||
Map<String, dynamic> userData = {};
|
||||
|
||||
|
||||
|
||||
Future<void> checkifLogin() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
bool? isLoggedIn = prefs.getBool('isLoggedIn');
|
||||
var userdatastr = prefs.getString('userData');
|
||||
|
||||
if (kDebugMode) {
|
||||
print('userData....$userdatastr');
|
||||
}
|
||||
if (isLoggedIn != null && isLoggedIn) {
|
||||
setState(() {
|
||||
isLogin = true;
|
||||
});
|
||||
}
|
||||
|
||||
if (userdatastr != null) {
|
||||
try{
|
||||
userData = json.decode(userdatastr);
|
||||
if (kDebugMode) {
|
||||
print(userData['token']);
|
||||
}
|
||||
}catch(e){
|
||||
if (kDebugMode) {
|
||||
print("error is ..................$e");
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
setState(() {
|
||||
isLogin = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
checkifLogin().then((value) async => {
|
||||
Future.delayed(const Duration(seconds: 2), () {
|
||||
Navigator.pushReplacement(context, MaterialPageRoute(builder: (context) => isLogin
|
||||
? TabbedLayoutComponent(): const LoginScreen()
|
||||
),);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: SingleChildScrollView(
|
||||
child: Container(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
height: MediaQuery.of(context).size.height,
|
||||
child: Center(
|
||||
child: SvgPicture.asset(
|
||||
'assets/images/cloudnsuresp.svg',
|
||||
width: 100,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user