From 5b33c6770b2e35aac4aecf1d0839f66ab604873e Mon Sep 17 00:00:00 2001 From: "saad.siddiq" Date: Fri, 30 Jan 2026 16:00:46 +0500 Subject: [PATCH] Add Report creation, report saving mechanism --- .../activities/DashboardActivity.java | 172 +++++++++++++++++- .../adapters/ReportListAdapter.java | 81 +++++++++ .../qc_android/apiservice/ApiService.java | 7 + .../qc_android/db/DatabaseHelper.java | 10 +- .../qc_android/db/ReportRepository.java | 140 ++++++++++++++ .../qc_android/db/ReportWrapper.java | 39 ++++ .../fragments/FragmentQcTerryThree.java | 45 ++++- .../fragments/FragmentQcTerryTwo.java | 2 - .../qc_android/models/DataEntryModel.java | 15 +- .../qc_android/utils/FileUtils.java | 40 ++++ .../utils/ReportSelectListener.java | 9 + .../viewmodels/ServiceViewModel.java | 47 +++-- app/src/main/res/drawable/card_background.xml | 8 + .../res/layout-sw800dp/activity_dashboard.xml | 23 ++- .../main/res/layout-sw800dp/check_point.xml | 12 +- .../res/layout-sw800dp/report_list_item.xml | 48 +++++ .../main/res/layout/activity_dashboard.xml | 97 +++++++++- app/src/main/res/layout/activity_login.xml | 41 +++-- app/src/main/res/layout/activity_qcterry.xml | 8 + app/src/main/res/layout/check_point.xml | 145 +++++---------- .../res/layout/custom_layout_for_image.xml | 6 +- .../main/res/layout/fragment_qc_terry_one.xml | 153 ++++++++-------- .../res/layout/fragment_qc_terry_three.xml | 81 +++++---- .../main/res/layout/fragment_qc_terry_two.xml | 78 +++----- app/src/main/res/layout/report_list_item.xml | 55 ++++++ 25 files changed, 1012 insertions(+), 350 deletions(-) create mode 100644 app/src/main/java/com/utopiaindustries/qc_android/adapters/ReportListAdapter.java create mode 100644 app/src/main/java/com/utopiaindustries/qc_android/db/ReportRepository.java create mode 100644 app/src/main/java/com/utopiaindustries/qc_android/db/ReportWrapper.java create mode 100644 app/src/main/java/com/utopiaindustries/qc_android/utils/ReportSelectListener.java create mode 100644 app/src/main/res/drawable/card_background.xml create mode 100644 app/src/main/res/layout-sw800dp/report_list_item.xml create mode 100644 app/src/main/res/layout/report_list_item.xml diff --git a/app/src/main/java/com/utopiaindustries/qc_android/activities/DashboardActivity.java b/app/src/main/java/com/utopiaindustries/qc_android/activities/DashboardActivity.java index eb62074..80da27b 100644 --- a/app/src/main/java/com/utopiaindustries/qc_android/activities/DashboardActivity.java +++ b/app/src/main/java/com/utopiaindustries/qc_android/activities/DashboardActivity.java @@ -7,11 +7,14 @@ import android.content.pm.PackageManager; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; import android.util.DisplayMetrics; import android.util.Log; import android.view.Window; import android.view.WindowManager; import android.widget.Button; +import android.widget.TextView; import android.widget.Toast; import androidx.activity.EdgeToEdge; @@ -23,6 +26,8 @@ import androidx.core.view.WindowCompat; import androidx.core.view.WindowInsetsCompat; import androidx.core.view.WindowInsetsControllerCompat; import androidx.lifecycle.ViewModelProvider; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; import androidx.viewpager.widget.ViewPager; import com.utopiaindustries.qc_android.R; @@ -30,15 +35,31 @@ import com.utopiaindustries.qc_android.adapters.PagerAdapter; import com.google.android.material.tabs.TabLayout; +import com.utopiaindustries.qc_android.adapters.ReportListAdapter; +import com.utopiaindustries.qc_android.db.ReportRepository; +import com.utopiaindustries.qc_android.db.ReportWrapper; import com.utopiaindustries.qc_android.helper.Helper; +import com.utopiaindustries.qc_android.utils.FileUtils; +import com.utopiaindustries.qc_android.utils.NotificationHelper; import com.utopiaindustries.qc_android.utils.ProgressDialogFragment; +import com.utopiaindustries.qc_android.utils.ReportSelectListener; import com.utopiaindustries.qc_android.viewmodels.ServiceViewModel; -public class DashboardActivity extends AppCompatActivity { +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.util.List; +import java.util.Map; + +public class DashboardActivity extends AppCompatActivity implements ReportSelectListener { Button btnCreateReport, btnFetchProduct, btnLogout, btnAppUpdate, btnReportUpload; ServiceViewModel serviceViewModel; + RecyclerView reportRecyclerview; + TextView reportTextView; + ReportListAdapter reportListAdapter; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -70,7 +91,30 @@ public class DashboardActivity extends AppCompatActivity { }); btnLogout.setOnClickListener(v -> {}); btnAppUpdate.setOnClickListener(v -> {}); - btnReportUpload.setOnClickListener(v -> {}); + btnReportUpload.setOnClickListener(v -> { + if (!Helper.isNetworkConnected(this)) { + Toast.makeText(this, "No Internet Connection Available", Toast.LENGTH_LONG).show(); + } + else { + pushDataToUind(); + } + }); + } + + private void pushDataToUind() { + ReportRepository repository = new ReportRepository(this); + List reportWrapperList = repository.findAllReports(); + + if (reportWrapperList.isEmpty()) { + Toast.makeText(this, "No Reports to upload", Toast.LENGTH_SHORT).show(); + return; + } + + Toast.makeText(this, "Uploading Reports. Please wait", Toast.LENGTH_LONG).show(); + //disableButtons(); + + // Start processing reports one by one + //processReportsSequentially(repository, reportWrapperList, 0, 100); } public void initializeLayout() { @@ -79,6 +123,7 @@ public class DashboardActivity extends AppCompatActivity { btnLogout = findViewById(R.id.btn_logout); btnAppUpdate = findViewById(R.id.btn_app_update); btnReportUpload = findViewById(R.id.btn_reports_upload); + reportRecyclerview = findViewById(R.id.report_recyclerview); serviceViewModel = new ViewModelProvider(this).get(ServiceViewModel.class); @@ -107,7 +152,7 @@ public class DashboardActivity extends AppCompatActivity { } }); - + loadReportList(); } private void getScreenSize() { @@ -169,4 +214,125 @@ public class DashboardActivity extends AppCompatActivity { progressDialog.dismiss(); } } + + public void loadReportList() { + ReportRepository repository = new ReportRepository(this); + List reportWrappers = repository.findAllReports(); + + reportListAdapter = new ReportListAdapter(reportWrappers, this, this); + reportRecyclerview.setLayoutManager(new LinearLayoutManager(this)); + reportRecyclerview.setAdapter(reportListAdapter); + + } + + @Override + public void onItemClicked(ReportWrapper reportWrapper) { + Toast.makeText(this, String.valueOf(reportWrapper.getId()), Toast.LENGTH_SHORT).show(); + } + + /*private void processReportsSequentially(ReportRepository repository, + List wrappers, + int currentIndex, int notificationId) { + // Check if all reports have been processed + if (currentIndex >= wrappers.size()) { + //enableButtons(); + return; + } + + ReportWrapper wrapper = wrappers.get(currentIndex); + + try { + // Load only one report at a time to save memory + byte[] fileData = FileUtils.readFile(wrapper.getContent()); + InspectionReport report = deserializeReport(fileData, wrapper); + + final int currentNotificationId = notificationId; + final int nextIndex = currentIndex + 1; + final int nextNotificationId = notificationId + 1; + + InspectionReportService service = InspectionReportService.getInstance(); + service.saveReport(report, new SubmitReportCallback() { + @Override + public void onSuccess(Map responseMap) { + String result = responseMap.get("result"); + String reportId = responseMap.get("reportId"); + String sku = responseMap.get("Sku"); + String generatedAt = responseMap.get("GeneratedAt"); + String modelNumber = responseMap.get("modelNumber"); + String code = responseMap.get("Code"); + + report.setPreviousReportId(Long.parseLong(reportId)); + report.setGeneratedAt(generatedAt); + report.setCode(code); + + // update status + repository.updateSyncStatus(report.getWrapperId()); + + saveReportToDraft(report, reportId); + + NotificationHelper.showNotificationForReportUpload( + HomeActivity.this, + currentNotificationId, + "Upload Success", + "SKU: " + report.getItems().get(0).getSku() + " uploaded successfully."); + + // Process next report after a short delay to free memory + new Handler(Looper.getMainLooper()).postDelayed(() -> { + // Force garbage collection before processing next report + System.gc(); + processReportsSequentially(repository, wrappers, nextIndex, nextNotificationId); + }, 500); // 500ms delay between reports + } + + @Override + public void onFailure(Throwable throwable) { + if (throwable.getMessage() != null && throwable.getMessage().contains("Duplicated")) { + Log.e("Request: ", "Duplicated"); + // update status + repository.updateSyncStatus(report.getWrapperId()); + // remove file + FileUtils.deleteFile(report.getFilePath()); + } else { + NotificationHelper.showNotificationForReportUpload( + HomeActivity.this, + currentNotificationId, + "Upload Failed", + "SKU: " + report.getItems().get(0).getSku() + " failed.\nReason: " + throwable.getMessage()); + } + + // Continue with next report even if current one fails + new Handler(Looper.getMainLooper()).postDelayed(() -> { + System.gc(); + processReportsSequentially(repository, wrappers, nextIndex, nextNotificationId); + }, 500); + } + }); + + } catch (Exception e) { + e.printStackTrace(); + // If there's an error loading the report, skip it and continue with the next one + NotificationHelper.showNotificationForReportUpload( + DashboardActivity.this, + notificationId, + "Upload Failed", + "Reason: " + e.getMessage()); + + new Handler(Looper.getMainLooper()).postDelayed(() -> { + processReportsSequentially(repository, wrappers, currentIndex + 1, notificationId + 1); + }, 500); + } + }*/ + + /*private InspectionReport deserializeReport(byte[] data, InspectionReportWrapper wrapper) + throws IOException, ClassNotFoundException { + + try (ByteArrayInputStream byteIn = new ByteArrayInputStream(data); + ObjectInputStream in = new ObjectInputStream(byteIn)) { + + InspectionReport report = (InspectionReport) in.readObject(); + report.setWrapperId(wrapper.getId()); + report.setFilePath(wrapper.getContent()); + return report; + } + }*/ } \ No newline at end of file diff --git a/app/src/main/java/com/utopiaindustries/qc_android/adapters/ReportListAdapter.java b/app/src/main/java/com/utopiaindustries/qc_android/adapters/ReportListAdapter.java new file mode 100644 index 0000000..754dd8f --- /dev/null +++ b/app/src/main/java/com/utopiaindustries/qc_android/adapters/ReportListAdapter.java @@ -0,0 +1,81 @@ +package com.utopiaindustries.qc_android.adapters; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.cardview.widget.CardView; +import androidx.recyclerview.widget.RecyclerView; + +import com.utopiaindustries.qc_android.R; +import com.utopiaindustries.qc_android.db.ReportWrapper; +import com.utopiaindustries.qc_android.utils.ReportSelectListener; +import com.utopiaindustries.qc_android.utils.SelectListener; + +import java.text.ParseException; +import java.util.List; + +public class ReportListAdapter extends RecyclerView.Adapter { + private List reportList; + private ReportSelectListener listener; + private Context context; + + public ReportListAdapter(List reports, ReportSelectListener listener, Context context) { + this.reportList = reports; + this.listener = listener; + this.context = context; + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.report_list_item, parent, false); + return new ViewHolder(view); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, @SuppressLint("RecyclerView") int position) { + try { + holder.bindData(reportList.get(position)); + + holder.cardView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + listener.onItemClicked(reportList.get(position)); + } + }); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + @Override + public int getItemCount() { + return reportList.size(); + } + + public static class ViewHolder extends RecyclerView.ViewHolder { + private final TextView txtCategory, txtCreatedBy, reportDate; + private final CardView cardView; + + public ViewHolder(@NonNull View itemView) { + super(itemView); + txtCategory = itemView.findViewById(R.id.txt_category); + txtCreatedBy = itemView.findViewById(R.id.txt_createdBy); + reportDate = itemView.findViewById(R.id.report_date); + cardView = itemView.findViewById(R.id.main_container); + } + + public void bindData(ReportWrapper report) { + + reportDate.setText(String.valueOf(report.getId())); + txtCategory.setText("Category"); + txtCreatedBy.setText("Created By"); + } + } +} diff --git a/app/src/main/java/com/utopiaindustries/qc_android/apiservice/ApiService.java b/app/src/main/java/com/utopiaindustries/qc_android/apiservice/ApiService.java index f232169..fc5604a 100644 --- a/app/src/main/java/com/utopiaindustries/qc_android/apiservice/ApiService.java +++ b/app/src/main/java/com/utopiaindustries/qc_android/apiservice/ApiService.java @@ -1,8 +1,10 @@ package com.utopiaindustries.qc_android.apiservice; +import com.utopiaindustries.qc_android.models.DataEntryModel; import com.utopiaindustries.qc_android.models.InspectionCheckPoint; import java.util.List; +import java.util.Map; import retrofit2.Call; import retrofit2.http.Body; @@ -50,4 +52,9 @@ public interface ApiService { @GET("rest/uic/inspection-report/checkpoints") Call> fetchCheckPoints(); + + @POST("rest/uic/inspection-report") + Call> saveReport( + @Body DataEntryModel inspectionReport + ); } diff --git a/app/src/main/java/com/utopiaindustries/qc_android/db/DatabaseHelper.java b/app/src/main/java/com/utopiaindustries/qc_android/db/DatabaseHelper.java index 8c6c8c7..89d21c4 100644 --- a/app/src/main/java/com/utopiaindustries/qc_android/db/DatabaseHelper.java +++ b/app/src/main/java/com/utopiaindustries/qc_android/db/DatabaseHelper.java @@ -79,7 +79,7 @@ public class DatabaseHelper extends SQLiteOpenHelper { public static final String REPORT_TABLE_NAME = "report"; public static final String REPORT_COLUMN_ID = "id"; public static final String REPORT_COLUMN_CONTENT = "content"; - public static final String REPORT_COLUMN_SYNCED = "synced"; + //public static final String REPORT_COLUMN_SYNCED = "synced"; /* * draft report table @@ -150,9 +150,7 @@ public class DatabaseHelper extends SQLiteOpenHelper { String CREATE_REPORT_TABLE = "CREATE TABLE " + REPORT_TABLE_NAME + " (" + REPORT_COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT," + - REPORT_COLUMN_CONTENT + " TEXT NOT NULL," + - REPORT_COLUMN_SYNCED + " INTEGER DEFAULT 0 CHECK(synced IN (0, 1))" - + ")"; + REPORT_COLUMN_CONTENT + " TEXT NOT NULL )"; String CREATE_DRAFT_REPORT_TABLE = "CREATE TABLE " + DRAFT_REPORT_TABLE_NAME + " (" + DRAFT_REPORT_COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + @@ -189,7 +187,7 @@ public class DatabaseHelper extends SQLiteOpenHelper { db.execSQL( CREATE_CHECKPOINT_TABLE ); ///db.execSQL( CREATE_DEFECT_TABLE ); //db.execSQL( CREATE_UNIT_TABLE ); - //db.execSQL( CREATE_REPORT_TABLE ); + db.execSQL( CREATE_REPORT_TABLE ); //db.execSQL( CREATE_DRAFT_REPORT_TABLE); //db.execSQL( CREATE_SKU_CHECKPOINT_TABLE ); //db.execSQL( CREATE_INSPECTION_LABEL_TABLE ); @@ -203,7 +201,7 @@ public class DatabaseHelper extends SQLiteOpenHelper { db.execSQL( "DROP TABLE IF EXISTS " + CHECKPOINT_TABLE_NAME ); //db.execSQL( "DROP TABLE IF EXISTS " + DEFECT_TABLE_NAME ); //db.execSQL( "DROP TABLE IF EXISTS " + UNIT_TABLE_NAME ); - //db.execSQL( "DROP TABLE IF EXISTS " + REPORT_TABLE_NAME ); + db.execSQL( "DROP TABLE IF EXISTS " + REPORT_TABLE_NAME ); // db.execSQL( "DROP TABLE IF EXISTS " + DRAFT_REPORT_TABLE_NAME ); //db.execSQL( "DROP TABLE IF EXISTS " + CHECKPOINT_SKU_TABLE_NAME ); //db.execSQL( "DROP TABLE IF EXISTS " + INSPECTION_LABEL_TABLE_NAME ); diff --git a/app/src/main/java/com/utopiaindustries/qc_android/db/ReportRepository.java b/app/src/main/java/com/utopiaindustries/qc_android/db/ReportRepository.java new file mode 100644 index 0000000..47e9b85 --- /dev/null +++ b/app/src/main/java/com/utopiaindustries/qc_android/db/ReportRepository.java @@ -0,0 +1,140 @@ +package com.utopiaindustries.qc_android.db; + +import static com.utopiaindustries.qc_android.db.DatabaseHelper.DRAFT_REPORT_TABLE_NAME; +import static com.utopiaindustries.qc_android.db.DatabaseHelper.REPORT_TABLE_NAME; + +import android.annotation.SuppressLint; +import android.content.ContentValues; +import android.content.Context; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.RejectedExecutionException; + +public class ReportRepository { + + private final DatabaseHelper dbHelper; + private SQLiteDatabase database; + private final ExecutorService executorService; + private Context cxt; + + public ReportRepository(Context context) { + dbHelper = new DatabaseHelper(context); + executorService = Executors.newSingleThreadExecutor(); + cxt = context; + } + + private void openDatabase() { + try { + if (database == null || !database.isOpen() || !database.isDbLockedByCurrentThread()) { + database = dbHelper.getWritableDatabase(); + } + } + catch (Exception e) { + e.printStackTrace(); + } + } + + public void insert(ReportWrapper wrapper) { + executeSafely(() -> { + openDatabase(); + database.beginTransaction(); + try { + ContentValues values = new ContentValues(); + values.put(DatabaseHelper.REPORT_COLUMN_CONTENT, wrapper.getContent()); + database.insertWithOnConflict(REPORT_TABLE_NAME, null, values, SQLiteDatabase.CONFLICT_REPLACE); + database.setTransactionSuccessful(); + + } catch (Exception e) { + e.printStackTrace(); + } finally { + database.endTransaction(); + close(); + } + }); + } + + /* + * Close the database when all operations are complete + */ + public void close() { + if (database != null && database.isOpen()) { + database.close(); + } + } + + /* + * Executes a task safely, ensuring the ExecutorService is still active + */ + private void executeSafely(Runnable task) { + try { + if (!executorService.isShutdown()) { + executorService.submit(task); + } else { + // Handle the situation when the executor is already shut down + System.out.println("Task execution rejected because ExecutorService is shut down"); + } + } catch (RejectedExecutionException e) { + e.printStackTrace(); + } + } + + @SuppressLint("Range") + public List findAllReports() { + List reports = new ArrayList<>(); + openDatabase(); + + try (Cursor cursor = database.query(REPORT_TABLE_NAME, + null, + null, + null, + null, + null, + null)) { + + if (cursor != null && cursor.moveToFirst()) { + do { + ReportWrapper wrapper = new ReportWrapper(); + wrapper.setId(cursor.getLong(cursor.getColumnIndex(DatabaseHelper.REPORT_COLUMN_ID))); + wrapper.setContent(cursor.getString(cursor.getColumnIndex(DatabaseHelper.REPORT_COLUMN_CONTENT))); + reports.add(wrapper); + } while (cursor.moveToNext()); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + close(); + } + return reports; + } + + /* + * Delete Draft Record from draft table + * */ + + public void deleteDraftRecordById(Long id) { + executeSafely(() -> { + openDatabase(); + database.beginTransaction(); + try { + String whereClause = DatabaseHelper.DRAFT_REPORT_COLUMN_ID + " = ?"; + + String[] whereArgs = {String.valueOf(id)}; + + database.delete(DRAFT_REPORT_TABLE_NAME, whereClause, whereArgs); + + database.setTransactionSuccessful(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + database.endTransaction(); + close(); + } + + }); + } +} diff --git a/app/src/main/java/com/utopiaindustries/qc_android/db/ReportWrapper.java b/app/src/main/java/com/utopiaindustries/qc_android/db/ReportWrapper.java new file mode 100644 index 0000000..317f3ee --- /dev/null +++ b/app/src/main/java/com/utopiaindustries/qc_android/db/ReportWrapper.java @@ -0,0 +1,39 @@ +package com.utopiaindustries.qc_android.db; + +public class ReportWrapper { + + private long id; + private String content; + + public ReportWrapper(long id, String content) { + this.id = id; + this.content = content; + } + + public ReportWrapper() { + } + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + @Override + public String toString() { + return "ReportWrapper{" + + "id=" + id + + ", content='" + content + '\'' + + '}'; + } +} diff --git a/app/src/main/java/com/utopiaindustries/qc_android/fragments/FragmentQcTerryThree.java b/app/src/main/java/com/utopiaindustries/qc_android/fragments/FragmentQcTerryThree.java index b342260..ccdaba4 100644 --- a/app/src/main/java/com/utopiaindustries/qc_android/fragments/FragmentQcTerryThree.java +++ b/app/src/main/java/com/utopiaindustries/qc_android/fragments/FragmentQcTerryThree.java @@ -1,5 +1,6 @@ package com.utopiaindustries.qc_android.fragments; +import android.content.Intent; import android.os.Bundle; import android.util.Log; import android.view.LayoutInflater; @@ -15,8 +16,15 @@ import androidx.annotation.Nullable; import androidx.fragment.app.Fragment; import com.utopiaindustries.qc_android.R; +import com.utopiaindustries.qc_android.activities.DashboardActivity; +import com.utopiaindustries.qc_android.db.ReportRepository; +import com.utopiaindustries.qc_android.db.ReportWrapper; import com.utopiaindustries.qc_android.models.DataEntryModel; import com.utopiaindustries.qc_android.utils.AppDataManager; +import com.utopiaindustries.qc_android.utils.FileUtils; + +import java.io.ByteArrayOutputStream; +import java.io.ObjectOutputStream; public class FragmentQcTerryThree extends Fragment { @@ -125,15 +133,38 @@ public class FragmentQcTerryThree extends Fragment { // Show success message Toast.makeText(getActivity(), "Data submitted successfully!", Toast.LENGTH_SHORT).show(); DataEntryModel dataEntryModel = AppDataManager.getInstance().getCurrentDataEntry(); - Log.e("DataEntryModel: " ,""+dataEntryModel); - // Update UI - //btnSubmit.setText("Submitted ✓"); - //btnSubmit.setEnabled(false); - //btnSubmit.setBackgroundColor(getResources().getColor(android.R.color.darker_gray)); + Log.e("DataEntryModel: ", "" + dataEntryModel); + saveReport(dataEntryModel); - // You would typically: // 1. Send data to API/backend // 2. Save to database - // 3. Navigate to success screen + // 3. Navigate to main screen + } + + public void saveReport(DataEntryModel dataEntryModel) { + try { + // convert into byte array + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + ObjectOutputStream objectOutputStream = new ObjectOutputStream(byteArrayOutputStream); + objectOutputStream.writeObject(dataEntryModel); + objectOutputStream.flush(); + byte[] bytes = byteArrayOutputStream.toByteArray(); + // write bytes in file + long epochSeconds = System.currentTimeMillis() / 1000; + //String fileName = "Report-" + inspectionReport.getItems().get(0).getSku() + ".bin"; + String fileName = "Report-" + epochSeconds + ".bin"; + String savedPath = FileUtils.writeFile(requireActivity(), bytes, fileName); + System.out.println(savedPath); + + new ReportRepository(getActivity()).insert( + new ReportWrapper(0, savedPath) + ); + + Intent intent = new Intent(getActivity(), DashboardActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); + startActivity(intent); + } catch (Exception e) { + e.printStackTrace(); + } } } diff --git a/app/src/main/java/com/utopiaindustries/qc_android/fragments/FragmentQcTerryTwo.java b/app/src/main/java/com/utopiaindustries/qc_android/fragments/FragmentQcTerryTwo.java index b4626b2..e4d646b 100644 --- a/app/src/main/java/com/utopiaindustries/qc_android/fragments/FragmentQcTerryTwo.java +++ b/app/src/main/java/com/utopiaindustries/qc_android/fragments/FragmentQcTerryTwo.java @@ -244,7 +244,6 @@ public class FragmentQcTerryTwo extends Fragment implements CheckPointAdapter.On result -> { if (result.getResultCode() == getActivity().RESULT_OK && photoUri != null) { //imageView.setImageURI(photoUri); - dataEntryModel.setSelectedImageUri(photoUri); Helper.uriToByteArrayAsync( getContext(), @@ -273,7 +272,6 @@ public class FragmentQcTerryTwo extends Fragment implements CheckPointAdapter.On uri -> { if (uri != null) { //imageView.setImageURI(uri); - dataEntryModel.setSelectedImageUri(uri); Helper.uriToByteArrayAsync( getContext(), diff --git a/app/src/main/java/com/utopiaindustries/qc_android/models/DataEntryModel.java b/app/src/main/java/com/utopiaindustries/qc_android/models/DataEntryModel.java index 4fe86f9..7505da7 100644 --- a/app/src/main/java/com/utopiaindustries/qc_android/models/DataEntryModel.java +++ b/app/src/main/java/com/utopiaindustries/qc_android/models/DataEntryModel.java @@ -2,10 +2,11 @@ package com.utopiaindustries.qc_android.models; import android.net.Uri; +import java.io.Serializable; import java.util.ArrayList; import java.util.List; -public class DataEntryModel { +public class DataEntryModel implements Serializable { private static final long serialVersionUID = 1L; // Personal Info @@ -21,7 +22,6 @@ public class DataEntryModel { private String company; private String position; - private Uri selectedImageUri; private List checkPointList = new ArrayList<>(); // Constructor @@ -38,7 +38,6 @@ public class DataEntryModel { this.city = other.city; this.company = other.company; this.position = other.position; - this.selectedImageUri = other.selectedImageUri; this.checkPointList = new ArrayList<>(other.checkPointList); } @@ -50,14 +49,6 @@ public class DataEntryModel { this.checkPointList = checkPointList; } - public Uri getSelectedImageUri() { - return selectedImageUri; - } - - public void setSelectedImageUri(Uri selectedImageUri) { - this.selectedImageUri = selectedImageUri; - } - public String getPosition() { return position; } @@ -122,7 +113,6 @@ public class DataEntryModel { city = null; company = null; position = null; - selectedImageUri = null; checkPointList.clear(); } @@ -136,7 +126,6 @@ public class DataEntryModel { ", city='" + city + '\'' + ", company='" + company + '\'' + ", position='" + position + '\'' + - ", selectedImageUri=" + selectedImageUri + ", checkPointListSize=" + checkPointList + '}'; } diff --git a/app/src/main/java/com/utopiaindustries/qc_android/utils/FileUtils.java b/app/src/main/java/com/utopiaindustries/qc_android/utils/FileUtils.java index 198d5bb..e20d13b 100644 --- a/app/src/main/java/com/utopiaindustries/qc_android/utils/FileUtils.java +++ b/app/src/main/java/com/utopiaindustries/qc_android/utils/FileUtils.java @@ -5,6 +5,7 @@ import android.content.Context; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; @@ -16,6 +17,45 @@ import java.io.ObjectOutputStream; public class FileUtils { + public static String writeFile( Context context , + byte[] content, + String fileName ){ + FileOutputStream fos = null; + try { + // Get the file path in the internal storage + File file = new File( context.getFilesDir(), fileName); + // Open the file output stream + fos = new FileOutputStream(file); + fos.write( content ); + fos.flush(); + return file.getAbsolutePath(); + } catch (IOException e) { + e.printStackTrace(); + } finally { + if (fos != null) { + try { + fos.close(); + } catch (IOException e) { + e.printStackTrace(); + } + } + } + return ""; + } + + public static byte[] readFile(String filePath) throws IOException { + File file = new File(filePath); + try (FileInputStream fis = new FileInputStream(file); + ByteArrayOutputStream baos = new ByteArrayOutputStream()) { + byte[] buffer = new byte[8192]; + int bytesRead; + while ((bytesRead = fis.read(buffer)) != -1) { + baos.write(buffer, 0, bytesRead); + } + return baos.toByteArray(); + } + } + // Save model object as byte array file public static String saveObjectToFile(Context context, Object model, String fileName) { File file = new File(context.getFilesDir(), fileName); diff --git a/app/src/main/java/com/utopiaindustries/qc_android/utils/ReportSelectListener.java b/app/src/main/java/com/utopiaindustries/qc_android/utils/ReportSelectListener.java new file mode 100644 index 0000000..e6cd8b8 --- /dev/null +++ b/app/src/main/java/com/utopiaindustries/qc_android/utils/ReportSelectListener.java @@ -0,0 +1,9 @@ +package com.utopiaindustries.qc_android.utils; + + +import com.utopiaindustries.qc_android.db.ReportWrapper; + +public interface ReportSelectListener { + + void onItemClicked(ReportWrapper reportWrapper); +} diff --git a/app/src/main/java/com/utopiaindustries/qc_android/viewmodels/ServiceViewModel.java b/app/src/main/java/com/utopiaindustries/qc_android/viewmodels/ServiceViewModel.java index 7f143d3..ebb82ac 100644 --- a/app/src/main/java/com/utopiaindustries/qc_android/viewmodels/ServiceViewModel.java +++ b/app/src/main/java/com/utopiaindustries/qc_android/viewmodels/ServiceViewModel.java @@ -10,6 +10,7 @@ import androidx.lifecycle.ViewModel; import com.utopiaindustries.qc_android.apiservice.ApiService; import com.utopiaindustries.qc_android.apiservice.ApiServiceFactory; import com.utopiaindustries.qc_android.db.CheckpointRepository; +import com.utopiaindustries.qc_android.models.DataEntryModel; import com.utopiaindustries.qc_android.models.InspectionCheckPoint; import java.util.List; @@ -229,35 +230,31 @@ public class ServiceViewModel extends ViewModel { }); }*/ - /*public void saveHSEData(HseReportRequest hseRequestModel) { + /*public void saveReport(DataEntryModel hseRequestModel) { isLoading.setValue(true); - // Execute the task in the background - executorService.execute(() -> { - try { - apiService.saveHseReport(hseRequestModel).enqueue(new Callback() { - @Override - public void onResponse(Call call, Response response) { - isLoading.setValue(false); - if (response.isSuccessful() && response.body() != null) { - userSaveLiveData.setValue(response.body()); - } else { - errorLiveData.setValue(response.message()); - } + try { + apiService.saveReport(hseRequestModel).enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + isLoading.setValue(false); + if (response.isSuccessful() && response.body() != null) { + userSaveLiveData.setValue(response.body()); + } else { + errorLiveData.setValue(response.message()); } + } - @Override - public void onFailure(Call call, Throwable t) { - isLoading.setValue(false); - errorLiveData.setValue(t.getMessage()); - } - }); - } catch (Exception e) { - errorLiveData.postValue(e.getMessage()); - isLoading.postValue(false); - } - }); - + @Override + public void onFailure(Call call, Throwable t) { + isLoading.setValue(false); + errorLiveData.setValue(t.getMessage()); + } + }); + } catch (Exception e) { + errorLiveData.postValue(e.getMessage()); + isLoading.postValue(false); + } }*/ public LiveData getLoginUser() { diff --git a/app/src/main/res/drawable/card_background.xml b/app/src/main/res/drawable/card_background.xml new file mode 100644 index 0000000..4e6d576 --- /dev/null +++ b/app/src/main/res/drawable/card_background.xml @@ -0,0 +1,8 @@ + + + + + diff --git a/app/src/main/res/layout-sw800dp/activity_dashboard.xml b/app/src/main/res/layout-sw800dp/activity_dashboard.xml index f3beb9e..5d5f7d3 100644 --- a/app/src/main/res/layout-sw800dp/activity_dashboard.xml +++ b/app/src/main/res/layout-sw800dp/activity_dashboard.xml @@ -23,7 +23,7 @@ android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Home" + android:text="Dashboard" android:textColor="@color/white" android:textSize="@dimen/_12sdp" app:layout_constraintBottom_toBottomOf="@+id/toolbar" @@ -50,7 +50,28 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/toolbar"> + + + + + android:background="@drawable/card_background" + android:foreground="?attr/selectableItemBackground" + app:cardCornerRadius="12dp" + app:cardElevation="6dp"> diff --git a/app/src/main/res/layout-sw800dp/report_list_item.xml b/app/src/main/res/layout-sw800dp/report_list_item.xml new file mode 100644 index 0000000..88ea6f4 --- /dev/null +++ b/app/src/main/res/layout-sw800dp/report_list_item.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_dashboard.xml b/app/src/main/res/layout/activity_dashboard.xml index 8777d86..aace309 100644 --- a/app/src/main/res/layout/activity_dashboard.xml +++ b/app/src/main/res/layout/activity_dashboard.xml @@ -23,9 +23,9 @@ android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="Home - Mobile" + android:text="Dashboard" android:textColor="@color/white" - android:textSize="@dimen/_15sdp" + android:textSize="@dimen/_12sdp" app:layout_constraintBottom_toBottomOf="@+id/toolbar" app:layout_constraintEnd_toEndOf="@+id/toolbar" app:layout_constraintStart_toStartOf="parent" @@ -50,7 +50,100 @@ app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/toolbar"> + + + + + + + +