Merge remote-tracking branch 'origin/main'
# Conflicts: # app/src/main/res/layout/fragment_profile.xml
This commit is contained in:
commit
116eb2f04b
@ -2,6 +2,11 @@
|
||||
|
||||
# НТО 2024. II отборочный этап. Командные задани — клиентская часть
|
||||
|
||||
## Визуализация дизайна приложения в Figma
|
||||
|
||||
- https://www.figma.com/design/JEGV0KLTYC3925JlsQds06/Pass-sistem?node-id=0-1&p=f&t=dDFutSZxZRnxQmEy-0
|
||||
|
||||
|
||||
## 📖 Предыстория
|
||||
В компании S контроль доступа в офис осуществляется с помощью СКУД (системы контроля управления доступом). На данный момент у каждого сотрудника компании есть карта-пропуск с NFC меткой. А у каждой входной двери есть считыватель с обеих сторон. При поднесении карты к считывателю, дверь открывается, а информация о времени входа или выхода сотрудника фиксируется в базе данных.
|
||||
Администрации компании S требуется мобильное приложение, как для рядовых сотрудников, так и для администрации с возможностью просмотра посещений и работой электронного пропуска как временной замены обычного (при помощи сканировании QR кода, который находится на считывателе). Поскольку в приложении есть возможность использовать телефон как пропуск - то к данному приложению повышенные требования к безопасности всех данных, находящихся внутри него.
|
||||
|
@ -34,6 +34,7 @@ public class LoginFragment extends Fragment {
|
||||
|
||||
private FragmentLoginBinding binding;
|
||||
private PreferenceManager preferenceManager;
|
||||
|
||||
private LoginViewModel viewModel;
|
||||
|
||||
@Nullable
|
||||
@ -47,10 +48,9 @@ public class LoginFragment extends Fragment {
|
||||
public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
|
||||
super.onViewCreated(view, savedInstanceState);
|
||||
|
||||
//binding.log.setText("created");
|
||||
preferenceManager = new PreferenceManager(this.getContext());
|
||||
viewModel = new ViewModelProvider(this).get(LoginViewModel.class);
|
||||
//sharedPreferences.edit().putString(ru.myitschool.work.ui.Constants.KEY_LOGIN, "5user").apply();
|
||||
|
||||
binding.login.setEnabled(false);
|
||||
|
||||
binding.username.addTextChangedListener(new OnChangeText() {
|
||||
@ -58,7 +58,7 @@ public class LoginFragment extends Fragment {
|
||||
public void afterTextChanged(Editable s) {
|
||||
super.afterTextChanged(s);
|
||||
viewModel.changeUsername(s.toString());
|
||||
if (binding.username.getText().length() >= 3 && binding.username.getText().toString().matches("[0-9a-zA-Z]+") && (binding.username.getText().toString().charAt(0) + "").matches("[0-9]+")) {
|
||||
if (binding.password.getText().length() >= 5 && binding.username.getText().length() >= 3 && binding.username.getText().toString().matches("[0-9a-zA-Z]+") && (binding.username.getText().toString().charAt(0) + "").matches("[0-9]+")) {
|
||||
binding.login.setEnabled(true);
|
||||
} else {
|
||||
binding.login.setEnabled(false);
|
||||
@ -69,32 +69,7 @@ public class LoginFragment extends Fragment {
|
||||
}
|
||||
});
|
||||
|
||||
binding.username.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||
if (binding.username.getText().length() >= 3 && binding.username.getText().toString().matches("[0-9a-zA-Z]+") && (binding.username.getText().toString().charAt(0) + "").matches("[0-9]+")) {
|
||||
binding.login.setEnabled(true);
|
||||
//binding.log.setText("changed true");
|
||||
} else {
|
||||
binding.login.setEnabled(false);
|
||||
//binding.log.setText("changed false");
|
||||
}
|
||||
//Log.d("tagg", "changed");
|
||||
if (binding.error.getVisibility() == View.VISIBLE) {
|
||||
binding.error.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterTextChanged(Editable editable) {
|
||||
|
||||
}
|
||||
});
|
||||
binding.password.addTextChangedListener(new TextWatcher() {
|
||||
@Override
|
||||
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||
@ -104,7 +79,7 @@ public class LoginFragment extends Fragment {
|
||||
@Override
|
||||
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
|
||||
viewModel.changePassword(charSequence.toString());
|
||||
if (binding.password.getText().length() >= 5) {
|
||||
if (binding.password.getText().length() >= 5 && binding.username.getText().length() >= 3 && binding.username.getText().toString().matches("[0-9a-zA-Z]+") && (binding.username.getText().toString().charAt(0) + "").matches("[0-9]+")) {
|
||||
binding.login.setEnabled(true);
|
||||
} else {
|
||||
binding.login.setEnabled(false);
|
||||
@ -122,66 +97,19 @@ public class LoginFragment extends Fragment {
|
||||
|
||||
binding.login.setOnClickListener(view1 -> {
|
||||
viewModel.confirm();
|
||||
/*if (binding.login.isEnabled()) {
|
||||
if (binding.error.getVisibility() == View.VISIBLE) {
|
||||
binding.error.setVisibility(View.GONE);
|
||||
//binding.log.setText("click enabled");
|
||||
}
|
||||
//binding.log.setText("click");
|
||||
onClickLogin(view);
|
||||
}*/
|
||||
|
||||
});
|
||||
|
||||
subscribe(viewModel);
|
||||
}
|
||||
|
||||
/*private void onClickLogin(View view) {
|
||||
Retrofit retrofit = new Retrofit.Builder()
|
||||
.baseUrl(Constants.SERVER_ADDRESS)
|
||||
.addConverterFactory(GsonConverterFactory.create())
|
||||
.build();
|
||||
|
||||
StoreAPI storeApi = retrofit.create(StoreAPI.class);
|
||||
|
||||
String login = binding.username.getText().toString();
|
||||
|
||||
Call<Boolean> call = storeApi.authenticateUser(login);
|
||||
call.enqueue(new Callback<Boolean>() {
|
||||
@Override
|
||||
public void onResponse(Call<Boolean> call, Response<Boolean> response) {
|
||||
if (response.isSuccessful()) {
|
||||
if (response.body() != null && response.body()) {
|
||||
preferenceManager.putString(ru.myitschool.work.utils.Constants.KEY_LOGIN, binding.username.getText().toString());
|
||||
Navigation.findNavController(view).navigate(R.id.action_loginFragment_to_informationFragment);
|
||||
//getFragmentManager().beginTransaction().replace(R.id.nav_host_fragment, new InformationFragment()).commit();
|
||||
} else {
|
||||
binding.error.setVisibility(View.VISIBLE);
|
||||
}
|
||||
} else if (response.code() == 401) {
|
||||
binding.error.setVisibility(View.VISIBLE);
|
||||
} else if (response.code() == 400) {
|
||||
binding.error.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
binding.error.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Call<Boolean> call, Throwable t) {
|
||||
binding.error.setVisibility(View.VISIBLE);
|
||||
}
|
||||
});
|
||||
}*/
|
||||
|
||||
private void subscribe(LoginViewModel viewModel) {
|
||||
viewModel.errorLiveData.observe(getViewLifecycleOwner(), error -> {
|
||||
//Toast.makeText(getContext(), error, Toast.LENGTH_SHORT).show();
|
||||
});
|
||||
/*viewModel.stateLiveData.observe(getViewLifecycleOwner(), state -> {
|
||||
binding.confirm.setText(state.getButton());
|
||||
binding.title.setText(state.getTitle());
|
||||
binding.password.setVisibility(Utils.visibleOrGone(state.isPasswordEnabled()));
|
||||
});*/
|
||||
|
||||
viewModel.openListLiveData.observe(getViewLifecycleOwner(), username -> {
|
||||
final View view = getView();
|
||||
//Toast.makeText(getContext(), "FFFFFFFFF", Toast.LENGTH_SHORT).show();
|
||||
|
4
app/src/main/res/color/gray_50.xml
Normal file
4
app/src/main/res/color/gray_50.xml
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<selector xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
|
||||
</selector>
|
BIN
app/src/main/res/drawable/iconmain.png
Normal file
BIN
app/src/main/res/drawable/iconmain.png
Normal file
Binary file not shown.
After ![]() (image error) Size: 18 KiB |
@ -5,11 +5,21 @@
|
||||
android:layout_height="match_parent"
|
||||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/image"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:src="@drawable/iconmain"
|
||||
app:layout_constraintEnd_toEndOf="@id/root_fragment"
|
||||
app:layout_constraintHorizontal_bias="0.17"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<fragment
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/nav_view"
|
||||
app:layout_constraintTop_toBottomOf="@id/image"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
|
||||
android:id="@+id/root_fragment"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
|
@ -11,77 +11,40 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/fullname"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/photo"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toBottomOf="@id/fullname"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/position"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toBottomOf="@id/photo"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/lastEntry"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toBottomOf="@id/position"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/logout"
|
||||
android:text="@string/logout"
|
||||
<ScrollView
|
||||
android:id="@+id/scrollView2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toBottomOf="@id/lastEntry"
|
||||
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/historylist"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/error"
|
||||
tools:listitem="@layout/item_history" />
|
||||
|
||||
</ScrollView>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/error"
|
||||
android:visibility="gone"
|
||||
android:text="@string/error"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toBottomOf="@id/logout"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
|
||||
<ScrollView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintTop_toBottomOf="@id/error"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
android:text="@string/error"
|
||||
android:visibility="visible"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/scrollView2"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent">
|
||||
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:id="@+id/historylist"
|
||||
tools:listitem="@layout/item_history"
|
||||
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
|
||||
app:layout_constraintTop_toBottomOf="@id/error"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
||||
|
||||
</ScrollView>
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
@ -9,7 +9,8 @@
|
||||
android:id="@+id/username"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/username"/>
|
||||
android:hint="@string/username" />
|
||||
|
||||
|
||||
<EditText
|
||||
android:id="@+id/password"
|
||||
|
@ -3,41 +3,79 @@
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
<ImageView
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/photo"
|
||||
android:text="Профиль"
|
||||
android:textStyle="bold"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Title"
|
||||
android:textSize="40sp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@+id/username"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:id="@+id/text"
|
||||
/>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Логин"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Title"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintTop_toBottomOf="@id/text"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:textSize="15sp"
|
||||
android:id="@+id/text1"/>
|
||||
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/username"
|
||||
app:layout_constraintTop_toBottomOf="@id/photo"
|
||||
app:layout_constraintTop_toBottomOf="@id/text1"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/name"
|
||||
android:text="ФИО"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Title"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintTop_toBottomOf="@id/username"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:textSize="15sp"
|
||||
android:id="@+id/text2"/>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/position"
|
||||
app:layout_constraintTop_toBottomOf="@id/name"
|
||||
app:layout_constraintTop_toBottomOf="@id/text2"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Должность"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Title"
|
||||
android:textStyle="bold"
|
||||
app:layout_constraintTop_toBottomOf="@id/position"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
android:textSize="15sp"
|
||||
android:id="@+id/text3"/>
|
||||
<TextView
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/lastTime"
|
||||
app:layout_constraintTop_toBottomOf="@id/text3"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
|
||||
<Button
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:id="@+id/exit"
|
||||
android:text="выход"
|
||||
app:layout_constraintTop_toBottomOf="@id/position"
|
||||
app:layout_constraintTop_toBottomOf="@id/lastTime"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"/>
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="16dp"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<LinearLayout
|
||||
@ -13,7 +14,7 @@
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="140dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Title"
|
||||
android:textSize="16sp"
|
||||
@ -37,7 +38,7 @@
|
||||
app:layout_constraintTop_toBottomOf="@id/layout_time">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="140dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Title"
|
||||
android:textSize="16sp"
|
||||
@ -61,7 +62,7 @@
|
||||
app:layout_constraintTop_toBottomOf="@id/layout_code">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_width="140dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:textAppearance="@style/TextAppearance.AppCompat.Title"
|
||||
android:textSize="16sp"
|
||||
|
Loading…
x
Reference in New Issue
Block a user