diff --git a/app/build.gradle b/app/build.gradle index b1cd196..11734e2 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -41,6 +41,9 @@ android { // but continue the build even when errors are found: abortOnError false } + buildFeatures { + viewBinding true + } } dependencies { @@ -49,6 +52,9 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.5.1' implementation 'com.google.android.material:material:1.7.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.6.1' + implementation 'androidx.navigation:navigation-fragment-ktx:2.5.2' + implementation 'androidx.navigation:navigation-ui-ktx:2.5.2' // implementation 'androidx.core:core-ktx:+' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.5' @@ -67,6 +73,9 @@ dependencies { // Barcode scanner implementation 'com.journeyapps:zxing-android-embedded:4.3.0' + // Google ML Kit usign play services + implementation 'com.google.android.gms:play-services-code-scanner:16.0.0' + } //repositories { // mavenCentral() diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3f374e3..0c2cbb6 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -10,6 +10,8 @@ + + @@ -23,40 +25,48 @@ android:supportsRtl="true" android:theme="@style/Theme.HPOS" tools:targetApi="31"> + + - - - - + android:parentActivityName=".presentation.MainActivity" + android:windowSoftInputMode="adjustPan"> - - - - + + + - + + + + + @@ -65,12 +75,17 @@ - + + + - \ No newline at end of file diff --git a/app/src/main/java/com/example/hpos/data/DataHolder.kt b/app/src/main/java/com/example/hpos/data/DataHolder.kt index d614ce4..f73808f 100644 --- a/app/src/main/java/com/example/hpos/data/DataHolder.kt +++ b/app/src/main/java/com/example/hpos/data/DataHolder.kt @@ -1,8 +1,8 @@ package com.example.hpos.data import androidx.lifecycle.MutableLiveData -import com.example.hpos.data.model.TestRightDeviceConstants -import com.example.hpos.data.model.TestType +import com.example.hpos.data.model.test.TestRightDeviceConstants +import com.example.hpos.data.model.test.TestType object DataHolder { diff --git a/app/src/main/java/com/example/hpos/data/Repository.kt b/app/src/main/java/com/example/hpos/data/Repository.kt index 6f89be1..e4114ab 100644 --- a/app/src/main/java/com/example/hpos/data/Repository.kt +++ b/app/src/main/java/com/example/hpos/data/Repository.kt @@ -1,6 +1,6 @@ package com.example.hpos.data -import com.example.hpos.data.model.TestInfo +import com.example.hpos.data.model.test.TestInfo interface Repository { suspend fun saveToDatabase(info: TestInfo) diff --git a/app/src/main/java/com/example/hpos/data/RepositoryImpl.kt b/app/src/main/java/com/example/hpos/data/RepositoryImpl.kt index 6f097b3..5152c75 100644 --- a/app/src/main/java/com/example/hpos/data/RepositoryImpl.kt +++ b/app/src/main/java/com/example/hpos/data/RepositoryImpl.kt @@ -1,6 +1,6 @@ package com.example.hpos.data -import com.example.hpos.data.model.TestInfo +import com.example.hpos.data.model.test.TestInfo class RepositoryImpl : Repository { diff --git a/app/src/main/java/com/example/hpos/data/constant/Constants.kt b/app/src/main/java/com/example/hpos/data/constant/Constants.kt index ab0baf6..3f688fe 100644 --- a/app/src/main/java/com/example/hpos/data/constant/Constants.kt +++ b/app/src/main/java/com/example/hpos/data/constant/Constants.kt @@ -3,6 +3,8 @@ package com.example.hpos.data.constant object Constants { const val ACTION_USB_PERMISSION = "shanmukha.in.sickle_cell.USB_PERMISSION" + const val ABHA_APP_PACKAGE = "in.ndhm.phr" + const val WRITE_TIMEOUT_MILLIS = 30000 // 30 sec const val READ_TIMEOUT_MILLIS = 60000 // 1 min const val DELAY_BETWEEN_COMMANDS: Long = 1000 diff --git a/app/src/main/java/com/example/hpos/data/model/AadharCard.java b/app/src/main/java/com/example/hpos/data/model/AadharCard.java new file mode 100644 index 0000000..c95cef8 --- /dev/null +++ b/app/src/main/java/com/example/hpos/data/model/AadharCard.java @@ -0,0 +1,174 @@ +package com.example.hpos.data.model; + +import android.graphics.Bitmap; + +public class AadharCard { + private String uuid; + private String name; + private String dateOfBirth; + private String gender; + private String careOf; + private String district; + private String landmark; + private String house; + private String location; + private String pinCode; + private String postOffice; + private String state; + private String street; + private String subDistrict; + private String vtc; + private Bitmap image; + private String email; + private String mobile; + private String signature; + + public void setUuid(String aUuid){ name = aUuid; } + public void setName(String aName){ name = aName; } + public void setDateOfBirth(String aDateOfBirth){ + dateOfBirth = aDateOfBirth; + } + public void setGender(String aGender){ + gender = aGender; + } + public void setCareOf(String aCareOf){ + careOf = aCareOf; + } + public void setDistrict(String aDistrict){ + district = aDistrict; + } + public void setLandmark(String aLandmark){ + landmark = aLandmark; + } + public void setHouse(String aHouse){ + house = aHouse; + } + public void setLocation(String aLocation){ location = aLocation; } + public void setPinCode(String aPinCode){ + pinCode = aPinCode; + } + public void setPostOffice(String aPostOffice){ + postOffice = aPostOffice; + } + public void setState(String aState){ + state = aState; + } + public void setStreet(String aStreet){ + street = aStreet; + } + public void setSubDistrict(String aSubDistrict){ + subDistrict = aSubDistrict; + } + public void setVtc(String aVtc){ + vtc = aVtc; + } + public void setImage(Bitmap aImage){ + image = aImage; + } + public void setEmail(String aEmail){ + email = aEmail; + } + public void setMobile(String aMobile){ + mobile = aMobile; + } + public void setSignature(String aSignature){ + signature = aSignature; + } + + public AadharCard(){ + uuid = ""; + name = ""; + dateOfBirth = ""; + gender = ""; + careOf = ""; + district = ""; + landmark = ""; + house = ""; + location = ""; + pinCode = ""; + postOffice = ""; + state = ""; + street = ""; + subDistrict = ""; + vtc = ""; + email = ""; + mobile = ""; + signature = ""; + } + + public String getName() { + return name; + } + + public String getUuid() { + return uuid; + } + + public String getDateOfBirth() { + return dateOfBirth; + } + + public String getGender() { + return gender; + } + + public String getCareOf() { + return careOf; + } + + public String getDistrict() { + return district; + } + + public String getLandmark() { + return landmark; + } + + public String getHouse() { + return house; + } + + public String getLocation() { + return location; + } + + public String getPinCode() { + return pinCode; + } + + public String getPostOffice() { + return postOffice; + } + + public String getState() { + return state; + } + + public String getStreet() { + return street; + } + + public String getSubDistrict() { + return subDistrict; + } + + public String getVtc() { + return vtc; + } + + public Bitmap getImage() { + return image; + } + + public String getEmail() { + return email; + } + + public String getMobile() { + return mobile; + } + + public String getSignature() { + return signature; + } +} diff --git a/app/src/main/java/com/example/hpos/data/model/PatientAadhaarData.kt b/app/src/main/java/com/example/hpos/data/model/PatientAadhaarData.kt deleted file mode 100644 index 6162d05..0000000 --- a/app/src/main/java/com/example/hpos/data/model/PatientAadhaarData.kt +++ /dev/null @@ -1,41 +0,0 @@ -package com.example.hpos.data.model - -data class PatientAadhaarData( - val uuid: String?, - val name: String, - val gender: Gender, - val careOf: String, - val yob: String, - val address: Address, - val pinCode: String, - val mobile: String?, - - val isMarried: Boolean?, - val bloodGroup: BloodGroup?, -) { - enum class Gender { - MALE, - FEMALE, - OTHER - } - - enum class BloodGroup { - O_POSITIVE, O_NEGATIVE, - A_POSITIVE, A_NEGATIVE, - B_POSITIVE, B_NEGATIVE, - AB_POSITIVE, AB_NEGATIVE, - } - - data class Address( - val house: String?, - val street: String?, - val location: String?, - val landMark: String?, - val postOffice: String?, - val district: String, - val subDistrict: String, - val state: String, - val vtc: String?, - val pinCode: Int, - ) -} diff --git a/app/src/main/java/com/example/hpos/data/model/PatientData.kt b/app/src/main/java/com/example/hpos/data/model/PatientData.kt index d9cbee1..7ef43d5 100644 --- a/app/src/main/java/com/example/hpos/data/model/PatientData.kt +++ b/app/src/main/java/com/example/hpos/data/model/PatientData.kt @@ -1,5 +1,7 @@ package com.example.hpos.data.model +import com.example.hpos.data.model.test.TestRightResultType + data class PatientData( val name: String, val age: Int, diff --git a/app/src/main/java/com/example/hpos/data/model/patient/PatientData.kt b/app/src/main/java/com/example/hpos/data/model/patient/PatientData.kt new file mode 100644 index 0000000..1b890e0 --- /dev/null +++ b/app/src/main/java/com/example/hpos/data/model/patient/PatientData.kt @@ -0,0 +1,76 @@ +package com.example.hpos.data.model.patient + +import java.util.Date + +data class PatientDetails( + var id: String, + var isIdABHA: Boolean, + var name: String?, + var yob: Int?, + var gender: Gender?, + var mobile: String?, + var isUnderMedication: Boolean?, + var isUnderTransfusion: Boolean?, + val photoUrl: String?, + var careOf: String?, + var isMarried: Boolean?, + var bloodGroup: String?, + var address: Address?, + var category: Category?, + var registerDate: Date?, + val uploadDate: Date? +) { + constructor() : this( + "", + false, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null, + null + ) + + enum class Gender { + MALE, + FEMALE, + OTHER + } + +// enum class BloodGroup { +// O_POSITIVE, O_NEGATIVE, +// A_POSITIVE, A_NEGATIVE, +// B_POSITIVE, B_NEGATIVE, +// AB_POSITIVE, AB_NEGATIVE, +// } + + data class Address( + var house: String?, + val street: String?, + var city: String?, + val landMark: String?, + var postOffice: String?, + var district: String?, + val subDistrict: String?, + var state: String?, + val vtc: String?, + var pinCode: Int?, + ) { + constructor() : this(null, null, null, null, null, null, null, null, null, null) + } + + enum class Category { + GENERAL, + OBC, + SC, + ST, + } +} diff --git a/app/src/main/java/com/example/hpos/data/model/TestInfo.kt b/app/src/main/java/com/example/hpos/data/model/test/TestInfo.kt similarity index 83% rename from app/src/main/java/com/example/hpos/data/model/TestInfo.kt rename to app/src/main/java/com/example/hpos/data/model/test/TestInfo.kt index 03fc71c..27b0ae6 100644 --- a/app/src/main/java/com/example/hpos/data/model/TestInfo.kt +++ b/app/src/main/java/com/example/hpos/data/model/test/TestInfo.kt @@ -1,4 +1,4 @@ -package com.example.hpos.data.model +package com.example.hpos.data.model.test data class TestInfo( val value: String, diff --git a/app/src/main/java/com/example/hpos/data/model/TestRightCalculationData.kt b/app/src/main/java/com/example/hpos/data/model/test/TestRightCalculationData.kt similarity index 90% rename from app/src/main/java/com/example/hpos/data/model/TestRightCalculationData.kt rename to app/src/main/java/com/example/hpos/data/model/test/TestRightCalculationData.kt index 90ceb62..78fef73 100644 --- a/app/src/main/java/com/example/hpos/data/model/TestRightCalculationData.kt +++ b/app/src/main/java/com/example/hpos/data/model/test/TestRightCalculationData.kt @@ -1,4 +1,4 @@ -package com.example.hpos.data.model +package com.example.hpos.data.model.test data class TestRightCalculationData( var absorbanceOne: Double?, diff --git a/app/src/main/java/com/example/hpos/data/model/TestRightDeviceConstants.kt b/app/src/main/java/com/example/hpos/data/model/test/TestRightDeviceConstants.kt similarity index 73% rename from app/src/main/java/com/example/hpos/data/model/TestRightDeviceConstants.kt rename to app/src/main/java/com/example/hpos/data/model/test/TestRightDeviceConstants.kt index 7e576c6..0539f37 100644 --- a/app/src/main/java/com/example/hpos/data/model/TestRightDeviceConstants.kt +++ b/app/src/main/java/com/example/hpos/data/model/test/TestRightDeviceConstants.kt @@ -1,4 +1,4 @@ -package com.example.hpos.data.model +package com.example.hpos.data.model.test data class TestRightDeviceConstants( var a: String, diff --git a/app/src/main/java/com/example/hpos/data/model/TestRightResultType.kt b/app/src/main/java/com/example/hpos/data/model/test/TestRightResultType.kt similarity index 78% rename from app/src/main/java/com/example/hpos/data/model/TestRightResultType.kt rename to app/src/main/java/com/example/hpos/data/model/test/TestRightResultType.kt index e8f83c5..e88ff92 100644 --- a/app/src/main/java/com/example/hpos/data/model/TestRightResultType.kt +++ b/app/src/main/java/com/example/hpos/data/model/test/TestRightResultType.kt @@ -1,4 +1,4 @@ -package com.example.hpos.data.model +package com.example.hpos.data.model.test enum class TestRightResultType { NORMAL, diff --git a/app/src/main/java/com/example/hpos/data/model/TestType.kt b/app/src/main/java/com/example/hpos/data/model/test/TestType.kt similarity index 57% rename from app/src/main/java/com/example/hpos/data/model/TestType.kt rename to app/src/main/java/com/example/hpos/data/model/test/TestType.kt index 015089e..c3dcf42 100644 --- a/app/src/main/java/com/example/hpos/data/model/TestType.kt +++ b/app/src/main/java/com/example/hpos/data/model/test/TestType.kt @@ -1,4 +1,4 @@ -package com.example.hpos.data.model +package com.example.hpos.data.model.test enum class TestType { SICKLECERT, diff --git a/app/src/main/java/com/example/hpos/domain/AadhaarScanner/QrCodeException.java b/app/src/main/java/com/example/hpos/domain/AadhaarScanner/QrCodeException.java new file mode 100644 index 0000000..0e3fcd6 --- /dev/null +++ b/app/src/main/java/com/example/hpos/domain/AadhaarScanner/QrCodeException.java @@ -0,0 +1,20 @@ +package com.example.hpos.domain.AadhaarScanner; +/** + * QrCodeException wraps all the exceptions which occurs while scanning and decoding secure Aadharcard + * Qr Code + * @author Raj Deol + */ +public class QrCodeException extends Exception { + + public QrCodeException(String message) { + super(message); + } + + public QrCodeException(String message, Throwable cause) { + super(message, cause); + } + + public QrCodeException(Throwable cause) { + super(cause); + } +} diff --git a/app/src/main/java/com/example/hpos/domain/AadhaarScanner/SecureQrCode.java b/app/src/main/java/com/example/hpos/domain/AadhaarScanner/SecureQrCode.java new file mode 100644 index 0000000..0a2b977 --- /dev/null +++ b/app/src/main/java/com/example/hpos/domain/AadhaarScanner/SecureQrCode.java @@ -0,0 +1,304 @@ +package com.example.hpos.domain.AadhaarScanner; + +import android.content.Context; +import android.util.Log; + +import com.example.hpos.data.model.AadharCard; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.zip.GZIPInputStream; + +/** + * Class to decode scanned QRcode + */ +public class SecureQrCode { + protected Context mContext; + protected static final byte SEPARATOR_BYTE = (byte)255; + protected static final int REFERENCE_ID_INDEX = 1, + NAME_INDEX = 2, + DATE_OF_BIRTH_INDEX = 3, + GENDER_INDEX = 4, + CARE_OF_INDEX = 5, + DISTRICT_INDEX = 6, + LANDMARK_INDEX = 7, + HOUSE_INDEX = 8, + LOCATION_INDEX = 9, + PIN_CODE_INDEX = 10, + POST_OFFICE_INDEX = 11, + STATE_INDEX = 12, + STREET_INDEX = 13, + SUB_DISTRICT_INDEX = 14, + VTC_INDEX = 15; + protected int emailMobilePresent, imageStartIndex, imageEndIndex; + protected ArrayList decodedData; + protected String signature,email,mobile; + protected AadharCard scannedAadharCard; + + public SecureQrCode(Context activity, String scanData) throws QrCodeException{ + mContext = activity; + scannedAadharCard = new AadharCard(); + + // 1. Convert Base10 to BigInt + final BigInteger bigIntScanData = new BigInteger(scanData,10); + + // 2. Convert BigInt to Byte Array + final byte byteScanData[] = bigIntScanData.toByteArray(); + + // 3. Decompress Byte Array + final byte[] decompByteScanData = decompressData(byteScanData); + + // 4. Split the byte array using delimiter + List parts = separateData(decompByteScanData); + // Throw error if there are no parts + if(parts.size() == 0){ + throw new QrCodeException("Invalid QR Code Data, no parts found after splitting by delimiter"); + } + + // 5. decode extracted data to string + decodeData(parts); + + // 6. Extract Signature + decodeSignature(decompByteScanData); + + // 7. Email and Mobile number + decodeMobileEmail(decompByteScanData); + + // 8. Extract Image + decodeImage(decompByteScanData); + Log.d("Rajdeol","Data Decoded"); + + } + + /** + * Decompress the byte array, compression used is GZIP + * @param byteScanData compressed byte array + * @return uncompressed byte array + * @throws QrCodeException + */ + protected byte[] decompressData(byte[] byteScanData) throws QrCodeException { + ByteArrayOutputStream bos = new ByteArrayOutputStream(byteScanData.length); + ByteArrayInputStream bin = new ByteArrayInputStream(byteScanData); + GZIPInputStream gis = null; + + try { + gis = new GZIPInputStream(bin); + } catch (IOException e) { + Log.e("Exception", "Decompressing QRcode, Opening byte stream failed: " + e.toString()); + throw new QrCodeException("Error in opening Gzip byte stream while decompressing QRcode",e); + } + + int size = 0; + byte[] buf = new byte[1024]; + while (size >= 0) { + try { + size = gis.read(buf,0,buf.length); + if(size > 0){ + bos.write(buf,0,size); + } + } catch (IOException e) { + Log.e("Exception", "Decompressing QRcode, writing byte stream failed: " + e.toString()); + throw new QrCodeException("Error in writing byte stream while decompressing QRcode",e); + } + } + + try { + gis.close(); + bin.close(); + } catch (IOException e) { + Log.e("Exception", "Decompressing QRcode, closing byte stream failed: " + e.toString()); + throw new QrCodeException("Error in closing byte stream while decompressing QRcode",e); + } + + return bos.toByteArray(); + } + + /** + * Function to split byte array with delimiter + * @param source source byte array + * @return list of separated byte arrays + */ + protected List separateData(byte[] source) { + List separatedParts = new LinkedList<>(); + int begin = 0; + + for (int i = 0; i < source.length; i++) { + if(source[i] == SEPARATOR_BYTE){ + // skip if first or last byte is separator + if(i != 0 && i != (source.length -1)){ + separatedParts.add(Arrays.copyOfRange(source, begin, i)); + } + begin = i + 1; + // check if we have got all the parts of text data + if(separatedParts.size() == (VTC_INDEX + 1)){ + // this is required to extract image data + imageStartIndex = begin; + break; + } + } + } + return separatedParts; + } + + /** + * function to decode string values + * @param encodedData + * @throws QrCodeException + */ + protected void decodeData(List encodedData) throws QrCodeException{ + Iterator i = encodedData.iterator(); + decodedData = new ArrayList(); + while(i.hasNext()){ + try { + decodedData.add(new String(i.next(), "ISO-8859-1")); + } catch (UnsupportedEncodingException e) { + Log.e("Exception", "Decoding QRcode, ISO-8859-1 not supported: " + e.toString()); + throw new QrCodeException("Decoding QRcode, ISO-8859-1 not supported",e); + } + } + // set the value of email/mobile present flag + emailMobilePresent = Integer.parseInt(decodedData.get(0)); + + // populate decoded data + scannedAadharCard.setName(decodedData.get(2)); + scannedAadharCard.setDateOfBirth(decodedData.get(3)); + scannedAadharCard.setGender(decodedData.get(4)); + scannedAadharCard.setCareOf(decodedData.get(5)); + scannedAadharCard.setDistrict(decodedData.get(6)); + scannedAadharCard.setLandmark(decodedData.get(7)); + scannedAadharCard.setHouse(decodedData.get(8)); + scannedAadharCard.setLocation(decodedData.get(9)); + scannedAadharCard.setPinCode(decodedData.get(10)); + scannedAadharCard.setPostOffice(decodedData.get(11)); + scannedAadharCard.setState(decodedData.get(12)); + scannedAadharCard.setStreet(decodedData.get(13)); + scannedAadharCard.setSubDistrict(decodedData.get(14)); + scannedAadharCard.setVtc(decodedData.get(15)); + } + + /** + * ref : https://uidai.gov.in/2-uncategorised/11320-aadhaar-paperless-offline-e-kyc-3.html + * Hashing logic for Email ID : + * Sha256(Sha256(Email+SharePhrase))*number of times last digit of Aadhaar number + * (Ref ID field contains last 4 digits). + * + * Example : + * Email: abc@gm.com + * Aadhaar Number:XXXX XXXX 3632 + * Passcode : Lock@487 + * Hash : Sha256(Sha256(abc@gm.comLock@487))*2 + * In case of Aadhaar number ends with Zero we will hashed one time. + * ********************************************************************** + * ********************************************************************** + * Hashing logic for Mobile Number : + * Sha256(Sha256(Mobile+SharePhrase))*number of times last digit of Aadhaar number + * (Ref ID field contains last 4 digits). + * + * Example : + * Mobile: 1234567890 + * Aadhaar Number:XXXX XXXX 3632 + * Passcode : Lock@487 + * Hash: Sha256(Sha256(1234567890Lock@487))*2 + * In case of Aadhaar number ends with Zero we will hashed one time. + * @param decompressedData + * @throws QrCodeException + */ + + protected void decodeMobileEmail(byte[] decompressedData) throws QrCodeException{ + int mobileStartIndex = 0,mobileEndIndex = 0,emailStartIndex = 0,emailEndIndex = 0; + switch (emailMobilePresent){ + case 3: + // both email mobile present + mobileStartIndex = decompressedData.length - 289; // length -1 -256 -32 + mobileEndIndex = decompressedData.length - 257; // length -1 -256 + emailStartIndex = decompressedData.length - 322;// length -1 -256 -32 -1 -32 + emailEndIndex = decompressedData.length - 290;// length -1 -256 -32 -1 + + mobile = bytesToHex (Arrays.copyOfRange(decompressedData,mobileStartIndex,mobileEndIndex+1)); + email = bytesToHex (Arrays.copyOfRange(decompressedData,emailStartIndex,emailEndIndex+1)); + // set image end index, it will be used to extract image data + imageEndIndex = decompressedData.length - 323; + break; + + case 2: + // only mobile + email = ""; + mobileStartIndex = decompressedData.length - 289; // length -1 -256 -32 + mobileEndIndex = decompressedData.length - 257; // length -1 -256 + + mobile = bytesToHex (Arrays.copyOfRange(decompressedData,mobileStartIndex,mobileEndIndex+1)); + // set image end index, it will be used to extract image data + imageEndIndex = decompressedData.length - 290; + break; + + case 1: + // only email + mobile = ""; + emailStartIndex = decompressedData.length - 289; // length -1 -256 -32 + emailEndIndex = decompressedData.length - 257; // length -1 -256 + + email = bytesToHex (Arrays.copyOfRange(decompressedData,emailStartIndex,emailEndIndex+1)); + // set image end index, it will be used to extract image data + imageEndIndex = decompressedData.length - 290; + break; + + default: + // no mobile or email + mobile = ""; + email = ""; + // set image end index, it will be used to extract image data + imageEndIndex = decompressedData.length - 257; + } + + } + + protected void decodeImage(byte[] decompressedData) throws QrCodeException{ + // image start and end indexes are calculated in functions : separateData and decodeMobileEmail + byte[] imageBytes = Arrays.copyOfRange(decompressedData,imageStartIndex,imageEndIndex+1); + +// Bitmap bmp = new JP2Decoder(imageBytes).decode(); +// scannedAadharCard.setImage(bmp); + } + + protected void decodeSignature(byte[] decompressedData) throws QrCodeException{ + // extract 256 bytes from the end of the byte array + int startIndex = decompressedData.length - 257, + noOfBytes = 256; + try { + signature = new String (decompressedData,startIndex,noOfBytes,"ISO-8859-1"); + } catch (UnsupportedEncodingException e) { + Log.e("Exception", "Decoding Signature of QRcode, ISO-8859-1 not supported: " + e.toString()); + throw new QrCodeException("Decoding Signature of QRcode, ISO-8859-1 not supported",e); + } + + } + + public AadharCard getScannedAadharCard(){ + return scannedAadharCard; + } + + /** + * Convert byte array to hex string + * @param bytes + * @return + */ + public static String bytesToHex(byte[] bytes) { + final char[] hexArray = "0123456789ABCDEF".toCharArray(); + + char[] hexChars = new char[bytes.length * 2]; + for ( int j = 0; j < bytes.length; j++ ) { + int v = bytes[j] & 0xFF; + hexChars[j * 2] = hexArray[v >>> 4]; + hexChars[j * 2 + 1] = hexArray[v & 0x0F]; + } + return new String(hexChars); + } +} diff --git a/app/src/main/java/com/example/hpos/domain/ResultCalculationWithAvgImpl.kt b/app/src/main/java/com/example/hpos/domain/ResultCalculationWithAvgImpl.kt index 2e4e5d4..870ac95 100644 --- a/app/src/main/java/com/example/hpos/domain/ResultCalculationWithAvgImpl.kt +++ b/app/src/main/java/com/example/hpos/domain/ResultCalculationWithAvgImpl.kt @@ -1,8 +1,8 @@ package com.example.hpos.domain import com.example.hpos.data.constant.Constants -import com.example.hpos.data.model.TestRightCalculationData -import com.example.hpos.data.model.TestRightResultType +import com.example.hpos.data.model.test.TestRightCalculationData +import com.example.hpos.data.model.test.TestRightResultType class ResultCalculationWithAvgImpl : TestRightResultCalculation { diff --git a/app/src/main/java/com/example/hpos/domain/ResultCalculationWithFirstImpl.kt b/app/src/main/java/com/example/hpos/domain/ResultCalculationWithFirstImpl.kt index b350f18..a3e790d 100644 --- a/app/src/main/java/com/example/hpos/domain/ResultCalculationWithFirstImpl.kt +++ b/app/src/main/java/com/example/hpos/domain/ResultCalculationWithFirstImpl.kt @@ -2,7 +2,7 @@ package com.example.hpos.domain import android.util.Log import com.example.hpos.data.constant.Constants -import com.example.hpos.data.model.TestRightResultType +import com.example.hpos.data.model.test.TestRightResultType import kotlin.math.log10 class ResultCalculationWithFirstImpl { diff --git a/app/src/main/java/com/example/hpos/domain/ResultCalculationWithMaxImpl.kt b/app/src/main/java/com/example/hpos/domain/ResultCalculationWithMaxImpl.kt index 3d289e6..c6362be 100644 --- a/app/src/main/java/com/example/hpos/domain/ResultCalculationWithMaxImpl.kt +++ b/app/src/main/java/com/example/hpos/domain/ResultCalculationWithMaxImpl.kt @@ -1,8 +1,8 @@ package com.example.hpos.domain import com.example.hpos.data.constant.Constants -import com.example.hpos.data.model.TestRightCalculationData -import com.example.hpos.data.model.TestRightResultType +import com.example.hpos.data.model.test.TestRightCalculationData +import com.example.hpos.data.model.test.TestRightResultType class ResultCalculationWithMaxImpl : TestRightResultCalculation { diff --git a/app/src/main/java/com/example/hpos/domain/SaveRawData.kt b/app/src/main/java/com/example/hpos/domain/SaveRawData.kt index bbe76c7..1fbcd8a 100644 --- a/app/src/main/java/com/example/hpos/domain/SaveRawData.kt +++ b/app/src/main/java/com/example/hpos/domain/SaveRawData.kt @@ -4,10 +4,7 @@ import android.util.Log import com.example.hpos.data.LocalFileRepository import com.example.hpos.data.constant.Constants import com.example.hpos.data.model.PatientData -import com.example.hpos.data.model.TestRightCalculationData -import com.opencsv.CSVWriter -import java.io.File -import java.io.FileWriter +import com.example.hpos.data.model.test.TestRightCalculationData import java.util.Collections.sort class SaveRawData(private val localFileRepository: LocalFileRepository) { diff --git a/app/src/main/java/com/example/hpos/domain/SickleFindResultCaluculationWithMaxImpl.kt b/app/src/main/java/com/example/hpos/domain/SickleFindResultCaluculationWithMaxImpl.kt index 01ca955..8cca8a3 100644 --- a/app/src/main/java/com/example/hpos/domain/SickleFindResultCaluculationWithMaxImpl.kt +++ b/app/src/main/java/com/example/hpos/domain/SickleFindResultCaluculationWithMaxImpl.kt @@ -1,8 +1,8 @@ package com.example.hpos.domain import com.example.hpos.data.constant.Constants -import com.example.hpos.data.model.TestRightCalculationData -import com.example.hpos.data.model.TestRightResultType +import com.example.hpos.data.model.test.TestRightCalculationData +import com.example.hpos.data.model.test.TestRightResultType class SickleFindResultCaluculationWithMaxImpl : TestRightResultCalculation{ diff --git a/app/src/main/java/com/example/hpos/domain/TestRightResultCalculation.kt b/app/src/main/java/com/example/hpos/domain/TestRightResultCalculation.kt index 63df403..cd65dc6 100644 --- a/app/src/main/java/com/example/hpos/domain/TestRightResultCalculation.kt +++ b/app/src/main/java/com/example/hpos/domain/TestRightResultCalculation.kt @@ -1,6 +1,6 @@ package com.example.hpos.domain -import com.example.hpos.data.model.TestRightCalculationData +import com.example.hpos.data.model.test.TestRightCalculationData interface TestRightResultCalculation { fun getResults( diff --git a/app/src/main/java/com/example/hpos/presentation/DashboardFragment.kt b/app/src/main/java/com/example/hpos/presentation/DashboardFragment.kt deleted file mode 100644 index 49960fa..0000000 --- a/app/src/main/java/com/example/hpos/presentation/DashboardFragment.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.example.hpos.presentation - -import android.os.Bundle -import androidx.fragment.app.Fragment -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import com.example.hpos.R - -class DashboardFragment : Fragment() { - - override fun onCreateView( - inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? - ): View? { - // Inflate the layout for this fragment - return inflater.inflate(R.layout.fragment_dashboard, container, false) - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/example/hpos/presentation/MainActivity.kt b/app/src/main/java/com/example/hpos/presentation/MainActivity.kt index becb896..e71a2b2 100644 --- a/app/src/main/java/com/example/hpos/presentation/MainActivity.kt +++ b/app/src/main/java/com/example/hpos/presentation/MainActivity.kt @@ -4,11 +4,9 @@ import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter -import android.hardware.usb.UsbDevice import android.hardware.usb.UsbManager import android.os.Bundle import android.util.Log -import android.view.Gravity import android.view.Menu import android.widget.Toast import androidx.appcompat.app.AppCompatActivity @@ -18,7 +16,7 @@ import androidx.lifecycle.ViewModelProvider import com.example.hpos.R import com.example.hpos.data.DataHolder import com.example.hpos.data.constant.Constants -import com.example.hpos.data.model.TestType +import com.example.hpos.data.model.test.TestType import com.example.hpos.databinding.ActivityMainBinding import com.example.hpos.presentation.testRight.TestRightActivity import com.example.hpos.util.MyViewModelFactory @@ -26,7 +24,6 @@ import com.hoho.android.usbserial.driver.UsbSerialProber class MainActivity : AppCompatActivity() -// , SerialInputOutputManager.Listener { private lateinit var binding: ActivityMainBinding @@ -67,6 +64,8 @@ class MainActivity : AppCompatActivity() filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED) filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED) registerReceiver(mUsbReceiver, filter) + + } private fun checkAndUpdateUsbConnection() { @@ -107,6 +106,13 @@ class MainActivity : AppCompatActivity() myMenu?.get(0)?.icon = ContextCompat.getDrawable(this, R.drawable.ic_baseline_usb_off_24) } } + + // TODO Scan: Remove this line + binding.cvItem3.setOnClickListener { + val i = Intent(applicationContext, TestRightActivity::class.java) + startActivity(i) + } + } override fun onCreateOptionsMenu(menu: Menu?): Boolean { diff --git a/app/src/main/java/com/example/hpos/presentation/RegisterOneScanAbhaFragment.kt b/app/src/main/java/com/example/hpos/presentation/RegisterOneScanAbhaFragment.kt deleted file mode 100644 index 69b3ee3..0000000 --- a/app/src/main/java/com/example/hpos/presentation/RegisterOneScanAbhaFragment.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.example.hpos.presentation - -import android.os.Bundle -import androidx.fragment.app.Fragment -import android.view.LayoutInflater -import android.view.View -import android.view.ViewGroup -import com.example.hpos.R - -class RegisterOneScanAbhaFragment : Fragment() { - - override fun onCreateView( - inflater: LayoutInflater, container: ViewGroup?, - savedInstanceState: Bundle? - ): View? { - // Inflate the layout for this fragment - return inflater.inflate(R.layout.fragment_register_one_scan_abha, container, false) - } - -} \ No newline at end of file diff --git a/app/src/main/java/com/example/hpos/presentation/SplashActivity.kt b/app/src/main/java/com/example/hpos/presentation/SplashActivity.kt index db63bf1..bea43d7 100644 --- a/app/src/main/java/com/example/hpos/presentation/SplashActivity.kt +++ b/app/src/main/java/com/example/hpos/presentation/SplashActivity.kt @@ -8,32 +8,53 @@ import android.os.Build import android.os.Bundle import android.os.Environment import android.provider.Settings +import android.util.Log import android.widget.Toast import androidx.activity.result.contract.ActivityResultContracts import androidx.annotation.RequiresApi import androidx.appcompat.app.AppCompatActivity +import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import com.example.hpos.data.DataHolder import com.example.hpos.databinding.ActivitySplashBinding +import com.example.hpos.presentation.dashboard.DashboardActivity import com.example.hpos.util.MyUtils + /** * Splash Activity * Used for preprocessing of data, permissions */ class SplashActivity : AppCompatActivity() { + private val MY_CAMERA_REQUEST_CODE: Int = 100 private lateinit var binding: ActivitySplashBinding + var permissionStorage = false + var permissionLocation = false + var permissionCamera = false override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivitySplashBinding.inflate(layoutInflater) setContentView(binding.root) - checkForPermissions() + checkForStoragePermissions() + checkForLocationPermission() + // Keep this in last permission check, as checking all given or not after this + checkForCameraPermission() + +// Log.d("surya_permission", "passed first") + checkAllPermissionsGiven() + } - private fun checkForPermissions() { + private fun checkAllPermissionsGiven() { +// Log.d("surya_permission", "inside checkAllPermissionsGiven") + if (permissionStorage && permissionCamera && permissionLocation) + moveToLandingPage() + } + + private fun checkForStoragePermissions() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { getPermissionsAboveAndroidR() } else { @@ -49,7 +70,8 @@ class SplashActivity : AppCompatActivity() { registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { if (Environment.isExternalStorageManager()) { DataHolder.isStoragePermissionGranted = true - moveToLandingPage() +// moveToLandingPage() + permissionStorage = true } else { DataHolder.isStoragePermissionGranted = false Toast.makeText( @@ -66,7 +88,8 @@ class SplashActivity : AppCompatActivity() { storagePermissionResultLauncher.launch(intent) } else { DataHolder.isStoragePermissionGranted = true - moveToLandingPage() +// moveToLandingPage() + permissionStorage = true } } @@ -75,7 +98,8 @@ class SplashActivity : AppCompatActivity() { registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean -> if (isGranted) { DataHolder.isStoragePermissionGranted = true - moveToLandingPage() +// moveToLandingPage() + permissionStorage = true } else { DataHolder.isStoragePermissionGranted = false Toast.makeText( @@ -97,19 +121,71 @@ class SplashActivity : AppCompatActivity() { requestPermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE) } else { DataHolder.isStoragePermissionGranted = true - moveToLandingPage() +// moveToLandingPage() + permissionStorage = true + } + } + + private fun checkForCameraPermission() { + if (ContextCompat.checkSelfPermission(applicationContext, Manifest.permission.CAMERA) + == PackageManager.PERMISSION_DENIED + ) { + val requestPermissionLauncher = + registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean -> + if (isGranted) { + permissionCamera = true + checkAllPermissionsGiven() + } else { + Toast.makeText( + this, + "You must grant permission to Camera to use the app", + Toast.LENGTH_SHORT + ).show() + } + } + + requestPermissionLauncher.launch(Manifest.permission.CAMERA) + } else { + permissionCamera = true + checkAllPermissionsGiven() + } + } + + private fun checkForLocationPermission() { + if (ContextCompat.checkSelfPermission(applicationContext, Manifest.permission.ACCESS_COARSE_LOCATION) + == PackageManager.PERMISSION_DENIED + ) { + val requestPermissionLauncher = + registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean -> + if (isGranted) { + permissionLocation = true + checkAllPermissionsGiven() + } else { + Toast.makeText( + this, + "You must grant permission to Location to use the app", + Toast.LENGTH_SHORT + ).show() + } + } + + requestPermissionLauncher.launch(Manifest.permission.ACCESS_COARSE_LOCATION) + } else { + permissionLocation = true + checkAllPermissionsGiven() } } private fun moveToLandingPage() { createAppFolder() - val i = Intent(applicationContext, MainActivity::class.java) +// val i = Intent(applicationContext, MainActivity::class.java) + val i = Intent(applicationContext, DashboardActivity::class.java) startActivity(i) } private fun createAppFolder() { val folderPath = MyUtils.createAppFolder(applicationContext) - if (folderPath != null){ + if (folderPath != null) { DataHolder.isAppFolderCreated = true DataHolder.appFolderPath = folderPath } diff --git a/app/src/main/java/com/example/hpos/presentation/dashboard/DashboardActivity.kt b/app/src/main/java/com/example/hpos/presentation/dashboard/DashboardActivity.kt new file mode 100644 index 0000000..4d72da1 --- /dev/null +++ b/app/src/main/java/com/example/hpos/presentation/dashboard/DashboardActivity.kt @@ -0,0 +1,65 @@ +package com.example.hpos.presentation.dashboard + +import android.os.Bundle +import android.view.Menu +import com.google.android.material.navigation.NavigationView +import androidx.navigation.findNavController +import androidx.navigation.ui.AppBarConfiguration +import androidx.navigation.ui.navigateUp +import androidx.navigation.ui.setupActionBarWithNavController +import androidx.navigation.ui.setupWithNavController +import androidx.drawerlayout.widget.DrawerLayout +import androidx.appcompat.app.AppCompatActivity +import androidx.lifecycle.ViewModelProvider +import com.example.hpos.R +import com.example.hpos.databinding.ActivityDashboardBinding +import com.example.hpos.presentation.testRight.TestRightViewModel +import com.example.hpos.util.MyViewModelFactory + +class DashboardActivity : AppCompatActivity() { + + private lateinit var appBarConfiguration: AppBarConfiguration + private lateinit var binding: ActivityDashboardBinding + private lateinit var viewModel: DashboardViewModel + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + binding = ActivityDashboardBinding.inflate(layoutInflater) + setContentView(binding.root) + + setSupportActionBar(binding.appBarDashboard.toolbar) + + val drawerLayout: DrawerLayout = binding.drawerLayout + val navView: NavigationView = binding.navView + val navController = findNavController(R.id.nav_host_fragment_content_dashboard) + // Passing each menu ID as a set of Ids because each + // menu should be considered as top level destinations. + appBarConfiguration = AppBarConfiguration( + setOf( + R.id.nav_home, R.id.nav_profile, R.id.nav_settings + ), drawerLayout + ) + setupActionBarWithNavController(navController, appBarConfiguration) + navView.setupWithNavController(navController) + +// val i = Intent(applicationContext, MainActivity::class.java) +// startActivity(i) + + viewModel = ViewModelProvider( + this, + MyViewModelFactory(this.applicationContext) + )[DashboardViewModel::class.java] + } + + override fun onCreateOptionsMenu(menu: Menu): Boolean { + // Inflate the menu; this adds items to the action bar if it is present. + menuInflater.inflate(R.menu.dashboard, menu) + return true + } + + override fun onSupportNavigateUp(): Boolean { + val navController = findNavController(R.id.nav_host_fragment_content_dashboard) + return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp() + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/hpos/presentation/dashboard/DashboardViewModel.kt b/app/src/main/java/com/example/hpos/presentation/dashboard/DashboardViewModel.kt new file mode 100644 index 0000000..b92831c --- /dev/null +++ b/app/src/main/java/com/example/hpos/presentation/dashboard/DashboardViewModel.kt @@ -0,0 +1,55 @@ +package com.example.hpos.presentation.dashboard + +import androidx.lifecycle.ViewModel +import com.example.hpos.data.model.AadharCard +import com.example.hpos.data.model.patient.PatientDetails +import com.example.hpos.util.MyUtils.fetchYOBFromDOB +import com.example.hpos.util.MyUtils.mapToGender + +class DashboardViewModel : ViewModel() { + lateinit var aadharCard: AadharCard + lateinit var patientDetails: PatientDetails + + + fun initializePatientDetails(patient: PatientDetails) { + patientDetails = patient + } + + fun mapAadhaarDataToPatient() { + if (patientDetails.name.isNullOrEmpty()) + patientDetails.name = aadharCard.name + if (patientDetails.yob == null) + patientDetails.yob = aadharCard.dateOfBirth.fetchYOBFromDOB() + if (patientDetails.gender == null) + patientDetails.gender = aadharCard.gender.mapToGender() + if (patientDetails.mobile.isNullOrEmpty()) + patientDetails.mobile = aadharCard.mobile + if (patientDetails.careOf.isNullOrEmpty()) + patientDetails.careOf = aadharCard.careOf + + if (patientDetails.address == null) { + patientDetails.address = PatientDetails.Address() + patientDetails.address?.house = aadharCard.house + patientDetails.address?.city = aadharCard.location + patientDetails.address?.postOffice = aadharCard.postOffice + patientDetails.address?.district = aadharCard.district + patientDetails.address?.state = aadharCard.state + patientDetails.address?.pinCode = aadharCard.pinCode.toInt() + } + } + + // ------- Cloud Actions ------------------------------------------ + + fun pushPatientDetailsToCloud() { + // Synchronous Call Require + TODO("Not yet implemented") + } + + fun createTest() { + TODO("Not yet implemented") + } + + + + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/hpos/presentation/dashboard/GalleryFragment.kt b/app/src/main/java/com/example/hpos/presentation/dashboard/GalleryFragment.kt new file mode 100644 index 0000000..bead752 --- /dev/null +++ b/app/src/main/java/com/example/hpos/presentation/dashboard/GalleryFragment.kt @@ -0,0 +1,43 @@ +package com.example.hpos.presentation.dashboard + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.fragment.app.Fragment +import androidx.lifecycle.ViewModelProvider +import com.example.hpos.databinding.FragmentGalleryBinding +import com.example.hpos.presentation.dashboard.ui.gallery.GalleryViewModel + +class GalleryFragment : Fragment() { + + private var _binding: FragmentGalleryBinding? = null + + // This property is only valid between onCreateView and + // onDestroyView. + private val binding get() = _binding!! + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + val galleryViewModel = + ViewModelProvider(this).get(GalleryViewModel::class.java) + + _binding = FragmentGalleryBinding.inflate(inflater, container, false) + val root: View = binding.root + + val textView: TextView = binding.textGallery + galleryViewModel.text.observe(viewLifecycleOwner) { + textView.text = it + } + return root + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/hpos/presentation/dashboard/HomeFragment.kt b/app/src/main/java/com/example/hpos/presentation/dashboard/HomeFragment.kt new file mode 100644 index 0000000..1b85142 --- /dev/null +++ b/app/src/main/java/com/example/hpos/presentation/dashboard/HomeFragment.kt @@ -0,0 +1,47 @@ +package com.example.hpos.presentation.dashboard + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels +import androidx.lifecycle.ViewModelProvider +import androidx.navigation.fragment.findNavController +import com.example.hpos.R +import com.example.hpos.data.model.patient.PatientDetails +import com.example.hpos.databinding.FragmentHomeBinding +import com.example.hpos.presentation.dashboard.ui.home.HomeViewModel + +class HomeFragment : Fragment() { + + private var _binding: FragmentHomeBinding? = null + private val binding get() = _binding!! + private val viewModel: DashboardViewModel by activityViewModels() + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + _binding = FragmentHomeBinding.inflate(inflater, container, false) + + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + binding.btnAdd.setOnClickListener { + viewModel.initializePatientDetails(PatientDetails()) + findNavController().navigate(R.id.action_nav_home_to_registerOneScanAbhaFragment) + } + binding.btnTest.setOnClickListener { + findNavController().navigate(R.id.action_nav_home_to_mainActivity) + } + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/hpos/presentation/dashboard/SlideshowFragment.kt b/app/src/main/java/com/example/hpos/presentation/dashboard/SlideshowFragment.kt new file mode 100644 index 0000000..7487ba8 --- /dev/null +++ b/app/src/main/java/com/example/hpos/presentation/dashboard/SlideshowFragment.kt @@ -0,0 +1,43 @@ +package com.example.hpos.presentation.dashboard + +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.TextView +import androidx.fragment.app.Fragment +import androidx.lifecycle.ViewModelProvider +import com.example.hpos.databinding.FragmentSlideshowBinding +import com.example.hpos.presentation.dashboard.ui.slideshow.SlideshowViewModel + +class SlideshowFragment : Fragment() { + + private var _binding: FragmentSlideshowBinding? = null + + // This property is only valid between onCreateView and + // onDestroyView. + private val binding get() = _binding!! + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + val slideshowViewModel = + ViewModelProvider(this).get(SlideshowViewModel::class.java) + + _binding = FragmentSlideshowBinding.inflate(inflater, container, false) + val root: View = binding.root + + val textView: TextView = binding.textSlideshow + slideshowViewModel.text.observe(viewLifecycleOwner) { + textView.text = it + } + return root + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/hpos/presentation/dashboard/register/RegisterOneCreateAbha.kt b/app/src/main/java/com/example/hpos/presentation/dashboard/register/RegisterOneCreateAbha.kt new file mode 100644 index 0000000..3e0d4da --- /dev/null +++ b/app/src/main/java/com/example/hpos/presentation/dashboard/register/RegisterOneCreateAbha.kt @@ -0,0 +1,70 @@ +package com.example.hpos.presentation.dashboard.register + +import android.content.ActivityNotFoundException +import android.content.Intent +import android.content.pm.PackageManager +import android.net.Uri +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels +import androidx.navigation.fragment.findNavController +import com.example.hpos.R +import com.example.hpos.data.constant.Constants +import com.example.hpos.databinding.FragmentRegisterOneCreateAbhaBinding +import com.example.hpos.presentation.dashboard.DashboardViewModel + + +class RegisterOneCreateAbha : Fragment() { + + private val TAG = "RegisterOneCreateAbha" + private lateinit var binding: FragmentRegisterOneCreateAbhaBinding + private val viewModel: DashboardViewModel by activityViewModels() + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + binding = FragmentRegisterOneCreateAbhaBinding.inflate(inflater, container, false) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + binding.btnRedirect.setOnClickListener { + redirectApp() + } + binding.tvSkip.setOnClickListener { + // Taking to aadhaar page if ABHA is skipped + findNavController().navigate(R.id.action_registerOneCreateAbha_to_registerTwoAadhaarFragment) + } + } + + private fun redirectApp() { + val launchIntent: Intent? = requireActivity().packageManager + .getLaunchIntentForPackage(Constants.ABHA_APP_PACKAGE) + + if (launchIntent != null) { + startActivity(launchIntent) + } else { + try { + startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=${Constants.ABHA_APP_PACKAGE}"))) + } catch (e: ActivityNotFoundException) { + startActivity(Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=${Constants.ABHA_APP_PACKAGE}"))) + } + } + } + +// private fun appInstalledOrNot(uri: String): Boolean { +// val pm: PackageManager = requireActivity().packageManager +// try { +// pm.getPackageInfo(uri, PackageManager.GET_ACTIVITIES) +// return true +// } catch (e: PackageManager.NameNotFoundException) { +// } +// return false +// } + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/hpos/presentation/dashboard/register/RegisterOneScanAbhaFragment.kt b/app/src/main/java/com/example/hpos/presentation/dashboard/register/RegisterOneScanAbhaFragment.kt new file mode 100644 index 0000000..e3d4705 --- /dev/null +++ b/app/src/main/java/com/example/hpos/presentation/dashboard/register/RegisterOneScanAbhaFragment.kt @@ -0,0 +1,172 @@ +package com.example.hpos.presentation.dashboard.register + +import android.os.Bundle +import android.util.Log +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Toast +import androidx.fragment.app.Fragment +import androidx.fragment.app.activityViewModels +import androidx.navigation.fragment.findNavController +import com.example.hpos.R +import com.example.hpos.data.model.patient.PatientDetails +import com.example.hpos.databinding.FragmentRegisterOneScanAbhaBinding +import com.example.hpos.presentation.dashboard.DashboardViewModel +import com.example.hpos.util.MyUtils.fetchYOBFromDOB +import com.example.hpos.util.MyUtils.mapToGender +import com.google.mlkit.vision.barcode.common.Barcode +import com.google.mlkit.vision.codescanner.GmsBarcodeScannerOptions +import com.google.mlkit.vision.codescanner.GmsBarcodeScanning +import com.journeyapps.barcodescanner.ScanContract +import com.journeyapps.barcodescanner.ScanIntentResult +import com.journeyapps.barcodescanner.ScanOptions +import org.json.JSONObject +import java.lang.Exception + + +class RegisterOneScanAbhaFragment : Fragment() { + + private val TAG = "RegisterOneScanAbha" + private lateinit var binding: FragmentRegisterOneScanAbhaBinding + private val viewModel: DashboardViewModel by activityViewModels() + + private val barcodeLauncher = registerForActivityResult( + ScanContract() + ) { result: ScanIntentResult -> + if (result.contents == null) { + Toast.makeText(requireContext(), "Cancelled: Unable to scan, Try Again!!", Toast.LENGTH_LONG).show() + } else { + Log.d(TAG, result.contents) + processScannedData(result.contents) + } + } + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + binding = FragmentRegisterOneScanAbhaBinding.inflate(inflater, container, false) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + binding.btnScanNow.setOnClickListener { + // Todo: Remove this, add later +// viewModel.patientDetails.name = "Surya" +// viewModel.patientDetails.gender = PatientDetails.Gender.MALE +// moveToRegisterThree() + startScanningNow() + } + + binding.btnGo.setOnClickListener { + val abhaID = validateAndReturnId() + if (abhaID == null) { + Toast.makeText(requireContext(), "Invalid ID Entered", Toast.LENGTH_SHORT).show() + } else { + viewModel.patientDetails.id = abhaID + viewModel.patientDetails.isIdABHA = true + + // Scan aadhaar card to get more details + moveToRegisterTwo() + } + } + + binding.btnClickHere.setOnClickListener { + findNavController().navigate(R.id.action_registerOneScanAbhaFragment_to_registerOneCreateAbha) + } + + } + + private fun validateAndReturnId(): String? { + if (binding.nameEditText.text.isNullOrEmpty() || binding.nameEditText.text?.length != 14){ + return null + } + return binding.nameEditText.text.toString() + } + + private fun startScanningNow() { + val options = ScanOptions() + options.setDesiredBarcodeFormats(ScanOptions.QR_CODE) + options.setPrompt("Scan a barcode") + options.setCameraId(0) // Use a specific camera of the device + + options.setBeepEnabled(true) + options.setBarcodeImageEnabled(true) + + options.setPrompt("Start Scanning") + options.setOrientationLocked(false) +// options.setTimeout(10000) // in ms + + barcodeLauncher.launch(options) + } + + private fun processScannedData(contents: String) { + try { + val obj = JSONObject(contents) +// Log.d(TAG, obj.get("hidn").toString()) +// Log.d(TAG, obj.get("name").toString()) +// Log.d(TAG, obj.get("address").toString()) + + // Details mapping + viewModel.patientDetails.id = obj.get("hidn").toString().replace("-", "") + viewModel.patientDetails.isIdABHA = true + viewModel.patientDetails.name = obj.get("name").toString() + viewModel.patientDetails.gender = obj.get("gender").toString().mapToGender() + viewModel.patientDetails.yob = obj.get("dob").toString().fetchYOBFromDOB() + viewModel.patientDetails.mobile = obj.get("mobile").toString() + + // Address mapping + viewModel.patientDetails.address = PatientDetails.Address() + viewModel.patientDetails.address!!.state = obj.get("state name").toString() + viewModel.patientDetails.address!!.district = obj.get("district_name").toString() + viewModel.patientDetails.address!!.house = obj.get("address").toString() + + moveToRegisterThree() + } catch (e: Exception) { + Log.e(TAG, "Unable to parse json") + e.printStackTrace() + } + } + + private fun moveToRegisterThree() { + findNavController().navigate(R.id.action_registerOneScanAbhaFragment_to_registerThreeEnterPatientDetails) + } + + private fun moveToRegisterTwo() { + findNavController().navigate(R.id.action_registerOneScanAbhaFragment_to_registerTwoAadhaarFragment) + } + +// fun String.mapToGender(): PatientDetails.Gender { +// if (this.lowercase() == "m"|| this.lowercase() == "male") { +// return PatientDetails.Gender.MALE +// } else if (this.lowercase() == "f"|| this.lowercase() == "female") { +// return PatientDetails.Gender.FEMALE +// } else { +// return PatientDetails.Gender.OTHER +// } +// } + + private fun startScanningNow2() { + val options = GmsBarcodeScannerOptions.Builder() + .setBarcodeFormats(Barcode.FORMAT_QR_CODE) + .build() + val scanner = GmsBarcodeScanning.getClient(requireActivity(), options) + scanner.startScan() + .addOnSuccessListener { barcode -> + Log.d(TAG, barcode.rawValue!!) + } + .addOnCanceledListener { + // Task canceled + Log.d(TAG, "cancelled") + } + .addOnFailureListener { e -> + Log.d(TAG, "failed") + e.printStackTrace() + } + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/hpos/presentation/dashboard/register/RegisterThreeEnterPatientDetails.kt b/app/src/main/java/com/example/hpos/presentation/dashboard/register/RegisterThreeEnterPatientDetails.kt new file mode 100644 index 0000000..daac411 --- /dev/null +++ b/app/src/main/java/com/example/hpos/presentation/dashboard/register/RegisterThreeEnterPatientDetails.kt @@ -0,0 +1,168 @@ +package com.example.hpos.presentation.dashboard.register + +import android.os.Bundle +import androidx.fragment.app.Fragment +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Toast +import androidx.fragment.app.activityViewModels +import androidx.navigation.fragment.findNavController +import com.example.hpos.R +import com.example.hpos.data.model.PatientData +import com.example.hpos.data.model.patient.PatientDetails +import com.example.hpos.databinding.FragmentRegisterOneScanAbhaBinding +import com.example.hpos.databinding.FragmentRegisterThreeEnterPatientDetailsBinding +import com.example.hpos.presentation.dashboard.DashboardViewModel +import com.example.hpos.util.MyUtils +import com.example.hpos.util.MyUtils.mapToCategory +import com.example.hpos.util.MyUtils.mapToGender +import com.example.hpos.util.MyUtils.mapYesNoStringToBool +import java.util.Calendar + +class RegisterThreeEnterPatientDetails : Fragment() { + + private val TAG = "RegisterThreeEnterPatientDetails" + private lateinit var binding: FragmentRegisterThreeEnterPatientDetailsBinding + private val viewModel: DashboardViewModel by activityViewModels() + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + binding = FragmentRegisterThreeEnterPatientDetailsBinding.inflate(inflater, container, false) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + prefillTexts() + + binding.btnSubmit.setOnClickListener { + val mPatient = validateAndReturnPatientData() + if(mPatient != null){ + viewModel.patientDetails = mPatient + viewModel.pushPatientDetailsToCloud() + viewModel.createTest() + moveToNextPage() + } else { + Toast.makeText(requireContext(), "Fields can't be empty", Toast.LENGTH_SHORT).show() + } + } + } + + private fun moveToNextPage() { + findNavController().navigate(R.id.action_registerThreeEnterPatientDetails_to_mainActivity) + } + + private fun prefillTexts() { + viewModel.patientDetails.name?.let { binding.etName.setText(it) } + viewModel.patientDetails.yob?.let { binding.etYob.setText(it.toString()) } + viewModel.patientDetails.gender?.let { binding.etGenderBlock.setText(it.toString(), false) } + viewModel.patientDetails.mobile?.let { binding.etMobile.setText(it) } + viewModel.patientDetails.address?.house?.let { binding.etHouse.setText(it) } + viewModel.patientDetails.address?.district?.let { binding.etDistrict.setText(it) } + viewModel.patientDetails.address?.state?.let { binding.etState.setText(it) } + viewModel.patientDetails.address?.pinCode?.let { binding.etPincode.setText(it.toString()) } + } + + private fun validateAndReturnPatientData(): PatientDetails? { + if (viewModel.patientDetails.id.isEmpty()){ + Toast.makeText(requireContext(), "Unable to get \"ABHA ID\" or \"AADHAAR NO\", please try again", Toast.LENGTH_LONG).show() + } + + if (viewModel.patientDetails.address == null){ + viewModel.patientDetails.address = PatientDetails.Address() + } + + if (binding.etName.text.isNullOrEmpty()) { + binding.etName.error = getString(R.string.name_error) + return null + } else { + viewModel.patientDetails.name = binding.etName.text.toString() + } + + if (binding.etYob.text.isNullOrEmpty()) { + binding.etYob.error = getString(R.string.yob_error) + return null + } else { + viewModel.patientDetails.yob = binding.etYob.text.toString().toInt() + } + + if (binding.etGenderBlock.text.isNullOrEmpty()) { + binding.etGenderBlock.error = getString(R.string.gender_error) + return null + } else { + viewModel.patientDetails.gender = binding.etGenderBlock.text.toString().mapToGender() + } + + if (binding.etMobile.text.isNullOrEmpty()) { + binding.etMobile.error = getString(R.string.mobile_error) + return null + } else { + viewModel.patientDetails.mobile = binding.etMobile.text.toString() + } + + if (binding.etCareof.text.isNullOrEmpty()) { + binding.etCareof.error = getString(R.string.this_error) + return null + } else { + viewModel.patientDetails.careOf = binding.etCareof.text.toString() + } + + if (binding.etIsMarried.text.isNullOrEmpty()) { + binding.etIsMarried.error = getString(R.string.this_error) + return null + } else { + viewModel.patientDetails.isMarried = binding.etIsMarried.text.toString().mapYesNoStringToBool() + } + + if (binding.etCategory.text.isNullOrEmpty()) { + binding.etCategory.error = getString(R.string.this_error) + return null + } else { + viewModel.patientDetails.category = binding.etCategory.text.toString().mapToCategory() + } + + if (binding.etHouse.text.isNullOrEmpty()) { + binding.etHouse.error = getString(R.string.this_error) + return null + } else { + viewModel.patientDetails.address?.house = binding.etHouse.text.toString() + } + + if (binding.etCity.text.isNullOrEmpty()) { + binding.etCity.error = getString(R.string.this_error) + return null + } else { + viewModel.patientDetails.address?.city = binding.etCity.text.toString() + } + + if (binding.etState.text.isNullOrEmpty()) { + binding.etState.error = getString(R.string.this_error) + return null + } else { + viewModel.patientDetails.address?.state = binding.etState.text.toString() + } + + if (binding.etPincode.text.isNullOrEmpty() || binding.etPincode.text?.length != 6) { + binding.etPincode.error = getString(R.string.this_error) + return null + } else { + viewModel.patientDetails.address?.pinCode = binding.etPincode.text.toString().toInt() + } + + if (binding.etBloodGroup.text.isNullOrEmpty()) { + binding.etBloodGroup.error = getString(R.string.this_error) + return null + } else { + viewModel.patientDetails.bloodGroup = binding.etBloodGroup.text.toString() + } + + viewModel.patientDetails.isUnderMedication = binding.cbItem1.isChecked + viewModel.patientDetails.isUnderTransfusion = binding.cbItem2.isChecked + + viewModel.patientDetails.registerDate = Calendar.getInstance().time + return viewModel.patientDetails + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/hpos/presentation/dashboard/register/RegisterTwoAadhaarFragment.kt b/app/src/main/java/com/example/hpos/presentation/dashboard/register/RegisterTwoAadhaarFragment.kt new file mode 100644 index 0000000..6fa4519 --- /dev/null +++ b/app/src/main/java/com/example/hpos/presentation/dashboard/register/RegisterTwoAadhaarFragment.kt @@ -0,0 +1,124 @@ +package com.example.hpos.presentation.dashboard.register + +import android.os.Bundle +import android.util.Log +import androidx.fragment.app.Fragment +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Toast +import androidx.fragment.app.activityViewModels +import androidx.navigation.fragment.findNavController +import com.example.hpos.R +import com.example.hpos.databinding.FragmentRegisterTwoAadhaarBinding +import com.example.hpos.domain.AadhaarScanner.QrCodeException +import com.example.hpos.domain.AadhaarScanner.SecureQrCode +import com.example.hpos.presentation.dashboard.DashboardViewModel +import com.journeyapps.barcodescanner.ScanContract +import com.journeyapps.barcodescanner.ScanIntentResult +import com.journeyapps.barcodescanner.ScanOptions + +class RegisterTwoAadhaarFragment : Fragment() { + + private val TAG = "RegisterTwoAadhaarFrag" + private lateinit var binding: FragmentRegisterTwoAadhaarBinding + private val viewModel: DashboardViewModel by activityViewModels() + + private val barcodeLauncher = registerForActivityResult( + ScanContract() + ) { result: ScanIntentResult -> + if (result.contents == null) { + Toast.makeText(requireContext(), "Cancelled: Unable to scan, Try Again!!", Toast.LENGTH_LONG).show() + } else { + Log.d(TAG, result.contents) + processScannedData(result.contents) + } + } + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + binding = FragmentRegisterTwoAadhaarBinding.inflate(inflater, container, false) + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + binding.btnScanNow.setOnClickListener { + startScanningNow() + } + binding.btnGo.setOnClickListener { + val aadhaarId = validateAndReturnId() + if (aadhaarId == null) { + binding.etAbhaId.error = getString(R.string.please_enter_aadhaar) + Toast.makeText(requireContext(), "Invalid ID Entered", Toast.LENGTH_SHORT).show() + } else { + viewModel.patientDetails.id = aadhaarId + viewModel.patientDetails.isIdABHA = false + + checkForIdThenMove() + } + } + binding.etAbhaId.setOnClickListener { binding.etAbhaId.isErrorEnabled = false } + } + + private fun validateAndReturnId(): String? { + if (binding.nameEditText.text.isNullOrEmpty() || binding.nameEditText.text?.length != 12){ + return null + } + return binding.nameEditText.text.toString() + } + + private fun startScanningNow() { + val options = ScanOptions() + options.setDesiredBarcodeFormats(ScanOptions.QR_CODE) + options.setPrompt("Scan a barcode") + options.setCameraId(0) // Use a specific camera of the device + + options.setBeepEnabled(true) + options.setBarcodeImageEnabled(true) + + options.setPrompt("Start Scanning") + options.setOrientationLocked(false) +// options.setTimeout(10000) // in ms + + barcodeLauncher.launch(options) + } + + private fun processScannedData(scanData: String) { + try { + val decodedData = SecureQrCode(requireActivity(), scanData) + viewModel.aadharCard = decodedData.scannedAadharCard + + Toast.makeText(requireContext(), "Scanned Aadhar Card Successfully", Toast.LENGTH_SHORT).show() + Log.d(TAG, viewModel.aadharCard.toString()) + + viewModel.mapAadhaarDataToPatient() + + checkForIdThenMove() + + } catch (e: QrCodeException) { + e.printStackTrace() + Toast.makeText(requireContext(), "Unable to Fetch data, please try again!!", Toast.LENGTH_SHORT).show() + } + } + + private fun checkForIdThenMove() { + Log.d(TAG, "Inside: checkForIdThenMove()") + Log.d(TAG, "ID is ${viewModel.patientDetails.id}") + + if (viewModel.patientDetails.id.isNullOrEmpty()){ + binding.etAbhaId.error = getString(R.string.please_enter_aadhaar) + binding.btnScanNow.alpha = 0.2f + binding.btnScanNow.isEnabled = false + } else { + moveToRegisterThree() + } + } + + private fun moveToRegisterThree() { + findNavController().navigate(R.id.action_registerTwoAadhaarFragment_to_registerThreeEnterPatientDetails) + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/hpos/presentation/dashboard/ui/gallery/GalleryViewModel.kt b/app/src/main/java/com/example/hpos/presentation/dashboard/ui/gallery/GalleryViewModel.kt new file mode 100644 index 0000000..7ca47c0 --- /dev/null +++ b/app/src/main/java/com/example/hpos/presentation/dashboard/ui/gallery/GalleryViewModel.kt @@ -0,0 +1,13 @@ +package com.example.hpos.presentation.dashboard.ui.gallery + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel + +class GalleryViewModel : ViewModel() { + + private val _text = MutableLiveData().apply { + value = "This is gallery Fragment" + } + val text: LiveData = _text +} \ No newline at end of file diff --git a/app/src/main/java/com/example/hpos/presentation/dashboard/ui/home/HomeViewModel.kt b/app/src/main/java/com/example/hpos/presentation/dashboard/ui/home/HomeViewModel.kt new file mode 100644 index 0000000..e151bcb --- /dev/null +++ b/app/src/main/java/com/example/hpos/presentation/dashboard/ui/home/HomeViewModel.kt @@ -0,0 +1,13 @@ +package com.example.hpos.presentation.dashboard.ui.home + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel + +class HomeViewModel : ViewModel() { + + private val _text = MutableLiveData().apply { + value = "This is home Fragment" + } + val text: LiveData = _text +} \ No newline at end of file diff --git a/app/src/main/java/com/example/hpos/presentation/dashboard/ui/slideshow/SlideshowViewModel.kt b/app/src/main/java/com/example/hpos/presentation/dashboard/ui/slideshow/SlideshowViewModel.kt new file mode 100644 index 0000000..04eec20 --- /dev/null +++ b/app/src/main/java/com/example/hpos/presentation/dashboard/ui/slideshow/SlideshowViewModel.kt @@ -0,0 +1,13 @@ +package com.example.hpos.presentation.dashboard.ui.slideshow + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel + +class SlideshowViewModel : ViewModel() { + + private val _text = MutableLiveData().apply { + value = "This is slideshow Fragment" + } + val text: LiveData = _text +} \ No newline at end of file diff --git a/app/src/main/java/com/example/hpos/presentation/testRight/TestRightActivity.kt b/app/src/main/java/com/example/hpos/presentation/testRight/TestRightActivity.kt index e208e41..3d3bbeb 100644 --- a/app/src/main/java/com/example/hpos/presentation/testRight/TestRightActivity.kt +++ b/app/src/main/java/com/example/hpos/presentation/testRight/TestRightActivity.kt @@ -79,8 +79,13 @@ class TestRightActivity : AppCompatActivity() { setSupportActionBar(binding.myToolbar) supportActionBar?.setDisplayHomeAsUpEnabled(true) + // TODO Scan: Remove this line +// supportFragmentManager.beginTransaction() +// .replace(binding.flMain.id, TestRightExpScanner()).commit() + setupListener() + // TODO Scan: uncomment this line connectUsb(false) } @@ -149,7 +154,7 @@ class TestRightActivity : AppCompatActivity() { this, 0, Intent(Constants.ACTION_USB_PERMISSION), - PendingIntent.FLAG_ONE_SHOT + PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE ) } diff --git a/app/src/main/java/com/example/hpos/presentation/testRight/TestRightExpSample.kt b/app/src/main/java/com/example/hpos/presentation/testRight/TestRightExpSample.kt index 8d157e0..7abbe31 100644 --- a/app/src/main/java/com/example/hpos/presentation/testRight/TestRightExpSample.kt +++ b/app/src/main/java/com/example/hpos/presentation/testRight/TestRightExpSample.kt @@ -16,8 +16,8 @@ import com.example.hpos.data.constant.Constants import com.example.hpos.data.constant.TestRightCommands import com.example.hpos.data.model.ErrorMessage import com.example.hpos.data.model.PatientData -import com.example.hpos.data.model.TestRightResultType -import com.example.hpos.data.model.TestType +import com.example.hpos.data.model.test.TestRightResultType +import com.example.hpos.data.model.test.TestType import com.example.hpos.databinding.FragmentTestRightExpSampleBinding import com.example.hpos.presentation.UsbServiceListener import com.example.hpos.presentation.utils.MyDialogListener diff --git a/app/src/main/java/com/example/hpos/presentation/testRight/TestRightResults.kt b/app/src/main/java/com/example/hpos/presentation/testRight/TestRightResults.kt index 29d8d41..6e9c311 100644 --- a/app/src/main/java/com/example/hpos/presentation/testRight/TestRightResults.kt +++ b/app/src/main/java/com/example/hpos/presentation/testRight/TestRightResults.kt @@ -13,11 +13,10 @@ import com.example.hpos.R import com.example.hpos.data.DataHolder import com.example.hpos.data.PreferenceUtility import com.example.hpos.data.constant.Constants -import com.example.hpos.data.model.TestRightResultType -import com.example.hpos.data.model.TestType +import com.example.hpos.data.model.test.TestRightResultType +import com.example.hpos.data.model.test.TestType import com.example.hpos.databinding.FragmentTestRightResultsBinding import com.example.hpos.presentation.MainActivity -import com.example.hpos.util.MyUtils import java.text.SimpleDateFormat import java.util.* diff --git a/app/src/main/java/com/example/hpos/presentation/testRight/TestRightViewModel.kt b/app/src/main/java/com/example/hpos/presentation/testRight/TestRightViewModel.kt index 681e7ed..ba3b6bd 100644 --- a/app/src/main/java/com/example/hpos/presentation/testRight/TestRightViewModel.kt +++ b/app/src/main/java/com/example/hpos/presentation/testRight/TestRightViewModel.kt @@ -5,14 +5,14 @@ import android.util.Log import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import com.example.hpos.data.DataHolder -import com.example.hpos.data.LocalFileRepository import com.example.hpos.data.constant.Constants import com.example.hpos.data.model.* +import com.example.hpos.data.model.test.TestRightCalculationData +import com.example.hpos.data.model.test.TestRightDeviceConstants import com.example.hpos.domain.* import com.example.hpos.util.MyUtils import java.text.SimpleDateFormat import java.util.* -import java.util.Collections.sort import kotlin.collections.ArrayList import kotlin.math.log10 import kotlin.math.pow diff --git a/app/src/main/java/com/example/hpos/util/MyUtils.kt b/app/src/main/java/com/example/hpos/util/MyUtils.kt index 9d90ba3..196239c 100644 --- a/app/src/main/java/com/example/hpos/util/MyUtils.kt +++ b/app/src/main/java/com/example/hpos/util/MyUtils.kt @@ -3,7 +3,10 @@ package com.example.hpos.util import android.content.Context import android.os.Environment import com.example.hpos.R +import com.example.hpos.data.model.patient.PatientDetails import java.io.File +import java.net.InetAddress + object MyUtils { @@ -22,4 +25,43 @@ object MyUtils { } } + fun isInternetConnected(): Boolean { + return try { + val ipAddr: InetAddress = InetAddress.getByName("google.com") + ipAddr.equals("hpos") + } catch (e: Exception) { + false + } + } + + fun String.mapToGender(): PatientDetails.Gender { + return if (this.lowercase() == "m"|| this.lowercase() == "male") { + PatientDetails.Gender.MALE + } else if (this.lowercase() == "f"|| this.lowercase() == "female") { + PatientDetails.Gender.FEMALE + } else { + PatientDetails.Gender.OTHER + } + } + + fun String.mapToCategory(): PatientDetails.Category { + return when (this.lowercase()){ + "gen" -> PatientDetails.Category.GENERAL + "general" -> PatientDetails.Category.GENERAL + "obc" -> PatientDetails.Category.OBC + "sc" -> PatientDetails.Category.SC + "st" -> PatientDetails.Category.ST + else -> {PatientDetails.Category.GENERAL} + } + } + + fun String.fetchYOBFromDOB(): Int { + val startIndex = if (this.length >= 4) this.length - 4 else 0 + return this.substring(startIndex).toInt() + } + + fun String.mapYesNoStringToBool(): Boolean { + return this.lowercase() == "yes" + } + } \ No newline at end of file diff --git a/app/src/main/java/com/example/hpos/util/MyViewModelFactory.kt b/app/src/main/java/com/example/hpos/util/MyViewModelFactory.kt index 6478d3c..fc4167c 100644 --- a/app/src/main/java/com/example/hpos/util/MyViewModelFactory.kt +++ b/app/src/main/java/com/example/hpos/util/MyViewModelFactory.kt @@ -8,6 +8,7 @@ import com.example.hpos.data.datasource.LocalFileDataSource import com.example.hpos.domain.SaveRawData import com.example.hpos.domain.SaveRawDataTest import com.example.hpos.presentation.MainViewModel +import com.example.hpos.presentation.dashboard.DashboardViewModel import com.example.hpos.presentation.testRight.TestRightViewModel class MyViewModelFactory(private val context: Context) : ViewModelProvider.Factory { @@ -18,8 +19,10 @@ class MyViewModelFactory(private val context: Context) : ViewModelProvider.Facto else if (modelClass.isAssignableFrom(TestRightViewModel::class.java)) { val repository = LocalFileRepository(LocalFileDataSource()) return TestRightViewModel(SaveRawData(repository), SaveRawDataTest(repository)) as T - } - else + } else if (modelClass.isAssignableFrom(DashboardViewModel::class.java)) { +// val repository = LocalFileRepository(LocalFileDataSource()) + return DashboardViewModel() as T + } else throw IllegalArgumentException("Unknown ViewModel class"); } } \ No newline at end of file diff --git a/app/src/main/res/drawable/baseline_home_24.xml b/app/src/main/res/drawable/baseline_home_24.xml new file mode 100644 index 0000000..d24c1d8 --- /dev/null +++ b/app/src/main/res/drawable/baseline_home_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/baseline_person_24.xml b/app/src/main/res/drawable/baseline_person_24.xml new file mode 100644 index 0000000..f211ae4 --- /dev/null +++ b/app/src/main/res/drawable/baseline_person_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/baseline_settings_24.xml b/app/src/main/res/drawable/baseline_settings_24.xml new file mode 100644 index 0000000..96f3add --- /dev/null +++ b/app/src/main/res/drawable/baseline_settings_24.xml @@ -0,0 +1,5 @@ + + + diff --git a/app/src/main/res/drawable/ic_menu_camera.xml b/app/src/main/res/drawable/ic_menu_camera.xml new file mode 100644 index 0000000..634fe92 --- /dev/null +++ b/app/src/main/res/drawable/ic_menu_camera.xml @@ -0,0 +1,12 @@ + + + + diff --git a/app/src/main/res/drawable/side_nav_bar.xml b/app/src/main/res/drawable/side_nav_bar.xml new file mode 100644 index 0000000..6d81870 --- /dev/null +++ b/app/src/main/res/drawable/side_nav_bar.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/layout/activity_dashboard.xml b/app/src/main/res/layout/activity_dashboard.xml new file mode 100644 index 0000000..233d9bb --- /dev/null +++ b/app/src/main/res/layout/activity_dashboard.xml @@ -0,0 +1,26 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/app_bar_dashboard.xml b/app/src/main/res/layout/app_bar_dashboard.xml new file mode 100644 index 0000000..9361fe9 --- /dev/null +++ b/app/src/main/res/layout/app_bar_dashboard.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/content_dashboard.xml b/app/src/main/res/layout/content_dashboard.xml new file mode 100644 index 0000000..a08750e --- /dev/null +++ b/app/src/main/res/layout/content_dashboard.xml @@ -0,0 +1,20 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_gallery.xml b/app/src/main/res/layout/fragment_gallery.xml new file mode 100644 index 0000000..7fdf639 --- /dev/null +++ b/app/src/main/res/layout/fragment_gallery.xml @@ -0,0 +1,22 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_dashboard.xml b/app/src/main/res/layout/fragment_home.xml similarity index 91% rename from app/src/main/res/layout/fragment_dashboard.xml rename to app/src/main/res/layout/fragment_home.xml index d39206f..e2f8a86 100644 --- a/app/src/main/res/layout/fragment_dashboard.xml +++ b/app/src/main/res/layout/fragment_home.xml @@ -1,8 +1,7 @@ + xmlns:tools="http://schemas.android.com/tools"> @@ -60,6 +60,7 @@ android:layout_margin="24dp" android:drawableLeft="@drawable/test_tube" android:text="@string/test" + android:textColor="@color/white" app:cornerRadius="16dp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" /> diff --git a/app/src/main/res/layout/fragment_register_one_create_abha.xml b/app/src/main/res/layout/fragment_register_one_create_abha.xml new file mode 100644 index 0000000..2a9e50c --- /dev/null +++ b/app/src/main/res/layout/fragment_register_one_create_abha.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_register_one_scan_abha.xml b/app/src/main/res/layout/fragment_register_one_scan_abha.xml index 590a070..1a811da 100644 --- a/app/src/main/res/layout/fragment_register_one_scan_abha.xml +++ b/app/src/main/res/layout/fragment_register_one_scan_abha.xml @@ -2,7 +2,7 @@ + tools:context=".presentation.dashboard.register.RegisterOneScanAbhaFragment"> @@ -99,7 +100,9 @@ android:id="@+id/name_edit_text" android:layout_width="match_parent" android:layout_height="wrap_content" - android:hint="@string/abha_id" /> + android:hint="@string/abha_id" + android:maxLength="14" + android:inputType="number" /> @@ -160,15 +163,16 @@ android:layout_height="wrap_content" android:layout_marginHorizontal="24dp" android:layout_marginTop="48dp" - android:text="@string/enter_abha_number_manualy" + android:text="Create ABHA ID card" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@id/seperator2" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_register_two_aadhaar.xml b/app/src/main/res/layout/fragment_register_two_aadhaar.xml new file mode 100644 index 0000000..07350d5 --- /dev/null +++ b/app/src/main/res/layout/fragment_register_two_aadhaar.xml @@ -0,0 +1,123 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_slideshow.xml b/app/src/main/res/layout/fragment_slideshow.xml new file mode 100644 index 0000000..97d46aa --- /dev/null +++ b/app/src/main/res/layout/fragment_slideshow.xml @@ -0,0 +1,22 @@ + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/nav_header_dashboard.xml b/app/src/main/res/layout/nav_header_dashboard.xml new file mode 100644 index 0000000..c145545 --- /dev/null +++ b/app/src/main/res/layout/nav_header_dashboard.xml @@ -0,0 +1,35 @@ + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/table_item.xml b/app/src/main/res/layout/table_item.xml index c95b0dc..ff505a0 100644 --- a/app/src/main/res/layout/table_item.xml +++ b/app/src/main/res/layout/table_item.xml @@ -1,8 +1,6 @@ + xmlns:app="http://schemas.android.com/apk/res-auto"> + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/dashboard.xml b/app/src/main/res/menu/dashboard.xml new file mode 100644 index 0000000..2336500 --- /dev/null +++ b/app/src/main/res/menu/dashboard.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/app/src/main/res/navigation/dashboard_navigation.xml b/app/src/main/res/navigation/dashboard_navigation.xml new file mode 100644 index 0000000..f6e48b7 --- /dev/null +++ b/app/src/main/res/navigation/dashboard_navigation.xml @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-land/dimens.xml b/app/src/main/res/values-land/dimens.xml new file mode 100644 index 0000000..22d7f00 --- /dev/null +++ b/app/src/main/res/values-land/dimens.xml @@ -0,0 +1,3 @@ + + 48dp + \ No newline at end of file diff --git a/app/src/main/res/values-w1240dp/dimens.xml b/app/src/main/res/values-w1240dp/dimens.xml new file mode 100644 index 0000000..d73f4a3 --- /dev/null +++ b/app/src/main/res/values-w1240dp/dimens.xml @@ -0,0 +1,3 @@ + + 200dp + \ No newline at end of file diff --git a/app/src/main/res/values-w600dp/dimens.xml b/app/src/main/res/values-w600dp/dimens.xml new file mode 100644 index 0000000..22d7f00 --- /dev/null +++ b/app/src/main/res/values-w600dp/dimens.xml @@ -0,0 +1,3 @@ + + 48dp + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml new file mode 100644 index 0000000..4ab4520 --- /dev/null +++ b/app/src/main/res/values/dimens.xml @@ -0,0 +1,8 @@ + + + 16dp + 16dp + 8dp + 176dp + 16dp + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index eb69625..0028c58 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -12,6 +12,29 @@ Other + + Yes + No + + + + GEN + OBC + SC + ST + + + + O+ve + O-ve + A+ve + A-ve + B+ve + B-ve + AB+ve + AB-ve + + Hello blank fragment Select the Test Set Reference @@ -53,6 +76,11 @@ Gender can\'t be empty Age should be valid + Year of birth can\'t be empty + Mobile Number can\'t be empty + This can\'t be empty + + Test Results Name : %1$s Gender : %1$s @@ -99,5 +127,36 @@ ABHA ID GO Click Here + DashboardActivity + Open navigation drawer + Close navigation drawer + Android Studio + android.studio@android.com + Navigation header + Settings + + Home + Gallery + Slideshow + Profile + Year of Birth + Father\'s Name / Husband\'s Name + Is Patient Married? (Yes/No) + Category + Blood Group + Patient Medical Records + Patient Address Details + District + City / Town + State + Pincode + ... + Create ABHA ID Card + Official ABHA App + Scan Patient Aadhaar Card + Enter Aadhaar number manualy + Aadhaar Number + Please use “Official ABHA App" to create ABHA ID, and come back. + Please Enter Aadhaar Number to continue \ No newline at end of file diff --git a/app/src/main/res/values/themes.xml b/app/src/main/res/values/themes.xml index 5048e46..131ce2c 100644 --- a/app/src/main/res/values/themes.xml +++ b/app/src/main/res/values/themes.xml @@ -1,10 +1,10 @@ + + + +