environment_monitoring_app/lib/models/tarball_data.dart

201 lines
7.8 KiB
Dart

//import 'dart' as dart;
import 'dart:io';
import 'dart:convert';
/// This class holds all the data collected across the multi-step tarball sampling form.
/// It acts as a temporary data container that is passed between screens.
class TarballSamplingData {
// --- Step 1 Data: Collected in TarballSamplingStep1 ---
String? firstSampler;
int? firstSamplerUserId;
Map<String, dynamic>? secondSampler; // Holds the full user map for the 2nd sampler
String? samplingDate;
String? samplingTime;
String? selectedStateName;
String? selectedCategoryName;
Map<String, dynamic>? selectedStation; // Holds the full station map
String? stationLatitude;
String? stationLongitude;
String? currentLatitude;
String? currentLongitude;
double? distanceDifference;
String? distanceDifferenceRemarks;
// --- Step 2 Data: Collected in TarballSamplingStep2 ---
int? classificationId;
// NECESSARY CHANGE: Add property to hold the full classification object.
Map<String, dynamic>? selectedClassification;
File? leftCoastalViewImage;
File? rightCoastalViewImage;
File? verticalLinesImage;
File? horizontalLineImage;
File? optionalImage1;
String? optionalRemark1;
File? optionalImage2;
String? optionalRemark2;
File? optionalImage3;
String? optionalRemark3;
File? optionalImage4;
String? optionalRemark4;
// --- Step 3 Data: For handling the submission response ---
String? reportId;
String? submissionStatus;
String? submissionMessage;
/// Generates a formatted Telegram alert message for successful submissions.
String generateTelegramAlertMessage({required bool isDataOnly}) {
final submissionType = isDataOnly ? "(Data Only)" : "(Data & Images)";
final stationName = selectedStation?['tbl_station_name'] ?? 'N/A';
final stationCode = selectedStation?['tbl_station_code'] ?? 'N/A';
// This logic now correctly uses the full classification object if available.
final classification = selectedClassification?['classification_name'] ?? classificationId?.toString() ?? 'N/A';
final buffer = StringBuffer()
..writeln('✅ *Tarball Sample $submissionType Submitted:*')
..writeln()
..writeln('*Station Name & Code:* $stationName ($stationCode)')
..writeln('*Date of Submission:* $samplingDate')
..writeln('*Submitted by User:* $firstSampler')
..writeln('*Classification:* $classification')
..writeln('*Status of Submission:* Successful');
// Add distance alert if relevant
if (distanceDifference != null && distanceDifference! > 0) {
buffer
..writeln()
..writeln('🔔 *Alert:*')
..writeln('*Distance from station:* ${(distanceDifference! * 1000).toStringAsFixed(0)} meters');
if (distanceDifferenceRemarks != null && distanceDifferenceRemarks!.isNotEmpty) {
buffer.writeln('*Remarks for distance:* $distanceDifferenceRemarks');
}
}
return buffer.toString();
}
/// Converts the form's text and selection data into a Map suitable for JSON encoding.
/// This map will be sent as the body of the first API request.
Map<String, String> toFormData() {
final Map<String, String> data = {
// Required fields
'station_id': selectedStation?['station_id']?.toString() ?? '',
'sampling_date': samplingDate ?? '',
'sampling_time': samplingTime ?? '',
// User ID fields
'first_sampler_user_id': firstSamplerUserId?.toString() ?? '',
'second_sampler_user_id': secondSampler?['user_id']?.toString() ?? '',
// Foreign Key ID for classification
'classification_id': classificationId?.toString() ?? '',
// Other nullable fields
'current_latitude': currentLatitude ?? '',
'current_longitude': currentLongitude ?? '',
'distance_difference': distanceDifference?.toString() ?? '',
'optional_photo_remark_01': optionalRemark1 ?? '',
'optional_photo_remark_02': optionalRemark2 ?? '',
'optional_photo_remark_03': optionalRemark3 ?? '',
'optional_photo_remark_04': optionalRemark4 ?? '',
'distance_remarks': distanceDifferenceRemarks ?? '',
// Human-readable names for the Telegram alert
'tbl_station_name': selectedStation?['tbl_station_name']?.toString() ?? '',
'tbl_station_code': selectedStation?['tbl_station_code']?.toString() ?? '',
'first_sampler_name': firstSampler ?? '',
// NECESSARY CHANGE: Add the classification name for the alert.
'classification_name': selectedClassification?['classification_name']?.toString() ?? '',
};
return data;
}
/// Gathers all non-null image files into a Map.
/// This map is used to build the multipart request for the second API call (image upload).
Map<String, File?> toImageFiles() {
return {
'left_side_coastal_view': leftCoastalViewImage,
'right_side_coastal_view': rightCoastalViewImage,
'drawing_vertical_lines': verticalLinesImage,
'drawing_horizontal_line': horizontalLineImage,
'optional_photo_01': optionalImage1,
'optional_photo_02': optionalImage2,
'optional_photo_03': optionalImage3,
'optional_photo_04': optionalImage4,
};
}
// --- ADDED: Methods to format data for FTP submission as separate JSON files ---
/// Creates a single JSON object with all submission data, mimicking 'db.json'
Map<String, dynamic> toDbJson() {
return {
'firstSampler': firstSampler,
'firstSamplerUserId': firstSamplerUserId,
'secondSampler': secondSampler,
'samplingDate': samplingDate,
'samplingTime': samplingTime,
'selectedStateName': selectedStateName,
'selectedCategoryName': selectedCategoryName,
'selectedStation': selectedStation,
'stationLatitude': stationLatitude,
'stationLongitude': stationLongitude,
'currentLatitude': currentLatitude,
'currentLongitude': currentLongitude,
'distanceDifference': distanceDifference,
'distanceDifferenceRemarks': distanceDifferenceRemarks,
'classificationId': classificationId,
'selectedClassification': selectedClassification,
'optionalRemark1': optionalRemark1,
'optionalRemark2': optionalRemark2,
'optionalRemark3': optionalRemark3,
'optionalRemark4': optionalRemark4,
'reportId': reportId,
'submissionStatus': submissionStatus,
'submissionMessage': submissionMessage,
};
}
/// Creates a JSON object for basic form info, mimicking 'basic_form.json'.
Map<String, dynamic> toBasicFormJson() {
return {
'tech_name': firstSampler,
'sampler_2ndname': secondSampler?['user_name'],
'sample_date': samplingDate,
'sample_time': samplingTime,
'sample_state': selectedStateName,
'station_id': selectedStation?['tbl_station_code'],
'station_latitude': stationLatitude,
'station_longitude': stationLongitude,
'latitude': currentLatitude,
'longitude': currentLongitude,
'sample_id': reportId, // Using reportId as a unique identifier for the sample.
};
}
/// Creates a JSON object for sensor readings, mimicking 'reading.json'.
Map<String, dynamic> toReadingJson() {
return {
'classification': selectedClassification?['classification_name'],
'classification_id': classificationId,
'optional_remark_1': optionalRemark1,
'optional_remark_2': optionalRemark2,
'optional_remark_3': optionalRemark3,
'optional_remark_4': optionalRemark4,
'distance_difference': distanceDifference,
'distance_difference_remarks': distanceDifferenceRemarks,
};
}
/// Creates a JSON object for manual info, mimicking 'manual_info.json'.
Map<String, dynamic> toManualInfoJson() {
return {
// Tarball forms don't have a specific 'weather' or general remarks field,
// so we use the distance remarks as a stand-in if available.
'remarks_event': distanceDifferenceRemarks,
'remarks_lab': null,
};
}
}