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 |