Commit 5619cc28 authored by Ishankha K.C's avatar Ishankha K.C

Merge branch 'feature/chamod_dev' into 'master'

Feature/chamod dev

See merge request !1
parents f95aa25c 227c13db
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="AppInsightsSettings">
<option name="selectedTabId" value="Android Vitals" />
<option name="tabSettings">
<map>
<entry key="Firebase Crashlytics">
......
......@@ -3,7 +3,20 @@
<component name="deploymentTargetDropDown">
<value>
<entry key="app">
<State />
<State>
<runningDeviceTargetSelectedWithDropDown>
<Target>
<type value="RUNNING_DEVICE_TARGET" />
<deviceKey>
<Key>
<type value="SERIAL_NUMBER" />
<value value="adb-AYAV6R3925006878-kh1m4J._adb-tls-connect._tcp" />
</Key>
</deviceKey>
</Target>
</runningDeviceTargetSelectedWithDropDown>
<timeTargetWasSelectedWithDropDown value="2024-05-18T11:27:38.975164100Z" />
</State>
</entry>
</value>
</component>
......
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GitToolBoxProjectSettings">
<option name="commitMessageIssueKeyValidationOverride">
<BoolValueOverride>
<option name="enabled" value="true" />
</BoolValueOverride>
</option>
<option name="commitMessageValidationEnabledOverride">
<BoolValueOverride>
<option name="enabled" value="true" />
</BoolValueOverride>
</option>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleMigrationSettings" migrationVersion="1" />
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
......
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="AutoCloseableResource" enabled="true" level="WARNING" enabled_by_default="true">
<option name="METHOD_MATCHER_CONFIG" value="java.util.Formatter,format,java.io.Writer,append,com.google.common.base.Preconditions,checkNotNull,org.hibernate.Session,close,java.io.PrintWriter,printf,java.io.PrintStream,printf,retrofit2.Response,errorBody" />
</inspection_tool>
</profile>
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="jbr-17" project-jdk-type="JavaSDK">
......
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
......@@ -38,7 +38,15 @@ dependencies {
implementation(libs.constraintlayout)
implementation(libs.navigation.fragment)
implementation(libs.navigation.ui)
implementation(libs.activity)
implementation(libs.android.spinkit)
implementation(libs.retrofit2)
implementation(libs.convertor.gson)
implementation(libs.jackson.databind)
testImplementation(libs.junit)
androidTestImplementation(libs.ext.junit)
androidTestImplementation(libs.espresso.core)
compileOnly(libs.projectlombok)
annotationProcessor(libs.projectlombok)
}
\ No newline at end of file
......@@ -2,16 +2,32 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:networkSecurityConfig="@xml/network_security_config"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.BabyCare"
tools:targetApi="31">
<activity
android:name=".activities.UserProfileActivity"
android:exported="false" />
<activity
android:name=".activities.DashboardActivity"
android:exported="false" />
<activity
android:name=".activities.auth.RegisterActivity"
android:exported="false" />
<activity
android:name=".activities.auth.LoginActivity"
android:exported="false" />
<activity
android:name=".MainActivity"
android:exported="true"
......
package com.kaluwa.enterprises.babycare;
import static com.kaluwa.enterprises.babycare.config.TokenSaver.getToken;
import static com.kaluwa.enterprises.babycare.utils.Utils.animationChanger;
import android.content.Intent;
import android.os.Bundle;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.android.material.snackbar.Snackbar;
import androidx.appcompat.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import androidx.navigation.NavController;
......@@ -13,17 +19,57 @@ import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import com.kaluwa.enterprises.babycare.activities.DashboardActivity;
import com.kaluwa.enterprises.babycare.activities.auth.LoginActivity;
import com.kaluwa.enterprises.babycare.config.TokenSaver;
import com.kaluwa.enterprises.babycare.databinding.ActivityMainBinding;
import com.kaluwa.enterprises.babycare.dto.AuthenticationDto;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
private final static String TAG = "MainActivity";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button startedBtn = findViewById(R.id.m_btn_get_started);
startedBtn.setOnClickListener(v -> {
Intent intent = new Intent(this, LoginActivity.class);
startActivity(intent);
animationChanger(this);
});
}
@Override
protected void onStart() {
super.onStart();
// auto login
autoLogin();
}
private void autoLogin() {
// check auth
try {
AuthenticationDto authDto = getToken(getApplicationContext());
if (authDto != null) {
Intent intent = new Intent(this, DashboardActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
Toast.makeText(this, "Successfully logged in.", Toast.LENGTH_SHORT).show();
finish();
animationChanger(this);
}
} catch (JsonProcessingException e) {
Log.e(TAG, "Error: "+e.getMessage());
Toast.makeText(this, "Auto login failed.", Toast.LENGTH_SHORT).show();
}
}
}
\ No newline at end of file
package com.kaluwa.enterprises.babycare.activities;
import static com.kaluwa.enterprises.babycare.config.TokenSaver.clearToken;
import static com.kaluwa.enterprises.babycare.utils.Utils.animationChanger;
import android.content.Intent;
import android.os.Bundle;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.PopupMenu;
import androidx.appcompat.widget.Toolbar;
import com.kaluwa.enterprises.babycare.MainActivity;
import com.kaluwa.enterprises.babycare.R;
import com.kaluwa.enterprises.babycare.activities.auth.LoginActivity;
public class DashboardActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_dashboard);
// define actionbar
defineActionbar();
}
private void defineActionbar() {
Toolbar toolbar = findViewById(R.id.b_care_action_bar);
setSupportActionBar(toolbar);
if (getSupportActionBar() != null) {
getSupportActionBar().setDisplayShowTitleEnabled(false);
}
toolbar.setNavigationIcon(R.drawable.ico_menu_32);
toolbar.setNavigationOnClickListener(v -> {
// Initializing the popup menu and giving the reference as current context
PopupMenu popupMenu = new PopupMenu(this, toolbar);
popupMenu.setGravity(Gravity.BOTTOM);
popupMenu.getMenuInflater().inflate(R.menu.menu_main, popupMenu.getMenu());
popupMenu.setOnMenuItemClickListener(item -> {
int id = item.getItemId();
if (id == R.id.mm_device_setting) {
Toast.makeText(this, "You Clicked " + item.getTitle(), Toast.LENGTH_SHORT).show();
} else if (id == R.id.mm_app_setting) {
Toast.makeText(this, "You Clicked " + item.getTitle(), Toast.LENGTH_SHORT).show();
} else if (id == R.id.mm_logout) {
clearToken(getApplicationContext());
Toast.makeText(this, "Logout successful.", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(this, MainActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
animationChanger(this);
}
return true;
});
popupMenu.show();
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.user_action_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
int id = item.getItemId();
if (id == R.id.user) {
Intent intent = new Intent(this, UserProfileActivity.class);
startActivity(intent);
animationChanger(this);
} else {
Toast.makeText(this, "No item.", Toast.LENGTH_SHORT).show();
}
return super.onOptionsItemSelected(item);
}
@Override
public void onBackPressed() {
super.onBackPressed();
animationChanger(this);
}
}
\ No newline at end of file
package com.kaluwa.enterprises.babycare.activities.auth;
import static com.kaluwa.enterprises.babycare.config.TokenSaver.getToken;
import static com.kaluwa.enterprises.babycare.config.TokenSaver.setToken;
import static com.kaluwa.enterprises.babycare.utils.Utils.animationChanger;
import static com.kaluwa.enterprises.babycare.utils.Utils.emailAddressValidation;
import static com.kaluwa.enterprises.babycare.utils.Utils.loader;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import androidx.activity.EdgeToEdge;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.github.ybq.android.spinkit.SpinKitView;
import com.google.gson.Gson;
import com.kaluwa.enterprises.babycare.R;
import com.kaluwa.enterprises.babycare.activities.DashboardActivity;
import com.kaluwa.enterprises.babycare.activities.UserProfileActivity;
import com.kaluwa.enterprises.babycare.config.ApiConfig;
import com.kaluwa.enterprises.babycare.dto.AuthenticationDto;
import com.kaluwa.enterprises.babycare.dto.LoginRequest;
import com.kaluwa.enterprises.babycare.dto.UserDto;
import com.kaluwa.enterprises.babycare.error.ErrorDto;
import com.kaluwa.enterprises.babycare.service.AuthApiService;
import java.io.IOException;
import java.util.Objects;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class LoginActivity extends AppCompatActivity {
private static final String TAG = "LoginActivity";
private EditText etEmail, etPassword;
private Button btnLogin;
private SpinKitView progressBar;
private View overlay;
// auth api service
private final AuthApiService authApiService = ApiConfig.getInstance().getAuthApi();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
// progress
progressBar = findViewById(R.id.progress_bar);
overlay = findViewById(R.id.overlay);
TextView tvRegister = findViewById(R.id.l_tv_register);
tvRegister.setOnClickListener(v -> {
Intent intent = new Intent(this, RegisterActivity.class);
startActivity(intent);
animationChanger(this);
});
etEmail = findViewById(R.id.l_et_username);
etPassword = findViewById(R.id.l_et_password);
btnLogin = findViewById(R.id.l_btn_login);
btnLogin.setOnClickListener(v -> {
LoginRequest request = validate();
// call api()
if (!TextUtils.isEmpty(request.getEmail())) {
loader(overlay, progressBar, true);
Call<AuthenticationDto> call = authApiService.userLogin(request);
call.enqueue(new Callback<AuthenticationDto>() {
@Override
public void onResponse(Call<AuthenticationDto> call, Response<AuthenticationDto> response) {
if (response.isSuccessful()) {
AuthenticationDto authDto = response.body();
try {
setToken(getApplicationContext(), authDto);
Toast.makeText(LoginActivity.this, "Successfully logged in.", Toast.LENGTH_LONG).show();
Intent intent = new Intent(LoginActivity.this, DashboardActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
finish();
} catch (JsonProcessingException e) {
Log.e(TAG, e.getMessage());
Toast.makeText(LoginActivity.this, "Token saver error.", Toast.LENGTH_LONG).show();
}
loader(overlay, progressBar, false);
} else {
try {
Gson gson = new Gson();
assert response.errorBody() != null;
String errorBodyString = response.errorBody().string();
// Check if the error body is in JSON format
if (errorBodyString.startsWith("{")) {
ErrorDto errorDto = gson.fromJson(errorBodyString, ErrorDto.class);
Toast.makeText(LoginActivity.this, errorDto.getMessage(), Toast.LENGTH_LONG).show();
} else {
// If the error body is not in JSON format, display a generic error message
Log.e(TAG, errorBodyString);
Toast.makeText(LoginActivity.this, "An unexpected error occurred", Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
Log.e(TAG, e.getMessage());
Toast.makeText(LoginActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
}
loader(overlay, progressBar, false);
}
}
@Override
public void onFailure(Call<AuthenticationDto> call, Throwable t) {
Toast.makeText(LoginActivity.this, "Error to Failure", Toast.LENGTH_LONG).show();
loader(overlay, progressBar, false);
}
});
}
});
}
private LoginRequest validate() {
LoginRequest request = new LoginRequest();
String email, password;
email = etEmail.getText().toString();
password = etPassword.getText().toString();
if (TextUtils.isEmpty(email)) {
etEmail.setError("Email is required.");
etEmail.requestFocus();
} else if (!emailAddressValidation(email)) {
etEmail.setError("Invalid email address, Please re-check & try again.");
etEmail.requestFocus();
} else if (TextUtils.isEmpty(password)) {
etPassword.setError("Password is required.");
etPassword.requestFocus();
} else {
request.setEmail(email);
request.setPassword(password);
}
return request;
}
@Override
public void onBackPressed() {
super.onBackPressed();
animationChanger(this);
}
}
\ No newline at end of file
package com.kaluwa.enterprises.babycare.activities.auth;
import static com.kaluwa.enterprises.babycare.utils.Utils.animationChanger;
import static com.kaluwa.enterprises.babycare.utils.Utils.emailAddressValidation;
import static com.kaluwa.enterprises.babycare.utils.Utils.loader;
import static com.kaluwa.enterprises.babycare.utils.Utils.mobileNumberValidation;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import com.github.ybq.android.spinkit.SpinKitView;
import com.google.gson.Gson;
import com.kaluwa.enterprises.babycare.R;
import com.kaluwa.enterprises.babycare.activities.UserProfileActivity;
import com.kaluwa.enterprises.babycare.config.ApiConfig;
import com.kaluwa.enterprises.babycare.dto.RegisterRequest;
import com.kaluwa.enterprises.babycare.dto.UserDto;
import com.kaluwa.enterprises.babycare.error.ErrorDto;
import com.kaluwa.enterprises.babycare.service.AuthApiService;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class RegisterActivity extends AppCompatActivity {
private static final String TAG = "RegisterActivity";
private EditText etFirstName, etLastName, etMobileNumber, etEmail, etPassword, etConfPassword;
private Button btnRegister;
private SpinKitView progressBar;
private View overlay;
// auth api service
private final AuthApiService authApiService = ApiConfig.getInstance().getAuthApi();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_register);
// progress
progressBar = findViewById(R.id.progress_bar);
overlay = findViewById(R.id.overlay);
// values
etFirstName = findViewById(R.id.r_et_first_name);
etLastName = findViewById(R.id.r_et_last_name);
etMobileNumber = findViewById(R.id.r_et_mobile);
etEmail = findViewById(R.id.r_et_username);
etPassword = findViewById(R.id.r_et_password);
etConfPassword = findViewById(R.id.r_et_conf_password);
btnRegister = findViewById(R.id.r_btn_register);
btnRegister.setOnClickListener(v -> {
RegisterRequest request = validate();
// call api()
if (request.getEmail() != null) {
loader(overlay, progressBar, true);
Call<UserDto> regCall = authApiService.userRegister(request);
regCall.enqueue(new Callback<UserDto>() {
@Override
public void onResponse(Call<UserDto> call, Response<UserDto> response) {
if (response.isSuccessful()) {
UserDto userDto = response.body();
System.out.println("UserId: " + userDto.getUserId());
Toast.makeText(RegisterActivity.this, "User Registration is successful, Please login now.", Toast.LENGTH_LONG).show();
loader(overlay, progressBar, false);
Intent intent = new Intent(RegisterActivity.this, LoginActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
animationChanger(RegisterActivity.this);
} else {
try {
Gson gson = new Gson();
assert response.errorBody() != null;
String errorBodyString = response.errorBody().string();
// Check if the error body is in JSON format
if (errorBodyString.startsWith("{")) {
ErrorDto errorDto = gson.fromJson(errorBodyString, ErrorDto.class);
Toast.makeText(RegisterActivity.this, errorDto.getMessage(), Toast.LENGTH_LONG).show();
} else {
// If the error body is not in JSON format, display a generic error message
Log.e(TAG, errorBodyString);
Toast.makeText(RegisterActivity.this, "An unexpected error occurred", Toast.LENGTH_LONG).show();
}
} catch (Exception e) {
Log.e(TAG, e.getMessage());
Toast.makeText(RegisterActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
}
loader(overlay, progressBar, false);
}
}
@Override
public void onFailure(Call<UserDto> call, Throwable t) {
Toast.makeText(RegisterActivity.this, "Error to Failure", Toast.LENGTH_LONG).show();
loader(overlay, progressBar, false);
}
});
}
});
}
private RegisterRequest validate() {
RegisterRequest request = new RegisterRequest();
String firstname, lastname, mobile, email, password, confPassword;
firstname = etFirstName.getText().toString();
lastname = etLastName.getText().toString();
mobile = etMobileNumber.getText().toString();
email = etEmail.getText().toString();
password = etPassword.getText().toString();
confPassword = etConfPassword.getText().toString();
if (TextUtils.isEmpty(firstname)) {
etFirstName.setError("First name is required.");
etFirstName.requestFocus();
} else if (TextUtils.isEmpty(lastname)) {
etLastName.setError("Last name is required.");
etLastName.requestFocus();
} else if (TextUtils.isEmpty(mobile)) {
etMobileNumber.setError("Mobile number is required.");
etMobileNumber.requestFocus();
} else if (!mobileNumberValidation(mobile)) {
etMobileNumber.setError("Invalid mobile number format, use - (+94*********)");
etMobileNumber.requestFocus();
} else if (TextUtils.isEmpty(email)) {
etEmail.setError("Email address is required.");
etEmail.requestFocus();
} else if (!emailAddressValidation(email)) {
etEmail.setError("Invalid email address, Please re-check & try again.");
etEmail.requestFocus();
} else if (TextUtils.isEmpty(password)) {
etPassword.setError("Password is required");
etPassword.requestFocus();
} else if (password.length() < 6) {
etPassword.setError("Password must be at least 6 characters long.");
etPassword.requestFocus();
} else if (!password.equals(confPassword)) {
etConfPassword.setError("Password and confirm password do not match, Please re-check & try again.");
etConfPassword.requestFocus();
} else {
request.setFirstName(firstname);
request.setLastName(lastname);
request.setPhone(mobile);
request.setEmail(email);
request.setPassword(password);
}
return request;
}
@Override
public void onBackPressed() {
super.onBackPressed();