diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b068fd1..3c2a98c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -2,6 +2,9 @@ + @@ -66,6 +69,17 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/java/com/utopiaindustries/qualitychecker/apiservice/RetrofitClient.java b/app/src/main/java/com/utopiaindustries/qualitychecker/apiservice/RetrofitClient.java index c8355b5..2db4921 100644 --- a/app/src/main/java/com/utopiaindustries/qualitychecker/apiservice/RetrofitClient.java +++ b/app/src/main/java/com/utopiaindustries/qualitychecker/apiservice/RetrofitClient.java @@ -20,7 +20,7 @@ import retrofit2.converter.gson.GsonConverterFactory; public class RetrofitClient { private final static String BASE_URL = "https://portal.utopiaindustries.pk/uind/"; - // private final static String BASE_URL = "http://192.168.91.16:8080/uind/"; + // private final static String BASE_URL = "http://192.168.90.27:8080/uind/";//"http://192.168.91.16:8080/uind/"; private static Retrofit retrofit; diff --git a/app/src/main/java/com/utopiaindustries/qualitychecker/async/ImageProcessor.java b/app/src/main/java/com/utopiaindustries/qualitychecker/async/ImageProcessor.java index f63a442..5d5a35f 100644 --- a/app/src/main/java/com/utopiaindustries/qualitychecker/async/ImageProcessor.java +++ b/app/src/main/java/com/utopiaindustries/qualitychecker/async/ImageProcessor.java @@ -28,7 +28,7 @@ public class ImageProcessor { mainHandler = new Handler(Looper.getMainLooper()); } - public void compressImageFromUriAsync(final Context context, final Uri uri, final int maxSizeKB, final OnImageCompressedListener listener) { + /*public void compressImageFromUriAsync(final Context context, final Uri uri, final int maxSizeKB, final OnImageCompressedListener listener) { backgroundHandler.post(() -> { byte[] imageData = getBytesFromUri(context, uri); if (imageData != null) { @@ -43,7 +43,7 @@ public class ImageProcessor { }); } }); - } + }*/ private byte[] getBytesFromUri(Context context, Uri uri) { if (uri != null) { @@ -87,11 +87,62 @@ public class ImageProcessor { return null; } + public void uriToByteArrayAsync(Context context, Uri uri, int targetSizeInKB, OnImageCompressedListener listener) { + new Thread(() -> { + try { + // Target file size in bytes + int targetSizeInBytes = targetSizeInKB * 1024; + + // Load the image as a Bitmap without scaling + Bitmap bitmap; + try (InputStream inputStream = context.getContentResolver().openInputStream(uri)) { + bitmap = BitmapFactory.decodeStream(inputStream); + } + + if (bitmap == null) { + throw new IOException("Failed to decode image from URI."); + } + + // Initial quality for compression + int minQuality = 10; + int maxQuality = 100; + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + int quality = maxQuality; + + // Use binary search for quality adjustment to find optimal size faster + while (minQuality <= maxQuality) { + byteArrayOutputStream.reset(); + bitmap.compress(Bitmap.CompressFormat.JPEG, quality, byteArrayOutputStream); + + int byteSize = byteArrayOutputStream.size(); + if (byteSize > targetSizeInBytes) { + maxQuality = quality - 5; + } else if (byteSize < targetSizeInBytes) { + minQuality = quality + 5; + } else { + break; + } + quality = (minQuality + maxQuality) / 2; + } + + // Return compressed byte array + listener.onCompressed(byteArrayOutputStream.toByteArray()); + } catch (IOException e) { + listener.onError(e); + } + }).start(); + } + public void shutdown() { executorService.shutdown(); } - public interface OnImageCompressedListener { + /*public interface OnImageCompressedListener { void onImageCompressed(byte[] compressedData); + }*/ + + public interface OnImageCompressedListener { + void onCompressed(byte[] compressedImage); + void onError(Exception e); } } diff --git a/app/src/main/java/com/utopiaindustries/qualitychecker/db/DatabaseHelper.java b/app/src/main/java/com/utopiaindustries/qualitychecker/db/DatabaseHelper.java index 28b8a77..10db032 100644 --- a/app/src/main/java/com/utopiaindustries/qualitychecker/db/DatabaseHelper.java +++ b/app/src/main/java/com/utopiaindustries/qualitychecker/db/DatabaseHelper.java @@ -66,6 +66,16 @@ public class DatabaseHelper extends SQLiteOpenHelper { public static final String REPORT_COLUMN_CONTENT = "content"; public static final String REPORT_COLUMN_SYNCED = "synced"; + /* + * draft report table + * */ + public static final String DRAFT_REPORT_TABLE_NAME = "draft_report"; + public static final String DRAFT_REPORT_COLUMN_ID = "id"; + public static final String DRAFT_REPORT_COLUMN_CONTENT = "content"; + //public static final String DRAFT_REPORT_COLUMN_FNSKU = "fnsku"; + public static final String DRAFT_REPORT_COLUMN_SYNCED = "synced"; + + /* * sku checkpoints standard * */ @@ -129,6 +139,13 @@ public class DatabaseHelper extends SQLiteOpenHelper { REPORT_COLUMN_SYNCED + " INTEGER DEFAULT 0 CHECK(synced IN (0, 1))" + ")"; + String CREATE_DRAFT_REPORT_TABLE = "CREATE TABLE " + DRAFT_REPORT_TABLE_NAME + " (" + + DRAFT_REPORT_COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + + DRAFT_REPORT_COLUMN_CONTENT + " TEXT NOT NULL, " + + // DRAFT_REPORT_COLUMN_FNSKU + " TEXT NOT NULL," + + DRAFT_REPORT_COLUMN_SYNCED + " INTEGER DEFAULT 0 CHECK(synced IN (0, 1))" + + ")"; + String CREATE_SKU_CHECKPOINT_TABLE = "CREATE TABLE " + CHECKPOINT_SKU_TABLE_NAME + " (" + CHECKPOINT_SKU_SKU + " TEXT NOT NULL," + CHECKPOINT_SKU_MARKETPLACE + " TEXT NOT NULL," + @@ -142,6 +159,7 @@ public class DatabaseHelper extends SQLiteOpenHelper { db.execSQL( CREATE_DEFECT_TABLE ); db.execSQL( CREATE_UNIT_TABLE ); db.execSQL( CREATE_REPORT_TABLE ); + db.execSQL( CREATE_DRAFT_REPORT_TABLE); db.execSQL( CREATE_SKU_CHECKPOINT_TABLE ); } @@ -153,6 +171,7 @@ public class DatabaseHelper extends SQLiteOpenHelper { 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 " + DRAFT_REPORT_TABLE_NAME ); db.execSQL( "DROP TABLE IF EXISTS " + CHECKPOINT_SKU_TABLE_NAME ); onCreate(db); } diff --git a/app/src/main/java/com/utopiaindustries/qualitychecker/db/ReportRepository.java b/app/src/main/java/com/utopiaindustries/qualitychecker/db/ReportRepository.java index b20d019..ba054d7 100644 --- a/app/src/main/java/com/utopiaindustries/qualitychecker/db/ReportRepository.java +++ b/app/src/main/java/com/utopiaindustries/qualitychecker/db/ReportRepository.java @@ -1,5 +1,8 @@ package com.utopiaindustries.qualitychecker.db; +import static com.utopiaindustries.qualitychecker.db.DatabaseHelper.DRAFT_REPORT_COLUMN_ID; +import static com.utopiaindustries.qualitychecker.db.DatabaseHelper.DRAFT_REPORT_TABLE_NAME; + import android.annotation.SuppressLint; import android.content.ContentValues; import android.content.Context; @@ -26,8 +29,13 @@ public class ReportRepository { } private void openDatabase() { - if (database == null || !database.isOpen()) { - database = dbHelper.getWritableDatabase(); + try { + if (database == null || !database.isOpen() || !database.isDbLockedByCurrentThread()) { + database = dbHelper.getWritableDatabase(); + } + } + catch (Exception e) { + e.printStackTrace(); } } @@ -50,6 +58,75 @@ public class ReportRepository { }); } + public void insertOrReplaceUser(InspectionReportWrapper wrapper) { + executeSafely(() -> { + openDatabase(); + database.beginTransaction(); + try { + + ContentValues values = new ContentValues(); + values.put(DatabaseHelper.DRAFT_REPORT_COLUMN_ID, wrapper.getId()); // You need to explicitly provide the ID + values.put(DatabaseHelper.DRAFT_REPORT_COLUMN_CONTENT, wrapper.getContent()); + values.put(DatabaseHelper.DRAFT_REPORT_COLUMN_SYNCED, wrapper.isSynced()); + + // Insert or replace a row + database.replace(DRAFT_REPORT_TABLE_NAME, null, values); + } catch (Exception e) { + System.out.println("Draft Button Click-12"); + e.printStackTrace(); + } finally { + System.out.println("Draft Button Click-13"); + database.endTransaction(); + close(); + } + }); + } + + public void insertDraft(InspectionReportWrapper wrapper, String fnsku) { + System.out.println("Report-ID: "+ wrapper.getId()); + executeSafely(() -> { + openDatabase(); + database.beginTransaction(); + try { + ContentValues values = new ContentValues(); + if (wrapper.getId() != 0) { + System.out.println("final-insertion: " + wrapper.getId()); + values.put(DatabaseHelper.DRAFT_REPORT_COLUMN_ID, wrapper.getId()); + } + values.put(DatabaseHelper.DRAFT_REPORT_COLUMN_CONTENT, wrapper.getContent()); + values.put(DatabaseHelper.DRAFT_REPORT_COLUMN_SYNCED, wrapper.isSynced()); + database.insertWithOnConflict(DRAFT_REPORT_TABLE_NAME, null, values, SQLiteDatabase.CONFLICT_REPLACE); + database.setTransactionSuccessful(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + database.endTransaction(); + close(); + } + }); + } + + // Update data based on the id + /*public void updateData(InspectionReportWrapper wrapper) { + + executeSafely(() -> { + openDatabase(); + database.beginTransaction(); + try { + ContentValues values = new ContentValues(); + values.put(DatabaseHelper.DRAFT_REPORT_COLUMN_CONTENT, wrapper.getContent()); + values.put(DatabaseHelper.DRAFT_REPORT_COLUMN_SYNCED, wrapper.isSynced()); + database.update(DRAFT_REPORT_TABLE_NAME, values, DRAFT_REPORT_COLUMN_ID + " = ?", new String[]{String.valueOf(wrapper.getId())}); + database.setTransactionSuccessful(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + database.endTransaction(); + close(); + } + }); + }*/ + public void updateSyncStatus(long id) { executeSafely(() -> { openDatabase(); @@ -102,6 +179,73 @@ public class ReportRepository { return reports; } + /* + * List Of Draft Reports + * */ + @SuppressLint("Range") + public List findAllDraftReports() { + List reports = new ArrayList<>(); + openDatabase(); + + try (Cursor cursor = database.query(DRAFT_REPORT_TABLE_NAME, + null, + null, + null, + null, + null, + null)) { + + if (cursor != null && cursor.moveToFirst()) { + do { + InspectionReportWrapper wrapper = new InspectionReportWrapper(); + wrapper.setId(cursor.getLong(cursor.getColumnIndex(DatabaseHelper.REPORT_COLUMN_ID))); + wrapper.setContent(cursor.getString(cursor.getColumnIndex(DatabaseHelper.REPORT_COLUMN_CONTENT))); + wrapper.setSynced(cursor.getInt(cursor.getColumnIndex(DatabaseHelper.REPORT_COLUMN_SYNCED)) == 1); + reports.add(wrapper); + } while (cursor.moveToNext()); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + close(); + } + return reports; + } + + /* + * Single Draft Report + * */ + @SuppressLint("Range") + public InspectionReportWrapper findDraftReportById(long id) { + InspectionReportWrapper report = null; + openDatabase(); + + String selection = DatabaseHelper.REPORT_COLUMN_ID + " = ?"; + String[] selectionArgs = { String.valueOf(id) }; // The ID to search for + + try (Cursor cursor = database.query(DRAFT_REPORT_TABLE_NAME, + null, // Columns - null selects all columns + selection, // The WHERE clause + selectionArgs, // The arguments for the WHERE clause + null, // Group by + null, // Having + null)) { // Order by + + if (cursor != null && cursor.moveToFirst()) { + report = new InspectionReportWrapper(); + report.setId(cursor.getLong(cursor.getColumnIndex(DatabaseHelper.REPORT_COLUMN_ID))); + report.setContent(cursor.getString(cursor.getColumnIndex(DatabaseHelper.REPORT_COLUMN_CONTENT))); + report.setSynced(cursor.getInt(cursor.getColumnIndex(DatabaseHelper.REPORT_COLUMN_SYNCED)) == 1); + } + } catch (Exception e) { + e.printStackTrace(); + } finally { + close(); + } + + return report; // Returns null if no report is found with the given ID + } + /* * Close the database when all operations are complete */ @@ -126,4 +270,30 @@ public class ReportRepository { e.printStackTrace(); } } + + /* + * 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/qualitychecker/models/InspectionItemCheckPoint.java b/app/src/main/java/com/utopiaindustries/qualitychecker/models/InspectionItemCheckPoint.java index 4851fe9..5357b2f 100644 --- a/app/src/main/java/com/utopiaindustries/qualitychecker/models/InspectionItemCheckPoint.java +++ b/app/src/main/java/com/utopiaindustries/qualitychecker/models/InspectionItemCheckPoint.java @@ -1,8 +1,7 @@ package com.utopiaindustries.qualitychecker.models; -import androidx.annotation.NonNull; - import java.io.Serializable; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.UUID; @@ -23,6 +22,7 @@ public class InspectionItemCheckPoint implements Serializable { private byte[] file; private String imagePath; private UUID uuid; + private List files = new ArrayList<>(); public InspectionItemCheckPoint(){ this.uuid = UUID.randomUUID(); // Generate a random UUID @@ -122,7 +122,14 @@ public class InspectionItemCheckPoint implements Serializable { this.quantities = quantities; } - @NonNull + public List getFiles() { + return files; + } + + public void addImageList(byte[] image) { + this.files.add(image); + } + @Override public String toString() { return "InspectionItemCheckPoint{" + @@ -138,6 +145,7 @@ public class InspectionItemCheckPoint implements Serializable { ", file=" + Arrays.toString(file) + ", imagePath='" + imagePath + '\'' + ", uuid=" + uuid + + ", imageList=" + files + '}'; } diff --git a/app/src/main/java/com/utopiaindustries/qualitychecker/models/InspectionReport.java b/app/src/main/java/com/utopiaindustries/qualitychecker/models/InspectionReport.java index 7202508..c9b86e3 100644 --- a/app/src/main/java/com/utopiaindustries/qualitychecker/models/InspectionReport.java +++ b/app/src/main/java/com/utopiaindustries/qualitychecker/models/InspectionReport.java @@ -19,6 +19,9 @@ public class InspectionReport implements Serializable { private long functionId; private String generalRemarks; private String reportResult; + private String qualityAuditor; + private String productionRepresentative; + private String qcRepresentative; // wrapper List items; @@ -134,6 +137,30 @@ public class InspectionReport implements Serializable { this.wrapperId = wrapperId; } + public String getQualityAuditor() { + return qualityAuditor; + } + + public void setQualityAuditor(String qualityAuditor) { + this.qualityAuditor = qualityAuditor; + } + + public String getProductionRepresentative() { + return productionRepresentative; + } + + public void setProductionRepresentative(String productionRepresentative) { + this.productionRepresentative = productionRepresentative; + } + + public String getQcRepresentative() { + return qcRepresentative; + } + + public void setQcRepresentative(String qcRepresentative) { + this.qcRepresentative = qcRepresentative; + } + public String getFilePath() { return filePath; } @@ -156,7 +183,11 @@ public class InspectionReport implements Serializable { ", functionId=" + functionId + ", generalRemarks='" + generalRemarks + '\'' + ", reportResult='" + reportResult + '\'' + + ", qualityAuditor='" + qualityAuditor + '\'' + + ", productionRepresentative='" + productionRepresentative + '\'' + + ", qcRepresentative='" + qcRepresentative + '\'' + ", items=" + items + + ", filePath='" + filePath + '\'' + ", wrapperId=" + wrapperId + '}'; } diff --git a/app/src/main/java/com/utopiaindustries/qualitychecker/models/InspectionReportItem.java b/app/src/main/java/com/utopiaindustries/qualitychecker/models/InspectionReportItem.java index 63bdb89..214d074 100644 --- a/app/src/main/java/com/utopiaindustries/qualitychecker/models/InspectionReportItem.java +++ b/app/src/main/java/com/utopiaindustries/qualitychecker/models/InspectionReportItem.java @@ -30,6 +30,11 @@ public class InspectionReportItem implements Serializable { private float cartonsSelected; private float packsSelected; private float piecesSelected; + + private float checkedCartonsSelected; + private float checkedPacksSelected; + private float checkedPiecesSelected; + private String packingDetails; private String sampleSize; private String dateAdded; @@ -255,6 +260,30 @@ public class InspectionReportItem implements Serializable { this.fnsku = fnsku; } + public float getCheckedCartonsSelected() { + return checkedCartonsSelected; + } + + public void setCheckedCartonsSelected(float checkedCartonsSelected) { + this.checkedCartonsSelected = checkedCartonsSelected; + } + + public float getCheckedPacksSelected() { + return checkedPacksSelected; + } + + public void setCheckedPacksSelected(float checkedPacksSelected) { + this.checkedPacksSelected = checkedPacksSelected; + } + + public float getCheckedPiecesSelected() { + return checkedPiecesSelected; + } + + public void setCheckedPiecesSelected(float checkedPiecesSelected) { + this.checkedPiecesSelected = checkedPiecesSelected; + } + @NonNull @Override public String toString() { diff --git a/app/src/main/java/com/utopiaindustries/qualitychecker/models/callback/SaveDraftReportCallback.java b/app/src/main/java/com/utopiaindustries/qualitychecker/models/callback/SaveDraftReportCallback.java new file mode 100644 index 0000000..ab441bd --- /dev/null +++ b/app/src/main/java/com/utopiaindustries/qualitychecker/models/callback/SaveDraftReportCallback.java @@ -0,0 +1,4 @@ +package com.utopiaindustries.qualitychecker.models.callback; + +public interface SaveDraftReportCallback extends SaveCallback{ +} \ No newline at end of file diff --git a/app/src/main/java/com/utopiaindustries/qualitychecker/service/InspectionReportService.java b/app/src/main/java/com/utopiaindustries/qualitychecker/service/InspectionReportService.java index 76cc57d..8fad9cd 100644 --- a/app/src/main/java/com/utopiaindustries/qualitychecker/service/InspectionReportService.java +++ b/app/src/main/java/com/utopiaindustries/qualitychecker/service/InspectionReportService.java @@ -1,6 +1,8 @@ package com.utopiaindustries.qualitychecker.service; import android.content.Context; +import android.content.SharedPreferences; +import android.util.Log; import androidx.annotation.NonNull; @@ -26,6 +28,7 @@ import com.utopiaindustries.qualitychecker.models.Product; import com.utopiaindustries.qualitychecker.models.callback.SaveCheckpointCallback; import com.utopiaindustries.qualitychecker.models.callback.SaveDefectCallback; import com.utopiaindustries.qualitychecker.models.callback.SaveDimensionCallback; +import com.utopiaindustries.qualitychecker.models.callback.SaveDraftReportCallback; import com.utopiaindustries.qualitychecker.models.callback.SaveItemCallback; import com.utopiaindustries.qualitychecker.models.callback.SaveProductCallBack; import com.utopiaindustries.qualitychecker.models.callback.SaveReportCallback; @@ -170,7 +173,52 @@ public class InspectionReportService { } } + private synchronized void saveDraftReportInDb( final Context context, + final InspectionReport inspectionReport, + final SaveDraftReportCallback callback) throws IOException { + SharedPreferences sharedPreferences = context.getSharedPreferences("login_prefs", Context.MODE_PRIVATE); + long draftReportId = Long.parseLong(sharedPreferences.getString("draftReportId", null)); + //System.out.println(sharedPreferences.getString("draftReportId", null)); + //System.out.println("Draft Button Click-8: " + draftReportId); + + try { + // convert into byte array + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + ObjectOutputStream objectOutputStream = new ObjectOutputStream( byteArrayOutputStream ); + objectOutputStream.writeObject( inspectionReport ); + objectOutputStream.flush(); + byte[] bytes = byteArrayOutputStream.toByteArray(); + // write bytes in file + long epochSeconds = System.currentTimeMillis() / 1000; + String fileName = "Report-" + epochSeconds + ".bin"; + String savedPath = FileUtils.writeFile( context, bytes, fileName ); + //System.out.println(fileName + "---" + savedPath ); + new ReportRepository( context ).insertDraft( + new InspectionReportWrapper( draftReportId, savedPath, false ), + store.getReport().getItems().get(0).getFnsku() + ); + callback.onSuccess(); + } catch ( Exception e ){ + callback.onFailure( new Exception( "Failed to Save in DB" ) ); + e.printStackTrace(); + } + } + + public void saveDraftInLocalDb( Context context, + InspectionReport inspectionReport , + SaveDraftReportCallback callback ){ + + new Thread(() -> { + populateDefectsInBackground( inspectionReport ); + //post report + try { + saveDraftReportInDb( context, inspectionReport , callback ); + } catch (IOException e) { + throw new RuntimeException(e); + } + }).start(); + } public void saveInLocalDb( Context context, InspectionReport inspectionReport , diff --git a/app/src/main/java/com/utopiaindustries/qualitychecker/service/NetworkService.java b/app/src/main/java/com/utopiaindustries/qualitychecker/service/NetworkService.java index 6ae1eed..5a1f7a6 100644 --- a/app/src/main/java/com/utopiaindustries/qualitychecker/service/NetworkService.java +++ b/app/src/main/java/com/utopiaindustries/qualitychecker/service/NetworkService.java @@ -130,6 +130,9 @@ public class NetworkService extends Service { } catch ( Exception e){ e.printStackTrace(); } + catch (OutOfMemoryError e) { + e.printStackTrace(); + } } } return reports; diff --git a/app/src/main/java/com/utopiaindustries/qualitychecker/ui/activities/HomeActivity.java b/app/src/main/java/com/utopiaindustries/qualitychecker/ui/activities/HomeActivity.java index 6c9506c..5385dac 100644 --- a/app/src/main/java/com/utopiaindustries/qualitychecker/ui/activities/HomeActivity.java +++ b/app/src/main/java/com/utopiaindustries/qualitychecker/ui/activities/HomeActivity.java @@ -9,6 +9,7 @@ import android.content.pm.ActivityInfo; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.os.Bundle; +import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.ImageView; @@ -22,8 +23,10 @@ import androidx.core.view.ViewCompat; import androidx.core.view.WindowInsetsCompat; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; +import androidx.viewpager.widget.ViewPager; import com.bumptech.glide.Glide; +import com.google.android.material.tabs.TabLayout; import com.utopiaindustries.qualitychecker.R; import com.utopiaindustries.qualitychecker.apiservice.ApiService; import com.utopiaindustries.qualitychecker.apiservice.ApiServiceFactory; @@ -44,7 +47,10 @@ import com.utopiaindustries.qualitychecker.notification.NotificationHelper; import com.utopiaindustries.qualitychecker.receiver.NetworkReceiver; import com.utopiaindustries.qualitychecker.service.InspectionReportService; import com.utopiaindustries.qualitychecker.store.Store; +import com.utopiaindustries.qualitychecker.ui.activities.fragments.ReportsFragment; +import com.utopiaindustries.qualitychecker.ui.adapter.PagerAdapter; import com.utopiaindustries.qualitychecker.ui.adapter.ReportAdapter; +import com.utopiaindustries.qualitychecker.ui.fragments.FirstStepFragment; import java.util.List; import java.util.Objects; @@ -56,15 +62,20 @@ import retrofit2.Response; public class HomeActivity extends AppCompatActivity implements View.OnClickListener { private Button createReportBtn,refreshReportsBtn,logoutBtn,fetchProductBtn; - private RecyclerView recyclerView; + //private RecyclerView recyclerView; private ApiService apiService; - private TextView usernameTitle, emptyReportTextView; + private TextView usernameTitle;//, emptyReportTextView; private ImageView profileImage; private Store store; private InspectionReportService inspectionReportService; private NetworkReceiver networkReceiver; private boolean isReceiverRegistered = false; + TabLayout tabLayout; + ViewPager viewPager; + + PagerAdapter pagerAdapter; + @SuppressLint("SourceLockedOrientationActivity") @Override protected void onCreate(Bundle savedInstanceState) { @@ -89,23 +100,35 @@ public class HomeActivity extends AppCompatActivity implements View.OnClickListe refreshReportsBtn = findViewById( R.id.refresh_btn ); logoutBtn = findViewById( R.id.logout_btn ); fetchProductBtn = findViewById( R.id.fetch_product_btn ); - recyclerView = findViewById( R.id.reports_recyclerview ); + //recyclerView = findViewById( R.id.reports_recyclerview ); usernameTitle = findViewById( R.id.username_title ); profileImage = findViewById( R.id.profile_image ); - emptyReportTextView = findViewById( R.id.empty_report_text ); + //emptyReportTextView = findViewById( R.id.empty_report_text ); + + viewPager = (ViewPager) findViewById(R.id.viewpager); + pagerAdapter = new PagerAdapter(getSupportFragmentManager(), HomeActivity.this); + viewPager.setAdapter(pagerAdapter); + + tabLayout = (TabLayout) findViewById(R.id.tab_layout); + tabLayout.setupWithViewPager(viewPager); + + for (int i = 0; i < tabLayout.getTabCount(); i++) { + TabLayout.Tab tab = tabLayout.getTabAt(i); + tab.setCustomView(pagerAdapter.getTabView(i)); + } refreshReportsBtn.setOnClickListener( this ); createReportBtn.setOnClickListener( this ); logoutBtn.setOnClickListener( this ); fetchProductBtn.setOnClickListener( this ); - recyclerView.setLayoutManager( new LinearLayoutManager( this ) ); + //recyclerView.setLayoutManager( new LinearLayoutManager( this ) ); updateProfileImage(); - refreshReportData(); + // refreshReportData(); } - private void refreshReportData(){ + /*private void refreshReportData(){ SharedPreferences sharedPreferences = getSharedPreferences("login_prefs", Context.MODE_PRIVATE); String username = sharedPreferences.getString("username", null ); apiService.fetchAllReports( username ).enqueue( @@ -130,13 +153,21 @@ public class HomeActivity extends AppCompatActivity implements View.OnClickListe } } ); - } + }*/ @Override public void onClick(View v) { int id = v.getId(); if( id == R.id.create_report_btn ){ + SharedPreferences sharedPreferences = getSharedPreferences("login_prefs", Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sharedPreferences.edit(); + + editor.putString("draftReportId", "0"); + editor.apply(); + Intent intent = new Intent( this, MainActivity.class ); + intent.putExtra("fromClass", "Home"); + intent.putExtra("draftID", "0"); startActivity( intent ); } if( id == R.id.logout_btn ){ @@ -150,8 +181,11 @@ public class HomeActivity extends AppCompatActivity implements View.OnClickListe finish(); } if( id == R.id.refresh_btn ){ - refreshReportData(); + // refreshReportData(); updateProfileImage(); + ReportsFragment secondFragment = (ReportsFragment) getSupportFragmentManager().getFragments().get(0); + secondFragment.updateData(); + } if( id == R.id.fetch_product_btn ){ if( isNetworkConnected() ) { @@ -183,6 +217,7 @@ public class HomeActivity extends AppCompatActivity implements View.OnClickListe editor.apply(); usernameTitle.setText( response.body().getName() ); store.setEmployeePhoto( response.body() ); + Log.e("Profile-Image: ",""+store.getProfileImage()); Glide.with( getBaseContext() ) .load( store.getProfileImage( ) ) .into( profileImage ); @@ -376,7 +411,7 @@ public class HomeActivity extends AppCompatActivity implements View.OnClickListe @Override protected void onResume() { super.onResume(); - refreshReportData(); + // refreshReportData(); } @Override diff --git a/app/src/main/java/com/utopiaindustries/qualitychecker/ui/activities/MainActivity.java b/app/src/main/java/com/utopiaindustries/qualitychecker/ui/activities/MainActivity.java index 1a8bf53..6f863ed 100644 --- a/app/src/main/java/com/utopiaindustries/qualitychecker/ui/activities/MainActivity.java +++ b/app/src/main/java/com/utopiaindustries/qualitychecker/ui/activities/MainActivity.java @@ -6,6 +6,7 @@ import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.ActivityInfo; import android.os.Bundle; +import android.util.Log; import android.view.View; import android.view.ViewTreeObserver; import android.widget.Toast; @@ -22,16 +23,27 @@ import androidx.navigation.Navigation; import androidx.navigation.fragment.NavHostFragment; import com.utopiaindustries.qualitychecker.R; +import com.utopiaindustries.qualitychecker.db.ReportRepository; +import com.utopiaindustries.qualitychecker.models.InspectionReport; +import com.utopiaindustries.qualitychecker.models.InspectionReportWrapper; import com.utopiaindustries.qualitychecker.store.Store; import com.utopiaindustries.qualitychecker.ui.fragments.FirstStepFragment; import com.utopiaindustries.qualitychecker.ui.fragments.SecondStepFragment; import com.google.zxing.integration.android.IntentIntegrator; import com.google.zxing.integration.android.IntentResult; +import com.utopiaindustries.qualitychecker.utils.FileUtils; + +import java.io.ByteArrayInputStream; +import java.io.ObjectInputStream; +import java.util.ArrayList; +import java.util.List; public class MainActivity extends AppCompatActivity implements View.OnClickListener { private NavController navController; private Store store; + private String fromClass; + private String draftReportId; @SuppressLint("SourceLockedOrientationActivity") @Override @@ -47,9 +59,19 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe return insets; }); setRequestedOrientation( ActivityInfo.SCREEN_ORIENTATION_PORTRAIT ); - navController = Navigation.findNavController( this, R.id.nav_host_fragment ); + + fromClass = getIntent().getStringExtra("fromClass"); + draftReportId = getIntent().getStringExtra("draftID"); + + if (fromClass.equalsIgnoreCase("Draft")) { + System.out.println("Draft Report ID: " + draftReportId); + + } + + navController = Navigation.findNavController( this, R.id.nav_host_fragment); // initializing fields updateUsername(); + } private void updateUsername() { if ( store.getReport() != null ) { @@ -76,19 +98,35 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { - IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data); - if (result != null) { - if (result.getContents() == null) { - Toast.makeText(this, "Cancelled", Toast.LENGTH_LONG).show(); - } else { - super.onActivityResult(requestCode, resultCode, data); - FirstStepFragment firstStepFragment = ( FirstStepFragment) getCurrentVisibleFragment(); - firstStepFragment.onBarcodeScanResult( result.getContents() ); + Log.e("requestCode: ",""+requestCode); + Log.e("resultCode: ",""+resultCode); + Log.e("data: ",""+data); + Log.e("-----------------------","---------------------"); + + if (requestCode == IntentIntegrator.REQUEST_CODE) { + Log.e("Zxing barcode scan: ","-----"); + + IntentResult result = IntentIntegrator.parseActivityResult(requestCode, resultCode, data); + + if (result != null) { + if (result.getContents() == null) { + Toast.makeText(this, "Cancelled", Toast.LENGTH_LONG).show(); + } else { + super.onActivityResult(requestCode, resultCode, data); + FirstStepFragment firstStepFragment = ( FirstStepFragment) getCurrentVisibleFragment(); + firstStepFragment.onBarcodeScanResult( result.getContents() ); + } } - } else { - super.onActivityResult(requestCode, resultCode, data); - SecondStepFragment secondStepFragment = ( SecondStepFragment) getCurrentVisibleFragment(); - secondStepFragment.onImagePickerResult( requestCode, resultCode, data ); + } + else if (requestCode != -1 && resultCode == -1 && data == null) { + Log.e("camera ","------- camera ***"); + SecondStepFragment secondStepFragment = ( SecondStepFragment) getCurrentVisibleFragment(); + secondStepFragment.onImagePickerResult( requestCode, resultCode, data ); + } + else if (requestCode != -1 && resultCode == -1 && data != null) { + Log.e("gallery ","------ gallery ***"); + SecondStepFragment secondStepFragment = ( SecondStepFragment) getCurrentVisibleFragment(); + secondStepFragment.onImagePickerResult( requestCode, resultCode, data ); } } @@ -98,4 +136,31 @@ public class MainActivity extends AppCompatActivity implements View.OnClickListe FragmentManager fragmentManager = navHostFragment.getChildFragmentManager(); return fragmentManager.getPrimaryNavigationFragment(); } + + private InspectionReport getSingleReport(InspectionReportWrapper wrapper) { + InspectionReport report = null; + + if (wrapper != null) { + try { + // Get byte array from file content path + byte[] result = FileUtils.readFile(wrapper.getContent()); + + // Convert byte array to an InspectionReport object + ByteArrayInputStream byteIn = new ByteArrayInputStream(result); + ObjectInputStream in = new ObjectInputStream(byteIn); + report = (InspectionReport) in.readObject(); + + // Set additional details from the wrapper + report.setWrapperId(wrapper.getId()); + report.setFilePath(wrapper.getContent()); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + return report; + } + + } \ No newline at end of file diff --git a/app/src/main/java/com/utopiaindustries/qualitychecker/ui/activities/fragments/DraftFragment.java b/app/src/main/java/com/utopiaindustries/qualitychecker/ui/activities/fragments/DraftFragment.java new file mode 100644 index 0000000..c72746b --- /dev/null +++ b/app/src/main/java/com/utopiaindustries/qualitychecker/ui/activities/fragments/DraftFragment.java @@ -0,0 +1,109 @@ +package com.utopiaindustries.qualitychecker.ui.activities.fragments; + +import android.content.Context; +import android.content.Intent; +import android.content.SharedPreferences; +import android.os.Bundle; + +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; +import android.widget.Toast; + +import com.utopiaindustries.qualitychecker.R; +import com.utopiaindustries.qualitychecker.db.ReportRepository; +import com.utopiaindustries.qualitychecker.models.InspectionReport; +import com.utopiaindustries.qualitychecker.models.InspectionReportWrapper; +import com.utopiaindustries.qualitychecker.store.Store; +import com.utopiaindustries.qualitychecker.ui.activities.MainActivity; +import com.utopiaindustries.qualitychecker.ui.adapter.DraftReportAdapter; +import com.utopiaindustries.qualitychecker.ui.adapter.ReportAdapter; +import com.utopiaindustries.qualitychecker.utils.FileUtils; +import com.utopiaindustries.qualitychecker.utils.SelectListener; + +import java.io.ByteArrayInputStream; +import java.io.ObjectInputStream; +import java.util.List; + +public class DraftFragment extends Fragment implements SelectListener { + + RecyclerView recyclerView; + TextView emptyReportTextView; + private Store store; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + // Inflate the layout for this fragment + + View view = inflater.inflate(R.layout.fragment_draft , container, false ); + + initializeViews( view ); + + return view; + } + + private void initializeViews( View view ) { + recyclerView = view.findViewById( R.id.draft_recyclerview ); + emptyReportTextView = view.findViewById(R.id.empty_report_text); + + recyclerView.setLayoutManager( new LinearLayoutManager( getContext() ) ); + store = Store.getInstance(); + + refreshReportData(); + } + + @Override + public void onResume() { + super.onResume(); + + refreshReportData(); + } + + public void refreshReportData() { + ReportRepository repository = new ReportRepository( getContext() ); + List reportWrappers = repository.findAllDraftReports(); + System.out.println(reportWrappers.size()); + + DraftReportAdapter adapter = new DraftReportAdapter( reportWrappers, this ); + recyclerView.setAdapter( adapter ); + + if(reportWrappers.isEmpty()) { + emptyReportTextView.setVisibility( View.VISIBLE ) ; + } + else { + emptyReportTextView.setVisibility( View.INVISIBLE ) ; + } + + + } + + @Override + public void onItemClicked(InspectionReportWrapper reportWrapper) { + //Toast.makeText(getContext(), String.valueOf(reportWrapper.getId()), Toast.LENGTH_SHORT).show(); + + SharedPreferences sharedPreferences = getContext().getSharedPreferences("login_prefs", Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sharedPreferences.edit(); + + editor.putString("draftReportId", String.valueOf(reportWrapper.getId())); + editor.apply(); + + Intent intent = new Intent( getContext(), MainActivity.class ); + intent.putExtra("fromClass", "Draft"); + intent.putExtra("draftID", String.valueOf(reportWrapper.getId())); + startActivity( intent ); + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/utopiaindustries/qualitychecker/ui/activities/fragments/ReportsFragment.java b/app/src/main/java/com/utopiaindustries/qualitychecker/ui/activities/fragments/ReportsFragment.java new file mode 100644 index 0000000..573b271 --- /dev/null +++ b/app/src/main/java/com/utopiaindustries/qualitychecker/ui/activities/fragments/ReportsFragment.java @@ -0,0 +1,112 @@ +package com.utopiaindustries.qualitychecker.ui.activities.fragments; + +import android.content.Context; +import android.content.SharedPreferences; +import android.os.Bundle; + +import androidx.fragment.app.Fragment; +import androidx.recyclerview.widget.LinearLayoutManager; +import androidx.recyclerview.widget.RecyclerView; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; +import android.widget.Toast; + +import com.utopiaindustries.qualitychecker.R; +import com.utopiaindustries.qualitychecker.apiservice.ApiService; +import com.utopiaindustries.qualitychecker.apiservice.ApiServiceFactory; +import com.utopiaindustries.qualitychecker.models.InspectionReport; +import com.utopiaindustries.qualitychecker.receiver.NetworkReceiver; +import com.utopiaindustries.qualitychecker.service.InspectionReportService; +import com.utopiaindustries.qualitychecker.store.Store; +import com.utopiaindustries.qualitychecker.ui.adapter.ReportAdapter; + +import java.util.List; + +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; + +public class ReportsFragment extends Fragment { + + RecyclerView recyclerView; + ApiService apiService; + + Store store; + InspectionReportService inspectionReportService; + TextView emptyReportTextView; + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + + View view = inflater.inflate(R.layout.fragment_reports , container, false ); + + initializeViews( view ); + // Inflate the layout for this fragment + return view; + } + + private void initializeViews( View view ) { + + store = Store.getInstance(); + apiService = ApiServiceFactory.getApiService(); + inspectionReportService = InspectionReportService.getInstance(); + recyclerView = view.findViewById( R.id.reports_recyclerview ); + emptyReportTextView = view.findViewById(R.id.empty_report_text); + + recyclerView.setLayoutManager( new LinearLayoutManager( getContext() ) ); + + //Toast.makeText(getContext(), "Reports Fragment", Toast.LENGTH_LONG).show(); + + + } + + private void refreshReportData(){ + SharedPreferences sharedPreferences = getContext().getSharedPreferences("login_prefs", Context.MODE_PRIVATE); + String username = sharedPreferences.getString("username", null ); + apiService.fetchAllReports( username ).enqueue( + new Callback>() { + @Override + public void onResponse(Call> call, Response> response) { + if( response.isSuccessful() && response.body() != null ){ + System.out.println( response.body().size() ); + ReportAdapter adapter = new ReportAdapter( response.body() ); + recyclerView.setAdapter( adapter ); + if( response.body().isEmpty() ) + emptyReportTextView.setVisibility( View.VISIBLE ) ; + } else { + System.out.println("Error"); + emptyReportTextView.setVisibility( View.VISIBLE ) ; + } + } + @Override + public void onFailure(Call> call, Throwable t) { + System.out.println( t.getMessage() ); + emptyReportTextView.setVisibility( View.VISIBLE ) ; + } + } + ); + } + + @Override + public void onResume() { + super.onResume(); + + refreshReportData(); + } + + public void updateData() { + // Your logic to update fragment data + System.out.println("Reports-Update"); + refreshReportData(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/utopiaindustries/qualitychecker/ui/adapter/CheckPointAdapter.java b/app/src/main/java/com/utopiaindustries/qualitychecker/ui/adapter/CheckPointAdapter.java index 6d056fc..5dde62b 100644 --- a/app/src/main/java/com/utopiaindustries/qualitychecker/ui/adapter/CheckPointAdapter.java +++ b/app/src/main/java/com/utopiaindustries/qualitychecker/ui/adapter/CheckPointAdapter.java @@ -1,12 +1,17 @@ package com.utopiaindustries.qualitychecker.ui.adapter; +import static androidx.core.app.ActivityCompat.startActivityForResult; + import android.app.Activity; +import android.app.AlertDialog; import android.content.Context; import android.content.Intent; -import android.graphics.Bitmap; -import android.graphics.BitmapFactory; +import android.net.Uri; +import android.os.Environment; +import android.provider.MediaStore; import android.text.Editable; import android.text.TextWatcher; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -16,12 +21,12 @@ import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.EditText; import android.widget.ImageButton; -import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.Spinner; import android.widget.TextView; import androidx.annotation.NonNull; +import androidx.core.content.FileProvider; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -30,7 +35,12 @@ import com.utopiaindustries.qualitychecker.models.InspectionCheckPoint; import com.utopiaindustries.qualitychecker.models.InspectionCheckpointSku; import com.utopiaindustries.qualitychecker.models.InspectionDefect; import com.utopiaindustries.qualitychecker.models.InspectionItemCheckPoint; +import com.utopiaindustries.qualitychecker.utils.ImageUriHolder; +import java.io.File; +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; import java.util.List; import java.util.stream.Collectors; @@ -43,6 +53,7 @@ public class CheckPointAdapter extends private final List defectTypes; private final List checkpointSkus; private final Context context; + public CheckPointAdapter( List checkPointList, List checkPoints, List defects, @@ -74,6 +85,7 @@ public class CheckPointAdapter extends @Override public void onBindViewHolder(@NonNull ViewHolder holder, int position) { InspectionItemCheckPoint checkPoint = checkPointList.get( position ); + holder.imageRecyclerView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)); holder.bind(checkPoints, defects, defectTypes, checkPoint, checkpointSkus, context ); //holder.setIsRecyclable(false); @@ -106,16 +118,60 @@ public class CheckPointAdapter extends } holder.imagePicker.setOnClickListener( v -> { - Intent intent = new Intent( Intent.ACTION_GET_CONTENT ); + //-------------------------------------------------------------------------------------- + AlertDialog.Builder builder = new AlertDialog.Builder(context); + builder.setTitle("Choose an Option"); + + String[] options = {"Gallery", "Camera"}; + builder.setItems(options, (dialog, which) -> { + switch (which) { + case 0: + Log.e("Gallery","**********"); + Intent intent = new Intent( Intent.ACTION_GET_CONTENT ); + intent.addCategory( Intent.CATEGORY_OPENABLE ); + intent.setType( "image/*" ); + ( ( Activity ) context ).startActivityForResult( intent, position ); + break; + case 1: + Log.e("Camera: ","***********"); + Intent camera_intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + File imageFile = new File(context.getExternalFilesDir(Environment.DIRECTORY_PICTURES), "captured_image.jpg"); + Uri imageUri = FileProvider.getUriForFile(context, context.getPackageName() + ".fileprovider", imageFile); + //Log.e("imageUri: ",""+imageUri); + ImageUriHolder.getInstance().setImageUri(imageUri); + camera_intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); + ( ( Activity ) context ).startActivityForResult(camera_intent, position); + break; + } + }); + + builder.setNegativeButton("Cancel", (dialog, which) -> dialog.dismiss()); + + AlertDialog dialog = builder.create(); + dialog.show(); + //-------------------------------------------------------------------------------------- + //Image pick from Gallery + /*Intent intent = new Intent( Intent.ACTION_GET_CONTENT ); intent.addCategory( Intent.CATEGORY_OPENABLE ); intent.setType( "image/*" ); - ( ( Activity ) context ).startActivityForResult( intent, position ); + ( ( Activity ) context ).startActivityForResult( intent, position );*/ + + //Now image Pick from Camera + /*Intent camera_intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + ( ( Activity ) context ).startActivityForResult(camera_intent, position);*/ + }); holder.deleteImage.setOnClickListener( v -> { checkPoint.setFile( null ); checkPoint.setImagePath( "" ); - holder.imagePreview.setImageDrawable( null ); + // holder.imagePreview.setImageDrawable( null ); + checkPoint.getFiles().listIterator(checkPoint.getFiles().size()); + if (!checkPoint.getFiles().isEmpty()) { + checkPoint.getFiles().remove(checkPoint.getFiles().size() - 1); + } else { + System.out.println("The list is empty"); + } notifyItemChanged( position ); }); @@ -140,12 +196,15 @@ public class CheckPointAdapter extends private final ImageButton imagePicker,deleteImage,addDefect; private final LinearLayout linearLayout; private final TextView selectedImage,standard; - private final ImageView imagePreview; + //private final ImageView imagePreview; private final RecyclerView defectRecyclerView; private TextWatcher remarksTextWatcher; private CompoundButton.OnCheckedChangeListener okCheckboxListener; private CompoundButton.OnCheckedChangeListener noCheckboxListener; + private RecyclerView imageRecyclerView; + private ImageAdapter imageAdapter; + public ViewHolder(@NonNull View itemView) { super(itemView); remarks = itemView.findViewById(R.id.check_point_remarks); @@ -156,7 +215,10 @@ public class CheckPointAdapter extends selectedImage = itemView.findViewById( R.id.selected_image ); linearLayout = itemView.findViewById(R.id.defect_layout); deleteImage = itemView.findViewById( R.id.delete_image ); - imagePreview = itemView.findViewById( R.id.preview_image ); + // imagePreview = itemView.findViewById( R.id.preview_image ); + + imageRecyclerView = itemView.findViewById(R.id.imageRecyclerView); + defectRecyclerView = itemView.findViewById( R.id.defects_recyclerview ); addDefect = itemView.findViewById( R.id.add_defect ); standard = itemView.findViewById( R.id.standard ); @@ -181,23 +243,38 @@ public class CheckPointAdapter extends } remarks.setText( data.getRemarks() ); - imagePreview.setImageBitmap( null ); + // imagePreview.setImageBitmap( null ); selectedImage.setText( "" ); - if( data.getFile() != null && data.getFile().length > 0 && data.getImagePath() != null && ! data.getImagePath().isEmpty() ){ + /*if( data.getFile() != null && data.getFile().length > 0 && data.getImagePath() != null && ! data.getImagePath().isEmpty() ){ Bitmap bitmap = BitmapFactory.decodeByteArray( data.getFile(), 0 , data.getFile().length ); imagePreview.setImageBitmap( bitmap ); selectedImage.setText( data.getImagePath() ); - } + }*/ // initialize recyclerview List checkPointsList = checkPoints.stream().map(InspectionCheckPoint::getTitle).collect(Collectors.toList()); + // Populate checklist Spinner dropdown ArrayAdapter spinnerAdapter = new ArrayAdapter<>(checkpointSpinner.getContext(), android.R.layout.simple_spinner_item, checkPointsList); spinnerAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); checkpointSpinner.setAdapter(spinnerAdapter); + //image Recyclerview + + if ( data != null ) { + if (data.getFiles() != null) { + List imageList = data.getFiles(); + //System.out.println("Image-size-adapter: " + imageList.size()); + imageRecyclerView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)); + imageAdapter = new ImageAdapter(imageList, context); + imageRecyclerView.setAdapter(imageAdapter); + imageAdapter.notifyItemChanged(getAdapterPosition()); + + } + } + // Pre populate String defaultSelectedItem = data.getTitle(); int defaultPosition = checkPointsList.indexOf(defaultSelectedItem); diff --git a/app/src/main/java/com/utopiaindustries/qualitychecker/ui/adapter/DraftReportAdapter.java b/app/src/main/java/com/utopiaindustries/qualitychecker/ui/adapter/DraftReportAdapter.java new file mode 100644 index 0000000..6cc9dac --- /dev/null +++ b/app/src/main/java/com/utopiaindustries/qualitychecker/ui/adapter/DraftReportAdapter.java @@ -0,0 +1,115 @@ +package com.utopiaindustries.qualitychecker.ui.adapter; + +import android.util.Log; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageButton; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.cardview.widget.CardView; +import androidx.recyclerview.widget.RecyclerView; + +import com.utopiaindustries.qualitychecker.R; +import com.utopiaindustries.qualitychecker.db.ReportRepository; +import com.utopiaindustries.qualitychecker.models.InspectionReport; +import com.utopiaindustries.qualitychecker.models.InspectionReportWrapper; +import com.utopiaindustries.qualitychecker.utils.SelectListener; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.List; +import java.util.Locale; + +public class DraftReportAdapter extends + RecyclerView.Adapter{ + private final List reports; + private SelectListener listener; + + public DraftReportAdapter(List reports, SelectListener listener) { + this.reports = reports; + this.listener = listener; + } + + @NonNull + @Override + public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view = LayoutInflater.from( parent.getContext() ).inflate(R.layout.draft_report_item , parent, false); + return new ViewHolder(view); + } + + @Override + public void onBindViewHolder(@NonNull ViewHolder holder, int position) { + try { + holder.bindDate( reports.get( position ) ); + holder.cardView.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + listener.onItemClicked(reports.get(position)); + } + }); + + holder.delete_image.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Log.e("Delete-Report: ","********"); + new ReportRepository(v.getContext()).deleteDraftRecordById(reports.get(position).getId()); + reports.remove(position); // Remove from the list + notifyItemRemoved(position); // Notify RecyclerView about the item removal + notifyItemRangeChanged(position, reports.size()); + + } + }); + } catch (ParseException e) { + throw new RuntimeException(e); + } + } + + @Override + public int getItemCount() { + return reports.size(); + } + + public static class ViewHolder extends RecyclerView.ViewHolder { + private final TextView codeTv, remarksTv,dateTv,status;//createdByTv,; + private final SimpleDateFormat jsonDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss", Locale.getDefault()); + private final SimpleDateFormat displayDateFormat = new SimpleDateFormat("MMM dd, yyyy hh:mm a", Locale.getDefault()); + private final CardView cardView; + private final ImageButton delete_image; + + public ViewHolder(@NonNull View itemView) { + super(itemView); + codeTv = itemView.findViewById( R.id.code ); + //createdByTv = itemView.findViewById( R.id.created_by ); + delete_image = itemView.findViewById(R.id.delete_image); + remarksTv = itemView.findViewById( R.id.remarks ); + dateTv = itemView.findViewById( R.id.date ); + status = itemView.findViewById( R.id.status ); + cardView = itemView.findViewById(R.id.main_container); + } + + public void bindDate( InspectionReportWrapper report ) throws ParseException { + codeTv.setText( "Report- " + (getAdapterPosition() + 1) ); + //createdByTv.setText("" ); + remarksTv.setText( "" ); + + //Date date = jsonDateFormat.parse( new Date().toString() ); + // Format the date in 12-hour format + //String formattedDateTime = displayDateFormat.format( date ); + String date = displayDateFormat.format(new Date()); + dateTv.setText(date); + /* if( report.getReportResult().equalsIgnoreCase("FAILED") ){ + status.setBackgroundResource( R.drawable.failed_bg ); + } + if( report.getReportResult().equalsIgnoreCase("PASSED") ){ + status.setBackgroundResource( R.drawable.passed_bg ); + } + if( report.getReportResult().equalsIgnoreCase("ON_HOLD") ){ + status.setBackgroundResource( R.drawable.hold_bg ); + }*/ + status.setText("Draft"); + } + } +} diff --git a/app/src/main/java/com/utopiaindustries/qualitychecker/ui/adapter/ImageAdapter.java b/app/src/main/java/com/utopiaindustries/qualitychecker/ui/adapter/ImageAdapter.java new file mode 100644 index 0000000..32f2164 --- /dev/null +++ b/app/src/main/java/com/utopiaindustries/qualitychecker/ui/adapter/ImageAdapter.java @@ -0,0 +1,72 @@ +package com.utopiaindustries.qualitychecker.ui.adapter; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.RecyclerView; + +import com.bumptech.glide.Glide; +import com.bumptech.glide.request.RequestOptions; +import com.utopiaindustries.qualitychecker.R; + +import java.util.List; + +public class ImageAdapter extends RecyclerView.Adapter { + + //private byte[] file; + //private List imageList; + List imageList; + private Context context; + + public ImageAdapter(List imageList, Context context) { + this.imageList = imageList; + this.context = context; + } + + @NonNull + @Override + public ImageViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_image, parent, false); + return new ImageViewHolder(view); + } + + @Override + public void onBindViewHolder(@NonNull ImageViewHolder holder, int position) { + //holder.imageView.setImageBitmap(null); + holder.imageView.setImageResource(R.drawable.img_load); + //Bitmap bitmap = BitmapFactory.decodeByteArray( imageList.get(position), 0 , imageList.get(position).length ); + //holder.imageView.setImageBitmap( bitmap ); + + /*Glide.with(context) + .load(bitmap) // Load the Bitmap directly + .placeholder(R.drawable.img_load) + .apply(new RequestOptions().centerCrop()) // Optional: apply transformations like center crop + .into(holder.imageView);*/ + + Glide.with(context) + .load(imageList.get(position)) // Glide will handle the decoding and placeholder + .placeholder(R.drawable.img_load) + .apply(new RequestOptions().centerCrop()) + .into(holder.imageView); + } + + @Override + public int getItemCount() { + return imageList.size(); + } + + public class ImageViewHolder extends RecyclerView.ViewHolder { + ImageView imageView; + + public ImageViewHolder(@NonNull View itemView) { + super(itemView); + imageView = itemView.findViewById(R.id.imageView); + } + } +} diff --git a/app/src/main/java/com/utopiaindustries/qualitychecker/ui/adapter/PagerAdapter.java b/app/src/main/java/com/utopiaindustries/qualitychecker/ui/adapter/PagerAdapter.java new file mode 100644 index 0000000..8e63269 --- /dev/null +++ b/app/src/main/java/com/utopiaindustries/qualitychecker/ui/adapter/PagerAdapter.java @@ -0,0 +1,62 @@ +package com.utopiaindustries.qualitychecker.ui.adapter; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentStatePagerAdapter; + +import com.utopiaindustries.qualitychecker.R; +import com.utopiaindustries.qualitychecker.ui.activities.fragments.DraftFragment; +import com.utopiaindustries.qualitychecker.ui.activities.fragments.ReportsFragment; + +@SuppressWarnings("deprecation") +public class PagerAdapter extends FragmentStatePagerAdapter { + + String tabTitles[] = new String[]{"Reports", "Draft"}; + Context context; + + public PagerAdapter(FragmentManager fm, Context context) { + super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT); + this.context = context; + } + + @Override + public int getCount() { + return tabTitles.length; + } + + @NonNull + @Override + public Fragment getItem(int position) { + + switch (position) { + case 0: + return new ReportsFragment(); + case 1: + return new DraftFragment(); + } + return null; + } + + @Override + public CharSequence getPageTitle(int position) { + // Generate title based on item position + // return tabTitles[position]; + return null; + } + + public View getTabView(int position) { + View tab = LayoutInflater.from(context).inflate(R.layout.custom_tab, null); + + TextView tv = (TextView) tab.findViewById(R.id.txt_name); + tv.setText(tabTitles[position]); + // tv.setTextSize(TypedValue.COMPLEX_UNIT_SP, context.getResources().getDimension(R.dimen.tab_text_size)); + + return tab; + } +} diff --git a/app/src/main/java/com/utopiaindustries/qualitychecker/ui/fragments/FirstStepFragment.java b/app/src/main/java/com/utopiaindustries/qualitychecker/ui/fragments/FirstStepFragment.java index 59230dc..7ddb6df 100644 --- a/app/src/main/java/com/utopiaindustries/qualitychecker/ui/fragments/FirstStepFragment.java +++ b/app/src/main/java/com/utopiaindustries/qualitychecker/ui/fragments/FirstStepFragment.java @@ -4,6 +4,8 @@ import android.annotation.SuppressLint; import android.content.Context; import android.content.SharedPreferences; import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; import android.text.Editable; import android.text.TextWatcher; import android.view.LayoutInflater; @@ -18,6 +20,7 @@ import android.widget.ImageButton; import android.widget.ImageView; import android.widget.Spinner; import android.widget.TextView; +import android.widget.Toast; import androidx.annotation.NonNull; import androidx.annotation.Nullable; @@ -35,16 +38,24 @@ import com.utopiaindustries.qualitychecker.apiservice.ApiServiceFactory; import com.utopiaindustries.qualitychecker.db.DimensionRepository; import com.utopiaindustries.qualitychecker.db.InspectionCheckpointSkuRepository; import com.utopiaindustries.qualitychecker.db.ProductRepository; +import com.utopiaindustries.qualitychecker.db.ReportRepository; import com.utopiaindustries.qualitychecker.models.InspectionCheckpointSku; import com.utopiaindustries.qualitychecker.models.InspectionDimension; +import com.utopiaindustries.qualitychecker.models.InspectionReport; import com.utopiaindustries.qualitychecker.models.InspectionReportItem; +import com.utopiaindustries.qualitychecker.models.InspectionReportWrapper; import com.utopiaindustries.qualitychecker.models.Product; +import com.utopiaindustries.qualitychecker.models.callback.SaveDraftReportCallback; +import com.utopiaindustries.qualitychecker.notification.NotificationHelper; import com.utopiaindustries.qualitychecker.service.InspectionReportService; import com.utopiaindustries.qualitychecker.store.Store; import com.utopiaindustries.qualitychecker.ui.adapter.ItemHistoryAdapter; import com.google.zxing.integration.android.IntentIntegrator; import com.journeyapps.barcodescanner.CaptureActivity; +import com.utopiaindustries.qualitychecker.utils.FileUtils; +import java.io.ByteArrayInputStream; +import java.io.ObjectInputStream; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -58,8 +69,8 @@ import retrofit2.Response; public class FirstStepFragment extends Fragment implements View.OnClickListener { private NavController navController; - private Button leftFab,rightFab,showHistoryBtn; - private EditText sku,boxCarton,itemPerBox,pieces,packagingDetails,boxCartonSelected,itemPerBoxSelected,piecesSelected; + private Button leftFab,rightFab,showHistoryBtn, btnDraft; + private EditText sku,boxCarton,itemPerBox,pieces,packagingDetails,boxCartonSelected,itemPerBoxSelected,piecesSelected, checkedBoxCartonSelected, checkedItemPerBoxSelected, checkedPiecesSelected; private Spinner markerplace,modelNumber,title,color,size; private CheckBox fri,refri; private ImageButton searchSku,scanBtn; @@ -67,23 +78,62 @@ public class FirstStepFragment extends Fragment implements View.OnClickListener private ImageView profileImage; private ApiService apiService; private Store store; + private InspectionReportService inspectionReportService; + + List sizes = Collections.singletonList("[Size]"); + List colors = Collections.singletonList("[Color]"); + List titles = Collections.singletonList("[Title]"); + List modelNumbers = Collections.singletonList("[Model Number]"); + List marketplaces = Collections.singletonList("[ Marketplace ]"); @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.fragment_first_step , container, false ); + //System.out.println("onCreateView---------->"); + SharedPreferences sharedPreferences = getContext().getSharedPreferences("login_prefs", Context.MODE_PRIVATE); + long draftReportId = Long.parseLong(sharedPreferences.getString("draftReportId", null)); + //System.out.println("onCreateView---------->" + draftReportId); + store = Store.getInstance(); + + if (draftReportId > 0) { + ReportRepository repository = new ReportRepository( getContext() ); + + InspectionReportWrapper report = repository.findDraftReportById(Long.parseLong(String.valueOf(draftReportId))); + InspectionReport inspectionReport = getSingleReport(report); + //System.out.println(inspectionReport); + store.setReport(inspectionReport); + //System.out.println("Report-SKU: " + store.getReport().getItems().get(0).getFnsku()); + } + initializeViews( view ); apiService = ApiServiceFactory.getApiService(); - store = Store.getInstance(); + inspectionReportService = InspectionReportService.getInstance(); + // set on click listener leftFab.setOnClickListener( this ); rightFab.setOnClickListener( this ); searchSku.setOnClickListener( this ); + btnDraft.setOnClickListener( this); scanBtn.setOnClickListener( this ); showHistoryBtn.setOnClickListener( this ); populateItem( store.getProducts(), true ); prePopulateData( store.getProducts() ); updateProfileViews(); + // sku.setText(store.getReport().getItems().get(0).getFnsku()); + + if (draftReportId > 0) { + String selectedString = store.getReport().getItems().get(0).getMarketplace(); + int index = marketplaces.indexOf(selectedString); + markerplace.setSelection(index); + + if( sku.getText() != null ){ + populateProductDataOnSelection( sku.getText().toString(), "", true ); + store.setCheckpointSkus( new ArrayList<>() ); + populateSkuCheckpointsParams( store.getReport().getItems().get(0).getSku(), + store.getReport().getItems().get(0).getMarketplace()); + } + } fri.setOnCheckedChangeListener((buttonView, isChecked) -> { if( isChecked ){ @@ -196,6 +246,8 @@ public class FirstStepFragment extends Fragment implements View.OnClickListener } }); + //onTextChanges logic implementation + //box = 1, itemPerBox, pieces boxCartonSelected.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { @@ -205,6 +257,22 @@ public class FirstStepFragment extends Fragment implements View.OnClickListener @Override public void onTextChanged(CharSequence s, int start, int before, int count) { try { + int packsCount = 0, piecesCount = 0; + int boxCount = Integer.parseInt(s.toString()); + if (itemPerBox.getText().toString().isEmpty() || pieces.getText().toString().isEmpty()) { + Toast.makeText(getContext(), "Enter Item/Pieces Per box", Toast.LENGTH_SHORT).show(); + } + else { + packsCount = (int) store.getProducts().get(0).getItemPerPack(); + piecesCount = (int) store.getProducts().get(0).getItemPerBox(); + + int totalPacks = boxCount * packsCount; + int totalPieces = totalPacks * piecesCount; + + itemPerBoxSelected.setText(String.valueOf(totalPacks)); + piecesSelected.setText(String.valueOf(totalPieces)); + } + store.getReport().getItems().get(0).setCartonsSelected( Long.parseLong( s.toString() ) ); } catch ( Exception e ){ store.getReport().getItems().get(0).setCartonsSelected( 0 ); @@ -217,6 +285,44 @@ public class FirstStepFragment extends Fragment implements View.OnClickListener } }); + //checked Item + checkedBoxCartonSelected.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + try { + int packsCount = 0, piecesCount = 0; + int boxCount = Integer.parseInt(s.toString()); + if (itemPerBox.getText().toString().isEmpty() || pieces.getText().toString().isEmpty()) { + Toast.makeText(getContext(), "Enter Item/Pieces Per box", Toast.LENGTH_SHORT).show(); + } + else { + packsCount = (int) store.getProducts().get(0).getItemPerPack(); + piecesCount = (int) store.getProducts().get(0).getItemPerBox(); + + int totalPacks = boxCount * packsCount; + int totalPieces = totalPacks * piecesCount; + + checkedItemPerBoxSelected.setText(String.valueOf(totalPacks)); + checkedPiecesSelected.setText(String.valueOf(totalPieces)); + } + + store.getReport().getItems().get(0).setCheckedCartonsSelected( Long.parseLong( s.toString() ) ); + } catch ( Exception e ){ + store.getReport().getItems().get(0).setCheckedCartonsSelected( 0 ); + } + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + itemPerBoxSelected.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { @@ -238,6 +344,28 @@ public class FirstStepFragment extends Fragment implements View.OnClickListener } }); + //checkedItemPerBox + checkedItemPerBoxSelected.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + try { + store.getReport().getItems().get(0).setCheckedPacksSelected( Long.parseLong( s.toString() ) ); + } catch ( Exception e ){ + store.getReport().getItems().get(0).setCheckedPacksSelected( 0 ); + } + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + piecesSelected.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { @@ -259,6 +387,28 @@ public class FirstStepFragment extends Fragment implements View.OnClickListener } }); + //checkedPieces + checkedPiecesSelected.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + try { + store.getReport().getItems().get(0).setCheckedPiecesSelected( Long.parseLong( s.toString() ) ); + } catch ( Exception e ){ + store.getReport().getItems().get(0).setCheckedPiecesSelected( 0 ); + } + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + // generalRemarks.addTextChangedListener(new TextWatcher() { // @Override // public void beforeTextChanged(CharSequence s, int start, int count, int after) { @@ -283,19 +433,85 @@ public class FirstStepFragment extends Fragment implements View.OnClickListener return view; } + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + //System.out.println("onViewCreated---------->"); + store = Store.getInstance(); + //System.out.println("Draft Button Click-1" + store.getReport()); + //System.out.println("Report: " + store.getReport()); + //System.out.println("SKU: " + store.getReport().getItems().get(0).getFnsku()); + } + @Override public void onClick(View v) { navController = Navigation.findNavController( requireView() ); + if (v.getId() == R.id.button_draft_first) { + + //--Draft Incomplete Report + //Log.e("sku: ",""+sku.getText().toString()); + //Log.e("Market-place: ",""+store.getReport().getItems().get(0).getMarketplace()); + if(!sku.getText().toString().isEmpty() && !store.getReport().getItems().get(0).getMarketplace().equalsIgnoreCase("[ Marketplace ]")) { + if (store.getReport() != null) { + inspectionReportService.saveDraftInLocalDb(getContext(), store.getReport(), new SaveDraftReportCallback() { + @Override + public void onSuccess() { + Handler handler = new Handler(Looper.getMainLooper()); + handler.post(() -> { + // progressBar.setVisibility(View.INVISIBLE); + SharedPreferences sharedPreferences = getContext().getSharedPreferences("login_prefs", Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sharedPreferences.edit(); + + editor.putString("draftReportId", "0"); + editor.apply(); + + Objects.requireNonNull(getActivity()).finish(); + NotificationHelper.showNotification(Objects.requireNonNull(getContext()), + "Utopia QA App", + "Report is successfully drafted"); + + Toast.makeText(getContext(), "Report Saved as Draft", Toast.LENGTH_SHORT).show(); + + }); + } + + @Override + public void onFailure(Throwable throwable) { + Handler handler = new Handler(Looper.getMainLooper()); + handler.post(() -> { + Toast.makeText(getContext(), throwable.getMessage(), Toast.LENGTH_LONG).show(); + //progressBar.setVisibility(View.INVISIBLE); + NotificationHelper.showNotification(Objects.requireNonNull(getContext()), + "Utopia QA App", + "Error in saving report"); + }); + } + }); + } + } + else { + Toast.makeText(getContext(),"Please enter or scan sku details", Toast.LENGTH_SHORT).show(); + } + //--- + + } if( v.getId() == R.id.button_left_frag_1 ){ if( getActivity() != null ){ getActivity().finish(); } } if( v.getId() == R.id.button_right_frag_1 ){ - navController.navigate( R.id.action_firstStepFragment_to_secondStepFragment ); + if (!sku.getText().toString().isEmpty() && !store.getReport().getItems().get(0).getMarketplace().equalsIgnoreCase("[ Marketplace ]")) { + navController.navigate( R.id.action_firstStepFragment_to_secondStepFragment ); + } + else { + Toast.makeText(getContext(),"Please enter or scan sku details", Toast.LENGTH_SHORT).show(); + } + } if( v.getId() == R.id.search_sku_btn ){ - if( sku.getText() != null ){ + if( sku.getText() != null && !sku.getText().toString().isEmpty() ){ populateProductDataOnSelection( sku.getText().toString(), "", true ); store.setCheckpointSkus( new ArrayList<>() ); populateSkuCheckpointsParams( store.getReport().getItems().get(0).getSku(), @@ -344,6 +560,7 @@ public class FirstStepFragment extends Fragment implements View.OnClickListener } } private void prePopulateData( List products ){ + System.out.println("prePopulateData: " + store.getReport().getItems().get(0).getFnsku()); fri.setChecked( store.getReport().getFri() ); refri.setChecked( ! store.getReport().getFri() ); // sku @@ -397,6 +614,12 @@ public class FirstStepFragment extends Fragment implements View.OnClickListener boxCartonSelected.setText( String.valueOf( store.getReport().getItems().get(0).getCartonsSelected() )); itemPerBoxSelected.setText( String.valueOf( store.getReport().getItems().get(0).getPacksSelected() ) ); piecesSelected.setText( String.valueOf( store.getReport().getItems().get(0).getPiecesSelected() ) ); + + checkedBoxCartonSelected.setText( String.valueOf( store.getReport().getItems().get(0).getCheckedCartonsSelected() )); + checkedItemPerBoxSelected.setText( String.valueOf( store.getReport().getItems().get(0).getCheckedPacksSelected() ) ); + checkedPiecesSelected.setText( String.valueOf( store.getReport().getItems().get(0).getCheckedPiecesSelected() ) ); + + // generalRemarks.setText( store.getReport().getItems().get(0).getSampleSize() ); store.getReport().getItems().get(0).setTotalPresentPieces( Long.parseLong( inventory ) ); @@ -415,7 +638,7 @@ public class FirstStepFragment extends Fragment implements View.OnClickListener private void populateSize( List products ){ - List sizes = Collections.singletonList("[Size]"); + if( ! products.isEmpty() ){ sizes = products.stream().map( Product::getSmSize ).distinct().filter(Objects::nonNull).collect(Collectors.toList() ); } @@ -430,7 +653,7 @@ public class FirstStepFragment extends Fragment implements View.OnClickListener } private void populateColor( List products ){ - List colors = Collections.singletonList("[Color]"); + if( ! products.isEmpty() ){ colors = products.stream().map( Product::getSmColor ).distinct().filter(Objects::nonNull).collect(Collectors.toList() ); } @@ -445,7 +668,7 @@ public class FirstStepFragment extends Fragment implements View.OnClickListener } private void populateTitle( List products ){ - List titles = Collections.singletonList("[Title]"); + if( ! products.isEmpty() ){ titles = products.stream().map( Product::getTitle ).distinct().filter(Objects::nonNull).collect(Collectors.toList()) ; } @@ -459,7 +682,7 @@ public class FirstStepFragment extends Fragment implements View.OnClickListener private void populateModelNumber( List products ){ - List modelNumbers = Collections.singletonList("[Model Number]"); + if( ! products.isEmpty() ){ modelNumbers = products.stream().map( Product::getModelNumber ).distinct().filter(Objects::nonNull).collect(Collectors.toList() ) ; } @@ -473,7 +696,7 @@ public class FirstStepFragment extends Fragment implements View.OnClickListener } private void populateMarketplaces( List products ){ - List marketplaces = Collections.singletonList("[ Marketplace ]"); + if( ! products.isEmpty() ){ marketplaces = products.stream().map( Product::getMarketplace ).distinct().filter(Objects::nonNull).collect(Collectors.toList() ); } @@ -493,6 +716,7 @@ public class FirstStepFragment extends Fragment implements View.OnClickListener private void initializeViews( View view ){ leftFab = view.findViewById( R.id.button_left_frag_1 ); rightFab = view.findViewById( R.id.button_right_frag_1 ); + btnDraft = view.findViewById(R.id.button_draft_first); markerplace = view.findViewById( R.id.marketplace ); sku = view.findViewById( R.id.sku ); modelNumber = view.findViewById( R.id.model_number ); @@ -506,6 +730,11 @@ public class FirstStepFragment extends Fragment implements View.OnClickListener boxCartonSelected = view.findViewById( R.id.box_carton_selected ); itemPerBoxSelected = view.findViewById( R.id.item_per_box_selected ); piecesSelected = view.findViewById( R.id.pieces_selected ); + + checkedBoxCartonSelected = view.findViewById(R.id.checked_box_carton_selected); + checkedItemPerBoxSelected = view.findViewById(R.id.checked_item_per_box_selected); + checkedPiecesSelected = view.findViewById(R.id.checked_pieces_selected); + fri = view.findViewById( R.id.fri ); refri = view.findViewById( R.id.refri ); searchSku = view.findViewById( R.id.search_sku_btn ); @@ -518,6 +747,7 @@ public class FirstStepFragment extends Fragment implements View.OnClickListener public void onBarcodeScanResult( String result ){ if( result != null && ! result.isEmpty() ){ store.getReport().getItems().get(0).setSku( result ); + System.out.println("SKU-2: " + store.getReport().getItems().get(0).getFnsku()); sku.setText( result ); } } @@ -578,4 +808,29 @@ public class FirstStepFragment extends Fragment implements View.OnClickListener .load( store.getProfileImage( ) ) .into( profileImage ); } + + private InspectionReport getSingleReport(InspectionReportWrapper wrapper) { + InspectionReport report = null; + + if (wrapper != null) { + try { + // Get byte array from file content path + byte[] result = FileUtils.readFile(wrapper.getContent()); + + // Convert byte array to an InspectionReport object + ByteArrayInputStream byteIn = new ByteArrayInputStream(result); + ObjectInputStream in = new ObjectInputStream(byteIn); + report = (InspectionReport) in.readObject(); + + // Set additional details from the wrapper + report.setWrapperId(wrapper.getId()); + report.setFilePath(wrapper.getContent()); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + return report; + } } diff --git a/app/src/main/java/com/utopiaindustries/qualitychecker/ui/fragments/SecondStepFragment.java b/app/src/main/java/com/utopiaindustries/qualitychecker/ui/fragments/SecondStepFragment.java index 8433abb..f72df0b 100644 --- a/app/src/main/java/com/utopiaindustries/qualitychecker/ui/fragments/SecondStepFragment.java +++ b/app/src/main/java/com/utopiaindustries/qualitychecker/ui/fragments/SecondStepFragment.java @@ -7,9 +7,14 @@ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.PackageManager; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; import android.graphics.Rect; import android.net.Uri; import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -33,15 +38,29 @@ import androidx.recyclerview.widget.RecyclerView; import com.bumptech.glide.Glide; import com.utopiaindustries.qualitychecker.R; import com.utopiaindustries.qualitychecker.async.ImageProcessor; +import com.utopiaindustries.qualitychecker.models.callback.SaveDraftReportCallback; +import com.utopiaindustries.qualitychecker.models.callback.SaveReportCallback; +import com.utopiaindustries.qualitychecker.notification.NotificationHelper; import com.utopiaindustries.qualitychecker.service.InspectionReportService; import com.utopiaindustries.qualitychecker.store.Store; import com.utopiaindustries.qualitychecker.ui.adapter.CheckPointAdapter; +import com.utopiaindustries.qualitychecker.utils.FileUtils; +import com.utopiaindustries.qualitychecker.utils.ImageUriHolder; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Objects; +import java.util.function.Consumer; public class SecondStepFragment extends Fragment implements View.OnClickListener { private NavController navController; - private Button leftFab,rightFab; + private Button leftFab, rightFab, draftFab; private RecyclerView recyclerView; private CheckPointAdapter adapter; private TextView profileName; @@ -49,112 +68,294 @@ public class SecondStepFragment extends Fragment private InspectionReportService inspectionReportService; private Store store; private static final int MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 100; - private static final int MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 101; - + private static final int MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE = 101; + private static final int MY_PERMISSIONS_REQUEST_CAMERA = 102; + List temp_path = new ArrayList<>(); + private HashMap> imagesMap = new HashMap<>(); @Nullable @Override public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.fragment_second_step , container, false ); + View view = inflater.inflate(R.layout.fragment_second_step, container, false); store = Store.getInstance(); inspectionReportService = InspectionReportService.getInstance(); - leftFab = view.findViewById( R.id.button_left_frag_2 ); - rightFab = view.findViewById( R.id.button_right_frag_2 ); - recyclerView = view.findViewById( R.id.check_point_recycler_view ); - profileName = view.findViewById( R.id.second_profile_name ); - profileImage = view.findViewById( R.id.second_step_profile_image ); - recyclerView.setLayoutManager( new LinearLayoutManager( getContext() ) ); + draftFab = view.findViewById(R.id.button_draft_second); + leftFab = view.findViewById(R.id.button_left_frag_2); + rightFab = view.findViewById(R.id.button_right_frag_2); + recyclerView = view.findViewById(R.id.check_point_recycler_view); + profileName = view.findViewById(R.id.second_profile_name); + profileImage = view.findViewById(R.id.second_step_profile_image); + recyclerView.setLayoutManager(new LinearLayoutManager(getContext())); // PERMISSIONS { // Check if permission is not granted - if ( ContextCompat.checkSelfPermission( getContext(), Manifest.permission.READ_EXTERNAL_STORAGE ) + if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { // Permission is not granted, request it - ActivityCompat.requestPermissions( getActivity(), + ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, MY_PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE); } - if (ContextCompat.checkSelfPermission( getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) + if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { - ActivityCompat.requestPermissions( getActivity(), + ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, MY_PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE); } + + if (ContextCompat.checkSelfPermission(getContext(), Manifest.permission.CAMERA) + != PackageManager.PERMISSION_GRANTED) { + + ActivityCompat.requestPermissions(getActivity(), + new String[]{Manifest.permission.CAMERA}, + MY_PERMISSIONS_REQUEST_CAMERA); + } } - adapter = new CheckPointAdapter( store.getReport().getItems().get( 0 ).getCheckPoints(), - store.getCheckPoints(), - store.getDefects(), - inspectionReportService.getDefectTypes(), - store.getCheckpointSkus(), - getContext()); - recyclerView.setAdapter( adapter ); + adapter = new CheckPointAdapter(store.getReport().getItems().get(0).getCheckPoints(), + store.getCheckPoints(), + store.getDefects(), + inspectionReportService.getDefectTypes(), + store.getCheckpointSkus(), + getContext()); + recyclerView.setAdapter(adapter); // set on click listener - leftFab.setOnClickListener( this ); - rightFab.setOnClickListener( this ); + leftFab.setOnClickListener(this); + rightFab.setOnClickListener(this); + draftFab.setOnClickListener(this); updateProfileViews(); return view; } @Override public void onClick(View v) { - navController = Navigation.findNavController( requireView() ); - if( v.getId() == R.id.button_left_frag_2 ){ - navController.navigate( R.id.action_secondStepFragment_to_firstStepFragment ); + navController = Navigation.findNavController(requireView()); + + if (v.getId() == R.id.button_draft_second) { + //System.out.println("Draft Button Click-1" + store.getReport()); + //--Storing draft report in database + if (store.getReport() != null) { + //System.out.println("Draft Button Click-2"); + inspectionReportService.saveDraftInLocalDb(getContext(), store.getReport(), new SaveDraftReportCallback() { + @Override + public void onSuccess() { + //System.out.println("Draft Button Click-3"); + Handler handler = new Handler(Looper.getMainLooper()); + handler.post(() -> { + SharedPreferences sharedPreferences = getContext().getSharedPreferences("login_prefs", Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sharedPreferences.edit(); + + editor.putString("draftReportId", "0"); + editor.apply(); + // progressBar.setVisibility(View.INVISIBLE); + Objects.requireNonNull(getActivity()).finish(); + NotificationHelper.showNotification(Objects.requireNonNull(getContext()), + "Utopia QA App", + "Report is successfully drafted"); + }); + + Toast.makeText(getContext(), "Report saved as Draft", Toast.LENGTH_SHORT).show(); + + + } + + @Override + public void onFailure(Throwable throwable) { + System.out.println("Draft Button Click-4"); + Handler handler = new Handler(Looper.getMainLooper()); + handler.post(() -> { + Toast.makeText(getContext(), throwable.getMessage(), Toast.LENGTH_LONG).show(); + //progressBar.setVisibility(View.INVISIBLE); + NotificationHelper.showNotification(Objects.requireNonNull(getContext()), + "Utopia QA App", + "Error in saving report"); + }); + } + }); + } + + //--- + } - if( v.getId() == R.id.button_right_frag_2 ){ - checkIsRecyclerViewIsCompletelyScrolled( recyclerView ); + if (v.getId() == R.id.button_left_frag_2) { + navController.navigate(R.id.action_secondStepFragment_to_firstStepFragment); + } + if (v.getId() == R.id.button_right_frag_2) { + checkIsRecyclerViewIsCompletelyScrolled(recyclerView); } } public void onImagePickerResult(int requestCode, int resultCode, Intent data) { - if ( resultCode == RESULT_OK && data != null ) { + if (requestCode != RESULT_OK) { try { - System.out.println( requestCode ); + System.out.println(requestCode); ImageProcessor imageProcessor = new ImageProcessor(); - Uri selectedImageUri = data.getData(); - assert selectedImageUri != null; - String imagePath = selectedImageUri.getPath(); - store.getReport().getItems().get(0).getCheckPoints().get(requestCode).setImagePath(imagePath); + /*Bitmap photo = (Bitmap) data.getExtras().get("data"); + assert photo != null; - imageProcessor.compressImageFromUriAsync( getContext(), selectedImageUri, 200, compressedData -> { + Uri selectedImageUri = FileUtils.getImageUriFromBitmap(requireContext(), photo); + + assert selectedImageUri != null; + String imagePath = selectedImageUri.getPath();*/ + String imagePath = ""; + Uri selectedImageUri = null; + + if (data != null) { + Log.e("onImagePickerResult: ", "Gallery: " + data); + /*Bitmap photo = (Bitmap) data.getExtras().get("data"); + + assert photo != null; + selectedImageUri = FileUtils.getImageUriFromBitmap(requireContext(), photo); + imagePath = selectedImageUri.getPath();*/ + selectedImageUri = data.getData(); + assert selectedImageUri != null; + imagePath = selectedImageUri.getPath(); + } else { + Log.e("onImagePickerResult: ", "Camera"); + selectedImageUri = ImageUriHolder.getInstance().getImageUri(); + imagePath = selectedImageUri.getPath(); + } + + store.getReport().getItems().get(0).getCheckPoints().get(requestCode).setImagePath(imagePath); + //store.getReport().getItems().get(0).getCheckPoints().get(requestCode).addImageList(uriToByteArray(getContext(), selectedImageUri)); + + uriToByteArrayAsync( + getContext(), + selectedImageUri, + 100, // Target size in KB + compressedImage -> { + // Handle the compressed image here, e.g., display it + requireActivity().runOnUiThread(() -> { + store.getReport().getItems().get(0).getCheckPoints().get(requestCode).addImageList(compressedImage); + adapter.notifyItemChanged(requestCode); + }); + }, + error -> { + // Handle any errors + requireActivity().runOnUiThread(() -> { + Toast.makeText(getContext(), "Error compressing image: " + error.getMessage(), Toast.LENGTH_SHORT).show(); + }); + } + ); + + /*imageProcessor.compressImageFromUriAsync( getContext(), selectedImageUri, 500, compressedData -> { if (compressedData != null) { store.getReport().getItems().get(0).getCheckPoints().get(requestCode).setFile(compressedData); + //store.getReport().getItems().get(0).getCheckPoints().get(requestCode).addImageList(compressedData); } else { store.getReport().getItems().get(0).getCheckPoints().get(requestCode).setFile(null); } adapter.notifyItemChanged( requestCode ); - }); - } catch ( Exception e ){ + });*/ + //adapter.notifyItemChanged(requestCode); + + } catch (Exception e) { e.printStackTrace(); } } } - private void checkIsRecyclerViewIsCompletelyScrolled( RecyclerView recyclerView ){ + public byte[] uriToByteArray(Context context, Uri uri) throws IOException { + // Target file size in bytes (100 KB) + int targetSizeInBytes = 100 * 1024; + + // Load the image as a Bitmap without scaling down + Bitmap bitmap; + try (InputStream inputStream = context.getContentResolver().openInputStream(uri)) { + bitmap = BitmapFactory.decodeStream(inputStream); + } + + if (bitmap == null) { + throw new IOException("Failed to decode image from URI."); + } + + // Compress the bitmap with an initial high quality + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + int quality = 100; + bitmap.compress(Bitmap.CompressFormat.JPEG, quality, byteArrayOutputStream); + + // Gradually reduce quality until the image is under the target size + while (byteArrayOutputStream.size() > targetSizeInBytes && quality > 10) { + byteArrayOutputStream.reset(); // Clear the stream for new compression + quality -= 5; // Reduce quality by 5 each time + bitmap.compress(Bitmap.CompressFormat.JPEG, quality, byteArrayOutputStream); + } + + return byteArrayOutputStream.toByteArray(); + } + + public void uriToByteArrayAsync( + Context context, + Uri uri, + int targetSizeInKB, + Consumer onSuccess, + Consumer onError + ) { + new Thread(() -> { + try { + int targetSizeInBytes = targetSizeInKB * 1024; + + // Load the image as a Bitmap without scaling + Bitmap bitmap; + try (InputStream inputStream = context.getContentResolver().openInputStream(uri)) { + bitmap = BitmapFactory.decodeStream(inputStream); + } + + if (bitmap == null) { + throw new IOException("Failed to decode image from URI."); + } + + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + int minQuality = 10; + int maxQuality = 100; + int quality = maxQuality; + + // Binary search for the best quality that meets the target size + while (minQuality <= maxQuality) { + byteArrayOutputStream.reset(); + bitmap.compress(Bitmap.CompressFormat.JPEG, quality, byteArrayOutputStream); + + int byteSize = byteArrayOutputStream.size(); + if (byteSize > targetSizeInBytes) { + maxQuality = quality - 1; + } else { + minQuality = quality + 1; + } + quality = (minQuality + maxQuality) / 2; + } + + onSuccess.accept(byteArrayOutputStream.toByteArray()); + } catch (IOException e) { + onError.accept(e); + } + }).start(); + } + + + private void checkIsRecyclerViewIsCompletelyScrolled(RecyclerView recyclerView) { if (recyclerView.getLayoutManager() instanceof LinearLayoutManager) { LinearLayoutManager layoutManager = (LinearLayoutManager) recyclerView.getLayoutManager(); int lastVisibleItemPosition = layoutManager.findLastCompletelyVisibleItemPosition(); int totalItemCount = layoutManager.getItemCount(); - if ( lastVisibleItemPosition == totalItemCount - 1 ) { - navController.navigate( R.id.action_secondStepFragment_to_thirdStepFragment ); + if (lastVisibleItemPosition == totalItemCount - 1) { + navController.navigate(R.id.action_secondStepFragment_to_thirdStepFragment); } else { - Toast.makeText( getContext(), "Please Scroll at the bottom to continue", Toast.LENGTH_SHORT ).show(); + Toast.makeText(getContext(), "Please Scroll at the bottom to continue", Toast.LENGTH_SHORT).show(); } } } - private void updateProfileViews( ) throws NullPointerException{ + private void updateProfileViews() throws NullPointerException { SharedPreferences sharedPreferences = getActivity().getSharedPreferences("login_prefs", Context.MODE_PRIVATE); - profileName.setText( sharedPreferences.getString("name", null ) ); - Glide.with( getContext() ) - .load( store.getProfileImage( ) ) - .into( profileImage ); + profileName.setText(sharedPreferences.getString("name", null)); + Glide.with(getContext()) + .load(store.getProfileImage()) + .into(profileImage); } } diff --git a/app/src/main/java/com/utopiaindustries/qualitychecker/ui/fragments/ThirdStepFragment.java b/app/src/main/java/com/utopiaindustries/qualitychecker/ui/fragments/ThirdStepFragment.java index 439e58d..050fd05 100644 --- a/app/src/main/java/com/utopiaindustries/qualitychecker/ui/fragments/ThirdStepFragment.java +++ b/app/src/main/java/com/utopiaindustries/qualitychecker/ui/fragments/ThirdStepFragment.java @@ -35,9 +35,11 @@ import com.bumptech.glide.Glide; import com.utopiaindustries.qualitychecker.R; import com.utopiaindustries.qualitychecker.apiservice.ApiService; import com.utopiaindustries.qualitychecker.apiservice.ApiServiceFactory; +import com.utopiaindustries.qualitychecker.db.ReportRepository; import com.utopiaindustries.qualitychecker.models.InspectionItemCheckPoint; import com.utopiaindustries.qualitychecker.models.InspectionItemDimension; import com.utopiaindustries.qualitychecker.models.InspectionReport; +import com.utopiaindustries.qualitychecker.models.callback.SaveDraftReportCallback; import com.utopiaindustries.qualitychecker.models.callback.SaveReportCallback; import com.utopiaindustries.qualitychecker.models.VoiceOfCustomer; import com.utopiaindustries.qualitychecker.notification.NotificationHelper; @@ -57,7 +59,7 @@ import retrofit2.Response; public class ThirdStepFragment extends Fragment implements View.OnClickListener { private NavController navController; - private Button backBtn,nextBtn,openDimensionDialog; + private Button backBtn,nextBtn,openDimensionDialog, btnDraft; private TextView profileName; private ImageView profileImage; private InspectionReportService inspectionReportService; @@ -65,7 +67,7 @@ public class ThirdStepFragment extends Fragment implements View.OnClickListener private Store store; private Spinner resultSpinner; private ApiService apiService; - private EditText generalRemarks; + private EditText generalRemarks, etQualityAuditor, etProdRepresentative, etQcRepresentative; private TextView minorCountTv,majorCountTv,criticalCountTv; @@ -106,6 +108,69 @@ public class ThirdStepFragment extends Fragment implements View.OnClickListener ItemDimensionAdapter adapter = new ItemDimensionAdapter( store.getReport().getItems().get(0).getDimensions() ); itemDimensionsRecyclerView.setAdapter( adapter ); + etQcRepresentative.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + try { + store.getReport().setQcRepresentative( s.toString() ); + } catch ( Exception e ){ + store.getReport().setQcRepresentative( ""); + } + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + + etProdRepresentative.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + try { + store.getReport().setProductionRepresentative( s.toString() ); + } catch ( Exception e ){ + store.getReport().setProductionRepresentative( ""); + } + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + + etQualityAuditor.addTextChangedListener(new TextWatcher() { + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + + } + + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + try { + store.getReport().setQualityAuditor( s.toString() ); + } catch ( Exception e ){ + store.getReport().setQualityAuditor( ""); + } + } + + @Override + public void afterTextChanged(Editable s) { + + } + }); + generalRemarks.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { @@ -135,6 +200,46 @@ public class ThirdStepFragment extends Fragment implements View.OnClickListener if( v.getId() == R.id.button_left_frag_3 ){ navController.navigate( R.id.action_thirdStepFragment_to_secondStepFragment ); } + if (v.getId() == R.id.button_draft_third) { + //-- + if (store.getReport() != null) { + inspectionReportService.saveDraftInLocalDb( getContext(), store.getReport(), new SaveDraftReportCallback() { + @Override + public void onSuccess() { + Handler handler = new Handler(Looper.getMainLooper()); + handler.post(() -> { + SharedPreferences sharedPreferences = getContext().getSharedPreferences("login_prefs", Context.MODE_PRIVATE); + SharedPreferences.Editor editor = sharedPreferences.edit(); + + editor.putString("draftReportId", "0"); + editor.apply(); + // progressBar.setVisibility(View.INVISIBLE); + Objects.requireNonNull(getActivity()).finish(); + NotificationHelper.showNotification(Objects.requireNonNull(getContext()), + "Utopia QA App", + "Report is successfully drafted"); + }); + + Toast.makeText(getContext(), "Report saved as Draft", Toast.LENGTH_SHORT).show(); + + } + + @Override + public void onFailure(Throwable throwable) { + Handler handler = new Handler(Looper.getMainLooper()); + handler.post(() -> { + Toast.makeText(getContext(), throwable.getMessage(), Toast.LENGTH_LONG).show(); + //progressBar.setVisibility(View.INVISIBLE); + NotificationHelper.showNotification(Objects.requireNonNull(getContext()), + "Utopia QA App", + "Error in saving report"); + }); + } + }); + } + + //--- + } if( v.getId() == R.id.button_right_frag_3 ){ saveReportDialog(); } @@ -162,6 +267,11 @@ public class ThirdStepFragment extends Fragment implements View.OnClickListener public void onSuccess() { Handler handler = new Handler(Looper.getMainLooper()); handler.post(() -> { + + SharedPreferences sharedPreferences = getContext().getSharedPreferences("login_prefs", Context.MODE_PRIVATE); + long draftReportId = Long.parseLong(sharedPreferences.getString("draftReportId", null)); + + new ReportRepository(getContext()).deleteDraftRecordById(draftReportId); Toast.makeText(getContext(), "Report saved Successfully", Toast.LENGTH_LONG).show(); progressBar.setVisibility(View.INVISIBLE); Objects.requireNonNull(getActivity()).finish(); @@ -246,6 +356,9 @@ public class ThirdStepFragment extends Fragment implements View.OnClickListener @SuppressLint("DefaultLocale") private void populateViews(){ generalRemarks.setText( store.getReport().getGeneralRemarks() ); + etQualityAuditor.setText(store.getReport().getQualityAuditor()); + etProdRepresentative.setText(store.getReport().getProductionRepresentative()); + etQcRepresentative.setText(store.getReport().getQcRepresentative()); ArrayAdapter adapter = new ArrayAdapter<>( getContext(), android.R.layout.simple_spinner_item, @@ -358,6 +471,7 @@ public class ThirdStepFragment extends Fragment implements View.OnClickListener private void initializeViews( View view ){ backBtn = view.findViewById( R.id.button_left_frag_3 ); nextBtn = view.findViewById( R.id.button_right_frag_3 ); + btnDraft = view.findViewById(R.id.button_draft_third); openDimensionDialog = view.findViewById( R.id.button_open_dimension ); profileImage = view.findViewById( R.id.third_step_profile_image ); profileName = view.findViewById( R.id.third_profile_name ); @@ -368,10 +482,15 @@ public class ThirdStepFragment extends Fragment implements View.OnClickListener minorCountTv = view.findViewById( R.id.minor_count ); majorCountTv = view.findViewById( R.id.major_count ); criticalCountTv = view.findViewById( R.id.critical_count ); + etQualityAuditor = view.findViewById(R.id.et_quality_auditor); + etProdRepresentative = view.findViewById(R.id.et_prod_represent); + etQcRepresentative = view.findViewById(R.id.et_qc_represent); + } private void setOnClickListeners(){ nextBtn.setOnClickListener( this ); backBtn.setOnClickListener( this ); + btnDraft.setOnClickListener( this); openDimensionDialog.setOnClickListener( this); } diff --git a/app/src/main/java/com/utopiaindustries/qualitychecker/utils/FileUtils.java b/app/src/main/java/com/utopiaindustries/qualitychecker/utils/FileUtils.java index ce8fd31..6bb320e 100644 --- a/app/src/main/java/com/utopiaindustries/qualitychecker/utils/FileUtils.java +++ b/app/src/main/java/com/utopiaindustries/qualitychecker/utils/FileUtils.java @@ -1,12 +1,31 @@ package com.utopiaindustries.qualitychecker.utils; +import android.app.Activity; import android.content.Context; +import android.graphics.Bitmap; +import android.net.Uri; +import android.os.Handler; +import android.os.Looper; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ProgressBar; +import android.widget.Toast; + +import androidx.appcompat.app.AlertDialog; +import androidx.core.content.FileProvider; + +import com.utopiaindustries.qualitychecker.R; +import com.utopiaindustries.qualitychecker.models.callback.SaveReportCallback; +import com.utopiaindustries.qualitychecker.notification.NotificationHelper; +import com.utopiaindustries.qualitychecker.service.InspectionReportService; +import com.utopiaindustries.qualitychecker.store.Store; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; +import java.util.Objects; public class FileUtils { public static String writeFile( Context context , @@ -39,7 +58,7 @@ public class FileUtils { File file = new File(filePath); try (FileInputStream fis = new FileInputStream(file); ByteArrayOutputStream baos = new ByteArrayOutputStream()) { - byte[] buffer = new byte[1024]; + byte[] buffer = new byte[8192]; int bytesRead; while ((bytesRead = fis.read(buffer)) != -1) { baos.write(buffer, 0, bytesRead); @@ -60,4 +79,79 @@ public class FileUtils { System.out.println("File does not exist"); } } + + public static Uri getImageUriFromBitmap(Context context, Bitmap bitmap) { + // Create a file in the cache directory + File cachePath = new File(context.getCacheDir(), "images"); + cachePath.mkdirs(); // Create the directory if it doesn't exist + File file = new File(cachePath, "image.png"); // File name with PNG format + + try { + // Write the bitmap to the file + FileOutputStream stream = new FileOutputStream(file); + //bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream); // 100 indicates no compression + bitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream); + stream.flush(); + stream.close(); + } catch (IOException e) { + e.printStackTrace(); + } + + // Get the URI using FileProvider + Uri uri = FileProvider.getUriForFile(context, "com.utopiaindustries.qualitychecker.fileprovider", file); + + return uri; + } + + private void saveDraftReportDialog(Context context, InspectionReportService inspectionReportService, Store store) { + LayoutInflater inflater = LayoutInflater.from(context ); + View dialogView = inflater.inflate( R.layout.save_report_dialog, null); + // progress bar + ProgressBar progressBar = dialogView.findViewById( R.id.save_report_progress ); + + AlertDialog.Builder builder = new AlertDialog.Builder( Objects.requireNonNull(context) ); + builder.setView( dialogView ) + .setTitle("So you want to save report as draft?") + .setPositiveButton( "Save",(dialog, which) -> { + progressBar.setVisibility(View.VISIBLE); + NotificationHelper.showNotification(Objects.requireNonNull(context), + "Utopia QA App", + "Report is saving keep patience..."); + inspectionReportService.saveInLocalDb(context, store.getReport(), new SaveReportCallback() { + @Override + public void onSuccess() { + Handler handler = new Handler(Looper.getMainLooper()); + handler.post(() -> { + Toast.makeText(context, "Report draft Successfully", Toast.LENGTH_LONG).show(); + progressBar.setVisibility(View.INVISIBLE); + //Objects.requireNonNull(context).finish(); + NotificationHelper.showNotification(Objects.requireNonNull(context), + "Utopia QA App", + "Report is successfully saved"); + }); + } + + @Override + public void onFailure(Throwable throwable) { + Handler handler = new Handler(Looper.getMainLooper()); + handler.post(() -> { + Toast.makeText(context, throwable.getMessage(), Toast.LENGTH_LONG).show(); + progressBar.setVisibility(View.INVISIBLE); + NotificationHelper.showNotification(Objects.requireNonNull(context), + "Utopia QA App", + "Error in saving report"); + }); + } + }); + }) + .setNegativeButton("Cancel", (dialog, which) -> { + // Handle Cancel button click + dialog.dismiss(); + }); + // Show the dialog + AlertDialog dialog = builder.create(); + progressBar.setVisibility( View.GONE ); + dialog.show(); + + } } diff --git a/app/src/main/java/com/utopiaindustries/qualitychecker/utils/ImageUriHolder.java b/app/src/main/java/com/utopiaindustries/qualitychecker/utils/ImageUriHolder.java new file mode 100644 index 0000000..efde2cd --- /dev/null +++ b/app/src/main/java/com/utopiaindustries/qualitychecker/utils/ImageUriHolder.java @@ -0,0 +1,25 @@ +package com.utopiaindustries.qualitychecker.utils; + +import android.net.Uri; + +public class ImageUriHolder { + private static ImageUriHolder instance; + private Uri imageUri; + + private ImageUriHolder() {} + + public static ImageUriHolder getInstance() { + if (instance == null) { + instance = new ImageUriHolder(); + } + return instance; + } + + public Uri getImageUri() { + return imageUri; + } + + public void setImageUri(Uri uri) { + this.imageUri = uri; + } +} diff --git a/app/src/main/java/com/utopiaindustries/qualitychecker/utils/NonSwipeableViewPager.java b/app/src/main/java/com/utopiaindustries/qualitychecker/utils/NonSwipeableViewPager.java new file mode 100644 index 0000000..77b5693 --- /dev/null +++ b/app/src/main/java/com/utopiaindustries/qualitychecker/utils/NonSwipeableViewPager.java @@ -0,0 +1,33 @@ +package com.utopiaindustries.qualitychecker.utils; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; + +import androidx.viewpager.widget.ViewPager; + +/** + * Created by Development on 05-Oct-2021. + */ +public class NonSwipeableViewPager extends ViewPager +{ + public NonSwipeableViewPager(Context context) { + super(context); + } + + public NonSwipeableViewPager(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent event) { + // Never allow swiping to switch between pages + return false; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + // Never allow swiping to switch between pages + return false; + } +} diff --git a/app/src/main/java/com/utopiaindustries/qualitychecker/utils/SelectListener.java b/app/src/main/java/com/utopiaindustries/qualitychecker/utils/SelectListener.java new file mode 100644 index 0000000..2c364da --- /dev/null +++ b/app/src/main/java/com/utopiaindustries/qualitychecker/utils/SelectListener.java @@ -0,0 +1,8 @@ +package com.utopiaindustries.qualitychecker.utils; + +import com.utopiaindustries.qualitychecker.models.InspectionReportWrapper; + +public interface SelectListener { + + void onItemClicked(InspectionReportWrapper reportWrapper); +} diff --git a/app/src/main/res/drawable/box_border.xml b/app/src/main/res/drawable/box_border.xml new file mode 100644 index 0000000..3d7ad3b --- /dev/null +++ b/app/src/main/res/drawable/box_border.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/app/src/main/res/drawable/img_load.xml b/app/src/main/res/drawable/img_load.xml new file mode 100644 index 0000000..2102567 --- /dev/null +++ b/app/src/main/res/drawable/img_load.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/app/src/main/res/drawable/tab_selected_color.xml b/app/src/main/res/drawable/tab_selected_color.xml new file mode 100644 index 0000000..5f25406 --- /dev/null +++ b/app/src/main/res/drawable/tab_selected_color.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_home.xml b/app/src/main/res/layout/activity_home.xml index b6c7bad..6922529 100644 --- a/app/src/main/res/layout/activity_home.xml +++ b/app/src/main/res/layout/activity_home.xml @@ -2,9 +2,9 @@ - - + + + + + diff --git a/app/src/main/res/layout/check_point.xml b/app/src/main/res/layout/check_point.xml index bd94c31..39520e9 100644 --- a/app/src/main/res/layout/check_point.xml +++ b/app/src/main/res/layout/check_point.xml @@ -71,18 +71,27 @@ + android:layout_height="wrap_content" + android:weightSum="1" + android:orientation="horizontal"> + - - + --> diff --git a/app/src/main/res/layout/custom_tab.xml b/app/src/main/res/layout/custom_tab.xml new file mode 100644 index 0000000..7e3b118 --- /dev/null +++ b/app/src/main/res/layout/custom_tab.xml @@ -0,0 +1,21 @@ + + + + + + diff --git a/app/src/main/res/layout/draft_report_item.xml b/app/src/main/res/layout/draft_report_item.xml new file mode 100644 index 0000000..ce4e277 --- /dev/null +++ b/app/src/main/res/layout/draft_report_item.xml @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_draft.xml b/app/src/main/res/layout/fragment_draft.xml new file mode 100644 index 0000000..d02cf1f --- /dev/null +++ b/app/src/main/res/layout/fragment_draft.xml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_first_step.xml b/app/src/main/res/layout/fragment_first_step.xml index 438b108..6d3ac90 100644 --- a/app/src/main/res/layout/fragment_first_step.xml +++ b/app/src/main/res/layout/fragment_first_step.xml @@ -1,373 +1,478 @@ - + android:scrollbars="vertical" + android:scrollbarFadeDuration="0" + android:fadeScrollbars="false" + android:scrollbarThumbVertical="@android:color/darker_gray" + android:fillViewport="true"> + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginEnd="2dp" + tools:context=".ui.activities.LoginActivity"> - + app:layout_constraintVertical_bias="0.0"> - + + + + + + + + +