First working version of the app.
|
|
@ -0,0 +1,63 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<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_FINE_LOCATION" />
|
||||||
|
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
|
||||||
|
<uses-permission
|
||||||
|
android:name="android.permission.READ_EXTERNAL_STORAGE"
|
||||||
|
android:maxSdkVersion="32" />
|
||||||
|
|
||||||
|
<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:roundIcon="@mipmap/ic_launcher_round"
|
||||||
|
android:supportsRtl="true"
|
||||||
|
android:theme="@style/Theme.AcLoc"
|
||||||
|
android:usesCleartextTraffic="true"
|
||||||
|
tools:targetApi="31">
|
||||||
|
<activity
|
||||||
|
android:name=".activity.ManageRolesActivity"
|
||||||
|
android:exported="false"
|
||||||
|
android:screenOrientation="portrait" />
|
||||||
|
<activity
|
||||||
|
android:name=".activity.AddNewPlaceActivity"
|
||||||
|
android:exported="false"
|
||||||
|
android:screenOrientation="portrait" />
|
||||||
|
<activity
|
||||||
|
android:name=".activity.PlaceDetailActivity"
|
||||||
|
android:exported="false"
|
||||||
|
android:screenOrientation="portrait" />
|
||||||
|
<activity
|
||||||
|
android:name=".activity.AddReportActivity"
|
||||||
|
android:exported="false"
|
||||||
|
android:screenOrientation="portrait" />
|
||||||
|
<activity
|
||||||
|
android:name=".activity.LoginActivity"
|
||||||
|
android:exported="true"
|
||||||
|
android:screenOrientation="portrait" >
|
||||||
|
<intent-filter>
|
||||||
|
<action android:name="android.intent.action.MAIN" />
|
||||||
|
|
||||||
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
</intent-filter>
|
||||||
|
</activity>
|
||||||
|
<activity
|
||||||
|
android:name=".activity.RegisterActivity"
|
||||||
|
android:exported="false"
|
||||||
|
android:screenOrientation="portrait" />
|
||||||
|
<activity
|
||||||
|
android:name=".MainActivity"
|
||||||
|
android:exported="false"
|
||||||
|
android:screenOrientation="portrait" />
|
||||||
|
|
||||||
|
<meta-data
|
||||||
|
android:name="com.google.android.geo.API_KEY"
|
||||||
|
android:value="@string/google_maps_api_key" />
|
||||||
|
</application>
|
||||||
|
|
||||||
|
</manifest>
|
||||||
|
After Width: | Height: | Size: 46 KiB |
|
|
@ -0,0 +1,275 @@
|
||||||
|
package com.example.acloc;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.res.Configuration;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuItem;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.appcompat.view.menu.MenuBuilder;
|
||||||
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.fragment.app.FragmentTransaction;
|
||||||
|
|
||||||
|
import com.example.acloc.activities.ManageRolesActivity;
|
||||||
|
import com.example.acloc.api.ApiClient;
|
||||||
|
import com.example.acloc.dialog.AlertChangePasswordDialog;
|
||||||
|
import com.example.acloc.dialog.AlertViewOrUpdateProfileDialog;
|
||||||
|
import com.example.acloc.fragments.FavoriteFragment;
|
||||||
|
import com.example.acloc.fragments.MapFragment;
|
||||||
|
import com.example.acloc.fragments.MyReportsFragment;
|
||||||
|
import com.example.acloc.interfaces.ApiService;
|
||||||
|
import com.example.acloc.utility.DialogUtils;
|
||||||
|
import com.example.acloc.utility.Helper;
|
||||||
|
import com.example.acloc.utility.SharedPref;
|
||||||
|
import com.google.android.material.bottomnavigation.BottomNavigationView;
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Callback;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
public class MainActivity extends AppCompatActivity {
|
||||||
|
private static final String TAG = MainActivity.class.getSimpleName();
|
||||||
|
private RelativeLayout rlMainActivity;
|
||||||
|
private BottomNavigationView bottomNavigationView;
|
||||||
|
private Toolbar toolbar;
|
||||||
|
private Dialog dialog;
|
||||||
|
private Context context;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
// Get saved language from SharedPreferences
|
||||||
|
String savedLanguage = SharedPref.getLanguage(this);
|
||||||
|
|
||||||
|
// Check if current language matches saved
|
||||||
|
if (!Locale.getDefault().getLanguage().equals(savedLanguage)) {
|
||||||
|
setLocale(savedLanguage); // Apply only if needed
|
||||||
|
}
|
||||||
|
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_main);
|
||||||
|
initToolbar();
|
||||||
|
initUI();
|
||||||
|
initObj();
|
||||||
|
initListeners();
|
||||||
|
// Load default fragment
|
||||||
|
loadDefaultFragment(savedInstanceState);
|
||||||
|
getRoleUuids();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initToolbar() {
|
||||||
|
toolbar = findViewById(R.id.toolbar);
|
||||||
|
setSupportActionBar(toolbar);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initUI() {
|
||||||
|
rlMainActivity = findViewById(R.id.rlMainActivity);
|
||||||
|
bottomNavigationView = findViewById(R.id.bottomNavView);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("RestrictedApi")
|
||||||
|
@Override
|
||||||
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
|
getMenuInflater().inflate(R.menu.menu_dashboard, menu);
|
||||||
|
if (menu instanceof MenuBuilder) {
|
||||||
|
MenuBuilder m = (MenuBuilder) menu;
|
||||||
|
m.setOptionalIconsVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// show/hide the "Manage Roles" menu item
|
||||||
|
MenuItem manageNotesItem = menu.findItem(R.id.menu_manageRoles);
|
||||||
|
if (!"admin".equalsIgnoreCase(SharedPref.getRole(context))) {
|
||||||
|
manageNotesItem.setVisible(false); // hide for non-admins
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
|
||||||
|
int id = item.getItemId();
|
||||||
|
|
||||||
|
if (id == R.id.menu_profile) {
|
||||||
|
dialog = new AlertViewOrUpdateProfileDialog(context)
|
||||||
|
.openProfileDialog();
|
||||||
|
return true;
|
||||||
|
} else if (id == R.id.menu_changePassword) {
|
||||||
|
dialog = new AlertChangePasswordDialog(context)
|
||||||
|
.openChangePasswordDialog();
|
||||||
|
} else if (id == R.id.menu_changeLanguage) {
|
||||||
|
changeLanguage();
|
||||||
|
} else if (id == R.id.menu_manageRoles) {
|
||||||
|
Helper.goTo(MainActivity.this, ManageRolesActivity.class);
|
||||||
|
} else if (id == R.id.menu_logout) {
|
||||||
|
AlertDialog dialog = DialogUtils.logoutDialog(context);
|
||||||
|
dialog.show();
|
||||||
|
}
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void changeLanguage() {
|
||||||
|
String currentLanguage = Locale.getDefault().getLanguage();
|
||||||
|
String newLanguage = currentLanguage.equals("es") ? "en" : "es";
|
||||||
|
|
||||||
|
AlertDialog dialog = DialogUtils.confirmationDialog(
|
||||||
|
this,
|
||||||
|
getString(R.string.change_language_confirmation),
|
||||||
|
(dialogInterface, i) -> {
|
||||||
|
SharedPref.setLanguage(this, newLanguage); // Save to SharedPref
|
||||||
|
setLocale(newLanguage); // Apply language
|
||||||
|
|
||||||
|
// Restart app to apply change
|
||||||
|
Intent intent = new Intent(this, MainActivity.class);
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||||
|
startActivity(intent);
|
||||||
|
finish();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
dialog.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to update the language dynamically
|
||||||
|
private void setLocale(String lang) {
|
||||||
|
Locale locale = new Locale(lang);
|
||||||
|
Locale.setDefault(locale);
|
||||||
|
|
||||||
|
Configuration config = new Configuration();
|
||||||
|
config.setLocale(locale);
|
||||||
|
|
||||||
|
getBaseContext().getResources().updateConfiguration(config, getBaseContext().getResources().getDisplayMetrics());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initObj() {
|
||||||
|
context = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initListeners() {
|
||||||
|
// Set item selected listener for bottom navigation
|
||||||
|
bottomNavigationView.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
|
||||||
|
Fragment selectedFragment = null;
|
||||||
|
String title = "";
|
||||||
|
|
||||||
|
int id = item.getItemId();
|
||||||
|
if (id == R.id.menu_myReports) {
|
||||||
|
selectedFragment = new MyReportsFragment();
|
||||||
|
title = getString(R.string.My_Report);
|
||||||
|
} else if (id == R.id.menu_map) {
|
||||||
|
selectedFragment = new MapFragment();
|
||||||
|
title = getString(R.string.Map);
|
||||||
|
} else if (id == R.id.menu_favorite) {
|
||||||
|
selectedFragment = new FavoriteFragment();
|
||||||
|
title = getString(R.string.Favorite);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectedFragment != null) {
|
||||||
|
loadFragment(selectedFragment, title);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadFragment(Fragment fragment, String title) {
|
||||||
|
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
|
||||||
|
transaction.replace(R.id.flMainContainer, fragment);
|
||||||
|
transaction.commit();
|
||||||
|
|
||||||
|
if (getSupportActionBar() != null) {
|
||||||
|
getSupportActionBar().setTitle(title); // Correct way to set title with support action bar
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadDefaultFragment(Bundle savedInstanceState) {
|
||||||
|
if (savedInstanceState == null) {
|
||||||
|
Fragment defaultFragment = new MapFragment();
|
||||||
|
String defaultTitle = getString(R.string.Map);
|
||||||
|
|
||||||
|
loadFragment(defaultFragment, defaultTitle);
|
||||||
|
bottomNavigationView.setSelectedItemId(R.id.menu_map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// to change the fragment
|
||||||
|
public void openFragmentFromChild(Fragment fragment, String title, int navItemId) {
|
||||||
|
Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.flMainContainer);
|
||||||
|
if (currentFragment != null && currentFragment.getClass().equals(fragment.getClass())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
|
||||||
|
transaction.setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out);
|
||||||
|
transaction.replace(R.id.flMainContainer, fragment);
|
||||||
|
transaction.commit();
|
||||||
|
|
||||||
|
if (getSupportActionBar() != null) {
|
||||||
|
getSupportActionBar().setTitle(title);
|
||||||
|
}
|
||||||
|
|
||||||
|
bottomNavigationView.setSelectedItemId(navItemId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getRoleUuids() {
|
||||||
|
DialogUtils.showLoadingDialog(context, "");
|
||||||
|
|
||||||
|
String token = "Bearer " + SharedPref.getAccessToken(context);
|
||||||
|
ApiService apiService = ApiClient.getClient().create(ApiService.class);
|
||||||
|
|
||||||
|
Call<JsonObject> call = apiService.getRoles(token);
|
||||||
|
call.enqueue(new Callback<JsonObject>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
if (response.isSuccessful() && response.body() != null) {
|
||||||
|
JsonObject responseBody = response.body();
|
||||||
|
JsonObject data = responseBody.getAsJsonObject("_data");
|
||||||
|
|
||||||
|
if (data != null && data.has("role")) {
|
||||||
|
JsonArray rolesArray = data.getAsJsonArray("role");
|
||||||
|
|
||||||
|
for (JsonElement element : rolesArray) {
|
||||||
|
JsonObject roleObj = element.getAsJsonObject();
|
||||||
|
String roleName = roleObj.get("name").getAsString();
|
||||||
|
String roleUuid = roleObj.get("uuid").getAsString();
|
||||||
|
|
||||||
|
if ("admin".equalsIgnoreCase(roleName)) {
|
||||||
|
SharedPref.setAdminRoleUuid(context, roleUuid);
|
||||||
|
} else if ("viewer".equalsIgnoreCase(roleName)) {
|
||||||
|
SharedPref.setViewerRoleUuid(context, roleUuid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Log.d(TAG, "Admin UUID: " + SharedPref.getAdminRoleUuid(context));
|
||||||
|
Log.d(TAG, "Viewer UUID: " + SharedPref.getViewerRoleUuid(context));
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "No roles found.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "Failed to load roles. Try again.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<JsonObject> call, Throwable t) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
Log.e(TAG, "Get Roles Failure: ", t);
|
||||||
|
// Helper.makeSnackBar(rlMainActivity, context.getString(R.string.Network_error_Try_again));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,266 @@
|
||||||
|
package com.example.acloc.activities;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.provider.MediaStore;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.appcompat.widget.AppCompatButton;
|
||||||
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
|
||||||
|
import com.example.acloc.R;
|
||||||
|
import com.example.acloc.api.ApiClient;
|
||||||
|
import com.example.acloc.interfaces.ApiService;
|
||||||
|
import com.example.acloc.model.Place;
|
||||||
|
import com.example.acloc.utility.Constants;
|
||||||
|
import com.example.acloc.utility.DialogUtils;
|
||||||
|
import com.example.acloc.utility.Helper;
|
||||||
|
import com.example.acloc.utility.SharedPref;
|
||||||
|
import com.google.android.material.textfield.TextInputEditText;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Callback;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
public class AddNewPlaceActivity extends AppCompatActivity implements View.OnClickListener {
|
||||||
|
private static final String TAG = AddNewPlaceActivity.class.getSimpleName();
|
||||||
|
private RelativeLayout rlAddPlace;
|
||||||
|
private ImageView ivPlacePhoto;
|
||||||
|
private TextInputEditText etPlaceName, etLatitude, etLongitude, etAddress, etPlaceDescription;
|
||||||
|
private AppCompatButton btnSubmit;
|
||||||
|
private Dialog dialog;
|
||||||
|
private Context context;
|
||||||
|
private double lat, lng;
|
||||||
|
private String placeName, address;
|
||||||
|
|
||||||
|
private Place entity;
|
||||||
|
private String place_uuid;
|
||||||
|
private static final int PICK_IMAGE_REQUEST = 200;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_add_new_place);
|
||||||
|
initToolbar();
|
||||||
|
initUI();
|
||||||
|
initObj();
|
||||||
|
setListeners();
|
||||||
|
loadIntentData();
|
||||||
|
setDataToText();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initToolbar() {
|
||||||
|
try {
|
||||||
|
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||||
|
setSupportActionBar(toolbar);
|
||||||
|
if (getSupportActionBar() != null) {
|
||||||
|
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
|
||||||
|
getSupportActionBar().setTitle(getString(R.string.Add_Place));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error in AddNewPlaceActivity", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initUI() {
|
||||||
|
rlAddPlace = findViewById(R.id.rlAddPlace);
|
||||||
|
ivPlacePhoto = findViewById(R.id.ivPlacePhoto);
|
||||||
|
etPlaceName = findViewById(R.id.etPlaceName);
|
||||||
|
etLatitude = findViewById(R.id.etLatitude);
|
||||||
|
etLongitude = findViewById(R.id.etLongitude);
|
||||||
|
etAddress = findViewById(R.id.etAddress);
|
||||||
|
etPlaceDescription = findViewById(R.id.etPlaceDescription);
|
||||||
|
btnSubmit = findViewById(R.id.btnSubmit);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadIntentData() {
|
||||||
|
entity = (Place) getIntent().getSerializableExtra(Constants.PLACE);
|
||||||
|
place_uuid = entity.getUuid(); // setting place uuid first
|
||||||
|
if (entity != null) {
|
||||||
|
Log.d(TAG,
|
||||||
|
"PLACE ENTITY DATA \n " +
|
||||||
|
"Place uuid: " + entity.getUuid() + "\n " +
|
||||||
|
"Place name: " + entity.getName() + "\n " +
|
||||||
|
"Place address: " + entity.getAddress() + "\n " +
|
||||||
|
"Place created by: " + entity.getCreatedBy() + "\n " +
|
||||||
|
"Place latitude: " + entity.getLatitude() + "\n " +
|
||||||
|
"Place longitude: " + entity.getLongitude() + "\n " +
|
||||||
|
"Place description: " + entity.getDescription() + "\n "
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setListeners() {
|
||||||
|
ivPlacePhoto.setOnClickListener(this);
|
||||||
|
btnSubmit.setOnClickListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initObj() {
|
||||||
|
context = this;
|
||||||
|
entity = new Place();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setDataToText() {
|
||||||
|
etPlaceName.setText(entity.getName());
|
||||||
|
etLatitude.setText(entity.getLatitude());
|
||||||
|
etLongitude.setText(entity.getLongitude());
|
||||||
|
etAddress.setText(entity.getAddress());
|
||||||
|
etPlaceDescription.setText(entity.getDescription());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NonConstantResourceId")
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
int id = v.getId();
|
||||||
|
if (id == R.id.ivPlacePhoto) {
|
||||||
|
onClickIvPlacePhoto();
|
||||||
|
} else if (id == R.id.btnSubmit) {
|
||||||
|
onClickBtnSubmit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onClickIvPlacePhoto() {
|
||||||
|
// Open the gallery to select an image
|
||||||
|
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
|
||||||
|
intent.setType("image/*"); // Restrict to images only
|
||||||
|
startActivityForResult(intent, PICK_IMAGE_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null) {
|
||||||
|
// Get the image URI
|
||||||
|
Uri selectedImageUri = data.getData();
|
||||||
|
|
||||||
|
// Set the image in the ImageView
|
||||||
|
ivPlacePhoto.setImageURI(selectedImageUri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onClickBtnSubmit() {
|
||||||
|
View[] views = {etPlaceName, etLatitude, etLongitude, etAddress, etPlaceDescription};
|
||||||
|
if (Helper.isEmptyFieldValidation(views)) {
|
||||||
|
setInputDataToEntity();
|
||||||
|
|
||||||
|
if (place_uuid != null && !place_uuid.isEmpty()) {
|
||||||
|
// Update existing place
|
||||||
|
updatePlaceRetrofit(place_uuid, entity.getName(), entity.getDescription(),
|
||||||
|
entity.getAddress(), entity.getLatitude(), entity.getLongitude(), entity.getCreatedBy());
|
||||||
|
} else {
|
||||||
|
// Insert new place
|
||||||
|
insertPlaceRetrofit(entity.getName(), entity.getDescription(),
|
||||||
|
entity.getAddress(), entity.getLatitude(), entity.getLongitude(), entity.getCreatedBy());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setInputDataToEntity() {
|
||||||
|
entity.setName(Helper.getStringFromInput(etPlaceName));
|
||||||
|
entity.setDescription(Helper.getStringFromInput(etPlaceDescription));
|
||||||
|
entity.setAddress(Helper.getStringFromInput(etAddress));
|
||||||
|
entity.setLatitude(Helper.getStringFromInput(etLatitude));
|
||||||
|
entity.setLongitude(Helper.getStringFromInput(etLongitude));
|
||||||
|
entity.setCreatedBy(SharedPref.getUserUid(context));
|
||||||
|
entity.setUuid(place_uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void insertPlaceRetrofit(String name, String description, String address,
|
||||||
|
String latitude, String longitude, String createdBy) {
|
||||||
|
DialogUtils.showLoadingDialog(context, context.getString(R.string.Please_wait));
|
||||||
|
|
||||||
|
JsonObject placeBody = new JsonObject();
|
||||||
|
placeBody.addProperty("name", name);
|
||||||
|
placeBody.addProperty("description", description);
|
||||||
|
placeBody.addProperty("address", address);
|
||||||
|
placeBody.addProperty("latitude", latitude);
|
||||||
|
placeBody.addProperty("longitude", longitude);
|
||||||
|
placeBody.addProperty("createdBy", createdBy);
|
||||||
|
|
||||||
|
String token = "Bearer " + SharedPref.getAccessToken(context);
|
||||||
|
ApiService apiService = ApiClient.getClient().create(ApiService.class);
|
||||||
|
|
||||||
|
Call<JsonObject> call = apiService.insertPlace(token, placeBody);
|
||||||
|
call.enqueue(new Callback<JsonObject>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
if (response.isSuccessful() && response.body() != null) {
|
||||||
|
JsonObject responseBody = response.body();
|
||||||
|
JsonObject data = responseBody.getAsJsonObject("_data");
|
||||||
|
if (data != null && data.has("places")) {
|
||||||
|
JsonObject placeObject = data.getAsJsonArray("places").get(0).getAsJsonObject();
|
||||||
|
place_uuid = placeObject.get("uuid").getAsString();
|
||||||
|
Log.d(TAG, "Place UUID: " + place_uuid);
|
||||||
|
Helper.makeSnackBar(rlAddPlace, context.getString(R.string.Place_inserted_successfully));
|
||||||
|
rlAddPlace.postDelayed(() -> {
|
||||||
|
finish();
|
||||||
|
}, 500);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Helper.makeSnackBar(rlAddPlace, context.getString(R.string.Failed_to_extract_place_Try_again));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Helper.makeSnackBar(rlAddPlace, context.getString(R.string.Insert_failed_Server_error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<JsonObject> call, Throwable t) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
Log.e(TAG, "Insert Place Error: ", t);
|
||||||
|
Helper.makeSnackBar(rlAddPlace, context.getString(R.string.Network_error_Try_again));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updatePlaceRetrofit(String uuid, String name, String description, String address,
|
||||||
|
String latitude, String longitude, String createdBy) {
|
||||||
|
|
||||||
|
DialogUtils.showLoadingDialog(context, getString(R.string.Updating_place));
|
||||||
|
|
||||||
|
JsonObject placeBody = new JsonObject();
|
||||||
|
placeBody.addProperty("name", name);
|
||||||
|
placeBody.addProperty("description", description);
|
||||||
|
placeBody.addProperty("address", address);
|
||||||
|
placeBody.addProperty("latitude", latitude);
|
||||||
|
placeBody.addProperty("longitude", longitude);
|
||||||
|
placeBody.addProperty("createdBy", createdBy);
|
||||||
|
|
||||||
|
String token = "Bearer " + SharedPref.getAccessToken(context);
|
||||||
|
ApiService apiService = ApiClient.getClient().create(ApiService.class);
|
||||||
|
|
||||||
|
Call<JsonObject> call = apiService.updatePlace(token, uuid, placeBody);
|
||||||
|
call.enqueue(new Callback<JsonObject>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
Helper.makeSnackBar(rlAddPlace, getString(R.string.Place_updated_successfully));
|
||||||
|
rlAddPlace.postDelayed(() -> {
|
||||||
|
finish();
|
||||||
|
}, 500);
|
||||||
|
} else {
|
||||||
|
Helper.makeSnackBar(rlAddPlace, getString(R.string.Update_failed_Server_error_Try_again));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<JsonObject> call, Throwable t) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
Log.e(TAG, "Update Place Error: ", t);
|
||||||
|
Helper.makeSnackBar(rlAddPlace, context.getString(R.string.Network_error_Try_again));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,348 @@
|
||||||
|
package com.example.acloc.activities;
|
||||||
|
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.graphics.PorterDuff;
|
||||||
|
import android.net.Uri;
|
||||||
|
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.provider.MediaStore;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.appcompat.widget.AppCompatButton;
|
||||||
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
|
||||||
|
import com.example.acloc.R;
|
||||||
|
import com.example.acloc.api.ApiClient;
|
||||||
|
import com.example.acloc.interfaces.ApiService;
|
||||||
|
import com.example.acloc.model.Place;
|
||||||
|
import com.example.acloc.model.Report;
|
||||||
|
import com.example.acloc.utility.Constants;
|
||||||
|
import com.example.acloc.utility.DialogUtils;
|
||||||
|
import com.example.acloc.utility.Helper;
|
||||||
|
import com.example.acloc.utility.SharedPref;
|
||||||
|
import com.google.android.material.textfield.TextInputEditText;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Callback;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
public class AddReportActivity extends AppCompatActivity implements View.OnClickListener {
|
||||||
|
|
||||||
|
public static final String TAG = AddReportActivity.class.getSimpleName();
|
||||||
|
private RelativeLayout rlAddReport;
|
||||||
|
private TextInputEditText etDescription, etPlaceName;
|
||||||
|
private ImageView ivReportPhoto;
|
||||||
|
private ImageView ivThumbsUp, ivThumbsAverage, ivThumbsDown;
|
||||||
|
private AppCompatButton btnSubmit;
|
||||||
|
private Context context;
|
||||||
|
private Dialog dialog;
|
||||||
|
private Place placeEntity;
|
||||||
|
private Report reportEntity;
|
||||||
|
private String report_type_uuid, place_uuid;
|
||||||
|
private int reportRating;
|
||||||
|
private String report_uuid;
|
||||||
|
|
||||||
|
private static final int PICK_IMAGE_REQUEST = 100;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_add_report);
|
||||||
|
|
||||||
|
initToolbar();
|
||||||
|
initUI();
|
||||||
|
loadIntentData();
|
||||||
|
initListener();
|
||||||
|
initObj();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initToolbar() {
|
||||||
|
try {
|
||||||
|
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||||
|
setSupportActionBar(toolbar);
|
||||||
|
if (getSupportActionBar() != null) {
|
||||||
|
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
|
||||||
|
getSupportActionBar().setTitle(getString(R.string.Add_Report));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error in AddReportActivity", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initUI() {
|
||||||
|
rlAddReport = findViewById(R.id.rlAddReport);
|
||||||
|
ivReportPhoto = findViewById(R.id.ivReportPhoto);
|
||||||
|
etPlaceName = findViewById(R.id.etPlaceName);
|
||||||
|
etDescription = findViewById(R.id.etDescription);
|
||||||
|
ivThumbsUp = findViewById(R.id.ivThumbsUp);
|
||||||
|
ivThumbsAverage = findViewById(R.id.ivThumbsAverage);
|
||||||
|
ivThumbsDown = findViewById(R.id.ivThumbsDown);
|
||||||
|
btnSubmit = findViewById(R.id.btnSubmit);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadIntentData() {
|
||||||
|
placeEntity = (Place) getIntent().getSerializableExtra(Constants.PLACE);
|
||||||
|
if (placeEntity != null) {
|
||||||
|
place_uuid = placeEntity.getUuid();
|
||||||
|
etPlaceName.setText(placeEntity.getName()); //Just to display place name in report
|
||||||
|
// Log.d(TAG,
|
||||||
|
// "PLACE ENTITY DATA \n " +
|
||||||
|
// "Place uuid: " + placeEntity.getUuid() + "\n " +
|
||||||
|
// "Place name: " + placeEntity.getName() + "\n " +
|
||||||
|
// "Place address: " + placeEntity.getAddress() + "\n " +
|
||||||
|
// "Place created by: " + placeEntity.getCreatedBy() + "\n " +
|
||||||
|
// "Place latitude: " + placeEntity.getLatitude() + "\n " +
|
||||||
|
// "Place longitude: " + placeEntity.getLongitude() + "\n " +
|
||||||
|
// "Place description: " + placeEntity.getDescription() + "\n "
|
||||||
|
// );
|
||||||
|
}
|
||||||
|
|
||||||
|
reportEntity = (Report) getIntent().getSerializableExtra(Constants.REPORT);
|
||||||
|
if (reportEntity != null) {
|
||||||
|
report_uuid = reportEntity.getUuid(); // setting place uuid first
|
||||||
|
place_uuid = reportEntity.getPlaceUuid();
|
||||||
|
Log.d(TAG, "" +
|
||||||
|
"place uuid: " + reportEntity.getPlaceUuid() +
|
||||||
|
"\n fkplace " + reportEntity.getFkPlace());
|
||||||
|
setDataToEditText();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setDataToEditText() {
|
||||||
|
etPlaceName.setText(reportEntity.getPlaceName());
|
||||||
|
etDescription.setText(reportEntity.getDescription());
|
||||||
|
int rating = reportEntity.getReportRating();
|
||||||
|
if (rating == 1) {
|
||||||
|
ivThumbsDown.setColorFilter(ContextCompat.getColor(this, R.color.red), PorterDuff.Mode.SRC_IN);
|
||||||
|
ivThumbsUp.setColorFilter(null); // reset the other
|
||||||
|
ivThumbsAverage.setColorFilter(null);
|
||||||
|
reportRating = Constants.BAD_RATING; //1
|
||||||
|
} else if (rating == 2) {
|
||||||
|
ivThumbsAverage.setColorFilter(ContextCompat.getColor(this, R.color.yellow), PorterDuff.Mode.SRC_IN);
|
||||||
|
ivThumbsUp.setColorFilter(null); // reset the others
|
||||||
|
ivThumbsDown.setColorFilter(null);
|
||||||
|
reportRating = Constants.AVERAGE_RATING; //2
|
||||||
|
} else if (rating == 3) {
|
||||||
|
ivThumbsUp.setColorFilter(ContextCompat.getColor(this, R.color.green), PorterDuff.Mode.SRC_IN);
|
||||||
|
ivThumbsDown.setColorFilter(null); // reset the other
|
||||||
|
ivThumbsAverage.setColorFilter(null);
|
||||||
|
reportRating = Constants.GOOD_RATING; //3
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initListener() {
|
||||||
|
ivThumbsUp.setOnClickListener(this);
|
||||||
|
ivThumbsAverage.setOnClickListener(this);
|
||||||
|
ivThumbsDown.setOnClickListener(this);
|
||||||
|
ivReportPhoto.setOnClickListener(this);
|
||||||
|
btnSubmit.setOnClickListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initObj() {
|
||||||
|
context = this;
|
||||||
|
reportEntity = new Report();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
int id = v.getId();
|
||||||
|
if (id == R.id.ivThumbsUp) {
|
||||||
|
onClickThumbsUp();
|
||||||
|
} else if (id == R.id.ivThumbsAverage) {
|
||||||
|
onClickThumbsAverage();
|
||||||
|
} else if (id == R.id.ivThumbsDown) {
|
||||||
|
onClickThumbsDown();
|
||||||
|
} else if (id == R.id.ivReportPhoto) {
|
||||||
|
onClickIvReportPhoto();
|
||||||
|
} else if (id == R.id.btnSubmit) {
|
||||||
|
onClickBtnSubmit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onClickIvReportPhoto() {
|
||||||
|
// Open the gallery to select an image
|
||||||
|
Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
|
||||||
|
intent.setType("image/*"); // Restrict to images only
|
||||||
|
startActivityForResult(intent, PICK_IMAGE_REQUEST);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||||
|
super.onActivityResult(requestCode, resultCode, data);
|
||||||
|
if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null) {
|
||||||
|
// Get the image URI
|
||||||
|
Uri selectedImageUri = data.getData();
|
||||||
|
|
||||||
|
// Set the image in the ImageView
|
||||||
|
ivReportPhoto.setImageURI(selectedImageUri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onClickThumbsUp() {
|
||||||
|
ivThumbsUp.setColorFilter(ContextCompat.getColor(this, R.color.green), PorterDuff.Mode.SRC_IN);
|
||||||
|
ivThumbsDown.setColorFilter(null); // reset the other
|
||||||
|
ivThumbsAverage.setColorFilter(null);
|
||||||
|
reportRating = Constants.GOOD_RATING; //3
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onClickThumbsAverage() {
|
||||||
|
ivThumbsAverage.setColorFilter(ContextCompat.getColor(this, R.color.yellow), PorterDuff.Mode.SRC_IN);
|
||||||
|
ivThumbsUp.setColorFilter(null); // reset the others
|
||||||
|
ivThumbsDown.setColorFilter(null);
|
||||||
|
reportRating = Constants.AVERAGE_RATING; //2
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onClickThumbsDown() {
|
||||||
|
ivThumbsDown.setColorFilter(ContextCompat.getColor(this, R.color.red), PorterDuff.Mode.SRC_IN);
|
||||||
|
ivThumbsUp.setColorFilter(null); // reset the other
|
||||||
|
ivThumbsAverage.setColorFilter(null);
|
||||||
|
reportRating = Constants.BAD_RATING; //1
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onClickBtnSubmit() {
|
||||||
|
View[] views = {etPlaceName, etDescription};
|
||||||
|
if (Helper.isEmptyFieldValidation(views) && isValidateRating()) {
|
||||||
|
setInputDataToEntity();
|
||||||
|
|
||||||
|
if (report_uuid != null && !report_uuid.isEmpty()) {
|
||||||
|
// Update existing report
|
||||||
|
updateReportRetrofit(
|
||||||
|
report_uuid,
|
||||||
|
place_uuid,
|
||||||
|
SharedPref.getUserUid(context),
|
||||||
|
String.valueOf(reportEntity.getReportRating()),
|
||||||
|
reportEntity.getDescription(),
|
||||||
|
reportEntity.getCreatedBy()
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
insertReportRetrofit(
|
||||||
|
placeEntity.getUuid(),
|
||||||
|
SharedPref.getUserUid(context),
|
||||||
|
String.valueOf(reportEntity.getReportRating()),
|
||||||
|
reportEntity.getDescription(),
|
||||||
|
reportEntity.getCreatedBy()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setInputDataToEntity() {
|
||||||
|
reportEntity.setDescription(Helper.getStringFromInput(etDescription));
|
||||||
|
reportEntity.setReportRating(reportRating);
|
||||||
|
reportEntity.setCreatedBy(SharedPref.getUserUid(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isValidateRating() {
|
||||||
|
if (reportRating != 0) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
Helper.makeSnackBar(rlAddReport, getString(R.string.Please_select_rating));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void insertReportRetrofit(String placeUuid, String userUuid, String rating,
|
||||||
|
String description, String createdBy) {
|
||||||
|
|
||||||
|
DialogUtils.showLoadingDialog(context, getString(R.string.Please_wait));
|
||||||
|
|
||||||
|
JsonObject reportBody = new JsonObject();
|
||||||
|
reportBody.addProperty("place_uuid", placeUuid);
|
||||||
|
reportBody.addProperty("user_uuid", userUuid);
|
||||||
|
reportBody.addProperty("rating", rating);
|
||||||
|
reportBody.addProperty("description", description);
|
||||||
|
reportBody.addProperty("createdBy", createdBy);
|
||||||
|
|
||||||
|
String token = "Bearer " + SharedPref.getAccessToken(context);
|
||||||
|
ApiService apiService = ApiClient.getClient().create(ApiService.class);
|
||||||
|
|
||||||
|
Call<JsonObject> call = apiService.insertReport(token, reportBody);
|
||||||
|
call.enqueue(new Callback<JsonObject>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
if (response.isSuccessful() && response.body() != null) {
|
||||||
|
JsonObject responseBody = response.body();
|
||||||
|
JsonObject data = responseBody.getAsJsonObject("_data");
|
||||||
|
if (data != null && data.has("reports")) {
|
||||||
|
JsonObject reportObject = data.getAsJsonArray("reports").get(0).getAsJsonObject();
|
||||||
|
String report_uuid = reportObject.get("uuid").getAsString();
|
||||||
|
Log.d(TAG, "Report UUID: " + report_uuid);
|
||||||
|
Helper.makeSnackBar(rlAddReport, getString(R.string.Report_submitted_successfully));
|
||||||
|
rlAddReport.postDelayed(() -> {
|
||||||
|
finish();
|
||||||
|
}, 500);
|
||||||
|
// Delay .5 sec
|
||||||
|
// rlAddReport.postDelayed(() -> {
|
||||||
|
// Helper.goToAndFinish(AddReportActivity.this, MainActivity.class);
|
||||||
|
// }, 500);
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "Failed to extract report UUID.");
|
||||||
|
Helper.makeSnackBar(rlAddReport, getString(R.string.Something_went_wrong_Try_again));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Helper.makeSnackBar(rlAddReport, getString(R.string.Report_submission_failed_Try_again));
|
||||||
|
Log.e(TAG, "Insert Report Error: " + response.code());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<JsonObject> call, Throwable t) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
Log.e(TAG, "Insert Report Failure: ", t);
|
||||||
|
Helper.makeSnackBar(rlAddReport, context.getString(R.string.Network_error_Try_again));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateReportRetrofit(String uuid, String placeUuid, String userUuid, String rating,
|
||||||
|
String description, String createdBy) {
|
||||||
|
|
||||||
|
DialogUtils.showLoadingDialog(context, getString(R.string.Updating_report));
|
||||||
|
|
||||||
|
JsonObject reportBody = new JsonObject();
|
||||||
|
reportBody.addProperty("place_uuid", placeUuid);
|
||||||
|
reportBody.addProperty("user_uuid", userUuid);
|
||||||
|
reportBody.addProperty("rating", rating);
|
||||||
|
reportBody.addProperty("description", description);
|
||||||
|
reportBody.addProperty("createdBy", createdBy);
|
||||||
|
|
||||||
|
String token = "Bearer " + SharedPref.getAccessToken(context);
|
||||||
|
ApiService apiService = ApiClient.getClient().create(ApiService.class);
|
||||||
|
|
||||||
|
Call<JsonObject> call = apiService.updateReport(token, uuid, reportBody);
|
||||||
|
call.enqueue(new Callback<JsonObject>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
Helper.makeSnackBar(rlAddReport, getString(R.string.Report_updated_successfully));
|
||||||
|
rlAddReport.postDelayed(() -> {
|
||||||
|
finish(); //to go back to the previous activity
|
||||||
|
}, 500);
|
||||||
|
} else {
|
||||||
|
Helper.makeSnackBar(rlAddReport, getString(R.string.Update_failed_Server_error_Try_again));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<JsonObject> call, Throwable t) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
Log.e(TAG, "Update Place Error: ", t);
|
||||||
|
Helper.makeSnackBar(rlAddReport, context.getString(R.string.Network_error_Try_again));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,201 @@
|
||||||
|
package com.example.acloc.activities;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.appcompat.widget.AppCompatButton;
|
||||||
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
|
||||||
|
import com.example.acloc.MainActivity;
|
||||||
|
import com.example.acloc.R;
|
||||||
|
import com.example.acloc.api.ApiClient;
|
||||||
|
import com.example.acloc.interfaces.ApiService;
|
||||||
|
import com.example.acloc.model.User;
|
||||||
|
import com.example.acloc.utility.DialogUtils;
|
||||||
|
import com.example.acloc.utility.Helper;
|
||||||
|
import com.example.acloc.utility.SharedPref;
|
||||||
|
import com.google.android.material.textfield.TextInputEditText;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Callback;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
public class LoginActivity extends AppCompatActivity implements View.OnClickListener {
|
||||||
|
private static final String TAG = LoginActivity.class.getSimpleName();
|
||||||
|
private RelativeLayout rlLogin;
|
||||||
|
private TextInputEditText etUsername, etPassword;
|
||||||
|
private AppCompatButton btnLogin;
|
||||||
|
private Context context;
|
||||||
|
private TextView tvRegisterRedirect;
|
||||||
|
private User entity;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_login);
|
||||||
|
|
||||||
|
checkForLoginStatusAndNavigate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkForLoginStatusAndNavigate() {
|
||||||
|
boolean loginStatus = SharedPref.getIsLoggedIn(this);
|
||||||
|
boolean isTokenValid = SharedPref.isAccessTokenValid(this);
|
||||||
|
|
||||||
|
if (loginStatus && isTokenValid) {
|
||||||
|
Helper.goTo(this, MainActivity.class);
|
||||||
|
finish();
|
||||||
|
} else {
|
||||||
|
// Optionally force logout if token expired
|
||||||
|
SharedPref.setIsLoggedIn(this, false);
|
||||||
|
SharedPref.setAccessToken(this, ""); // clear token
|
||||||
|
setContentView(R.layout.activity_login);
|
||||||
|
initToolbar();
|
||||||
|
initUI();
|
||||||
|
initObj();
|
||||||
|
initListeners();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void initToolbar() {
|
||||||
|
try {
|
||||||
|
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||||
|
setSupportActionBar(toolbar);
|
||||||
|
if (getSupportActionBar() != null) {
|
||||||
|
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
|
||||||
|
getSupportActionBar().setTitle(getString(R.string.LOGIN));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error in LoginActivity", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initUI() {
|
||||||
|
rlLogin = findViewById(R.id.rlLogin);
|
||||||
|
etUsername = findViewById(R.id.etUsername);
|
||||||
|
etPassword = findViewById(R.id.etPassword);
|
||||||
|
btnLogin = findViewById(R.id.btnLogin);
|
||||||
|
tvRegisterRedirect = findViewById(R.id.tvRegisterRedirect);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initListeners() {
|
||||||
|
btnLogin.setOnClickListener(this);
|
||||||
|
tvRegisterRedirect.setOnClickListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initObj() {
|
||||||
|
context = this;
|
||||||
|
entity = new User();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
int id = v.getId();
|
||||||
|
if (id == R.id.tvRegisterRedirect) {
|
||||||
|
onClickRegisterRedirect();
|
||||||
|
} else if (id == R.id.btnLogin) {
|
||||||
|
onClickBtnLogin();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onClickRegisterRedirect() {
|
||||||
|
Helper.goToAndFinish(LoginActivity.this, RegisterActivity.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onClickBtnLogin() {
|
||||||
|
View[] views = {etUsername, etPassword};
|
||||||
|
if (Helper.isEmptyFieldValidation(views)) {
|
||||||
|
setInputDataToEntity();
|
||||||
|
loginUserWithRetrofit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setInputDataToEntity() {
|
||||||
|
entity.setUsername(Helper.getStringFromInput(etUsername));
|
||||||
|
entity.setPassword(Helper.getStringFromInput(etPassword));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loginUserWithRetrofit() {
|
||||||
|
DialogUtils.showLoadingDialog(context, getString(R.string.Please_wait));
|
||||||
|
|
||||||
|
JsonObject jsonParam = new JsonObject();
|
||||||
|
jsonParam.addProperty("username", entity.getUsername());
|
||||||
|
jsonParam.addProperty("password", entity.getPassword());
|
||||||
|
|
||||||
|
ApiService apiService = ApiClient.getClient().create(ApiService.class);
|
||||||
|
Call<JsonObject> call = apiService.loginUser(jsonParam);
|
||||||
|
|
||||||
|
call.enqueue(new Callback<JsonObject>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
|
||||||
|
if (response.isSuccessful() && response.body() != null) {
|
||||||
|
JsonObject json = response.body();
|
||||||
|
|
||||||
|
if (json.has("user")) {
|
||||||
|
JsonObject userObj = json.getAsJsonObject("user");
|
||||||
|
|
||||||
|
// 1. Extract user data from _data
|
||||||
|
if (userObj.has("_data")) {
|
||||||
|
JsonObject data = userObj.getAsJsonObject("_data");
|
||||||
|
|
||||||
|
String uuid = data.has("uuid") ? data.get("uuid").getAsString() : "";
|
||||||
|
String username = data.has("username") ? data.get("username").getAsString() : "";
|
||||||
|
String email = data.has("email") ? data.get("email").getAsString() : "";
|
||||||
|
String role = data.has("role") ? data.get("role").getAsString() : "";
|
||||||
|
|
||||||
|
SharedPref.setUuid(context, uuid);
|
||||||
|
SharedPref.setUsername(context, username);
|
||||||
|
SharedPref.setUserEmail(context, email);
|
||||||
|
SharedPref.setRole(context, role);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Extract tokens
|
||||||
|
String accessToken = userObj.has("accessToken") ? userObj.get("accessToken").getAsString() : "";
|
||||||
|
String refreshToken = userObj.has("refreshToken") ? userObj.get("refreshToken").getAsString() : "";
|
||||||
|
|
||||||
|
if (!accessToken.isEmpty()) SharedPref.setAccessToken(context, accessToken);
|
||||||
|
if (!refreshToken.isEmpty())
|
||||||
|
SharedPref.setRefreshToken(context, refreshToken);
|
||||||
|
|
||||||
|
Helper.makeSnackBar(rlLogin, getString(R.string.Login_Successful));
|
||||||
|
SharedPref.setIsLoggedIn(context, true);
|
||||||
|
Helper.goToAndFinish(LoginActivity.this, MainActivity.class);
|
||||||
|
} else {
|
||||||
|
Helper.makeSnackBar(rlLogin, getString(R.string.Invalid_Credentials_Please_try_again));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
if (response.errorBody() != null) {
|
||||||
|
String errorBody = response.errorBody().string();
|
||||||
|
Log.e(TAG, "Login Error: " + errorBody);
|
||||||
|
Helper.makeSnackBar(rlLogin, getString(R.string.Login_failed) + errorBody + " Try again");
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e(TAG, "Login error reading response", e);
|
||||||
|
// Helper.makeSnackBar(rlLogin, getString(R.string.Something_went_wrong));
|
||||||
|
Helper.makeSnackBar(rlLogin, e.toString() + " Try again");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<JsonObject> call, Throwable t) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
Log.e(TAG, "Login API call failed", t);
|
||||||
|
// Helper.makeSnackBar(rlLogin, getString(R.string.Something_went_wrong));
|
||||||
|
Helper.makeSnackBar(rlLogin, "API Failure: " + t.toString() + " Try again");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,247 @@
|
||||||
|
package com.example.acloc.activities;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.text.TextUtils;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.inputmethod.EditorInfo;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.example.acloc.R;
|
||||||
|
import com.example.acloc.adapter.UserAdapter;
|
||||||
|
import com.example.acloc.api.ApiClient;
|
||||||
|
import com.example.acloc.interfaces.ApiService;
|
||||||
|
import com.example.acloc.model.User;
|
||||||
|
import com.example.acloc.utility.DialogUtils;
|
||||||
|
import com.example.acloc.utility.Helper;
|
||||||
|
import com.example.acloc.utility.SharedPref;
|
||||||
|
import com.google.android.material.textfield.TextInputEditText;
|
||||||
|
import com.google.android.material.textfield.TextInputLayout;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Callback;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
public class ManageRolesActivity extends AppCompatActivity {
|
||||||
|
|
||||||
|
public static final String TAG = ManageRolesActivity.class.getSimpleName();
|
||||||
|
private RelativeLayout rlManageRoles;
|
||||||
|
private TextInputLayout tilSearch;
|
||||||
|
private TextInputEditText etSearchUser;
|
||||||
|
private RecyclerView rvUsers;
|
||||||
|
private List<User> userList;
|
||||||
|
private UserAdapter adapter;
|
||||||
|
private Context context;
|
||||||
|
private User userEntity;
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_manage_roles);
|
||||||
|
|
||||||
|
initToolbar();
|
||||||
|
initUI();
|
||||||
|
initListener();
|
||||||
|
initObj();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
if (adapter != null) {
|
||||||
|
setDataVisibility(false);
|
||||||
|
userList.clear();
|
||||||
|
}
|
||||||
|
if (context != null) loadData();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setDataVisibility(boolean isDataAvailable) {
|
||||||
|
if (isDataAvailable) {
|
||||||
|
rvUsers.setVisibility(View.VISIBLE);
|
||||||
|
} else {
|
||||||
|
// rvReports.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initToolbar() {
|
||||||
|
try {
|
||||||
|
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||||
|
setSupportActionBar(toolbar);
|
||||||
|
if (getSupportActionBar() != null) {
|
||||||
|
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
|
||||||
|
getSupportActionBar().setTitle(getString(R.string.Manage_Roles));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error in ManageRoles", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initUI() {
|
||||||
|
rlManageRoles = findViewById(R.id.rlManageRoles);
|
||||||
|
tilSearch = findViewById(R.id.tilSearch);
|
||||||
|
etSearchUser = findViewById(R.id.etSearchUser);
|
||||||
|
rvUsers = findViewById(R.id.rvUsers);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
|
private void initListener() {
|
||||||
|
|
||||||
|
//Search drawable on click
|
||||||
|
etSearchUser.setOnTouchListener((v, event) -> {
|
||||||
|
if (event.getAction() == MotionEvent.ACTION_UP) {
|
||||||
|
int drawableEnd = etSearchUser.getCompoundDrawables()[2] != null
|
||||||
|
? etSearchUser.getWidth() - etSearchUser.getPaddingEnd()
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
if (event.getRawX() >= (etSearchUser.getRight() - etSearchUser.getCompoundDrawables()[2].getBounds().width())) {
|
||||||
|
// Search icon clicked
|
||||||
|
filterUserList(Helper.getStringFromInput(etSearchUser));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
//Enter
|
||||||
|
etSearchUser.setOnEditorActionListener((v, actionId, event) -> {
|
||||||
|
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
|
||||||
|
filterUserList(Helper.getStringFromInput(etSearchUser));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initObj() {
|
||||||
|
context = this;
|
||||||
|
userEntity = new User();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadData() {
|
||||||
|
try {
|
||||||
|
if (userList == null) {
|
||||||
|
userList = new ArrayList<>();
|
||||||
|
}
|
||||||
|
getAllUsers();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error in ManageRoles", e);
|
||||||
|
Helper.makeSnackBar(rlManageRoles, getString(R.string.Something_went_wrong_Try_again));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setUpRecyclerView(List<User> userList) {
|
||||||
|
try {
|
||||||
|
if (adapter != null) {
|
||||||
|
adapter.updateUserList(userList);
|
||||||
|
} else {
|
||||||
|
adapter = new UserAdapter(context, userList);
|
||||||
|
rvUsers.setAdapter(adapter);
|
||||||
|
rvUsers.setLayoutManager(Helper.getVerticalManager(context));
|
||||||
|
adapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
if (userList != null && !userList.isEmpty()) {
|
||||||
|
setDataVisibility(true); // Data available
|
||||||
|
} else {
|
||||||
|
setDataVisibility(false); // No data
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error in ManageRoles", e);
|
||||||
|
Helper.showToast(context, getString(R.string.Something_went_wrong_Try_again));
|
||||||
|
setDataVisibility(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void filterUserList(String query) {
|
||||||
|
if (TextUtils.isEmpty(query)) {
|
||||||
|
setUpRecyclerView(userList); // Show full list if query is empty
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<User> filteredList = new ArrayList<>();
|
||||||
|
for (User user : userList) {
|
||||||
|
if (user.getUsername() != null && user.getUsername().toLowerCase().contains(query.toLowerCase())) {
|
||||||
|
filteredList.add(user);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setUpRecyclerView(filteredList);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void getAllUsers() {
|
||||||
|
DialogUtils.showLoadingDialog(context, getString(R.string.Loading_users));
|
||||||
|
|
||||||
|
String token = "Bearer " + SharedPref.getAccessToken(context);
|
||||||
|
ApiService apiService = ApiClient.getClient().create(ApiService.class);
|
||||||
|
|
||||||
|
Call<JsonObject> call = apiService.getAllUsers(token);
|
||||||
|
call.enqueue(new Callback<JsonObject>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
if (response.isSuccessful() && response.body() != null) {
|
||||||
|
JsonObject responseBody = response.body();
|
||||||
|
JsonObject data = responseBody.getAsJsonObject("_data");
|
||||||
|
|
||||||
|
if (data != null && data.has("users")) {
|
||||||
|
userList.clear(); // clear previous list
|
||||||
|
|
||||||
|
for (JsonElement element : data.getAsJsonArray("users")) {
|
||||||
|
JsonObject userObj = element.getAsJsonObject();
|
||||||
|
String username = userObj.get("username").getAsString();
|
||||||
|
// Skip the current logged-in user
|
||||||
|
if (username.equals(SharedPref.getUserName(context))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
User user = new User();
|
||||||
|
user.setUsername(username);
|
||||||
|
user.setEmail(userObj.has("email") && !userObj.get("email").isJsonNull()
|
||||||
|
? userObj.get("email").getAsString() : null);
|
||||||
|
user.setUuid(userObj.get("uuid").getAsString());
|
||||||
|
user.setFkRole(userObj.get("fk_role").getAsString());
|
||||||
|
user.setRole(userObj.get("role").getAsString());
|
||||||
|
|
||||||
|
userList.add(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!userList.isEmpty()) {
|
||||||
|
setUpRecyclerView(userList);
|
||||||
|
} else {
|
||||||
|
setDataVisibility(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
setDataVisibility(false);
|
||||||
|
Helper.makeSnackBar(rlManageRoles, getString(R.string.No_users_found));
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
setDataVisibility(false);
|
||||||
|
Helper.makeSnackBar(rlManageRoles, getString(R.string.Failed_to_load_users_Try_again));
|
||||||
|
Log.e(TAG, "Get users error: " + response.code());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<JsonObject> call, Throwable t) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
Log.e(TAG, "Get users failure: ", t);
|
||||||
|
Helper.makeSnackBar(rlManageRoles, context.getString(R.string.Network_error_Try_again));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,430 @@
|
||||||
|
package com.example.acloc.activities;
|
||||||
|
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.appcompat.widget.AppCompatButton;
|
||||||
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.example.acloc.R;
|
||||||
|
import com.example.acloc.adapter.PlaceReportsAdapter;
|
||||||
|
import com.example.acloc.api.ApiClient;
|
||||||
|
import com.example.acloc.interfaces.ApiService;
|
||||||
|
import com.example.acloc.model.Place;
|
||||||
|
import com.example.acloc.model.Report;
|
||||||
|
import com.example.acloc.utility.Constants;
|
||||||
|
import com.example.acloc.utility.DialogUtils;
|
||||||
|
import com.example.acloc.utility.Helper;
|
||||||
|
import com.example.acloc.utility.SharedPref;
|
||||||
|
import com.google.android.material.textview.MaterialTextView;
|
||||||
|
import com.google.gson.JsonArray;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Callback;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
public class PlaceDetailActivity extends AppCompatActivity implements View.OnClickListener {
|
||||||
|
public static final String TAG = PlaceDetailActivity.class.getSimpleName();
|
||||||
|
private RelativeLayout rlPlaceDetails;
|
||||||
|
private MaterialTextView etPlaceName, etAddress, etPlaceDescription;
|
||||||
|
private ImageView ivFavorite, ivEdit;
|
||||||
|
private AppCompatButton btnSubmit;
|
||||||
|
private Dialog dialog;
|
||||||
|
private Context context;
|
||||||
|
private Place placeEntity;
|
||||||
|
private String place_uuid;
|
||||||
|
private boolean isFavorite = false; // Track favorite current state default false
|
||||||
|
private RecyclerView rvReports;
|
||||||
|
private TextView tvNoData;
|
||||||
|
private PlaceReportsAdapter adapter;
|
||||||
|
private Report reportEntity;
|
||||||
|
private List<Report> reportList;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_place_detail);
|
||||||
|
|
||||||
|
initToolbar();
|
||||||
|
initUI();
|
||||||
|
loadIntentData(); // load data
|
||||||
|
initListener(); // set fav, edit btn On Clicks
|
||||||
|
initObj();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
if (adapter != null) {
|
||||||
|
setDataVisibility(false);
|
||||||
|
adapter.clearReports(); // Safe way to clear and notify
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context != null) loadData();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void setDataVisibility(boolean isDataAvailable) {
|
||||||
|
if (isDataAvailable) {
|
||||||
|
rvReports.setVisibility(View.VISIBLE);
|
||||||
|
tvNoData.setVisibility(View.GONE);
|
||||||
|
} else {
|
||||||
|
tvNoData.setVisibility(View.VISIBLE);
|
||||||
|
// rvReports.setVisibility(View.GONE);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initToolbar() {
|
||||||
|
try {
|
||||||
|
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||||
|
setSupportActionBar(toolbar);
|
||||||
|
if (getSupportActionBar() != null) {
|
||||||
|
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
|
||||||
|
getSupportActionBar().setTitle(getString(R.string.Place_Details));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error in PlaceDetailActivity", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initUI() {
|
||||||
|
rlPlaceDetails = findViewById(R.id.rlPlaceDetails);
|
||||||
|
etPlaceName = findViewById(R.id.etPlaceName);
|
||||||
|
etPlaceDescription = findViewById(R.id.etPlaceDescription);
|
||||||
|
etAddress = findViewById(R.id.etAddress);
|
||||||
|
ivFavorite = findViewById(R.id.ivFavorite);
|
||||||
|
ivEdit = findViewById(R.id.ivEdit);
|
||||||
|
btnSubmit = findViewById(R.id.btnSubmit);
|
||||||
|
rvReports = findViewById(R.id.rvReports);
|
||||||
|
tvNoData = findViewById(R.id.tvNoData);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initListener() {
|
||||||
|
ivFavorite.setOnClickListener(this);
|
||||||
|
ivEdit.setOnClickListener(this);
|
||||||
|
btnSubmit.setOnClickListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initObj() {
|
||||||
|
context = this;
|
||||||
|
checkIfPlaceIsFavorite(SharedPref.getUserUid(context), place_uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadIntentData() {
|
||||||
|
placeEntity = (Place) getIntent().getSerializableExtra(Constants.PLACE);
|
||||||
|
if (placeEntity != null) {
|
||||||
|
place_uuid = placeEntity.getUuid();
|
||||||
|
etPlaceName.setText(placeEntity.getName());
|
||||||
|
etAddress.setText(placeEntity.getAddress());
|
||||||
|
etPlaceDescription.setText(placeEntity.getDescription());
|
||||||
|
Log.d(TAG,
|
||||||
|
"Place uuid: " + placeEntity.getUuid() + "\n " +
|
||||||
|
"Place name: " + placeEntity.getName() + "\n " +
|
||||||
|
"Place name: " + placeEntity.getAddress() + "\n " +
|
||||||
|
"Place created by: " + placeEntity.getCreatedBy() + "\n " +
|
||||||
|
"Place latitude: " + placeEntity.getLatitude() + "\n " +
|
||||||
|
"Place longitude: " + placeEntity.getLongitude() + "\n " +
|
||||||
|
"Place description: " + placeEntity.getDescription() + "\n "
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadData() {
|
||||||
|
try {
|
||||||
|
if (reportList == null) {
|
||||||
|
reportList = new ArrayList<>();
|
||||||
|
}
|
||||||
|
getReportsByPlaceUuid(placeEntity.getUuid());
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error in PlaceDetailActivity", e);
|
||||||
|
Helper.makeSnackBar(rlPlaceDetails, getString(R.string.Something_went_wrong_Try_again));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setUpRecyclerView(List<Report> latestReports) {
|
||||||
|
try {
|
||||||
|
if (adapter != null) {
|
||||||
|
adapter.updateReportsList(latestReports);
|
||||||
|
} else {
|
||||||
|
adapter = new PlaceReportsAdapter(context, latestReports);
|
||||||
|
rvReports.setAdapter(adapter);
|
||||||
|
rvReports.setLayoutManager(Helper.getVerticalManager(context));
|
||||||
|
adapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
if (latestReports != null && !latestReports.isEmpty()) {
|
||||||
|
setDataVisibility(true); // Data available
|
||||||
|
} else {
|
||||||
|
setDataVisibility(false); // No data
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error in PlaceDetailActivity", e);
|
||||||
|
Helper.showToast(context, getString(R.string.Something_went_wrong_Try_again));
|
||||||
|
setDataVisibility(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
int id = v.getId();
|
||||||
|
if (id == R.id.ivFavorite) {
|
||||||
|
onClickFavorite();
|
||||||
|
} else if (id == R.id.ivEdit) {
|
||||||
|
onClickBtnEdit();
|
||||||
|
} else if (id == R.id.btnSubmit) {
|
||||||
|
onClickBtnSubmit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onClickBtnEdit() {
|
||||||
|
Helper.goTo(context, AddNewPlaceActivity.class, Constants.PLACE, placeEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onClickBtnSubmit() {
|
||||||
|
Helper.goTo(context, AddReportActivity.class, Constants.PLACE, placeEntity);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onClickFavorite() {
|
||||||
|
if (isFavorite) {
|
||||||
|
removePlaceFromFavorites(SharedPref.getUserUid(context), place_uuid);
|
||||||
|
} else {
|
||||||
|
addPlaceToFavorites(SharedPref.getUserUid(context), place_uuid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addPlaceToFavorites(String userUuid, String placeUuid) {
|
||||||
|
DialogUtils.showLoadingDialog(context, getString(R.string.Adding_to_favorites));
|
||||||
|
|
||||||
|
JsonObject body = new JsonObject();
|
||||||
|
body.addProperty("place_uuid", placeUuid);
|
||||||
|
Log.d(TAG, "Request Body: " + body.toString());
|
||||||
|
|
||||||
|
String token = "Bearer " + SharedPref.getAccessToken(context);
|
||||||
|
ApiService apiService = ApiClient.getClient().create(ApiService.class);
|
||||||
|
|
||||||
|
Call<JsonObject> call = apiService.addPlaceToFavorites(token, userUuid, body);
|
||||||
|
call.enqueue(new Callback<JsonObject>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
Log.d(TAG, "Place added to fav!");
|
||||||
|
isFavorite = true; // Update state
|
||||||
|
updateFavoriteIcon(); // Update icon
|
||||||
|
Helper.makeSnackBar(rlPlaceDetails, getString(R.string.Place_added_to_favorites));
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "Failed to add favorite!");
|
||||||
|
try {
|
||||||
|
if (response.errorBody() != null) {
|
||||||
|
String errorBody = response.errorBody().string();
|
||||||
|
Log.e(TAG, "Error Body: " + errorBody);
|
||||||
|
|
||||||
|
// Try restoring if it's a duplicate (409 Conflict)
|
||||||
|
if (response.code() == 409 && errorBody.contains("ER_DUP_ENTRY")) {
|
||||||
|
Log.d(TAG, "Duplicate entry detected, trying to restore...");
|
||||||
|
restorePlaceToFavorites(userUuid, placeUuid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e(TAG, "ERROR: ", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
Helper.makeSnackBar(rlPlaceDetails, getString(R.string.Failed_to_add_favorite_Server_error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<JsonObject> call, Throwable t) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
Log.e(TAG, "Add Favorite Error: ", t);
|
||||||
|
Helper.makeSnackBar(rlPlaceDetails, context.getString(R.string.Network_error_Try_again));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void restorePlaceToFavorites(String userUuid, String placeUuid) {
|
||||||
|
DialogUtils.showLoadingDialog(context, getString(R.string.Restoring_favorite));
|
||||||
|
JsonObject body = new JsonObject();
|
||||||
|
body.addProperty("place_uuid", placeUuid);
|
||||||
|
|
||||||
|
String token = "Bearer " + SharedPref.getAccessToken(context);
|
||||||
|
ApiService apiService = ApiClient.getClient().create(ApiService.class);
|
||||||
|
|
||||||
|
Call<JsonObject> call = apiService.restorePlaceToFavorites(token, userUuid, body);
|
||||||
|
call.enqueue(new Callback<JsonObject>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
Log.d(TAG, "Place restored to favorites!");
|
||||||
|
Helper.makeSnackBar(rlPlaceDetails, getString(R.string.Place_restored_to_favorites));
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "Restore failed. Response code: " + response.code());
|
||||||
|
Helper.makeSnackBar(rlPlaceDetails, getString(R.string.Failed_to_restore_favorite));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<JsonObject> call, Throwable t) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
Log.e(TAG, "Restore Favorite Error: ", t);
|
||||||
|
Helper.makeSnackBar(rlPlaceDetails, context.getString(R.string.Network_error_Try_again));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removePlaceFromFavorites(String userUuid, String placeUuid) {
|
||||||
|
DialogUtils.showLoadingDialog(context, getString(R.string.Removing_from_favorites));
|
||||||
|
String token = "Bearer " + SharedPref.getAccessToken(context);
|
||||||
|
ApiService apiService = ApiClient.getClient().create(ApiService.class);
|
||||||
|
|
||||||
|
Call<Void> call = apiService.removePlaceFromFavorites(token, userUuid, placeUuid);
|
||||||
|
call.enqueue(new Callback<Void>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<Void> call, Response<Void> response) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
Log.d(TAG, "Place removed from fav!");
|
||||||
|
isFavorite = false; // Update state
|
||||||
|
updateFavoriteIcon(); // Update icon
|
||||||
|
Helper.makeSnackBar(rlPlaceDetails, getString(R.string.Removed_from_favorites));
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "Failed to remove from fav");
|
||||||
|
Helper.makeSnackBar(rlPlaceDetails, getString(R.string.Failed_to_remove_from_favorites));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<Void> call, Throwable t) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
Log.e(TAG, "Remove Favorite Error: ", t);
|
||||||
|
Helper.makeSnackBar(rlPlaceDetails, context.getString(R.string.Network_error_Try_again));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkIfPlaceIsFavorite(String userUuid, String currentPlaceUuid) {
|
||||||
|
DialogUtils.showLoadingDialog(context, getString(R.string.Checking_favorite_status));
|
||||||
|
|
||||||
|
String token = "Bearer " + SharedPref.getAccessToken(context);
|
||||||
|
ApiService apiService = ApiClient.getClient().create(ApiService.class);
|
||||||
|
|
||||||
|
Call<JsonObject> call = apiService.getFavoritePlaces(token, userUuid);
|
||||||
|
call.enqueue(new Callback<JsonObject>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
if (response.isSuccessful() && response.body() != null) {
|
||||||
|
JsonObject body = response.body();
|
||||||
|
JsonArray favoritesArray = body.getAsJsonObject("_data").getAsJsonArray("favorites");
|
||||||
|
|
||||||
|
isFavorite = false;
|
||||||
|
for (JsonElement item : favoritesArray) {
|
||||||
|
JsonObject favoriteObj = item.getAsJsonObject();
|
||||||
|
String favPlaceUuid = favoriteObj.get("place_uuid").getAsString();
|
||||||
|
if (favPlaceUuid.equals(currentPlaceUuid)) {
|
||||||
|
isFavorite = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updateFavoriteIcon();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "Failed to fetch favorites. Code: " + response.code());
|
||||||
|
isFavorite = false;
|
||||||
|
updateFavoriteIcon();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<JsonObject> call, Throwable t) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
Log.e(TAG, "Error fetching favorite places", t);
|
||||||
|
isFavorite = false;
|
||||||
|
updateFavoriteIcon();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateFavoriteIcon() {
|
||||||
|
if (isFavorite) {
|
||||||
|
ivFavorite.setImageResource(R.drawable.ic_favorite);
|
||||||
|
} else {
|
||||||
|
ivFavorite.setImageResource(R.drawable.ic_favorite_border);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getReportsByPlaceUuid(String placeUuid) {
|
||||||
|
DialogUtils.showLoadingDialog(context, getString(R.string.Loading_reports));
|
||||||
|
|
||||||
|
String token = "Bearer " + SharedPref.getAccessToken(context);
|
||||||
|
ApiService apiService = ApiClient.getClient().create(ApiService.class);
|
||||||
|
|
||||||
|
// Make the API call to fetch reports by place UUID
|
||||||
|
Call<JsonObject> call = apiService.getPlaceReports(token, placeUuid);
|
||||||
|
call.enqueue(new Callback<JsonObject>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
if (response.isSuccessful() && response.body() != null) {
|
||||||
|
JsonObject responseBody = response.body();
|
||||||
|
JsonObject data = responseBody.getAsJsonObject("_data");
|
||||||
|
|
||||||
|
if (data != null && data.has("reports")) {
|
||||||
|
reportList.clear(); // Clear previous list
|
||||||
|
|
||||||
|
for (JsonElement element : data.getAsJsonArray("reports")) {
|
||||||
|
JsonObject reportObject = element.getAsJsonObject();
|
||||||
|
Report report = new Report();
|
||||||
|
|
||||||
|
report.setUuid(reportObject.get("uuid").getAsString());
|
||||||
|
report.setReportRating(reportObject.get("rating").getAsInt());
|
||||||
|
report.setDescription(reportObject.get("description").getAsString());
|
||||||
|
report.setPlaceName(reportObject.get("place_name").getAsString());
|
||||||
|
report.setPlaceUuid(reportObject.get("place_uuid").getAsString());
|
||||||
|
|
||||||
|
reportList.add(report);
|
||||||
|
}
|
||||||
|
// to get latest report first
|
||||||
|
Collections.reverse(reportList);
|
||||||
|
List<Report> latestReports = reportList.size() > 5 ? reportList.subList(0, 5) : reportList;
|
||||||
|
|
||||||
|
// Update the RecyclerView with latest reports
|
||||||
|
setUpRecyclerView(latestReports);
|
||||||
|
} else {
|
||||||
|
setDataVisibility(false);
|
||||||
|
Helper.makeSnackBar(rlPlaceDetails, getString(R.string.No_reports_found));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setDataVisibility(false);
|
||||||
|
Helper.makeSnackBar(rlPlaceDetails, getString(R.string.Failed_to_load_reports_Try_again_));
|
||||||
|
Log.e(TAG, "Get Reports Error: " + response.code());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<JsonObject> call, Throwable t) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
Log.e(TAG, "Get Reports Failure: ", t);
|
||||||
|
Helper.makeSnackBar(rlPlaceDetails, context.getString(R.string.Network_error_Try_again));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,169 @@
|
||||||
|
package com.example.acloc.activities;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
|
import androidx.appcompat.widget.AppCompatButton;
|
||||||
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
|
||||||
|
import com.example.acloc.R;
|
||||||
|
import com.example.acloc.api.ApiClient;
|
||||||
|
import com.example.acloc.interfaces.ApiService;
|
||||||
|
import com.example.acloc.model.User;
|
||||||
|
import com.example.acloc.utility.Constants;
|
||||||
|
import com.example.acloc.utility.DialogUtils;
|
||||||
|
import com.example.acloc.utility.Helper;
|
||||||
|
import com.google.android.material.textfield.TextInputEditText;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Callback;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
public class RegisterActivity extends AppCompatActivity implements View.OnClickListener {
|
||||||
|
private static final String TAG = RegisterActivity.class.getSimpleName();
|
||||||
|
private RelativeLayout rlRegister;
|
||||||
|
private TextInputEditText etName, etEmail, etPassword;
|
||||||
|
private AppCompatButton btnRegister;
|
||||||
|
private TextView tvLoginRedirect;
|
||||||
|
private Context context;
|
||||||
|
private User entity;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
|
super.onCreate(savedInstanceState);
|
||||||
|
setContentView(R.layout.activity_register);
|
||||||
|
|
||||||
|
initToolbar();
|
||||||
|
initUI();
|
||||||
|
initObj();
|
||||||
|
initListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initToolbar() {
|
||||||
|
try {
|
||||||
|
Toolbar toolbar = findViewById(R.id.toolbar);
|
||||||
|
setSupportActionBar(toolbar);
|
||||||
|
if (getSupportActionBar() != null) {
|
||||||
|
getSupportActionBar().setDisplayHomeAsUpEnabled(false);
|
||||||
|
getSupportActionBar().setTitle(getString(R.string.REGISTER));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error in RegisterActivity", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initUI() {
|
||||||
|
rlRegister = findViewById(R.id.rlRegister);
|
||||||
|
etName = findViewById(R.id.etName);
|
||||||
|
etEmail = findViewById(R.id.etEmail);
|
||||||
|
etPassword = findViewById(R.id.etPassword);
|
||||||
|
btnRegister = findViewById(R.id.btnRegister);
|
||||||
|
tvLoginRedirect = findViewById(R.id.tvLoginRedirect);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initListeners() {
|
||||||
|
btnRegister.setOnClickListener(this);
|
||||||
|
tvLoginRedirect.setOnClickListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initObj() {
|
||||||
|
context = this;
|
||||||
|
entity = new User();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
int id = v.getId();
|
||||||
|
if (id == R.id.tvLoginRedirect) {
|
||||||
|
onClickLoginRedirect();
|
||||||
|
} else if (id == R.id.btnRegister) {
|
||||||
|
onClickBtnRegister();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onClickLoginRedirect() {
|
||||||
|
Helper.goToAndFinish(RegisterActivity.this, LoginActivity.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onClickBtnRegister() {
|
||||||
|
View[] views = {etName, etEmail, etPassword};
|
||||||
|
if (Helper.isEmptyFieldValidation(views) && Helper.isEmailValid(etEmail) && Helper.isPasswordValid(etPassword)) {
|
||||||
|
setInputDataToEntity();
|
||||||
|
registerUserWithRetrofit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setInputDataToEntity() {
|
||||||
|
entity.setUsername(Helper.getStringFromInput(etName));
|
||||||
|
entity.setEmail(Helper.getStringFromInput(etEmail));
|
||||||
|
entity.setPassword(Helper.getStringFromInput(etPassword));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerUserWithRetrofit() {
|
||||||
|
DialogUtils.showLoadingDialog(context, getString(R.string.Please_wait));
|
||||||
|
|
||||||
|
JsonObject jsonParam = new JsonObject();
|
||||||
|
jsonParam.addProperty("username", entity.getUsername());
|
||||||
|
jsonParam.addProperty("email", entity.getEmail());
|
||||||
|
jsonParam.addProperty("password", entity.getPassword());
|
||||||
|
jsonParam.addProperty("fk_role", Constants.ADMIN); //Default Admin for now (BUT acc to api it will be Viewer)
|
||||||
|
|
||||||
|
ApiService apiService = ApiClient.getClient().create(ApiService.class);
|
||||||
|
Call<JsonObject> call = apiService.registerUser(jsonParam);
|
||||||
|
|
||||||
|
call.enqueue(new Callback<JsonObject>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
|
||||||
|
if (response.isSuccessful() && response.body() != null) {
|
||||||
|
JsonObject json = response.body();
|
||||||
|
|
||||||
|
if (json.has("code") && json.get("code").getAsInt() == 409) {
|
||||||
|
Helper.makeSnackBar(rlRegister, getString(R.string.User_already_exists_Please_login));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (json.has("_data") && json.getAsJsonObject("_data").has("message")) {
|
||||||
|
Helper.makeSnackBar(rlRegister, getString(R.string.Registration_Successful));
|
||||||
|
Helper.goToAndFinish(RegisterActivity.this, LoginActivity.class);
|
||||||
|
} else {
|
||||||
|
Helper.makeSnackBar(rlRegister, getString(R.string.Invalid_Credentials_Please_try_again));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
if (response.errorBody() != null) {
|
||||||
|
String errorBody = response.errorBody().string();
|
||||||
|
Log.e(TAG, "Error Response: " + errorBody);
|
||||||
|
Helper.makeSnackBar(rlRegister, "Server Error " + errorBody + " Try again");
|
||||||
|
} else {
|
||||||
|
// Helper.makeSnackBar(rlRegister, getString(R.string.Something_went_wrong));
|
||||||
|
Helper.makeSnackBar(rlRegister, "Server Error " + " Try again");
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e(TAG, "Error reading errorBody", e);
|
||||||
|
// Helper.makeSnackBar(rlRegister, getString(R.string.Something_went_wrong));
|
||||||
|
Helper.makeSnackBar(rlRegister, "API Failure: " + e.toString() + " Try again");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<JsonObject> call, Throwable t) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
Log.e(TAG, "API Failure", t);
|
||||||
|
// Helper.makeSnackBar(rlRegister, getString(R.string.Something_went_wrong));
|
||||||
|
Helper.makeSnackBar(rlRegister, "API Failure: " + t.toString() + " Try again");
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,199 @@
|
||||||
|
package com.example.acloc.adapter;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.example.acloc.R;
|
||||||
|
import com.example.acloc.activities.PlaceDetailActivity;
|
||||||
|
import com.example.acloc.api.ApiClient;
|
||||||
|
import com.example.acloc.interfaces.ApiService;
|
||||||
|
import com.example.acloc.model.Favorite;
|
||||||
|
import com.example.acloc.model.Place;
|
||||||
|
import com.example.acloc.utility.Constants;
|
||||||
|
import com.example.acloc.utility.DialogUtils;
|
||||||
|
import com.example.acloc.utility.Helper;
|
||||||
|
import com.example.acloc.utility.SharedPref;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Callback;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
public class FavoriteAdapter extends RecyclerView.Adapter<FavoriteAdapter.ViewHolder> {
|
||||||
|
|
||||||
|
public static final String TAG = FavoriteAdapter.class.getSimpleName();
|
||||||
|
private final Context context;
|
||||||
|
private List<Favorite> favoriteList;
|
||||||
|
|
||||||
|
public FavoriteAdapter(Context context, List<Favorite> favoriteList) {
|
||||||
|
this.context = context;
|
||||||
|
this.favoriteList = favoriteList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
|
public void updateFavoriteList(List<Favorite> favoriteList) {
|
||||||
|
try {
|
||||||
|
if (favoriteList != null) {
|
||||||
|
this.favoriteList = favoriteList;
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
} catch (Exception exception) {
|
||||||
|
Log.e(TAG, "Error in FavoriteAdapter", exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
|
LayoutInflater inflater = LayoutInflater.from(context);
|
||||||
|
View detailItem = inflater.inflate(R.layout.list_view_favorite, parent, false);
|
||||||
|
return new ViewHolder(detailItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull FavoriteAdapter.ViewHolder holder, int position) {
|
||||||
|
try {
|
||||||
|
if (!favoriteList.isEmpty()) {
|
||||||
|
Favorite favorite = favoriteList.get(position);
|
||||||
|
holder.tvPlaceName.setText(favorite.getPlaceName());
|
||||||
|
holder.tvDescription.setText(favorite.getPlaceDescription());
|
||||||
|
|
||||||
|
// handle favorite on click
|
||||||
|
holder.ivFavorite.setOnClickListener(v -> {
|
||||||
|
removePlaceFromFavorites(SharedPref.getUserUid(context), favorite.getPlaceUuid(), favorite.getUuid());
|
||||||
|
});
|
||||||
|
|
||||||
|
holder.itemView.setOnClickListener(v -> getPlaceByUuid(favorite.getPlaceUuid()));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error in Favorite Adapter", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return favoriteList.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
private final TextView tvPlaceName, tvDescription;
|
||||||
|
private final ImageView ivFavorite;
|
||||||
|
|
||||||
|
public ViewHolder(@NonNull View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
tvPlaceName = itemView.findViewById(R.id.tvPlaceName);
|
||||||
|
tvDescription = itemView.findViewById(R.id.tvDescription);
|
||||||
|
ivFavorite = itemView.findViewById(R.id.ivFavorite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removePlaceFromFavorites(String userUuid, String placeUuid, String favoriteUuid) {
|
||||||
|
DialogUtils.showLoadingDialog(context, context.getString(R.string.Removing_from_favorites));
|
||||||
|
String token = "Bearer " + SharedPref.getAccessToken(context);
|
||||||
|
ApiService apiService = ApiClient.getClient().create(ApiService.class);
|
||||||
|
|
||||||
|
Call<Void> call = apiService.removePlaceFromFavorites(token, userUuid, placeUuid);
|
||||||
|
call.enqueue(new Callback<Void>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<Void> call, Response<Void> response) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
View rootView = ((Activity) context).findViewById(android.R.id.content);
|
||||||
|
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
// Find position of the favorite to be removed
|
||||||
|
int positionToRemove = -1;
|
||||||
|
for (int i = 0; i < favoriteList.size(); i++) {
|
||||||
|
if (favoriteList.get(i).getUuid().equals(favoriteUuid)) {
|
||||||
|
positionToRemove = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the favorite from the list
|
||||||
|
if (positionToRemove != -1) {
|
||||||
|
favoriteList.remove(positionToRemove);
|
||||||
|
notifyItemRemoved(positionToRemove); // Notify the adapter that the item was removed
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.d(TAG, "Favorite removed!");
|
||||||
|
Helper.makeSnackBar(rootView, context.getString(R.string.Favorite_removed));
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "Failed to remove Favorite");
|
||||||
|
Helper.makeSnackBar(rootView, context.getString(R.string.Failed_to_remove_Favorite));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<Void> call, Throwable t) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
View rootView = ((Activity) context).findViewById(android.R.id.content);
|
||||||
|
Log.e(TAG, "Remove Favorite Error: ", t);
|
||||||
|
Helper.makeSnackBar(rootView, context.getString(R.string.Network_error_Try_again));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getPlaceByUuid(String placeUuid) {
|
||||||
|
DialogUtils.showLoadingDialog(context, context.getString(R.string.Please_wait));
|
||||||
|
|
||||||
|
String token = "Bearer " + SharedPref.getAccessToken(context);
|
||||||
|
ApiService apiService = ApiClient.getClient().create(ApiService.class);
|
||||||
|
|
||||||
|
Call<JsonObject> call = apiService.getPlaceFromUuid(token, placeUuid);
|
||||||
|
call.enqueue(new Callback<JsonObject>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
if (response.isSuccessful() && response.body() != null) {
|
||||||
|
JsonObject responseBody = response.body();
|
||||||
|
JsonObject data = responseBody.getAsJsonObject("_data");
|
||||||
|
|
||||||
|
if (data != null && data.has("places")) {
|
||||||
|
Place place = new Place();
|
||||||
|
|
||||||
|
for (JsonElement element : data.getAsJsonArray("places")) {
|
||||||
|
JsonObject placeObject = element.getAsJsonObject();
|
||||||
|
|
||||||
|
place.setUuid(placeObject.get("uuid").getAsString());
|
||||||
|
place.setName(placeObject.get("name").getAsString());
|
||||||
|
place.setDescription(placeObject.get("description").getAsString());
|
||||||
|
place.setAddress(placeObject.get("address").getAsString());
|
||||||
|
place.setLatitude(placeObject.get("latitude").getAsString());
|
||||||
|
place.setLongitude(placeObject.get("longitude").getAsString());
|
||||||
|
}
|
||||||
|
Helper.goTo(context, PlaceDetailActivity.class, Constants.PLACE, place);
|
||||||
|
} else {
|
||||||
|
// Helper.makeSnackBar(rlPlaceDetails, getString(R.string.No_reports_found));
|
||||||
|
Log.e(TAG, "No place found");
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Helper.makeSnackBar(rlPlaceDetails, getString(R.string.Failed_to_load_reports_Try_again_));
|
||||||
|
Log.e(TAG, "Get Reports Error: " + response.code());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<JsonObject> call, Throwable t) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
Log.e(TAG, "Get Reports Failure: ", t);
|
||||||
|
// Helper.makeSnackBar(rlPlaceDetails, context.getString(R.string.Network_error_Try_again));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,169 @@
|
||||||
|
package com.example.acloc.adapter;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.example.acloc.R;
|
||||||
|
import com.example.acloc.activities.AddReportActivity;
|
||||||
|
import com.example.acloc.api.ApiClient;
|
||||||
|
import com.example.acloc.interfaces.ApiService;
|
||||||
|
import com.example.acloc.model.Report;
|
||||||
|
import com.example.acloc.utility.Constants;
|
||||||
|
import com.example.acloc.utility.DialogUtils;
|
||||||
|
import com.example.acloc.utility.Helper;
|
||||||
|
import com.example.acloc.utility.SharedPref;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Callback;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
public class MyReportsAdapter extends RecyclerView.Adapter<MyReportsAdapter.ViewHolder> {
|
||||||
|
public static final String TAG = MyReportsAdapter.class.getSimpleName();
|
||||||
|
private final Context context;
|
||||||
|
private List<Report> reportList;
|
||||||
|
|
||||||
|
public MyReportsAdapter(Context context, List<Report> reportList) {
|
||||||
|
this.context = context;
|
||||||
|
this.reportList = reportList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
|
public void updateReportList(List<Report> reportList) {
|
||||||
|
try {
|
||||||
|
if (reportList != null) {
|
||||||
|
this.reportList = reportList;
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
} catch (Exception exception) {
|
||||||
|
Log.e(TAG, "Error in MyReportsAdapter", exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
|
LayoutInflater inflater = LayoutInflater.from(context);
|
||||||
|
View detailItem = inflater.inflate(R.layout.list_view_my_report, parent, false);
|
||||||
|
return new ViewHolder(detailItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull MyReportsAdapter.ViewHolder holder, int position) {
|
||||||
|
try {
|
||||||
|
if (!reportList.isEmpty()) {
|
||||||
|
Report report = reportList.get(position);
|
||||||
|
holder.tvPlaceName.setText(report.getPlaceName());
|
||||||
|
holder.tvDescription.setText(report.getDescription());
|
||||||
|
if (report.getReportRating() == 1) {
|
||||||
|
holder.tvRating.setText(context.getString(R.string.Rating_BAD));
|
||||||
|
holder.tvRating.setBackgroundTintList(ContextCompat.getColorStateList(context, R.color.red));
|
||||||
|
} else if (report.getReportRating() == 2) {
|
||||||
|
holder.tvRating.setText(context.getString(R.string.Rating_AVERAGE));
|
||||||
|
holder.tvRating.setBackgroundTintList(ContextCompat.getColorStateList(context, R.color.yellow));
|
||||||
|
} else if (report.getReportRating() == 3) {
|
||||||
|
holder.tvRating.setText(context.getString(R.string.Rating_GOOD));
|
||||||
|
holder.tvRating.setBackgroundTintList(ContextCompat.getColorStateList(context, R.color.green));
|
||||||
|
}
|
||||||
|
|
||||||
|
holder.ivDelete.setOnClickListener(v -> {
|
||||||
|
String confirmationText = context.getString(R.string.Delete_report);
|
||||||
|
|
||||||
|
AlertDialog dialog = DialogUtils.confirmationDialog(
|
||||||
|
context,
|
||||||
|
confirmationText,
|
||||||
|
(dialogInterface, i) -> {
|
||||||
|
removeReport(report.getUuid());
|
||||||
|
}
|
||||||
|
);
|
||||||
|
dialog.show();
|
||||||
|
});
|
||||||
|
|
||||||
|
holder.ivEdit.setOnClickListener(v -> {
|
||||||
|
Helper.goTo(context, AddReportActivity.class, Constants.REPORT, report);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error in MyReports Adapter", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return reportList.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
private final TextView tvPlaceName, tvDescription, tvRating;
|
||||||
|
private final ImageView ivEdit, ivDelete;
|
||||||
|
|
||||||
|
public ViewHolder(@NonNull View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
tvPlaceName = itemView.findViewById(R.id.tvPlaceName);
|
||||||
|
tvDescription = itemView.findViewById(R.id.tvDescription);
|
||||||
|
tvRating = itemView.findViewById(R.id.tvRating);
|
||||||
|
ivEdit = itemView.findViewById(R.id.ivEdit);
|
||||||
|
ivDelete = itemView.findViewById(R.id.ivDelete);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeReport(String reportUuid) {
|
||||||
|
DialogUtils.showLoadingDialog(context, context.getString(R.string.Removing_Report));
|
||||||
|
String token = "Bearer " + SharedPref.getAccessToken(context);
|
||||||
|
ApiService apiService = ApiClient.getClient().create(ApiService.class);
|
||||||
|
|
||||||
|
Call<Void> call = apiService.removeReport(token, reportUuid);
|
||||||
|
call.enqueue(new Callback<Void>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<Void> call, Response<Void> response) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
View rootView = ((Activity) context).findViewById(android.R.id.content);
|
||||||
|
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
// Find position of the report to be deleted
|
||||||
|
int positionToRemove = -1;
|
||||||
|
for (int i = 0; i < reportList.size(); i++) {
|
||||||
|
if (reportList.get(i).getUuid().equals(reportUuid)) {
|
||||||
|
positionToRemove = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the report from the list
|
||||||
|
if (positionToRemove != -1) {
|
||||||
|
reportList.remove(positionToRemove);
|
||||||
|
notifyItemRemoved(positionToRemove); // Notify the adapter that the item was removed
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.d(TAG, "Report removed!");
|
||||||
|
Helper.makeSnackBar(rootView, context.getString(R.string.Report_removed));
|
||||||
|
} else {
|
||||||
|
Log.d(TAG, "Failed to remove report");
|
||||||
|
Helper.makeSnackBar(rootView, context.getString(R.string.Failed_to_remove_report));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<Void> call, Throwable t) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
View rootView = ((Activity) context).findViewById(android.R.id.content);
|
||||||
|
Log.e(TAG, "Remove Report Error: ", t);
|
||||||
|
Helper.makeSnackBar(rootView, context.getString(R.string.Network_error_Try_again));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,93 @@
|
||||||
|
package com.example.acloc.adapter;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.example.acloc.R;
|
||||||
|
import com.example.acloc.model.Report;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class PlaceReportsAdapter extends RecyclerView.Adapter<PlaceReportsAdapter.ViewHolder> {
|
||||||
|
public static final String TAG = PlaceReportsAdapter.class.getSimpleName();
|
||||||
|
private final Context context;
|
||||||
|
private List<Report> reportList;
|
||||||
|
|
||||||
|
public PlaceReportsAdapter(Context context, List<Report> reportList) {
|
||||||
|
this.context = context;
|
||||||
|
this.reportList = reportList;
|
||||||
|
}
|
||||||
|
public void clearReports() {
|
||||||
|
reportList.clear();
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
|
public void updateReportsList(List<Report> reportList) {
|
||||||
|
try {
|
||||||
|
if (reportList != null) {
|
||||||
|
this.reportList = reportList;
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
} catch (Exception exception) {
|
||||||
|
Log.e(TAG, "Error in PlaceReportsAdapter", exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
|
LayoutInflater inflater = LayoutInflater.from(context);
|
||||||
|
View detailItem = inflater.inflate(R.layout.list_view_place_reports, parent, false);
|
||||||
|
return new ViewHolder(detailItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("SetTextI18n")
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull PlaceReportsAdapter.ViewHolder holder, int position) {
|
||||||
|
try {
|
||||||
|
if (!reportList.isEmpty()) {
|
||||||
|
Report report = reportList.get(position);
|
||||||
|
holder.tvDescription.setText(report.getDescription());
|
||||||
|
if (report.getReportRating() == 1) {
|
||||||
|
holder.tvRating.setText(context.getString(R.string.Rating_BAD));
|
||||||
|
holder.ivRating.setImageResource(R.drawable.ic_thumbs_down);} else if (report.getReportRating() == 2) {
|
||||||
|
holder.tvRating.setText(context.getString(R.string.Rating_AVERAGE));
|
||||||
|
holder.ivRating.setImageResource(R.drawable.ic_thumb_up_average);
|
||||||
|
} else if (report.getReportRating() == 3) {
|
||||||
|
holder.tvRating.setText(context.getString(R.string.Rating_GOOD));
|
||||||
|
holder.ivRating.setImageResource(R.drawable.ic_thumbs_up);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error in PlaceReportsAdapter", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return reportList.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
private final TextView tvDescription, tvRating;
|
||||||
|
private final ImageView ivRating;
|
||||||
|
|
||||||
|
public ViewHolder(@NonNull View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
tvDescription = itemView.findViewById(R.id.tvDescription);
|
||||||
|
tvRating = itemView.findViewById(R.id.tvRating);
|
||||||
|
ivRating = itemView.findViewById(R.id.ivRating);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,156 @@
|
||||||
|
package com.example.acloc.adapter;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ArrayAdapter;
|
||||||
|
import android.widget.AutoCompleteTextView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import com.example.acloc.R;
|
||||||
|
import com.example.acloc.activities.ManageRolesActivity;
|
||||||
|
import com.example.acloc.api.ApiClient;
|
||||||
|
import com.example.acloc.interfaces.ApiService;
|
||||||
|
import com.example.acloc.model.User;
|
||||||
|
import com.example.acloc.utility.Constants;
|
||||||
|
import com.example.acloc.utility.DialogUtils;
|
||||||
|
import com.example.acloc.utility.Helper;
|
||||||
|
import com.example.acloc.utility.SharedPref;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Callback;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
public class UserAdapter extends RecyclerView.Adapter<UserAdapter.ViewHolder> {
|
||||||
|
public static final String TAG = UserAdapter.class.getSimpleName();
|
||||||
|
private final Context context;
|
||||||
|
private List<User> userList;
|
||||||
|
|
||||||
|
public UserAdapter(Context context, List<User> userList) {
|
||||||
|
this.context = context;
|
||||||
|
this.userList = userList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
|
public void updateUserList(List<User> userList) {
|
||||||
|
try {
|
||||||
|
if (userList != null) {
|
||||||
|
this.userList = userList;
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
} catch (Exception exception) {
|
||||||
|
Log.e(TAG, "Error in UserAdapter", exception);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||||
|
LayoutInflater inflater = LayoutInflater.from(context);
|
||||||
|
View detailItem = inflater.inflate(R.layout.list_view_users, parent, false);
|
||||||
|
return new ViewHolder(detailItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(@NonNull UserAdapter.ViewHolder holder, int position) {
|
||||||
|
try {
|
||||||
|
if (!userList.isEmpty()) {
|
||||||
|
User user = userList.get(position);
|
||||||
|
holder.tvUsername.setText(user.getUsername());
|
||||||
|
|
||||||
|
ArrayAdapter<String> roleAdapter = new ArrayAdapter<>(context, android.R.layout.simple_dropdown_item_1line, Constants.ROLES_OPTIONS);
|
||||||
|
holder.acRole.setAdapter(roleAdapter);
|
||||||
|
holder.acRole.setThreshold(1);
|
||||||
|
|
||||||
|
if (user.getRole() != null) {
|
||||||
|
holder.acRole.setText(user.getRole(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show dropdown on click or focus
|
||||||
|
holder.acRole.setOnClickListener(v -> holder.acRole.showDropDown());
|
||||||
|
holder.acRole.setOnFocusChangeListener((v, hasFocus) -> {
|
||||||
|
if (hasFocus) holder.acRole.showDropDown();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Handle item selection
|
||||||
|
holder.acRole.setOnItemClickListener((parent, view, posInDropdown, id) -> {
|
||||||
|
String selectedRole = parent.getItemAtPosition(posInDropdown).toString();
|
||||||
|
|
||||||
|
AlertDialog dialog = DialogUtils.confirmationDialog(context, context.getString(R.string.Change_Role_to) + " " + selectedRole, (dialogInterface, i) -> {
|
||||||
|
if (selectedRole.equalsIgnoreCase(Constants.ADMIN)) {
|
||||||
|
updateRole(user.getUuid(), SharedPref.getAdminRoleUuid(context), holder.itemView);
|
||||||
|
} else if (selectedRole.equalsIgnoreCase(Constants.VIEWER)) {
|
||||||
|
updateRole(user.getUuid(), SharedPref.getViewerRoleUuid(context), holder.itemView);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
dialog.show();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error in User Adapter", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return userList.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class ViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
private final TextView tvUsername;
|
||||||
|
private AutoCompleteTextView acRole;
|
||||||
|
|
||||||
|
public ViewHolder(@NonNull View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
tvUsername = itemView.findViewById(R.id.tvUsername);
|
||||||
|
acRole = itemView.findViewById(R.id.acRole);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateRole(String uuid, String fkRole, View rootView) {
|
||||||
|
|
||||||
|
DialogUtils.showLoadingDialog(context, context.getString(R.string.Updating_Role));
|
||||||
|
|
||||||
|
JsonObject userBody = new JsonObject();
|
||||||
|
userBody.addProperty("role", fkRole);
|
||||||
|
|
||||||
|
String token = "Bearer " + SharedPref.getAccessToken(context);
|
||||||
|
ApiService apiService = ApiClient.getClient().create(ApiService.class);
|
||||||
|
|
||||||
|
Call<JsonObject> call = apiService.updateRole(token, uuid, userBody);
|
||||||
|
call.enqueue(new Callback<JsonObject>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
Helper.makeSnackBar(rootView, context.getString(R.string.User_Role_update_successfully));
|
||||||
|
// Reload userList after update
|
||||||
|
if (context instanceof ManageRolesActivity) {
|
||||||
|
((ManageRolesActivity) context).getAllUsers();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Helper.makeSnackBar(rootView, context.getString(R.string.Update_failed_Server_error_Try_again));
|
||||||
|
notifyDataSetChanged(); // Reload previous userList
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<JsonObject> call, Throwable t) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
Log.e(TAG, "Update Role Error: ", t);
|
||||||
|
Helper.makeSnackBar(rootView, context.getString(R.string.Network_error_Try_again));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.example.acloc.api;
|
||||||
|
|
||||||
|
import static com.example.acloc.utility.Constants.BASE_URL;
|
||||||
|
|
||||||
|
import retrofit2.Retrofit;
|
||||||
|
import retrofit2.converter.gson.GsonConverterFactory;
|
||||||
|
|
||||||
|
public class ApiClient {
|
||||||
|
private static Retrofit retrofit;
|
||||||
|
|
||||||
|
public static Retrofit getClient() {
|
||||||
|
if (retrofit == null) {
|
||||||
|
retrofit = new Retrofit.Builder()
|
||||||
|
.baseUrl(BASE_URL)
|
||||||
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
return retrofit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,167 @@
|
||||||
|
package com.example.acloc.dialog;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.appcompat.widget.AppCompatButton;
|
||||||
|
|
||||||
|
import com.example.acloc.R;
|
||||||
|
import com.example.acloc.api.ApiClient;
|
||||||
|
import com.example.acloc.interfaces.ApiService;
|
||||||
|
import com.example.acloc.utility.DialogUtils;
|
||||||
|
import com.example.acloc.utility.Helper;
|
||||||
|
import com.example.acloc.utility.SharedPref;
|
||||||
|
import com.google.android.material.textfield.TextInputEditText;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Callback;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
public class AlertChangePasswordDialog implements View.OnClickListener {
|
||||||
|
private static final String TAG = AlertChangePasswordDialog.class.getSimpleName();
|
||||||
|
private View alertView;
|
||||||
|
private TextInputEditText etOldPassword, etNewPassword;
|
||||||
|
private AppCompatButton btnCancel, btnUpdate;
|
||||||
|
private Dialog dialog;
|
||||||
|
private Context context;
|
||||||
|
|
||||||
|
public AlertChangePasswordDialog(Context context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dialog openChangePasswordDialog() {
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
LayoutInflater layoutInflater = ((Activity) context).getLayoutInflater();
|
||||||
|
alertView = layoutInflater.inflate(R.layout.alert_dialog_change_password, null);
|
||||||
|
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(context);
|
||||||
|
if (alertView.getParent() != null) {
|
||||||
|
((ViewGroup) alertView.getParent()).removeView(alertView);
|
||||||
|
}
|
||||||
|
alertBuilder.setView(alertView);
|
||||||
|
|
||||||
|
initUI();
|
||||||
|
setListeners();
|
||||||
|
dialog = alertBuilder.create();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error in AlertChangePasswordDialog: ", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.show();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error in AlertChangePasswordDialog: ", e);
|
||||||
|
}
|
||||||
|
return dialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initUI() {
|
||||||
|
etOldPassword = alertView.findViewById(R.id.etOldPassword);
|
||||||
|
etNewPassword = alertView.findViewById(R.id.etNewPassword);
|
||||||
|
btnCancel = alertView.findViewById(R.id.btnCancel);
|
||||||
|
btnUpdate = alertView.findViewById(R.id.btnUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setListeners() {
|
||||||
|
btnCancel.setOnClickListener(this);
|
||||||
|
btnUpdate.setOnClickListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NonConstantResourceId")
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
int id = v.getId();
|
||||||
|
if (id == R.id.btnCancel) {
|
||||||
|
if (dialog != null && dialog.isShowing()) {
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
} else if (id == R.id.btnUpdate) {
|
||||||
|
onClickBtnUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onClickBtnUpdate() {
|
||||||
|
View[] views = {etOldPassword, etNewPassword};
|
||||||
|
if (Helper.isEmptyFieldValidation(views) && Helper.isPasswordValid(etNewPassword)) {
|
||||||
|
String username = SharedPref.getUserName(context);
|
||||||
|
String oldPassword = Helper.getStringFromInput(etOldPassword);
|
||||||
|
String newPassword = Helper.getStringFromInput(etNewPassword);
|
||||||
|
String uuid = SharedPref.getUserUid(context);
|
||||||
|
|
||||||
|
verifyOldPasswordRetrofit(uuid, username, oldPassword, newPassword);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void verifyOldPasswordRetrofit(String uuid, String username, String oldPassword, String newPassword) {
|
||||||
|
DialogUtils.showLoadingDialog(context, context.getString(R.string.Verifying_old_password));
|
||||||
|
|
||||||
|
JsonObject loginBody = new JsonObject();
|
||||||
|
loginBody.addProperty("username", username);
|
||||||
|
loginBody.addProperty("password", oldPassword);
|
||||||
|
|
||||||
|
ApiService apiService = ApiClient.getClient().create(ApiService.class);
|
||||||
|
Call<JsonObject> call = apiService.verifyOldPassword(loginBody);
|
||||||
|
|
||||||
|
call.enqueue(new Callback<JsonObject>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
|
||||||
|
if (response.isSuccessful() && response.body() != null && response.body().has("user")) {
|
||||||
|
// Proceed to change password
|
||||||
|
changePasswordRetrofit(uuid, newPassword);
|
||||||
|
} else {
|
||||||
|
Helper.makeSnackBar(alertView, context.getString(R.string.Invalid_old_password));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<JsonObject> call, Throwable t) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
Log.e(TAG, "Old password verification failed", t);
|
||||||
|
Helper.makeSnackBar(alertView, context.getString(R.string.Network_error_Try_again));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void changePasswordRetrofit(String uuid, String newPassword) {
|
||||||
|
DialogUtils.showLoadingDialog(context, context.getString(R.string.Changing_password));
|
||||||
|
|
||||||
|
JsonObject body = new JsonObject();
|
||||||
|
body.addProperty("password", newPassword);
|
||||||
|
|
||||||
|
String token = "Bearer " + SharedPref.getAccessToken(context);
|
||||||
|
|
||||||
|
ApiService apiService = ApiClient.getClient().create(ApiService.class);
|
||||||
|
Call<JsonObject> call = apiService.changePassword(token, uuid, body);
|
||||||
|
|
||||||
|
call.enqueue(new Callback<JsonObject>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
|
||||||
|
if (response.isSuccessful() && response.body() != null &&
|
||||||
|
response.body().toString().contains("User modified")) {
|
||||||
|
Helper.makeSnackBar(alertView, context.getString(R.string.Password_updated_successfully));
|
||||||
|
} else {
|
||||||
|
Helper.makeSnackBar(alertView, context.getString(R.string.Password_update_failed));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<JsonObject> call, Throwable t) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
Log.e(TAG, "Password change failed", t);
|
||||||
|
Helper.makeSnackBar(alertView, context.getString(R.string.Network_error_Try_again));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,234 @@
|
||||||
|
package com.example.acloc.dialog;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.appcompat.widget.AppCompatButton;
|
||||||
|
|
||||||
|
import com.example.acloc.MainActivity;
|
||||||
|
import com.example.acloc.R;
|
||||||
|
import com.example.acloc.api.ApiClient;
|
||||||
|
import com.example.acloc.interfaces.ApiService;
|
||||||
|
import com.example.acloc.model.Place;
|
||||||
|
import com.example.acloc.utility.DialogUtils;
|
||||||
|
import com.example.acloc.utility.Helper;
|
||||||
|
import com.example.acloc.utility.SharedPref;
|
||||||
|
import com.google.android.material.textfield.TextInputEditText;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Callback;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
public class AlertViewAddNewPlaceDialog implements View.OnClickListener {
|
||||||
|
private static final String TAG = AlertViewAddNewPlaceDialog.class.getSimpleName();
|
||||||
|
private View alertView;
|
||||||
|
private ImageView ivPlacePhoto;
|
||||||
|
private TextInputEditText etPlaceName, etLatitude, etLongitude, etAddress, etPlaceDescription;
|
||||||
|
private AppCompatButton btnSubmit;
|
||||||
|
private Dialog dialog;
|
||||||
|
private Context context;
|
||||||
|
private double lat, lng;
|
||||||
|
private String placeName, address;
|
||||||
|
|
||||||
|
private Place entity;
|
||||||
|
private String place_uuid;
|
||||||
|
|
||||||
|
|
||||||
|
public AlertViewAddNewPlaceDialog(Context context, double lat, double lng, String placeName, String address, String description, String uuid) {
|
||||||
|
this.context = context;
|
||||||
|
this.lat = lat;
|
||||||
|
this.lng = lng;
|
||||||
|
this.placeName = placeName;
|
||||||
|
this.address = address;
|
||||||
|
this.entity = new Place();
|
||||||
|
this.entity.setDescription(description);
|
||||||
|
this.entity.setName(placeName);
|
||||||
|
this.place_uuid = uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dialog openPlaceDialog() {
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
LayoutInflater layoutInflater = ((Activity) context).getLayoutInflater();
|
||||||
|
alertView = layoutInflater.inflate(R.layout.alert_dialog_add_new_place, null);
|
||||||
|
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(context);
|
||||||
|
if (alertView.getParent() != null) {
|
||||||
|
((ViewGroup) alertView.getParent()).removeView(alertView);
|
||||||
|
}
|
||||||
|
alertBuilder.setView(alertView);
|
||||||
|
|
||||||
|
initUI();
|
||||||
|
setListeners();
|
||||||
|
setDataToText();
|
||||||
|
|
||||||
|
dialog = alertBuilder.create();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error in AlertPlaceDialog: ", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.show();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error in AlertPlaceDialog: ", e);
|
||||||
|
}
|
||||||
|
return dialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initUI() {
|
||||||
|
ivPlacePhoto = alertView.findViewById(R.id.ivPlacePhoto);
|
||||||
|
etPlaceName = alertView.findViewById(R.id.etPlaceName);
|
||||||
|
etLatitude = alertView.findViewById(R.id.etLatitude);
|
||||||
|
etLongitude = alertView.findViewById(R.id.etLongitude);
|
||||||
|
etAddress = alertView.findViewById(R.id.etAddress);
|
||||||
|
etPlaceDescription = alertView.findViewById(R.id.etPlaceDescription);
|
||||||
|
btnSubmit = alertView.findViewById(R.id.btnSubmit);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setListeners() {
|
||||||
|
btnSubmit.setOnClickListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setDataToText() {
|
||||||
|
etPlaceName.setText(String.valueOf(placeName));
|
||||||
|
etLatitude.setText(String.valueOf(lat));
|
||||||
|
etLongitude.setText(String.valueOf(lng));
|
||||||
|
etAddress.setText(String.valueOf(address));
|
||||||
|
etPlaceDescription.setText(entity.getDescription());
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NonConstantResourceId")
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
int id = v.getId();
|
||||||
|
if (id == R.id.btnSubmit) {
|
||||||
|
onClickBtnSubmit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onClickBtnSubmit() {
|
||||||
|
View[] views = {etPlaceName, etLatitude, etLongitude, etAddress, etPlaceDescription};
|
||||||
|
if (Helper.isEmptyFieldValidation(views)) {
|
||||||
|
setInputDataToEntity();
|
||||||
|
|
||||||
|
if (place_uuid != null && !place_uuid.isEmpty()) {
|
||||||
|
// Update existing place
|
||||||
|
updatePlaceRetrofit(place_uuid, entity.getName(), entity.getDescription(),
|
||||||
|
entity.getAddress(), entity.getLatitude(), entity.getLongitude(), entity.getCreatedBy());
|
||||||
|
} else {
|
||||||
|
// Insert new place
|
||||||
|
insertPlaceRetrofit(entity.getName(), entity.getDescription(),
|
||||||
|
entity.getAddress(), entity.getLatitude(), entity.getLongitude(), entity.getCreatedBy());
|
||||||
|
}
|
||||||
|
// Helper.goTo(context, AddReportActivity.class, Constants.PLACE, entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setInputDataToEntity() {
|
||||||
|
entity.setName(Helper.getStringFromInput(etPlaceName));
|
||||||
|
entity.setDescription(Helper.getStringFromInput(etPlaceDescription));
|
||||||
|
entity.setAddress(Helper.getStringFromInput(etAddress));
|
||||||
|
entity.setLatitude(Helper.getStringFromInput(etLatitude));
|
||||||
|
entity.setLongitude(Helper.getStringFromInput(etLongitude));
|
||||||
|
entity.setCreatedBy(SharedPref.getUserUid(context));
|
||||||
|
entity.setUuid(place_uuid);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void insertPlaceRetrofit(String name, String description, String address,
|
||||||
|
String latitude, String longitude, String createdBy) {
|
||||||
|
DialogUtils.showLoadingDialog(context, "Please wait...");
|
||||||
|
|
||||||
|
JsonObject placeBody = new JsonObject();
|
||||||
|
placeBody.addProperty("name", name);
|
||||||
|
placeBody.addProperty("description", description);
|
||||||
|
placeBody.addProperty("address", address);
|
||||||
|
placeBody.addProperty("latitude", latitude);
|
||||||
|
placeBody.addProperty("longitude", longitude);
|
||||||
|
placeBody.addProperty("createdBy", createdBy);
|
||||||
|
|
||||||
|
String token = "Bearer " + SharedPref.getAccessToken(context);
|
||||||
|
ApiService apiService = ApiClient.getClient().create(ApiService.class);
|
||||||
|
|
||||||
|
Call<JsonObject> call = apiService.insertPlace(token, placeBody);
|
||||||
|
call.enqueue(new Callback<JsonObject>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
if (response.isSuccessful() && response.body() != null) {
|
||||||
|
JsonObject responseBody = response.body();
|
||||||
|
JsonObject data = responseBody.getAsJsonObject("_data");
|
||||||
|
if (data != null && data.has("places")) {
|
||||||
|
JsonObject placeObject = data.getAsJsonArray("places").get(0).getAsJsonObject();
|
||||||
|
place_uuid = placeObject.get("uuid").getAsString();
|
||||||
|
Log.d(TAG, "Place UUID: " + place_uuid);
|
||||||
|
Helper.makeSnackBar(alertView, "Place inserted successfully!");
|
||||||
|
alertView.postDelayed(() -> {
|
||||||
|
Helper.goToAndFinish(alertView.getContext(), MainActivity.class);
|
||||||
|
}, 500);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
Helper.makeSnackBar(alertView, "Failed to extract place UUID.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Helper.makeSnackBar(alertView, "Insert failed. Server error.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<JsonObject> call, Throwable t) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
Log.e(TAG, "Insert Place Error: ", t);
|
||||||
|
Helper.makeSnackBar(alertView, context.getString(R.string.Network_error_Try_again));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updatePlaceRetrofit(String uuid, String name, String description, String address,
|
||||||
|
String latitude, String longitude, String createdBy) {
|
||||||
|
|
||||||
|
DialogUtils.showLoadingDialog(context, "Updating place...");
|
||||||
|
|
||||||
|
JsonObject placeBody = new JsonObject();
|
||||||
|
placeBody.addProperty("name", name);
|
||||||
|
placeBody.addProperty("description", description);
|
||||||
|
placeBody.addProperty("address", address);
|
||||||
|
placeBody.addProperty("latitude", latitude);
|
||||||
|
placeBody.addProperty("longitude", longitude);
|
||||||
|
placeBody.addProperty("createdBy", createdBy);
|
||||||
|
|
||||||
|
String token = "Bearer " + SharedPref.getAccessToken(context);
|
||||||
|
ApiService apiService = ApiClient.getClient().create(ApiService.class);
|
||||||
|
|
||||||
|
Call<JsonObject> call = apiService.updatePlace(token, uuid, placeBody);
|
||||||
|
call.enqueue(new Callback<JsonObject>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
if (response.isSuccessful()) {
|
||||||
|
Helper.makeSnackBar(alertView, "Place updated successfully!");
|
||||||
|
alertView.postDelayed(() -> {
|
||||||
|
Helper.goToAndFinish(alertView.getContext(), MainActivity.class);
|
||||||
|
}, 500);
|
||||||
|
} else {
|
||||||
|
Helper.makeSnackBar(alertView, "Update failed. Server error.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<JsonObject> call, Throwable t) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
Log.e(TAG, "Update Place Error: ", t);
|
||||||
|
Helper.makeSnackBar(alertView, context.getString(R.string.Network_error_Try_again));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,179 @@
|
||||||
|
package com.example.acloc.dialog;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
|
import androidx.appcompat.app.AlertDialog;
|
||||||
|
import androidx.appcompat.widget.AppCompatButton;
|
||||||
|
|
||||||
|
import com.example.acloc.R;
|
||||||
|
import com.example.acloc.api.ApiClient;
|
||||||
|
import com.example.acloc.interfaces.ApiService;
|
||||||
|
import com.example.acloc.model.User;
|
||||||
|
import com.example.acloc.utility.DialogUtils;
|
||||||
|
import com.example.acloc.utility.Helper;
|
||||||
|
import com.example.acloc.utility.SharedPref;
|
||||||
|
import com.google.android.material.textfield.TextInputEditText;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Callback;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
public class AlertViewOrUpdateProfileDialog implements View.OnClickListener {
|
||||||
|
private static final String TAG = AlertViewOrUpdateProfileDialog.class.getSimpleName();
|
||||||
|
private View alertView;
|
||||||
|
private TextInputEditText etUsername, etEmail;
|
||||||
|
private AppCompatButton btnCancel, btnUpdate;
|
||||||
|
private Dialog dialog;
|
||||||
|
private Context context;
|
||||||
|
private User entity;
|
||||||
|
|
||||||
|
public AlertViewOrUpdateProfileDialog(Context context) {
|
||||||
|
this.context = context;
|
||||||
|
this.entity = new User();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Dialog openProfileDialog() {
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
LayoutInflater layoutInflater = ((Activity) context).getLayoutInflater();
|
||||||
|
alertView = layoutInflater.inflate(R.layout.alert_dialog_profile, null);
|
||||||
|
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(context);
|
||||||
|
if (alertView.getParent() != null) {
|
||||||
|
((ViewGroup) alertView.getParent()).removeView(alertView);
|
||||||
|
}
|
||||||
|
alertBuilder.setView(alertView);
|
||||||
|
|
||||||
|
initUI();
|
||||||
|
setListeners();
|
||||||
|
dialog = alertBuilder.create();
|
||||||
|
|
||||||
|
//get user profile
|
||||||
|
getProfile();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error in AlertProfileDialog: ", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog.show();
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error in AlertProfileDialog: ", e);
|
||||||
|
}
|
||||||
|
return dialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setDataToText() {
|
||||||
|
try {
|
||||||
|
if (entity != null) {
|
||||||
|
etUsername.setText(entity.getUsername());
|
||||||
|
etEmail.setText(entity.getEmail());
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error in setDataToText: ", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getProfile() {
|
||||||
|
entity.setUsername(SharedPref.getUserName(context));
|
||||||
|
entity.setEmail(SharedPref.getUserEmail(context));
|
||||||
|
setDataToText();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initUI() {
|
||||||
|
etUsername = alertView.findViewById(R.id.etUsername);
|
||||||
|
etEmail = alertView.findViewById(R.id.etEmail);
|
||||||
|
btnCancel = alertView.findViewById(R.id.btnCancel);
|
||||||
|
btnUpdate = alertView.findViewById(R.id.btnUpdate);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setListeners() {
|
||||||
|
btnCancel.setOnClickListener(this);
|
||||||
|
btnUpdate.setOnClickListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NonConstantResourceId")
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
int id = v.getId();
|
||||||
|
if (id == R.id.btnCancel) {
|
||||||
|
if (dialog != null && dialog.isShowing()) {
|
||||||
|
dialog.dismiss();
|
||||||
|
}
|
||||||
|
} else if (id == R.id.btnUpdate) {
|
||||||
|
onClickBtnUpdate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onClickBtnUpdate() {
|
||||||
|
View[] views = {etUsername, etEmail};
|
||||||
|
if (Helper.isEmptyFieldValidation(views) && Helper.isEmailValid(etEmail)) {
|
||||||
|
setInputDataToEntity();
|
||||||
|
String uuid = SharedPref.getUserUid(context);
|
||||||
|
updateUserWithRetrofit(uuid, entity.getUsername(), entity.getEmail());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setInputDataToEntity() {
|
||||||
|
entity.setUsername(Helper.getStringFromInput(etUsername));
|
||||||
|
entity.setEmail(Helper.getStringFromInput(etEmail));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateUserWithRetrofit(String uuid, String username, String email) {
|
||||||
|
DialogUtils.showLoadingDialog(context, context.getString(R.string.Updating));
|
||||||
|
|
||||||
|
JsonObject jsonBody = new JsonObject();
|
||||||
|
jsonBody.addProperty("username", username);
|
||||||
|
jsonBody.addProperty("email", email);
|
||||||
|
|
||||||
|
String accessToken = SharedPref.getAccessToken(context);
|
||||||
|
String bearerToken = "Bearer " + accessToken;
|
||||||
|
|
||||||
|
ApiService apiService = ApiClient.getClient().create(ApiService.class);
|
||||||
|
Call<JsonObject> call = apiService.updateUser(bearerToken, uuid, jsonBody);
|
||||||
|
|
||||||
|
call.enqueue(new Callback<JsonObject>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
|
||||||
|
if (response.isSuccessful() && response.body() != null) {
|
||||||
|
JsonObject responseBody = response.body();
|
||||||
|
if (responseBody.toString().contains("User modified")) {
|
||||||
|
Helper.makeSnackBar(alertView, context.getString(R.string.Profile_Updated_Successfully));
|
||||||
|
SharedPref.setUsername(context, username);
|
||||||
|
SharedPref.setUserEmail(context, email);
|
||||||
|
} else {
|
||||||
|
Helper.makeSnackBar(alertView, context.getString(R.string.Try_again_later));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
if (response.errorBody() != null) {
|
||||||
|
String error = response.errorBody().string();
|
||||||
|
Log.e(TAG, "Update Failed: " + error);
|
||||||
|
Helper.makeSnackBar(alertView, context.getString(R.string.Update_Failed));
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.e(TAG, "Error parsing error response", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<JsonObject> call, Throwable t) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
Log.e(TAG, "Update API failed", t);
|
||||||
|
Helper.makeSnackBar(alertView, context.getString(R.string.Something_went_wrong_Try_again));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,196 @@
|
||||||
|
package com.example.acloc.fragments;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.example.acloc.R;
|
||||||
|
import com.example.acloc.adapter.FavoriteAdapter;
|
||||||
|
import com.example.acloc.api.ApiClient;
|
||||||
|
import com.example.acloc.interfaces.ApiService;
|
||||||
|
import com.example.acloc.model.Favorite;
|
||||||
|
import com.example.acloc.utility.DialogUtils;
|
||||||
|
import com.example.acloc.utility.Helper;
|
||||||
|
import com.example.acloc.utility.SharedPref;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Callback;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
public class FavoriteFragment extends Fragment {
|
||||||
|
public static final String TAG = FavoriteFragment.class.getSimpleName();
|
||||||
|
private View view;
|
||||||
|
private FrameLayout rlFavorite;
|
||||||
|
private RecyclerView rvFavorite;
|
||||||
|
private TextView tvNoData;
|
||||||
|
private Context context;
|
||||||
|
private FavoriteAdapter adapter;
|
||||||
|
private Favorite favoriteEntity;
|
||||||
|
private List<Favorite> favoriteList;
|
||||||
|
|
||||||
|
public FavoriteFragment() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
view = inflater.inflate(R.layout.fragment_favorite, container, false);
|
||||||
|
initUI();
|
||||||
|
initObj();
|
||||||
|
initListener();
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttach(@NonNull Context context) {
|
||||||
|
super.onAttach(context);
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
if (adapter != null) {
|
||||||
|
setDataVisibility(false);
|
||||||
|
favoriteList.clear();
|
||||||
|
}
|
||||||
|
if (context != null) loadData();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setDataVisibility(boolean isDataAvailable) {
|
||||||
|
if (isDataAvailable) {
|
||||||
|
rvFavorite.setVisibility(View.VISIBLE);
|
||||||
|
tvNoData.setVisibility(View.GONE);
|
||||||
|
} else {
|
||||||
|
rvFavorite.setVisibility(View.GONE);
|
||||||
|
tvNoData.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initUI() {
|
||||||
|
rlFavorite = view.findViewById(R.id.rlFavorite);
|
||||||
|
rvFavorite = view.findViewById(R.id.rvFavorite);
|
||||||
|
tvNoData = view.findViewById(R.id.tvNoData);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initObj() {
|
||||||
|
context = getContext();
|
||||||
|
favoriteEntity = new Favorite();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initListener() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadData() {
|
||||||
|
try {
|
||||||
|
if (favoriteList == null) {
|
||||||
|
favoriteList = new ArrayList<>();
|
||||||
|
}
|
||||||
|
String userUuid = SharedPref.getUserUid(context);
|
||||||
|
getFavoriteByUserUuid(userUuid);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error in FavoriteFragment", e);
|
||||||
|
Helper.makeSnackBar(view, getString(R.string.Something_went_wrong_Try_again));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
|
private void setUpRecyclerView() {
|
||||||
|
try {
|
||||||
|
if (adapter != null) {
|
||||||
|
adapter.updateFavoriteList(favoriteList);
|
||||||
|
} else {
|
||||||
|
adapter = new FavoriteAdapter(context, favoriteList);
|
||||||
|
rvFavorite.setAdapter(adapter);
|
||||||
|
rvFavorite.setLayoutManager(Helper.getVerticalManager(context));
|
||||||
|
adapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
setDataVisibility(true);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error in FavoriteFragment", e);
|
||||||
|
Helper.showToast(context, getString(R.string.Something_went_wrong_Try_again));
|
||||||
|
setDataVisibility(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getFavoriteByUserUuid(String userUuid) {
|
||||||
|
DialogUtils.showLoadingDialog(context, context.getString(R.string.Loading_Favorites));
|
||||||
|
|
||||||
|
String token = "Bearer " + SharedPref.getAccessToken(context);
|
||||||
|
ApiService apiService = ApiClient.getClient().create(ApiService.class);
|
||||||
|
|
||||||
|
Call<JsonObject> call = apiService.getUserFavorites(token, userUuid);
|
||||||
|
call.enqueue(new Callback<JsonObject>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
if (response.isSuccessful() && response.body() != null) {
|
||||||
|
JsonObject responseBody = response.body();
|
||||||
|
JsonObject data = responseBody.getAsJsonObject("_data");
|
||||||
|
|
||||||
|
if (data != null && data.has("favorites")) {
|
||||||
|
favoriteList.clear(); // Clear previous list
|
||||||
|
|
||||||
|
for (JsonElement element : data.getAsJsonArray("favorites")) {
|
||||||
|
JsonObject favoriteObject = element.getAsJsonObject();
|
||||||
|
Favorite favorite = new Favorite();
|
||||||
|
|
||||||
|
favorite.setUuid(favoriteObject.get("uuid").getAsString());
|
||||||
|
favorite.setActive(favoriteObject.get("active").getAsString());
|
||||||
|
favorite.setPlaceUuid(favoriteObject.get("place_uuid").getAsString());
|
||||||
|
favorite.setPlaceName(favoriteObject.get("place_name").getAsString());
|
||||||
|
favorite.setPlaceAddress(favoriteObject.get("place_address").getAsString());
|
||||||
|
favorite.setPlaceLat(favoriteObject.get("place_latitude").getAsString());
|
||||||
|
favorite.setPlaceLng(favoriteObject.get("place_longitude").getAsString());
|
||||||
|
favorite.setPlaceDescription(favoriteObject.get("place_description").getAsString());
|
||||||
|
|
||||||
|
favoriteList.add(favorite);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up recyclerview
|
||||||
|
if (!favoriteList.isEmpty()) {
|
||||||
|
setUpRecyclerView();
|
||||||
|
} else {
|
||||||
|
setDataVisibility(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
setDataVisibility(false);
|
||||||
|
Helper.makeSnackBar(rlFavorite, context.getString(R.string.No_Favorite_found));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setDataVisibility(false);
|
||||||
|
Helper.makeSnackBar(rlFavorite, context.getString(R.string.Failed_to_load_favorite_Try_again));
|
||||||
|
Log.e(TAG, "Get favorite Error: " + response.code());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<JsonObject> call, Throwable t) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
Log.e(TAG, "Get favorite Failure: ", t);
|
||||||
|
Helper.makeSnackBar(rlFavorite, context.getString(R.string.Network_error_Try_again));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,381 @@
|
||||||
|
package com.example.acloc.fragments;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.pm.PackageManager;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
|
import android.location.Address;
|
||||||
|
import android.location.Geocoder;
|
||||||
|
import android.location.Location;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.core.content.ContextCompat;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
|
||||||
|
import android.provider.Settings;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.RelativeLayout;
|
||||||
|
|
||||||
|
import com.example.acloc.R;
|
||||||
|
import com.example.acloc.activities.AddNewPlaceActivity;
|
||||||
|
import com.example.acloc.activities.PlaceDetailActivity;
|
||||||
|
import com.example.acloc.interfaces.ApiService;
|
||||||
|
import com.example.acloc.model.Place;
|
||||||
|
import com.example.acloc.utility.Constants;
|
||||||
|
import com.example.acloc.utility.Helper;
|
||||||
|
import com.example.acloc.utility.SharedPref;
|
||||||
|
import com.google.android.gms.location.FusedLocationProviderClient;
|
||||||
|
import com.google.android.gms.location.LocationServices;
|
||||||
|
import com.google.android.gms.maps.CameraUpdateFactory;
|
||||||
|
import com.google.android.gms.maps.GoogleMap;
|
||||||
|
import com.google.android.gms.maps.SupportMapFragment;
|
||||||
|
import com.google.android.gms.maps.model.LatLng;
|
||||||
|
import com.google.android.gms.maps.model.MarkerOptions;
|
||||||
|
import com.google.android.material.textfield.TextInputEditText;
|
||||||
|
|
||||||
|
import org.json.JSONArray;
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import okhttp3.ResponseBody;
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Callback;
|
||||||
|
import retrofit2.Response;
|
||||||
|
import retrofit2.Retrofit;
|
||||||
|
import retrofit2.converter.gson.GsonConverterFactory;
|
||||||
|
|
||||||
|
|
||||||
|
public class MapFragment extends Fragment {
|
||||||
|
public static final String TAG = MapFragment.class.getSimpleName();
|
||||||
|
private static final int LOCATION_PERMISSION_REQUEST_CODE = 1001;
|
||||||
|
|
||||||
|
private RelativeLayout rlMap;
|
||||||
|
private View view;
|
||||||
|
private TextInputEditText etSearchLocation;
|
||||||
|
private GoogleMap googleMap;
|
||||||
|
private FusedLocationProviderClient fusedLocationClient;
|
||||||
|
private Geocoder geocoder;
|
||||||
|
private Dialog dialog;
|
||||||
|
private Context context;
|
||||||
|
|
||||||
|
private List<Place> placeList = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
|
public MapFragment() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
fetchAndShowAllPlaces();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
view = inflater.inflate(R.layout.fragment_map, container, false);
|
||||||
|
initUI();
|
||||||
|
initListener();
|
||||||
|
initObj();
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initUI() {
|
||||||
|
rlMap = view.findViewById(R.id.rlMap);
|
||||||
|
etSearchLocation = view.findViewById(R.id.etSearchLocation);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initObj() {
|
||||||
|
context = getContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("ClickableViewAccessibility")
|
||||||
|
private void initListener() {
|
||||||
|
SupportMapFragment mapFragment = (SupportMapFragment) getChildFragmentManager()
|
||||||
|
.findFragmentById(R.id.mapFrame);
|
||||||
|
|
||||||
|
if (mapFragment != null) {
|
||||||
|
mapFragment.getMapAsync(map -> {
|
||||||
|
googleMap = map;
|
||||||
|
initMap();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Handle search icon click
|
||||||
|
etSearchLocation.setOnTouchListener((v, event) -> {
|
||||||
|
if (event.getAction() == MotionEvent.ACTION_UP) {
|
||||||
|
Drawable drawableEnd = etSearchLocation.getCompoundDrawables()[2]; // Right drawable
|
||||||
|
|
||||||
|
if (drawableEnd != null) {
|
||||||
|
int drawableWidth = drawableEnd.getBounds().width();
|
||||||
|
int touchAreaStart = etSearchLocation.getWidth() - drawableWidth - etSearchLocation.getPaddingEnd();
|
||||||
|
|
||||||
|
if (event.getX() >= touchAreaStart) {
|
||||||
|
v.performClick(); // important for accessibility
|
||||||
|
String address = Helper.getStringFromInput(etSearchLocation);
|
||||||
|
if (!address.isEmpty()) {
|
||||||
|
searchLocationByAddress(address);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
// trigger on Enter/Done key
|
||||||
|
etSearchLocation.setOnEditorActionListener((v, actionId, event) -> {
|
||||||
|
String address = Helper.getStringFromInput(etSearchLocation);
|
||||||
|
if (!address.isEmpty()) {
|
||||||
|
searchLocationByAddress(address);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initMap() {
|
||||||
|
fetchAndShowAllPlaces();
|
||||||
|
|
||||||
|
fusedLocationClient = LocationServices.getFusedLocationProviderClient(requireActivity());
|
||||||
|
geocoder = new Geocoder(requireContext(), Locale.getDefault());
|
||||||
|
|
||||||
|
if (ContextCompat.checkSelfPermission(requireContext(), android.Manifest.permission.ACCESS_FINE_LOCATION)
|
||||||
|
== PackageManager.PERMISSION_GRANTED) {
|
||||||
|
|
||||||
|
googleMap.setMyLocationEnabled(true);
|
||||||
|
|
||||||
|
fusedLocationClient.getLastLocation().addOnSuccessListener(location -> {
|
||||||
|
if (location != null) {
|
||||||
|
LatLng currentLatLng = new LatLng(location.getLatitude(), location.getLongitude());
|
||||||
|
googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(currentLatLng, 14f));
|
||||||
|
showNearbyPlaces(currentLatLng);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
googleMap.setOnMapClickListener(latLng -> {
|
||||||
|
Place existingPlace = getPlaceIfExists(latLng);
|
||||||
|
if (existingPlace != null) {
|
||||||
|
Helper.goTo(getContext(), PlaceDetailActivity.class, Constants.PLACE, existingPlace); //Navigate to PlaceDetailActivity if the place already exists
|
||||||
|
return;
|
||||||
|
//
|
||||||
|
// dialog = new AlertViewAddNewPlaceDialog(requireContext(),
|
||||||
|
// Double.parseDouble(existingPlace.getLatitude()),
|
||||||
|
// Double.parseDouble(existingPlace.getLongitude()),
|
||||||
|
// existingPlace.getName(),
|
||||||
|
// existingPlace.getAddress(),
|
||||||
|
// existingPlace.getDescription(),
|
||||||
|
// existingPlace.getUuid())
|
||||||
|
// .openPlaceDialog();
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
List<Address> addressList = geocoder.getFromLocation(latLng.latitude, latLng.longitude, 1);
|
||||||
|
if (addressList != null && !addressList.isEmpty()) {
|
||||||
|
Address address = addressList.get(0);
|
||||||
|
String addressLine = address.getAddressLine(0);
|
||||||
|
String placeName = address.getFeatureName();
|
||||||
|
|
||||||
|
// dialog = new AlertViewAddNewPlaceDialog(requireContext(),
|
||||||
|
// latLng.latitude,
|
||||||
|
// latLng.longitude,
|
||||||
|
// placeName,
|
||||||
|
// addressLine,
|
||||||
|
// "", // Empty description
|
||||||
|
// null // UUID
|
||||||
|
// ).openPlaceDialog();
|
||||||
|
|
||||||
|
Place placeEntity = new Place();
|
||||||
|
placeEntity.setLatitude(String.valueOf(latLng.latitude));
|
||||||
|
placeEntity.setLongitude(String.valueOf(latLng.longitude));
|
||||||
|
placeEntity.setName(placeName);
|
||||||
|
placeEntity.setAddress(addressLine);
|
||||||
|
placeEntity.setDescription(""); // Empty description
|
||||||
|
placeEntity.setUuid(null); // No UUID for new place
|
||||||
|
Helper.goTo(getContext(), AddNewPlaceActivity.class, Constants.PLACE, placeEntity);
|
||||||
|
} else {
|
||||||
|
Place placeEntity = new Place();
|
||||||
|
placeEntity.setLatitude(String.valueOf(latLng.latitude));
|
||||||
|
placeEntity.setLongitude(String.valueOf(latLng.longitude));
|
||||||
|
placeEntity.setName("");
|
||||||
|
placeEntity.setAddress("Address not found");
|
||||||
|
placeEntity.setDescription(""); // Empty description
|
||||||
|
placeEntity.setUuid(null); // No UUID for a new place
|
||||||
|
Helper.goTo(getContext(), AddNewPlaceActivity.class, Constants.PLACE, placeEntity);
|
||||||
|
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
googleMap.setOnMarkerClickListener(marker -> {
|
||||||
|
marker.hideInfoWindow();
|
||||||
|
|
||||||
|
LatLng latLng = marker.getPosition();
|
||||||
|
Place existingPlace = getPlaceIfExists(latLng);
|
||||||
|
|
||||||
|
if (existingPlace != null) {
|
||||||
|
Helper.goTo(getContext(), PlaceDetailActivity.class, Constants.PLACE, existingPlace);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
requestPermissions(new String[]{android.Manifest.permission.ACCESS_FINE_LOCATION}, LOCATION_PERMISSION_REQUEST_CODE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Place getPlaceIfExists(LatLng clickedLatLng) {
|
||||||
|
final float[] result = new float[1];
|
||||||
|
for (Place place : placeList) {
|
||||||
|
double lat = Double.parseDouble(place.getLatitude());
|
||||||
|
double lng = Double.parseDouble(place.getLongitude());
|
||||||
|
|
||||||
|
Location.distanceBetween(
|
||||||
|
clickedLatLng.latitude, clickedLatLng.longitude,
|
||||||
|
lat, lng,
|
||||||
|
result);
|
||||||
|
|
||||||
|
if (result[0] < 10) { // less than 10 meters
|
||||||
|
return place;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showNearbyPlaces(LatLng latLng) {
|
||||||
|
googleMap.clear();
|
||||||
|
// googleMap.addMarker(new MarkerOptions()
|
||||||
|
// .position(latLng)
|
||||||
|
// .title("You are here"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void searchLocationByAddress(String address) {
|
||||||
|
try {
|
||||||
|
List<Address> addresses = geocoder.getFromLocationName(address, 1);
|
||||||
|
if (addresses != null && !addresses.isEmpty()) {
|
||||||
|
Address location = addresses.get(0);
|
||||||
|
LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
|
||||||
|
googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(latLng, 14f));
|
||||||
|
showNearbyPlaces(latLng);
|
||||||
|
} else {
|
||||||
|
Helper.makeSnackBar(rlMap, "Location not found");
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
Log.d(TAG, getString(R.string.Something_went_wrong_Try_again));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
|
||||||
|
@NonNull int[] grantResults) {
|
||||||
|
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
|
||||||
|
|
||||||
|
if (requestCode == LOCATION_PERMISSION_REQUEST_CODE
|
||||||
|
&& grantResults.length > 0
|
||||||
|
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
|
||||||
|
initMap();
|
||||||
|
} else {
|
||||||
|
boolean showRationale = shouldShowRequestPermissionRationale(android.Manifest.permission.ACCESS_FINE_LOCATION);
|
||||||
|
if (!showRationale) {
|
||||||
|
showPermissionRequiredDialog();
|
||||||
|
} else {
|
||||||
|
Helper.showToast(context, getString(R.string.Location_permission_is_required));
|
||||||
|
} }
|
||||||
|
}
|
||||||
|
private void showPermissionRequiredDialog() {
|
||||||
|
new AlertDialog.Builder(requireContext())
|
||||||
|
.setTitle(getString(R.string.Location_Permission_Required))
|
||||||
|
.setMessage(getString(R.string.Location_permission_rationale))
|
||||||
|
.setCancelable(false)
|
||||||
|
.setPositiveButton(getString(R.string.Go_to_Settings), (dialog, which) -> {
|
||||||
|
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
|
||||||
|
Uri uri = Uri.fromParts("package", requireContext().getPackageName(), null);
|
||||||
|
intent.setData(uri);
|
||||||
|
startActivity(intent);
|
||||||
|
})
|
||||||
|
.setNegativeButton(getString(R.string.Exit_App), (dialog, which) -> requireActivity().finish())
|
||||||
|
.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void fetchAndShowAllPlaces() {
|
||||||
|
String token = "Bearer " + SharedPref.getAccessToken(context); // get saved token
|
||||||
|
|
||||||
|
Retrofit retrofit = new Retrofit.Builder()
|
||||||
|
.baseUrl("https://locationapi-m13l.onrender.com/")
|
||||||
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
|
.build();
|
||||||
|
|
||||||
|
ApiService apiService = retrofit.create(ApiService.class);
|
||||||
|
Call<ResponseBody> call = apiService.getAllPlaces(token);
|
||||||
|
|
||||||
|
call.enqueue(new Callback<ResponseBody>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
|
||||||
|
if (response.isSuccessful() && response.body() != null) {
|
||||||
|
try {
|
||||||
|
JSONObject jsonObject = new JSONObject(response.body().string());
|
||||||
|
JSONArray placesArray = jsonObject.getJSONObject("_data").getJSONArray("places");
|
||||||
|
|
||||||
|
for (int i = 0; i < placesArray.length(); i++) {
|
||||||
|
JSONObject placeObj = placesArray.getJSONObject(i);
|
||||||
|
String name = placeObj.getString("name");
|
||||||
|
String address = placeObj.getString("address");
|
||||||
|
String description = placeObj.optString("description", "");
|
||||||
|
String createdBy = placeObj.optString("createdBy", "");
|
||||||
|
String uuid = placeObj.optString("uuid", "");
|
||||||
|
double lat = placeObj.getDouble("latitude");
|
||||||
|
double lng = placeObj.getDouble("longitude");
|
||||||
|
|
||||||
|
LatLng latLng = new LatLng(lat, lng);
|
||||||
|
googleMap.addMarker(new MarkerOptions()
|
||||||
|
.position(latLng)
|
||||||
|
.title(name)
|
||||||
|
.snippet(address));
|
||||||
|
|
||||||
|
// Add to memory list
|
||||||
|
Place place = new Place();
|
||||||
|
place.setName(name);
|
||||||
|
place.setAddress(address);
|
||||||
|
place.setLatitude(String.valueOf(lat));
|
||||||
|
place.setLongitude(String.valueOf(lng));
|
||||||
|
place.setDescription(description);
|
||||||
|
place.setCreatedBy(createdBy);
|
||||||
|
place.setUuid(uuid);
|
||||||
|
|
||||||
|
placeList.add(place);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Helper.makeSnackBar(rlMap, getString(R.string.Failed_to_load_places));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<ResponseBody> call, Throwable t) {
|
||||||
|
t.printStackTrace();
|
||||||
|
Helper.makeSnackBar(rlMap, getString(R.string.Network_error_Try_again));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,209 @@
|
||||||
|
package com.example.acloc.fragments;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.FrameLayout;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.example.acloc.MainActivity;
|
||||||
|
import com.example.acloc.R;
|
||||||
|
import com.example.acloc.adapter.MyReportsAdapter;
|
||||||
|
import com.example.acloc.api.ApiClient;
|
||||||
|
import com.example.acloc.interfaces.ApiService;
|
||||||
|
import com.example.acloc.model.Report;
|
||||||
|
import com.example.acloc.utility.DialogUtils;
|
||||||
|
import com.example.acloc.utility.Helper;
|
||||||
|
import com.example.acloc.utility.SharedPref;
|
||||||
|
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
|
||||||
|
import com.google.gson.JsonElement;
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Callback;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
|
public class MyReportsFragment extends Fragment implements View.OnClickListener {
|
||||||
|
public static final String TAG = MyReportsFragment.class.getSimpleName();
|
||||||
|
private View view;
|
||||||
|
private FrameLayout rlMyReport;
|
||||||
|
private RecyclerView rvReport;
|
||||||
|
private TextView tvNoData;
|
||||||
|
private ExtendedFloatingActionButton extendedFbReport;
|
||||||
|
private Context context;
|
||||||
|
private MyReportsAdapter adapter;
|
||||||
|
private Report reportEntity;
|
||||||
|
private List<Report> reportList;
|
||||||
|
|
||||||
|
public MyReportsFragment() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||||
|
Bundle savedInstanceState) {
|
||||||
|
view = inflater.inflate(R.layout.fragment_my_reports, container, false);
|
||||||
|
initUI();
|
||||||
|
initObj();
|
||||||
|
initListener();
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAttach(@NonNull Context context) {
|
||||||
|
super.onAttach(context);
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onResume() {
|
||||||
|
super.onResume();
|
||||||
|
if (adapter != null) {
|
||||||
|
setDataVisibility(false);
|
||||||
|
reportList.clear();
|
||||||
|
}
|
||||||
|
if (context != null) loadData();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setDataVisibility(boolean isDataAvailable) {
|
||||||
|
if (isDataAvailable) {
|
||||||
|
rvReport.setVisibility(View.VISIBLE);
|
||||||
|
tvNoData.setVisibility(View.GONE);
|
||||||
|
} else {
|
||||||
|
rvReport.setVisibility(View.GONE);
|
||||||
|
tvNoData.setVisibility(View.VISIBLE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initUI() {
|
||||||
|
rlMyReport = view.findViewById(R.id.rlMyReport);
|
||||||
|
rvReport = view.findViewById(R.id.rvReport);
|
||||||
|
tvNoData = view.findViewById(R.id.tvNoData);
|
||||||
|
extendedFbReport = view.findViewById(R.id.extendedFbReport);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initObj() {
|
||||||
|
context = getContext();
|
||||||
|
reportEntity = new Report();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initListener() {
|
||||||
|
extendedFbReport.setOnClickListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void loadData() {
|
||||||
|
try {
|
||||||
|
if (reportList == null) {
|
||||||
|
reportList = new ArrayList<>();
|
||||||
|
}
|
||||||
|
String userUuid = SharedPref.getUserUid(context);
|
||||||
|
getReportsByUserUuid(userUuid);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error in MyReportsFragment", e);
|
||||||
|
Helper.makeSnackBar(view, getString(R.string.Something_went_wrong_Try_again));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressLint("NotifyDataSetChanged")
|
||||||
|
private void setUpRecyclerView() {
|
||||||
|
try {
|
||||||
|
if (adapter != null) {
|
||||||
|
adapter.updateReportList(reportList);
|
||||||
|
} else {
|
||||||
|
adapter = new MyReportsAdapter(context, reportList);
|
||||||
|
rvReport.setAdapter(adapter);
|
||||||
|
rvReport.setLayoutManager(Helper.getVerticalManager(context));
|
||||||
|
adapter.notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
setDataVisibility(true);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error in MyReportFragment", e);
|
||||||
|
Helper.makeSnackBar(rlMyReport, getString(R.string.Something_went_wrong_Try_again));
|
||||||
|
setDataVisibility(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
int id = v.getId();
|
||||||
|
if (id == R.id.extendedFbReport) {
|
||||||
|
onClickExtendedFbReport();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Open Map Fragment to add new place report
|
||||||
|
private void onClickExtendedFbReport() {
|
||||||
|
((MainActivity) requireActivity())
|
||||||
|
.openFragmentFromChild(new MapFragment(), getString(R.string.Map), R.id.menu_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getReportsByUserUuid(String userUuid) {
|
||||||
|
DialogUtils.showLoadingDialog(context, getString(R.string.Loading_reports));
|
||||||
|
|
||||||
|
String token = "Bearer " + SharedPref.getAccessToken(context);
|
||||||
|
ApiService apiService = ApiClient.getClient().create(ApiService.class);
|
||||||
|
|
||||||
|
Call<JsonObject> call = apiService.getUserReports(token, userUuid);
|
||||||
|
call.enqueue(new Callback<JsonObject>() {
|
||||||
|
@Override
|
||||||
|
public void onResponse(Call<JsonObject> call, Response<JsonObject> response) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
if (response.isSuccessful() && response.body() != null) {
|
||||||
|
JsonObject responseBody = response.body();
|
||||||
|
JsonObject data = responseBody.getAsJsonObject("_data");
|
||||||
|
|
||||||
|
if (data != null && data.has("reports")) {
|
||||||
|
reportList.clear(); // Clear previous list
|
||||||
|
|
||||||
|
for (JsonElement element : data.getAsJsonArray("reports")) {
|
||||||
|
JsonObject reportObject = element.getAsJsonObject();
|
||||||
|
Report report = new Report();
|
||||||
|
|
||||||
|
report.setUuid(reportObject.get("uuid").getAsString());
|
||||||
|
report.setReportRating(reportObject.get("rating").getAsInt());
|
||||||
|
report.setDescription(reportObject.get("description").getAsString());
|
||||||
|
report.setPlaceName(reportObject.get("place_name").getAsString());
|
||||||
|
report.setPlaceUuid(reportObject.get("place_uuid").getAsString());
|
||||||
|
|
||||||
|
reportList.add(report);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up recyclerview
|
||||||
|
if (!reportList.isEmpty()) {
|
||||||
|
setUpRecyclerView();
|
||||||
|
} else {
|
||||||
|
setDataVisibility(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
setDataVisibility(false);
|
||||||
|
Helper.makeSnackBar(rlMyReport, getString(R.string.No_reports_found));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
setDataVisibility(false);
|
||||||
|
Helper.makeSnackBar(rlMyReport, getString(R.string.Failed_to_load_reports_Try_again_));
|
||||||
|
Log.e(TAG, "Get Reports Error: " + response.code());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFailure(Call<JsonObject> call, Throwable t) {
|
||||||
|
DialogUtils.dismissDialog();
|
||||||
|
Log.e(TAG, "Get Reports Failure: ", t);
|
||||||
|
Helper.makeSnackBar(rlMyReport, context.getString(R.string.Network_error_Try_again));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,139 @@
|
||||||
|
package com.example.acloc.interfaces;
|
||||||
|
|
||||||
|
import com.google.gson.JsonObject;
|
||||||
|
|
||||||
|
import okhttp3.ResponseBody;
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.http.Body;
|
||||||
|
import retrofit2.http.DELETE;
|
||||||
|
import retrofit2.http.GET;
|
||||||
|
import retrofit2.http.Header;
|
||||||
|
import retrofit2.http.POST;
|
||||||
|
import retrofit2.http.PUT;
|
||||||
|
import retrofit2.http.Path;
|
||||||
|
|
||||||
|
public interface ApiService {
|
||||||
|
@POST("signin")
|
||||||
|
Call<JsonObject> registerUser(@Body JsonObject userData);
|
||||||
|
|
||||||
|
@POST("login")
|
||||||
|
Call<JsonObject> loginUser(@Body JsonObject body);
|
||||||
|
|
||||||
|
@PUT("users/{uuid}")
|
||||||
|
Call<JsonObject> updateUser(
|
||||||
|
@Header("Authorization") String bearerToken,
|
||||||
|
@Path("uuid") String uuid,
|
||||||
|
@Body JsonObject body
|
||||||
|
);
|
||||||
|
|
||||||
|
@POST("login")
|
||||||
|
Call<JsonObject> verifyOldPassword(@Body JsonObject loginBody);
|
||||||
|
|
||||||
|
@PUT("users/{uuid}")
|
||||||
|
Call<JsonObject> changePassword(
|
||||||
|
@Header("Authorization") String token,
|
||||||
|
@Path("uuid") String uuid,
|
||||||
|
@Body JsonObject body
|
||||||
|
);
|
||||||
|
|
||||||
|
@POST("places")
|
||||||
|
Call<JsonObject> insertPlace(
|
||||||
|
@Header("Authorization") String token,
|
||||||
|
@Body JsonObject body
|
||||||
|
);
|
||||||
|
|
||||||
|
@POST("report_types")
|
||||||
|
Call<JsonObject> insertReportType(
|
||||||
|
@Header("Authorization") String token,
|
||||||
|
@Body JsonObject body
|
||||||
|
);
|
||||||
|
|
||||||
|
@PUT("places/{uuid}")
|
||||||
|
Call<JsonObject> updatePlace(@Header("Authorization") String token,
|
||||||
|
@Path("uuid") String uuid,
|
||||||
|
@Body JsonObject placeData);
|
||||||
|
|
||||||
|
|
||||||
|
@GET("places")
|
||||||
|
Call<ResponseBody> getAllPlaces(@Header("Authorization") String token);
|
||||||
|
|
||||||
|
@POST("users/{user_uuid}/places")
|
||||||
|
Call<JsonObject> addPlaceToFavorites(
|
||||||
|
@Header("Authorization") String token,
|
||||||
|
@Path("user_uuid") String userUuid,
|
||||||
|
@Body JsonObject placeBody
|
||||||
|
);
|
||||||
|
|
||||||
|
@DELETE("users/{user_uuid}/places/{place_uuid}")
|
||||||
|
Call<Void> removePlaceFromFavorites(
|
||||||
|
@Header("Authorization") String token,
|
||||||
|
@Path("user_uuid") String userUuid,
|
||||||
|
@Path("place_uuid") String placeUuid
|
||||||
|
);
|
||||||
|
|
||||||
|
@GET("users/{user_uuid}/places")
|
||||||
|
Call<JsonObject> getFavoritePlaces(
|
||||||
|
@Header("Authorization") String token,
|
||||||
|
@Path("user_uuid") String userUuid
|
||||||
|
);
|
||||||
|
|
||||||
|
@PUT("users/{user_uuid}/places")
|
||||||
|
Call<JsonObject> restorePlaceToFavorites(
|
||||||
|
@Header("Authorization") String authToken,
|
||||||
|
@Path("user_uuid") String userUuid,
|
||||||
|
@Body JsonObject body
|
||||||
|
);
|
||||||
|
|
||||||
|
@POST("reports")
|
||||||
|
Call<JsonObject> insertReport(
|
||||||
|
@Header("Authorization") String token,
|
||||||
|
@Body JsonObject reportBody
|
||||||
|
);
|
||||||
|
|
||||||
|
@GET("users/{user_uuid}/reports")
|
||||||
|
Call<JsonObject> getUserReports(
|
||||||
|
@Header("Authorization") String token,
|
||||||
|
@Path("user_uuid") String userUuid
|
||||||
|
);
|
||||||
|
|
||||||
|
@DELETE("reports/{report_uuid}")
|
||||||
|
Call<Void> removeReport(
|
||||||
|
@Header("Authorization") String token,
|
||||||
|
@Path("report_uuid") String reportUuid
|
||||||
|
);
|
||||||
|
|
||||||
|
@PUT("/reports/{uuid}")
|
||||||
|
Call<JsonObject> updateReport(@Header("Authorization") String token,
|
||||||
|
@Path("uuid") String uuid,
|
||||||
|
@Body JsonObject placeData);
|
||||||
|
|
||||||
|
@GET("places/{place_uuid}/reports")
|
||||||
|
Call<JsonObject> getPlaceReports(
|
||||||
|
@Header("Authorization") String token,
|
||||||
|
@Path("place_uuid") String placeUuid
|
||||||
|
);
|
||||||
|
|
||||||
|
@GET("users/{user_uuid}/places")
|
||||||
|
Call<JsonObject> getUserFavorites(
|
||||||
|
@Header("Authorization") String token,
|
||||||
|
@Path("user_uuid") String userUuid
|
||||||
|
);
|
||||||
|
|
||||||
|
@GET("roles")
|
||||||
|
Call<JsonObject> getRoles(@Header("Authorization") String token);
|
||||||
|
|
||||||
|
@GET("users")
|
||||||
|
Call<JsonObject> getAllUsers(@Header("Authorization") String token);
|
||||||
|
|
||||||
|
|
||||||
|
@PUT("users/{uuid}")
|
||||||
|
Call<JsonObject> updateRole(@Header("Authorization") String token,
|
||||||
|
@Path("uuid") String uuid,
|
||||||
|
@Body JsonObject userData);
|
||||||
|
|
||||||
|
@GET("places/{uuid}")
|
||||||
|
Call<JsonObject> getPlaceFromUuid(
|
||||||
|
@Header("Authorization") String token,
|
||||||
|
@Path("uuid") String uuid
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
package com.example.acloc.model;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class Favorite implements Serializable {
|
||||||
|
String uuid, active, placeUuid, placeName, placeAddress, placeLat, placeLng, placeDescription, userUsername;
|
||||||
|
|
||||||
|
public String getUuid() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUuid(String uuid) {
|
||||||
|
this.uuid = uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getActive() {
|
||||||
|
return active;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setActive(String active) {
|
||||||
|
this.active = active;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPlaceUuid() {
|
||||||
|
return placeUuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPlaceUuid(String placeUuid) {
|
||||||
|
this.placeUuid = placeUuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPlaceName() {
|
||||||
|
return placeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPlaceName(String placeName) {
|
||||||
|
this.placeName = placeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPlaceAddress() {
|
||||||
|
return placeAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPlaceAddress(String placeAddress) {
|
||||||
|
this.placeAddress = placeAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPlaceLat() {
|
||||||
|
return placeLat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPlaceLat(String placeLat) {
|
||||||
|
this.placeLat = placeLat;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPlaceLng() {
|
||||||
|
return placeLng;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPlaceLng(String placeLng) {
|
||||||
|
this.placeLng = placeLng;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPlaceDescription() {
|
||||||
|
return placeDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPlaceDescription(String placeDescription) {
|
||||||
|
this.placeDescription = placeDescription;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUserUsername() {
|
||||||
|
return userUsername;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUserUsername(String userUsername) {
|
||||||
|
this.userUsername = userUsername;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,63 @@
|
||||||
|
package com.example.acloc.model;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class Place implements Serializable {
|
||||||
|
String uuid, name, description, address, latitude, longitude, createdBy;
|
||||||
|
|
||||||
|
public String getUuid() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUuid(String uuid) {
|
||||||
|
this.uuid = uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAddress() {
|
||||||
|
return address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAddress(String address) {
|
||||||
|
this.address = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLatitude() {
|
||||||
|
return latitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLatitude(String latitude) {
|
||||||
|
this.latitude = latitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLongitude() {
|
||||||
|
return longitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLongitude(String longitude) {
|
||||||
|
this.longitude = longitude;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCreatedBy() {
|
||||||
|
return createdBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreatedBy(String createdBy) {
|
||||||
|
this.createdBy = createdBy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,81 @@
|
||||||
|
package com.example.acloc.model;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class Report implements Serializable {
|
||||||
|
String uuid, fkUser, fkPlace, fkReportType, description, createdBy;
|
||||||
|
String placeName, placeUuid;
|
||||||
|
int reportRating;
|
||||||
|
|
||||||
|
public String getUuid() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUuid(String uuid) {
|
||||||
|
this.uuid = uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFkUser() {
|
||||||
|
return fkUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFkUser(String fkUser) {
|
||||||
|
this.fkUser = fkUser;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFkPlace() {
|
||||||
|
return fkPlace;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFkPlace(String fkPlace) {
|
||||||
|
this.fkPlace = fkPlace;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFkReportType() {
|
||||||
|
return fkReportType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFkReportType(String fkReportType) {
|
||||||
|
this.fkReportType = fkReportType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCreatedBy() {
|
||||||
|
return createdBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreatedBy(String createdBy) {
|
||||||
|
this.createdBy = createdBy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getReportRating() {
|
||||||
|
return reportRating;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setReportRating(int reportRating) {
|
||||||
|
this.reportRating = reportRating;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPlaceName() {
|
||||||
|
return placeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPlaceName(String placeName) {
|
||||||
|
this.placeName = placeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPlaceUuid() {
|
||||||
|
return placeUuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPlaceUuid(String placeUuid) {
|
||||||
|
this.placeUuid = placeUuid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
package com.example.acloc.model;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class User implements Serializable {
|
||||||
|
private String username, email, password;
|
||||||
|
private String role, uuid, fkRole ;
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEmail() {
|
||||||
|
return email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEmail(String email) {
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRole() {
|
||||||
|
return role;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRole(String role) {
|
||||||
|
this.role = role;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUuid() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUuid(String uuid) {
|
||||||
|
this.uuid = uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFkRole() {
|
||||||
|
return fkRole;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFkRole(String fkRole) {
|
||||||
|
this.fkRole = fkRole;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.example.acloc.utility;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class Constants {
|
||||||
|
public static final String SHARED_PREF = "ACLOC";
|
||||||
|
public static final String ADMIN = "admin";
|
||||||
|
public static final String VIEWER = "viewer";
|
||||||
|
public static final String PLACE = "Place";
|
||||||
|
public static final String REPORT = "Report";
|
||||||
|
public static final String SOMETHING_WENT_WRONG = "Something went wrong";
|
||||||
|
|
||||||
|
public static final int GOOD_RATING = 3;
|
||||||
|
public static final int AVERAGE_RATING = 2;
|
||||||
|
public static final int BAD_RATING = 1;
|
||||||
|
|
||||||
|
public static final List<String> ROLES_OPTIONS = Arrays.asList("admin", "viewer");
|
||||||
|
public static final String BASE_URL = "https://locationapi-m13l.onrender.com/";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,85 @@
|
||||||
|
package com.example.acloc.utility;
|
||||||
|
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.DialogInterface;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.graphics.drawable.ColorDrawable;
|
||||||
|
import android.view.Window;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.example.acloc.R;
|
||||||
|
import com.example.acloc.activities.LoginActivity;
|
||||||
|
|
||||||
|
public class DialogUtils {
|
||||||
|
private static Dialog dialog;
|
||||||
|
|
||||||
|
public static void showLoadingDialog(Context context, String message) {
|
||||||
|
if (dialog != null && dialog.isShowing()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog = new Dialog(context);
|
||||||
|
dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||||
|
dialog.setContentView(R.layout.loading);
|
||||||
|
dialog.getWindow().setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
|
||||||
|
dialog.setCancelable(false);
|
||||||
|
|
||||||
|
TextView tvLoadingText = dialog.findViewById(R.id.tvLoadingText);
|
||||||
|
tvLoadingText.setText(message);
|
||||||
|
|
||||||
|
dialog.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void dismissDialog() {
|
||||||
|
if (dialog != null && dialog.isShowing()) {
|
||||||
|
dialog.dismiss();
|
||||||
|
dialog = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AlertDialog logoutDialog(final Context context) {
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||||
|
|
||||||
|
builder.setMessage(context.getString(R.string.Are_you_sure_you_want_to_logout));
|
||||||
|
|
||||||
|
builder.setPositiveButton("Yes", (dialog, id) -> {
|
||||||
|
dialog.cancel();
|
||||||
|
int flags = Intent.FLAG_ACTIVITY_CLEAR_TOP
|
||||||
|
| Intent.FLAG_ACTIVITY_CLEAR_TASK
|
||||||
|
| Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||||
|
SharedPref.setIsLoggedIn(context,false);
|
||||||
|
SharedPref.deleteAll(context);
|
||||||
|
Helper.goToWithFlags(context, LoginActivity.class, flags);
|
||||||
|
});
|
||||||
|
|
||||||
|
builder.setNegativeButton("No", (dialog, id) -> dialog.cancel());
|
||||||
|
return builder.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
// public static AlertDialog confirmationDialog(final Context context, String confirmationText
|
||||||
|
// , DialogInterface.OnClickListener onDeleteClickListener) {
|
||||||
|
// AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||||
|
// if (confirmationText == null) confirmationText = "perform this operation";
|
||||||
|
// builder.setMessage("Are you sure you want to " + confirmationText + "?" +
|
||||||
|
// "\nWARNING: This action cannot be undone");
|
||||||
|
// builder.setPositiveButton("Yes", onDeleteClickListener);
|
||||||
|
// builder.setNegativeButton("No", (dialog, id) -> dialog.cancel());
|
||||||
|
// return builder.create();
|
||||||
|
// }
|
||||||
|
|
||||||
|
public static AlertDialog confirmationDialog(final Context context, String confirmationText
|
||||||
|
, DialogInterface.OnClickListener onDeleteClickListener) {
|
||||||
|
AlertDialog.Builder builder = new AlertDialog.Builder(context);
|
||||||
|
if (confirmationText == null) confirmationText = "perform this operation";
|
||||||
|
String message = context.getString(R.string.confirmation_message, confirmationText);
|
||||||
|
builder.setMessage(message);
|
||||||
|
builder.setPositiveButton(context.getString(R.string.yes), onDeleteClickListener);
|
||||||
|
builder.setNegativeButton(context.getString(R.string.no), (dialog, id) -> dialog.cancel());
|
||||||
|
return builder.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,353 @@
|
||||||
|
package com.example.acloc.utility;
|
||||||
|
|
||||||
|
import android.app.Activity;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewParent;
|
||||||
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
|
||||||
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
|
import com.google.android.material.textfield.MaterialAutoCompleteTextView;
|
||||||
|
import com.google.android.material.textfield.TextInputEditText;
|
||||||
|
import com.google.android.material.textfield.TextInputLayout;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
public class Helper {
|
||||||
|
|
||||||
|
private static final String TAG = Helper.class.getSimpleName();
|
||||||
|
|
||||||
|
public static void showToast(Context context, String message) {
|
||||||
|
try {
|
||||||
|
Toast.makeText(context, message, Toast.LENGTH_SHORT).show();
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void makeSnackBar(View view, String message) {
|
||||||
|
try {
|
||||||
|
Snackbar.make(view, message, Snackbar.LENGTH_LONG).show();
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
showToast(view.getContext(), message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void goTo(Context context, Class<?> activity) {
|
||||||
|
Intent intent = new Intent(context, activity);
|
||||||
|
context.startActivity(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void goToAndFinish(Context context, Class<?> activity) {
|
||||||
|
Intent intent = new Intent(context, activity);
|
||||||
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
|
||||||
|
context.startActivity(intent);
|
||||||
|
|
||||||
|
// No need to finish explicitly here, flags handle it
|
||||||
|
if (context instanceof Activity) {
|
||||||
|
((Activity) context).finish();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void goTo(Context context, Class<?> activity, String key, Serializable object) {
|
||||||
|
Intent intent = new Intent(context, activity);
|
||||||
|
intent.putExtra(key, object);
|
||||||
|
context.startActivity(intent);
|
||||||
|
|
||||||
|
// if (context instanceof Activity) {
|
||||||
|
// ((Activity) context).finish();
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getIntValueFromString(String value) {
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(value);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static double getDoubleValueFromString(String value) {
|
||||||
|
try {
|
||||||
|
return Double.parseDouble(value);
|
||||||
|
} catch (Exception e) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getStringFromInput(View view) {
|
||||||
|
try {
|
||||||
|
if (view instanceof TextInputEditText) {
|
||||||
|
TextInputEditText editText = (TextInputEditText) view;
|
||||||
|
return Objects.requireNonNull(editText.getText()).toString().trim();
|
||||||
|
} else if (view instanceof MaterialAutoCompleteTextView) {
|
||||||
|
MaterialAutoCompleteTextView editText = (MaterialAutoCompleteTextView) view;
|
||||||
|
return Objects.requireNonNull(editText.getText()).toString();
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isEmptyFieldValidation(TextInputEditText editText) {
|
||||||
|
boolean isValidate = true;
|
||||||
|
try {
|
||||||
|
TextInputLayout textInputLayout = null;
|
||||||
|
ViewParent parent = editText.getParent().getParent();
|
||||||
|
if (parent instanceof TextInputLayout) {
|
||||||
|
textInputLayout = (TextInputLayout) parent;
|
||||||
|
}
|
||||||
|
if (Objects.requireNonNull(editText.getText()).toString().trim().isEmpty()) {
|
||||||
|
if (textInputLayout != null) {
|
||||||
|
textInputLayout.isHelperTextEnabled();
|
||||||
|
textInputLayout.setError("Please " + textInputLayout.getHint());
|
||||||
|
textInputLayout.setErrorEnabled(true);
|
||||||
|
} else {
|
||||||
|
editText.setError("Empty");
|
||||||
|
}
|
||||||
|
isValidate = false;
|
||||||
|
} else {
|
||||||
|
if (textInputLayout != null) {
|
||||||
|
textInputLayout.setErrorEnabled(false);
|
||||||
|
} else {
|
||||||
|
editText.setError(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error in Helper Class: ", e);
|
||||||
|
isValidate = false;
|
||||||
|
}
|
||||||
|
return isValidate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isEmptyFieldValidation(View[] inputFields) {
|
||||||
|
boolean isValidate = true;
|
||||||
|
try {
|
||||||
|
for (View view : inputFields) {
|
||||||
|
TextInputLayout textInputLayout = null;
|
||||||
|
ViewParent parent = view.getParent().getParent();
|
||||||
|
if (parent instanceof TextInputLayout) {
|
||||||
|
textInputLayout = (TextInputLayout) parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
String inputText = "";
|
||||||
|
if (view instanceof TextInputEditText) {
|
||||||
|
inputText = Objects.requireNonNull(((TextInputEditText) view).getText()).toString().trim();
|
||||||
|
} else if (view instanceof MaterialAutoCompleteTextView) {
|
||||||
|
inputText = Objects.requireNonNull(((MaterialAutoCompleteTextView) view).getText()).toString().trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inputText.isEmpty()) {
|
||||||
|
if (textInputLayout != null) {
|
||||||
|
textInputLayout.setError("Please " + textInputLayout.getHint());
|
||||||
|
textInputLayout.setErrorEnabled(true);
|
||||||
|
} else {
|
||||||
|
if (view instanceof TextInputEditText) {
|
||||||
|
((TextInputEditText) view).setError("Empty");
|
||||||
|
} else if (view instanceof MaterialAutoCompleteTextView) {
|
||||||
|
((MaterialAutoCompleteTextView) view).setError("Empty");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isValidate = false;
|
||||||
|
} else {
|
||||||
|
if (textInputLayout != null) {
|
||||||
|
textInputLayout.setErrorEnabled(false);
|
||||||
|
} else {
|
||||||
|
if (view instanceof TextInputEditText) {
|
||||||
|
((TextInputEditText) view).setError(null);
|
||||||
|
} else if (view instanceof MaterialAutoCompleteTextView) {
|
||||||
|
((MaterialAutoCompleteTextView) view).setError(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error in validation: ", e);
|
||||||
|
isValidate = false;
|
||||||
|
}
|
||||||
|
return isValidate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isEmailValid(View emailView) {
|
||||||
|
boolean isValidate = true;
|
||||||
|
try {
|
||||||
|
TextInputLayout textInputLayout = null;
|
||||||
|
ViewParent parent = emailView.getParent().getParent();
|
||||||
|
if (parent instanceof TextInputLayout) {
|
||||||
|
textInputLayout = (TextInputLayout) parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
String emailText = "";
|
||||||
|
if (emailView instanceof TextInputEditText) {
|
||||||
|
emailText = Objects.requireNonNull(((TextInputEditText) emailView).getText()).toString().trim();
|
||||||
|
} else if (emailView instanceof MaterialAutoCompleteTextView) {
|
||||||
|
emailText = Objects.requireNonNull(((MaterialAutoCompleteTextView) emailView).getText()).toString().trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regex for email validation
|
||||||
|
if (!emailText.matches("^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,6}$")) {
|
||||||
|
if (textInputLayout != null) {
|
||||||
|
textInputLayout.setError("Invalid Email Address");
|
||||||
|
textInputLayout.setErrorEnabled(true);
|
||||||
|
} else {
|
||||||
|
if (emailView instanceof TextInputEditText) {
|
||||||
|
((TextInputEditText) emailView).setError("Invalid Email Address");
|
||||||
|
} else if (emailView instanceof MaterialAutoCompleteTextView) {
|
||||||
|
((MaterialAutoCompleteTextView) emailView).setError("Invalid Email Address");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isValidate = false;
|
||||||
|
} else {
|
||||||
|
if (textInputLayout != null) {
|
||||||
|
textInputLayout.setErrorEnabled(false);
|
||||||
|
} else {
|
||||||
|
if (emailView instanceof TextInputEditText) {
|
||||||
|
((TextInputEditText) emailView).setError(null);
|
||||||
|
} else if (emailView instanceof MaterialAutoCompleteTextView) {
|
||||||
|
((MaterialAutoCompleteTextView) emailView).setError(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error in email validation: ", e);
|
||||||
|
isValidate = false;
|
||||||
|
}
|
||||||
|
return isValidate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isPasswordValid(View passwordView) {
|
||||||
|
boolean isValidate = true;
|
||||||
|
try {
|
||||||
|
TextInputLayout textInputLayout = null;
|
||||||
|
ViewParent parent = passwordView.getParent().getParent();
|
||||||
|
if (parent instanceof TextInputLayout) {
|
||||||
|
textInputLayout = (TextInputLayout) parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
String passwordText = "";
|
||||||
|
if (passwordView instanceof TextInputEditText) {
|
||||||
|
passwordText = Objects.requireNonNull(((TextInputEditText) passwordView).getText()).toString().trim();
|
||||||
|
} else if (passwordView instanceof MaterialAutoCompleteTextView) {
|
||||||
|
passwordText = Objects.requireNonNull(((MaterialAutoCompleteTextView) passwordView).getText()).toString().trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regex for strong password validation
|
||||||
|
String passwordPattern = "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{6,}$";
|
||||||
|
|
||||||
|
if (!passwordText.matches(passwordPattern)) {
|
||||||
|
if (textInputLayout != null) {
|
||||||
|
textInputLayout.setError("Password must be at least 6 characters, include 1 uppercase, 1 lowercase, 1 digit, and 1 special character.");
|
||||||
|
textInputLayout.setErrorEnabled(true);
|
||||||
|
} else {
|
||||||
|
if (passwordView instanceof TextInputEditText) {
|
||||||
|
((TextInputEditText) passwordView).setError("Password must be at least 6 characters, include 1 uppercase, 1 lowercase, 1 digit, and 1 special character.");
|
||||||
|
} else if (passwordView instanceof MaterialAutoCompleteTextView) {
|
||||||
|
((MaterialAutoCompleteTextView) passwordView).setError("Password must be at least 6 characters, include 1 uppercase, 1 lowercase, 1 digit, and 1 special character.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isValidate = false;
|
||||||
|
} else {
|
||||||
|
if (textInputLayout != null) {
|
||||||
|
textInputLayout.setErrorEnabled(false);
|
||||||
|
} else {
|
||||||
|
if (passwordView instanceof TextInputEditText) {
|
||||||
|
((TextInputEditText) passwordView).setError(null);
|
||||||
|
} else if (passwordView instanceof MaterialAutoCompleteTextView) {
|
||||||
|
((MaterialAutoCompleteTextView) passwordView).setError(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e("Helper", "Error in password validation: ", e);
|
||||||
|
isValidate = false;
|
||||||
|
}
|
||||||
|
return isValidate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isContactValid(View contactView) {
|
||||||
|
boolean isValidate = true;
|
||||||
|
try {
|
||||||
|
TextInputLayout textInputLayout = null;
|
||||||
|
ViewParent parent = contactView.getParent().getParent();
|
||||||
|
if (parent instanceof TextInputLayout) {
|
||||||
|
textInputLayout = (TextInputLayout) parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
String contactText = "";
|
||||||
|
if (contactView instanceof TextInputEditText) {
|
||||||
|
contactText = Objects.requireNonNull(((TextInputEditText) contactView).getText()).toString().trim();
|
||||||
|
} else if (contactView instanceof MaterialAutoCompleteTextView) {
|
||||||
|
contactText = Objects.requireNonNull(((MaterialAutoCompleteTextView) contactView).getText()).toString().trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Regex for validating contact (Assuming 10-digit phone number)
|
||||||
|
if (!contactText.matches("^[0-9]{10}$")) {
|
||||||
|
if (textInputLayout != null) {
|
||||||
|
textInputLayout.setError("Invalid Contact Number");
|
||||||
|
textInputLayout.setErrorEnabled(true);
|
||||||
|
} else {
|
||||||
|
if (contactView instanceof TextInputEditText) {
|
||||||
|
((TextInputEditText) contactView).setError("Invalid Contact Number");
|
||||||
|
} else if (contactView instanceof MaterialAutoCompleteTextView) {
|
||||||
|
((MaterialAutoCompleteTextView) contactView).setError("Invalid Contact Number");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isValidate = false;
|
||||||
|
} else {
|
||||||
|
if (textInputLayout != null) {
|
||||||
|
textInputLayout.setErrorEnabled(false);
|
||||||
|
} else {
|
||||||
|
if (contactView instanceof TextInputEditText) {
|
||||||
|
((TextInputEditText) contactView).setError(null);
|
||||||
|
} else if (contactView instanceof MaterialAutoCompleteTextView) {
|
||||||
|
((MaterialAutoCompleteTextView) contactView).setError(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e("ValidationHelper", "Error in contact validation: ", e);
|
||||||
|
isValidate = false;
|
||||||
|
}
|
||||||
|
return isValidate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getCurrentDate() {
|
||||||
|
try {
|
||||||
|
SimpleDateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy");
|
||||||
|
Date date = new Date();
|
||||||
|
return dateFormat.format(date);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error in getting current date: ", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getCurrentTime() {
|
||||||
|
try {
|
||||||
|
SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm:ss");
|
||||||
|
Date date = new Date();
|
||||||
|
return timeFormat.format(date);
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Error in getting current time: ", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void goToWithFlags(Context context, Class<?> activity, int flags) {
|
||||||
|
Intent intent = new Intent(context, activity);
|
||||||
|
intent.setFlags(flags);
|
||||||
|
context.startActivity(intent);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static LinearLayoutManager getVerticalManager(Context context) {
|
||||||
|
return new LinearLayoutManager(context, LinearLayoutManager.VERTICAL, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
package com.example.acloc.utility;
|
||||||
|
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
public class KeyGeneratorUtils {
|
||||||
|
|
||||||
|
private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||||
|
private static final int RANDOM_STRING_LENGTH = 8;
|
||||||
|
private static final SecureRandom random = new SecureRandom();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a unique key using timestamp + random string
|
||||||
|
* @return Unique string key
|
||||||
|
*/
|
||||||
|
public static String uniqueKeyGenerator() {
|
||||||
|
// Get current timestamp in yyyyMMddHHmmssSSS format
|
||||||
|
String timeStamp = new SimpleDateFormat("yyyyMMddHHmmssSSS", Locale.getDefault()).format(new Date());
|
||||||
|
|
||||||
|
// Generate random alphanumeric string
|
||||||
|
StringBuilder randomStr = new StringBuilder(RANDOM_STRING_LENGTH);
|
||||||
|
for (int i = 0; i < RANDOM_STRING_LENGTH; i++) {
|
||||||
|
int index = random.nextInt(CHARACTERS.length());
|
||||||
|
randomStr.append(CHARACTERS.charAt(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combine timestamp and random string
|
||||||
|
return timeStamp + "_" + randomStr.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,173 @@
|
||||||
|
package com.example.acloc.utility;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.SharedPreferences;
|
||||||
|
import android.util.Base64;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import org.json.JSONObject;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
public class SharedPref {
|
||||||
|
public static final String TAG = "SharedPref";
|
||||||
|
|
||||||
|
private static final String IS_LOGGED_IN = "isLoggedIn";
|
||||||
|
private static final String USER_UUID = "userUuid"; // Key for UID storage
|
||||||
|
private static final String ADMIN_ROLE_UUID = "adminRoleUuid";
|
||||||
|
private static final String VIEWER_ROLE_UUID = "viewerRoleUuid";
|
||||||
|
private static final String USER_NAME = "userName";
|
||||||
|
private static final String USER_EMAIL = "userEmail";
|
||||||
|
private static final String ROLE = "role";
|
||||||
|
private static final String ACCESS_TOKEN = "AccessToken";
|
||||||
|
private static final String ACCESS_TOKEN_EXPIRY = "AccessTokenExpiry";
|
||||||
|
private static final String REFRESH_TOKEN = "RefreshToken";
|
||||||
|
private static final String LANGUAGE_KEY = "language_key"; // Key to store selected language
|
||||||
|
|
||||||
|
public static SharedPreferences sharedPreferences(Context con) {
|
||||||
|
return con.getSharedPreferences(Constants.SHARED_PREF, Context.MODE_PRIVATE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setIsLoggedIn(Context con, boolean value) {
|
||||||
|
SharedPreferences.Editor editor = sharedPreferences(con).edit();
|
||||||
|
editor.putBoolean(IS_LOGGED_IN, value);
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean getIsLoggedIn(Context con) {
|
||||||
|
return sharedPreferences(con).getBoolean(IS_LOGGED_IN, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setUuid(Context con, String uid) {
|
||||||
|
SharedPreferences.Editor editor = sharedPreferences(con).edit();
|
||||||
|
editor.putString(USER_UUID, uid);
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getUserUid(Context con) {
|
||||||
|
return sharedPreferences(con).getString(USER_UUID, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setUsername(Context con, String username) {
|
||||||
|
SharedPreferences.Editor editor = sharedPreferences(con).edit();
|
||||||
|
editor.putString(USER_NAME, username);
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getUserName(Context con) {
|
||||||
|
return sharedPreferences(con).getString(USER_NAME, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setUserEmail(Context con, String userEmail) {
|
||||||
|
SharedPreferences.Editor editor = sharedPreferences(con).edit();
|
||||||
|
editor.putString(USER_EMAIL, userEmail);
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getUserEmail(Context con) {
|
||||||
|
return sharedPreferences(con).getString(USER_EMAIL, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setRole(Context con, String userEmail) {
|
||||||
|
SharedPreferences.Editor editor = sharedPreferences(con).edit();
|
||||||
|
editor.putString(ROLE, userEmail);
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getRole(Context con) {
|
||||||
|
return sharedPreferences(con).getString(ROLE, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setAccessToken(Context con, String token) {
|
||||||
|
SharedPreferences.Editor editor = sharedPreferences(con).edit();
|
||||||
|
editor.putString(ACCESS_TOKEN, token);
|
||||||
|
|
||||||
|
// Decode token to get expiry (exp) field
|
||||||
|
try {
|
||||||
|
if (token != null && !token.trim().isEmpty()) {
|
||||||
|
String[] split = token.split("\\.");
|
||||||
|
if (split.length >= 2) {
|
||||||
|
String payload = new String(Base64.decode(split[1], Base64.DEFAULT));
|
||||||
|
JSONObject jsonObject = new JSONObject(payload);
|
||||||
|
|
||||||
|
if (jsonObject.has("exp")) {
|
||||||
|
long exp = jsonObject.getLong("exp"); // in seconds
|
||||||
|
long expiryMillis = exp * 1000; // convert to milliseconds
|
||||||
|
editor.putLong(ACCESS_TOKEN_EXPIRY, expiryMillis);
|
||||||
|
} else {
|
||||||
|
editor.putLong(ACCESS_TOKEN_EXPIRY, 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
editor.putLong(ACCESS_TOKEN_EXPIRY, 0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
editor.putLong(ACCESS_TOKEN_EXPIRY, 0);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
Log.e(TAG, "Failed to decode token", e);
|
||||||
|
editor.putLong(ACCESS_TOKEN_EXPIRY, 0); // fallback
|
||||||
|
}
|
||||||
|
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static String getAccessToken(Context con) {
|
||||||
|
return sharedPreferences(con).getString(ACCESS_TOKEN, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isAccessTokenValid(Context con) {
|
||||||
|
long expiryTime = sharedPreferences(con).getLong(ACCESS_TOKEN_EXPIRY, 0);
|
||||||
|
long currentTime = System.currentTimeMillis();
|
||||||
|
return currentTime < expiryTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setRefreshToken(Context con, String refreshToken) {
|
||||||
|
SharedPreferences.Editor editor = sharedPreferences(con).edit();
|
||||||
|
editor.putString(REFRESH_TOKEN, refreshToken);
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getRefreshToken(Context con) {
|
||||||
|
return sharedPreferences(con).getString(REFRESH_TOKEN, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void deleteAll(Context context) {
|
||||||
|
SharedPreferences.Editor editor = sharedPreferences(context).edit();
|
||||||
|
editor.clear();
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to save selected language
|
||||||
|
public static void setLanguage(Context context, String language) {
|
||||||
|
SharedPreferences.Editor editor = sharedPreferences(context).edit();
|
||||||
|
editor.putString(LANGUAGE_KEY, language);
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Method to retrieve saved language, default to system language if not set
|
||||||
|
public static String getLanguage(Context context) {
|
||||||
|
return sharedPreferences(context).getString(LANGUAGE_KEY, Locale.getDefault().getLanguage());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void setViewerRoleUuid(Context con, String uid) {
|
||||||
|
SharedPreferences.Editor editor = sharedPreferences(con).edit();
|
||||||
|
editor.putString(VIEWER_ROLE_UUID, uid);
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getViewerRoleUuid(Context con) {
|
||||||
|
return sharedPreferences(con).getString(VIEWER_ROLE_UUID, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setAdminRoleUuid(Context con, String uid) {
|
||||||
|
SharedPreferences.Editor editor = sharedPreferences(con).edit();
|
||||||
|
editor.putString(ADMIN_ROLE_UUID, uid);
|
||||||
|
editor.apply();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getAdminRoleUuid(Context con) {
|
||||||
|
return sharedPreferences(con).getString(ADMIN_ROLE_UUID, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#FFFFFF" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M19,13h-6v6h-2v-6H5v-2h6V5h2v6h6v2z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M12,2C8.14,2 5,5.14 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13c0,-3.86 -3.14,-7 -7,-7zM16,10h-3v3h-2v-3L8,10L8,8h3L11,5h2v3h3v2z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#FF0000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2L18,7L6,7v12zM8,9h8v10L8,19L8,9zM15.5,4l-1,-1h-5l-1,1L5,4v2h14L19,4z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M7,10l5,5 5,-5z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M3,10h11v2H3V10zM3,8h11V6H3V8zM3,16h7v-2H3V16zM18.01,12.87l0.71,-0.71c0.39,-0.39 1.02,-0.39 1.41,0l0.71,0.71c0.39,0.39 0.39,1.02 0,1.41l-0.71,0.71L18.01,12.87zM17.3,13.58l-5.3,5.3V21h2.12l5.3,-5.3L17.3,13.58z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M13.95,13H9V8.05l5.61,-5.61C13.78,2.16 12.9,2 12,2c-4.2,0 -8,3.22 -8,8.2c0,3.32 2.67,7.25 8,11.8c5.33,-4.55 8,-8.48 8,-11.8c0,-1.01 -0.16,-1.94 -0.45,-2.8L13.95,13z"/>
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M11,11l2.12,0l6.16,-6.16l-2.12,-2.12l-6.16,6.16z"/>
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M20.71,2L20,1.29C19.8,1.1 19.55,1 19.29,1c-0.13,0 -0.48,0.07 -0.71,0.29l-0.72,0.72l2.12,2.12l0.72,-0.72C21.1,3.02 21.1,2.39 20.71,2z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M20,4L4,4c-1.1,0 -1.99,0.9 -1.99,2L2,18c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2zM20,8l-8,5 -8,-5L4,6l8,5 8,-5v2z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#BE0808" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M12,21.35l-1.45,-1.32C5.4,15.36 2,12.28 2,8.5 2,5.42 4.42,3 7.5,3c1.74,0 3.41,0.81 4.5,2.09C13.09,3.81 14.76,3 16.5,3 19.58,3 22,5.42 22,8.5c0,3.78 -3.4,6.86 -8.55,11.54L12,21.35z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#BE0808" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M16.5,3c-1.74,0 -3.41,0.81 -4.5,2.09C10.91,3.81 9.24,3 7.5,3 4.42,3 2,5.42 2,8.5c0,3.78 3.4,6.86 8.55,11.54L12,21.35l1.45,-1.32C18.6,15.36 22,12.28 22,8.5 22,5.42 19.58,3 16.5,3zM12.1,18.55l-0.1,0.1 -0.1,-0.1C7.14,14.24 4,11.39 4,8.5 4,6.5 5.5,5 7.5,5c1.54,0 3.04,0.99 3.57,2.36h1.87C13.46,5.99 14.96,5 16.5,5c2,0 3.5,1.5 3.5,3.5 0,2.89 -3.14,5.74 -7.9,10.05z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M10,20v-6h4v6h5v-8h3L12,3 2,12h3v8z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM18.92,8h-2.95c-0.32,-1.25 -0.78,-2.45 -1.38,-3.56 1.84,0.63 3.37,1.91 4.33,3.56zM12,4.04c0.83,1.2 1.48,2.53 1.91,3.96h-3.82c0.43,-1.43 1.08,-2.76 1.91,-3.96zM4.26,14C4.1,13.36 4,12.69 4,12s0.1,-1.36 0.26,-2h3.38c-0.08,0.66 -0.14,1.32 -0.14,2 0,0.68 0.06,1.34 0.14,2L4.26,14zM5.08,16h2.95c0.32,1.25 0.78,2.45 1.38,3.56 -1.84,-0.63 -3.37,-1.9 -4.33,-3.56zM8.03,8L5.08,8c0.96,-1.66 2.49,-2.93 4.33,-3.56C8.81,5.55 8.35,6.75 8.03,8zM12,19.96c-0.83,-1.2 -1.48,-2.53 -1.91,-3.96h3.82c-0.43,1.43 -1.08,2.76 -1.91,3.96zM14.34,14L9.66,14c-0.09,-0.66 -0.16,-1.32 -0.16,-2 0,-0.68 0.07,-1.35 0.16,-2h4.68c0.09,0.65 0.16,1.32 0.16,2 0,0.68 -0.07,1.34 -0.16,2zM14.59,19.56c0.6,-1.11 1.06,-2.31 1.38,-3.56h2.95c-0.96,1.65 -2.49,2.93 -4.33,3.56zM16.36,14c0.08,-0.66 0.14,-1.32 0.14,-2 0,-0.68 -0.06,-1.34 -0.14,-2h3.38c0.16,0.64 0.26,1.31 0.26,2s-0.1,1.36 -0.26,2h-3.38z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector
|
||||||
|
android:height="108dp"
|
||||||
|
android:width="108dp"
|
||||||
|
android:viewportHeight="108"
|
||||||
|
android:viewportWidth="108"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<path android:fillColor="#3DDC84"
|
||||||
|
android:pathData="M0,0h108v108h-108z"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M9,0L9,108"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M19,0L19,108"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M29,0L29,108"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M39,0L39,108"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M49,0L49,108"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M59,0L59,108"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M69,0L69,108"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M79,0L79,108"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M89,0L89,108"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M99,0L99,108"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M0,9L108,9"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M0,19L108,19"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M0,29L108,29"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M0,39L108,39"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M0,49L108,49"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M0,59L108,59"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M0,69L108,69"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M0,79L108,79"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M0,89L108,89"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M0,99L108,99"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M19,29L89,29"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M19,39L89,39"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M19,49L89,49"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M19,59L89,59"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M19,69L89,69"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M19,79L89,79"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M29,19L29,89"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M39,19L39,89"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M49,19L49,89"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M59,19L59,89"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M69,19L69,89"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
<path android:fillColor="#00000000" android:pathData="M79,19L79,89"
|
||||||
|
android:strokeColor="#33FFFFFF" android:strokeWidth="0.8"/>
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:aapt="http://schemas.android.com/aapt"
|
||||||
|
android:width="108dp"
|
||||||
|
android:height="108dp"
|
||||||
|
android:viewportWidth="108"
|
||||||
|
android:viewportHeight="108">
|
||||||
|
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
||||||
|
<aapt:attr name="android:fillColor">
|
||||||
|
<gradient
|
||||||
|
android:endX="85.84757"
|
||||||
|
android:endY="92.4963"
|
||||||
|
android:startX="42.9492"
|
||||||
|
android:startY="49.59793"
|
||||||
|
android:type="linear">
|
||||||
|
<item
|
||||||
|
android:color="#44000000"
|
||||||
|
android:offset="0.0" />
|
||||||
|
<item
|
||||||
|
android:color="#00000000"
|
||||||
|
android:offset="1.0" />
|
||||||
|
</gradient>
|
||||||
|
</aapt:attr>
|
||||||
|
</path>
|
||||||
|
<path
|
||||||
|
android:fillColor="#FFFFFF"
|
||||||
|
android:fillType="nonZero"
|
||||||
|
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
||||||
|
android:strokeWidth="1"
|
||||||
|
android:strokeColor="#00000000" />
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M12,2C8.13,2 5,5.13 5,9c0,5.25 7,13 7,13s7,-7.75 7,-13c0,-3.87 -3.13,-7 -7,-7zM12,11.5c-1.38,0 -2.5,-1.12 -2.5,-2.5s1.12,-2.5 2.5,-2.5 2.5,1.12 2.5,2.5 -1.12,2.5 -2.5,2.5z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#FFFFFF" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M18,8h-1L17,6c0,-2.76 -2.24,-5 -5,-5S7,3.24 7,6v2L6,8c-1.1,0 -2,0.9 -2,2v10c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2L20,10c0,-1.1 -0.9,-2 -2,-2zM12,17c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2 2,0.9 2,2 -0.9,2 -2,2zM15.1,8L8.9,8L8.9,6c0,-1.71 1.39,-3.1 3.1,-3.1 1.71,0 3.1,1.39 3.1,3.1v2z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:autoMirrored="true" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M17,7l-1.41,1.41L18.17,11H8v2h10.17l-2.58,2.58L17,17l5,-5zM4,5h8V3H4c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h8v-2H4V5z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M10,8m-4,0a4,4 0,1 1,8 0a4,4 0,1 1,-8 0"/>
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M10.67,13.02C10.45,13.01 10.23,13 10,13c-2.42,0 -4.68,0.67 -6.61,1.82C2.51,15.34 2,16.32 2,17.35V20h9.26C10.47,18.87 10,17.49 10,16C10,14.93 10.25,13.93 10.67,13.02z"/>
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M20.75,16c0,-0.22 -0.03,-0.42 -0.06,-0.63l1.14,-1.01l-1,-1.73l-1.45,0.49c-0.32,-0.27 -0.68,-0.48 -1.08,-0.63L18,11h-2l-0.3,1.49c-0.4,0.15 -0.76,0.36 -1.08,0.63l-1.45,-0.49l-1,1.73l1.14,1.01c-0.03,0.21 -0.06,0.41 -0.06,0.63s0.03,0.42 0.06,0.63l-1.14,1.01l1,1.73l1.45,-0.49c0.32,0.27 0.68,0.48 1.08,0.63L16,21h2l0.3,-1.49c0.4,-0.15 0.76,-0.36 1.08,-0.63l1.45,0.49l1,-1.73l-1.14,-1.01C20.72,16.42 20.75,16.22 20.75,16zM17,18c-1.1,0 -2,-0.9 -2,-2s0.9,-2 2,-2s2,0.9 2,2S18.1,18 17,18z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M20.5,3l-0.16,0.03L15,5.1 9,3 3.36,4.9c-0.21,0.07 -0.36,0.25 -0.36,0.48V20.5c0,0.28 0.22,0.5 0.5,0.5l0.16,-0.03L9,18.9l6,2.1 5.64,-1.9c0.21,-0.07 0.36,-0.25 0.36,-0.48V3.5c0,-0.28 -0.22,-0.5 -0.5,-0.5zM15,19l-6,-2.11V5l6,2.11V19z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#FFFFFF" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#FFFFFF" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M6.62,10.79c1.44,2.83 3.76,5.14 6.59,6.59l2.2,-2.2c0.27,-0.27 0.67,-0.36 1.02,-0.24 1.12,0.37 2.33,0.57 3.57,0.57 0.55,0 1,0.45 1,1V20c0,0.55 -0.45,1 -1,1 -9.39,0 -17,-7.61 -17,-17 0,-0.55 0.45,-1 1,-1h3.5c0.55,0 1,0.45 1,1 0,1.25 0.2,2.45 0.57,3.57 0.11,0.35 0.03,0.74 -0.25,1.02l-2.2,2.2z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M20,2L4,2c-1.1,0 -1.99,0.9 -1.99,2L2,22l4,-4h14c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM6,14v-2.47l6.88,-6.88c0.2,-0.2 0.51,-0.2 0.71,0l1.77,1.77c0.2,0.2 0.2,0.51 0,0.71L8.47,14L6,14zM18,14h-7.5l2,-2L18,12v2z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M15.5,14h-0.79l-0.28,-0.27C15.41,12.59 16,11.11 16,9.5 16,5.91 13.09,3 9.5,3S3,5.91 3,9.5 5.91,16 9.5,16c1.61,0 3.09,-0.59 4.23,-1.57l0.27,0.28v0.79l5,4.99L20.49,19l-4.99,-5zM9.5,14C7.01,14 5,11.99 5,9.5S7.01,5 9.5,5 14,7.01 14,9.5 11.99,14 9.5,14z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M22,4h-2c-0.55,0 -1,0.45 -1,1v9c0,0.55 0.45,1 1,1h2V4zM2.17,11.12c-0.11,0.25 -0.17,0.52 -0.17,0.8V13c0,1.1 0.9,2 2,2h5.5l-0.92,4.65c-0.05,0.22 -0.02,0.46 0.08,0.66 0.23,0.45 0.52,0.86 0.88,1.22L10,22l6.41,-6.41c0.38,-0.38 0.59,-0.89 0.59,-1.42V6.34C17,5.05 15.95,4 14.66,4h-8.1c-0.71,0 -1.36,0.37 -1.72,0.97l-2.67,6.15z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M10.89,18.28l0.57,-2.89c0.12,-0.59 -0.04,-1.2 -0.42,-1.66 -0.38,-0.46 -0.94,-0.73 -1.54,-0.73L4,13v-1.08L6.57,6h8.09c0.18,0 0.34,0.16 0.34,0.34v7.84l-4.11,4.1M10,22l6.41,-6.41c0.38,-0.38 0.59,-0.89 0.59,-1.42L17,6.34C17,5.05 15.95,4 14.66,4h-8.1c-0.71,0 -1.36,0.37 -1.72,0.97l-2.67,6.15c-0.11,0.25 -0.17,0.52 -0.17,0.8L2,13c0,1.1 0.9,2 2,2h5.5l-0.92,4.65c-0.05,0.22 -0.02,0.46 0.08,0.66 0.23,0.45 0.52,0.86 0.88,1.22L10,22zM20,15h2L22,4h-2c-0.55,0 -1,0.45 -1,1v9c0,0.55 0.45,1 1,1z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/holo_green_dark" android:pathData="M2,20h2c0.55,0 1,-0.45 1,-1v-9c0,-0.55 -0.45,-1 -1,-1L2,9v11zM21.83,12.88c0.11,-0.25 0.17,-0.52 0.17,-0.8L22,11c0,-1.1 -0.9,-2 -2,-2h-5.5l0.92,-4.65c0.05,-0.22 0.02,-0.46 -0.08,-0.66 -0.23,-0.45 -0.52,-0.86 -0.88,-1.22L14,2 7.59,8.41C7.21,8.79 7,9.3 7,9.83v7.84C7,18.95 8.05,20 9.34,20h8.11c0.7,0 1.36,-0.37 1.72,-0.97l2.66,-6.15z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#FFC107" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M2,20h2c0.55,0 1,-0.45 1,-1v-9c0,-0.55 -0.45,-1 -1,-1L2,9v11zM21.83,12.88c0.11,-0.25 0.17,-0.52 0.17,-0.8L22,11c0,-1.1 -0.9,-2 -2,-2h-5.5l0.92,-4.65c0.05,-0.22 0.02,-0.46 -0.08,-0.66 -0.23,-0.45 -0.52,-0.86 -0.88,-1.22L14,2 7.59,8.41C7.21,8.79 7,9.3 7,9.83v7.84C7,18.95 8.05,20 9.34,20h8.11c0.7,0 1.36,-0.37 1.72,-0.97l2.66,-6.15z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M13.11,5.72l-0.57,2.89c-0.12,0.59 0.04,1.2 0.42,1.66 0.38,0.46 0.94,0.73 1.54,0.73H20v1.08L17.43,18H9.34c-0.18,0 -0.34,-0.16 -0.34,-0.34V9.82l4.11,-4.1M14,2L7.59,8.41C7.21,8.79 7,9.3 7,9.83v7.83C7,18.95 8.05,20 9.34,20h8.1c0.71,0 1.36,-0.37 1.72,-0.97l2.67,-6.15c0.11,-0.25 0.17,-0.52 0.17,-0.8V11c0,-1.1 -0.9,-2 -2,-2h-5.5l0.92,-4.65c0.05,-0.22 0.02,-0.46 -0.08,-0.66 -0.23,-0.45 -0.52,-0.86 -0.88,-1.22L14,2zM4,9H2v11h2c0.55,0 1,-0.45 1,-1v-9c0,-0.55 -0.45,-1 -1,-1z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#F44336" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M22,4h-2c-0.55,0 -1,0.45 -1,1v9c0,0.55 0.45,1 1,1h2V4zM2.17,11.12c-0.11,0.25 -0.17,0.52 -0.17,0.8V13c0,1.1 0.9,2 2,2h5.5l-0.92,4.65c-0.05,0.22 -0.02,0.46 0.08,0.66 0.23,0.45 0.52,0.86 0.88,1.22L10,22l6.41,-6.41c0.38,-0.38 0.59,-0.89 0.59,-1.42V6.34C17,5.05 15.95,4 14.66,4h-8.1c-0.71,0 -1.36,0.37 -1.72,0.97l-2.67,6.15z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#4CAF50" android:viewportHeight="24" android:viewportWidth="24" android:width="24dp">
|
||||||
|
|
||||||
|
<path android:fillColor="@android:color/white" android:pathData="M2,20h2c0.55,0 1,-0.45 1,-1v-9c0,-0.55 -0.45,-1 -1,-1L2,9v11zM21.83,12.88c0.11,-0.25 0.17,-0.52 0.17,-0.8L22,11c0,-1.1 -0.9,-2 -2,-2h-5.5l0.92,-4.65c0.05,-0.22 0.02,-0.46 -0.08,-0.66 -0.23,-0.45 -0.52,-0.86 -0.88,-1.22L14,2 7.59,8.41C7.21,8.79 7,9.3 7,9.83v7.84C7,18.95 8.05,20 9.34,20h8.11c0.7,0 1.36,-0.37 1.72,-0.97l2.66,-6.15z"/>
|
||||||
|
|
||||||
|
</vector>
|
||||||
|
After Width: | Height: | Size: 7.3 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 987 KiB |
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||||
|
<solid android:color="?attr/colorPrimary"/>
|
||||||
|
<corners android:radius="50px"/>
|
||||||
|
<stroke android:width="1dip" android:color="?attr/colorPrimary"/>
|
||||||
|
</shape>
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
|
||||||
|
<solid android:color="@android:color/transparent"/>
|
||||||
|
<corners android:radius="1px"/>
|
||||||
|
<stroke android:width="1dip" android:color="?attr/colorPrimary"/>
|
||||||
|
</shape>
|
||||||
|
|
@ -0,0 +1,144 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/rlAddPlace"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".activity.AddNewPlaceActivity">
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
layout="@layout/toolbar" />
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_above="@id/btnSubmit"
|
||||||
|
android:layout_below="@id/toolbar"
|
||||||
|
android:fillViewport="true"
|
||||||
|
android:fitsSystemWindows="true"
|
||||||
|
android:padding="@dimen/layout_padding">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/llInput"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ivPlacePhoto"
|
||||||
|
android:layout_width="@dimen/image_view_width"
|
||||||
|
android:layout_height="@dimen/image_view_height"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_margin="@dimen/layout_padding"
|
||||||
|
android:background="@drawable/rectangle"
|
||||||
|
android:importantForAccessibility="no"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:padding="@dimen/content_padding"
|
||||||
|
android:src="@drawable/logo_add_location" />
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
app:startIconDrawable="@drawable/ic_location">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/etPlaceName"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/Enter_Place_Name"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="text"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
app:startIconDrawable="@drawable/ic_location">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/etLatitude"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:focusable="false"
|
||||||
|
android:hint="@string/Enter_Latitude"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="text"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
app:startIconDrawable="@drawable/ic_location">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/etLongitude"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:focusable="false"
|
||||||
|
android:hint="@string/Enter_Longitude"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="text"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
app:startIconDrawable="@drawable/ic_location">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/etAddress"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/Enter_Address"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="textImeMultiLine"
|
||||||
|
android:maxLines="4"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
app:startIconDrawable="@drawable/ic_location">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/etPlaceDescription"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/Enter_Place_Description"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="textImeMultiLine"
|
||||||
|
android:maxLines="5"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatButton
|
||||||
|
android:id="@+id/btnSubmit"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:background="?attr/colorPrimary"
|
||||||
|
android:backgroundTintMode="src_atop"
|
||||||
|
android:text="@string/SUBMIT"
|
||||||
|
android:textColor="?attr/colorOnPrimary"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
@ -0,0 +1,188 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/rlAddReport"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".activity.AddReportActivity">
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
layout="@layout/toolbar" />
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_above="@id/btnSubmit"
|
||||||
|
android:layout_below="@id/toolbar"
|
||||||
|
android:fillViewport="true"
|
||||||
|
android:fitsSystemWindows="true"
|
||||||
|
android:padding="@dimen/layout_padding">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ivReportPhoto"
|
||||||
|
android:layout_width="@dimen/image_view_width"
|
||||||
|
android:layout_height="@dimen/image_view_height"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_margin="@dimen/layout_padding"
|
||||||
|
android:background="@drawable/rectangle"
|
||||||
|
android:importantForAccessibility="no"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:padding="@dimen/content_padding"
|
||||||
|
android:src="@drawable/logo_add_location" />
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
app:startIconDrawable="@drawable/ic_location">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/etPlaceName"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clickable="false"
|
||||||
|
android:focusable="false"
|
||||||
|
android:hint="@string/Enter_Place_Name"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="text"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
app:startIconDrawable="@drawable/ic_location">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/etDescription"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/Enter_Description"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="textImeMultiLine"
|
||||||
|
android:maxLines="5"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ivThumbsUp"
|
||||||
|
android:layout_width="@dimen/image_icon_width"
|
||||||
|
android:layout_height="@dimen/image_icon_height"
|
||||||
|
android:background="?selectableItemBackgroundBorderless"
|
||||||
|
android:clickable="true"
|
||||||
|
android:contentDescription="Thumbs Up"
|
||||||
|
android:focusable="true"
|
||||||
|
android:padding="8dp"
|
||||||
|
app:tint="?attr/colorOnBackground"
|
||||||
|
android:src="@drawable/ic_thumb_up_border" />
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:text="@string/GOOD"
|
||||||
|
android:textColor="?attr/colorPrimary"
|
||||||
|
android:textSize="@dimen/textSizeInEditText"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_width="@dimen/edit_text_padding"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ivThumbsAverage"
|
||||||
|
android:layout_width="@dimen/image_icon_width"
|
||||||
|
android:layout_height="@dimen/image_icon_height"
|
||||||
|
android:background="?selectableItemBackgroundBorderless"
|
||||||
|
android:clickable="true"
|
||||||
|
android:contentDescription="Thumbs Average"
|
||||||
|
android:focusable="true"
|
||||||
|
android:padding="8dp"
|
||||||
|
app:tint="?attr/colorOnBackground"
|
||||||
|
android:src="@drawable/ic_thumb_up_border" />
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:text="@string/AVERAGE"
|
||||||
|
android:textColor="?attr/colorPrimary"
|
||||||
|
android:textSize="@dimen/textSizeInEditText"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_width="@dimen/edit_text_padding"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ivThumbsDown"
|
||||||
|
android:layout_width="@dimen/image_icon_width"
|
||||||
|
android:layout_height="@dimen/image_icon_height"
|
||||||
|
android:background="?selectableItemBackgroundBorderless"
|
||||||
|
android:clickable="true"
|
||||||
|
android:contentDescription="Thumbs Down"
|
||||||
|
android:focusable="true"
|
||||||
|
android:padding="8dp"
|
||||||
|
app:tint="?attr/colorOnBackground"
|
||||||
|
android:src="@drawable/ic_thumb_down_border" />
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:text="@string/BAD"
|
||||||
|
android:textColor="?attr/colorPrimary"
|
||||||
|
android:textSize="@dimen/textSizeInEditText"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatButton
|
||||||
|
android:id="@+id/btnSubmit"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:background="?attr/colorPrimary"
|
||||||
|
android:backgroundTintMode="src_atop"
|
||||||
|
android:text="@string/SUBMIT"
|
||||||
|
android:textColor="?attr/colorOnPrimary"
|
||||||
|
tools:ignore="HardcodedText"
|
||||||
|
/>
|
||||||
|
</RelativeLayout>
|
||||||
|
|
@ -0,0 +1,100 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/rlLogin"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".activity.LoginActivity">
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
layout="@layout/toolbar" />
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_below="@id/toolbar"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:fillViewport="true"
|
||||||
|
android:padding="@dimen/layout_padding">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
app:startIconDrawable="@drawable/ic_email">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/etUsername"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/Enter_Username"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="textPersonName" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
app:passwordToggleEnabled="true"
|
||||||
|
app:startIconDrawable="@drawable/ic_lock">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/etPassword"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/Enter_Password"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="textPassword" />
|
||||||
|
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatButton
|
||||||
|
android:id="@+id/btnLogin"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
android:background="?attr/colorPrimary"
|
||||||
|
android:backgroundTintMode="src_atop"
|
||||||
|
android:text="@string/LOGIN"
|
||||||
|
android:textColor="?attr/colorOnPrimary"
|
||||||
|
android:textSize="@dimen/textSizeInEditText" />
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
android:text="@string/Dont_have_an_Account" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvRegisterRedirect"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_marginStart="@dimen/small_content_padding"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
android:text="@string/Please_register"
|
||||||
|
android:textColor="?attr/colorPrimary"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</ScrollView>
|
||||||
|
</RelativeLayout>
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/rlMainActivity"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".MainActivity">
|
||||||
|
|
||||||
|
<androidx.coordinatorlayout.widget.CoordinatorLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
layout="@layout/toolbar" />
|
||||||
|
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@+id/flMainContainer"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
|
|
||||||
|
<!-- Bottom Navigation Menu -->
|
||||||
|
<com.google.android.material.bottomnavigation.BottomNavigationView
|
||||||
|
android:id="@+id/bottomNavView"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:background="?attr/colorTertiary"
|
||||||
|
app:itemIconTint="?attr/colorOnBackground"
|
||||||
|
app:itemTextColor="?attr/colorOnBackground"
|
||||||
|
app:menu="@menu/menu_bottom_navigation" />
|
||||||
|
</RelativeLayout>
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/rlManageRoles"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".activity.ManageRolesActivity">
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
layout="@layout/toolbar" />
|
||||||
|
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:id="@+id/tilSearch"
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@id/toolbar"
|
||||||
|
android:padding="@dimen/content_padding"
|
||||||
|
app:startIconDrawable="@drawable/ic_person">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/etSearchUser"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:drawableEnd="@drawable/ic_search"
|
||||||
|
android:hint="@string/Search_User"
|
||||||
|
android:imeOptions="actionSearch"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="textPersonName"
|
||||||
|
android:drawableTint="?attr/colorOnBackground"/>
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/rvUsers"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="@dimen/content_padding"
|
||||||
|
android:visibility="visible"
|
||||||
|
android:layout_below="@id/tilSearch"
|
||||||
|
tools:listitem="@layout/list_view_users" />
|
||||||
|
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
@ -0,0 +1,234 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/rlPlaceDetails"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".activity.PlaceDetailActivity">
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
layout="@layout/toolbar" />
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_above="@id/btnSubmit"
|
||||||
|
android:layout_below="@id/toolbar"
|
||||||
|
android:fillViewport="true"
|
||||||
|
android:padding="@dimen/layout_padding">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/llInput"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ivProductPhoto"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/image_icon_height"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:background="@drawable/rectangle"
|
||||||
|
android:importantForAccessibility="no"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:scaleType="fitXY"
|
||||||
|
android:src="@drawable/place_header" />
|
||||||
|
|
||||||
|
|
||||||
|
<!-- Place Name and Icons Row -->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
android:baselineAligned="false"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:weightSum="3">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="2.5"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<!-- Place Name -->
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/Place_Name"
|
||||||
|
android:textColor="?attr/colorPrimary"
|
||||||
|
android:textSize="@dimen/textSizeLarge"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:startIconDrawable="@drawable/ic_location" />
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:id="@+id/etPlaceName"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clickable="false"
|
||||||
|
android:focusable="false"
|
||||||
|
android:hint="@string/Place_Name"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="text"
|
||||||
|
android:text="@string/Place_Name"
|
||||||
|
android:textSize="@dimen/textSizeInEditText"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!-- Favorite & Edit Icons -->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="0.5"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ivFavorite"
|
||||||
|
android:layout_width="@dimen/small_image_icon_width"
|
||||||
|
android:layout_height="@dimen/small_image_icon_height"
|
||||||
|
android:autofillHints="Add to Favorite"
|
||||||
|
android:contentDescription="Add to Favorite"
|
||||||
|
android:src="@drawable/ic_favorite_border"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="@dimen/small_padding" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ivEdit"
|
||||||
|
android:layout_width="@dimen/smallest_image_icon_width"
|
||||||
|
android:layout_height="@dimen/smallest_image_icon_height"
|
||||||
|
android:autofillHints="Edit Place"
|
||||||
|
android:contentDescription="Edit Place"
|
||||||
|
android:src="@drawable/ic_edit_location"
|
||||||
|
app:tint="?attr/colorOnBackground" />
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!--Address-->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:weightSum="2">
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="@dimen/small_padding"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="@string/Address"
|
||||||
|
android:textColor="?attr/colorPrimary"
|
||||||
|
android:textSize="@dimen/textSizeLarge"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:startIconDrawable="@drawable/ic_location" />
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:id="@+id/etAddress"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:clickable="false"
|
||||||
|
android:focusable="false"
|
||||||
|
android:hint="@string/Address"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="textMultiLine"
|
||||||
|
android:maxLines="5"
|
||||||
|
android:text="@string/Address"
|
||||||
|
android:textColor="@color/neutralGrey"
|
||||||
|
android:textSize="@dimen/textSizeSmall" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!--Place description-->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:weightSum="2">
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="@dimen/small_padding"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:text="@string/Place_Description"
|
||||||
|
android:textColor="?attr/colorPrimary"
|
||||||
|
android:textSize="@dimen/textSizeLarge"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:startIconDrawable="@drawable/ic_location" />
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:id="@+id/etPlaceDescription"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:clickable="false"
|
||||||
|
android:focusable="false"
|
||||||
|
android:hint="@string/Place_Description"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="textMultiLine"
|
||||||
|
android:maxLines="5"
|
||||||
|
android:text="@string/Place_Description"
|
||||||
|
android:textColor="@color/neutralGrey"
|
||||||
|
android:textSize="@dimen/textSizeSmall" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
android:layout_marginBottom="@dimen/small_padding"
|
||||||
|
android:text="@string/Report"
|
||||||
|
android:textColor="?attr/colorPrimary"
|
||||||
|
android:textSize="@dimen/textSizeLarge"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:startIconDrawable="@drawable/ic_location" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvNoData"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/No_reports_found"
|
||||||
|
android:textAlignment="center" />
|
||||||
|
|
||||||
|
<!-- Report details -->
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/rvReports"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="visible"
|
||||||
|
tools:listitem="@layout/list_view_place_reports" />
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</ScrollView>
|
||||||
|
|
||||||
|
<!-- Add Report btn -->
|
||||||
|
<androidx.appcompat.widget.AppCompatButton
|
||||||
|
android:id="@+id/btnSubmit"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignParentBottom="true"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
android:background="?attr/colorPrimary"
|
||||||
|
android:backgroundTintMode="src_atop"
|
||||||
|
android:text="@string/ADD_REPORT"
|
||||||
|
android:textColor="?attr/colorOnPrimary" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
@ -0,0 +1,115 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/rlRegister"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
tools:context=".activity.RegisterActivity">
|
||||||
|
|
||||||
|
<include
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
layout="@layout/toolbar" />
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_below="@id/toolbar"
|
||||||
|
android:layout_centerInParent="true"
|
||||||
|
android:fillViewport="true"
|
||||||
|
android:padding="@dimen/layout_padding">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center_horizontal"
|
||||||
|
android:gravity="center"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
app:startIconDrawable="@drawable/ic_person">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/etName"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/Enter_Username"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="textPersonName" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
app:startIconDrawable="@drawable/ic_email">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/etEmail"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/Enter_Email"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="textEmailAddress" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
app:passwordToggleEnabled="true"
|
||||||
|
app:startIconDrawable="@drawable/ic_lock">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/etPassword"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/Enter_Password"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="textPassword" />
|
||||||
|
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatButton
|
||||||
|
android:id="@+id/btnRegister"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
android:background="?attr/colorPrimary"
|
||||||
|
android:backgroundTintMode="src_atop"
|
||||||
|
android:text="@string/REGISTER"
|
||||||
|
android:textColor="?attr/colorOnPrimary"
|
||||||
|
android:textSize="@dimen/textSizeInEditText" />
|
||||||
|
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
android:text="@string/Already_have_an_Account" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvLoginRedirect"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
android:text="@string/Please_login"
|
||||||
|
android:textColor="?attr/colorPrimary"
|
||||||
|
android:textStyle="bold" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</ScrollView>
|
||||||
|
</RelativeLayout>
|
||||||
|
|
@ -0,0 +1,128 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/llInput"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="@dimen/layout_padding"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ivPlacePhoto"
|
||||||
|
android:layout_width="@dimen/image_view_width"
|
||||||
|
android:layout_height="@dimen/image_view_height"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:layout_margin="@dimen/layout_padding"
|
||||||
|
android:background="@drawable/rectangle"
|
||||||
|
android:importantForAccessibility="no"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:padding="@dimen/content_padding"
|
||||||
|
android:src="@drawable/logo_add_location" />
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
app:startIconDrawable="@drawable/ic_location">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/etPlaceName"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/Enter_Place_Name"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="text"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
app:startIconDrawable="@drawable/ic_location">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/etLatitude"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/Enter_Latitude"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="text"
|
||||||
|
android:focusable="false"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
app:startIconDrawable="@drawable/ic_location">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/etLongitude"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/Enter_Longitude"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="text"
|
||||||
|
android:focusable="false"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
app:startIconDrawable="@drawable/ic_location">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/etAddress"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/Enter_Address"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="textImeMultiLine"
|
||||||
|
android:maxLines="4"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
app:startIconDrawable="@drawable/ic_location">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/etPlaceDescription"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/Enter_Place_Description"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="textImeMultiLine"
|
||||||
|
android:maxLines="5"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatButton
|
||||||
|
android:id="@+id/btnSubmit"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?attr/colorPrimary"
|
||||||
|
android:backgroundTintMode="src_atop"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
android:text="@string/SUBMIT"
|
||||||
|
android:textColor="?attr/colorOnPrimary"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/llInput"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="@dimen/layout_padding"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
app:passwordToggleEnabled="true"
|
||||||
|
app:startIconDrawable="@drawable/ic_lock">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/etOldPassword"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/Enter_Old_Password"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="textPassword"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
app:passwordToggleEnabled="true"
|
||||||
|
app:startIconDrawable="@drawable/ic_lock">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/etNewPassword"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/Enter_New_Password"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="textPassword"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@+id/llInput"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:weightSum="1">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatButton
|
||||||
|
android:id="@+id/btnCancel"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight=".5"
|
||||||
|
android:background="?attr/colorPrimary"
|
||||||
|
android:backgroundTintMode="src_atop"
|
||||||
|
android:text="@string/CANCEL"
|
||||||
|
android:textColor="?attr/colorOnPrimary"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="@dimen/card_stroke"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatButton
|
||||||
|
android:id="@+id/btnUpdate"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight=".5"
|
||||||
|
android:background="?attr/colorPrimary"
|
||||||
|
android:backgroundTintMode="src_atop"
|
||||||
|
android:text="@string/UPDATE"
|
||||||
|
android:textColor="?attr/colorOnPrimary"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/llInput"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="@dimen/layout_padding"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
app:startIconDrawable="@drawable/ic_person">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/etUsername"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/Enter_Username"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="textPersonName"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
app:startIconDrawable="@drawable/ic_email">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/etEmail"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/Enter_Email"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="textEmailAddress"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@+id/llInput"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:weightSum="1">
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatButton
|
||||||
|
android:id="@+id/btnCancel"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight=".5"
|
||||||
|
android:background="?attr/colorPrimary"
|
||||||
|
android:backgroundTintMode="src_atop"
|
||||||
|
android:text="@string/CANCEL"
|
||||||
|
android:textColor="?attr/colorOnPrimary"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:layout_width="@dimen/card_stroke"
|
||||||
|
android:layout_height="match_parent" />
|
||||||
|
|
||||||
|
<androidx.appcompat.widget.AppCompatButton
|
||||||
|
android:id="@+id/btnUpdate"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight=".5"
|
||||||
|
android:background="?attr/colorPrimary"
|
||||||
|
android:backgroundTintMode="src_atop"
|
||||||
|
android:text="@string/UPDATE"
|
||||||
|
android:textColor="?attr/colorOnPrimary"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/rlFavorite"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginTop="?attr/actionBarSize"
|
||||||
|
tools:context=".fragment.FavoriteFragment">
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/rvFavorite"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="visible"
|
||||||
|
tools:listitem="@layout/list_view_favorite"
|
||||||
|
android:layout_marginBottom="@dimen/bottom_menu_height"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvNoData"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/No_Favorite_found"
|
||||||
|
android:textAlignment="center"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:id="@+id/rlMap"
|
||||||
|
android:layout_marginTop="?attr/actionBarSize"
|
||||||
|
tools:context=".fragment.MapFragment">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:id="@+id/tilSearch"
|
||||||
|
android:padding="@dimen/content_padding"
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:startIconDrawable="@drawable/ic_location">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputEditText
|
||||||
|
android:id="@+id/etSearchLocation"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:drawableEnd="@drawable/ic_search"
|
||||||
|
android:hint="@string/Search_Place"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:imeOptions="actionSearch"
|
||||||
|
android:inputType="textPersonName"
|
||||||
|
android:drawableTint="?attr/colorOnBackground"/>
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
<androidx.fragment.app.FragmentContainerView
|
||||||
|
android:id="@+id/mapFrame"
|
||||||
|
android:name="com.google.android.gms.maps.SupportMapFragment"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_below="@+id/tilSearch" />
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_marginTop="?attr/actionBarSize"
|
||||||
|
android:id="@+id/rlMyReport"
|
||||||
|
tools:context=".fragment.MyReportsFragment"
|
||||||
|
android:layout_marginBottom="@dimen/bottom_menu_height">
|
||||||
|
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/rvReport"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:visibility="visible"
|
||||||
|
tools:listitem="@layout/list_view_my_report" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvNoData"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:gravity="center"
|
||||||
|
android:text="@string/No_reports_found"
|
||||||
|
android:textAlignment="center" />
|
||||||
|
|
||||||
|
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
|
||||||
|
android:id="@+id/extendedFbReport"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="bottom|end"
|
||||||
|
android:layout_marginStart="@dimen/layout_padding"
|
||||||
|
android:layout_marginTop="@dimen/layout_padding"
|
||||||
|
android:layout_marginEnd="@dimen/layout_padding"
|
||||||
|
android:layout_marginBottom="@dimen/layout_padding"
|
||||||
|
android:text="@string/Add_Report"
|
||||||
|
android:textColor="?attr/colorOnPrimary"
|
||||||
|
app:icon="@drawable/ic_add"
|
||||||
|
android:backgroundTint="?attr/colorPrimary"
|
||||||
|
app:iconSize="@dimen/textSizeLarge"
|
||||||
|
app:iconTint="?attr/colorOnPrimary"/>
|
||||||
|
|
||||||
|
|
||||||
|
</FrameLayout>
|
||||||
|
|
@ -0,0 +1,128 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:cardCornerRadius="12dp"
|
||||||
|
app:cardElevation="4dp"
|
||||||
|
app:cardUseCompatPadding="true"
|
||||||
|
app:strokeColor="?attr/colorPrimary"
|
||||||
|
app:strokeWidth="2dp"
|
||||||
|
tools:ignore="MissingConstraints">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="@dimen/content_padding"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:baselineAligned="false"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:weightSum="2">
|
||||||
|
|
||||||
|
<!--Place name-->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1.5"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="@dimen/small_padding"
|
||||||
|
android:text="@string/Place_Name"
|
||||||
|
android:textColor="?attr/colorPrimary"
|
||||||
|
android:textSize="@dimen/textSizeMedium"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:startIconDrawable="@drawable/ic_location" />
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:id="@+id/tvPlaceName"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clickable="false"
|
||||||
|
android:focusable="false"
|
||||||
|
android:hint="@string/Place_Name"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="textMultiLine"
|
||||||
|
android:maxLines="5"
|
||||||
|
android:text="@string/Place_Name"
|
||||||
|
android:textColor="@color/neutralGrey"
|
||||||
|
android:textSize="@dimen/textSizeInEditText"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="0.5"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ivFavorite"
|
||||||
|
android:layout_width="@dimen/small_image_icon_width"
|
||||||
|
android:layout_height="@dimen/small_image_icon_height"
|
||||||
|
android:autofillHints="Add to Favorite"
|
||||||
|
android:contentDescription="Add to Favorite"
|
||||||
|
android:src="@drawable/ic_favorite" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!--Report description-->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="@dimen/small_padding"
|
||||||
|
android:text="@string/Place_Description"
|
||||||
|
android:textColor="?attr/colorPrimary"
|
||||||
|
android:textSize="@dimen/textSizeInEditText"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:startIconDrawable="@drawable/ic_location" />
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:id="@+id/tvDescription"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clickable="false"
|
||||||
|
android:focusable="false"
|
||||||
|
android:hint="@string/Place_Description"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="textMultiLine"
|
||||||
|
android:maxLines="5"
|
||||||
|
android:text="@string/Place_Description"
|
||||||
|
android:textColor="@color/neutralGrey"
|
||||||
|
android:textSize="@dimen/textSizeSmall"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
@ -0,0 +1,141 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:cardCornerRadius="12dp"
|
||||||
|
app:cardElevation="4dp"
|
||||||
|
app:cardUseCompatPadding="true"
|
||||||
|
app:strokeColor="?attr/colorPrimary"
|
||||||
|
app:strokeWidth="2dp"
|
||||||
|
|
||||||
|
tools:ignore="MissingConstraints">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="@dimen/content_padding"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:baselineAligned="false"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:weightSum="2">
|
||||||
|
|
||||||
|
<!--Place name-->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1.5"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="@dimen/small_padding"
|
||||||
|
android:text="@string/Place_Name"
|
||||||
|
android:textColor="?attr/colorPrimary"
|
||||||
|
android:textSize="@dimen/textSizeMedium"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:startIconDrawable="@drawable/ic_location" />
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:id="@+id/tvPlaceName"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clickable="false"
|
||||||
|
android:focusable="false"
|
||||||
|
android:hint="@string/Place_Name"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="textMultiLine"
|
||||||
|
android:maxLines="5"
|
||||||
|
android:text="@string/Place_Name"
|
||||||
|
android:textColor="@color/neutralGrey"
|
||||||
|
android:textSize="@dimen/textSizeInEditText" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="0.5"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ivEdit"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:contentDescription="Edit"
|
||||||
|
android:src="@drawable/ic_edit_location"
|
||||||
|
app:tint="?attr/colorOnBackground" />
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ivDelete"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/small_padding"
|
||||||
|
android:contentDescription="@string/Delete_report"
|
||||||
|
android:src="@drawable/ic_delete" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!--Report description-->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="@dimen/small_padding"
|
||||||
|
android:text="@string/Report_Description"
|
||||||
|
android:textColor="?attr/colorPrimary"
|
||||||
|
android:textSize="@dimen/textSizeInEditText"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:startIconDrawable="@drawable/ic_location" />
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:id="@+id/tvDescription"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clickable="false"
|
||||||
|
android:focusable="false"
|
||||||
|
android:hint="@string/Report_Description"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="textMultiLine"
|
||||||
|
android:maxLines="5"
|
||||||
|
android:text="@string/Place_Description"
|
||||||
|
android:textColor="@color/neutralGrey"
|
||||||
|
android:textSize="@dimen/textSizeSmall" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:id="@+id/tvRating"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginTop="@dimen/content_padding"
|
||||||
|
android:background="@drawable/rating"
|
||||||
|
android:backgroundTint="@color/neutralGrey"
|
||||||
|
android:gravity="center"
|
||||||
|
android:padding="@dimen/content_padding"
|
||||||
|
android:text="@string/Rating_GOOD"
|
||||||
|
android:textAppearance="?attr/textAppearanceSubtitle1"
|
||||||
|
android:textColor="?attr/colorOnPrimary" />
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
@ -0,0 +1,91 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:cardCornerRadius="12dp"
|
||||||
|
app:cardElevation="4dp"
|
||||||
|
app:cardUseCompatPadding="true"
|
||||||
|
app:strokeColor="?attr/colorPrimary"
|
||||||
|
app:strokeWidth="2dp"
|
||||||
|
tools:ignore="MissingConstraints">
|
||||||
|
|
||||||
|
<!--Report rating-->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:baselineAligned="false"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:padding="@dimen/content_padding"
|
||||||
|
android:weightSum="2">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="0.6"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/ivRating"
|
||||||
|
android:layout_width="@dimen/small_image_icon_height"
|
||||||
|
android:layout_height="@dimen/small_image_icon_height"
|
||||||
|
android:contentDescription="rating"
|
||||||
|
android:src="@drawable/ic_thumbs_up" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvRating"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/Rating_GOOD"
|
||||||
|
android:textStyle="bold"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:textColor="?attr/colorOnBackground"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!--Report description-->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="@dimen/small_padding"
|
||||||
|
android:layout_weight="1.5"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="@dimen/small_padding"
|
||||||
|
android:text="@string/Report_Description"
|
||||||
|
android:textColor="?attr/colorPrimary"
|
||||||
|
android:textSize="@dimen/textSizeInEditText"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:startIconDrawable="@drawable/ic_location" />
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:id="@+id/tvDescription"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clickable="false"
|
||||||
|
android:focusable="false"
|
||||||
|
android:hint="@string/Report_Description"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="textMultiLine"
|
||||||
|
android:text="@string/Report_Description"
|
||||||
|
android:textColor="@color/neutralGrey"
|
||||||
|
android:textSize="@dimen/textSizeSmall"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
@ -0,0 +1,103 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<com.google.android.material.card.MaterialCardView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:cardCornerRadius="12dp"
|
||||||
|
app:cardElevation="4dp"
|
||||||
|
app:cardUseCompatPadding="true"
|
||||||
|
app:strokeColor="?attr/colorPrimary"
|
||||||
|
app:strokeWidth="2dp"
|
||||||
|
tools:ignore="MissingConstraints">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_margin="@dimen/content_padding"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:weightSum="2">
|
||||||
|
|
||||||
|
<!--user name-->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:baselineAligned="false"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="@dimen/small_padding"
|
||||||
|
android:text="@string/User"
|
||||||
|
android:textColor="?attr/colorPrimary"
|
||||||
|
android:textSize="@dimen/textSizeMedium"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:startIconDrawable="@drawable/ic_location" />
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
android:id="@+id/tvUsername"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:clickable="false"
|
||||||
|
android:focusable="false"
|
||||||
|
android:hint="@string/User"
|
||||||
|
android:importantForAutofill="no"
|
||||||
|
android:inputType="textMultiLine"
|
||||||
|
android:text="@string/User"
|
||||||
|
android:textColor="@color/neutralGrey"
|
||||||
|
android:textSize="@dimen/textSizeInEditText"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<!--Role-->
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.google.android.material.textview.MaterialTextView
|
||||||
|
style="@style/Widget.MaterialComponents.TextInputLayout.OutlinedBox"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginBottom="@dimen/small_padding"
|
||||||
|
android:text="@string/Role"
|
||||||
|
android:textColor="?attr/colorPrimary"
|
||||||
|
android:textSize="@dimen/textSizeMedium"
|
||||||
|
android:textStyle="bold"
|
||||||
|
app:startIconDrawable="@drawable/ic_location" />
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
|
android:id="@+id/tilStatus"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:hint="@string/Change_Role"
|
||||||
|
android:paddingEnd="@dimen/small_padding">
|
||||||
|
|
||||||
|
<com.google.android.material.textfield.MaterialAutoCompleteTextView
|
||||||
|
android:id="@+id/acRole"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:drawableEnd="@drawable/ic_dropdown"
|
||||||
|
android:inputType="none"
|
||||||
|
android:padding="@dimen/content_padding"
|
||||||
|
android:textColor="@color/neutralGrey"
|
||||||
|
android:textColorHint="@android:color/darker_gray" />
|
||||||
|
</com.google.android.material.textfield.TextInputLayout>
|
||||||
|
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:padding="20dp"
|
||||||
|
android:background="?attr/colorSurface"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:gravity="center">
|
||||||
|
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progressBar"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
style="?android:attr/progressBarStyleLarge"
|
||||||
|
android:indeterminate="true" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/tvLoadingText"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="Loading..."
|
||||||
|
android:paddingTop="10dp"
|
||||||
|
android:textSize="16sp"
|
||||||
|
android:textColor="?attr/colorOnBackground"
|
||||||
|
tools:ignore="HardcodedText" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.appcompat.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
android:id="@+id/toolbar"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="?attr/actionBarSize"
|
||||||
|
android:background="?attr/colorPrimary"
|
||||||
|
android:textColor="?attr/colorOnPrimary"
|
||||||
|
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
|
||||||
|
app:popupTheme="@style/ThemeOverlay.AppCompat.DayNight"
|
||||||
|
app:titleTextColor="?attr/colorOnPrimary" />
|
||||||
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_myReports"
|
||||||
|
android:icon="@drawable/ic_report"
|
||||||
|
android:title="@string/My_Report" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_map"
|
||||||
|
android:icon="@drawable/ic_map"
|
||||||
|
android:title="@string/Map" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_favorite"
|
||||||
|
android:icon="@drawable/ic_favorite"
|
||||||
|
android:title="@string/Favorite" />
|
||||||
|
|
||||||
|
</menu>
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_profile"
|
||||||
|
android:icon="@drawable/ic_person"
|
||||||
|
android:title="@string/Profile"
|
||||||
|
app:iconTint="?attr/colorPrimaryVariant" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_changePassword"
|
||||||
|
android:icon="@drawable/ic_lock"
|
||||||
|
android:title="@string/Change_Password"
|
||||||
|
app:iconTint="?attr/colorPrimaryVariant" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_changeLanguage"
|
||||||
|
android:icon="@drawable/ic_language"
|
||||||
|
android:title="@string/Change_Language"
|
||||||
|
app:iconTint="?attr/colorPrimaryVariant" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_manageRoles"
|
||||||
|
android:icon="@drawable/ic_manage_roles"
|
||||||
|
android:title="@string/Manage_Roles"
|
||||||
|
app:iconTint="?attr/colorPrimaryVariant" />
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_logout"
|
||||||
|
android:icon="@drawable/ic_logout"
|
||||||
|
android:title="@string/Logout"
|
||||||
|
app:iconTint="?attr/colorError" />
|
||||||
|
|
||||||
|
</menu>
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
|
<foreground android:drawable="@mipmap/ic_launcher_foreground"/>
|
||||||
|
</adaptive-icon>
|
||||||
|
After Width: | Height: | Size: 2.8 KiB |
|
After Width: | Height: | Size: 3.8 KiB |
|
After Width: | Height: | Size: 4.7 KiB |
|
After Width: | Height: | Size: 2.0 KiB |
|
After Width: | Height: | Size: 2.6 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 5.0 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 8.2 KiB |
|
After Width: | Height: | Size: 9.4 KiB |